diff options
Diffstat (limited to 'ext/openssl')
77 files changed, 22824 insertions, 10743 deletions
diff --git a/ext/openssl/History.md b/ext/openssl/History.md new file mode 100644 index 0000000000..419237ff16 --- /dev/null +++ b/ext/openssl/History.md @@ -0,0 +1,965 @@ +Version 4.0.0 +============= + +Compatibility +------------- + +* Ruby >= 2.7 +* OpenSSL >= 1.1.1, LibreSSL >= 3.9, and AWS-LC 1.66.0 + - Removed support for OpenSSL 1.0.2-1.1.0 and LibreSSL 3.1-3.8. + [[GitHub #835]](https://github.com/ruby/openssl/issues/835) + - Added support for AWS-LC. + [[GitHub #833]](https://github.com/ruby/openssl/issues/833) + + +Notable changes +--------------- + +* `OpenSSL::SSL` + - Reduce overhead when writing to `OpenSSL::SSL::SSLSocket`. `#syswrite` no + longer creates a temporary String object. + [[GitHub #831]](https://github.com/ruby/openssl/pull/831) + - Make `OpenSSL::SSL::SSLContext#min_version=` and `#max_version=` wrap the + corresponding OpenSSL APIs directly, and remove the fallback to SSL options. + [[GitHub #849]](https://github.com/ruby/openssl/pull/849) + - Add `OpenSSL::SSL::SSLContext#sigalgs=` and `#client_sigalgs=` for + specifying signature algorithms to use for connections. + [[GitHub #895]](https://github.com/ruby/openssl/pull/895) + - Rename `OpenSSL::SSL::SSLContext#ecdh_curves=` to `#groups=` following + the underlying OpenSSL API rename. This method is no longer specific to + ECDHE. The old method remains as an alias. + [[GitHub #900]](https://github.com/ruby/openssl/pull/900) + - Add `OpenSSL::SSL::SSLSocket#sigalg`, `#peer_sigalg`, and `#group` for + getting the signature algorithm and the key agreement group used in the + current connection. + [[GitHub #908]](https://github.com/ruby/openssl/pull/908) + - Enable `SSL_CTX_set_dh_auto()` for servers by default. + [[GitHub #924]](https://github.com/ruby/openssl/pull/924) + - Improve Ractor compatibility. Note that the internal-use constant + `OpenSSL::SSL::SSLContext::DEFAULT_PARAMS` is now frozen. + [[GitHub #925]](https://github.com/ruby/openssl/pull/925) +* `OpenSSL::PKey` + - Remove `OpenSSL::PKey::EC::Point#mul` support with array arguments. The + underlying OpenSSL API has been removed, and the method has been deprecated + since ruby/openssl v3.0.0. + [[GitHub #843]](https://github.com/ruby/openssl/pull/843) + - `OpenSSL::PKey::{RSA,DSA,DH}#params` uses `nil` to indicate missing fields + instead of the number `0`. + [[GitHub #774]](https://github.com/ruby/openssl/pull/774) + - Unify `OpenSSL::PKey::PKeyError` classes. The former subclasses + `OpenSSL::PKey::DHError`, `OpenSSL::PKey::DSAError`, + `OpenSSL::PKey::ECError`, and `OpenSSL::PKey::RSAError` have been merged + into a single class. + [[GitHub #929]](https://github.com/ruby/openssl/pull/929) +* `OpenSSL::Cipher` + - `OpenSSL::Cipher#encrypt` and `#decrypt` no longer accept arguments. + Passing passwords has been deprecated since Ruby 1.8.2 (released in 2004). + [[GitHub #887]](https://github.com/ruby/openssl/pull/887) + - `OpenSSL::Cipher#final` raises `OpenSSL::Cipher::AuthTagError` when the + integrity check fails for AEAD ciphers. `OpenSSL::Cipher::AuthTagError` is a + new subclass of `OpenSSL::Cipher::CipherError`, which was previously raised. + [[GitHub #939]](https://github.com/ruby/openssl/pull/939) + - `OpenSSL::Cipher.new` now raises `OpenSSL::Cipher::CipherError` instead of + `RuntimeError` when OpenSSL does not recognize the algorithm. + [[GitHub #958]](https://github.com/ruby/openssl/pull/958) + - Add support for "fetched" cipher algorithms with OpenSSL 3.0 or later. + [[GitHub #958]](https://github.com/ruby/openssl/pull/958) +* `OpenSSL::Digest` + - `OpenSSL::Digest.new` now raises `OpenSSL::Digest::DigestError` instead of + `RuntimeError` when OpenSSL does not recognize the algorithm. + [[GitHub #958]](https://github.com/ruby/openssl/pull/958) + - Add support for "fetched" digest algorithms with OpenSSL 3.0 or later. + [[GitHub #958]](https://github.com/ruby/openssl/pull/958) +* `OpenSSL::ASN1.decode` now assumes a 1950-2049 year range for `UTCTime` + according to RFC 5280. It previously used a 1969-2068 range. The encoder + has always used the 1950-2049 range. + [[GitHub #909]](https://github.com/ruby/openssl/pull/909) +* `OpenSSL::OpenSSLError`, the base class for all ruby/openssl errors, carry + an additional attribute `#errors` to keep the content of OpenSSL's error + queue. Also, add `#detailed_message` for Ruby 3.2 or later. + [[GitHub #976]](https://github.com/ruby/openssl/pull/976) +* `OpenSSL::PKCS7.new` raises `OpenSSL::PKCS7::PKCS7Error` instead of + `ArgumentError` on error to be consistent with other constructors. + [[GitHub #983]](https://github.com/ruby/openssl/pull/983) + + +Version 3.3.2 +============= + +Merged changes in 3.1.3 and 3.2.3. + + +Version 3.3.1 +============= + +Merged changes in 3.1.2 and 3.2.2. + + +Version 3.3.0 +============= + +Compatibility +------------- + +* Ruby version: 2.7 or later +* OpenSSL version: OpenSSL 1.0.2 or later, and LibreSSL 3.1 or later + +Notable changes +--------------- + +* `OpenSSL::SSL` + - `OpenSSL::SSL::SSLSocket#set_params` no longer sets `#min_version=` to TLS + 1.0 except when OpenSSL 1.0.2 is used. This has been done to disable + SSL 3.0, which is not supported by default in OpenSSL 1.1.0 or later, or in + LibreSSL. This lets it respect the system default if the system-wide + configuration file specifies a higher minimum protocol version. + [[GitHub #710]](https://github.com/ruby/openssl/pull/710) + - `OpenSSL::SSL::SSLSocket.new` no longer enables the `OpenSSL::SSL::OP_ALL` + SSL options by default and follows the system default. + [[GitHub #767]](https://github.com/ruby/openssl/pull/767) + - Add the following IO methods to `OpenSSL::SSL::SSLSocket`, which will pass + along to the underlying socket: `#local_address`, `#remote_address`, + `#close_on_exec=`, `#close_on_exec?`, `#wait`, `#wait_readable`, and + `#wait_writable`. + [[GitHub #708]](https://github.com/ruby/openssl/pull/708) + - Update `OpenSSL::SSL::SSLSocket#gets` to take the `chomp` keyword argument. + [[GitHub #708]](https://github.com/ruby/openssl/pull/708) + - Make `OpenSSL::SSL::SSLSocket` respect the `IO#timeout` value of the + underlying socket on Ruby 3.2 or later. `#timeout` and `#timeout=` methods + are also added. + [[GitHub #714]](https://github.com/ruby/openssl/pull/714) + - Add `OpenSSL::SSL::SSLSocket#close_read` and `#close_write`. + [[GitHub #743]](https://github.com/ruby/openssl/pull/743) + - Add `OpenSSL::Digest.digests` to get a list of all available digest + algorithms. + [[GitHub #726]](https://github.com/ruby/openssl/pull/726) + - Fix `OpenSSL::SSL::SSLSocket#read_nonblock` clearing the passed String + buffer when nothing can be read from the connection. + [[GitHub #739]](https://github.com/ruby/openssl/pull/739) +* Add `#to_text` methods to `OpenSSL::Timestamp::Response`, + `OpenSSL::Timestamp::Request`, `OpenSSL::Timestamp::TokenInfo`, and + `OpenSSL::PKCS7` to get a human-readable representation of the object. + [[GitHub #756]](https://github.com/ruby/openssl/pull/756) +* Add `OpenSSL::X509::Certificate#tbs_bytes` to get the DER encoding of the + TBSCertificate. + [[GitHub #753]](https://github.com/ruby/openssl/pull/753) +* Allow passing `nil` as the digest algorithm to `#sign` methods on + `OpenSSL::X509::Certificate`, `OpenSSL::X509::Request`, and + `OpenSSL::X509::CRL`. This adds supports for signing with EdDSA keys. + [[GitHub #761]](https://github.com/ruby/openssl/pull/761) + [[GitHub #804]](https://github.com/ruby/openssl/pull/804) +* Add `OpenSSL::SSL::SSLSocket#readbyte`. + [[GitHub #771]](https://github.com/ruby/openssl/pull/771) +* Change `OpenSSL::X509::Store#time=` to set the time to the `X509_VERIFY_PARAM` + in the `X509_STORE`. This allows `OpenSSL::Timestamp::Response#verify` to + verify a signature with the specified timestamp. + [[GitHub #770]](https://github.com/ruby/openssl/pull/770) +* Make `OpenSSL::PKCS7.encrypt`'s third parameter `cipher` mandatory. It had + an undocumented default value "RC2-40-CBC", which is not only insecure, but + also not supported in OpenSSL 3.0 or later. + [[GitHub #796]](https://github.com/ruby/openssl/pull/796) +* Make `OpenSSL::BN` shareable between ractors when frozen. + [[GitHub #808]](https://github.com/ruby/openssl/pull/808) +* Make `OpenSSL::Config` instances frozen by default, and make it shareable + between ractors. `OpenSSL::Config::DEFAULT_CONFIG_FILE` is also frozen. + [[GitHub #809]](https://github.com/ruby/openssl/pull/809) +* Add `OpenSSL::PKCS12#set_mac` to configure the MAC parameters and recalculate + a MAC for the content. + [[GitHub #788]](https://github.com/ruby/openssl/pull/788) + +And various non-user-visible changes and bug fixes. Please see the commit +history for more details. + + +Version 3.2.3 +============= + +Merged changes in 3.1.3. + + +Version 3.2.2 +============= + +Merged changes in 3.1.2. + + +Version 3.2.1 +============= + +Merged changes in 3.0.3. + + +Version 3.2.0 +============= + +Compatibility +------------- + +* Ruby >= 2.7 + - Support for Ruby 2.6 has been removed. Note that Ruby 2.6 reached the + end-of-life in 2022-04. + [[GitHub #639]](https://github.com/ruby/openssl/pull/639) +* OpenSSL >= 1.0.2 or LibreSSL >= 3.1 + +Notable changes +--------------- + +* Add a stub gemspec for JRuby, which depends on the `jruby-openssl` gem. + [[GitHub #598]](https://github.com/ruby/openssl/pull/598) +* Add support for the FIPS module in OpenSSL 3.0/3.1. + [[GitHub #608]](https://github.com/ruby/openssl/pull/608) +* Rework `OpenSSL::PKey` routines for loading DER or PEM encoded keys for better + compatibility with OpenSSL 3.0/3.1 with the FIPS module. + [[GitHub #615]](https://github.com/ruby/openssl/pull/615) + [[GitHub #669]](https://github.com/ruby/openssl/pull/669) +* Add `OpenSSL::Provider` module for loading and unloading OpenSSL 3 providers. + [[GitHub #635]](https://github.com/ruby/openssl/pull/635) +* Add `OpenSSL::PKey.new_raw_private_key`, `.new_raw_public_key`, + `OpenSSL::PKey::PKey#raw_private_key`, and `#raw_public_key` for public key + algorithms that use "raw private/public key", such as X25519 and Ed25519. + [[GitHub #646]](https://github.com/ruby/openssl/pull/646) +* Improve OpenSSL error messages to include additional information when + it is available in OpenSSL's error queue. + [[GitHub #648]](https://github.com/ruby/openssl/pull/648) +* Change `OpenSSL::SSL::SSLContext#ca_file=` and `#ca_path=` to raise + `OpenSSL::SSL::SSLError` instead of printing a warning message. + [[GitHub #659]](https://github.com/ruby/openssl/pull/659) +* Allow `OpenSSL::X509::ExtensionFactory#create_extension` to take OIDs in the + dotted-decimal notation. + [[GitHub #141]](https://github.com/ruby/openssl/pull/141) + + +Version 3.1.3 +============= + +Bug fixes +--------- + +* Fix missing NULL check for `EVP_PKEY_get0()` functions with OpenSSL 3.x. + [[GitHub #957]](https://github.com/ruby/openssl/pull/957) + + +Version 3.1.2 +============= + +Bug fixes +--------- + +* Fix crash when attempting to export an incomplete `OpenSSL::PKey::DSA` key. + [[GitHub #845]](https://github.com/ruby/openssl/issues/845) + [[GitHub #847]](https://github.com/ruby/openssl/pull/847) +* Remove the `OpenSSL::X509::V_FLAG_CRL_CHECK_ALL` flag from the default store + used by `OpenSSL::SSL::SSLContext#set_params`. It causes certificate + verification to fail with OpenSSL 3.6.0. It has no effect with any other + OpenSSL versions. + [[GitHub #949]](https://github.com/ruby/openssl/issues/949) + [[GitHub #950]](https://github.com/ruby/openssl/pull/950) + + +Version 3.1.1 +============= + +Merged changes in 3.0.3. + + +Version 3.1.0 +============= + +Ruby/OpenSSL 3.1 will be maintained for the lifetime of Ruby 3.2. + +Merged bug fixes in 2.2.3 and 3.0.2. Among the new features and changes are: + +Notable changes +--------------- + +* Add `OpenSSL::SSL::SSLContext#ciphersuites=` to allow setting TLS 1.3 cipher + suites. + [[GitHub #493]](https://github.com/ruby/openssl/pull/493) +* Add `OpenSSL::SSL::SSLSocket#export_keying_material` for exporting keying + material of the session, as defined in RFC 5705. + [[GitHub #530]](https://github.com/ruby/openssl/pull/530) +* Add `OpenSSL::SSL::SSLContext#keylog_cb=` for setting the TLS key logging + callback, which is useful for supporting NSS's SSLKEYLOGFILE debugging output. + [[GitHub #536]](https://github.com/ruby/openssl/pull/536) +* Remove the default digest algorithm from `OpenSSL::OCSP::BasicResponse#sign` + and `OpenSSL::OCSP::Request#sign`. Omitting the 5th parameter of these + methods used to be equivalent of specifying SHA-1. This default value is now + removed and we will let the underlying OpenSSL library decide instead. + [[GitHub #507]](https://github.com/ruby/openssl/pull/507) +* Add `OpenSSL::BN#mod_sqrt`. + [[GitHub #553]](https://github.com/ruby/openssl/pull/553) +* Allow calling `OpenSSL::Cipher#update` with an empty string. This was + prohibited to workaround an ancient bug in OpenSSL. + [[GitHub #568]](https://github.com/ruby/openssl/pull/568) +* Fix build on platforms without socket support, such as WASI. `OpenSSL::SSL` + will not be defined if OpenSSL is compiled with `OPENSSL_NO_SOCK`. + [[GitHub #558]](https://github.com/ruby/openssl/pull/558) +* Improve support for recent LibreSSL versions. This includes HKDF support in + LibreSSL 3.6 and Ed25519 support in LibreSSL 3.7. + + +Version 3.0.3 +============= + +Bug fixes +--------- + +* Fix a performance regression introduced in v2.1.3 on a buffered write to + `SSLSocket`. + [[GitHub #706]](https://github.com/ruby/openssl/pull/706) +* Fix `OpenSSL::PKCS7` to handle PKCS#7 structures without content. + [[GitHub #690]](https://github.com/ruby/openssl/pull/690) + [[GitHub #752]](https://github.com/ruby/openssl/pull/752) +* Fix `OpenSSL::ASN1::ObjectId#==` with OIDs without a known name. + [[GitHub #791]](https://github.com/ruby/openssl/issues/791) + [[GitHub #792]](https://github.com/ruby/openssl/pull/792) +* Fix `OpenSSL::X509::Certificate#crl_uris` to handle CDP with multiple CRL + URIs. + [[GitHub #775]](https://github.com/ruby/openssl/issues/775) + [[GitHub #776]](https://github.com/ruby/openssl/pull/776) +* Fix `OpenSSL::Cipher#update` to always make the output buffer `String` + independent. + [[Bug #20937]](https://bugs.ruby-lang.org/issues/20937) + [[GitHub #824]](https://github.com/ruby/openssl/pull/824) + + +Version 3.0.2 +============= + +Merged changes in 2.2.3. Additionally, the following issues are fixed by this +release. + +Bug fixes +--------- + +* Fix OpenSSL::PKey::EC#check_key not working correctly on OpenSSL 3.0. + [[GitHub #563]](https://github.com/ruby/openssl/issues/563) + [[GitHub #580]](https://github.com/ruby/openssl/pull/580) + + +Version 3.0.1 +============= + +Merged changes in 2.1.4 and 2.2.2. Additionally, the following issues are fixed +by this release. + +Bug fixes +--------- + +* Add missing type check in OpenSSL::PKey::PKey#sign's optional parameters. + [[GitHub #531]](https://github.com/ruby/openssl/pull/531) +* Work around OpenSSL 3.0's HMAC issues with a zero-length key. + [[GitHub #538]](https://github.com/ruby/openssl/pull/538) +* Fix a regression in OpenSSL::PKey::DSA.generate's default of 'q' size. + [[GitHub #483]](https://github.com/ruby/openssl/issues/483) + [[GitHub #539]](https://github.com/ruby/openssl/pull/539) +* Restore OpenSSL::PKey.read's ability to decode "openssl ecparam -genkey" + output when linked against OpenSSL 3.0. + [[GitHub #535]](https://github.com/ruby/openssl/pull/535) + [[GitHub #540]](https://github.com/ruby/openssl/pull/540) +* Restore error checks in OpenSSL::PKey::EC#{to_der,to_pem}. + [[GitHub #541]](https://github.com/ruby/openssl/pull/541) + + +Version 3.0.0 +============= + +Compatibility notes +------------------- + +* OpenSSL 1.0.1 and Ruby 2.3-2.5 are no longer supported. + [[GitHub #396]](https://github.com/ruby/openssl/pull/396) + [[GitHub #466]](https://github.com/ruby/openssl/pull/466) + +* OpenSSL 3.0 support is added. It is the first major version bump from OpenSSL + 1.1 and contains incompatible changes that affect Ruby/OpenSSL. + Note that OpenSSL 3.0 support is preliminary and not all features are + currently available: + [[GitHub #369]](https://github.com/ruby/openssl/issues/369) + + - Deprecate the ability to modify `OpenSSL::PKey::PKey` instances. OpenSSL 3.0 + made EVP_PKEY structure immutable, and hence the following methods are not + available when Ruby/OpenSSL is linked against OpenSSL 3.0. + [[GitHub #480]](https://github.com/ruby/openssl/pull/480) + + - `OpenSSL::PKey::RSA#set_key`, `#set_factors`, `#set_crt_params` + - `OpenSSL::PKey::DSA#set_pqg`, `#set_key` + - `OpenSSL::PKey::DH#set_pqg`, `#set_key`, `#generate_key!` + - `OpenSSL::PKey::EC#private_key=`, `#public_key=`, `#group=`, `#generate_key!` + + - Deprecate `OpenSSL::Engine`. The ENGINE API has been deprecated in OpenSSL 3.0 + in favor of the new "provider" concept and will be removed in a future + version. + [[GitHub #481]](https://github.com/ruby/openssl/pull/481) + +* `OpenSSL::SSL::SSLContext#tmp_ecdh_callback` has been removed. It has been + deprecated since v2.0.0 because it is incompatible with modern OpenSSL + versions. + [[GitHub #394]](https://github.com/ruby/openssl/pull/394) + +* `OpenSSL::SSL::SSLSocket#read` and `#write` now raise `OpenSSL::SSL::SSLError` + if called before a TLS connection is established. Historically, they + read/wrote unencrypted data to the underlying socket directly in that case. + [[GitHub #9]](https://github.com/ruby/openssl/issues/9) + [[GitHub #469]](https://github.com/ruby/openssl/pull/469) + + +Notable changes +--------------- + +* Enhance OpenSSL::PKey's common interface. + [[GitHub #370]](https://github.com/ruby/openssl/issues/370) + + - Key deserialization: Enhance `OpenSSL::PKey.read` to handle PEM encoding of + DH parameters, which used to be only deserialized by `OpenSSL::PKey::DH.new`. + [[GitHub #328]](https://github.com/ruby/openssl/issues/328) + - Key generation: Add `OpenSSL::PKey.generate_parameters` and + `OpenSSL::PKey.generate_key`. + [[GitHub #329]](https://github.com/ruby/openssl/issues/329) + - Public key signing: Enhance `OpenSSL::PKey::PKey#sign` and `#verify` to use + the new EVP_DigestSign() family to enable PureEdDSA support on OpenSSL 1.1.1 + or later. They also now take optional algorithm-specific parameters for more + control. + [[GitHub #329]](https://github.com/ruby/openssl/issues/329) + - Low-level public key signing and verification: Add + `OpenSSL::PKey::PKey#sign_raw`, `#verify_raw`, and `#verify_recover`. + [[GitHub #382]](https://github.com/ruby/openssl/issues/382) + - Public key encryption: Add `OpenSSL::PKey::PKey#encrypt` and `#decrypt`. + [[GitHub #382]](https://github.com/ruby/openssl/issues/382) + - Key agreement: Add `OpenSSL::PKey::PKey#derive`. + [[GitHub #329]](https://github.com/ruby/openssl/issues/329) + - Key comparison: Add `OpenSSL::PKey::PKey#compare?` to conveniently check + that two keys have common parameters and a public key. + [[GitHub #383]](https://github.com/ruby/openssl/issues/383) + +* Add `OpenSSL::BN#set_flags` and `#get_flags`. This can be used in combination + with `OpenSSL::BN::CONSTTIME` to force constant-time computation. + [[GitHub #417]](https://github.com/ruby/openssl/issues/417) + +* Add `OpenSSL::BN#abs` to get the absolute value of the BIGNUM. + [[GitHub #430]](https://github.com/ruby/openssl/issues/430) + +* Add `OpenSSL::SSL::SSLSocket#getbyte`. + [[GitHub #438]](https://github.com/ruby/openssl/issues/438) + +* Add `OpenSSL::SSL::SSLContext#tmp_dh=`. + [[GitHub #459]](https://github.com/ruby/openssl/pull/459) + +* Add `OpenSSL::X509::Certificate.load` to load a PEM-encoded and concatenated + list of X.509 certificates at once. + [[GitHub #441]](https://github.com/ruby/openssl/pull/441) + +* Change `OpenSSL::X509::Certificate.new` to attempt to deserialize the given + string first as DER encoding first and then as PEM encoding to ensure the + round-trip consistency. + [[GitHub #442]](https://github.com/ruby/openssl/pull/442) + +* Update various part of the code base to use the modern API. No breaking + changes are intended with this. This includes: + + - `OpenSSL::HMAC` uses the EVP API. + [[GitHub #371]](https://github.com/ruby/openssl/issues/371) + - `OpenSSL::Config` uses native OpenSSL API to parse config files. + [[GitHub #342]](https://github.com/ruby/openssl/issues/342) + + +Version 2.2.3 +============= + +Bug fixes +--------- + +* Fix serveral methods in OpenSSL::PKey::EC::Point attempting to raise an error + with an incorrect class, which would end up with a TypeError. + [[GitHub #570]](https://github.com/ruby/openssl/pull/570) +* Fix OpenSSL::PKey::EC::Point#eql? and OpenSSL::PKey::EC::Group#eql? + incorrectly treated OpenSSL's internal errors as "not equal". + [[GitHub #564]](https://github.com/ruby/openssl/pull/564) +* Fix build with LibreSSL 3.5 or later. + + +Version 2.2.2 +============= + +Merged changes in 2.1.4. + + +Version 2.2.1 +============= + +Merged changes in 2.1.3. Additionally, the following issues are fixed by this +release. + +Bug fixes +--------- + +* Fix crash in `OpenSSL::Timestamp::{Request,Response,TokenInfo}.new` when + invalid arguments are given. + [[GitHub #407]](https://github.com/ruby/openssl/pull/407) +* Fix `OpenSSL::Timestamp::Factory#create_timestamp` with LibreSSL on platforms + where `time_t` has a different size from `long`. + [[GitHub #454]](https://github.com/ruby/openssl/pull/454) + + +Version 2.2.0 +============= + +Compatibility notes +------------------- + +* Remove unsupported MDC2, DSS, DSS1, and SHA algorithms. +* Remove `OpenSSL::PKCS7::SignerInfo#name` alias for `#issuer`. + [[GitHub #266]](https://github.com/ruby/openssl/pull/266) +* Deprecate `OpenSSL::Config#add_value` and `#[]=` for future removal. + [[GitHub #322]](https://github.com/ruby/openssl/pull/322) + + +Notable changes +--------------- + +* Change default `OpenSSL::SSL::SSLServer#listen` backlog argument from + 5 to `Socket::SOMAXCONN`. + [[GitHub #286]](https://github.com/ruby/openssl/issues/286) +* Make `OpenSSL::HMAC#==` use a timing safe string comparison. + [[GitHub #284]](https://github.com/ruby/openssl/pull/284) +* Add support for SHA3 and BLAKE digests. + [[GitHub #282]](https://github.com/ruby/openssl/pull/282) +* Add `OpenSSL::SSL::SSLSocket.open` for opening a `TCPSocket` and + returning an `OpenSSL::SSL::SSLSocket` for it. + [[GitHub #225]](https://github.com/ruby/openssl/issues/225) +* Support marshalling of `OpenSSL::X509` and `OpenSSL::PKey` objects. + [[GitHub #281]](https://github.com/ruby/openssl/pull/281) + [[GitHub #363]](https://github.com/ruby/openssl/pull/363) +* Add `OpenSSL.secure_compare` for timing safe string comparison for + strings of possibly unequal length. + [[GitHub #280]](https://github.com/ruby/openssl/pull/280) +* Add `OpenSSL.fixed_length_secure_compare` for timing safe string + comparison for strings of equal length. + [[GitHub #269]](https://github.com/ruby/openssl/pull/269) +* Add `OpenSSL::SSL::SSLSocket#{finished_message,peer_finished_message}` + for last finished message sent and received. + [[GitHub #250]](https://github.com/ruby/openssl/pull/250) +* Add `OpenSSL::Timestamp` module for handing timestamp requests and + responses. + [[GitHub #204]](https://github.com/ruby/openssl/pull/204) +* Add helper methods for `OpenSSL::X509::Certificate`: + `find_extension`, `subject_key_identifier`, + `authority_key_identifier`, `crl_uris`, `ca_issuer_uris` and + `ocsp_uris`, and for `OpenSSL::X509::CRL`: + `find_extension` and `subject_key_identifier`. + [[GitHub #260]](https://github.com/ruby/openssl/pull/260) + [[GitHub #275]](https://github.com/ruby/openssl/pull/275) + [[GitHub #293]](https://github.com/ruby/openssl/pull/293) +* Add `OpenSSL::ECPoint#add` for performing elliptic curve point addition. + [[GitHub #261]](https://github.com/ruby/openssl/pull/261) +* Make `OpenSSL::PKey::RSA#{export,to_der}` check `key`, `factors`, and + `crt_params` to do proper private key serialization. + [[GitHub #258]](https://github.com/ruby/openssl/pull/258) +* Add `OpenSSL::SSL::{SSLSocket,SSLServer}#fileno`, returning the + underlying socket file descriptor number. + [[GitHub #247]](https://github.com/ruby/openssl/pull/247) +* Support client certificates with TLS 1.3, and support post-handshake + authentication with OpenSSL 1.1.1+. + [[GitHub #239]](https://github.com/ruby/openssl/pull/239) +* Add `OpenSSL::ASN1::ObjectId#==` for equality testing. +* Add `OpenSSL::X509::Extension#value_der` for the raw value of + the extension. + [[GitHub #234]](https://github.com/ruby/openssl/pull/234) +* Significantly reduce allocated memory in `OpenSSL::Buffering#do_write`. + [[GitHub #212]](https://github.com/ruby/openssl/pull/212) +* Ensure all valid IPv6 addresses are considered valid as elements + of subjectAlternativeName in certificates. + [[GitHub #185]](https://github.com/ruby/openssl/pull/185) +* Allow recipient's certificate to be omitted in PCKS7#decrypt. + [[GitHub #183]](https://github.com/ruby/openssl/pull/183) +* Add support for reading keys in PKCS #8 format and export via instance methods + added to `OpenSSL::PKey` classes: `private_to_der`, `private_to_pem`, + `public_to_der` and `public_to_pem`. + [[GitHub #297]](https://github.com/ruby/openssl/pull/297) + + +Version 2.1.4 +============= + +Bug fixes +--------- + +* Do not use pkg-config if --with-openssl-dir option is specified. + [[GitHub #486]](https://github.com/ruby/openssl/pull/486) + + +Version 2.1.3 +============= + +Bug fixes +--------- + +* Fix deprecation warnings on Ruby 3.0. +* Add ".include" directive support in `OpenSSL::Config`. + [[GitHub #216]](https://github.com/ruby/openssl/pull/216) +* Fix handling of IPv6 address SANs. + [[GitHub #185]](https://github.com/ruby/openssl/pull/185) +* Hostname verification failure with `OpenSSL::SSL::SSLContext#verify_hostname=` + sets a proper error code. + [[GitHub #350]](https://github.com/ruby/openssl/pull/350) +* Fix crash with `OpenSSL::BN.new(nil, 2)`. + [[Bug #15760]](https://bugs.ruby-lang.org/issues/15760) +* `OpenSSL::SSL::SSLSocket#sys{read,write}` prevent internal string buffers from + being modified by another thread. + [[GitHub #453]](https://github.com/ruby/openssl/pull/453) +* Fix misuse of input record separator in `OpenSSL::Buffering` where it was + for output. +* Fix wrong integer casting in `OpenSSL::PKey::EC#dsa_verify_asn1`. + [[GitHub #460]](https://github.com/ruby/openssl/pull/460) +* `extconf.rb` explicitly checks that OpenSSL's version number is 1.0.1 or + newer but also less than 3.0. Ruby/OpenSSL v2.1.x and v2.2.x will not support + OpenSSL 3.0 API. + [[GitHub #458]](https://github.com/ruby/openssl/pull/458) +* Activate `digest` gem correctly. `digest` library could go into an + inconsistent state if there are multiple versions of `digest` is installed + and `openssl` is `require`d before `digest`. + [[GitHub #463]](https://github.com/ruby/openssl/pull/463) +* Fix GC.compact compatibility. + [[GitHub #464]](https://github.com/ruby/openssl/issues/464) + [[GitHub #465]](https://github.com/ruby/openssl/pull/465) + + +Version 2.1.2 +============= + +Merged changes in 2.0.9. + + +Version 2.1.1 +============= + +Merged changes in 2.0.8. + + +Version 2.1.0 +============= + +Notable changes +--------------- + +* Support for OpenSSL versions before 1.0.1 and LibreSSL versions before 2.5 + is removed. + [[GitHub #86]](https://github.com/ruby/openssl/pull/86) +* OpenSSL::BN#negative?, #+@, and #-@ are added. +* OpenSSL::SSL::SSLSocket#connect raises a more informative exception when + certificate verification fails. + [[GitHub #99]](https://github.com/ruby/openssl/pull/99) +* OpenSSL::KDF module is newly added. In addition to PBKDF2-HMAC that has moved + from OpenSSL::PKCS5, scrypt and HKDF are supported. + [[GitHub #109]](https://github.com/ruby/openssl/pull/109) + [[GitHub #173]](https://github.com/ruby/openssl/pull/173) +* OpenSSL.fips_mode is added. We had the setter, but not the getter. + [[GitHub #125]](https://github.com/ruby/openssl/pull/125) +* OpenSSL::OCSP::Request#signed? is added. +* OpenSSL::ASN1 handles the indefinite length form better. OpenSSL::ASN1.decode + no longer wrongly treats the end-of-contents octets as part of the content. + OpenSSL::ASN1::ASN1Data#infinite_length is renamed to #indefinite_length. + [[GitHub #98]](https://github.com/ruby/openssl/pull/98) +* OpenSSL::X509::Name#add_entry now accepts two additional keyword arguments + 'loc' and 'set'. + [[GitHub #94]](https://github.com/ruby/openssl/issues/94) +* OpenSSL::SSL::SSLContext#min_version= and #max_version= are added to replace + #ssl_version= that was built on top of the deprecated OpenSSL C API. Use of + that method and the constant OpenSSL::SSL::SSLContext::METHODS is now + deprecated. + [[GitHub #142]](https://github.com/ruby/openssl/pull/142) +* OpenSSL::X509::Name#to_utf8 is added. + [[GitHub #26]](https://github.com/ruby/openssl/issues/26) + [[GitHub #143]](https://github.com/ruby/openssl/pull/143) +* OpenSSL::X509::{Extension,Attribute,Certificate,CRL,Revoked,Request} can be + compared with == operator. + [[GitHub #161]](https://github.com/ruby/openssl/pull/161) +* TLS Fallback Signaling Cipher Suite Value (SCSV) support is added. + [[GitHub #165]](https://github.com/ruby/openssl/pull/165) +* Build failure with OpenSSL 1.1 built with no-deprecated is fixed. + [[GitHub #160]](https://github.com/ruby/openssl/pull/160) +* OpenSSL::Buffering#write accepts an arbitrary number of arguments. + [[Feature #9323]](https://bugs.ruby-lang.org/issues/9323) + [[GitHub #162]](https://github.com/ruby/openssl/pull/162) +* OpenSSL::PKey::RSA#sign_pss and #verify_pss are added. They perform RSA-PSS + signature and verification. + [[GitHub #75]](https://github.com/ruby/openssl/issues/75) + [[GitHub #76]](https://github.com/ruby/openssl/pull/76) + [[GitHub #169]](https://github.com/ruby/openssl/pull/169) +* OpenSSL::SSL::SSLContext#add_certificate is added. + [[GitHub #167]](https://github.com/ruby/openssl/pull/167) +* OpenSSL::PKey::EC::Point#to_octet_string is added. + OpenSSL::PKey::EC::Point.new can now take String as the second argument. + [[GitHub #177]](https://github.com/ruby/openssl/pull/177) + + +Version 2.0.9 +============= + +Security fixes +-------------- + +* OpenSSL::X509::Name#<=> could incorrectly return 0 (= equal) for non-equal + objects. CVE-2018-16395 is assigned for this issue. + https://hackerone.com/reports/387250 + +Bug fixes +--------- + +* Fixed OpenSSL::PKey::\*.{new,generate} immediately aborting if the thread is + interrupted. + [[Bug #14882]](https://bugs.ruby-lang.org/issues/14882) + [[GitHub #205]](https://github.com/ruby/openssl/pull/205) +* Fixed OpenSSL::X509::Name#to_s failing with OpenSSL::X509::NameError if + called against an empty instance. + [[GitHub #200]](https://github.com/ruby/openssl/issues/200) + [[GitHub #211]](https://github.com/ruby/openssl/pull/211) + + +Version 2.0.8 +============= + +Bug fixes +--------- + +* OpenSSL::Cipher#pkcs5_keyivgen raises an error when a negative iteration + count is given. + [[GitHub #184]](https://github.com/ruby/openssl/pull/184) +* Fixed build with LibreSSL 2.7. + [[GitHub #192]](https://github.com/ruby/openssl/issues/192) + [[GitHub #193]](https://github.com/ruby/openssl/pull/193) + + +Version 2.0.7 +============= + +Bug fixes +--------- + +* OpenSSL::Cipher#auth_data= could segfault if called against a non-AEAD cipher. + [[Bug #14024]](https://bugs.ruby-lang.org/issues/14024) +* OpenSSL::X509::Certificate#public_key= (and similar methods) could segfault + when an instance of OpenSSL::PKey::PKey with no public key components is + passed. + [[Bug #14087]](https://bugs.ruby-lang.org/issues/14087) + [[GitHub #168]](https://github.com/ruby/openssl/pull/168) + + +Version 2.0.6 +============= + +Bug fixes +--------- + +* The session_remove_cb set to an OpenSSL::SSL::SSLContext is no longer called + during GC. +* A possible deadlock in OpenSSL::SSL::SSLSocket#sysread is fixed. + [[GitHub #139]](https://github.com/ruby/openssl/pull/139) +* OpenSSL::BN#hash could return an unnormalized fixnum value on Windows. + [[Bug #13877]](https://bugs.ruby-lang.org/issues/13877) +* OpenSSL::SSL::SSLSocket#sysread and #sysread_nonblock set the length of the + destination buffer String to 0 on error. + [[GitHub #153]](https://github.com/ruby/openssl/pull/153) +* Possible deadlock is fixed. This happened only when built with older versions + of OpenSSL (before 1.1.0) or LibreSSL. + [[GitHub #155]](https://github.com/ruby/openssl/pull/155) + + +Version 2.0.5 +============= + +Bug fixes +--------- + +* Reading a PEM/DER-encoded private key or certificate from an IO object did + not work properly on mswin platforms. + [[ruby/openssl#128]](https://github.com/ruby/openssl/issues/128) +* Broken length check in the PEM passphrase callback is fixed. +* It failed to compile when OpenSSL is configured without TLS 1.0 support. + + +Version 2.0.4 +============= + +Bug fixes +--------- + +* It now compiles with LibreSSL without renaming on Windows (mswin). +* A workaround for the error queue leak of X509_load_cert_crl_file() that + causes random errors is added. + [[Bug #11033]](https://bugs.ruby-lang.org/issues/11033) + + +Version 2.0.3 +============= + +Bug fixes +--------- + +* OpenSSL::ASN1::Constructive#each which was broken by 2.0.0 is fixed. + [[ruby/openssl#96]](https://github.com/ruby/openssl/pull/96) +* Fixed build with static OpenSSL libraries on Windows. + [[Bug #13080]](https://bugs.ruby-lang.org/issues/13080) +* OpenSSL::X509::Name#eql? which was broken by 2.0.0 is fixed. + + +Version 2.0.2 +============= + +Bug fixes +--------- + +* Fix build with early 0.9.8 series which did not have SSL_CTX_clear_options(). + [ruby-core:78693] + + +Version 2.0.1 +============= + +Bug fixes +--------- + +* A GC issue around OpenSSL::BN is fixed. + [[ruby/openssl#87]](https://github.com/ruby/openssl/issues/87) +* OpenSSL::ASN1 now parses BER encoding of GeneralizedTime without seconds. + [[ruby/openssl#88]](https://github.com/ruby/openssl/pull/88) + + +Version 2.0.0 +============= + +This is the first release of openssl gem, formerly a standard library of Ruby, +ext/openssl. This is the successor of the version included in Ruby 2.3. + +Compatibility notes +------------------- + +* Support for OpenSSL version 0.9.6 and 0.9.7 is completely removed. openssl gem + still works with OpenSSL 0.9.8, but users are strongly encouraged to upgrade + to at least 1.0.1, as OpenSSL < 1.0.1 will not receive any security fixes from + the OpenSSL development team. + +Supported platforms +------------------- + +* OpenSSL 1.0.0, 1.0.1, 1.0.2, 1.1.0 +* OpenSSL < 0.9.8 is no longer supported. +* LibreSSL 2.3, 2.4, 2.5 +* Ruby 2.3, 2.4 + +Notable changes +--------------- + +* Add support for OpenSSL 1.1.0. + [[Feature #12324]](https://bugs.ruby-lang.org/issues/12324) +* Add support for LibreSSL + +* OpenSSL::Cipher + + - OpenSSL::Cipher#key= and #iv= reject too long inputs. They used to truncate + silently. [[Bug #12561]](https://bugs.ruby-lang.org/issues/12561) + + - OpenSSL::Cipher#iv_len= is added. It allows changing IV (nonce) length if + using AEAD ciphers. + [[Bug #8667]](https://bugs.ruby-lang.org/issues/8667), + [[Bug #10420]](https://bugs.ruby-lang.org/issues/10420), + [[GH ruby/ruby#569]](https://github.com/ruby/ruby/pull/569), + [[GH ruby/openssl#58]](https://github.com/ruby/openssl/pull/58) + + - OpenSSL::Cipher#auth_tag_len= is added. This sets the authentication tag + length to be generated by an AEAD cipher. + +* OpenSSL::OCSP + + - Accessor methods are added to OpenSSL::OCSP::CertificateId. + [[Feature #7181]](https://bugs.ruby-lang.org/issues/7181) + + - OpenSSL::OCSP::Request and BasicResponse can be signed with non-SHA-1 hash + algorithm. [[Feature #11552]](https://bugs.ruby-lang.org/issues/11552) + + - OpenSSL::OCSP::CertificateId and BasicResponse can be encoded into DER. + + - A new class OpenSSL::OCSP::SingleResponse is added for convenience. + + - OpenSSL::OCSP::BasicResponse#add_status accepts absolute times. They used to + accept only relative seconds from the current time. + +* OpenSSL::PKey + + - OpenSSL::PKey::EC follows the general PKey interface. + [[Bug #6567]](https://bugs.ruby-lang.org/issues/6567) + + - OpenSSL::PKey.read raises OpenSSL::PKey::PKeyError instead of ArgumentError + for consistency with OpenSSL::PKey::{DH,DSA,RSA,EC}#new. + [[Bug #11774]](https://bugs.ruby-lang.org/issues/11774), + [[GH ruby/openssl#55]](https://github.com/ruby/openssl/pull/55) + + - OpenSSL::PKey::EC::Group retrieved by OpenSSL::PKey::EC#group is no longer + linked with the EC key. Modifications to the EC::Group have no effect on the + key. [[GH ruby/openssl#71]](https://github.com/ruby/openssl/pull/71) + + - OpenSSL::PKey::EC::Point#to_bn allows specifying the point conversion form + by the optional argument. + +* OpenSSL::SSL + + - OpenSSL::SSL::SSLSocket#tmp_key is added. A client can call it after the + connection is established to retrieve the ephemeral key. + [[GH ruby/ruby#1318]](https://github.com/ruby/ruby/pull/1318) + + - The automatic ephemeral ECDH curve selection is enabled by default when + built with OpenSSL >= 1.0.2 or LibreSSL. + + - OpenSSL::SSL::SSLContext#security_level= is added. You can set the "security + level" of the SSL context. This is effective only when built with OpenSSL + 1.1.0. + + - A new option 'verify_hostname' is added to OpenSSL::SSL::SSLContext. When it + is enabled, and the SNI hostname is also set, the hostname verification on + the server certificate is automatically performed. It is now enabled by + OpenSSL::SSL::SSLContext#set_params. + [[GH ruby/openssl#60]](https://github.com/ruby/openssl/pull/60) + +Removals +-------- + +* OpenSSL::Engine + + - OpenSSL::Engine.cleanup does nothing when built with OpenSSL 1.1.0. + +* OpenSSL::SSL + + - OpenSSL::PKey::DH::DEFAULT_512 is removed. Hence servers no longer use + 512-bit DH group by default. It is considered too weak nowadays. + [[Bug #11968]](https://bugs.ruby-lang.org/issues/11968), + [[GH ruby/ruby#1196]](https://github.com/ruby/ruby/pull/1196) + + - RC4 cipher suites are removed from OpenSSL::SSL::SSLContext::DEFAULT_PARAMS. + RC4 is now considered to be weak. + [[GH ruby/openssl#50]](https://github.com/ruby/openssl/pull/50) + +Deprecations +------------ + +* OpenSSL::PKey + + - OpenSSL::PKey::RSA#n=, #e=, #d=, #p=, #q=, #dmp1=, #dmq1=, #iqmp=, + OpenSSL::PKey::DSA#p=, #q=, #g=, #priv_key=, #pub_key=, + OpenSSL::PKey::DH#p=, #g=, #priv_key= and #pub_key= are deprecated. They are + disabled when built with OpenSSL 1.1.0, due to its API change. Instead, + OpenSSL::PKey::RSA#set_key, #set_factors, #set_crt_params, + OpenSSL::PKey::DSA#set_pqg, #set_key, OpenSSL::PKey::DH#set_pqg and #set_key + are added. + +* OpenSSL::Random + + - OpenSSL::Random.pseudo_bytes is deprecated, and not defined when built with + OpenSSL 1.1.0. Use OpenSSL::Random.random_bytes instead. + +* OpenSSL::SSL + + - OpenSSL::SSL::SSLContext#tmp_ecdh_callback is deprecated, as the underlying + API SSL_CTX_set_tmp_ecdh_callback() is removed in OpenSSL 1.1.0. It was + first added in Ruby 2.3.0. To specify the curve to be used in ephemeral + ECDH, use OpenSSL::SSL::SSLContext#ecdh_curves=. The automatic curve + selection is also now enabled by default when built with a capable OpenSSL. diff --git a/ext/openssl/depend b/ext/openssl/depend index 21ba20abde..435f4a1c68 100644 --- a/ext/openssl/depend +++ b/ext/openssl/depend @@ -1,21 +1,183 @@ # AUTOGENERATED DEPENDENCIES START openssl_missing.o: $(RUBY_EXTCONF_H) +openssl_missing.o: $(arch_hdrdir)/ruby/config.h openssl_missing.o: openssl_missing.c openssl_missing.o: openssl_missing.h ossl.o: $(RUBY_EXTCONF_H) ossl.o: $(arch_hdrdir)/ruby/config.h +ossl.o: $(hdrdir)/ruby.h +ossl.o: $(hdrdir)/ruby/assert.h +ossl.o: $(hdrdir)/ruby/backward.h +ossl.o: $(hdrdir)/ruby/backward/2/assume.h +ossl.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl.o: $(hdrdir)/ruby/backward/2/bool.h +ossl.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl.o: $(hdrdir)/ruby/backward/2/limits.h +ossl.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl.o: $(hdrdir)/ruby/defines.h ossl.o: $(hdrdir)/ruby/encoding.h ossl.o: $(hdrdir)/ruby/intern.h +ossl.o: $(hdrdir)/ruby/internal/abi.h +ossl.o: $(hdrdir)/ruby/internal/anyargs.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl.o: $(hdrdir)/ruby/internal/assume.h +ossl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl.o: $(hdrdir)/ruby/internal/attr/const.h +ossl.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl.o: $(hdrdir)/ruby/internal/attr/error.h +ossl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl.o: $(hdrdir)/ruby/internal/attr/format.h +ossl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl.o: $(hdrdir)/ruby/internal/cast.h +ossl.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl.o: $(hdrdir)/ruby/internal/config.h +ossl.o: $(hdrdir)/ruby/internal/constant_p.h +ossl.o: $(hdrdir)/ruby/internal/core.h +ossl.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl.o: $(hdrdir)/ruby/internal/core/robject.h +ossl.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl.o: $(hdrdir)/ruby/internal/ctype.h +ossl.o: $(hdrdir)/ruby/internal/dllexport.h +ossl.o: $(hdrdir)/ruby/internal/dosish.h +ossl.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl.o: $(hdrdir)/ruby/internal/error.h +ossl.o: $(hdrdir)/ruby/internal/eval.h +ossl.o: $(hdrdir)/ruby/internal/event.h +ossl.o: $(hdrdir)/ruby/internal/fl_type.h +ossl.o: $(hdrdir)/ruby/internal/gc.h +ossl.o: $(hdrdir)/ruby/internal/glob.h +ossl.o: $(hdrdir)/ruby/internal/globals.h +ossl.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl.o: $(hdrdir)/ruby/internal/has/extension.h +ossl.o: $(hdrdir)/ruby/internal/has/feature.h +ossl.o: $(hdrdir)/ruby/internal/has/warning.h +ossl.o: $(hdrdir)/ruby/internal/intern/array.h +ossl.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl.o: $(hdrdir)/ruby/internal/intern/class.h +ossl.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl.o: $(hdrdir)/ruby/internal/intern/error.h +ossl.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl.o: $(hdrdir)/ruby/internal/intern/file.h +ossl.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl.o: $(hdrdir)/ruby/internal/intern/io.h +ossl.o: $(hdrdir)/ruby/internal/intern/load.h +ossl.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl.o: $(hdrdir)/ruby/internal/intern/object.h +ossl.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl.o: $(hdrdir)/ruby/internal/intern/process.h +ossl.o: $(hdrdir)/ruby/internal/intern/random.h +ossl.o: $(hdrdir)/ruby/internal/intern/range.h +ossl.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl.o: $(hdrdir)/ruby/internal/intern/re.h +ossl.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl.o: $(hdrdir)/ruby/internal/intern/select.h +ossl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl.o: $(hdrdir)/ruby/internal/intern/set.h +ossl.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl.o: $(hdrdir)/ruby/internal/intern/string.h +ossl.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl.o: $(hdrdir)/ruby/internal/intern/time.h +ossl.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl.o: $(hdrdir)/ruby/internal/interpreter.h +ossl.o: $(hdrdir)/ruby/internal/iterator.h +ossl.o: $(hdrdir)/ruby/internal/memory.h +ossl.o: $(hdrdir)/ruby/internal/method.h +ossl.o: $(hdrdir)/ruby/internal/module.h +ossl.o: $(hdrdir)/ruby/internal/newobj.h +ossl.o: $(hdrdir)/ruby/internal/scan_args.h +ossl.o: $(hdrdir)/ruby/internal/special_consts.h +ossl.o: $(hdrdir)/ruby/internal/static_assert.h +ossl.o: $(hdrdir)/ruby/internal/stdalign.h +ossl.o: $(hdrdir)/ruby/internal/stdbool.h +ossl.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl.o: $(hdrdir)/ruby/internal/symbol.h +ossl.o: $(hdrdir)/ruby/internal/value.h +ossl.o: $(hdrdir)/ruby/internal/value_type.h +ossl.o: $(hdrdir)/ruby/internal/variable.h +ossl.o: $(hdrdir)/ruby/internal/warning_push.h +ossl.o: $(hdrdir)/ruby/internal/xmalloc.h ossl.o: $(hdrdir)/ruby/io.h ossl.o: $(hdrdir)/ruby/missing.h +ossl.o: $(hdrdir)/ruby/onigmo.h ossl.o: $(hdrdir)/ruby/oniguruma.h +ossl.o: $(hdrdir)/ruby/ractor.h ossl.o: $(hdrdir)/ruby/ruby.h ossl.o: $(hdrdir)/ruby/st.h ossl.o: $(hdrdir)/ruby/subst.h ossl.o: $(hdrdir)/ruby/thread.h -ossl.o: $(hdrdir)/ruby/thread_native.h -ossl.o: $(top_srcdir)/include/ruby.h ossl.o: openssl_missing.h ossl.o: ossl.c ossl.o: ossl.h @@ -27,30 +189,192 @@ ossl.o: ossl_config.h ossl.o: ossl_digest.h ossl.o: ossl_engine.h ossl.o: ossl_hmac.h +ossl.o: ossl_kdf.h ossl.o: ossl_ns_spki.h ossl.o: ossl_ocsp.h ossl.o: ossl_pkcs12.h -ossl.o: ossl_pkcs5.h ossl.o: ossl_pkcs7.h ossl.o: ossl_pkey.h +ossl.o: ossl_provider.h ossl.o: ossl_rand.h ossl.o: ossl_ssl.h -ossl.o: ossl_version.h +ossl.o: ossl_ts.h ossl.o: ossl_x509.h -ossl.o: ruby_missing.h ossl_asn1.o: $(RUBY_EXTCONF_H) ossl_asn1.o: $(arch_hdrdir)/ruby/config.h +ossl_asn1.o: $(hdrdir)/ruby.h +ossl_asn1.o: $(hdrdir)/ruby/assert.h +ossl_asn1.o: $(hdrdir)/ruby/backward.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_asn1.o: $(hdrdir)/ruby/defines.h ossl_asn1.o: $(hdrdir)/ruby/encoding.h ossl_asn1.o: $(hdrdir)/ruby/intern.h +ossl_asn1.o: $(hdrdir)/ruby/internal/abi.h +ossl_asn1.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/assume.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_asn1.o: $(hdrdir)/ruby/internal/cast.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_asn1.o: $(hdrdir)/ruby/internal/config.h +ossl_asn1.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_asn1.o: $(hdrdir)/ruby/internal/ctype.h +ossl_asn1.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_asn1.o: $(hdrdir)/ruby/internal/dosish.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_asn1.o: $(hdrdir)/ruby/internal/error.h +ossl_asn1.o: $(hdrdir)/ruby/internal/eval.h +ossl_asn1.o: $(hdrdir)/ruby/internal/event.h +ossl_asn1.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_asn1.o: $(hdrdir)/ruby/internal/gc.h +ossl_asn1.o: $(hdrdir)/ruby/internal/glob.h +ossl_asn1.o: $(hdrdir)/ruby/internal/globals.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_asn1.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_asn1.o: $(hdrdir)/ruby/internal/iterator.h +ossl_asn1.o: $(hdrdir)/ruby/internal/memory.h +ossl_asn1.o: $(hdrdir)/ruby/internal/method.h +ossl_asn1.o: $(hdrdir)/ruby/internal/module.h +ossl_asn1.o: $(hdrdir)/ruby/internal/newobj.h +ossl_asn1.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_asn1.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_asn1.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_asn1.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_asn1.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_asn1.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_asn1.o: $(hdrdir)/ruby/internal/symbol.h +ossl_asn1.o: $(hdrdir)/ruby/internal/value.h +ossl_asn1.o: $(hdrdir)/ruby/internal/value_type.h +ossl_asn1.o: $(hdrdir)/ruby/internal/variable.h +ossl_asn1.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_asn1.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_asn1.o: $(hdrdir)/ruby/io.h ossl_asn1.o: $(hdrdir)/ruby/missing.h +ossl_asn1.o: $(hdrdir)/ruby/onigmo.h ossl_asn1.o: $(hdrdir)/ruby/oniguruma.h +ossl_asn1.o: $(hdrdir)/ruby/ractor.h ossl_asn1.o: $(hdrdir)/ruby/ruby.h ossl_asn1.o: $(hdrdir)/ruby/st.h ossl_asn1.o: $(hdrdir)/ruby/subst.h ossl_asn1.o: $(hdrdir)/ruby/thread.h -ossl_asn1.o: $(top_srcdir)/include/ruby.h ossl_asn1.o: openssl_missing.h ossl_asn1.o: ossl.h ossl_asn1.o: ossl_asn1.c @@ -62,30 +386,192 @@ ossl_asn1.o: ossl_config.h ossl_asn1.o: ossl_digest.h ossl_asn1.o: ossl_engine.h ossl_asn1.o: ossl_hmac.h +ossl_asn1.o: ossl_kdf.h ossl_asn1.o: ossl_ns_spki.h ossl_asn1.o: ossl_ocsp.h ossl_asn1.o: ossl_pkcs12.h -ossl_asn1.o: ossl_pkcs5.h ossl_asn1.o: ossl_pkcs7.h ossl_asn1.o: ossl_pkey.h +ossl_asn1.o: ossl_provider.h ossl_asn1.o: ossl_rand.h ossl_asn1.o: ossl_ssl.h -ossl_asn1.o: ossl_version.h +ossl_asn1.o: ossl_ts.h ossl_asn1.o: ossl_x509.h -ossl_asn1.o: ruby_missing.h ossl_bio.o: $(RUBY_EXTCONF_H) ossl_bio.o: $(arch_hdrdir)/ruby/config.h +ossl_bio.o: $(hdrdir)/ruby.h +ossl_bio.o: $(hdrdir)/ruby/assert.h +ossl_bio.o: $(hdrdir)/ruby/backward.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_bio.o: $(hdrdir)/ruby/defines.h ossl_bio.o: $(hdrdir)/ruby/encoding.h ossl_bio.o: $(hdrdir)/ruby/intern.h +ossl_bio.o: $(hdrdir)/ruby/internal/abi.h +ossl_bio.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/assume.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_bio.o: $(hdrdir)/ruby/internal/cast.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_bio.o: $(hdrdir)/ruby/internal/config.h +ossl_bio.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_bio.o: $(hdrdir)/ruby/internal/core.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_bio.o: $(hdrdir)/ruby/internal/ctype.h +ossl_bio.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_bio.o: $(hdrdir)/ruby/internal/dosish.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_bio.o: $(hdrdir)/ruby/internal/error.h +ossl_bio.o: $(hdrdir)/ruby/internal/eval.h +ossl_bio.o: $(hdrdir)/ruby/internal/event.h +ossl_bio.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_bio.o: $(hdrdir)/ruby/internal/gc.h +ossl_bio.o: $(hdrdir)/ruby/internal/glob.h +ossl_bio.o: $(hdrdir)/ruby/internal/globals.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_bio.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_bio.o: $(hdrdir)/ruby/internal/iterator.h +ossl_bio.o: $(hdrdir)/ruby/internal/memory.h +ossl_bio.o: $(hdrdir)/ruby/internal/method.h +ossl_bio.o: $(hdrdir)/ruby/internal/module.h +ossl_bio.o: $(hdrdir)/ruby/internal/newobj.h +ossl_bio.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_bio.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_bio.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_bio.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_bio.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_bio.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_bio.o: $(hdrdir)/ruby/internal/symbol.h +ossl_bio.o: $(hdrdir)/ruby/internal/value.h +ossl_bio.o: $(hdrdir)/ruby/internal/value_type.h +ossl_bio.o: $(hdrdir)/ruby/internal/variable.h +ossl_bio.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_bio.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_bio.o: $(hdrdir)/ruby/io.h ossl_bio.o: $(hdrdir)/ruby/missing.h +ossl_bio.o: $(hdrdir)/ruby/onigmo.h ossl_bio.o: $(hdrdir)/ruby/oniguruma.h +ossl_bio.o: $(hdrdir)/ruby/ractor.h ossl_bio.o: $(hdrdir)/ruby/ruby.h ossl_bio.o: $(hdrdir)/ruby/st.h ossl_bio.o: $(hdrdir)/ruby/subst.h ossl_bio.o: $(hdrdir)/ruby/thread.h -ossl_bio.o: $(top_srcdir)/include/ruby.h ossl_bio.o: openssl_missing.h ossl_bio.o: ossl.h ossl_bio.o: ossl_asn1.h @@ -97,30 +583,192 @@ ossl_bio.o: ossl_config.h ossl_bio.o: ossl_digest.h ossl_bio.o: ossl_engine.h ossl_bio.o: ossl_hmac.h +ossl_bio.o: ossl_kdf.h ossl_bio.o: ossl_ns_spki.h ossl_bio.o: ossl_ocsp.h ossl_bio.o: ossl_pkcs12.h -ossl_bio.o: ossl_pkcs5.h ossl_bio.o: ossl_pkcs7.h ossl_bio.o: ossl_pkey.h +ossl_bio.o: ossl_provider.h ossl_bio.o: ossl_rand.h ossl_bio.o: ossl_ssl.h -ossl_bio.o: ossl_version.h +ossl_bio.o: ossl_ts.h ossl_bio.o: ossl_x509.h -ossl_bio.o: ruby_missing.h ossl_bn.o: $(RUBY_EXTCONF_H) ossl_bn.o: $(arch_hdrdir)/ruby/config.h +ossl_bn.o: $(hdrdir)/ruby.h +ossl_bn.o: $(hdrdir)/ruby/assert.h +ossl_bn.o: $(hdrdir)/ruby/backward.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_bn.o: $(hdrdir)/ruby/defines.h ossl_bn.o: $(hdrdir)/ruby/encoding.h ossl_bn.o: $(hdrdir)/ruby/intern.h +ossl_bn.o: $(hdrdir)/ruby/internal/abi.h +ossl_bn.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/assume.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_bn.o: $(hdrdir)/ruby/internal/cast.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_bn.o: $(hdrdir)/ruby/internal/config.h +ossl_bn.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_bn.o: $(hdrdir)/ruby/internal/core.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_bn.o: $(hdrdir)/ruby/internal/ctype.h +ossl_bn.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_bn.o: $(hdrdir)/ruby/internal/dosish.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_bn.o: $(hdrdir)/ruby/internal/error.h +ossl_bn.o: $(hdrdir)/ruby/internal/eval.h +ossl_bn.o: $(hdrdir)/ruby/internal/event.h +ossl_bn.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_bn.o: $(hdrdir)/ruby/internal/gc.h +ossl_bn.o: $(hdrdir)/ruby/internal/glob.h +ossl_bn.o: $(hdrdir)/ruby/internal/globals.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_bn.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_bn.o: $(hdrdir)/ruby/internal/iterator.h +ossl_bn.o: $(hdrdir)/ruby/internal/memory.h +ossl_bn.o: $(hdrdir)/ruby/internal/method.h +ossl_bn.o: $(hdrdir)/ruby/internal/module.h +ossl_bn.o: $(hdrdir)/ruby/internal/newobj.h +ossl_bn.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_bn.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_bn.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_bn.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_bn.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_bn.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_bn.o: $(hdrdir)/ruby/internal/symbol.h +ossl_bn.o: $(hdrdir)/ruby/internal/value.h +ossl_bn.o: $(hdrdir)/ruby/internal/value_type.h +ossl_bn.o: $(hdrdir)/ruby/internal/variable.h +ossl_bn.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_bn.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_bn.o: $(hdrdir)/ruby/io.h ossl_bn.o: $(hdrdir)/ruby/missing.h +ossl_bn.o: $(hdrdir)/ruby/onigmo.h ossl_bn.o: $(hdrdir)/ruby/oniguruma.h +ossl_bn.o: $(hdrdir)/ruby/ractor.h ossl_bn.o: $(hdrdir)/ruby/ruby.h ossl_bn.o: $(hdrdir)/ruby/st.h ossl_bn.o: $(hdrdir)/ruby/subst.h ossl_bn.o: $(hdrdir)/ruby/thread.h -ossl_bn.o: $(top_srcdir)/include/ruby.h ossl_bn.o: openssl_missing.h ossl_bn.o: ossl.h ossl_bn.o: ossl_asn1.h @@ -132,30 +780,192 @@ ossl_bn.o: ossl_config.h ossl_bn.o: ossl_digest.h ossl_bn.o: ossl_engine.h ossl_bn.o: ossl_hmac.h +ossl_bn.o: ossl_kdf.h ossl_bn.o: ossl_ns_spki.h ossl_bn.o: ossl_ocsp.h ossl_bn.o: ossl_pkcs12.h -ossl_bn.o: ossl_pkcs5.h ossl_bn.o: ossl_pkcs7.h ossl_bn.o: ossl_pkey.h +ossl_bn.o: ossl_provider.h ossl_bn.o: ossl_rand.h ossl_bn.o: ossl_ssl.h -ossl_bn.o: ossl_version.h +ossl_bn.o: ossl_ts.h ossl_bn.o: ossl_x509.h -ossl_bn.o: ruby_missing.h ossl_cipher.o: $(RUBY_EXTCONF_H) ossl_cipher.o: $(arch_hdrdir)/ruby/config.h +ossl_cipher.o: $(hdrdir)/ruby.h +ossl_cipher.o: $(hdrdir)/ruby/assert.h +ossl_cipher.o: $(hdrdir)/ruby/backward.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_cipher.o: $(hdrdir)/ruby/defines.h ossl_cipher.o: $(hdrdir)/ruby/encoding.h ossl_cipher.o: $(hdrdir)/ruby/intern.h +ossl_cipher.o: $(hdrdir)/ruby/internal/abi.h +ossl_cipher.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/assume.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_cipher.o: $(hdrdir)/ruby/internal/cast.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_cipher.o: $(hdrdir)/ruby/internal/config.h +ossl_cipher.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_cipher.o: $(hdrdir)/ruby/internal/ctype.h +ossl_cipher.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_cipher.o: $(hdrdir)/ruby/internal/dosish.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_cipher.o: $(hdrdir)/ruby/internal/error.h +ossl_cipher.o: $(hdrdir)/ruby/internal/eval.h +ossl_cipher.o: $(hdrdir)/ruby/internal/event.h +ossl_cipher.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_cipher.o: $(hdrdir)/ruby/internal/gc.h +ossl_cipher.o: $(hdrdir)/ruby/internal/glob.h +ossl_cipher.o: $(hdrdir)/ruby/internal/globals.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_cipher.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_cipher.o: $(hdrdir)/ruby/internal/iterator.h +ossl_cipher.o: $(hdrdir)/ruby/internal/memory.h +ossl_cipher.o: $(hdrdir)/ruby/internal/method.h +ossl_cipher.o: $(hdrdir)/ruby/internal/module.h +ossl_cipher.o: $(hdrdir)/ruby/internal/newobj.h +ossl_cipher.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_cipher.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_cipher.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_cipher.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_cipher.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_cipher.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_cipher.o: $(hdrdir)/ruby/internal/symbol.h +ossl_cipher.o: $(hdrdir)/ruby/internal/value.h +ossl_cipher.o: $(hdrdir)/ruby/internal/value_type.h +ossl_cipher.o: $(hdrdir)/ruby/internal/variable.h +ossl_cipher.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_cipher.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_cipher.o: $(hdrdir)/ruby/io.h ossl_cipher.o: $(hdrdir)/ruby/missing.h +ossl_cipher.o: $(hdrdir)/ruby/onigmo.h ossl_cipher.o: $(hdrdir)/ruby/oniguruma.h +ossl_cipher.o: $(hdrdir)/ruby/ractor.h ossl_cipher.o: $(hdrdir)/ruby/ruby.h ossl_cipher.o: $(hdrdir)/ruby/st.h ossl_cipher.o: $(hdrdir)/ruby/subst.h ossl_cipher.o: $(hdrdir)/ruby/thread.h -ossl_cipher.o: $(top_srcdir)/include/ruby.h ossl_cipher.o: openssl_missing.h ossl_cipher.o: ossl.h ossl_cipher.o: ossl_asn1.h @@ -167,30 +977,192 @@ ossl_cipher.o: ossl_config.h ossl_cipher.o: ossl_digest.h ossl_cipher.o: ossl_engine.h ossl_cipher.o: ossl_hmac.h +ossl_cipher.o: ossl_kdf.h ossl_cipher.o: ossl_ns_spki.h ossl_cipher.o: ossl_ocsp.h ossl_cipher.o: ossl_pkcs12.h -ossl_cipher.o: ossl_pkcs5.h ossl_cipher.o: ossl_pkcs7.h ossl_cipher.o: ossl_pkey.h +ossl_cipher.o: ossl_provider.h ossl_cipher.o: ossl_rand.h ossl_cipher.o: ossl_ssl.h -ossl_cipher.o: ossl_version.h +ossl_cipher.o: ossl_ts.h ossl_cipher.o: ossl_x509.h -ossl_cipher.o: ruby_missing.h ossl_config.o: $(RUBY_EXTCONF_H) ossl_config.o: $(arch_hdrdir)/ruby/config.h +ossl_config.o: $(hdrdir)/ruby.h +ossl_config.o: $(hdrdir)/ruby/assert.h +ossl_config.o: $(hdrdir)/ruby/backward.h +ossl_config.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_config.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_config.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_config.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_config.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_config.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_config.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_config.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_config.o: $(hdrdir)/ruby/defines.h ossl_config.o: $(hdrdir)/ruby/encoding.h ossl_config.o: $(hdrdir)/ruby/intern.h +ossl_config.o: $(hdrdir)/ruby/internal/abi.h +ossl_config.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_config.o: $(hdrdir)/ruby/internal/assume.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_config.o: $(hdrdir)/ruby/internal/cast.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_config.o: $(hdrdir)/ruby/internal/config.h +ossl_config.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_config.o: $(hdrdir)/ruby/internal/core.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_config.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_config.o: $(hdrdir)/ruby/internal/ctype.h +ossl_config.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_config.o: $(hdrdir)/ruby/internal/dosish.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_config.o: $(hdrdir)/ruby/internal/error.h +ossl_config.o: $(hdrdir)/ruby/internal/eval.h +ossl_config.o: $(hdrdir)/ruby/internal/event.h +ossl_config.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_config.o: $(hdrdir)/ruby/internal/gc.h +ossl_config.o: $(hdrdir)/ruby/internal/glob.h +ossl_config.o: $(hdrdir)/ruby/internal/globals.h +ossl_config.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_config.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_config.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_config.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_config.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_config.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_config.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_config.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_config.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_config.o: $(hdrdir)/ruby/internal/iterator.h +ossl_config.o: $(hdrdir)/ruby/internal/memory.h +ossl_config.o: $(hdrdir)/ruby/internal/method.h +ossl_config.o: $(hdrdir)/ruby/internal/module.h +ossl_config.o: $(hdrdir)/ruby/internal/newobj.h +ossl_config.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_config.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_config.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_config.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_config.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_config.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_config.o: $(hdrdir)/ruby/internal/symbol.h +ossl_config.o: $(hdrdir)/ruby/internal/value.h +ossl_config.o: $(hdrdir)/ruby/internal/value_type.h +ossl_config.o: $(hdrdir)/ruby/internal/variable.h +ossl_config.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_config.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_config.o: $(hdrdir)/ruby/io.h ossl_config.o: $(hdrdir)/ruby/missing.h +ossl_config.o: $(hdrdir)/ruby/onigmo.h ossl_config.o: $(hdrdir)/ruby/oniguruma.h +ossl_config.o: $(hdrdir)/ruby/ractor.h ossl_config.o: $(hdrdir)/ruby/ruby.h ossl_config.o: $(hdrdir)/ruby/st.h ossl_config.o: $(hdrdir)/ruby/subst.h ossl_config.o: $(hdrdir)/ruby/thread.h -ossl_config.o: $(top_srcdir)/include/ruby.h ossl_config.o: openssl_missing.h ossl_config.o: ossl.h ossl_config.o: ossl_asn1.h @@ -202,30 +1174,192 @@ ossl_config.o: ossl_config.h ossl_config.o: ossl_digest.h ossl_config.o: ossl_engine.h ossl_config.o: ossl_hmac.h +ossl_config.o: ossl_kdf.h ossl_config.o: ossl_ns_spki.h ossl_config.o: ossl_ocsp.h ossl_config.o: ossl_pkcs12.h -ossl_config.o: ossl_pkcs5.h ossl_config.o: ossl_pkcs7.h ossl_config.o: ossl_pkey.h +ossl_config.o: ossl_provider.h ossl_config.o: ossl_rand.h ossl_config.o: ossl_ssl.h -ossl_config.o: ossl_version.h +ossl_config.o: ossl_ts.h ossl_config.o: ossl_x509.h -ossl_config.o: ruby_missing.h ossl_digest.o: $(RUBY_EXTCONF_H) ossl_digest.o: $(arch_hdrdir)/ruby/config.h +ossl_digest.o: $(hdrdir)/ruby.h +ossl_digest.o: $(hdrdir)/ruby/assert.h +ossl_digest.o: $(hdrdir)/ruby/backward.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_digest.o: $(hdrdir)/ruby/defines.h ossl_digest.o: $(hdrdir)/ruby/encoding.h ossl_digest.o: $(hdrdir)/ruby/intern.h +ossl_digest.o: $(hdrdir)/ruby/internal/abi.h +ossl_digest.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/assume.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_digest.o: $(hdrdir)/ruby/internal/cast.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_digest.o: $(hdrdir)/ruby/internal/config.h +ossl_digest.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_digest.o: $(hdrdir)/ruby/internal/core.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_digest.o: $(hdrdir)/ruby/internal/ctype.h +ossl_digest.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_digest.o: $(hdrdir)/ruby/internal/dosish.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_digest.o: $(hdrdir)/ruby/internal/error.h +ossl_digest.o: $(hdrdir)/ruby/internal/eval.h +ossl_digest.o: $(hdrdir)/ruby/internal/event.h +ossl_digest.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_digest.o: $(hdrdir)/ruby/internal/gc.h +ossl_digest.o: $(hdrdir)/ruby/internal/glob.h +ossl_digest.o: $(hdrdir)/ruby/internal/globals.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_digest.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_digest.o: $(hdrdir)/ruby/internal/iterator.h +ossl_digest.o: $(hdrdir)/ruby/internal/memory.h +ossl_digest.o: $(hdrdir)/ruby/internal/method.h +ossl_digest.o: $(hdrdir)/ruby/internal/module.h +ossl_digest.o: $(hdrdir)/ruby/internal/newobj.h +ossl_digest.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_digest.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_digest.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_digest.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_digest.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_digest.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_digest.o: $(hdrdir)/ruby/internal/symbol.h +ossl_digest.o: $(hdrdir)/ruby/internal/value.h +ossl_digest.o: $(hdrdir)/ruby/internal/value_type.h +ossl_digest.o: $(hdrdir)/ruby/internal/variable.h +ossl_digest.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_digest.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_digest.o: $(hdrdir)/ruby/io.h ossl_digest.o: $(hdrdir)/ruby/missing.h +ossl_digest.o: $(hdrdir)/ruby/onigmo.h ossl_digest.o: $(hdrdir)/ruby/oniguruma.h +ossl_digest.o: $(hdrdir)/ruby/ractor.h ossl_digest.o: $(hdrdir)/ruby/ruby.h ossl_digest.o: $(hdrdir)/ruby/st.h ossl_digest.o: $(hdrdir)/ruby/subst.h ossl_digest.o: $(hdrdir)/ruby/thread.h -ossl_digest.o: $(top_srcdir)/include/ruby.h ossl_digest.o: openssl_missing.h ossl_digest.o: ossl.h ossl_digest.o: ossl_asn1.h @@ -237,30 +1371,192 @@ ossl_digest.o: ossl_digest.c ossl_digest.o: ossl_digest.h ossl_digest.o: ossl_engine.h ossl_digest.o: ossl_hmac.h +ossl_digest.o: ossl_kdf.h ossl_digest.o: ossl_ns_spki.h ossl_digest.o: ossl_ocsp.h ossl_digest.o: ossl_pkcs12.h -ossl_digest.o: ossl_pkcs5.h ossl_digest.o: ossl_pkcs7.h ossl_digest.o: ossl_pkey.h +ossl_digest.o: ossl_provider.h ossl_digest.o: ossl_rand.h ossl_digest.o: ossl_ssl.h -ossl_digest.o: ossl_version.h +ossl_digest.o: ossl_ts.h ossl_digest.o: ossl_x509.h -ossl_digest.o: ruby_missing.h ossl_engine.o: $(RUBY_EXTCONF_H) ossl_engine.o: $(arch_hdrdir)/ruby/config.h +ossl_engine.o: $(hdrdir)/ruby.h +ossl_engine.o: $(hdrdir)/ruby/assert.h +ossl_engine.o: $(hdrdir)/ruby/backward.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_engine.o: $(hdrdir)/ruby/defines.h ossl_engine.o: $(hdrdir)/ruby/encoding.h ossl_engine.o: $(hdrdir)/ruby/intern.h +ossl_engine.o: $(hdrdir)/ruby/internal/abi.h +ossl_engine.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/assume.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_engine.o: $(hdrdir)/ruby/internal/cast.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_engine.o: $(hdrdir)/ruby/internal/config.h +ossl_engine.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_engine.o: $(hdrdir)/ruby/internal/core.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_engine.o: $(hdrdir)/ruby/internal/ctype.h +ossl_engine.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_engine.o: $(hdrdir)/ruby/internal/dosish.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_engine.o: $(hdrdir)/ruby/internal/error.h +ossl_engine.o: $(hdrdir)/ruby/internal/eval.h +ossl_engine.o: $(hdrdir)/ruby/internal/event.h +ossl_engine.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_engine.o: $(hdrdir)/ruby/internal/gc.h +ossl_engine.o: $(hdrdir)/ruby/internal/glob.h +ossl_engine.o: $(hdrdir)/ruby/internal/globals.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_engine.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_engine.o: $(hdrdir)/ruby/internal/iterator.h +ossl_engine.o: $(hdrdir)/ruby/internal/memory.h +ossl_engine.o: $(hdrdir)/ruby/internal/method.h +ossl_engine.o: $(hdrdir)/ruby/internal/module.h +ossl_engine.o: $(hdrdir)/ruby/internal/newobj.h +ossl_engine.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_engine.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_engine.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_engine.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_engine.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_engine.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_engine.o: $(hdrdir)/ruby/internal/symbol.h +ossl_engine.o: $(hdrdir)/ruby/internal/value.h +ossl_engine.o: $(hdrdir)/ruby/internal/value_type.h +ossl_engine.o: $(hdrdir)/ruby/internal/variable.h +ossl_engine.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_engine.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_engine.o: $(hdrdir)/ruby/io.h ossl_engine.o: $(hdrdir)/ruby/missing.h +ossl_engine.o: $(hdrdir)/ruby/onigmo.h ossl_engine.o: $(hdrdir)/ruby/oniguruma.h +ossl_engine.o: $(hdrdir)/ruby/ractor.h ossl_engine.o: $(hdrdir)/ruby/ruby.h ossl_engine.o: $(hdrdir)/ruby/st.h ossl_engine.o: $(hdrdir)/ruby/subst.h ossl_engine.o: $(hdrdir)/ruby/thread.h -ossl_engine.o: $(top_srcdir)/include/ruby.h ossl_engine.o: openssl_missing.h ossl_engine.o: ossl.h ossl_engine.o: ossl_asn1.h @@ -272,30 +1568,192 @@ ossl_engine.o: ossl_digest.h ossl_engine.o: ossl_engine.c ossl_engine.o: ossl_engine.h ossl_engine.o: ossl_hmac.h +ossl_engine.o: ossl_kdf.h ossl_engine.o: ossl_ns_spki.h ossl_engine.o: ossl_ocsp.h ossl_engine.o: ossl_pkcs12.h -ossl_engine.o: ossl_pkcs5.h ossl_engine.o: ossl_pkcs7.h ossl_engine.o: ossl_pkey.h +ossl_engine.o: ossl_provider.h ossl_engine.o: ossl_rand.h ossl_engine.o: ossl_ssl.h -ossl_engine.o: ossl_version.h +ossl_engine.o: ossl_ts.h ossl_engine.o: ossl_x509.h -ossl_engine.o: ruby_missing.h ossl_hmac.o: $(RUBY_EXTCONF_H) ossl_hmac.o: $(arch_hdrdir)/ruby/config.h +ossl_hmac.o: $(hdrdir)/ruby.h +ossl_hmac.o: $(hdrdir)/ruby/assert.h +ossl_hmac.o: $(hdrdir)/ruby/backward.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_hmac.o: $(hdrdir)/ruby/defines.h ossl_hmac.o: $(hdrdir)/ruby/encoding.h ossl_hmac.o: $(hdrdir)/ruby/intern.h +ossl_hmac.o: $(hdrdir)/ruby/internal/abi.h +ossl_hmac.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/assume.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_hmac.o: $(hdrdir)/ruby/internal/cast.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_hmac.o: $(hdrdir)/ruby/internal/config.h +ossl_hmac.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_hmac.o: $(hdrdir)/ruby/internal/ctype.h +ossl_hmac.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_hmac.o: $(hdrdir)/ruby/internal/dosish.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_hmac.o: $(hdrdir)/ruby/internal/error.h +ossl_hmac.o: $(hdrdir)/ruby/internal/eval.h +ossl_hmac.o: $(hdrdir)/ruby/internal/event.h +ossl_hmac.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_hmac.o: $(hdrdir)/ruby/internal/gc.h +ossl_hmac.o: $(hdrdir)/ruby/internal/glob.h +ossl_hmac.o: $(hdrdir)/ruby/internal/globals.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_hmac.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_hmac.o: $(hdrdir)/ruby/internal/iterator.h +ossl_hmac.o: $(hdrdir)/ruby/internal/memory.h +ossl_hmac.o: $(hdrdir)/ruby/internal/method.h +ossl_hmac.o: $(hdrdir)/ruby/internal/module.h +ossl_hmac.o: $(hdrdir)/ruby/internal/newobj.h +ossl_hmac.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_hmac.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_hmac.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_hmac.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_hmac.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_hmac.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_hmac.o: $(hdrdir)/ruby/internal/symbol.h +ossl_hmac.o: $(hdrdir)/ruby/internal/value.h +ossl_hmac.o: $(hdrdir)/ruby/internal/value_type.h +ossl_hmac.o: $(hdrdir)/ruby/internal/variable.h +ossl_hmac.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_hmac.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_hmac.o: $(hdrdir)/ruby/io.h ossl_hmac.o: $(hdrdir)/ruby/missing.h +ossl_hmac.o: $(hdrdir)/ruby/onigmo.h ossl_hmac.o: $(hdrdir)/ruby/oniguruma.h +ossl_hmac.o: $(hdrdir)/ruby/ractor.h ossl_hmac.o: $(hdrdir)/ruby/ruby.h ossl_hmac.o: $(hdrdir)/ruby/st.h ossl_hmac.o: $(hdrdir)/ruby/subst.h ossl_hmac.o: $(hdrdir)/ruby/thread.h -ossl_hmac.o: $(top_srcdir)/include/ruby.h ossl_hmac.o: openssl_missing.h ossl_hmac.o: ossl.h ossl_hmac.o: ossl_asn1.h @@ -307,30 +1765,389 @@ ossl_hmac.o: ossl_digest.h ossl_hmac.o: ossl_engine.h ossl_hmac.o: ossl_hmac.c ossl_hmac.o: ossl_hmac.h +ossl_hmac.o: ossl_kdf.h ossl_hmac.o: ossl_ns_spki.h ossl_hmac.o: ossl_ocsp.h ossl_hmac.o: ossl_pkcs12.h -ossl_hmac.o: ossl_pkcs5.h ossl_hmac.o: ossl_pkcs7.h ossl_hmac.o: ossl_pkey.h +ossl_hmac.o: ossl_provider.h ossl_hmac.o: ossl_rand.h ossl_hmac.o: ossl_ssl.h -ossl_hmac.o: ossl_version.h +ossl_hmac.o: ossl_ts.h ossl_hmac.o: ossl_x509.h -ossl_hmac.o: ruby_missing.h +ossl_kdf.o: $(RUBY_EXTCONF_H) +ossl_kdf.o: $(arch_hdrdir)/ruby/config.h +ossl_kdf.o: $(hdrdir)/ruby.h +ossl_kdf.o: $(hdrdir)/ruby/assert.h +ossl_kdf.o: $(hdrdir)/ruby/backward.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/stdarg.h +ossl_kdf.o: $(hdrdir)/ruby/defines.h +ossl_kdf.o: $(hdrdir)/ruby/encoding.h +ossl_kdf.o: $(hdrdir)/ruby/intern.h +ossl_kdf.o: $(hdrdir)/ruby/internal/abi.h +ossl_kdf.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/assume.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_kdf.o: $(hdrdir)/ruby/internal/cast.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_kdf.o: $(hdrdir)/ruby/internal/config.h +ossl_kdf.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_kdf.o: $(hdrdir)/ruby/internal/ctype.h +ossl_kdf.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_kdf.o: $(hdrdir)/ruby/internal/dosish.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_kdf.o: $(hdrdir)/ruby/internal/error.h +ossl_kdf.o: $(hdrdir)/ruby/internal/eval.h +ossl_kdf.o: $(hdrdir)/ruby/internal/event.h +ossl_kdf.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_kdf.o: $(hdrdir)/ruby/internal/gc.h +ossl_kdf.o: $(hdrdir)/ruby/internal/glob.h +ossl_kdf.o: $(hdrdir)/ruby/internal/globals.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_kdf.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_kdf.o: $(hdrdir)/ruby/internal/iterator.h +ossl_kdf.o: $(hdrdir)/ruby/internal/memory.h +ossl_kdf.o: $(hdrdir)/ruby/internal/method.h +ossl_kdf.o: $(hdrdir)/ruby/internal/module.h +ossl_kdf.o: $(hdrdir)/ruby/internal/newobj.h +ossl_kdf.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_kdf.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_kdf.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_kdf.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_kdf.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_kdf.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_kdf.o: $(hdrdir)/ruby/internal/symbol.h +ossl_kdf.o: $(hdrdir)/ruby/internal/value.h +ossl_kdf.o: $(hdrdir)/ruby/internal/value_type.h +ossl_kdf.o: $(hdrdir)/ruby/internal/variable.h +ossl_kdf.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_kdf.o: $(hdrdir)/ruby/internal/xmalloc.h +ossl_kdf.o: $(hdrdir)/ruby/io.h +ossl_kdf.o: $(hdrdir)/ruby/missing.h +ossl_kdf.o: $(hdrdir)/ruby/onigmo.h +ossl_kdf.o: $(hdrdir)/ruby/oniguruma.h +ossl_kdf.o: $(hdrdir)/ruby/ractor.h +ossl_kdf.o: $(hdrdir)/ruby/ruby.h +ossl_kdf.o: $(hdrdir)/ruby/st.h +ossl_kdf.o: $(hdrdir)/ruby/subst.h +ossl_kdf.o: $(hdrdir)/ruby/thread.h +ossl_kdf.o: openssl_missing.h +ossl_kdf.o: ossl.h +ossl_kdf.o: ossl_asn1.h +ossl_kdf.o: ossl_bio.h +ossl_kdf.o: ossl_bn.h +ossl_kdf.o: ossl_cipher.h +ossl_kdf.o: ossl_config.h +ossl_kdf.o: ossl_digest.h +ossl_kdf.o: ossl_engine.h +ossl_kdf.o: ossl_hmac.h +ossl_kdf.o: ossl_kdf.c +ossl_kdf.o: ossl_kdf.h +ossl_kdf.o: ossl_ns_spki.h +ossl_kdf.o: ossl_ocsp.h +ossl_kdf.o: ossl_pkcs12.h +ossl_kdf.o: ossl_pkcs7.h +ossl_kdf.o: ossl_pkey.h +ossl_kdf.o: ossl_provider.h +ossl_kdf.o: ossl_rand.h +ossl_kdf.o: ossl_ssl.h +ossl_kdf.o: ossl_ts.h +ossl_kdf.o: ossl_x509.h ossl_ns_spki.o: $(RUBY_EXTCONF_H) ossl_ns_spki.o: $(arch_hdrdir)/ruby/config.h +ossl_ns_spki.o: $(hdrdir)/ruby.h +ossl_ns_spki.o: $(hdrdir)/ruby/assert.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_ns_spki.o: $(hdrdir)/ruby/defines.h ossl_ns_spki.o: $(hdrdir)/ruby/encoding.h ossl_ns_spki.o: $(hdrdir)/ruby/intern.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/abi.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/assume.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/cast.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/config.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/ctype.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/dosish.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/error.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/eval.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/event.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/gc.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/glob.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/globals.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/iterator.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/memory.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/method.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/module.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/newobj.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/symbol.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/value.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/value_type.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/variable.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_ns_spki.o: $(hdrdir)/ruby/io.h ossl_ns_spki.o: $(hdrdir)/ruby/missing.h +ossl_ns_spki.o: $(hdrdir)/ruby/onigmo.h ossl_ns_spki.o: $(hdrdir)/ruby/oniguruma.h +ossl_ns_spki.o: $(hdrdir)/ruby/ractor.h ossl_ns_spki.o: $(hdrdir)/ruby/ruby.h ossl_ns_spki.o: $(hdrdir)/ruby/st.h ossl_ns_spki.o: $(hdrdir)/ruby/subst.h ossl_ns_spki.o: $(hdrdir)/ruby/thread.h -ossl_ns_spki.o: $(top_srcdir)/include/ruby.h ossl_ns_spki.o: openssl_missing.h ossl_ns_spki.o: ossl.h ossl_ns_spki.o: ossl_asn1.h @@ -341,31 +2158,193 @@ ossl_ns_spki.o: ossl_config.h ossl_ns_spki.o: ossl_digest.h ossl_ns_spki.o: ossl_engine.h ossl_ns_spki.o: ossl_hmac.h +ossl_ns_spki.o: ossl_kdf.h ossl_ns_spki.o: ossl_ns_spki.c ossl_ns_spki.o: ossl_ns_spki.h ossl_ns_spki.o: ossl_ocsp.h ossl_ns_spki.o: ossl_pkcs12.h -ossl_ns_spki.o: ossl_pkcs5.h ossl_ns_spki.o: ossl_pkcs7.h ossl_ns_spki.o: ossl_pkey.h +ossl_ns_spki.o: ossl_provider.h ossl_ns_spki.o: ossl_rand.h ossl_ns_spki.o: ossl_ssl.h -ossl_ns_spki.o: ossl_version.h +ossl_ns_spki.o: ossl_ts.h ossl_ns_spki.o: ossl_x509.h -ossl_ns_spki.o: ruby_missing.h ossl_ocsp.o: $(RUBY_EXTCONF_H) ossl_ocsp.o: $(arch_hdrdir)/ruby/config.h +ossl_ocsp.o: $(hdrdir)/ruby.h +ossl_ocsp.o: $(hdrdir)/ruby/assert.h +ossl_ocsp.o: $(hdrdir)/ruby/backward.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_ocsp.o: $(hdrdir)/ruby/defines.h ossl_ocsp.o: $(hdrdir)/ruby/encoding.h ossl_ocsp.o: $(hdrdir)/ruby/intern.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/abi.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/assume.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/cast.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/config.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/ctype.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/dosish.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/error.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/eval.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/event.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/gc.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/glob.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/globals.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/iterator.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/memory.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/method.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/module.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/newobj.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/symbol.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/value.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/value_type.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/variable.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_ocsp.o: $(hdrdir)/ruby/io.h ossl_ocsp.o: $(hdrdir)/ruby/missing.h +ossl_ocsp.o: $(hdrdir)/ruby/onigmo.h ossl_ocsp.o: $(hdrdir)/ruby/oniguruma.h +ossl_ocsp.o: $(hdrdir)/ruby/ractor.h ossl_ocsp.o: $(hdrdir)/ruby/ruby.h ossl_ocsp.o: $(hdrdir)/ruby/st.h ossl_ocsp.o: $(hdrdir)/ruby/subst.h ossl_ocsp.o: $(hdrdir)/ruby/thread.h -ossl_ocsp.o: $(top_srcdir)/include/ruby.h ossl_ocsp.o: openssl_missing.h ossl_ocsp.o: ossl.h ossl_ocsp.o: ossl_asn1.h @@ -376,31 +2355,193 @@ ossl_ocsp.o: ossl_config.h ossl_ocsp.o: ossl_digest.h ossl_ocsp.o: ossl_engine.h ossl_ocsp.o: ossl_hmac.h +ossl_ocsp.o: ossl_kdf.h ossl_ocsp.o: ossl_ns_spki.h ossl_ocsp.o: ossl_ocsp.c ossl_ocsp.o: ossl_ocsp.h ossl_ocsp.o: ossl_pkcs12.h -ossl_ocsp.o: ossl_pkcs5.h ossl_ocsp.o: ossl_pkcs7.h ossl_ocsp.o: ossl_pkey.h +ossl_ocsp.o: ossl_provider.h ossl_ocsp.o: ossl_rand.h ossl_ocsp.o: ossl_ssl.h -ossl_ocsp.o: ossl_version.h +ossl_ocsp.o: ossl_ts.h ossl_ocsp.o: ossl_x509.h -ossl_ocsp.o: ruby_missing.h ossl_pkcs12.o: $(RUBY_EXTCONF_H) ossl_pkcs12.o: $(arch_hdrdir)/ruby/config.h +ossl_pkcs12.o: $(hdrdir)/ruby.h +ossl_pkcs12.o: $(hdrdir)/ruby/assert.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_pkcs12.o: $(hdrdir)/ruby/defines.h ossl_pkcs12.o: $(hdrdir)/ruby/encoding.h ossl_pkcs12.o: $(hdrdir)/ruby/intern.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/abi.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/assume.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/cast.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/config.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/ctype.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/dosish.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/error.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/eval.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/event.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/gc.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/glob.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/globals.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/iterator.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/memory.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/method.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/module.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/newobj.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/symbol.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/value.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/value_type.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/variable.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_pkcs12.o: $(hdrdir)/ruby/io.h ossl_pkcs12.o: $(hdrdir)/ruby/missing.h +ossl_pkcs12.o: $(hdrdir)/ruby/onigmo.h ossl_pkcs12.o: $(hdrdir)/ruby/oniguruma.h +ossl_pkcs12.o: $(hdrdir)/ruby/ractor.h ossl_pkcs12.o: $(hdrdir)/ruby/ruby.h ossl_pkcs12.o: $(hdrdir)/ruby/st.h ossl_pkcs12.o: $(hdrdir)/ruby/subst.h ossl_pkcs12.o: $(hdrdir)/ruby/thread.h -ossl_pkcs12.o: $(top_srcdir)/include/ruby.h ossl_pkcs12.o: openssl_missing.h ossl_pkcs12.o: ossl.h ossl_pkcs12.o: ossl_asn1.h @@ -411,66 +2552,193 @@ ossl_pkcs12.o: ossl_config.h ossl_pkcs12.o: ossl_digest.h ossl_pkcs12.o: ossl_engine.h ossl_pkcs12.o: ossl_hmac.h +ossl_pkcs12.o: ossl_kdf.h ossl_pkcs12.o: ossl_ns_spki.h ossl_pkcs12.o: ossl_ocsp.h ossl_pkcs12.o: ossl_pkcs12.c ossl_pkcs12.o: ossl_pkcs12.h -ossl_pkcs12.o: ossl_pkcs5.h ossl_pkcs12.o: ossl_pkcs7.h ossl_pkcs12.o: ossl_pkey.h +ossl_pkcs12.o: ossl_provider.h ossl_pkcs12.o: ossl_rand.h ossl_pkcs12.o: ossl_ssl.h -ossl_pkcs12.o: ossl_version.h +ossl_pkcs12.o: ossl_ts.h ossl_pkcs12.o: ossl_x509.h -ossl_pkcs12.o: ruby_missing.h -ossl_pkcs5.o: $(RUBY_EXTCONF_H) -ossl_pkcs5.o: $(arch_hdrdir)/ruby/config.h -ossl_pkcs5.o: $(hdrdir)/ruby/defines.h -ossl_pkcs5.o: $(hdrdir)/ruby/encoding.h -ossl_pkcs5.o: $(hdrdir)/ruby/intern.h -ossl_pkcs5.o: $(hdrdir)/ruby/io.h -ossl_pkcs5.o: $(hdrdir)/ruby/missing.h -ossl_pkcs5.o: $(hdrdir)/ruby/oniguruma.h -ossl_pkcs5.o: $(hdrdir)/ruby/ruby.h -ossl_pkcs5.o: $(hdrdir)/ruby/st.h -ossl_pkcs5.o: $(hdrdir)/ruby/subst.h -ossl_pkcs5.o: $(hdrdir)/ruby/thread.h -ossl_pkcs5.o: $(top_srcdir)/include/ruby.h -ossl_pkcs5.o: openssl_missing.h -ossl_pkcs5.o: ossl.h -ossl_pkcs5.o: ossl_asn1.h -ossl_pkcs5.o: ossl_bio.h -ossl_pkcs5.o: ossl_bn.h -ossl_pkcs5.o: ossl_cipher.h -ossl_pkcs5.o: ossl_config.h -ossl_pkcs5.o: ossl_digest.h -ossl_pkcs5.o: ossl_engine.h -ossl_pkcs5.o: ossl_hmac.h -ossl_pkcs5.o: ossl_ns_spki.h -ossl_pkcs5.o: ossl_ocsp.h -ossl_pkcs5.o: ossl_pkcs12.h -ossl_pkcs5.o: ossl_pkcs5.c -ossl_pkcs5.o: ossl_pkcs5.h -ossl_pkcs5.o: ossl_pkcs7.h -ossl_pkcs5.o: ossl_pkey.h -ossl_pkcs5.o: ossl_rand.h -ossl_pkcs5.o: ossl_ssl.h -ossl_pkcs5.o: ossl_version.h -ossl_pkcs5.o: ossl_x509.h -ossl_pkcs5.o: ruby_missing.h ossl_pkcs7.o: $(RUBY_EXTCONF_H) ossl_pkcs7.o: $(arch_hdrdir)/ruby/config.h +ossl_pkcs7.o: $(hdrdir)/ruby.h +ossl_pkcs7.o: $(hdrdir)/ruby/assert.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_pkcs7.o: $(hdrdir)/ruby/defines.h ossl_pkcs7.o: $(hdrdir)/ruby/encoding.h ossl_pkcs7.o: $(hdrdir)/ruby/intern.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/abi.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/assume.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/cast.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/config.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/ctype.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/dosish.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/error.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/eval.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/event.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/gc.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/glob.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/globals.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/iterator.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/memory.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/method.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/module.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/newobj.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/symbol.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/value.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/value_type.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/variable.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_pkcs7.o: $(hdrdir)/ruby/io.h ossl_pkcs7.o: $(hdrdir)/ruby/missing.h +ossl_pkcs7.o: $(hdrdir)/ruby/onigmo.h ossl_pkcs7.o: $(hdrdir)/ruby/oniguruma.h +ossl_pkcs7.o: $(hdrdir)/ruby/ractor.h ossl_pkcs7.o: $(hdrdir)/ruby/ruby.h ossl_pkcs7.o: $(hdrdir)/ruby/st.h ossl_pkcs7.o: $(hdrdir)/ruby/subst.h ossl_pkcs7.o: $(hdrdir)/ruby/thread.h -ossl_pkcs7.o: $(top_srcdir)/include/ruby.h ossl_pkcs7.o: openssl_missing.h ossl_pkcs7.o: ossl.h ossl_pkcs7.o: ossl_asn1.h @@ -481,31 +2749,193 @@ ossl_pkcs7.o: ossl_config.h ossl_pkcs7.o: ossl_digest.h ossl_pkcs7.o: ossl_engine.h ossl_pkcs7.o: ossl_hmac.h +ossl_pkcs7.o: ossl_kdf.h ossl_pkcs7.o: ossl_ns_spki.h ossl_pkcs7.o: ossl_ocsp.h ossl_pkcs7.o: ossl_pkcs12.h -ossl_pkcs7.o: ossl_pkcs5.h ossl_pkcs7.o: ossl_pkcs7.c ossl_pkcs7.o: ossl_pkcs7.h ossl_pkcs7.o: ossl_pkey.h +ossl_pkcs7.o: ossl_provider.h ossl_pkcs7.o: ossl_rand.h ossl_pkcs7.o: ossl_ssl.h -ossl_pkcs7.o: ossl_version.h +ossl_pkcs7.o: ossl_ts.h ossl_pkcs7.o: ossl_x509.h -ossl_pkcs7.o: ruby_missing.h ossl_pkey.o: $(RUBY_EXTCONF_H) ossl_pkey.o: $(arch_hdrdir)/ruby/config.h +ossl_pkey.o: $(hdrdir)/ruby.h +ossl_pkey.o: $(hdrdir)/ruby/assert.h +ossl_pkey.o: $(hdrdir)/ruby/backward.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_pkey.o: $(hdrdir)/ruby/defines.h ossl_pkey.o: $(hdrdir)/ruby/encoding.h ossl_pkey.o: $(hdrdir)/ruby/intern.h +ossl_pkey.o: $(hdrdir)/ruby/internal/abi.h +ossl_pkey.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/assume.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_pkey.o: $(hdrdir)/ruby/internal/cast.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_pkey.o: $(hdrdir)/ruby/internal/config.h +ossl_pkey.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_pkey.o: $(hdrdir)/ruby/internal/ctype.h +ossl_pkey.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_pkey.o: $(hdrdir)/ruby/internal/dosish.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_pkey.o: $(hdrdir)/ruby/internal/error.h +ossl_pkey.o: $(hdrdir)/ruby/internal/eval.h +ossl_pkey.o: $(hdrdir)/ruby/internal/event.h +ossl_pkey.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_pkey.o: $(hdrdir)/ruby/internal/gc.h +ossl_pkey.o: $(hdrdir)/ruby/internal/glob.h +ossl_pkey.o: $(hdrdir)/ruby/internal/globals.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_pkey.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_pkey.o: $(hdrdir)/ruby/internal/iterator.h +ossl_pkey.o: $(hdrdir)/ruby/internal/memory.h +ossl_pkey.o: $(hdrdir)/ruby/internal/method.h +ossl_pkey.o: $(hdrdir)/ruby/internal/module.h +ossl_pkey.o: $(hdrdir)/ruby/internal/newobj.h +ossl_pkey.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_pkey.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_pkey.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_pkey.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_pkey.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_pkey.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_pkey.o: $(hdrdir)/ruby/internal/symbol.h +ossl_pkey.o: $(hdrdir)/ruby/internal/value.h +ossl_pkey.o: $(hdrdir)/ruby/internal/value_type.h +ossl_pkey.o: $(hdrdir)/ruby/internal/variable.h +ossl_pkey.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_pkey.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_pkey.o: $(hdrdir)/ruby/io.h ossl_pkey.o: $(hdrdir)/ruby/missing.h +ossl_pkey.o: $(hdrdir)/ruby/onigmo.h ossl_pkey.o: $(hdrdir)/ruby/oniguruma.h +ossl_pkey.o: $(hdrdir)/ruby/ractor.h ossl_pkey.o: $(hdrdir)/ruby/ruby.h ossl_pkey.o: $(hdrdir)/ruby/st.h ossl_pkey.o: $(hdrdir)/ruby/subst.h ossl_pkey.o: $(hdrdir)/ruby/thread.h -ossl_pkey.o: $(top_srcdir)/include/ruby.h ossl_pkey.o: openssl_missing.h ossl_pkey.o: ossl.h ossl_pkey.o: ossl_asn1.h @@ -516,31 +2946,193 @@ ossl_pkey.o: ossl_config.h ossl_pkey.o: ossl_digest.h ossl_pkey.o: ossl_engine.h ossl_pkey.o: ossl_hmac.h +ossl_pkey.o: ossl_kdf.h ossl_pkey.o: ossl_ns_spki.h ossl_pkey.o: ossl_ocsp.h ossl_pkey.o: ossl_pkcs12.h -ossl_pkey.o: ossl_pkcs5.h ossl_pkey.o: ossl_pkcs7.h ossl_pkey.o: ossl_pkey.c ossl_pkey.o: ossl_pkey.h +ossl_pkey.o: ossl_provider.h ossl_pkey.o: ossl_rand.h ossl_pkey.o: ossl_ssl.h -ossl_pkey.o: ossl_version.h +ossl_pkey.o: ossl_ts.h ossl_pkey.o: ossl_x509.h -ossl_pkey.o: ruby_missing.h ossl_pkey_dh.o: $(RUBY_EXTCONF_H) ossl_pkey_dh.o: $(arch_hdrdir)/ruby/config.h +ossl_pkey_dh.o: $(hdrdir)/ruby.h +ossl_pkey_dh.o: $(hdrdir)/ruby/assert.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_pkey_dh.o: $(hdrdir)/ruby/defines.h ossl_pkey_dh.o: $(hdrdir)/ruby/encoding.h ossl_pkey_dh.o: $(hdrdir)/ruby/intern.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/abi.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/assume.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/cast.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/config.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/ctype.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/dosish.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/error.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/eval.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/event.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/gc.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/glob.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/globals.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/iterator.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/memory.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/method.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/module.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/newobj.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/symbol.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/value.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/value_type.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/variable.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_pkey_dh.o: $(hdrdir)/ruby/io.h ossl_pkey_dh.o: $(hdrdir)/ruby/missing.h +ossl_pkey_dh.o: $(hdrdir)/ruby/onigmo.h ossl_pkey_dh.o: $(hdrdir)/ruby/oniguruma.h +ossl_pkey_dh.o: $(hdrdir)/ruby/ractor.h ossl_pkey_dh.o: $(hdrdir)/ruby/ruby.h ossl_pkey_dh.o: $(hdrdir)/ruby/st.h ossl_pkey_dh.o: $(hdrdir)/ruby/subst.h ossl_pkey_dh.o: $(hdrdir)/ruby/thread.h -ossl_pkey_dh.o: $(top_srcdir)/include/ruby.h ossl_pkey_dh.o: openssl_missing.h ossl_pkey_dh.o: ossl.h ossl_pkey_dh.o: ossl_asn1.h @@ -551,31 +3143,193 @@ ossl_pkey_dh.o: ossl_config.h ossl_pkey_dh.o: ossl_digest.h ossl_pkey_dh.o: ossl_engine.h ossl_pkey_dh.o: ossl_hmac.h +ossl_pkey_dh.o: ossl_kdf.h ossl_pkey_dh.o: ossl_ns_spki.h ossl_pkey_dh.o: ossl_ocsp.h ossl_pkey_dh.o: ossl_pkcs12.h -ossl_pkey_dh.o: ossl_pkcs5.h ossl_pkey_dh.o: ossl_pkcs7.h ossl_pkey_dh.o: ossl_pkey.h ossl_pkey_dh.o: ossl_pkey_dh.c +ossl_pkey_dh.o: ossl_provider.h ossl_pkey_dh.o: ossl_rand.h ossl_pkey_dh.o: ossl_ssl.h -ossl_pkey_dh.o: ossl_version.h +ossl_pkey_dh.o: ossl_ts.h ossl_pkey_dh.o: ossl_x509.h -ossl_pkey_dh.o: ruby_missing.h ossl_pkey_dsa.o: $(RUBY_EXTCONF_H) ossl_pkey_dsa.o: $(arch_hdrdir)/ruby/config.h +ossl_pkey_dsa.o: $(hdrdir)/ruby.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/assert.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_pkey_dsa.o: $(hdrdir)/ruby/defines.h ossl_pkey_dsa.o: $(hdrdir)/ruby/encoding.h ossl_pkey_dsa.o: $(hdrdir)/ruby/intern.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/abi.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/assume.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/cast.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/config.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/ctype.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/dosish.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/error.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/eval.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/event.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/gc.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/glob.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/globals.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/iterator.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/memory.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/method.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/module.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/newobj.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/symbol.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/value.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/value_type.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/variable.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_pkey_dsa.o: $(hdrdir)/ruby/io.h ossl_pkey_dsa.o: $(hdrdir)/ruby/missing.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/onigmo.h ossl_pkey_dsa.o: $(hdrdir)/ruby/oniguruma.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/ractor.h ossl_pkey_dsa.o: $(hdrdir)/ruby/ruby.h ossl_pkey_dsa.o: $(hdrdir)/ruby/st.h ossl_pkey_dsa.o: $(hdrdir)/ruby/subst.h ossl_pkey_dsa.o: $(hdrdir)/ruby/thread.h -ossl_pkey_dsa.o: $(top_srcdir)/include/ruby.h ossl_pkey_dsa.o: openssl_missing.h ossl_pkey_dsa.o: ossl.h ossl_pkey_dsa.o: ossl_asn1.h @@ -586,31 +3340,193 @@ ossl_pkey_dsa.o: ossl_config.h ossl_pkey_dsa.o: ossl_digest.h ossl_pkey_dsa.o: ossl_engine.h ossl_pkey_dsa.o: ossl_hmac.h +ossl_pkey_dsa.o: ossl_kdf.h ossl_pkey_dsa.o: ossl_ns_spki.h ossl_pkey_dsa.o: ossl_ocsp.h ossl_pkey_dsa.o: ossl_pkcs12.h -ossl_pkey_dsa.o: ossl_pkcs5.h ossl_pkey_dsa.o: ossl_pkcs7.h ossl_pkey_dsa.o: ossl_pkey.h ossl_pkey_dsa.o: ossl_pkey_dsa.c +ossl_pkey_dsa.o: ossl_provider.h ossl_pkey_dsa.o: ossl_rand.h ossl_pkey_dsa.o: ossl_ssl.h -ossl_pkey_dsa.o: ossl_version.h +ossl_pkey_dsa.o: ossl_ts.h ossl_pkey_dsa.o: ossl_x509.h -ossl_pkey_dsa.o: ruby_missing.h ossl_pkey_ec.o: $(RUBY_EXTCONF_H) ossl_pkey_ec.o: $(arch_hdrdir)/ruby/config.h +ossl_pkey_ec.o: $(hdrdir)/ruby.h +ossl_pkey_ec.o: $(hdrdir)/ruby/assert.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_pkey_ec.o: $(hdrdir)/ruby/defines.h ossl_pkey_ec.o: $(hdrdir)/ruby/encoding.h ossl_pkey_ec.o: $(hdrdir)/ruby/intern.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/abi.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/assume.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/cast.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/config.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/ctype.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/dosish.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/error.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/eval.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/event.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/gc.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/glob.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/globals.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/iterator.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/memory.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/method.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/module.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/newobj.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/symbol.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/value.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/value_type.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/variable.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_pkey_ec.o: $(hdrdir)/ruby/io.h ossl_pkey_ec.o: $(hdrdir)/ruby/missing.h +ossl_pkey_ec.o: $(hdrdir)/ruby/onigmo.h ossl_pkey_ec.o: $(hdrdir)/ruby/oniguruma.h +ossl_pkey_ec.o: $(hdrdir)/ruby/ractor.h ossl_pkey_ec.o: $(hdrdir)/ruby/ruby.h ossl_pkey_ec.o: $(hdrdir)/ruby/st.h ossl_pkey_ec.o: $(hdrdir)/ruby/subst.h ossl_pkey_ec.o: $(hdrdir)/ruby/thread.h -ossl_pkey_ec.o: $(top_srcdir)/include/ruby.h ossl_pkey_ec.o: openssl_missing.h ossl_pkey_ec.o: ossl.h ossl_pkey_ec.o: ossl_asn1.h @@ -621,31 +3537,193 @@ ossl_pkey_ec.o: ossl_config.h ossl_pkey_ec.o: ossl_digest.h ossl_pkey_ec.o: ossl_engine.h ossl_pkey_ec.o: ossl_hmac.h +ossl_pkey_ec.o: ossl_kdf.h ossl_pkey_ec.o: ossl_ns_spki.h ossl_pkey_ec.o: ossl_ocsp.h ossl_pkey_ec.o: ossl_pkcs12.h -ossl_pkey_ec.o: ossl_pkcs5.h ossl_pkey_ec.o: ossl_pkcs7.h ossl_pkey_ec.o: ossl_pkey.h ossl_pkey_ec.o: ossl_pkey_ec.c +ossl_pkey_ec.o: ossl_provider.h ossl_pkey_ec.o: ossl_rand.h ossl_pkey_ec.o: ossl_ssl.h -ossl_pkey_ec.o: ossl_version.h +ossl_pkey_ec.o: ossl_ts.h ossl_pkey_ec.o: ossl_x509.h -ossl_pkey_ec.o: ruby_missing.h ossl_pkey_rsa.o: $(RUBY_EXTCONF_H) ossl_pkey_rsa.o: $(arch_hdrdir)/ruby/config.h +ossl_pkey_rsa.o: $(hdrdir)/ruby.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/assert.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_pkey_rsa.o: $(hdrdir)/ruby/defines.h ossl_pkey_rsa.o: $(hdrdir)/ruby/encoding.h ossl_pkey_rsa.o: $(hdrdir)/ruby/intern.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/abi.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/assume.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/cast.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/config.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/ctype.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/dosish.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/error.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/eval.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/event.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/gc.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/glob.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/globals.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/iterator.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/memory.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/method.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/module.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/newobj.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/symbol.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/value.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/value_type.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/variable.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_pkey_rsa.o: $(hdrdir)/ruby/io.h ossl_pkey_rsa.o: $(hdrdir)/ruby/missing.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/onigmo.h ossl_pkey_rsa.o: $(hdrdir)/ruby/oniguruma.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/ractor.h ossl_pkey_rsa.o: $(hdrdir)/ruby/ruby.h ossl_pkey_rsa.o: $(hdrdir)/ruby/st.h ossl_pkey_rsa.o: $(hdrdir)/ruby/subst.h ossl_pkey_rsa.o: $(hdrdir)/ruby/thread.h -ossl_pkey_rsa.o: $(top_srcdir)/include/ruby.h ossl_pkey_rsa.o: openssl_missing.h ossl_pkey_rsa.o: ossl.h ossl_pkey_rsa.o: ossl_asn1.h @@ -656,31 +3734,390 @@ ossl_pkey_rsa.o: ossl_config.h ossl_pkey_rsa.o: ossl_digest.h ossl_pkey_rsa.o: ossl_engine.h ossl_pkey_rsa.o: ossl_hmac.h +ossl_pkey_rsa.o: ossl_kdf.h ossl_pkey_rsa.o: ossl_ns_spki.h ossl_pkey_rsa.o: ossl_ocsp.h ossl_pkey_rsa.o: ossl_pkcs12.h -ossl_pkey_rsa.o: ossl_pkcs5.h ossl_pkey_rsa.o: ossl_pkcs7.h ossl_pkey_rsa.o: ossl_pkey.h ossl_pkey_rsa.o: ossl_pkey_rsa.c +ossl_pkey_rsa.o: ossl_provider.h ossl_pkey_rsa.o: ossl_rand.h ossl_pkey_rsa.o: ossl_ssl.h -ossl_pkey_rsa.o: ossl_version.h +ossl_pkey_rsa.o: ossl_ts.h ossl_pkey_rsa.o: ossl_x509.h -ossl_pkey_rsa.o: ruby_missing.h +ossl_provider.o: $(RUBY_EXTCONF_H) +ossl_provider.o: $(arch_hdrdir)/ruby/config.h +ossl_provider.o: $(hdrdir)/ruby.h +ossl_provider.o: $(hdrdir)/ruby/assert.h +ossl_provider.o: $(hdrdir)/ruby/backward.h +ossl_provider.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_provider.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_provider.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_provider.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_provider.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_provider.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_provider.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_provider.o: $(hdrdir)/ruby/backward/2/stdarg.h +ossl_provider.o: $(hdrdir)/ruby/defines.h +ossl_provider.o: $(hdrdir)/ruby/encoding.h +ossl_provider.o: $(hdrdir)/ruby/intern.h +ossl_provider.o: $(hdrdir)/ruby/internal/abi.h +ossl_provider.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_provider.o: $(hdrdir)/ruby/internal/assume.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_provider.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_provider.o: $(hdrdir)/ruby/internal/cast.h +ossl_provider.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_provider.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_provider.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_provider.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_provider.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_provider.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_provider.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_provider.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_provider.o: $(hdrdir)/ruby/internal/config.h +ossl_provider.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_provider.o: $(hdrdir)/ruby/internal/core.h +ossl_provider.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_provider.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_provider.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_provider.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_provider.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_provider.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_provider.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_provider.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_provider.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_provider.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_provider.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_provider.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_provider.o: $(hdrdir)/ruby/internal/ctype.h +ossl_provider.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_provider.o: $(hdrdir)/ruby/internal/dosish.h +ossl_provider.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_provider.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_provider.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_provider.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_provider.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_provider.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_provider.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_provider.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_provider.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_provider.o: $(hdrdir)/ruby/internal/error.h +ossl_provider.o: $(hdrdir)/ruby/internal/eval.h +ossl_provider.o: $(hdrdir)/ruby/internal/event.h +ossl_provider.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_provider.o: $(hdrdir)/ruby/internal/gc.h +ossl_provider.o: $(hdrdir)/ruby/internal/glob.h +ossl_provider.o: $(hdrdir)/ruby/internal/globals.h +ossl_provider.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_provider.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_provider.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_provider.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_provider.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_provider.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_provider.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_provider.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_provider.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_provider.o: $(hdrdir)/ruby/internal/iterator.h +ossl_provider.o: $(hdrdir)/ruby/internal/memory.h +ossl_provider.o: $(hdrdir)/ruby/internal/method.h +ossl_provider.o: $(hdrdir)/ruby/internal/module.h +ossl_provider.o: $(hdrdir)/ruby/internal/newobj.h +ossl_provider.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_provider.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_provider.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_provider.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_provider.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_provider.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_provider.o: $(hdrdir)/ruby/internal/symbol.h +ossl_provider.o: $(hdrdir)/ruby/internal/value.h +ossl_provider.o: $(hdrdir)/ruby/internal/value_type.h +ossl_provider.o: $(hdrdir)/ruby/internal/variable.h +ossl_provider.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_provider.o: $(hdrdir)/ruby/internal/xmalloc.h +ossl_provider.o: $(hdrdir)/ruby/io.h +ossl_provider.o: $(hdrdir)/ruby/missing.h +ossl_provider.o: $(hdrdir)/ruby/onigmo.h +ossl_provider.o: $(hdrdir)/ruby/oniguruma.h +ossl_provider.o: $(hdrdir)/ruby/ractor.h +ossl_provider.o: $(hdrdir)/ruby/ruby.h +ossl_provider.o: $(hdrdir)/ruby/st.h +ossl_provider.o: $(hdrdir)/ruby/subst.h +ossl_provider.o: $(hdrdir)/ruby/thread.h +ossl_provider.o: openssl_missing.h +ossl_provider.o: ossl.h +ossl_provider.o: ossl_asn1.h +ossl_provider.o: ossl_bio.h +ossl_provider.o: ossl_bn.h +ossl_provider.o: ossl_cipher.h +ossl_provider.o: ossl_config.h +ossl_provider.o: ossl_digest.h +ossl_provider.o: ossl_engine.h +ossl_provider.o: ossl_hmac.h +ossl_provider.o: ossl_kdf.h +ossl_provider.o: ossl_ns_spki.h +ossl_provider.o: ossl_ocsp.h +ossl_provider.o: ossl_pkcs12.h +ossl_provider.o: ossl_pkcs7.h +ossl_provider.o: ossl_pkey.h +ossl_provider.o: ossl_provider.c +ossl_provider.o: ossl_provider.h +ossl_provider.o: ossl_rand.h +ossl_provider.o: ossl_ssl.h +ossl_provider.o: ossl_ts.h +ossl_provider.o: ossl_x509.h ossl_rand.o: $(RUBY_EXTCONF_H) ossl_rand.o: $(arch_hdrdir)/ruby/config.h +ossl_rand.o: $(hdrdir)/ruby.h +ossl_rand.o: $(hdrdir)/ruby/assert.h +ossl_rand.o: $(hdrdir)/ruby/backward.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_rand.o: $(hdrdir)/ruby/defines.h ossl_rand.o: $(hdrdir)/ruby/encoding.h ossl_rand.o: $(hdrdir)/ruby/intern.h +ossl_rand.o: $(hdrdir)/ruby/internal/abi.h +ossl_rand.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/assume.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_rand.o: $(hdrdir)/ruby/internal/cast.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_rand.o: $(hdrdir)/ruby/internal/config.h +ossl_rand.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_rand.o: $(hdrdir)/ruby/internal/core.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_rand.o: $(hdrdir)/ruby/internal/ctype.h +ossl_rand.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_rand.o: $(hdrdir)/ruby/internal/dosish.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_rand.o: $(hdrdir)/ruby/internal/error.h +ossl_rand.o: $(hdrdir)/ruby/internal/eval.h +ossl_rand.o: $(hdrdir)/ruby/internal/event.h +ossl_rand.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_rand.o: $(hdrdir)/ruby/internal/gc.h +ossl_rand.o: $(hdrdir)/ruby/internal/glob.h +ossl_rand.o: $(hdrdir)/ruby/internal/globals.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_rand.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_rand.o: $(hdrdir)/ruby/internal/iterator.h +ossl_rand.o: $(hdrdir)/ruby/internal/memory.h +ossl_rand.o: $(hdrdir)/ruby/internal/method.h +ossl_rand.o: $(hdrdir)/ruby/internal/module.h +ossl_rand.o: $(hdrdir)/ruby/internal/newobj.h +ossl_rand.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_rand.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_rand.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_rand.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_rand.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_rand.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_rand.o: $(hdrdir)/ruby/internal/symbol.h +ossl_rand.o: $(hdrdir)/ruby/internal/value.h +ossl_rand.o: $(hdrdir)/ruby/internal/value_type.h +ossl_rand.o: $(hdrdir)/ruby/internal/variable.h +ossl_rand.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_rand.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_rand.o: $(hdrdir)/ruby/io.h ossl_rand.o: $(hdrdir)/ruby/missing.h +ossl_rand.o: $(hdrdir)/ruby/onigmo.h ossl_rand.o: $(hdrdir)/ruby/oniguruma.h +ossl_rand.o: $(hdrdir)/ruby/ractor.h ossl_rand.o: $(hdrdir)/ruby/ruby.h ossl_rand.o: $(hdrdir)/ruby/st.h ossl_rand.o: $(hdrdir)/ruby/subst.h ossl_rand.o: $(hdrdir)/ruby/thread.h -ossl_rand.o: $(top_srcdir)/include/ruby.h ossl_rand.o: openssl_missing.h ossl_rand.o: ossl.h ossl_rand.o: ossl_asn1.h @@ -691,31 +4128,193 @@ ossl_rand.o: ossl_config.h ossl_rand.o: ossl_digest.h ossl_rand.o: ossl_engine.h ossl_rand.o: ossl_hmac.h +ossl_rand.o: ossl_kdf.h ossl_rand.o: ossl_ns_spki.h ossl_rand.o: ossl_ocsp.h ossl_rand.o: ossl_pkcs12.h -ossl_rand.o: ossl_pkcs5.h ossl_rand.o: ossl_pkcs7.h ossl_rand.o: ossl_pkey.h +ossl_rand.o: ossl_provider.h ossl_rand.o: ossl_rand.c ossl_rand.o: ossl_rand.h ossl_rand.o: ossl_ssl.h -ossl_rand.o: ossl_version.h +ossl_rand.o: ossl_ts.h ossl_rand.o: ossl_x509.h -ossl_rand.o: ruby_missing.h ossl_ssl.o: $(RUBY_EXTCONF_H) ossl_ssl.o: $(arch_hdrdir)/ruby/config.h +ossl_ssl.o: $(hdrdir)/ruby.h +ossl_ssl.o: $(hdrdir)/ruby/assert.h +ossl_ssl.o: $(hdrdir)/ruby/backward.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_ssl.o: $(hdrdir)/ruby/defines.h ossl_ssl.o: $(hdrdir)/ruby/encoding.h ossl_ssl.o: $(hdrdir)/ruby/intern.h +ossl_ssl.o: $(hdrdir)/ruby/internal/abi.h +ossl_ssl.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/assume.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_ssl.o: $(hdrdir)/ruby/internal/cast.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_ssl.o: $(hdrdir)/ruby/internal/config.h +ossl_ssl.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_ssl.o: $(hdrdir)/ruby/internal/ctype.h +ossl_ssl.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_ssl.o: $(hdrdir)/ruby/internal/dosish.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_ssl.o: $(hdrdir)/ruby/internal/error.h +ossl_ssl.o: $(hdrdir)/ruby/internal/eval.h +ossl_ssl.o: $(hdrdir)/ruby/internal/event.h +ossl_ssl.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_ssl.o: $(hdrdir)/ruby/internal/gc.h +ossl_ssl.o: $(hdrdir)/ruby/internal/glob.h +ossl_ssl.o: $(hdrdir)/ruby/internal/globals.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_ssl.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_ssl.o: $(hdrdir)/ruby/internal/iterator.h +ossl_ssl.o: $(hdrdir)/ruby/internal/memory.h +ossl_ssl.o: $(hdrdir)/ruby/internal/method.h +ossl_ssl.o: $(hdrdir)/ruby/internal/module.h +ossl_ssl.o: $(hdrdir)/ruby/internal/newobj.h +ossl_ssl.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_ssl.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_ssl.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_ssl.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_ssl.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_ssl.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_ssl.o: $(hdrdir)/ruby/internal/symbol.h +ossl_ssl.o: $(hdrdir)/ruby/internal/value.h +ossl_ssl.o: $(hdrdir)/ruby/internal/value_type.h +ossl_ssl.o: $(hdrdir)/ruby/internal/variable.h +ossl_ssl.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_ssl.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_ssl.o: $(hdrdir)/ruby/io.h ossl_ssl.o: $(hdrdir)/ruby/missing.h +ossl_ssl.o: $(hdrdir)/ruby/onigmo.h ossl_ssl.o: $(hdrdir)/ruby/oniguruma.h +ossl_ssl.o: $(hdrdir)/ruby/ractor.h ossl_ssl.o: $(hdrdir)/ruby/ruby.h ossl_ssl.o: $(hdrdir)/ruby/st.h ossl_ssl.o: $(hdrdir)/ruby/subst.h ossl_ssl.o: $(hdrdir)/ruby/thread.h -ossl_ssl.o: $(top_srcdir)/include/ruby.h ossl_ssl.o: openssl_missing.h ossl_ssl.o: ossl.h ossl_ssl.o: ossl_asn1.h @@ -726,31 +4325,193 @@ ossl_ssl.o: ossl_config.h ossl_ssl.o: ossl_digest.h ossl_ssl.o: ossl_engine.h ossl_ssl.o: ossl_hmac.h +ossl_ssl.o: ossl_kdf.h ossl_ssl.o: ossl_ns_spki.h ossl_ssl.o: ossl_ocsp.h ossl_ssl.o: ossl_pkcs12.h -ossl_ssl.o: ossl_pkcs5.h ossl_ssl.o: ossl_pkcs7.h ossl_ssl.o: ossl_pkey.h +ossl_ssl.o: ossl_provider.h ossl_ssl.o: ossl_rand.h ossl_ssl.o: ossl_ssl.c ossl_ssl.o: ossl_ssl.h -ossl_ssl.o: ossl_version.h +ossl_ssl.o: ossl_ts.h ossl_ssl.o: ossl_x509.h -ossl_ssl.o: ruby_missing.h ossl_ssl_session.o: $(RUBY_EXTCONF_H) ossl_ssl_session.o: $(arch_hdrdir)/ruby/config.h +ossl_ssl_session.o: $(hdrdir)/ruby.h +ossl_ssl_session.o: $(hdrdir)/ruby/assert.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_ssl_session.o: $(hdrdir)/ruby/defines.h ossl_ssl_session.o: $(hdrdir)/ruby/encoding.h ossl_ssl_session.o: $(hdrdir)/ruby/intern.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/abi.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/assume.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/cast.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/config.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/ctype.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/dosish.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/error.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/eval.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/event.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/gc.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/glob.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/globals.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/iterator.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/memory.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/method.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/module.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/newobj.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/symbol.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/value.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/value_type.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/variable.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_ssl_session.o: $(hdrdir)/ruby/io.h ossl_ssl_session.o: $(hdrdir)/ruby/missing.h +ossl_ssl_session.o: $(hdrdir)/ruby/onigmo.h ossl_ssl_session.o: $(hdrdir)/ruby/oniguruma.h +ossl_ssl_session.o: $(hdrdir)/ruby/ractor.h ossl_ssl_session.o: $(hdrdir)/ruby/ruby.h ossl_ssl_session.o: $(hdrdir)/ruby/st.h ossl_ssl_session.o: $(hdrdir)/ruby/subst.h ossl_ssl_session.o: $(hdrdir)/ruby/thread.h -ossl_ssl_session.o: $(top_srcdir)/include/ruby.h ossl_ssl_session.o: openssl_missing.h ossl_ssl_session.o: ossl.h ossl_ssl_session.o: ossl_asn1.h @@ -761,31 +4522,390 @@ ossl_ssl_session.o: ossl_config.h ossl_ssl_session.o: ossl_digest.h ossl_ssl_session.o: ossl_engine.h ossl_ssl_session.o: ossl_hmac.h +ossl_ssl_session.o: ossl_kdf.h ossl_ssl_session.o: ossl_ns_spki.h ossl_ssl_session.o: ossl_ocsp.h ossl_ssl_session.o: ossl_pkcs12.h -ossl_ssl_session.o: ossl_pkcs5.h ossl_ssl_session.o: ossl_pkcs7.h ossl_ssl_session.o: ossl_pkey.h +ossl_ssl_session.o: ossl_provider.h ossl_ssl_session.o: ossl_rand.h ossl_ssl_session.o: ossl_ssl.h ossl_ssl_session.o: ossl_ssl_session.c -ossl_ssl_session.o: ossl_version.h +ossl_ssl_session.o: ossl_ts.h ossl_ssl_session.o: ossl_x509.h -ossl_ssl_session.o: ruby_missing.h +ossl_ts.o: $(RUBY_EXTCONF_H) +ossl_ts.o: $(arch_hdrdir)/ruby/config.h +ossl_ts.o: $(hdrdir)/ruby.h +ossl_ts.o: $(hdrdir)/ruby/assert.h +ossl_ts.o: $(hdrdir)/ruby/backward.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/stdarg.h +ossl_ts.o: $(hdrdir)/ruby/defines.h +ossl_ts.o: $(hdrdir)/ruby/encoding.h +ossl_ts.o: $(hdrdir)/ruby/intern.h +ossl_ts.o: $(hdrdir)/ruby/internal/abi.h +ossl_ts.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/assume.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_ts.o: $(hdrdir)/ruby/internal/cast.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_ts.o: $(hdrdir)/ruby/internal/config.h +ossl_ts.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_ts.o: $(hdrdir)/ruby/internal/core.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_ts.o: $(hdrdir)/ruby/internal/ctype.h +ossl_ts.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_ts.o: $(hdrdir)/ruby/internal/dosish.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_ts.o: $(hdrdir)/ruby/internal/error.h +ossl_ts.o: $(hdrdir)/ruby/internal/eval.h +ossl_ts.o: $(hdrdir)/ruby/internal/event.h +ossl_ts.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_ts.o: $(hdrdir)/ruby/internal/gc.h +ossl_ts.o: $(hdrdir)/ruby/internal/glob.h +ossl_ts.o: $(hdrdir)/ruby/internal/globals.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_ts.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_ts.o: $(hdrdir)/ruby/internal/iterator.h +ossl_ts.o: $(hdrdir)/ruby/internal/memory.h +ossl_ts.o: $(hdrdir)/ruby/internal/method.h +ossl_ts.o: $(hdrdir)/ruby/internal/module.h +ossl_ts.o: $(hdrdir)/ruby/internal/newobj.h +ossl_ts.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_ts.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_ts.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_ts.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_ts.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_ts.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_ts.o: $(hdrdir)/ruby/internal/symbol.h +ossl_ts.o: $(hdrdir)/ruby/internal/value.h +ossl_ts.o: $(hdrdir)/ruby/internal/value_type.h +ossl_ts.o: $(hdrdir)/ruby/internal/variable.h +ossl_ts.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_ts.o: $(hdrdir)/ruby/internal/xmalloc.h +ossl_ts.o: $(hdrdir)/ruby/io.h +ossl_ts.o: $(hdrdir)/ruby/missing.h +ossl_ts.o: $(hdrdir)/ruby/onigmo.h +ossl_ts.o: $(hdrdir)/ruby/oniguruma.h +ossl_ts.o: $(hdrdir)/ruby/ractor.h +ossl_ts.o: $(hdrdir)/ruby/ruby.h +ossl_ts.o: $(hdrdir)/ruby/st.h +ossl_ts.o: $(hdrdir)/ruby/subst.h +ossl_ts.o: $(hdrdir)/ruby/thread.h +ossl_ts.o: openssl_missing.h +ossl_ts.o: ossl.h +ossl_ts.o: ossl_asn1.h +ossl_ts.o: ossl_bio.h +ossl_ts.o: ossl_bn.h +ossl_ts.o: ossl_cipher.h +ossl_ts.o: ossl_config.h +ossl_ts.o: ossl_digest.h +ossl_ts.o: ossl_engine.h +ossl_ts.o: ossl_hmac.h +ossl_ts.o: ossl_kdf.h +ossl_ts.o: ossl_ns_spki.h +ossl_ts.o: ossl_ocsp.h +ossl_ts.o: ossl_pkcs12.h +ossl_ts.o: ossl_pkcs7.h +ossl_ts.o: ossl_pkey.h +ossl_ts.o: ossl_provider.h +ossl_ts.o: ossl_rand.h +ossl_ts.o: ossl_ssl.h +ossl_ts.o: ossl_ts.c +ossl_ts.o: ossl_ts.h +ossl_ts.o: ossl_x509.h ossl_x509.o: $(RUBY_EXTCONF_H) ossl_x509.o: $(arch_hdrdir)/ruby/config.h +ossl_x509.o: $(hdrdir)/ruby.h +ossl_x509.o: $(hdrdir)/ruby/assert.h +ossl_x509.o: $(hdrdir)/ruby/backward.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509.o: $(hdrdir)/ruby/defines.h ossl_x509.o: $(hdrdir)/ruby/encoding.h ossl_x509.o: $(hdrdir)/ruby/intern.h +ossl_x509.o: $(hdrdir)/ruby/internal/abi.h +ossl_x509.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509.o: $(hdrdir)/ruby/internal/config.h +ossl_x509.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509.o: $(hdrdir)/ruby/internal/core.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509.o: $(hdrdir)/ruby/internal/error.h +ossl_x509.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509.o: $(hdrdir)/ruby/internal/event.h +ossl_x509.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509.o: $(hdrdir)/ruby/internal/method.h +ossl_x509.o: $(hdrdir)/ruby/internal/module.h +ossl_x509.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_x509.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_x509.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_x509.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_x509.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_x509.o: $(hdrdir)/ruby/internal/symbol.h +ossl_x509.o: $(hdrdir)/ruby/internal/value.h +ossl_x509.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509.o: $(hdrdir)/ruby/io.h ossl_x509.o: $(hdrdir)/ruby/missing.h +ossl_x509.o: $(hdrdir)/ruby/onigmo.h ossl_x509.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509.o: $(hdrdir)/ruby/ractor.h ossl_x509.o: $(hdrdir)/ruby/ruby.h ossl_x509.o: $(hdrdir)/ruby/st.h ossl_x509.o: $(hdrdir)/ruby/subst.h ossl_x509.o: $(hdrdir)/ruby/thread.h -ossl_x509.o: $(top_srcdir)/include/ruby.h ossl_x509.o: openssl_missing.h ossl_x509.o: ossl.h ossl_x509.o: ossl_asn1.h @@ -796,31 +4916,193 @@ ossl_x509.o: ossl_config.h ossl_x509.o: ossl_digest.h ossl_x509.o: ossl_engine.h ossl_x509.o: ossl_hmac.h +ossl_x509.o: ossl_kdf.h ossl_x509.o: ossl_ns_spki.h ossl_x509.o: ossl_ocsp.h ossl_x509.o: ossl_pkcs12.h -ossl_x509.o: ossl_pkcs5.h ossl_x509.o: ossl_pkcs7.h ossl_x509.o: ossl_pkey.h +ossl_x509.o: ossl_provider.h ossl_x509.o: ossl_rand.h ossl_x509.o: ossl_ssl.h -ossl_x509.o: ossl_version.h +ossl_x509.o: ossl_ts.h ossl_x509.o: ossl_x509.c ossl_x509.o: ossl_x509.h -ossl_x509.o: ruby_missing.h ossl_x509attr.o: $(RUBY_EXTCONF_H) ossl_x509attr.o: $(arch_hdrdir)/ruby/config.h +ossl_x509attr.o: $(hdrdir)/ruby.h +ossl_x509attr.o: $(hdrdir)/ruby/assert.h +ossl_x509attr.o: $(hdrdir)/ruby/backward.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509attr.o: $(hdrdir)/ruby/defines.h ossl_x509attr.o: $(hdrdir)/ruby/encoding.h ossl_x509attr.o: $(hdrdir)/ruby/intern.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/abi.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/config.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/error.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/event.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/method.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/module.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/symbol.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/value.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509attr.o: $(hdrdir)/ruby/io.h ossl_x509attr.o: $(hdrdir)/ruby/missing.h +ossl_x509attr.o: $(hdrdir)/ruby/onigmo.h ossl_x509attr.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509attr.o: $(hdrdir)/ruby/ractor.h ossl_x509attr.o: $(hdrdir)/ruby/ruby.h ossl_x509attr.o: $(hdrdir)/ruby/st.h ossl_x509attr.o: $(hdrdir)/ruby/subst.h ossl_x509attr.o: $(hdrdir)/ruby/thread.h -ossl_x509attr.o: $(top_srcdir)/include/ruby.h ossl_x509attr.o: openssl_missing.h ossl_x509attr.o: ossl.h ossl_x509attr.o: ossl_asn1.h @@ -831,31 +5113,193 @@ ossl_x509attr.o: ossl_config.h ossl_x509attr.o: ossl_digest.h ossl_x509attr.o: ossl_engine.h ossl_x509attr.o: ossl_hmac.h +ossl_x509attr.o: ossl_kdf.h ossl_x509attr.o: ossl_ns_spki.h ossl_x509attr.o: ossl_ocsp.h ossl_x509attr.o: ossl_pkcs12.h -ossl_x509attr.o: ossl_pkcs5.h ossl_x509attr.o: ossl_pkcs7.h ossl_x509attr.o: ossl_pkey.h +ossl_x509attr.o: ossl_provider.h ossl_x509attr.o: ossl_rand.h ossl_x509attr.o: ossl_ssl.h -ossl_x509attr.o: ossl_version.h +ossl_x509attr.o: ossl_ts.h ossl_x509attr.o: ossl_x509.h ossl_x509attr.o: ossl_x509attr.c -ossl_x509attr.o: ruby_missing.h ossl_x509cert.o: $(RUBY_EXTCONF_H) ossl_x509cert.o: $(arch_hdrdir)/ruby/config.h +ossl_x509cert.o: $(hdrdir)/ruby.h +ossl_x509cert.o: $(hdrdir)/ruby/assert.h +ossl_x509cert.o: $(hdrdir)/ruby/backward.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509cert.o: $(hdrdir)/ruby/defines.h ossl_x509cert.o: $(hdrdir)/ruby/encoding.h ossl_x509cert.o: $(hdrdir)/ruby/intern.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/abi.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/config.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/error.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/event.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/method.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/module.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/symbol.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/value.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509cert.o: $(hdrdir)/ruby/io.h ossl_x509cert.o: $(hdrdir)/ruby/missing.h +ossl_x509cert.o: $(hdrdir)/ruby/onigmo.h ossl_x509cert.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509cert.o: $(hdrdir)/ruby/ractor.h ossl_x509cert.o: $(hdrdir)/ruby/ruby.h ossl_x509cert.o: $(hdrdir)/ruby/st.h ossl_x509cert.o: $(hdrdir)/ruby/subst.h ossl_x509cert.o: $(hdrdir)/ruby/thread.h -ossl_x509cert.o: $(top_srcdir)/include/ruby.h ossl_x509cert.o: openssl_missing.h ossl_x509cert.o: ossl.h ossl_x509cert.o: ossl_asn1.h @@ -866,31 +5310,193 @@ ossl_x509cert.o: ossl_config.h ossl_x509cert.o: ossl_digest.h ossl_x509cert.o: ossl_engine.h ossl_x509cert.o: ossl_hmac.h +ossl_x509cert.o: ossl_kdf.h ossl_x509cert.o: ossl_ns_spki.h ossl_x509cert.o: ossl_ocsp.h ossl_x509cert.o: ossl_pkcs12.h -ossl_x509cert.o: ossl_pkcs5.h ossl_x509cert.o: ossl_pkcs7.h ossl_x509cert.o: ossl_pkey.h +ossl_x509cert.o: ossl_provider.h ossl_x509cert.o: ossl_rand.h ossl_x509cert.o: ossl_ssl.h -ossl_x509cert.o: ossl_version.h +ossl_x509cert.o: ossl_ts.h ossl_x509cert.o: ossl_x509.h ossl_x509cert.o: ossl_x509cert.c -ossl_x509cert.o: ruby_missing.h ossl_x509crl.o: $(RUBY_EXTCONF_H) ossl_x509crl.o: $(arch_hdrdir)/ruby/config.h +ossl_x509crl.o: $(hdrdir)/ruby.h +ossl_x509crl.o: $(hdrdir)/ruby/assert.h +ossl_x509crl.o: $(hdrdir)/ruby/backward.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509crl.o: $(hdrdir)/ruby/defines.h ossl_x509crl.o: $(hdrdir)/ruby/encoding.h ossl_x509crl.o: $(hdrdir)/ruby/intern.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/abi.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/config.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/error.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/event.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/method.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/module.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/symbol.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/value.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509crl.o: $(hdrdir)/ruby/io.h ossl_x509crl.o: $(hdrdir)/ruby/missing.h +ossl_x509crl.o: $(hdrdir)/ruby/onigmo.h ossl_x509crl.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509crl.o: $(hdrdir)/ruby/ractor.h ossl_x509crl.o: $(hdrdir)/ruby/ruby.h ossl_x509crl.o: $(hdrdir)/ruby/st.h ossl_x509crl.o: $(hdrdir)/ruby/subst.h ossl_x509crl.o: $(hdrdir)/ruby/thread.h -ossl_x509crl.o: $(top_srcdir)/include/ruby.h ossl_x509crl.o: openssl_missing.h ossl_x509crl.o: ossl.h ossl_x509crl.o: ossl_asn1.h @@ -901,31 +5507,193 @@ ossl_x509crl.o: ossl_config.h ossl_x509crl.o: ossl_digest.h ossl_x509crl.o: ossl_engine.h ossl_x509crl.o: ossl_hmac.h +ossl_x509crl.o: ossl_kdf.h ossl_x509crl.o: ossl_ns_spki.h ossl_x509crl.o: ossl_ocsp.h ossl_x509crl.o: ossl_pkcs12.h -ossl_x509crl.o: ossl_pkcs5.h ossl_x509crl.o: ossl_pkcs7.h ossl_x509crl.o: ossl_pkey.h +ossl_x509crl.o: ossl_provider.h ossl_x509crl.o: ossl_rand.h ossl_x509crl.o: ossl_ssl.h -ossl_x509crl.o: ossl_version.h +ossl_x509crl.o: ossl_ts.h ossl_x509crl.o: ossl_x509.h ossl_x509crl.o: ossl_x509crl.c -ossl_x509crl.o: ruby_missing.h ossl_x509ext.o: $(RUBY_EXTCONF_H) ossl_x509ext.o: $(arch_hdrdir)/ruby/config.h +ossl_x509ext.o: $(hdrdir)/ruby.h +ossl_x509ext.o: $(hdrdir)/ruby/assert.h +ossl_x509ext.o: $(hdrdir)/ruby/backward.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509ext.o: $(hdrdir)/ruby/defines.h ossl_x509ext.o: $(hdrdir)/ruby/encoding.h ossl_x509ext.o: $(hdrdir)/ruby/intern.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/abi.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/config.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/error.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/event.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/method.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/module.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/symbol.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/value.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509ext.o: $(hdrdir)/ruby/io.h ossl_x509ext.o: $(hdrdir)/ruby/missing.h +ossl_x509ext.o: $(hdrdir)/ruby/onigmo.h ossl_x509ext.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509ext.o: $(hdrdir)/ruby/ractor.h ossl_x509ext.o: $(hdrdir)/ruby/ruby.h ossl_x509ext.o: $(hdrdir)/ruby/st.h ossl_x509ext.o: $(hdrdir)/ruby/subst.h ossl_x509ext.o: $(hdrdir)/ruby/thread.h -ossl_x509ext.o: $(top_srcdir)/include/ruby.h ossl_x509ext.o: openssl_missing.h ossl_x509ext.o: ossl.h ossl_x509ext.o: ossl_asn1.h @@ -936,31 +5704,193 @@ ossl_x509ext.o: ossl_config.h ossl_x509ext.o: ossl_digest.h ossl_x509ext.o: ossl_engine.h ossl_x509ext.o: ossl_hmac.h +ossl_x509ext.o: ossl_kdf.h ossl_x509ext.o: ossl_ns_spki.h ossl_x509ext.o: ossl_ocsp.h ossl_x509ext.o: ossl_pkcs12.h -ossl_x509ext.o: ossl_pkcs5.h ossl_x509ext.o: ossl_pkcs7.h ossl_x509ext.o: ossl_pkey.h +ossl_x509ext.o: ossl_provider.h ossl_x509ext.o: ossl_rand.h ossl_x509ext.o: ossl_ssl.h -ossl_x509ext.o: ossl_version.h +ossl_x509ext.o: ossl_ts.h ossl_x509ext.o: ossl_x509.h ossl_x509ext.o: ossl_x509ext.c -ossl_x509ext.o: ruby_missing.h ossl_x509name.o: $(RUBY_EXTCONF_H) ossl_x509name.o: $(arch_hdrdir)/ruby/config.h +ossl_x509name.o: $(hdrdir)/ruby.h +ossl_x509name.o: $(hdrdir)/ruby/assert.h +ossl_x509name.o: $(hdrdir)/ruby/backward.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509name.o: $(hdrdir)/ruby/defines.h ossl_x509name.o: $(hdrdir)/ruby/encoding.h ossl_x509name.o: $(hdrdir)/ruby/intern.h +ossl_x509name.o: $(hdrdir)/ruby/internal/abi.h +ossl_x509name.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509name.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509name.o: $(hdrdir)/ruby/internal/config.h +ossl_x509name.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509name.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509name.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509name.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509name.o: $(hdrdir)/ruby/internal/error.h +ossl_x509name.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509name.o: $(hdrdir)/ruby/internal/event.h +ossl_x509name.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509name.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509name.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509name.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509name.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509name.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509name.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509name.o: $(hdrdir)/ruby/internal/method.h +ossl_x509name.o: $(hdrdir)/ruby/internal/module.h +ossl_x509name.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509name.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_x509name.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_x509name.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_x509name.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_x509name.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509name.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_x509name.o: $(hdrdir)/ruby/internal/symbol.h +ossl_x509name.o: $(hdrdir)/ruby/internal/value.h +ossl_x509name.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509name.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509name.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509name.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509name.o: $(hdrdir)/ruby/io.h ossl_x509name.o: $(hdrdir)/ruby/missing.h +ossl_x509name.o: $(hdrdir)/ruby/onigmo.h ossl_x509name.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509name.o: $(hdrdir)/ruby/ractor.h ossl_x509name.o: $(hdrdir)/ruby/ruby.h ossl_x509name.o: $(hdrdir)/ruby/st.h ossl_x509name.o: $(hdrdir)/ruby/subst.h ossl_x509name.o: $(hdrdir)/ruby/thread.h -ossl_x509name.o: $(top_srcdir)/include/ruby.h ossl_x509name.o: openssl_missing.h ossl_x509name.o: ossl.h ossl_x509name.o: ossl_asn1.h @@ -971,31 +5901,193 @@ ossl_x509name.o: ossl_config.h ossl_x509name.o: ossl_digest.h ossl_x509name.o: ossl_engine.h ossl_x509name.o: ossl_hmac.h +ossl_x509name.o: ossl_kdf.h ossl_x509name.o: ossl_ns_spki.h ossl_x509name.o: ossl_ocsp.h ossl_x509name.o: ossl_pkcs12.h -ossl_x509name.o: ossl_pkcs5.h ossl_x509name.o: ossl_pkcs7.h ossl_x509name.o: ossl_pkey.h +ossl_x509name.o: ossl_provider.h ossl_x509name.o: ossl_rand.h ossl_x509name.o: ossl_ssl.h -ossl_x509name.o: ossl_version.h +ossl_x509name.o: ossl_ts.h ossl_x509name.o: ossl_x509.h ossl_x509name.o: ossl_x509name.c -ossl_x509name.o: ruby_missing.h ossl_x509req.o: $(RUBY_EXTCONF_H) ossl_x509req.o: $(arch_hdrdir)/ruby/config.h +ossl_x509req.o: $(hdrdir)/ruby.h +ossl_x509req.o: $(hdrdir)/ruby/assert.h +ossl_x509req.o: $(hdrdir)/ruby/backward.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509req.o: $(hdrdir)/ruby/defines.h ossl_x509req.o: $(hdrdir)/ruby/encoding.h ossl_x509req.o: $(hdrdir)/ruby/intern.h +ossl_x509req.o: $(hdrdir)/ruby/internal/abi.h +ossl_x509req.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509req.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509req.o: $(hdrdir)/ruby/internal/config.h +ossl_x509req.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509req.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509req.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509req.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509req.o: $(hdrdir)/ruby/internal/error.h +ossl_x509req.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509req.o: $(hdrdir)/ruby/internal/event.h +ossl_x509req.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509req.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509req.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509req.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509req.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509req.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509req.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509req.o: $(hdrdir)/ruby/internal/method.h +ossl_x509req.o: $(hdrdir)/ruby/internal/module.h +ossl_x509req.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509req.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_x509req.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_x509req.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_x509req.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_x509req.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509req.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_x509req.o: $(hdrdir)/ruby/internal/symbol.h +ossl_x509req.o: $(hdrdir)/ruby/internal/value.h +ossl_x509req.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509req.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509req.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509req.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509req.o: $(hdrdir)/ruby/io.h ossl_x509req.o: $(hdrdir)/ruby/missing.h +ossl_x509req.o: $(hdrdir)/ruby/onigmo.h ossl_x509req.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509req.o: $(hdrdir)/ruby/ractor.h ossl_x509req.o: $(hdrdir)/ruby/ruby.h ossl_x509req.o: $(hdrdir)/ruby/st.h ossl_x509req.o: $(hdrdir)/ruby/subst.h ossl_x509req.o: $(hdrdir)/ruby/thread.h -ossl_x509req.o: $(top_srcdir)/include/ruby.h ossl_x509req.o: openssl_missing.h ossl_x509req.o: ossl.h ossl_x509req.o: ossl_asn1.h @@ -1006,31 +6098,193 @@ ossl_x509req.o: ossl_config.h ossl_x509req.o: ossl_digest.h ossl_x509req.o: ossl_engine.h ossl_x509req.o: ossl_hmac.h +ossl_x509req.o: ossl_kdf.h ossl_x509req.o: ossl_ns_spki.h ossl_x509req.o: ossl_ocsp.h ossl_x509req.o: ossl_pkcs12.h -ossl_x509req.o: ossl_pkcs5.h ossl_x509req.o: ossl_pkcs7.h ossl_x509req.o: ossl_pkey.h +ossl_x509req.o: ossl_provider.h ossl_x509req.o: ossl_rand.h ossl_x509req.o: ossl_ssl.h -ossl_x509req.o: ossl_version.h +ossl_x509req.o: ossl_ts.h ossl_x509req.o: ossl_x509.h ossl_x509req.o: ossl_x509req.c -ossl_x509req.o: ruby_missing.h ossl_x509revoked.o: $(RUBY_EXTCONF_H) ossl_x509revoked.o: $(arch_hdrdir)/ruby/config.h +ossl_x509revoked.o: $(hdrdir)/ruby.h +ossl_x509revoked.o: $(hdrdir)/ruby/assert.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509revoked.o: $(hdrdir)/ruby/defines.h ossl_x509revoked.o: $(hdrdir)/ruby/encoding.h ossl_x509revoked.o: $(hdrdir)/ruby/intern.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/abi.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/config.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/error.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/event.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/method.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/module.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/symbol.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/value.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509revoked.o: $(hdrdir)/ruby/io.h ossl_x509revoked.o: $(hdrdir)/ruby/missing.h +ossl_x509revoked.o: $(hdrdir)/ruby/onigmo.h ossl_x509revoked.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509revoked.o: $(hdrdir)/ruby/ractor.h ossl_x509revoked.o: $(hdrdir)/ruby/ruby.h ossl_x509revoked.o: $(hdrdir)/ruby/st.h ossl_x509revoked.o: $(hdrdir)/ruby/subst.h ossl_x509revoked.o: $(hdrdir)/ruby/thread.h -ossl_x509revoked.o: $(top_srcdir)/include/ruby.h ossl_x509revoked.o: openssl_missing.h ossl_x509revoked.o: ossl.h ossl_x509revoked.o: ossl_asn1.h @@ -1041,31 +6295,193 @@ ossl_x509revoked.o: ossl_config.h ossl_x509revoked.o: ossl_digest.h ossl_x509revoked.o: ossl_engine.h ossl_x509revoked.o: ossl_hmac.h +ossl_x509revoked.o: ossl_kdf.h ossl_x509revoked.o: ossl_ns_spki.h ossl_x509revoked.o: ossl_ocsp.h ossl_x509revoked.o: ossl_pkcs12.h -ossl_x509revoked.o: ossl_pkcs5.h ossl_x509revoked.o: ossl_pkcs7.h ossl_x509revoked.o: ossl_pkey.h +ossl_x509revoked.o: ossl_provider.h ossl_x509revoked.o: ossl_rand.h ossl_x509revoked.o: ossl_ssl.h -ossl_x509revoked.o: ossl_version.h +ossl_x509revoked.o: ossl_ts.h ossl_x509revoked.o: ossl_x509.h ossl_x509revoked.o: ossl_x509revoked.c -ossl_x509revoked.o: ruby_missing.h ossl_x509store.o: $(RUBY_EXTCONF_H) ossl_x509store.o: $(arch_hdrdir)/ruby/config.h +ossl_x509store.o: $(hdrdir)/ruby.h +ossl_x509store.o: $(hdrdir)/ruby/assert.h +ossl_x509store.o: $(hdrdir)/ruby/backward.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509store.o: $(hdrdir)/ruby/defines.h ossl_x509store.o: $(hdrdir)/ruby/encoding.h ossl_x509store.o: $(hdrdir)/ruby/intern.h +ossl_x509store.o: $(hdrdir)/ruby/internal/abi.h +ossl_x509store.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509store.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509store.o: $(hdrdir)/ruby/internal/config.h +ossl_x509store.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509store.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509store.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509store.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509store.o: $(hdrdir)/ruby/internal/error.h +ossl_x509store.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509store.o: $(hdrdir)/ruby/internal/event.h +ossl_x509store.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509store.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509store.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509store.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/rational.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/re.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/ruby.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/select.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/set.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/signal.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509store.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509store.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509store.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509store.o: $(hdrdir)/ruby/internal/method.h +ossl_x509store.o: $(hdrdir)/ruby/internal/module.h +ossl_x509store.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509store.o: $(hdrdir)/ruby/internal/scan_args.h +ossl_x509store.o: $(hdrdir)/ruby/internal/special_consts.h +ossl_x509store.o: $(hdrdir)/ruby/internal/static_assert.h +ossl_x509store.o: $(hdrdir)/ruby/internal/stdalign.h +ossl_x509store.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509store.o: $(hdrdir)/ruby/internal/stdckdint.h +ossl_x509store.o: $(hdrdir)/ruby/internal/symbol.h +ossl_x509store.o: $(hdrdir)/ruby/internal/value.h +ossl_x509store.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509store.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509store.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509store.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509store.o: $(hdrdir)/ruby/io.h ossl_x509store.o: $(hdrdir)/ruby/missing.h +ossl_x509store.o: $(hdrdir)/ruby/onigmo.h ossl_x509store.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509store.o: $(hdrdir)/ruby/ractor.h ossl_x509store.o: $(hdrdir)/ruby/ruby.h ossl_x509store.o: $(hdrdir)/ruby/st.h ossl_x509store.o: $(hdrdir)/ruby/subst.h ossl_x509store.o: $(hdrdir)/ruby/thread.h -ossl_x509store.o: $(top_srcdir)/include/ruby.h ossl_x509store.o: openssl_missing.h ossl_x509store.o: ossl.h ossl_x509store.o: ossl_asn1.h @@ -1076,16 +6492,16 @@ ossl_x509store.o: ossl_config.h ossl_x509store.o: ossl_digest.h ossl_x509store.o: ossl_engine.h ossl_x509store.o: ossl_hmac.h +ossl_x509store.o: ossl_kdf.h ossl_x509store.o: ossl_ns_spki.h ossl_x509store.o: ossl_ocsp.h ossl_x509store.o: ossl_pkcs12.h -ossl_x509store.o: ossl_pkcs5.h ossl_x509store.o: ossl_pkcs7.h ossl_x509store.o: ossl_pkey.h +ossl_x509store.o: ossl_provider.h ossl_x509store.o: ossl_rand.h ossl_x509store.o: ossl_ssl.h -ossl_x509store.o: ossl_version.h +ossl_x509store.o: ossl_ts.h ossl_x509store.o: ossl_x509.h ossl_x509store.o: ossl_x509store.c -ossl_x509store.o: ruby_missing.h # AUTOGENERATED DEPENDENCIES END diff --git a/ext/openssl/deprecation.rb b/ext/openssl/deprecation.rb deleted file mode 100644 index 39ebfa0d37..0000000000 --- a/ext/openssl/deprecation.rb +++ /dev/null @@ -1,21 +0,0 @@ -module OpenSSL - def self.deprecated_warning_flag - unless flag = (@deprecated_warning_flag ||= nil) - if try_compile("", flag = "-Werror=deprecated-declarations") - if with_config("broken-apple-openssl") - flag = "-Wno-deprecated-declarations" - end - $warnflags << " #{flag}" - else - flag = "" - end - @deprecated_warning_flag = flag - end - flag - end - - def self.check_func(func, header) - have_func(func, header, deprecated_warning_flag) and - have_header(header, nil, deprecated_warning_flag) - end -end diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index e272cba092..a897c86b65 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -1,160 +1,182 @@ # -*- coding: us-ascii -*- +# frozen_string_literal: true =begin -= $RCSfile$ -- Generator for Makefile - = Info 'OpenSSL for Ruby 2' project Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz> All rights reserved. = Licence - This program is licenced under the same licence as Ruby. - (See the file 'LICENCE'.) - -= Version - $Id$ + This program is licensed under the same licence as Ruby. + (See the file 'COPYING'.) =end require "mkmf" -require File.expand_path('../deprecation', __FILE__) -dir_config("openssl") -dir_config("kerberos") +ssl_dirs = dir_config("openssl") +dir_config_given = ssl_dirs.any? -Logging::message "=== OpenSSL for Ruby configurator ===\n" +_, ssl_ldir = ssl_dirs +if ssl_ldir&.split(File::PATH_SEPARATOR)&.none? { |dir| File.directory?(dir) } + # According to the `mkmf.rb#dir_config`, the `--with-openssl-dir=<dir>` uses + # the value of the `File.basename(RbConfig::MAKEFILE_CONFIG["libdir"])` as a + # loaded library directory name. + ruby_ldir_name = File.basename(RbConfig::MAKEFILE_CONFIG["libdir"]) -## -# Adds -DOSSL_DEBUG for compilation and some more targets when GCC is used -# To turn it on, use: --with-debug or --enable-debug -# -if with_config("debug") or enable_config("debug") - $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG" + raise "OpenSSL library directory could not be found in '#{ssl_ldir}'. " \ + "You might want to fix this error in one of the following ways.\n" \ + " * Recompile OpenSSL by configuring it with --libdir=#{ruby_ldir_name} " \ + " to specify the OpenSSL library directory.\n" \ + " * Recompile Ruby by configuring it with --libdir=<dir> to specify the " \ + "Ruby library directory.\n" \ + " * Compile this openssl gem with --with-openssl-include=<dir> and " \ + "--with-openssl-lib=<dir> options to specify the OpenSSL include and " \ + "library directories." end +Logging::message "=== OpenSSL for Ruby configurator ===\n" + +$defs.push("-D""OPENSSL_SUPPRESS_DEPRECATED") + +# Missing in TruffleRuby +have_func("rb_call_super_kw(0, NULL, 0)", "ruby.h") +# Ruby 3.1 +have_func("rb_io_descriptor", "ruby/io.h") +have_func("rb_io_maybe_wait(0, Qnil, Qnil, Qnil)", "ruby/io.h") +# Ruby 3.2 +have_func("rb_io_timeout", "ruby/io.h") + Logging::message "=== Checking for system dependent stuff... ===\n" have_library("nsl", "t_open") have_library("socket", "socket") -have_header("assert.h") +if $mswin || $mingw + have_library("ws2_32") +end -Logging::message "=== Checking for required stuff... ===\n" if $mingw - have_library("wsock32") - have_library("gdi32") + append_cflags '-D_FORTIFY_SOURCE=2' + append_ldflags '-fstack-protector' + have_library 'ssp' end -result = pkg_config("openssl") && have_header("openssl/ssl.h") +def find_openssl_library + if $mswin || $mingw + # required for static OpenSSL libraries + have_library("crypt32") + end + + return false unless have_header("openssl/ssl.h") + + ret = have_library("crypto", "CRYPTO_malloc") && + have_library("ssl", "SSL_new") + return ret if ret -unless result - result = have_header("openssl/ssl.h") - result &&= %w[crypto libeay32].any? {|lib| have_library(lib, "OpenSSL_add_all_digests")} - result &&= %w[ssl ssleay32].any? {|lib| have_library(lib, "SSL_library_init")} - unless result - Logging::message "=== Checking for required stuff failed. ===\n" - Logging::message "Makefile wasn't created. Fix the errors above.\n" - exit 1 + if $mswin + # OpenSSL >= 1.1.0: libcrypto.lib and libssl.lib. + if have_library("libcrypto", "CRYPTO_malloc") && + have_library("libssl", "SSL_new") + return true + end + + # LibreSSL: libcrypto-##.lib and libssl-##.lib, where ## is the ABI version + # number. We have to find the version number out by scanning libpath. + libpath = $LIBPATH.dup + libpath |= ENV["LIB"].split(File::PATH_SEPARATOR) + libpath.map! { |d| d.tr(File::ALT_SEPARATOR, File::SEPARATOR) } + + ret = [ + ["crypto", "CRYPTO_malloc"], + ["ssl", "SSL_new"] + ].all? do |base, func| + result = false + libs = ["lib#{base}-[0-9][0-9]", "lib#{base}-[0-9][0-9][0-9]"] + libs = Dir.glob(libs.map{|l| libpath.map{|d| File.join(d, l + ".*")}}.flatten).map{|path| File.basename(path, ".*")}.uniq + libs.each do |lib| + result = have_library(lib, func) + break if result + end + result + end + return ret if ret end + return false end -unless have_header("openssl/conf_api.h") - raise "OpenSSL 0.9.6 or later required." -end -unless OpenSSL.check_func("SSL_library_init()", "openssl/ssl.h") - raise "Ignore OpenSSL broken by Apple.\nPlease use another openssl. (e.g. using `configure --with-openssl-dir=/path/to/openssl')" +Logging::message "=== Checking for required stuff... ===\n" +pkg_config_found = !dir_config_given && pkg_config("openssl") && have_header("openssl/ssl.h") + +if !pkg_config_found && !find_openssl_library + Logging::message "=== Checking for required stuff failed. ===\n" + Logging::message "Makefile wasn't created. Fix the errors above.\n" + raise "OpenSSL library could not be found. You might want to use " \ + "--with-openssl-dir=<dir> option to specify the prefix where OpenSSL " \ + "is installed." end -Logging::message "=== Checking for OpenSSL features... ===\n" -have_func("ERR_peek_last_error") -have_func("ASN1_put_eoc") -have_func("BN_mod_add") -have_func("BN_mod_sqr") -have_func("BN_mod_sub") -have_func("BN_pseudo_rand_range") -have_func("BN_rand_range") -have_func("CONF_get1_default_config_file") -have_func("EVP_CIPHER_CTX_copy") -have_func("EVP_CIPHER_CTX_set_padding") -have_func("EVP_CipherFinal_ex") -have_func("EVP_CipherInit_ex") -have_func("EVP_DigestFinal_ex") -have_func("EVP_DigestInit_ex") -have_func("EVP_MD_CTX_cleanup") -have_func("EVP_MD_CTX_create") -have_func("EVP_MD_CTX_destroy") -have_func("EVP_MD_CTX_init") -have_func("HMAC_CTX_cleanup") -have_func("HMAC_CTX_copy") -have_func("HMAC_CTX_init") -have_func("PEM_def_callback") -have_func("PKCS5_PBKDF2_HMAC") -have_func("PKCS5_PBKDF2_HMAC_SHA1") -have_func("X509V3_set_nconf") -have_func("X509V3_EXT_nconf_nid") -have_func("X509_CRL_add0_revoked") -have_func("X509_CRL_set_issuer_name") -have_func("X509_CRL_set_version") -have_func("X509_CRL_sort") -have_func("X509_NAME_hash_old") -have_func("X509_STORE_get_ex_data") -have_func("X509_STORE_set_ex_data") -have_func("OBJ_NAME_do_all_sorted") -have_func("SSL_SESSION_get_id") -have_func("SSL_SESSION_cmp") -have_func("OPENSSL_cleanse") -have_func("SSLv2_method") -have_func("SSLv2_server_method") -have_func("SSLv2_client_method") -have_func("TLSv1_1_method") -have_func("TLSv1_1_server_method") -have_func("TLSv1_1_client_method") -have_func("TLSv1_2_method") -have_func("TLSv1_2_server_method") -have_func("TLSv1_2_client_method") -have_macro("OPENSSL_NPN_NEGOTIATED", ['openssl/ssl.h']) && $defs.push("-DHAVE_OPENSSL_NPN_NEGOTIATED") -unless have_func("SSL_set_tlsext_host_name", ['openssl/ssl.h']) - have_macro("SSL_set_tlsext_host_name", ['openssl/ssl.h']) && $defs.push("-DHAVE_SSL_SET_TLSEXT_HOST_NAME") +version_ok = if have_macro("LIBRESSL_VERSION_NUMBER", "openssl/opensslv.h") + is_libressl = true + checking_for("LibreSSL version >= 3.9.0") { + try_static_assert("LIBRESSL_VERSION_NUMBER >= 0x30900000L", "openssl/opensslv.h") } +else + is_openssl = true + checking_for("OpenSSL version >= 1.1.1") { + try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10101000L", "openssl/opensslv.h") } end -if have_header("openssl/engine.h") - have_func("ENGINE_add") - have_func("ENGINE_load_builtin_engines") - have_func("ENGINE_load_openbsd_dev_crypto") - have_func("ENGINE_get_digest") - have_func("ENGINE_get_cipher") - have_func("ENGINE_cleanup") - have_func("ENGINE_load_dynamic") - have_func("ENGINE_load_4758cca") - have_func("ENGINE_load_aep") - have_func("ENGINE_load_atalla") - have_func("ENGINE_load_chil") - have_func("ENGINE_load_cswift") - have_func("ENGINE_load_nuron") - have_func("ENGINE_load_sureware") - have_func("ENGINE_load_ubsec") - have_func("ENGINE_load_padlock") - have_func("ENGINE_load_capi") - have_func("ENGINE_load_gmp") - have_func("ENGINE_load_gost") - have_func("ENGINE_load_cryptodev") - have_func("ENGINE_load_aesni") +unless version_ok + raise "OpenSSL >= 1.1.1 or LibreSSL >= 3.9.0 is required" end -have_func("DH_generate_parameters_ex") -have_func("DSA_generate_parameters_ex") -have_func("RSA_generate_key_ex") -if checking_for('OpenSSL version is 0.9.7 or later') { - try_static_assert('OPENSSL_VERSION_NUMBER >= 0x00907000L', 'openssl/opensslv.h') - } - have_header("openssl/ocsp.h") + +# Prevent wincrypt.h from being included, which defines conflicting macro with openssl/x509.h +if is_libressl && ($mswin || $mingw) + $defs.push("-DNOCRYPT") end -have_struct_member("CRYPTO_THREADID", "ptr", "openssl/crypto.h") -have_struct_member("EVP_CIPHER_CTX", "flags", "openssl/evp.h") -have_struct_member("EVP_CIPHER_CTX", "engine", "openssl/evp.h") -have_struct_member("X509_ATTRIBUTE", "single", "openssl/x509.h") -have_macro("OPENSSL_FIPS", ['openssl/opensslconf.h']) && $defs.push("-DHAVE_OPENSSL_FIPS") -have_macro("EVP_CTRL_GCM_GET_TAG", ['openssl/evp.h']) && $defs.push("-DHAVE_AUTHENTICATED_ENCRYPTION") + +Logging::message "=== Checking for OpenSSL features... ===\n" +evp_h = "openssl/evp.h".freeze +ts_h = "openssl/ts.h".freeze +ssl_h = "openssl/ssl.h".freeze + +# compile options +have_func("RAND_egd()", "openssl/rand.h") + +# added in OpenSSL 1.0.2, not in LibreSSL yet +have_func("SSL_CTX_set1_sigalgs_list(NULL, NULL)", ssl_h) +# added in OpenSSL 1.0.2, not in LibreSSL or AWS-LC yet +have_func("SSL_CTX_set1_client_sigalgs_list(NULL, NULL)", ssl_h) + +# added in 1.1.0, currently not in LibreSSL +have_func("EVP_PBE_scrypt(\"\", 0, (unsigned char *)\"\", 0, 0, 0, 0, 0, NULL, 0)", evp_h) + +# added in OpenSSL 1.1.1 and LibreSSL 3.5.0, then removed in LibreSSL 4.0.0 +have_func("EVP_PKEY_check(NULL)", evp_h) + +# added in 3.0.0 +have_func("SSL_CTX_set0_tmp_dh_pkey(NULL, NULL)", ssl_h) +have_func("ERR_get_error_all(NULL, NULL, NULL, NULL, NULL)", "openssl/err.h") +have_func("SSL_CTX_load_verify_file(NULL, \"\")", ssl_h) +have_func("BN_check_prime(NULL, NULL, NULL)", "openssl/bn.h") +have_func("EVP_MD_CTX_get0_md(NULL)", evp_h) +have_func("EVP_MD_CTX_get_pkey_ctx(NULL)", evp_h) +have_func("EVP_PKEY_eq(NULL, NULL)", evp_h) +have_func("EVP_PKEY_dup(NULL)", evp_h) + +# added in 3.2.0 +have_func("SSL_get0_group_name(NULL)", ssl_h) + +# added in 3.4.0 +have_func("TS_VERIFY_CTX_set0_certs(NULL, NULL)", ts_h) + +# added in 3.5.0 +have_func("SSL_get0_peer_signature_name(NULL, NULL)", ssl_h) Logging::message "=== Checking done. ===\n" +# Append flags from environment variables. +extcflags = ENV["RUBY_OPENSSL_EXTCFLAGS"] +append_cflags(extcflags.split) if extcflags +extldflags = ENV["RUBY_OPENSSL_EXTLDFLAGS"] +append_ldflags(extldflags.split) if extldflags + create_header -create_makefile("openssl") {|conf| - conf << "THREAD_MODEL = #{CONFIG["THREAD_MODEL"]}\n" -} +create_makefile("openssl") Logging::message "Done.\n" diff --git a/ext/openssl/lib/openssl.rb b/ext/openssl/lib/openssl.rb index 19a4382d0d..98fa8d39f2 100644 --- a/ext/openssl/lib/openssl.rb +++ b/ext/openssl/lib/openssl.rb @@ -1,24 +1,41 @@ +# frozen_string_literal: true =begin -= $RCSfile$ -- Loader for all OpenSSL C-space and Ruby-space definitions - = Info 'OpenSSL for Ruby 2' project Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz> All rights reserved. = Licence - This program is licenced under the same licence as Ruby. - (See the file 'LICENCE'.) - -= Version - $Id$ + This program is licensed under the same licence as Ruby. + (See the file 'COPYING'.) =end require 'openssl.so' -require 'openssl/bn' -require 'openssl/cipher' -require 'openssl/config' -require 'openssl/digest' -require 'openssl/x509' -require 'openssl/ssl' +require_relative 'openssl/bn' +require_relative 'openssl/cipher' +require_relative 'openssl/digest' +require_relative 'openssl/hmac' +require_relative 'openssl/pkcs5' +require_relative 'openssl/pkey' +require_relative 'openssl/ssl' +require_relative 'openssl/version' +require_relative 'openssl/x509' + +module OpenSSL + # :call-seq: + # OpenSSL.secure_compare(string, string) -> true or false + # + # Constant time memory comparison. Inputs are hashed using SHA-256 to mask + # the length of the secret. Returns +true+ if the strings are identical, + # +false+ otherwise. + # + # This method is expensive due to the SHA-256 hashing. In most cases, where + # the input lengths are known to be equal or are not sensitive, + # OpenSSL.fixed_length_secure_compare should be used instead. + def self.secure_compare(a, b) + hashed_a = OpenSSL::Digest.digest('SHA256', a) + hashed_b = OpenSSL::Digest.digest('SHA256', b) + OpenSSL.fixed_length_secure_compare(hashed_a, hashed_b) && a == b + end +end diff --git a/ext/openssl/lib/openssl/bn.rb b/ext/openssl/lib/openssl/bn.rb index 95babb4cbd..e4889a140c 100644 --- a/ext/openssl/lib/openssl/bn.rb +++ b/ext/openssl/lib/openssl/bn.rb @@ -1,7 +1,6 @@ +# frozen_string_literal: true #-- # -# $RCSfile$ -# # = Ruby-space definitions that completes C-space funcs for BN # # = Info @@ -10,12 +9,8 @@ # All rights reserved. # # = Licence -# This program is licenced under the same licence as Ruby. -# (See the file 'LICENCE'.) -# -# = Version -# $Id$ -# +# This program is licensed under the same licence as Ruby. +# (See the file 'COPYING'.) #++ module OpenSSL @@ -32,8 +27,9 @@ module OpenSSL end # OpenSSL ## +#-- # Add double dispatch to Integer -# +#++ class Integer # Casts an Integer as an OpenSSL::BN # @@ -42,4 +38,3 @@ class Integer OpenSSL::BN::new(self) end end # Integer - diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb index 1223c5de15..1464a4292d 100644 --- a/ext/openssl/lib/openssl/buffering.rb +++ b/ext/openssl/lib/openssl/buffering.rb @@ -1,18 +1,14 @@ # coding: binary +# frozen_string_literal: true #-- -#= $RCSfile$ -- Buffering mix-in module. -# #= Info # 'OpenSSL for Ruby 2' project # Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org> # All rights reserved. # #= Licence -# This program is licenced under the same licence as Ruby. -# (See the file 'LICENCE'.) -# -#= Version -# $Id$ +# This program is licensed under the same licence as Ruby. +# (See the file 'COPYING'.) #++ ## @@ -26,6 +22,25 @@ module OpenSSL::Buffering include Enumerable + # A buffer which will retain binary encoding. + class Buffer < String + unless String.method_defined?(:append_as_bytes) + alias_method :_append, :<< + def append_as_bytes(string) + if string.encoding == Encoding::BINARY + _append(string) + else + _append(string.b) + end + + self + end + end + + undef_method :concat + undef_method :<< + end + ## # The "sync mode" of the SSLSocket. # @@ -44,7 +59,7 @@ module OpenSSL::Buffering def initialize(*) super @eof = false - @rbuffer = "" + @rbuffer = Buffer.new @sync = @io.sync end @@ -58,7 +73,7 @@ module OpenSSL::Buffering def fill_rbuff begin - @rbuffer << self.sysread(BLOCK_SIZE) + @rbuffer.append_as_bytes(self.sysread(BLOCK_SIZE)) rescue Errno::EAGAIN retry rescue EOFError @@ -67,23 +82,35 @@ module OpenSSL::Buffering end ## - # Consumes +size+ bytes from the buffer + # Consumes _size_ bytes from the buffer def consume_rbuff(size=nil) if @rbuffer.empty? nil else size = @rbuffer.size unless size - ret = @rbuffer[0, size] - @rbuffer[0, size] = "" - ret + @rbuffer.slice!(0, size) end end public + # call-seq: + # ssl.getbyte => 81 + # + # Get the next 8bit byte from `ssl`. Returns `nil` on EOF + def getbyte + read(1)&.ord + end + + # Get the next 8bit byte. Raises EOFError on EOF + def readbyte + raise EOFError if eof? + getbyte + end + ## - # Reads +size+ bytes from the stream. If +buf+ is provided it must + # Reads _size_ bytes from the stream. If _buf_ is provided it must # reference a string which will receive the data. # # See IO#read for full details. @@ -110,7 +137,7 @@ module OpenSSL::Buffering end ## - # Reads at most +maxlen+ bytes from the stream. If +buf+ is provided it + # Reads at most _maxlen_ bytes from the stream. If _buf_ is provided it # must reference a string which will receive the data. # # See IO#readpartial for full details. @@ -136,12 +163,11 @@ module OpenSSL::Buffering buf.replace(ret) ret = buf end - raise EOFError if ret.empty? ret end ## - # Reads at most +maxlen+ bytes in the non-blocking manner. + # Reads at most _maxlen_ bytes in the non-blocking manner. # # When no data can be read without blocking it raises # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable. @@ -168,6 +194,11 @@ module OpenSSL::Buffering # Note that one reason that read_nonblock writes to the underlying IO is # when the peer requests a new TLS/SSL handshake. See openssl the FAQ for # more details. http://www.openssl.org/support/faq.html + # + # By specifying a keyword argument _exception_ to +false+, you can indicate + # that read_nonblock should not raise an IO::Wait*able exception, but + # return the symbol +:wait_writable+ or +:wait_readable+ instead. At EOF, + # it will return +nil+ instead of raising EOFError. def read_nonblock(maxlen, buf=nil, exception: true) if maxlen == 0 @@ -186,22 +217,21 @@ module OpenSSL::Buffering buf.replace(ret) ret = buf end - raise EOFError if ret.empty? ret end ## - # Reads the next "line+ from the stream. Lines are separated by +eol+. If - # +limit+ is provided the result will not be longer than the given number of + # Reads the next "line" from the stream. Lines are separated by _eol_. If + # _limit_ is provided the result will not be longer than the given number of # bytes. # - # +eol+ may be a String or Regexp. + # _eol_ may be a String or Regexp. # # Unlike IO#gets the line read will not be assigned to +$_+. # # Unlike IO#gets the separator must be provided if a limit is provided. - def gets(eol=$/, limit=nil) + def gets(eol=$/, limit=nil, chomp: false) idx = @rbuffer.index(eol) until @eof break if idx @@ -213,15 +243,19 @@ module OpenSSL::Buffering else size = idx ? idx+eol.size : nil end - if limit and limit >= 0 + if size && limit && limit >= 0 size = [size, limit].min end - consume_rbuff(size) + line = consume_rbuff(size) + if chomp && line + line.chomp!(eol) + end + line end ## # Executes the block for every line in the stream where lines are separated - # by +eol+. + # by _eol_. # # See also #gets @@ -233,7 +267,7 @@ module OpenSSL::Buffering alias each_line each ## - # Reads lines from the stream which are separated by +eol+. + # Reads lines from the stream which are separated by _eol_. # # See also #gets @@ -246,7 +280,7 @@ module OpenSSL::Buffering end ## - # Reads a line from the stream which is separated by +eol+. + # Reads a line from the stream which is separated by _eol_. # # Raises EOFError if at end of file. @@ -282,7 +316,7 @@ module OpenSSL::Buffering end ## - # Pushes character +c+ back onto the stream such that a subsequent buffered + # Pushes character _c_ back onto the stream such that a subsequent buffered # character read will return it. # # Unlike IO#getc multiple bytes may be pushed back onto the stream. @@ -309,44 +343,56 @@ module OpenSSL::Buffering private ## - # Writes +s+ to the buffer. When the buffer is full or #sync is true the + # Writes _s_ to the buffer. When the buffer is full or #sync is true the # buffer is flushed to the underlying socket. def do_write(s) - @wbuffer = "" unless defined? @wbuffer - @wbuffer << s - @wbuffer.force_encoding(Encoding::BINARY) + @wbuffer = Buffer.new unless defined? @wbuffer + @wbuffer.append_as_bytes(s) + @sync ||= false - if @sync or @wbuffer.size > BLOCK_SIZE or idx = @wbuffer.rindex($/) - remain = idx ? idx + $/.size : @wbuffer.length - nwritten = 0 - while remain > 0 - str = @wbuffer[nwritten,remain] - begin - nwrote = syswrite(str) - rescue Errno::EAGAIN - retry + buffer_size = @wbuffer.bytesize + if @sync or buffer_size > BLOCK_SIZE + nwrote = 0 + begin + while nwrote < buffer_size do + begin + chunk = if nwrote > 0 + @wbuffer.byteslice(nwrote, @wbuffer.bytesize) + else + @wbuffer + end + + nwrote += syswrite(chunk) + rescue Errno::EAGAIN + retry + end + end + ensure + if nwrote < @wbuffer.bytesize + @wbuffer[0, nwrote] = "" + else + @wbuffer.clear end - remain -= nwrote - nwritten += nwrote end - @wbuffer[0,nwritten] = "" end end public ## - # Writes +s+ to the stream. If the argument is not a string it will be - # converted using String#to_s. Returns the number of bytes written. + # Writes _s_ to the stream. If the argument is not a String it will be + # converted using +.to_s+ method. Returns the number of bytes written. - def write(s) - do_write(s) - s.bytesize + def write(*s) + s.inject(0) do |written, str| + do_write(str) + written + str.bytesize + end end ## - # Writes +str+ in the non-blocking manner. + # Writes _s_ in the non-blocking manner. # # If there is buffered data, it is flushed first. This may block. # @@ -377,6 +423,10 @@ module OpenSSL::Buffering # Note that one reason that write_nonblock reads from the underlying IO # is when the peer requests a new TLS/SSL handshake. See the openssl FAQ # for more details. http://www.openssl.org/support/faq.html + # + # By specifying a keyword argument _exception_ to +false+, you can indicate + # that write_nonblock should not raise an IO::Wait*able exception, but + # return the symbol +:wait_writable+ or +:wait_readable+ instead. def write_nonblock(s, exception: true) flush @@ -384,42 +434,40 @@ module OpenSSL::Buffering end ## - # Writes +s+ to the stream. +s+ will be converted to a String using - # String#to_s. + # Writes _s_ to the stream. _s_ will be converted to a String using + # +.to_s+ method. - def << (s) + def <<(s) do_write(s) self end ## - # Writes +args+ to the stream along with a record separator. + # Writes _args_ to the stream along with a record separator. # # See IO#puts for full details. def puts(*args) - s = "" + s = Buffer.new if args.empty? - s << "\n" + s.append_as_bytes("\n") end args.each{|arg| - s << arg.to_s - if $/ && /\n\z/ !~ s - s << "\n" - end + s.append_as_bytes(arg.to_s) + s.sub!(/(?<!\n)\z/, "\n") } do_write(s) nil end ## - # Writes +args+ to the stream. + # Writes _args_ to the stream. # # See IO#print for full details. def print(*args) - s = "" - args.each{ |arg| s << arg.to_s } + s = Buffer.new + args.each{ |arg| s.append_as_bytes(arg.to_s) } do_write(s) nil end diff --git a/ext/openssl/lib/openssl/cipher.rb b/ext/openssl/lib/openssl/cipher.rb index b3340ff52a..ab75ac8e1a 100644 --- a/ext/openssl/lib/openssl/cipher.rb +++ b/ext/openssl/lib/openssl/cipher.rb @@ -1,7 +1,5 @@ +# frozen_string_literal: true #-- -# -# $RCSfile$ -# # = Ruby-space predefined Cipher subclasses # # = Info @@ -10,12 +8,8 @@ # All rights reserved. # # = Licence -# This program is licenced under the same licence as Ruby. -# (See the file 'LICENCE'.) -# -# = Version -# $Id$ -# +# This program is licensed under the same licence as Ruby. +# (See the file 'COPYING'.) #++ module OpenSSL @@ -24,7 +18,7 @@ module OpenSSL klass = Class.new(Cipher){ define_method(:initialize){|*args| cipher_name = args.inject(name){|n, arg| "#{n}-#{arg}" } - super(cipher_name) + super(cipher_name.downcase) } } const_set(name, klass) @@ -32,34 +26,42 @@ module OpenSSL %w(128 192 256).each{|keylen| klass = Class.new(Cipher){ - define_method(:initialize){|mode| - mode ||= "CBC" - cipher_name = "AES-#{keylen}-#{mode}" - super(cipher_name) + define_method(:initialize){|mode = "CBC"| + super("aes-#{keylen}-#{mode}".downcase) } } const_set("AES#{keylen}", klass) } - # Generate, set, and return a random key. - # You must call cipher.encrypt or cipher.decrypt before calling this method. + # call-seq: + # cipher.random_key -> key + # + # Generate a random key with OpenSSL::Random.random_bytes and sets it to + # the cipher, and returns it. + # + # You must call #encrypt or #decrypt before calling this method. def random_key str = OpenSSL::Random.random_bytes(self.key_len) self.key = str - return str end - # Generate, set, and return a random iv. - # You must call cipher.encrypt or cipher.decrypt before calling this method. + # call-seq: + # cipher.random_iv -> iv + # + # Generate a random IV with OpenSSL::Random.random_bytes and sets it to the + # cipher, and returns it. + # + # You must call #encrypt or #decrypt before calling this method. def random_iv str = OpenSSL::Random.random_bytes(self.iv_len) self.iv = str - return str end - # This class is only provided for backwards compatibility. Use OpenSSL::Cipher in the future. - class Cipher < Cipher - # add warning - end + # Deprecated. + # + # This class is only provided for backwards compatibility. + # Use OpenSSL::Cipher. + class Cipher < Cipher; end + deprecate_constant :Cipher end # Cipher end # OpenSSL diff --git a/ext/openssl/lib/openssl/config.rb b/ext/openssl/lib/openssl/config.rb deleted file mode 100644 index 5716d59fd6..0000000000 --- a/ext/openssl/lib/openssl/config.rb +++ /dev/null @@ -1,472 +0,0 @@ -=begin -= Ruby-space definitions that completes C-space funcs for Config - -= Info - Copyright (C) 2010 Hiroshi Nakamura <nahi@ruby-lang.org> - -= Licence - This program is licenced under the same licence as Ruby. - (See the file 'LICENCE'.) - -=end - -require 'stringio' - -module OpenSSL - ## - # = OpenSSL::Config - # - # Configuration for the openssl library. - # - # Many system's installation of openssl library will depend on your system - # configuration. See the value of OpenSSL::Config::DEFAULT_CONFIG_FILE for - # the location of the file for your host. - # - # See also http://www.openssl.org/docs/apps/config.html - class Config - include Enumerable - - class << self - - ## - # Parses a given +string+ as a blob that contains configuration for openssl. - # - # If the source of the IO is a file, then consider using #parse_config. - def parse(string) - c = new() - parse_config(StringIO.new(string)).each do |section, hash| - c[section] = hash - end - c - end - - ## - # load is an alias to ::new - alias load new - - ## - # Parses the configuration data read from +io+, see also #parse. - # - # Raises a ConfigError on invalid configuration data. - def parse_config(io) - begin - parse_config_lines(io) - rescue ConfigError => e - e.message.replace("error in line #{io.lineno}: " + e.message) - raise - end - end - - def get_key_string(data, section, key) # :nodoc: - if v = data[section] && data[section][key] - return v - elsif section == 'ENV' - if v = ENV[key] - return v - end - end - if v = data['default'] && data['default'][key] - return v - end - end - - private - - def parse_config_lines(io) - section = 'default' - data = {section => {}} - while definition = get_definition(io) - definition = clear_comments(definition) - next if definition.empty? - if definition[0] == ?[ - if /\[([^\]]*)\]/ =~ definition - section = $1.strip - data[section] ||= {} - else - raise ConfigError, "missing close square bracket" - end - else - if /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/ =~ definition - if $2 - section = $1 - key = $2 - else - key = $1 - end - value = unescape_value(data, section, $3) - (data[section] ||= {})[key] = value.strip - else - raise ConfigError, "missing equal sign" - end - end - end - data - end - - # escape with backslash - QUOTE_REGEXP_SQ = /\A([^'\\]*(?:\\.[^'\\]*)*)'/ - # escape with backslash and doubled dq - QUOTE_REGEXP_DQ = /\A([^"\\]*(?:""[^"\\]*|\\.[^"\\]*)*)"/ - # escaped char map - ESCAPE_MAP = { - "r" => "\r", - "n" => "\n", - "b" => "\b", - "t" => "\t", - } - - def unescape_value(data, section, value) - scanned = [] - while m = value.match(/['"\\$]/) - scanned << m.pre_match - c = m[0] - value = m.post_match - case c - when "'" - if m = value.match(QUOTE_REGEXP_SQ) - scanned << m[1].gsub(/\\(.)/, '\\1') - value = m.post_match - else - break - end - when '"' - if m = value.match(QUOTE_REGEXP_DQ) - scanned << m[1].gsub(/""/, '').gsub(/\\(.)/, '\\1') - value = m.post_match - else - break - end - when "\\" - c = value.slice!(0, 1) - scanned << (ESCAPE_MAP[c] || c) - when "$" - ref, value = extract_reference(value) - refsec = section - if ref.index('::') - refsec, ref = ref.split('::', 2) - end - if v = get_key_string(data, refsec, ref) - scanned << v - else - raise ConfigError, "variable has no value" - end - else - raise 'must not reaced' - end - end - scanned << value - scanned.join - end - - def extract_reference(value) - rest = '' - if m = value.match(/\(([^)]*)\)|\{([^}]*)\}/) - value = m[1] || m[2] - rest = m.post_match - elsif [?(, ?{].include?(value[0]) - raise ConfigError, "no close brace" - end - if m = value.match(/[a-zA-Z0-9_]*(?:::[a-zA-Z0-9_]*)?/) - return m[0], m.post_match + rest - else - raise - end - end - - def clear_comments(line) - # FCOMMENT - if m = line.match(/\A([\t\n\f ]*);.*\z/) - return m[1] - end - # COMMENT - scanned = [] - while m = line.match(/[#'"\\]/) - scanned << m.pre_match - c = m[0] - line = m.post_match - case c - when '#' - line = nil - break - when "'", '"' - regexp = (c == "'") ? QUOTE_REGEXP_SQ : QUOTE_REGEXP_DQ - scanned << c - if m = line.match(regexp) - scanned << m[0] - line = m.post_match - else - scanned << line - line = nil - break - end - when "\\" - scanned << c - scanned << line.slice!(0, 1) - else - raise 'must not reaced' - end - end - scanned << line - scanned.join - end - - def get_definition(io) - if line = get_line(io) - while /[^\\]\\\z/ =~ line - if extra = get_line(io) - line += extra - else - break - end - end - return line.strip - end - end - - def get_line(io) - if line = io.gets - line.gsub(/[\r\n]*/, '') - end - end - end - - ## - # Creates an instance of OpenSSL's configuration class. - # - # This can be used in contexts like OpenSSL::X509::ExtensionFactory.config= - # - # If the optional +filename+ parameter is provided, then it is read in and - # parsed via #parse_config. - # - # This can raise IO exceptions based on the access, or availability of the - # file. A ConfigError exception may be raised depending on the validity of - # the data being configured. - # - def initialize(filename = nil) - @data = {} - if filename - File.open(filename.to_s) do |file| - Config.parse_config(file).each do |section, hash| - self[section] = hash - end - end - end - end - - ## - # Gets the value of +key+ from the given +section+ - # - # Given the following configurating file being loaded: - # - # config = OpenSSL::Config.load('foo.cnf') - # #=> #<OpenSSL::Config sections=["default"]> - # puts config.to_s - # #=> [ default ] - # # foo=bar - # - # You can get a specific value from the config if you know the +section+ - # and +key+ like so: - # - # config.get_value('default','foo') - # #=> "bar" - # - def get_value(section, key) - if section.nil? - raise TypeError.new('nil not allowed') - end - section = 'default' if section.empty? - get_key_string(section, key) - end - - ## - # - # *Deprecated* - # - # Use #get_value instead - def value(arg1, arg2 = nil) # :nodoc: - warn('Config#value is deprecated; use Config#get_value') - if arg2.nil? - section, key = 'default', arg1 - else - section, key = arg1, arg2 - end - section ||= 'default' - section = 'default' if section.empty? - get_key_string(section, key) - end - - ## - # Set the target +key+ with a given +value+ under a specific +section+. - # - # Given the following configurating file being loaded: - # - # config = OpenSSL::Config.load('foo.cnf') - # #=> #<OpenSSL::Config sections=["default"]> - # puts config.to_s - # #=> [ default ] - # # foo=bar - # - # You can set the value of +foo+ under the +default+ section to a new - # value: - # - # config.add_value('default', 'foo', 'buzz') - # #=> "buzz" - # puts config.to_s - # #=> [ default ] - # # foo=buzz - # - def add_value(section, key, value) - check_modify - (@data[section] ||= {})[key] = value - end - - ## - # Get a specific +section+ from the current configuration - # - # Given the following configurating file being loaded: - # - # config = OpenSSL::Config.load('foo.cnf') - # #=> #<OpenSSL::Config sections=["default"]> - # puts config.to_s - # #=> [ default ] - # # foo=bar - # - # You can get a hash of the specific section like so: - # - # config['default'] - # #=> {"foo"=>"bar"} - # - def [](section) - @data[section] || {} - end - - ## - # Deprecated - # - # Use #[] instead - def section(name) # :nodoc: - warn('Config#section is deprecated; use Config#[]') - @data[name] || {} - end - - ## - # Sets a specific +section+ name with a Hash +pairs+ - # - # Given the following configuration being created: - # - # config = OpenSSL::Config.new - # #=> #<OpenSSL::Config sections=[]> - # config['default'] = {"foo"=>"bar","baz"=>"buz"} - # #=> {"foo"=>"bar", "baz"=>"buz"} - # puts config.to_s - # #=> [ default ] - # # foo=bar - # # baz=buz - # - # It's important to note that this will essentially merge any of the keys - # in +pairs+ with the existing +section+. For example: - # - # config['default'] - # #=> {"foo"=>"bar", "baz"=>"buz"} - # config['default'] = {"foo" => "changed"} - # #=> {"foo"=>"changed"} - # config['default'] - # #=> {"foo"=>"changed", "baz"=>"buz"} - # - def []=(section, pairs) - check_modify - @data[section] ||= {} - pairs.each do |key, value| - self.add_value(section, key, value) - end - end - - ## - # Get the names of all sections in the current configuration - def sections - @data.keys - end - - ## - # Get the parsable form of the current configuration - # - # Given the following configuration being created: - # - # config = OpenSSL::Config.new - # #=> #<OpenSSL::Config sections=[]> - # config['default'] = {"foo"=>"bar","baz"=>"buz"} - # #=> {"foo"=>"bar", "baz"=>"buz"} - # puts config.to_s - # #=> [ default ] - # # foo=bar - # # baz=buz - # - # You can parse get the serialized configuration using #to_s and then parse - # it later: - # - # serialized_config = config.to_s - # # much later... - # new_config = OpenSSL::Config.parse(serialized_config) - # #=> #<OpenSSL::Config sections=["default"]> - # puts new_config - # #=> [ default ] - # foo=bar - # baz=buz - # - def to_s - ary = [] - @data.keys.sort.each do |section| - ary << "[ #{section} ]\n" - @data[section].keys.each do |key| - ary << "#{key}=#{@data[section][key]}\n" - end - ary << "\n" - end - ary.join - end - - ## - # For a block. - # - # Receive the section and its pairs for the current configuration. - # - # config.each do |section, key, value| - # # ... - # end - # - def each - @data.each do |section, hash| - hash.each do |key, value| - yield [section, key, value] - end - end - end - - ## - # String representation of this configuration object, including the class - # name and its sections. - def inspect - "#<#{self.class.name} sections=#{sections.inspect}>" - end - - protected - - def data # :nodoc: - @data - end - - private - - def initialize_copy(other) - @data = other.data.dup - end - - def check_modify - raise TypeError.new("Insecure: can't modify OpenSSL config") if frozen? - end - - def get_key_string(section, key) - Config.get_key_string(@data, section, key) - end - end -end diff --git a/ext/openssl/lib/openssl/digest.rb b/ext/openssl/lib/openssl/digest.rb index a7b641fd22..46ddfd6021 100644 --- a/ext/openssl/lib/openssl/digest.rb +++ b/ext/openssl/lib/openssl/digest.rb @@ -1,7 +1,5 @@ +# frozen_string_literal: true #-- -# -# $RCSfile$ -# # = Ruby-space predefined Digest subclasses # # = Info @@ -10,72 +8,56 @@ # All rights reserved. # # = Licence -# This program is licenced under the same licence as Ruby. -# (See the file 'LICENCE'.) -# -# = Version -# $Id$ -# +# This program is licensed under the same licence as Ruby. +# (See the file 'COPYING'.) #++ module OpenSSL class Digest - alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1) - if OPENSSL_VERSION_NUMBER > 0x00908000 - alg += %w(SHA224 SHA256 SHA384 SHA512) - end - - # Return the +data+ hash computed with +name+ Digest. +name+ is either the + # Return the hash value computed with _name_ Digest. _name_ is either the # long name or short name of a supported digest algorithm. # - # === Examples + # === Example # # OpenSSL::Digest.digest("SHA256", "abc") - # - # which is equivalent to: - # - # OpenSSL::Digest::SHA256.digest("abc") def self.digest(name, data) super(data, name) end - alg.each{|name| + %w(MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512).each do |name| klass = Class.new(self) { define_method(:initialize, ->(data = nil) {super(name, data)}) } + singleton = (class << klass; self; end) + singleton.class_eval{ - define_method(:digest){|data| new.digest(data) } - define_method(:hexdigest){|data| new.hexdigest(data) } + define_method(:digest) {|data| new.digest(data)} + define_method(:hexdigest) {|data| new.hexdigest(data)} } - const_set(name, klass) - } + + const_set(name.tr('-', '_'), klass) + end # Deprecated. # # This class is only provided for backwards compatibility. - class Digest < Digest # :nodoc: - # Deprecated. - # - # See OpenSSL::Digest.new - def initialize(*args) - warn('Digest::Digest is deprecated; use Digest') - super(*args) - end - end + # Use OpenSSL::Digest instead. + class Digest < Digest; end # :nodoc: + deprecate_constant :Digest end # Digest - # Returns a Digest subclass by +name+. + # Returns a Digest subclass by _name_ # # require 'openssl' # # OpenSSL::Digest("MD5") # # => OpenSSL::Digest::MD5 # - # Digest("Foo") + # OpenSSL::Digest("Foo") # # => NameError: wrong constant name Foo def Digest(name) @@ -85,4 +67,3 @@ module OpenSSL module_function :Digest end # OpenSSL - diff --git a/ext/openssl/lib/openssl/hmac.rb b/ext/openssl/lib/openssl/hmac.rb new file mode 100644 index 0000000000..c8c844d8d7 --- /dev/null +++ b/ext/openssl/lib/openssl/hmac.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +module OpenSSL + class HMAC + # Securely compare with another HMAC instance in constant time. + def ==(other) + return false unless HMAC === other + return false unless self.digest.bytesize == other.digest.bytesize + + OpenSSL.fixed_length_secure_compare(self.digest, other.digest) + end + + # :call-seq: + # hmac.base64digest -> string + # + # Returns the authentication code an a Base64-encoded string. + def base64digest + [digest].pack("m0") + end + + class << self + # :call-seq: + # HMAC.digest(digest, key, data) -> aString + # + # Returns the authentication code as a binary string. The _digest_ parameter + # specifies the digest algorithm to use. This may be a String representing + # the algorithm name or an instance of OpenSSL::Digest. + # + # === Example + # key = 'key' + # data = 'The quick brown fox jumps over the lazy dog' + # + # hmac = OpenSSL::HMAC.digest('SHA1', key, data) + # #=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9" + def digest(digest, key, data) + hmac = new(key, digest) + hmac << data + hmac.digest + end + + # :call-seq: + # HMAC.hexdigest(digest, key, data) -> aString + # + # Returns the authentication code as a hex-encoded string. The _digest_ + # parameter specifies the digest algorithm to use. This may be a String + # representing the algorithm name or an instance of OpenSSL::Digest. + # + # === Example + # key = 'key' + # data = 'The quick brown fox jumps over the lazy dog' + # + # hmac = OpenSSL::HMAC.hexdigest('SHA1', key, data) + # #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9" + def hexdigest(digest, key, data) + hmac = new(key, digest) + hmac << data + hmac.hexdigest + end + + # :call-seq: + # HMAC.base64digest(digest, key, data) -> aString + # + # Returns the authentication code as a Base64-encoded string. The _digest_ + # parameter specifies the digest algorithm to use. This may be a String + # representing the algorithm name or an instance of OpenSSL::Digest. + # + # === Example + # key = 'key' + # data = 'The quick brown fox jumps over the lazy dog' + # + # hmac = OpenSSL::HMAC.base64digest('SHA1', key, data) + # #=> "3nybhbi3iqa8ino29wqQcBydtNk=" + def base64digest(digest, key, data) + [digest(digest, key, data)].pack("m0") + end + end + end +end diff --git a/ext/openssl/lib/openssl/marshal.rb b/ext/openssl/lib/openssl/marshal.rb new file mode 100644 index 0000000000..eb8eda4748 --- /dev/null +++ b/ext/openssl/lib/openssl/marshal.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true +#-- +# = Ruby-space definitions to add DER (de)serialization to classes +# +# = Info +# 'OpenSSL for Ruby 2' project +# Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz> +# All rights reserved. +# +# = Licence +# This program is licensed under the same licence as Ruby. +# (See the file 'COPYING'.) +#++ +module OpenSSL + module Marshal + def self.included(base) + base.extend(ClassMethods) + end + + module ClassMethods + def _load(string) + new(string) + end + end + + def _dump(_level) + to_der + end + end +end diff --git a/ext/openssl/lib/openssl/pkcs5.rb b/ext/openssl/lib/openssl/pkcs5.rb new file mode 100644 index 0000000000..8dedc4beef --- /dev/null +++ b/ext/openssl/lib/openssl/pkcs5.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true +#-- +# Ruby/OpenSSL Project +# Copyright (C) 2017 Ruby/OpenSSL Project Authors +#++ + +module OpenSSL + module PKCS5 + module_function + + # OpenSSL::PKCS5.pbkdf2_hmac has been renamed to OpenSSL::KDF.pbkdf2_hmac. + # This method is provided for backwards compatibility. + def pbkdf2_hmac(pass, salt, iter, keylen, digest) + OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter, + length: keylen, hash: digest) + end + + def pbkdf2_hmac_sha1(pass, salt, iter, keylen) + pbkdf2_hmac(pass, salt, iter, keylen, "sha1") + end + end +end diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb new file mode 100644 index 0000000000..39871e15dd --- /dev/null +++ b/ext/openssl/lib/openssl/pkey.rb @@ -0,0 +1,493 @@ +# frozen_string_literal: true +#-- +# Ruby/OpenSSL Project +# Copyright (C) 2017 Ruby/OpenSSL Project Authors +#++ + +require_relative 'marshal' + +module OpenSSL::PKey + # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError. + DHError = PKeyError + + class DH + include OpenSSL::Marshal + + # :call-seq: + # dh.public_key -> dhnew + # + # Returns a new DH instance that carries just the \DH parameters. + # + # Contrary to the method name, the returned DH object contains only + # parameters and not the public key. + # + # This method is provided for backwards compatibility. In most cases, there + # is no need to call this method. + # + # For the purpose of re-generating the key pair while keeping the + # parameters, check OpenSSL::PKey.generate_key. + # + # Example: + # # OpenSSL::PKey::DH.generate by default generates a random key pair + # dh1 = OpenSSL::PKey::DH.generate(2048) + # p dh1.priv_key #=> #<OpenSSL::BN 1288347...> + # dhcopy = dh1.public_key + # p dhcopy.priv_key #=> nil + def public_key + DH.new(to_der) + end + + # :call-seq: + # dh.params -> hash + # + # Stores all parameters of key to a Hash. + # + # The hash has keys 'p', 'q', 'g', 'pub_key', and 'priv_key'. + def params + %w{p q g pub_key priv_key}.map { |name| + [name, send(name)] + }.to_h + end + + # :call-seq: + # dh.compute_key(pub_bn) -> string + # + # Returns a String containing a shared secret computed from the other + # party's public value. + # + # This method is provided for backwards compatibility, and calls #derive + # internally. + # + # === Parameters + # * _pub_bn_ is a OpenSSL::BN, *not* the DH instance returned by + # DH#public_key as that contains the DH parameters only. + def compute_key(pub_bn) + # FIXME: This is constructing an X.509 SubjectPublicKeyInfo and is very + # inefficient + obj = OpenSSL::ASN1.Sequence([ + OpenSSL::ASN1.Sequence([ + OpenSSL::ASN1.ObjectId("dhKeyAgreement"), + OpenSSL::ASN1.Sequence([ + OpenSSL::ASN1.Integer(p), + OpenSSL::ASN1.Integer(g), + ]), + ]), + OpenSSL::ASN1.BitString(OpenSSL::ASN1.Integer(pub_bn).to_der), + ]) + derive(OpenSSL::PKey.read(obj.to_der)) + end + + # :call-seq: + # dh.generate_key! -> self + # + # Generates a private and public key unless a private key already exists. + # If this DH instance was generated from public \DH parameters (e.g. by + # encoding the result of DH#public_key), then this method needs to be + # called first in order to generate the per-session keys before performing + # the actual key exchange. + # + # <b>Deprecated in version 3.0</b>. This method is incompatible with + # OpenSSL 3.0.0 or later. + # + # See also OpenSSL::PKey.generate_key. + # + # Example: + # # DEPRECATED USAGE: This will not work on OpenSSL 3.0 or later + # dh0 = OpenSSL::PKey::DH.new(2048) + # dh = dh0.public_key # #public_key only copies the DH parameters (contrary to the name) + # dh.generate_key! + # puts dh.private? # => true + # puts dh0.pub_key == dh.pub_key #=> false + # + # # With OpenSSL::PKey.generate_key + # dh0 = OpenSSL::PKey::DH.new(2048) + # dh = OpenSSL::PKey.generate_key(dh0) + # puts dh0.pub_key == dh.pub_key #=> false + def generate_key! + if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x30000000 + raise PKeyError, "OpenSSL::PKey::DH is immutable on OpenSSL 3.0; " \ + "use OpenSSL::PKey.generate_key instead" + end + + unless priv_key + tmp = OpenSSL::PKey.generate_key(self) + set_key(tmp.pub_key, tmp.priv_key) + end + self + end + + class << self + # :call-seq: + # DH.generate(size, generator = 2) -> dh + # + # Creates a new DH instance from scratch by generating random parameters + # and a key pair. + # + # See also OpenSSL::PKey.generate_parameters and + # OpenSSL::PKey.generate_key. + # + # +size+:: + # The desired key size in bits. + # +generator+:: + # The generator. + def generate(size, generator = 2, &blk) + dhparams = OpenSSL::PKey.generate_parameters("DH", { + "dh_paramgen_prime_len" => size, + "dh_paramgen_generator" => generator, + }, &blk) + OpenSSL::PKey.generate_key(dhparams) + end + + # Handle DH.new(size, generator) form here; new(str) and new() forms + # are handled by #initialize + def new(*args, &blk) # :nodoc: + if args[0].is_a?(Integer) + generate(*args, &blk) + else + super + end + end + end + end + + # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError. + DSAError = PKeyError + + class DSA + include OpenSSL::Marshal + + # :call-seq: + # dsa.public_key -> dsanew + # + # Returns a new DSA instance that carries just the \DSA parameters and the + # public key. + # + # This method is provided for backwards compatibility. In most cases, there + # is no need to call this method. + # + # For the purpose of serializing the public key, to PEM or DER encoding of + # X.509 SubjectPublicKeyInfo format, check PKey#public_to_pem and + # PKey#public_to_der. + def public_key + OpenSSL::PKey.read(public_to_der) + end + + # :call-seq: + # dsa.params -> hash + # + # Stores all parameters of key to a Hash. + # + # The hash has keys 'p', 'q', 'g', 'pub_key', and 'priv_key'. + def params + %w{p q g pub_key priv_key}.map { |name| + [name, send(name)] + }.to_h + end + + class << self + # :call-seq: + # DSA.generate(size) -> dsa + # + # Creates a new DSA instance by generating a private/public key pair + # from scratch. + # + # See also OpenSSL::PKey.generate_parameters and + # OpenSSL::PKey.generate_key. + # + # +size+:: + # The desired key size in bits. + def generate(size, &blk) + # FIPS 186-4 specifies four (L,N) pairs: (1024,160), (2048,224), + # (2048,256), and (3072,256). + # + # q size is derived here with compatibility with + # DSA_generator_parameters_ex() which previous versions of ruby/openssl + # used to call. + qsize = size >= 2048 ? 256 : 160 + dsaparams = OpenSSL::PKey.generate_parameters("DSA", { + "dsa_paramgen_bits" => size, + "dsa_paramgen_q_bits" => qsize, + }, &blk) + OpenSSL::PKey.generate_key(dsaparams) + end + + # Handle DSA.new(size) form here; new(str) and new() forms + # are handled by #initialize + def new(*args, &blk) # :nodoc: + if args[0].is_a?(Integer) + generate(*args, &blk) + else + super + end + end + end + + # :call-seq: + # dsa.syssign(string) -> string + # + # Computes and returns the \DSA signature of +string+, where +string+ is + # expected to be an already-computed message digest of the original input + # data. The signature is issued using the private key of this DSA instance. + # + # <b>Deprecated in version 3.0</b>. + # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw instead. + # + # +string+:: + # A message digest of the original input data to be signed. + # + # Example: + # dsa = OpenSSL::PKey::DSA.new(2048) + # doc = "Sign me" + # digest = OpenSSL::Digest.digest('SHA1', doc) + # + # # With legacy #syssign and #sysverify: + # sig = dsa.syssign(digest) + # p dsa.sysverify(digest, sig) #=> true + # + # # With #sign_raw and #verify_raw: + # sig = dsa.sign_raw(nil, digest) + # p dsa.verify_raw(nil, sig, digest) #=> true + def syssign(string) + q or raise PKeyError, "incomplete DSA" + private? or raise PKeyError, "Private DSA key needed!" + sign_raw(nil, string) + end + + # :call-seq: + # dsa.sysverify(digest, sig) -> true | false + # + # Verifies whether the signature is valid given the message digest input. + # It does so by validating +sig+ using the public key of this DSA instance. + # + # <b>Deprecated in version 3.0</b>. + # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw instead. + # + # +digest+:: + # A message digest of the original input data to be signed. + # +sig+:: + # A \DSA signature value. + def sysverify(digest, sig) + verify_raw(nil, sig, digest) + end + end + + if defined?(EC) + # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError. + ECError = PKeyError + + class EC + include OpenSSL::Marshal + + # :call-seq: + # key.dsa_sign_asn1(data) -> String + # + # <b>Deprecated in version 3.0</b>. + # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw instead. + def dsa_sign_asn1(data) + sign_raw(nil, data) + end + + # :call-seq: + # key.dsa_verify_asn1(data, sig) -> true | false + # + # <b>Deprecated in version 3.0</b>. + # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw instead. + def dsa_verify_asn1(data, sig) + verify_raw(nil, sig, data) + end + + # :call-seq: + # ec.dh_compute_key(pubkey) -> string + # + # Derives a shared secret by ECDH. _pubkey_ must be an instance of + # OpenSSL::PKey::EC::Point and must belong to the same group. + # + # This method is provided for backwards compatibility, and calls #derive + # internally. + def dh_compute_key(pubkey) + obj = OpenSSL::ASN1.Sequence([ + OpenSSL::ASN1.Sequence([ + OpenSSL::ASN1.ObjectId("id-ecPublicKey"), + group.to_der, + ]), + OpenSSL::ASN1.BitString(pubkey.to_octet_string(:uncompressed)), + ]) + derive(OpenSSL::PKey.read(obj.to_der)) + end + end + + class EC::Point + # :call-seq: + # point.to_bn([conversion_form]) -> OpenSSL::BN + # + # Returns the octet string representation of the EC point as an instance of + # OpenSSL::BN. + # + # If _conversion_form_ is not given, the _point_conversion_form_ attribute + # set to the group is used. + # + # See #to_octet_string for more information. + def to_bn(conversion_form = group.point_conversion_form) + OpenSSL::BN.new(to_octet_string(conversion_form), 2) + end + end + end + + # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError. + RSAError = PKeyError + + class RSA + include OpenSSL::Marshal + + # :call-seq: + # rsa.public_key -> rsanew + # + # Returns a new RSA instance that carries just the public key components. + # + # This method is provided for backwards compatibility. In most cases, there + # is no need to call this method. + # + # For the purpose of serializing the public key, to PEM or DER encoding of + # X.509 SubjectPublicKeyInfo format, check PKey#public_to_pem and + # PKey#public_to_der. + def public_key + OpenSSL::PKey.read(public_to_der) + end + + # :call-seq: + # rsa.params -> hash + # + # Stores all parameters of key to a Hash. + # + # The hash has keys 'n', 'e', 'd', 'p', 'q', 'dmp1', 'dmq1', and 'iqmp'. + def params + %w{n e d p q dmp1 dmq1 iqmp}.map { |name| + [name, send(name)] + }.to_h + end + + class << self + # :call-seq: + # RSA.generate(size, exponent = 65537) -> RSA + # + # Generates an \RSA keypair. + # + # See also OpenSSL::PKey.generate_key. + # + # +size+:: + # The desired key size in bits. + # +exponent+:: + # An odd Integer, normally 3, 17, or 65537. + def generate(size, exp = 0x10001, &blk) + OpenSSL::PKey.generate_key("RSA", { + "rsa_keygen_bits" => size, + "rsa_keygen_pubexp" => exp, + }, &blk) + end + + # Handle RSA.new(size, exponent) form here; new(str) and new() forms + # are handled by #initialize + def new(*args, &blk) # :nodoc: + if args[0].is_a?(Integer) + generate(*args, &blk) + else + super + end + end + end + + # :call-seq: + # rsa.private_encrypt(string) -> String + # rsa.private_encrypt(string, padding) -> String + # + # Encrypt +string+ with the private key. +padding+ defaults to + # PKCS1_PADDING, which is known to be insecure but is kept for backwards + # compatibility. The encrypted string output can be decrypted using + # #public_decrypt. + # + # <b>Deprecated in version 3.0</b>. + # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw, and + # PKey::PKey#verify_recover instead. + def private_encrypt(string, padding = PKCS1_PADDING) + n or raise PKeyError, "incomplete RSA" + private? or raise PKeyError, "private key needed." + sign_raw(nil, string, { + "rsa_padding_mode" => translate_padding_mode(padding), + }) + end + + # :call-seq: + # rsa.public_decrypt(string) -> String + # rsa.public_decrypt(string, padding) -> String + # + # Decrypt +string+, which has been encrypted with the private key, with the + # public key. +padding+ defaults to PKCS1_PADDING which is known to be + # insecure but is kept for backwards compatibility. + # + # <b>Deprecated in version 3.0</b>. + # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw, and + # PKey::PKey#verify_recover instead. + def public_decrypt(string, padding = PKCS1_PADDING) + n or raise PKeyError, "incomplete RSA" + verify_recover(nil, string, { + "rsa_padding_mode" => translate_padding_mode(padding), + }) + end + + # :call-seq: + # rsa.public_encrypt(string) -> String + # rsa.public_encrypt(string, padding) -> String + # + # Encrypt +string+ with the public key. +padding+ defaults to + # PKCS1_PADDING, which is known to be insecure but is kept for backwards + # compatibility. The encrypted string output can be decrypted using + # #private_decrypt. + # + # <b>Deprecated in version 3.0</b>. + # Consider using PKey::PKey#encrypt and PKey::PKey#decrypt instead. + def public_encrypt(data, padding = PKCS1_PADDING) + n or raise PKeyError, "incomplete RSA" + encrypt(data, { + "rsa_padding_mode" => translate_padding_mode(padding), + }) + end + + # :call-seq: + # rsa.private_decrypt(string) -> String + # rsa.private_decrypt(string, padding) -> String + # + # Decrypt +string+, which has been encrypted with the public key, with the + # private key. +padding+ defaults to PKCS1_PADDING, which is known to be + # insecure but is kept for backwards compatibility. + # + # <b>Deprecated in version 3.0</b>. + # Consider using PKey::PKey#encrypt and PKey::PKey#decrypt instead. + def private_decrypt(data, padding = PKCS1_PADDING) + n or raise PKeyError, "incomplete RSA" + private? or raise PKeyError, "private key needed." + decrypt(data, { + "rsa_padding_mode" => translate_padding_mode(padding), + }) + end + + PKCS1_PADDING = 1 + SSLV23_PADDING = 2 + NO_PADDING = 3 + PKCS1_OAEP_PADDING = 4 + + private def translate_padding_mode(num) + case num + when PKCS1_PADDING + "pkcs1" + when SSLV23_PADDING + "sslv23" + when NO_PADDING + "none" + when PKCS1_OAEP_PADDING + "oaep" + else + raise PKeyError, "unsupported padding mode" + end + end + end +end diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb index ff1d4efb32..3268c126b9 100644 --- a/ext/openssl/lib/openssl/ssl.rb +++ b/ext/openssl/lib/openssl/ssl.rb @@ -1,100 +1,184 @@ +# frozen_string_literal: true =begin -= $RCSfile$ -- Ruby-space definitions that completes C-space funcs for SSL - = Info 'OpenSSL for Ruby 2' project Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org> All rights reserved. = Licence - This program is licenced under the same licence as Ruby. - (See the file 'LICENCE'.) - -= Version - $Id$ + This program is licensed under the same licence as Ruby. + (See the file 'COPYING'.) =end require "openssl/buffering" -require "fcntl" + +if defined?(OpenSSL::SSL) + +require "io/nonblock" +require "ipaddr" +require "socket" module OpenSSL module SSL class SSLContext - DEFAULT_PARAMS = { - :ssl_version => "SSLv23", + DEFAULT_PARAMS = { # :nodoc: :verify_mode => OpenSSL::SSL::VERIFY_PEER, - :ciphers => %w{ - ECDHE-ECDSA-AES128-GCM-SHA256 - ECDHE-RSA-AES128-GCM-SHA256 - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384 - DHE-RSA-AES128-GCM-SHA256 - DHE-DSS-AES128-GCM-SHA256 - DHE-RSA-AES256-GCM-SHA384 - DHE-DSS-AES256-GCM-SHA384 - ECDHE-ECDSA-AES128-SHA256 - ECDHE-RSA-AES128-SHA256 - ECDHE-ECDSA-AES128-SHA - ECDHE-RSA-AES128-SHA - ECDHE-ECDSA-AES256-SHA384 - ECDHE-RSA-AES256-SHA384 - ECDHE-ECDSA-AES256-SHA - ECDHE-RSA-AES256-SHA - DHE-RSA-AES128-SHA256 - DHE-RSA-AES256-SHA256 - DHE-RSA-AES128-SHA - DHE-RSA-AES256-SHA - DHE-DSS-AES128-SHA256 - DHE-DSS-AES256-SHA256 - DHE-DSS-AES128-SHA - DHE-DSS-AES256-SHA - AES128-GCM-SHA256 - AES256-GCM-SHA384 - AES128-SHA256 - AES256-SHA256 - AES128-SHA - AES256-SHA - ECDHE-ECDSA-RC4-SHA - ECDHE-RSA-RC4-SHA - RC4-SHA - }.join(":"), + :verify_hostname => true, :options => -> { opts = OpenSSL::SSL::OP_ALL - opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS) - opts |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION) - opts |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2) - opts |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3) + opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS + opts |= OpenSSL::SSL::OP_NO_COMPRESSION opts }.call } - DEFAULT_CERT_STORE = OpenSSL::X509::Store.new + if !OpenSSL::OPENSSL_VERSION.start_with?("OpenSSL") + DEFAULT_PARAMS.merge!( + min_version: OpenSSL::SSL::TLS1_VERSION, + ciphers: %w{ + ECDHE-ECDSA-AES128-GCM-SHA256 + ECDHE-RSA-AES128-GCM-SHA256 + ECDHE-ECDSA-AES256-GCM-SHA384 + ECDHE-RSA-AES256-GCM-SHA384 + DHE-RSA-AES128-GCM-SHA256 + DHE-DSS-AES128-GCM-SHA256 + DHE-RSA-AES256-GCM-SHA384 + DHE-DSS-AES256-GCM-SHA384 + ECDHE-ECDSA-AES128-SHA256 + ECDHE-RSA-AES128-SHA256 + ECDHE-ECDSA-AES128-SHA + ECDHE-RSA-AES128-SHA + ECDHE-ECDSA-AES256-SHA384 + ECDHE-RSA-AES256-SHA384 + ECDHE-ECDSA-AES256-SHA + ECDHE-RSA-AES256-SHA + DHE-RSA-AES128-SHA256 + DHE-RSA-AES256-SHA256 + DHE-RSA-AES128-SHA + DHE-RSA-AES256-SHA + DHE-DSS-AES128-SHA256 + DHE-DSS-AES256-SHA256 + DHE-DSS-AES128-SHA + DHE-DSS-AES256-SHA + AES128-GCM-SHA256 + AES256-GCM-SHA384 + AES128-SHA256 + AES256-SHA256 + AES128-SHA + AES256-SHA + }.join(":").freeze, + ) + end + DEFAULT_PARAMS.freeze + + DEFAULT_CERT_STORE = OpenSSL::X509::Store.new # :nodoc: DEFAULT_CERT_STORE.set_default_paths - if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL) - DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL + + # A callback invoked at connect time to distinguish between multiple + # server names. + # + # The callback is invoked with an SSLSocket and a server name. The + # callback must return an SSLContext for the server name or nil. + attr_accessor :servername_cb + + # call-seq: + # SSLContext.new -> ctx + # SSLContext.new(:TLSv1) -> ctx + # SSLContext.new("SSLv23") -> ctx + # + # Creates a new SSL context. + # + # If an argument is given, #ssl_version= is called with the value. Note + # that this form is deprecated. New applications should use #min_version= + # and #max_version= as necessary. + def initialize(version = nil) + self.ssl_version = version if version + self.verify_mode = OpenSSL::SSL::VERIFY_NONE + self.verify_hostname = false end ## - # Sets the parameters for this SSL context to the values in +params+. - # The keys in +params+ must be assignment methods on SSLContext. + # call-seq: + # ctx.set_params(params = {}) -> params + # + # Sets saner defaults optimized for the use with HTTP-like protocols. + # + # If a Hash _params_ is given, the parameters are overridden with it. + # The keys in _params_ must be assignment methods on SSLContext. # # If the verify_mode is not VERIFY_NONE and ca_file, ca_path and # cert_store are not set then the system default certificate store is # used. - def set_params(params={}) params = DEFAULT_PARAMS.merge(params) + self.options |= params.delete(:options) # set before min_version/max_version params.each{|name, value| self.__send__("#{name}=", value) } if self.verify_mode != OpenSSL::SSL::VERIFY_NONE unless self.ca_file or self.ca_path or self.cert_store - self.cert_store = DEFAULT_CERT_STORE + if not defined?(Ractor) or Ractor.current == Ractor.main + self.cert_store = DEFAULT_CERT_STORE + else + self.cert_store = Ractor.current[:__openssl_default_store__] ||= + OpenSSL::X509::Store.new.tap { |store| + store.set_default_paths + } + end end end return params end + + # call-seq: + # ctx.ssl_version = :TLSv1 + # ctx.ssl_version = "SSLv23" + # + # Sets the SSL/TLS protocol version for the context. This forces + # connections to use only the specified protocol version. This is + # deprecated and only provided for backwards compatibility. Use + # #min_version= and #max_version= instead. + # + # === History + # As the name hints, this used to call the SSL_CTX_set_ssl_version() + # function which sets the SSL method used for connections created from + # the context. As of Ruby/OpenSSL 2.1, this accessor method is + # implemented to call #min_version= and #max_version= instead. + def ssl_version=(meth) + meth = meth.to_s if meth.is_a?(Symbol) + if /(?<type>_client|_server)\z/ =~ meth + meth = $` + if $VERBOSE + warn "#{caller(1, 1)[0]}: method type #{type.inspect} is ignored" + end + end + version = METHODS_MAP[meth.intern] or + raise ArgumentError, "unknown SSL method `%s'" % meth + self.min_version = self.max_version = version + end + + METHODS_MAP = { + SSLv23: 0, + SSLv2: OpenSSL::SSL::SSL2_VERSION, + SSLv3: OpenSSL::SSL::SSL3_VERSION, + TLSv1: OpenSSL::SSL::TLS1_VERSION, + TLSv1_1: OpenSSL::SSL::TLS1_1_VERSION, + TLSv1_2: OpenSSL::SSL::TLS1_2_VERSION, + }.freeze + private_constant :METHODS_MAP + + # The list of available SSL/TLS methods. This constant is only provided + # for backwards compatibility. + METHODS = METHODS_MAP.flat_map { |name,| + [name, :"#{name}_client", :"#{name}_server"] + }.freeze + deprecate_constant :METHODS end module SocketForwarder + # The file descriptor for the socket. + def fileno + to_io.fileno + end + def addr to_io.addr end @@ -103,6 +187,14 @@ module OpenSSL to_io.peeraddr end + def local_address + to_io.local_address + end + + def remote_address + to_io.remote_address + end + def setsockopt(level, optname, optval) to_io.setsockopt(level, optname, optval) end @@ -122,14 +214,35 @@ module OpenSSL def do_not_reverse_lookup=(flag) to_io.do_not_reverse_lookup = flag end - end - module Nonblock - def initialize(*args) - flag = File::NONBLOCK - flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL) - @io.fcntl(Fcntl::F_SETFL, flag) - super + def close_on_exec=(value) + to_io.close_on_exec = value + end + + def close_on_exec? + to_io.close_on_exec? + end + + def wait(*args) + to_io.wait(*args) + end + + def wait_readable(*args) + to_io.wait_readable(*args) + end + + def wait_writable(*args) + to_io.wait_writable(*args) + end + + if IO.method_defined?(:timeout) + def timeout + to_io.timeout + end + + def timeout=(value) + to_io.timeout=(value) + end end end @@ -143,15 +256,14 @@ module OpenSSL case san.tag when 2 # dNSName in GeneralName (RFC5280) should_verify_common_name = false - reg = Regexp.escape(san.value).gsub(/\\\*/, "[^.]+") - return true if /\A#{reg}\z/i =~ hostname + return true if verify_hostname(hostname, san.value) when 7 # iPAddress in GeneralName (RFC5280) should_verify_common_name = false - # follows GENERAL_NAME_print() in x509v3/v3_alt.c - if san.value.size == 4 - return true if san.value.unpack('C*').join('.') == hostname - elsif san.value.size == 16 - return true if san.value.unpack('n*').map { |e| sprintf("%X", e) }.join(':') == hostname + if san.value.size == 4 || san.value.size == 16 + begin + return true if san.value == IPAddr.new(hostname).hton + rescue IPAddr::InvalidAddressError + end end end } @@ -159,8 +271,7 @@ module OpenSSL if should_verify_common_name cert.subject.to_a.each{|oid, value| if oid == "CN" - reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+") - return true if /\A#{reg}\z/i =~ hostname + return true if verify_hostname(hostname, value) end } end @@ -168,23 +279,198 @@ module OpenSSL end module_function :verify_certificate_identity + def verify_hostname(hostname, san) # :nodoc: + # RFC 5280, IA5String is limited to the set of ASCII characters + return false unless san.ascii_only? + return false unless hostname.ascii_only? + + # See RFC 6125, section 6.4.1 + # Matching is case-insensitive. + san_parts = san.downcase.split(".") + + # TODO: this behavior should probably be more strict + return san == hostname if san_parts.size < 2 + + # Matching is case-insensitive. + host_parts = hostname.downcase.split(".") + + # RFC 6125, section 6.4.3, subitem 2. + # If the wildcard character is the only character of the left-most + # label in the presented identifier, the client SHOULD NOT compare + # against anything but the left-most label of the reference + # identifier (e.g., *.example.com would match foo.example.com but + # not bar.foo.example.com or example.com). + return false unless san_parts.size == host_parts.size + + # RFC 6125, section 6.4.3, subitem 1. + # The client SHOULD NOT attempt to match a presented identifier in + # which the wildcard character comprises a label other than the + # left-most label (e.g., do not match bar.*.example.net). + return false unless verify_wildcard(host_parts.shift, san_parts.shift) + + san_parts.join(".") == host_parts.join(".") + end + module_function :verify_hostname + + def verify_wildcard(domain_component, san_component) # :nodoc: + parts = san_component.split("*", -1) + + return false if parts.size > 2 + return san_component == domain_component if parts.size == 1 + + # RFC 6125, section 6.4.3, subitem 3. + # The client SHOULD NOT attempt to match a presented identifier + # where the wildcard character is embedded within an A-label or + # U-label of an internationalized domain name. + return false if domain_component.start_with?("xn--") && san_component != "*" + + parts[0].length + parts[1].length < domain_component.length && + domain_component.start_with?(parts[0]) && + domain_component.end_with?(parts[1]) + end + module_function :verify_wildcard + class SSLSocket include Buffering include SocketForwarder - include Nonblock + attr_reader :hostname + + # The underlying IO object. + attr_reader :io + alias :to_io :io + + # The SSLContext object used in this connection. + attr_reader :context + + # Whether to close the underlying socket as well, when the SSL/TLS + # connection is shut down. This defaults to +false+. + attr_accessor :sync_close + + # call-seq: + # ssl.sysclose => nil + # + # Sends "close notify" to the peer and tries to shut down the SSL + # connection gracefully. + # + # If sync_close is set to +true+, the underlying IO is also closed. + def sysclose + return if closed? + stop + io.close if sync_close + end + + # call-seq: + # ssl.post_connection_check(hostname) -> true + # + # Perform hostname verification following RFC 6125. + # + # This method MUST be called after calling #connect to ensure that the + # hostname of a remote peer has been verified. def post_connection_check(hostname) + if peer_cert.nil? + msg = "Peer verification enabled, but no certificate received." + if using_anon_cipher? + msg += " Anonymous cipher suite #{cipher[0]} was negotiated. " \ + "Anonymous suites must be disabled to use peer verification." + end + raise SSLError, msg + end + unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname) raise SSLError, "hostname \"#{hostname}\" does not match the server certificate" end return true end + # call-seq: + # ssl.session -> aSession + # + # Returns the SSLSession object currently used, or nil if the session is + # not established. def session SSL::Session.new(self) rescue SSL::Session::SessionError nil end + + # Close the stream for reading. + # This method is ignored by OpenSSL as there is no reasonable way to + # implement it, but exists for compatibility with IO. + def close_read + # Unsupported and ignored. + # Just don't read any more. + end + + # Closes the stream for writing. The behavior of this method depends on + # the version of OpenSSL and the TLS protocol in use. + # + # - Sends a 'close_notify' alert to the peer. + # - Does not wait for the peer's 'close_notify' alert in response. + # + # In TLS 1.2 and earlier: + # - On receipt of a 'close_notify' alert, responds with a 'close_notify' + # alert of its own and close down the connection immediately, + # discarding any pending writes. + # + # Therefore, on TLS 1.2, this method will cause the connection to be + # completely shut down. On TLS 1.3, the connection will remain open for + # reading only. + def close_write + stop + end + + private + + def using_anon_cipher? + ctx = OpenSSL::SSL::SSLContext.new + ctx.ciphers = "aNULL" + ctx.ciphers.include?(cipher) + end + + def client_cert_cb + @context.client_cert_cb + end + + def session_new_cb + @context.session_new_cb + end + + def session_get_cb + @context.session_get_cb + end + + class << self + + # call-seq: + # open(remote_host, remote_port, local_host=nil, local_port=nil, context: nil) + # + # Creates a new instance of SSLSocket. + # _remote\_host_ and _remote\_port_ are used to open TCPSocket. + # If _local\_host_ and _local\_port_ are specified, + # then those parameters are used on the local end to establish the connection. + # If _context_ is provided, + # the SSL Sockets initial params will be taken from the context. + # + # === Examples + # + # sock = OpenSSL::SSL::SSLSocket.open('localhost', 443) + # sock.connect # Initiates a connection to localhost:443 + # + # with SSLContext: + # + # ctx = OpenSSL::SSL::SSLContext.new + # sock = OpenSSL::SSL::SSLSocket.open('localhost', 443, context: ctx) + # sock.connect # Initiates a connection to localhost:443 with SSLContext + def open(remote_host, remote_port, local_host=nil, local_port=nil, context: nil) + sock = ::TCPSocket.open(remote_host, remote_port, local_host, local_port) + if context.nil? + return OpenSSL::SSL::SSLSocket.new(sock) + else + return OpenSSL::SSL::SSLSocket.new(sock, context) + end + end + end end ## @@ -195,15 +481,15 @@ module OpenSSL attr_accessor :start_immediately # Creates a new instance of SSLServer. - # * +srv+ is an instance of TCPServer. - # * +ctx+ is an instance of OpenSSL::SSL::SSLContext. + # * _srv_ is an instance of TCPServer. + # * _ctx_ is an instance of OpenSSL::SSL::SSLContext. def initialize(svr, ctx) @svr = svr @ctx = ctx unless ctx.session_id_context # see #6137 - session id may not exceed 32 bytes prng = ::Random.new($0.hash) - session_id = prng.bytes(16).unpack('H*')[0] + session_id = prng.bytes(16).unpack1('H*') @ctx.session_id_context = session_id end @start_immediately = true @@ -215,7 +501,7 @@ module OpenSSL end # See TCPServer#listen for details. - def listen(backlog=5) + def listen(backlog=Socket::SOMAXCONN) @svr.listen(backlog) end @@ -252,3 +538,5 @@ module OpenSSL end end end + +end diff --git a/ext/openssl/lib/openssl/version.rb b/ext/openssl/lib/openssl/version.rb new file mode 100644 index 0000000000..88570562e2 --- /dev/null +++ b/ext/openssl/lib/openssl/version.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module OpenSSL + # The version string of Ruby/OpenSSL. + VERSION = "4.0.0" +end diff --git a/ext/openssl/lib/openssl/x509.rb b/ext/openssl/lib/openssl/x509.rb index 38b65c71cf..66765ffeab 100644 --- a/ext/openssl/lib/openssl/x509.rb +++ b/ext/openssl/lib/openssl/x509.rb @@ -1,7 +1,5 @@ +# frozen_string_literal: true #-- -# -# $RCSfile$ -# # = Ruby-space definitions that completes C-space funcs for X509 and subclasses # # = Info @@ -10,14 +8,12 @@ # All rights reserved. # # = Licence -# This program is licenced under the same licence as Ruby. -# (See the file 'LICENCE'.) -# -# = Version -# $Id$ -# +# This program is licensed under the same licence as Ruby. +# (See the file 'COPYING'.) #++ +require_relative 'marshal' + module OpenSSL module X509 class ExtensionFactory @@ -47,6 +43,13 @@ module OpenSSL end class Extension + include OpenSSL::Marshal + + def ==(other) + return false unless Extension === other + to_der == other.to_der + end + def to_s # "oid = critical, value" str = self.oid str << " = " @@ -61,9 +64,146 @@ module OpenSSL def to_a [ self.oid, self.value, self.critical? ] end + + module Helpers + def find_extension(oid) + extensions.find { |e| e.oid == oid } + end + end + + module SubjectKeyIdentifier + include Helpers + + # Get the subject's key identifier from the subjectKeyIdentifier + # exteension, as described in RFC5280 Section 4.2.1.2. + # + # Returns the binary String key identifier or nil or raises + # ASN1::ASN1Error. + def subject_key_identifier + ext = find_extension("subjectKeyIdentifier") + return nil if ext.nil? + + ski_asn1 = ASN1.decode(ext.value_der) + if ext.critical? || ski_asn1.tag_class != :UNIVERSAL || ski_asn1.tag != ASN1::OCTET_STRING + raise ASN1::ASN1Error, "invalid extension" + end + + ski_asn1.value + end + end + + module AuthorityKeyIdentifier + include Helpers + + # Get the issuing certificate's key identifier from the + # authorityKeyIdentifier extension, as described in RFC5280 + # Section 4.2.1.1 + # + # Returns the binary String keyIdentifier or nil or raises + # ASN1::ASN1Error. + def authority_key_identifier + ext = find_extension("authorityKeyIdentifier") + return nil if ext.nil? + + aki_asn1 = ASN1.decode(ext.value_der) + if ext.critical? || aki_asn1.tag_class != :UNIVERSAL || aki_asn1.tag != ASN1::SEQUENCE + raise ASN1::ASN1Error, "invalid extension" + end + + key_id = aki_asn1.value.find do |v| + v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0 + end + + key_id.nil? ? nil : key_id.value + end + end + + module CRLDistributionPoints + include Helpers + + # Get the distributionPoint fullName URI from the certificate's CRL + # distribution points extension, as described in RFC 5280 Section + # 4.2.1.13. + # + # Returns an array of strings or nil or raises ASN1::ASN1Error. + def crl_uris + ext = find_extension("crlDistributionPoints") + return nil if ext.nil? + + cdp_asn1 = ASN1.decode(ext.value_der) + if cdp_asn1.tag_class != :UNIVERSAL || cdp_asn1.tag != ASN1::SEQUENCE + raise ASN1::ASN1Error, "invalid extension" + end + + crl_uris = cdp_asn1.flat_map do |crl_distribution_point| + distribution_point = crl_distribution_point.value.find do |v| + v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0 + end + full_name = distribution_point&.value&.find do |v| + v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0 + end + full_name&.value&.select do |v| + v.tag_class == :CONTEXT_SPECIFIC && v.tag == 6 # uniformResourceIdentifier + end + end + + crl_uris.empty? ? nil : crl_uris.map(&:value) + end + end + + module AuthorityInfoAccess + include Helpers + + # Get the information and services for the issuer from the certificate's + # authority information access extension exteension, as described in RFC5280 + # Section 4.2.2.1. + # + # Returns an array of strings or nil or raises ASN1::ASN1Error. + def ca_issuer_uris + aia_asn1 = parse_aia_asn1 + return nil if aia_asn1.nil? + + ca_issuer = aia_asn1.value.select do |authority_info_access| + authority_info_access.value.first.value == "caIssuers" + end + + ca_issuer&.map(&:value)&.map(&:last)&.map(&:value) + end + + # Get the URIs for OCSP from the certificate's authority information access + # extension exteension, as described in RFC5280 Section 4.2.2.1. + # + # Returns an array of strings or nil or raises ASN1::ASN1Error. + def ocsp_uris + aia_asn1 = parse_aia_asn1 + return nil if aia_asn1.nil? + + ocsp = aia_asn1.value.select do |authority_info_access| + authority_info_access.value.first.value == "OCSP" + end + + ocsp&.map(&:value)&.map(&:last)&.map(&:value) + end + + private + + def parse_aia_asn1 + ext = find_extension("authorityInfoAccess") + return nil if ext.nil? + + aia_asn1 = ASN1.decode(ext.value_der) + if ext.critical? || aia_asn1.tag_class != :UNIVERSAL || aia_asn1.tag != ASN1::SEQUENCE + raise ASN1::ASN1Error, "invalid extension" + end + + aia_asn1 + end + end end class Name + include OpenSSL::Marshal + module RFC2253DN Special = ',=+<>#;' HexChar = /[0-9a-fA-F]/ @@ -139,13 +279,37 @@ module OpenSSL end class << self + # Parses the UTF-8 string representation of a distinguished name, + # according to RFC 2253. + # + # See also #to_utf8 for the opposite operation. def parse_rfc2253(str, template=OBJECT_TYPE_TEMPLATE) ary = OpenSSL::X509::Name::RFC2253DN.scan(str) self.new(ary, template) end + # Parses the string representation of a distinguished name. Two + # different forms are supported: + # + # - \OpenSSL format (<tt>X509_NAME_oneline()</tt>) used by + # <tt>#to_s</tt>. For example: <tt>/DC=com/DC=example/CN=nobody</tt> + # - \OpenSSL format (<tt>X509_NAME_print()</tt>) + # used by <tt>#to_s(OpenSSL::X509::Name::COMPAT)</tt>. For example: + # <tt>DC=com, DC=example, CN=nobody</tt> + # + # Neither of them is standardized and has quirks and inconsistencies + # in handling of escaped characters or multi-valued RDNs. + # + # Use of this method is discouraged in new applications. See + # Name.parse_rfc2253 and #to_utf8 for the alternative. def parse_openssl(str, template=OBJECT_TYPE_TEMPLATE) - ary = str.scan(/\s*([^\/,]+)\s*/).collect{|i| i[0].split("=", 2) } + if str.start_with?("/") + # /A=B/C=D format + ary = str[1..-1].split("/").map { |i| i.split("=", 2) } + else + # Comma-separated + ary = str.split(",").map { |i| i.strip.split("=", 2) } + end self.new(ary, template) end @@ -160,6 +324,15 @@ module OpenSSL end end + class Attribute + include OpenSSL::Marshal + + def ==(other) + return false unless Attribute === other + to_der == other.to_der + end + end + class StoreContext def cleanup warn "(#{caller.first}) OpenSSL::X509::StoreContext#cleanup is deprecated with no replacement" if $VERBOSE @@ -167,6 +340,21 @@ module OpenSSL end class Certificate + include OpenSSL::Marshal + include Extension::SubjectKeyIdentifier + include Extension::AuthorityKeyIdentifier + include Extension::CRLDistributionPoints + include Extension::AuthorityInfoAccess + + def inspect + "#<#{self.class}: " \ + "subject=#{subject.inspect}, " \ + "issuer=#{issuer.inspect}, " \ + "serial=#{serial.inspect}, " \ + "not_before=#{not_before.inspect rescue "(error)"}, " \ + "not_after=#{not_after.inspect rescue "(error)"}>" + end + def pretty_print(q) q.object_group(self) { q.breakable @@ -177,6 +365,36 @@ module OpenSSL q.text 'not_after='; q.pp self.not_after } end + + def self.load_file(path) + load(File.binread(path)) + end + end + + class CRL + include OpenSSL::Marshal + include Extension::AuthorityKeyIdentifier + + def ==(other) + return false unless CRL === other + to_der == other.to_der + end + end + + class Revoked + def ==(other) + return false unless Revoked === other + to_der == other.to_der + end + end + + class Request + include OpenSSL::Marshal + + def ==(other) + return false unless Request === other + to_der == other.to_der + end end end end diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec new file mode 100644 index 0000000000..7072d599d8 --- /dev/null +++ b/ext/openssl/openssl.gemspec @@ -0,0 +1,28 @@ +Gem::Specification.new do |spec| + spec.name = "openssl" + spec.version = "4.0.0" + spec.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"] + spec.email = ["ruby-core@ruby-lang.org"] + spec.summary = %q{SSL/TLS and general-purpose cryptography for Ruby} + spec.description = %q{OpenSSL for Ruby provides access to SSL/TLS and general-purpose cryptography based on the OpenSSL library.} + spec.homepage = "https://github.com/ruby/openssl" + spec.licenses = ["Ruby", "BSD-2-Clause"] + + if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby' + spec.platform = "java" + spec.files = [] + spec.add_runtime_dependency('jruby-openssl', '~> 0.14') + else + spec.files = Dir.glob(["lib/**/*.rb", "ext/**/*.{c,h,rb}", "*.md"], base: File.expand_path("..", __FILE__)) + + ["BSDL", "COPYING"] + spec.require_paths = ["lib"] + spec.extensions = ["ext/openssl/extconf.rb"] + end + + spec.extra_rdoc_files = Dir["*.md"] + spec.rdoc_options = ["--main", "README.md"] + + spec.required_ruby_version = ">= 2.7.0" + + spec.metadata["msys2_mingw_dependencies"] = "openssl" +end diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c deleted file mode 100644 index b5efaaf15d..0000000000 --- a/ext/openssl/openssl_missing.c +++ /dev/null @@ -1,356 +0,0 @@ -/* - * $Id$ - * 'OpenSSL for Ruby' project - * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> - * All rights reserved. - */ -/* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) - */ -#include RUBY_EXTCONF_H - -#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_EVP_CIPHER_CTX_ENGINE) -# include <openssl/engine.h> -#endif -#include <openssl/x509_vfy.h> - -#if !defined(OPENSSL_NO_HMAC) -#include <string.h> /* memcpy() */ -#include <openssl/hmac.h> - -#include "openssl_missing.h" - -#if !defined(HAVE_HMAC_CTX_COPY) -void -HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in) -{ - if (!out || !in) return; - memcpy(out, in, sizeof(HMAC_CTX)); - - EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx); - EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx); - EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx); -} -#endif /* HAVE_HMAC_CTX_COPY */ -#endif /* NO_HMAC */ - -#if !defined(HAVE_X509_STORE_SET_EX_DATA) -int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data) -{ - return CRYPTO_set_ex_data(&str->ex_data, idx, data); -} -#endif - -#if !defined(HAVE_X509_STORE_GET_EX_DATA) -void *X509_STORE_get_ex_data(X509_STORE *str, int idx) -{ - return CRYPTO_get_ex_data(&str->ex_data, idx); -} -#endif - -#if !defined(HAVE_EVP_MD_CTX_CREATE) -EVP_MD_CTX * -EVP_MD_CTX_create(void) -{ - EVP_MD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_MD_CTX)); - if (!ctx) return NULL; - - memset(ctx, 0, sizeof(EVP_MD_CTX)); - - return ctx; -} -#endif - -#if !defined(HAVE_EVP_MD_CTX_CLEANUP) -int -EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) -{ - /* FIXME!!! */ - memset(ctx, 0, sizeof(EVP_MD_CTX)); - - return 1; -} -#endif - -#if !defined(HAVE_EVP_MD_CTX_DESTROY) -void -EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) -{ - EVP_MD_CTX_cleanup(ctx); - OPENSSL_free(ctx); -} -#endif - -#if !defined(HAVE_EVP_MD_CTX_INIT) -void -EVP_MD_CTX_init(EVP_MD_CTX *ctx) -{ - memset(ctx, 0, sizeof(EVP_MD_CTX)); -} -#endif - -#if !defined(HAVE_HMAC_CTX_INIT) -void -HMAC_CTX_init(HMAC_CTX *ctx) -{ - EVP_MD_CTX_init(&ctx->i_ctx); - EVP_MD_CTX_init(&ctx->o_ctx); - EVP_MD_CTX_init(&ctx->md_ctx); -} -#endif - -#if !defined(HAVE_HMAC_CTX_CLEANUP) -void -HMAC_CTX_cleanup(HMAC_CTX *ctx) -{ - EVP_MD_CTX_cleanup(&ctx->i_ctx); - EVP_MD_CTX_cleanup(&ctx->o_ctx); - EVP_MD_CTX_cleanup(&ctx->md_ctx); - memset(ctx, 0, sizeof(HMAC_CTX)); -} -#endif - -#if !defined(HAVE_EVP_CIPHER_CTX_COPY) -/* - * this function does not exist in OpenSSL yet... or ever?. - * a future version may break this function. - * tested on 0.9.7d. - */ -int -EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in) -{ - memcpy(out, in, sizeof(EVP_CIPHER_CTX)); - -#if defined(HAVE_ENGINE_ADD) && defined(HAVE_EVP_CIPHER_CTX_ENGINE) - if (in->engine) ENGINE_add(out->engine); - if (in->cipher_data) { - out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size); - memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size); - } -#endif - - return 1; -} -#endif - -#if !defined(HAVE_X509_CRL_SET_VERSION) -int -X509_CRL_set_version(X509_CRL *x, long version) -{ - if (x == NULL || x->crl == NULL) return 0; - if (x->crl->version == NULL) { - x->crl->version = M_ASN1_INTEGER_new(); - if (x->crl->version == NULL) return 0; - } - return ASN1_INTEGER_set(x->crl->version, version); -} -#endif - -#if !defined(HAVE_X509_CRL_SET_ISSUER_NAME) -int -X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name) -{ - if (x == NULL || x->crl == NULL) return 0; - return X509_NAME_set(&x->crl->issuer, name); -} -#endif - -#if !defined(HAVE_X509_CRL_SORT) -int -X509_CRL_sort(X509_CRL *c) -{ - int i; - X509_REVOKED *r; - /* sort the data so it will be written in serial - * number order */ - sk_X509_REVOKED_sort(c->crl->revoked); - for (i=0; i<sk_X509_REVOKED_num(c->crl->revoked); i++) { - r=sk_X509_REVOKED_value(c->crl->revoked, i); - r->sequence=i; - } - return 1; -} -#endif - -#if !defined(HAVE_X509_CRL_ADD0_REVOKED) -static int -OSSL_X509_REVOKED_cmp(const X509_REVOKED * const *a, const X509_REVOKED * const *b) -{ - return(ASN1_STRING_cmp( - (ASN1_STRING *)(*a)->serialNumber, - (ASN1_STRING *)(*b)->serialNumber)); -} - -int -X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev) -{ - X509_CRL_INFO *inf; - - inf = crl->crl; - if (!inf->revoked) - inf->revoked = sk_X509_REVOKED_new(OSSL_X509_REVOKED_cmp); - if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) - return 0; - return 1; -} -#endif - -#if !defined(HAVE_BN_MOD_SQR) -int -BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) -{ - if (!BN_sqr(r, (BIGNUM*)a, ctx)) return 0; - return BN_mod(r, r, m, ctx); -} -#endif - -#if !defined(HAVE_BN_MOD_ADD) || !defined(HAVE_BN_MOD_SUB) -int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) -{ - if (!BN_mod(r,m,d,ctx)) return 0; - if (!r->neg) return 1; - return (d->neg ? BN_sub : BN_add)(r, r, d); -} -#endif - -#if !defined(HAVE_BN_MOD_ADD) -int -BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx) -{ - if (!BN_add(r, a, b)) return 0; - return BN_nnmod(r, r, m, ctx); -} -#endif - -#if !defined(HAVE_BN_MOD_SUB) -int -BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx) -{ - if (!BN_sub(r, a, b)) return 0; - return BN_nnmod(r, r, m, ctx); -} -#endif - -#if !defined(HAVE_BN_RAND_RANGE) || !defined(HAVE_BN_PSEUDO_RAND_RANGE) -static int -bn_rand_range(int pseudo, BIGNUM *r, BIGNUM *range) -{ - int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand; - int n; - - if (range->neg || BN_is_zero(range)) return 0; - - n = BN_num_bits(range); - - if (n == 1) { - if (!BN_zero(r)) return 0; - } else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) { - do { - if (!bn_rand(r, n + 1, -1, 0)) return 0; - if (BN_cmp(r ,range) >= 0) { - if (!BN_sub(r, r, range)) return 0; - if (BN_cmp(r, range) >= 0) - if (!BN_sub(r, r, range)) return 0; - } - } while (BN_cmp(r, range) >= 0); - } else { - do { - if (!bn_rand(r, n, -1, 0)) return 0; - } while (BN_cmp(r, range) >= 0); - } - - return 1; -} -#endif - -#if !defined(HAVE_BN_RAND_RANGE) -int -BN_rand_range(BIGNUM *r, BIGNUM *range) -{ - return bn_rand_range(0, r, range); -} -#endif - -#if !defined(HAVE_BN_PSEUDO_RAND_RANGE) -int -BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range) -{ - return bn_rand_range(1, r, range); -} -#endif - -#if !defined(HAVE_CONF_GET1_DEFAULT_CONFIG_FILE) -#define OPENSSL_CONF "openssl.cnf" -char * -CONF_get1_default_config_file(void) -{ - char *file; - int len; - - file = getenv("OPENSSL_CONF"); - if (file) return BUF_strdup(file); - len = strlen(X509_get_default_cert_area()); -#ifndef OPENSSL_SYS_VMS - len++; -#endif - len += strlen(OPENSSL_CONF); - file = OPENSSL_malloc(len + 1); - if (!file) return NULL; - strcpy(file,X509_get_default_cert_area()); -#ifndef OPENSSL_SYS_VMS - strcat(file,"/"); -#endif - strcat(file,OPENSSL_CONF); - - return file; -} -#endif - -#if !defined(HAVE_PEM_DEF_CALLBACK) -#define OSSL_PASS_MIN_LENGTH 4 -int -PEM_def_callback(char *buf, int num, int w, void *key) -{ - int i,j; - const char *prompt; - - if (key) { - i = strlen(key); - i = (i > num) ? num : i; - memcpy(buf, key, i); - return i; - } - - prompt = EVP_get_pw_prompt(); - if (prompt == NULL) prompt = "Enter PEM pass phrase:"; - for (;;) { - i = EVP_read_pw_string(buf, num, prompt, w); - if (i != 0) { - memset(buf, 0, (unsigned int)num); - return(-1); - } - j = strlen(buf); - if (j < OSSL_PASS_MIN_LENGTH) { - fprintf(stderr, - "phrase is too short, needs to be at least %d chars\n", - OSSL_PASS_MIN_LENGTH); - } - else break; - } - return j; -} -#endif - -#if !defined(HAVE_ASN1_PUT_EOC) -int -ASN1_put_eoc(unsigned char **pp) -{ - unsigned char *p = *pp; - *p++ = 0; - *p++ = 0; - *pp = p; - return 2; -} -#endif - diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h index 3635f88b73..6592f9ccea 100644 --- a/ext/openssl/openssl_missing.h +++ b/ext/openssl/openssl_missing.h @@ -1,198 +1,32 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(_OSSL_OPENSSL_MISSING_H_) #define _OSSL_OPENSSL_MISSING_H_ -#if defined(__cplusplus) -extern "C" { -#endif +#include "ruby/config.h" -#ifndef TYPEDEF_D2I_OF -typedef char *d2i_of_void(); -#endif -#ifndef TYPEDEF_I2D_OF -typedef int i2d_of_void(); +/* added in 3.0.0 */ +#ifndef HAVE_EVP_MD_CTX_GET0_MD +# define EVP_MD_CTX_get0_md(ctx) EVP_MD_CTX_md(ctx) #endif /* - * These functions are not included in headers of OPENSSL <= 0.9.6b + * OpenSSL 1.1.0 added EVP_MD_CTX_pkey_ctx(), and then it was renamed to + * EVP_MD_CTX_get_pkey_ctx(x) in OpenSSL 3.0. */ - -#if !defined(PEM_read_bio_DSAPublicKey) -# define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \ - (d2i_of_void *)d2i_DSAPublicKey,PEM_STRING_DSA_PUBLIC,(bp),(void **)(x),(cb),(u)) -#endif - -#if !defined(PEM_write_bio_DSAPublicKey) -# define PEM_write_bio_DSAPublicKey(bp,x) \ - PEM_ASN1_write_bio((i2d_of_void *)i2d_DSAPublicKey,\ - PEM_STRING_DSA_PUBLIC,\ - (bp),(char *)(x), NULL, NULL, 0, NULL, NULL) -#endif - -#if !defined(DSAPrivateKey_dup) -# define DSAPrivateKey_dup(dsa) (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey, \ - (d2i_of_void *)d2i_DSAPrivateKey,(char *)(dsa)) -#endif - -#if !defined(DSAPublicKey_dup) -# define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPublicKey, \ - (d2i_of_void *)d2i_DSAPublicKey,(char *)(dsa)) -#endif - -#if !defined(X509_REVOKED_dup) -# define X509_REVOKED_dup(rev) (X509_REVOKED *)ASN1_dup((i2d_of_void *)i2d_X509_REVOKED, \ - (d2i_of_void *)d2i_X509_REVOKED, (char *)(rev)) -#endif - -#if !defined(PKCS7_SIGNER_INFO_dup) -# define PKCS7_SIGNER_INFO_dup(si) (PKCS7_SIGNER_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_SIGNER_INFO, \ - (d2i_of_void *)d2i_PKCS7_SIGNER_INFO, (char *)(si)) -#endif - -#if !defined(PKCS7_RECIP_INFO_dup) -# define PKCS7_RECIP_INFO_dup(ri) (PKCS7_RECIP_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO, \ - (d2i_of_void *)d2i_PKCS7_RECIP_INFO, (char *)(ri)) -#endif - -#if !defined(HAVE_HMAC_CTX_INIT) -void HMAC_CTX_init(HMAC_CTX *ctx); -#endif - -#if !defined(HAVE_HMAC_CTX_COPY) -void HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in); -#endif - -#if !defined(HAVE_HMAC_CTX_CLEANUP) -void HMAC_CTX_cleanup(HMAC_CTX *ctx); -#endif - -#if !defined(HAVE_EVP_MD_CTX_CREATE) -EVP_MD_CTX *EVP_MD_CTX_create(void); -#endif - -#if !defined(HAVE_EVP_MD_CTX_INIT) -void EVP_MD_CTX_init(EVP_MD_CTX *ctx); -#endif - -#if !defined(HAVE_EVP_MD_CTX_CLEANUP) -int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx); -#endif - -#if !defined(HAVE_EVP_MD_CTX_DESTROY) -void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx); -#endif - -#if !defined(HAVE_EVP_CIPHER_CTX_COPY) -int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in); -#endif - -#if !defined(HAVE_EVP_DIGESTINIT_EX) -# define EVP_DigestInit_ex(ctx, md, engine) EVP_DigestInit((ctx), (md)) -#endif -#if !defined(HAVE_EVP_DIGESTFINAL_EX) -# define EVP_DigestFinal_ex(ctx, buf, len) EVP_DigestFinal((ctx), (buf), (len)) -#endif - -#if !defined(HAVE_EVP_CIPHERINIT_EX) -# define EVP_CipherInit_ex(ctx, type, impl, key, iv, enc) EVP_CipherInit((ctx), (type), (key), (iv), (enc)) -#endif -#if !defined(HAVE_EVP_CIPHERFINAL_EX) -# define EVP_CipherFinal_ex(ctx, outm, outl) EVP_CipherFinal((ctx), (outm), (outl)) +#ifndef HAVE_EVP_MD_CTX_GET_PKEY_CTX +# define EVP_MD_CTX_get_pkey_ctx(x) EVP_MD_CTX_pkey_ctx(x) #endif -#if !defined(EVP_CIPHER_name) -# define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e)) +#ifndef HAVE_EVP_PKEY_EQ +# define EVP_PKEY_eq(a, b) EVP_PKEY_cmp(a, b) #endif -#if !defined(EVP_MD_name) -# define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_type(e)) -#endif - -#if !defined(HAVE_EVP_HMAC_INIT_EX) -# define HMAC_Init_ex(ctx, key, len, digest, engine) HMAC_Init((ctx), (key), (len), (digest)) -#endif - -#if !defined(PKCS7_is_detached) -# define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7)) -#endif - -#if !defined(PKCS7_type_is_encrypted) -# define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted) -#endif - -#if !defined(HAVE_OPENSSL_CLEANSE) -#define OPENSSL_cleanse(p, l) memset((p), 0, (l)) -#endif - -#if !defined(HAVE_X509_STORE_GET_EX_DATA) -void *X509_STORE_get_ex_data(X509_STORE *str, int idx); -#endif - -#if !defined(HAVE_X509_STORE_SET_EX_DATA) -int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data); -#endif - -#if !defined(HAVE_X509_CRL_SET_VERSION) -int X509_CRL_set_version(X509_CRL *x, long version); -#endif - -#if !defined(HAVE_X509_CRL_SET_ISSUER_NAME) -int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name); -#endif - -#if !defined(HAVE_X509_CRL_SORT) -int X509_CRL_sort(X509_CRL *c); -#endif - -#if !defined(HAVE_X509_CRL_ADD0_REVOKED) -int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev); -#endif - -#if !defined(HAVE_BN_MOD_SQR) -int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); -#endif - -#if !defined(HAVE_BN_MOD_ADD) -int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); -#endif - -#if !defined(HAVE_BN_MOD_SUB) -int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); -#endif - -#if !defined(HAVE_BN_RAND_RANGE) -int BN_rand_range(BIGNUM *r, BIGNUM *range); -#endif - -#if !defined(HAVE_BN_PSEUDO_RAND_RANGE) -int BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range); -#endif - -#if !defined(HAVE_CONF_GET1_DEFAULT_CONFIG_FILE) -char *CONF_get1_default_config_file(void); -#endif - -#if !defined(HAVE_PEM_DEF_CALLBACK) -int PEM_def_callback(char *buf, int num, int w, void *key); -#endif - -#if !defined(HAVE_ASN1_PUT_EOC) -int ASN1_put_eoc(unsigned char **pp); -#endif - -#if defined(__cplusplus) -} -#endif - - #endif /* _OSSL_OPENSSL_MISSING_H_ */ - diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index 5fbfb3358a..98127fcba0 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -1,257 +1,220 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" #include <stdarg.h> /* for ossl_raise */ /* - * String to HEXString conversion - */ -int -string2hex(const unsigned char *buf, int buf_len, char **hexbuf, int *hexbuf_len) -{ - static const char hex[]="0123456789abcdef"; - int i, len; - - if (buf_len < 0 || buf_len > INT_MAX / 2) { /* PARANOIA? */ - return -1; - } - len = 2 * buf_len; - if (!hexbuf) { /* if no buf, return calculated len */ - if (hexbuf_len) { - *hexbuf_len = len; - } - return len; - } - if (!(*hexbuf = OPENSSL_malloc(len + 1))) { - return -1; - } - for (i = 0; i < buf_len; i++) { - (*hexbuf)[2 * i] = hex[((unsigned char)buf[i]) >> 4]; - (*hexbuf)[2 * i + 1] = hex[buf[i] & 0x0f]; - } - (*hexbuf)[2 * i] = '\0'; - - if (hexbuf_len) { - *hexbuf_len = len; - } - return len; -} - -/* * Data Conversion */ -#define OSSL_IMPL_ARY2SK(name, type, expected_class, dup) \ -STACK_OF(type) * \ -ossl_##name##_ary2sk0(VALUE ary) \ -{ \ - STACK_OF(type) *sk; \ - VALUE val; \ - type *x; \ - int i; \ - \ - Check_Type(ary, T_ARRAY); \ - sk = sk_##type##_new_null(); \ - if (!sk) ossl_raise(eOSSLError, NULL); \ - \ - for (i = 0; i < RARRAY_LEN(ary); i++) { \ - val = rb_ary_entry(ary, i); \ - if (!rb_obj_is_kind_of(val, expected_class)) { \ - sk_##type##_pop_free(sk, type##_free); \ - ossl_raise(eOSSLError, "object in array not" \ - " of class ##type##"); \ - } \ - x = dup(val); /* NEED TO DUP */ \ - sk_##type##_push(sk, x); \ - } \ - return sk; \ -} \ - \ -STACK_OF(type) * \ -ossl_protect_##name##_ary2sk(VALUE ary, int *status) \ -{ \ - return (STACK_OF(type)*)rb_protect( \ - (VALUE(*)_((VALUE)))ossl_##name##_ary2sk0, \ - ary, \ - status); \ -} \ - \ -STACK_OF(type) * \ -ossl_##name##_ary2sk(VALUE ary) \ -{ \ - STACK_OF(type) *sk; \ - int status = 0; \ - \ - sk = ossl_protect_##name##_ary2sk(ary, &status); \ - if (status) rb_jump_tag(status); \ - \ - return sk; \ +#define OSSL_IMPL_ARY2SK(name, type, expected_class, dup) \ +VALUE \ +ossl_##name##_ary2sk0(VALUE ary) \ +{ \ + STACK_OF(type) *sk; \ + VALUE val; \ + type *x; \ + int i; \ + \ + Check_Type(ary, T_ARRAY); \ + sk = sk_##type##_new_null(); \ + if (!sk) ossl_raise(eOSSLError, NULL); \ + \ + for (i = 0; i < RARRAY_LEN(ary); i++) { \ + val = rb_ary_entry(ary, i); \ + if (!rb_obj_is_kind_of(val, expected_class)) { \ + sk_##type##_pop_free(sk, type##_free); \ + ossl_raise(eOSSLError, "object in array not" \ + " of class ##type##"); \ + } \ + x = dup(val); /* NEED TO DUP */ \ + sk_##type##_push(sk, x); \ + } \ + return (VALUE)sk; \ +} \ + \ +STACK_OF(type) * \ +ossl_protect_##name##_ary2sk(VALUE ary, int *status) \ +{ \ + return (STACK_OF(type)*)rb_protect( \ + (VALUE (*)(VALUE))ossl_##name##_ary2sk0, \ + ary, \ + status); \ +} \ + \ +STACK_OF(type) * \ +ossl_##name##_ary2sk(VALUE ary) \ +{ \ + STACK_OF(type) *sk; \ + int status = 0; \ + \ + sk = ossl_protect_##name##_ary2sk(ary, &status); \ + if (status) rb_jump_tag(status); \ + \ + return sk; \ } OSSL_IMPL_ARY2SK(x509, X509, cX509Cert, DupX509CertPtr) -#define OSSL_IMPL_SK2ARY(name, type) \ -VALUE \ -ossl_##name##_sk2ary(STACK_OF(type) *sk) \ -{ \ - type *t; \ - int i, num; \ - VALUE ary; \ - \ - if (!sk) { \ - OSSL_Debug("empty sk!"); \ - return Qnil; \ - } \ - num = sk_##type##_num(sk); \ - if (num < 0) { \ - OSSL_Debug("items in sk < -1???"); \ - return rb_ary_new(); \ - } \ - ary = rb_ary_new2(num); \ - \ - for (i=0; i<num; i++) { \ - t = sk_##type##_value(sk, i); \ - rb_ary_push(ary, ossl_##name##_new(t)); \ - } \ - return ary; \ +#define OSSL_IMPL_SK2ARY(name, type) \ +VALUE \ +ossl_##name##_sk2ary(const STACK_OF(type) *sk) \ +{ \ + type *t; \ + int i, num; \ + VALUE ary; \ + \ + RUBY_ASSERT(sk != NULL); \ + num = sk_##type##_num(sk); \ + ary = rb_ary_new_capa(num); \ + \ + for (i=0; i<num; i++) { \ + t = sk_##type##_value(sk, i); \ + rb_ary_push(ary, ossl_##name##_new(t)); \ + } \ + return ary; \ } OSSL_IMPL_SK2ARY(x509, X509) OSSL_IMPL_SK2ARY(x509crl, X509_CRL) OSSL_IMPL_SK2ARY(x509name, X509_NAME) static VALUE -ossl_str_new(int size) +ossl_str_new_i(VALUE size) { - return rb_str_new(0, size); + return rb_str_new(NULL, (long)size); } VALUE -ossl_buf2str(char *buf, int len) +ossl_str_new(const char *ptr, long len, int *pstate) { VALUE str; - int status = 0; - - str = rb_protect((VALUE(*)_((VALUE)))ossl_str_new, len, &status); - if(!NIL_P(str)) memcpy(RSTRING_PTR(str), buf, len); - OPENSSL_free(buf); - if(status) rb_jump_tag(status); - + int state; + + str = rb_protect(ossl_str_new_i, len, &state); + if (pstate) + *pstate = state; + if (state) { + if (!pstate) + rb_set_errinfo(Qnil); + return Qnil; + } + if (ptr) + memcpy(RSTRING_PTR(str), ptr, len); return str; } -/* - * our default PEM callback - */ -static VALUE -ossl_pem_passwd_cb0(VALUE flag) +VALUE +ossl_buf2str(char *buf, int len) { - VALUE pass; - - pass = rb_yield(flag); - SafeStringValue(pass); + VALUE str; + int state; - return pass; + str = ossl_str_new(buf, len, &state); + OPENSSL_free(buf); + if (state) + rb_jump_tag(state); + return str; } -int -ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd) +void +ossl_bin2hex(const unsigned char *in, char *out, size_t inlen) { - int len, status = 0; - VALUE rflag, pass; + const char *hex = "0123456789abcdef"; + size_t i; - if (pwd || !rb_block_given_p()) - return PEM_def_callback(buf, max_len, flag, pwd); + assert(inlen <= LONG_MAX / 2); + for (i = 0; i < inlen; i++) { + unsigned char p = in[i]; - while (1) { - /* - * when the flag is nonzero, this passphrase - * will be used to perform encryption; otherwise it will - * be used to perform decryption. - */ - rflag = flag ? Qtrue : Qfalse; - pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status); - if (status) { - /* ignore an exception raised. */ - rb_set_errinfo(Qnil); - return -1; - } - len = RSTRING_LENINT(pass); - if (len < 4) { /* 4 is OpenSSL hardcoded limit */ - rb_warning("password must be longer than 4 bytes"); - continue; - } - if (len > max_len) { - rb_warning("password must be shorter then %d bytes", max_len-1); - continue; - } - memcpy(buf, RSTRING_PTR(pass), len); - break; + out[i * 2 + 0] = hex[p >> 4]; + out[i * 2 + 1] = hex[p & 0x0f]; } - return len; } /* - * Verify callback + * our default PEM callback */ -int ossl_verify_cb_idx; - VALUE -ossl_call_verify_cb_proc(struct ossl_verify_cb_args *args) +ossl_pem_passwd_value(VALUE pass) { - return rb_funcall(args->proc, rb_intern("call"), 2, - args->preverify_ok, args->store_ctx); + if (NIL_P(pass)) + return Qnil; + + StringValue(pass); + + /* PEM_BUFSIZE is currently used as the second argument of pem_password_cb, + * that is +max_len+ of ossl_pem_passwd_cb() */ + if (RSTRING_LEN(pass) > PEM_BUFSIZE) + ossl_raise(eOSSLError, "password must not be longer than %d bytes", PEM_BUFSIZE); + + return pass; +} + +static VALUE +ossl_pem_passwd_cb0(VALUE flag) +{ + VALUE pass = rb_yield(flag); + if (NIL_P(pass)) + return Qnil; + StringValue(pass); + return pass; } int -ossl_verify_cb(int ok, X509_STORE_CTX *ctx) +ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_) { - VALUE proc, rctx, ret; - struct ossl_verify_cb_args args; - int state = 0; - - proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_verify_cb_idx); - if ((void*)proc == 0) - proc = (VALUE)X509_STORE_get_ex_data(ctx->ctx, ossl_verify_cb_idx); - if ((void*)proc == 0) - return ok; - if (!NIL_P(proc)) { - ret = Qfalse; - rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new, - (VALUE)ctx, &state); - if (state) { - rb_set_errinfo(Qnil); - rb_warn("StoreContext initialization failure"); - } - else { - args.proc = proc; - args.preverify_ok = ok ? Qtrue : Qfalse; - args.store_ctx = rctx; - ret = rb_protect((VALUE(*)(VALUE))ossl_call_verify_cb_proc, (VALUE)&args, &state); - if (state) { - rb_set_errinfo(Qnil); - rb_warn("exception in verify_callback is ignored"); - } - ossl_x509stctx_clear_ptr(rctx); - } - if (ret == Qtrue) { - X509_STORE_CTX_set_error(ctx, X509_V_OK); - ok = 1; - } - else{ - if (X509_STORE_CTX_get_error(ctx) == X509_V_OK) { - X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED); - } - ok = 0; - } + long len; + int status; + VALUE rflag, pass = (VALUE)pwd_; + + if (RTEST(pass)) { + /* PEM_def_callback(buf, max_len, flag, StringValueCStr(pass)) does not + * work because it does not allow NUL characters and truncates to 1024 + * bytes silently if the input is over 1024 bytes */ + if (RB_TYPE_P(pass, T_STRING)) { + len = RSTRING_LEN(pass); + if (len <= max_len) { + memcpy(buf, RSTRING_PTR(pass), len); + return (int)len; + } + } + OSSL_Debug("passed data is not valid String???"); + return -1; } - return ok; + if (!rb_block_given_p()) { + return PEM_def_callback(buf, max_len, flag, NULL); + } + + while (1) { + /* + * when the flag is nonzero, this password + * will be used to perform encryption; otherwise it will + * be used to perform decryption. + */ + rflag = flag ? Qtrue : Qfalse; + pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status); + if (status) { + /* ignore an exception raised. */ + rb_set_errinfo(Qnil); + return -1; + } + if (NIL_P(pass)) + return -1; + len = RSTRING_LEN(pass); + if (len > max_len) { + rb_warning("password must not be longer than %d bytes", max_len); + continue; + } + memcpy(buf, RSTRING_PTR(pass), len); + break; + } + return (int)len; } /* @@ -267,7 +230,7 @@ VALUE eOSSLError; /* * Convert to DER string */ -ID ossl_s_to_der; +static ID ossl_s_to_der; VALUE ossl_to_der(VALUE obj) @@ -284,50 +247,46 @@ VALUE ossl_to_der_if_possible(VALUE obj) { if(rb_respond_to(obj, ossl_s_to_der)) - return ossl_to_der(obj); + return ossl_to_der(obj); return obj; } /* * Errors */ -static VALUE -ossl_make_error(VALUE exc, const char *fmt, va_list args) +static ID id_i_errors; + +static void collect_errors_into(VALUE ary); + +VALUE +ossl_make_error(VALUE exc, VALUE str) { - VALUE str = Qnil; - const char *msg; - long e; + unsigned long e; + const char *data; + int flags; + VALUE errors = rb_ary_new(); -#ifdef HAVE_ERR_PEEK_LAST_ERROR - e = ERR_peek_last_error(); + if (NIL_P(str)) + str = rb_str_new(NULL, 0); + +#ifdef HAVE_ERR_GET_ERROR_ALL + e = ERR_peek_last_error_all(NULL, NULL, NULL, &data, &flags); #else - e = ERR_peek_error(); + e = ERR_peek_last_error_line_data(NULL, NULL, &data, &flags); #endif - if (fmt) { - str = rb_vsprintf(fmt, args); - } if (e) { - if (dOSSL == Qtrue) /* FULL INFO */ - msg = ERR_error_string(e, NULL); - else - msg = ERR_reason_error_string(e); - if (NIL_P(str)) { - if (msg) str = rb_str_new_cstr(msg); - } - else { - if (RSTRING_LEN(str)) rb_str_cat2(str, ": "); - rb_str_cat2(str, msg ? msg : "(null)"); - } - } - if (dOSSL == Qtrue){ /* show all errors on the stack */ - while ((e = ERR_get_error()) != 0){ - rb_warn("error on stack: %s", ERR_error_string(e, NULL)); - } + const char *msg = ERR_reason_error_string(e); + + if (RSTRING_LEN(str)) rb_str_cat_cstr(str, ": "); + rb_str_cat_cstr(str, msg ? msg : "(null)"); + if (flags & ERR_TXT_STRING && data) + rb_str_catf(str, " (%s)", data); + collect_errors_into(errors); } - ERR_clear_error(); - if (NIL_P(str)) str = rb_str_new(0, 0); - return rb_exc_new3(exc, str); + VALUE obj = rb_exc_new_str(exc, str); + rb_ivar_set(obj, id_i_errors, errors); + return obj; } void @@ -335,33 +294,111 @@ ossl_raise(VALUE exc, const char *fmt, ...) { va_list args; VALUE err; - va_start(args, fmt); - err = ossl_make_error(exc, fmt, args); - va_end(args); - rb_exc_raise(err); + + if (fmt) { + va_start(args, fmt); + err = rb_vsprintf(fmt, args); + va_end(args); + } + else { + err = Qnil; + } + + rb_exc_raise(ossl_make_error(exc, err)); } -VALUE -ossl_exc_new(VALUE exc, const char *fmt, ...) +static void +collect_errors_into(VALUE ary) { - va_list args; - VALUE err; - va_start(args, fmt); - err = ossl_make_error(exc, fmt, args); - va_end(args); - return err; + if (dOSSL == Qtrue || !NIL_P(ary)) { + unsigned long e; + const char *file, *data, *func, *lib, *reason; + int line, flags; + +#ifdef HAVE_ERR_GET_ERROR_ALL + while ((e = ERR_get_error_all(&file, &line, &func, &data, &flags))) { +#else + while ((e = ERR_get_error_line_data(&file, &line, &data, &flags))) { + func = ERR_func_error_string(e); +#endif + lib = ERR_lib_error_string(e); + reason = ERR_reason_error_string(e); + + VALUE str = rb_sprintf("error:%08lX:%s:%s:%s", e, lib ? lib : "", + func ? func : "", reason ? reason : ""); + if (flags & ERR_TXT_STRING) { + if (!data) + data = "(null)"; + rb_str_catf(str, " (%s)", data); + } + + if (dOSSL == Qtrue) + rb_warn("error on stack: %"PRIsVALUE, str); + if (!NIL_P(ary)) + rb_ary_push(ary, str); + } + } + else { + ERR_clear_error(); + } +} + +void +ossl_clear_error(void) +{ + collect_errors_into(Qnil); +} + +/* + * call-seq: + * ossl_error.detailed_message(**) -> string + * + * Returns the exception message decorated with the captured \OpenSSL error + * queue entries. + */ +static VALUE +osslerror_detailed_message(int argc, VALUE *argv, VALUE self) +{ + VALUE str; +#ifdef HAVE_RB_CALL_SUPER_KW + // Ruby >= 3.2 + if (RTEST(rb_funcall(rb_eException, rb_intern("method_defined?"), 1, + ID2SYM(rb_intern("detailed_message"))))) + str = rb_call_super_kw(argc, argv, RB_PASS_CALLED_KEYWORDS); + else +#endif + str = rb_funcall(self, rb_intern("message"), 0); + VALUE errors = rb_attr_get(self, id_i_errors); + + // OpenSSLError was not created by ossl_make_error() + if (!RB_TYPE_P(errors, T_ARRAY)) + return str; + + str = rb_str_resurrect(str); + rb_str_catf(str, "\nOpenSSL error queue reported %ld errors:", + RARRAY_LEN(errors)); + for (long i = 0; i < RARRAY_LEN(errors); i++) { + VALUE err = RARRAY_AREF(errors, i); + rb_str_catf(str, "\n%"PRIsVALUE, err); + } + return str; } /* * call-seq: * OpenSSL.errors -> [String...] * - * See any remaining errors held in queue. + * Returns any remaining errors held in the \OpenSSL thread-local error queue + * and clears the queue. This should normally return an empty array. + * + * This is intended for debugging Ruby/OpenSSL. If you see any errors here, + * it likely indicates a bug in the extension. Please file an issue at + * https://github.com/ruby/openssl. * - * Any errors you see here are probably due to a bug in ruby's OpenSSL implementation. + * For debugging your program, OpenSSL.debug= may be useful. */ -VALUE -ossl_get_errors(void) +static VALUE +ossl_get_errors(VALUE _) { VALUE ary; long e; @@ -379,25 +416,11 @@ ossl_get_errors(void) */ VALUE dOSSL; -#if !defined(HAVE_VA_ARGS_MACRO) -void -ossl_debug(const char *fmt, ...) -{ - va_list args; - - if (dOSSL == Qtrue) { - fprintf(stderr, "OSSL_DEBUG: "); - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - fprintf(stderr, " [CONTEXT N/A]\n"); - } -} -#endif - /* * call-seq: * OpenSSL.debug -> true | false + * + * Returns whether Ruby/OpenSSL's debug mode is currently enabled. */ static VALUE ossl_debug_get(VALUE self) @@ -407,154 +430,117 @@ ossl_debug_get(VALUE self) /* * call-seq: - * OpenSSL.debug = boolean -> boolean + * OpenSSL.debug = boolean * - * Turns on or off CRYPTO_MEM_CHECK. - * Also shows some debugging message on stderr. + * Turns on or off debug mode. With debug mode, all errors added to the \OpenSSL + * error queue will be printed to stderr. */ static VALUE ossl_debug_set(VALUE self, VALUE val) { - VALUE old = dOSSL; - dOSSL = val; - - if (old != dOSSL) { - if (dOSSL == Qtrue) { - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); - fprintf(stderr, "OSSL_DEBUG: IS NOW ON!\n"); - } else if (old == Qtrue) { - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF); - fprintf(stderr, "OSSL_DEBUG: IS NOW OFF!\n"); - } - } + dOSSL = RTEST(val) ? Qtrue : Qfalse; + return val; } /* * call-seq: - * OpenSSL.fips_mode = boolean -> boolean + * OpenSSL.fips_mode -> true | false + * + * Returns whether the FIPS mode is currently enabled. + */ +static VALUE +ossl_fips_mode_get(VALUE self) +{ + +#if OSSL_OPENSSL_PREREQ(3, 0, 0) + VALUE enabled; + enabled = EVP_default_properties_is_fips_enabled(NULL) ? Qtrue : Qfalse; + return enabled; +#elif defined(OPENSSL_FIPS) || defined(OPENSSL_IS_AWSLC) + VALUE enabled; + enabled = FIPS_mode() ? Qtrue : Qfalse; + return enabled; +#else + return Qfalse; +#endif +} + +/* + * call-seq: + * OpenSSL.fips_mode = boolean * * Turns FIPS mode on or off. Turning on FIPS mode will obviously only have an - * effect for FIPS-capable installations of the OpenSSL library. Trying to do + * effect for FIPS-capable installations of the \OpenSSL library. Trying to do * so otherwise will result in an error. * * === Examples - * - * OpenSSL.fips_mode = true # turn FIPS mode on - * OpenSSL.fips_mode = false # and off again + * OpenSSL.fips_mode = true # turn FIPS mode on + * OpenSSL.fips_mode = false # and off again */ static VALUE ossl_fips_mode_set(VALUE self, VALUE enabled) { - -#ifdef HAVE_OPENSSL_FIPS +#if OSSL_OPENSSL_PREREQ(3, 0, 0) if (RTEST(enabled)) { - int mode = FIPS_mode(); - if(!mode && !FIPS_mode_set(1)) /* turning on twice leads to an error */ - ossl_raise(eOSSLError, "Turning on FIPS mode failed"); + if (!EVP_default_properties_enable_fips(NULL, 1)) { + ossl_raise(eOSSLError, "Turning on FIPS mode failed"); + } } else { - if(!FIPS_mode_set(0)) /* turning off twice is OK */ - ossl_raise(eOSSLError, "Turning off FIPS mode failed"); + if (!EVP_default_properties_enable_fips(NULL, 0)) { + ossl_raise(eOSSLError, "Turning off FIPS mode failed"); + } + } + return enabled; +#elif defined(OPENSSL_FIPS) || defined(OPENSSL_IS_AWSLC) + if (RTEST(enabled)) { + int mode = FIPS_mode(); + if(!mode && !FIPS_mode_set(1)) /* turning on twice leads to an error */ + ossl_raise(eOSSLError, "Turning on FIPS mode failed"); + } else { + if(!FIPS_mode_set(0)) /* turning off twice is OK */ + ossl_raise(eOSSLError, "Turning off FIPS mode failed"); } return enabled; #else if (RTEST(enabled)) - ossl_raise(eOSSLError, "This version of OpenSSL does not support FIPS mode"); + ossl_raise(eOSSLError, "This version of OpenSSL does not support FIPS mode"); return enabled; #endif } -/** - * Stores locks needed for OpenSSL thread safety +/* + * call-seq: + * OpenSSL.fixed_length_secure_compare(string, string) -> true or false + * + * Constant time memory comparison for fixed length strings, such as results + * of \HMAC calculations. + * + * Returns +true+ if the strings are identical, +false+ if they are of the same + * length but not identical. If the length is different, ArgumentError is + * raised. */ -#include "ruby/thread_native.h" -static rb_nativethread_lock_t *ossl_locks; - -static void -ossl_lock_unlock(int mode, rb_nativethread_lock_t *lock) -{ - if (mode & CRYPTO_LOCK) { - rb_nativethread_lock_lock(lock); - } else { - rb_nativethread_lock_unlock(lock); - } -} - -static void -ossl_lock_callback(int mode, int type, const char *file, int line) -{ - ossl_lock_unlock(mode, &ossl_locks[type]); -} - -struct CRYPTO_dynlock_value { - rb_nativethread_lock_t lock; -}; - -static struct CRYPTO_dynlock_value * -ossl_dyn_create_callback(const char *file, int line) -{ - struct CRYPTO_dynlock_value *dynlock = (struct CRYPTO_dynlock_value *)OPENSSL_malloc((int)sizeof(struct CRYPTO_dynlock_value)); - rb_nativethread_lock_initialize(&dynlock->lock); - return dynlock; -} - -static void -ossl_dyn_lock_callback(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line) -{ - ossl_lock_unlock(mode, &l->lock); -} - -static void -ossl_dyn_destroy_callback(struct CRYPTO_dynlock_value *l, const char *file, int line) -{ - rb_nativethread_lock_destroy(&l->lock); - OPENSSL_free(l); -} - -#ifdef HAVE_CRYPTO_THREADID_PTR -static void ossl_threadid_func(CRYPTO_THREADID *id) -{ - /* register native thread id */ - CRYPTO_THREADID_set_pointer(id, (void *)rb_nativethread_self()); -} -#else -static unsigned long ossl_thread_id(void) -{ - /* before OpenSSL 1.0, this is 'unsigned long' */ - return (unsigned long)rb_nativethread_self(); -} -#endif - -static void Init_ossl_locks(void) +static VALUE +ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2) { - int i; - int num_locks = CRYPTO_num_locks(); + const unsigned char *p1 = (const unsigned char *)StringValuePtr(str1); + const unsigned char *p2 = (const unsigned char *)StringValuePtr(str2); + long len1 = RSTRING_LEN(str1); + long len2 = RSTRING_LEN(str2); - if ((unsigned)num_locks >= INT_MAX / (int)sizeof(VALUE)) { - rb_raise(rb_eRuntimeError, "CRYPTO_num_locks() is too big: %d", num_locks); - } - ossl_locks = (rb_nativethread_lock_t *) OPENSSL_malloc(num_locks * (int)sizeof(rb_nativethread_lock_t)); - if (!ossl_locks) { - rb_raise(rb_eNoMemError, "CRYPTO_num_locks() is too big: %d", num_locks); - } - for (i = 0; i < num_locks; i++) { - rb_nativethread_lock_initialize(&ossl_locks[i]); + if (len1 != len2) { + ossl_raise(rb_eArgError, "inputs must be of equal length"); } -#ifdef HAVE_CRYPTO_THREADID_PTR - CRYPTO_THREADID_set_callback(ossl_threadid_func); -#else - CRYPTO_set_id_callback(ossl_thread_id); -#endif - CRYPTO_set_locking_callback(ossl_lock_callback); - CRYPTO_set_dynlock_create_callback(ossl_dyn_create_callback); - CRYPTO_set_dynlock_lock_callback(ossl_dyn_lock_callback); - CRYPTO_set_dynlock_destroy_callback(ossl_dyn_destroy_callback); + switch (CRYPTO_memcmp(p1, p2, len1)) { + case 0: return Qtrue; + default: return Qfalse; + } } /* - * OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the - * OpenSSL[http://www.openssl.org/] library. + * OpenSSL provides \SSL, TLS and general purpose cryptography. It wraps the + * OpenSSL[https://www.openssl.org/] library. * * = Examples * @@ -574,23 +560,21 @@ static void Init_ossl_locks(void) * * key = OpenSSL::PKey::RSA.new 2048 * - * open 'private_key.pem', 'w' do |io| io.write key.to_pem end - * open 'public_key.pem', 'w' do |io| io.write key.public_key.to_pem end + * File.write 'private_key.pem', key.private_to_pem + * File.write 'public_key.pem', key.public_to_pem * * === Exporting a Key * * Keys saved to disk without encryption are not secure as anyone who gets * ahold of the key may use it unless it is encrypted. In order to securely - * export a key you may export it with a pass phrase. + * export a key you may export it with a password. * - * cipher = OpenSSL::Cipher.new 'AES-128-CBC' - * pass_phrase = 'my secure pass phrase goes here' + * cipher = OpenSSL::Cipher.new 'aes-256-cbc' + * password = 'my secure password goes here' * - * key_secure = key.export cipher, pass_phrase + * key_secure = key.private_to_pem cipher, password * - * open 'private.secure.pem', 'w' do |io| - * io.write key_secure - * end + * File.write 'private.secure.pem', key_secure * * OpenSSL::Cipher.ciphers returns a list of available ciphers. * @@ -598,22 +582,25 @@ static void Init_ossl_locks(void) * * A key can also be loaded from a file. * - * key2 = OpenSSL::PKey::RSA.new File.read 'private_key.pem' + * key2 = OpenSSL::PKey.read File.read 'private_key.pem' * key2.public? # => true + * key2.private? # => true * * or * - * key3 = OpenSSL::PKey::RSA.new File.read 'public_key.pem' + * key3 = OpenSSL::PKey.read File.read 'public_key.pem' + * key3.public? # => true * key3.private? # => false * * === Loading an Encrypted Key * - * OpenSSL will prompt you for your pass phrase when loading an encrypted key. - * If you will not be able to type in the pass phrase you may provide it when + * \OpenSSL will prompt you for your password when loading an encrypted key. + * If you will not be able to type in the password you may provide it when * loading the key: * * key4_pem = File.read 'private.secure.pem' - * key4 = OpenSSL::PKey::RSA.new key4_pem, pass_phrase + * password = 'my secure password goes here' + * key4 = OpenSSL::PKey.read key4_pem, password * * == RSA Encryption * @@ -655,16 +642,14 @@ static void Init_ossl_locks(void) * To sign a document, a cryptographically secure hash of the document is * computed first, which is then signed using the private key. * - * digest = OpenSSL::Digest::SHA256.new - * signature = key.sign digest, document + * signature = key.sign 'SHA256', document * * To validate the signature, again a hash of the document is computed and * the signature is decrypted using the public key. The result is then * compared to the hash just computed, if they are equal the signature was * valid. * - * digest = OpenSSL::Digest::SHA256.new - * if key.verify digest, signature, document + * if key.verify 'SHA256', signature, document * puts 'Valid' * else * puts 'Invalid' @@ -672,7 +657,7 @@ static void Init_ossl_locks(void) * * == PBKDF2 Password-based Encryption * - * If supported by the underlying OpenSSL version used, Password-based + * If supported by the underlying \OpenSSL version used, Password-based * Encryption should use the features of PKCS5. If not supported or if * required by legacy applications, the older, less secure methods specified * in RFC 2898 are also supported (see below). @@ -690,7 +675,7 @@ static void Init_ossl_locks(void) * using PBKDF2. PKCS #5 v2.0 recommends at least 8 bytes for the salt, * the number of iterations largely depends on the hardware being used. * - * cipher = OpenSSL::Cipher.new 'AES-128-CBC' + * cipher = OpenSSL::Cipher.new 'aes-256-cbc' * cipher.encrypt * iv = cipher.random_iv * @@ -698,7 +683,7 @@ static void Init_ossl_locks(void) * salt = OpenSSL::Random.random_bytes 16 * iter = 20000 * key_len = cipher.key_len - * digest = OpenSSL::Digest::SHA256.new + * digest = OpenSSL::Digest.new('SHA256') * * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest) * cipher.key = key @@ -713,7 +698,7 @@ static void Init_ossl_locks(void) * Use the same steps as before to derive the symmetric AES key, this time * setting the Cipher up for decryption. * - * cipher = OpenSSL::Cipher.new 'AES-128-CBC' + * cipher = OpenSSL::Cipher.new 'aes-256-cbc' * cipher.decrypt * cipher.iv = iv # the one generated with #random_iv * @@ -721,7 +706,7 @@ static void Init_ossl_locks(void) * salt = ... # the one generated above * iter = 20000 * key_len = cipher.key_len - * digest = OpenSSL::Digest::SHA256.new + * digest = OpenSSL::Digest.new('SHA256') * * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest) * cipher.key = key @@ -731,53 +716,15 @@ static void Init_ossl_locks(void) * decrypted = cipher.update encrypted * decrypted << cipher.final * - * == PKCS #5 Password-based Encryption - * - * PKCS #5 is a password-based encryption standard documented at - * RFC2898[http://www.ietf.org/rfc/rfc2898.txt]. It allows a short password or - * passphrase to be used to create a secure encryption key. If possible, PBKDF2 - * as described above should be used if the circumstances allow it. - * - * PKCS #5 uses a Cipher, a pass phrase and a salt to generate an encryption - * key. - * - * pass_phrase = 'my secure pass phrase goes here' - * salt = '8 octets' - * - * === Encryption - * - * First set up the cipher for encryption - * - * encryptor = OpenSSL::Cipher.new 'AES-128-CBC' - * encryptor.encrypt - * encryptor.pkcs5_keyivgen pass_phrase, salt - * - * Then pass the data you want to encrypt through - * - * encrypted = encryptor.update 'top secret document' - * encrypted << encryptor.final - * - * === Decryption - * - * Use a new Cipher instance set up for decryption - * - * decryptor = OpenSSL::Cipher.new 'AES-128-CBC' - * decryptor.decrypt - * decryptor.pkcs5_keyivgen pass_phrase, salt - * - * Then pass the data you want to decrypt through - * - * plain = decryptor.update encrypted - * plain << decryptor.final - * - * == X509 Certificates + * == \X509 Certificates * * === Creating a Certificate * * This example creates a self-signed certificate using an RSA key and a SHA1 * signature. * - * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example' + * key = OpenSSL::PKey::RSA.new 2048 + * name = OpenSSL::X509::Name.parse '/CN=nobody/DC=example' * * cert = OpenSSL::X509::Certificate.new * cert.version = 2 @@ -806,7 +753,7 @@ static void Init_ossl_locks(void) * extension_factory.create_extension('subjectKeyIdentifier', 'hash') * * The list of supported extensions (and in some cases their possible values) - * can be derived from the "objects.h" file in the OpenSSL source code. + * can be derived from the "objects.h" file in the \OpenSSL source code. * * === Signing a Certificate * @@ -816,7 +763,7 @@ static void Init_ossl_locks(void) * certificate. * * cert.issuer = name - * cert.sign key, OpenSSL::Digest::SHA1.new + * cert.sign key, OpenSSL::Digest.new('SHA1') * * open 'certificate.pem', 'w' do |io| io.write cert.to_pem end * @@ -846,11 +793,12 @@ static void Init_ossl_locks(void) * not readable by other users. * * ca_key = OpenSSL::PKey::RSA.new 2048 + * password = 'my secure password goes here' * - * cipher = OpenSSL::Cipher::Cipher.new 'AES-128-CBC' + * cipher = 'aes-256-cbc' * * open 'ca_key.pem', 'w', 0400 do |io| - * io.write ca_key.export(cipher, pass_phrase) + * io.write ca_key.private_to_pem(cipher, password) * end * * === CA Certificate @@ -858,7 +806,7 @@ static void Init_ossl_locks(void) * A CA certificate is created the same way we created a certificate above, but * with different extensions. * - * ca_name = OpenSSL::X509::Name.parse 'CN=ca/DC=example' + * ca_name = OpenSSL::X509::Name.parse '/CN=ca/DC=example' * * ca_cert = OpenSSL::X509::Certificate.new * ca_cert.serial = 0 @@ -891,7 +839,7 @@ static void Init_ossl_locks(void) * * Root CA certificates are self-signed. * - * ca_cert.sign ca_key, OpenSSL::Digest::SHA1.new + * ca_cert.sign ca_key, OpenSSL::Digest.new('SHA1') * * The CA certificate is saved to disk so it may be distributed to all the * users of the keys this CA will sign. @@ -909,7 +857,7 @@ static void Init_ossl_locks(void) * csr.version = 0 * csr.subject = name * csr.public_key = key.public_key - * csr.sign key, OpenSSL::Digest::SHA1.new + * csr.sign key, OpenSSL::Digest.new('SHA1') * * A CSR is saved to disk and sent to the CA for signing. * @@ -953,29 +901,29 @@ static void Init_ossl_locks(void) * csr_cert.add_extension \ * extension_factory.create_extension('subjectKeyIdentifier', 'hash') * - * csr_cert.sign ca_key, OpenSSL::Digest::SHA1.new + * csr_cert.sign ca_key, OpenSSL::Digest.new('SHA1') * * open 'csr_cert.pem', 'w' do |io| * io.write csr_cert.to_pem * end * - * == SSL and TLS Connections + * == \SSL and TLS Connections * - * Using our created key and certificate we can create an SSL or TLS connection. - * An SSLContext is used to set up an SSL session. + * Using our created key and certificate we can create an \SSL or TLS + * connection. An OpenSSL::SSL::SSLContext is used to set up an \SSL session. * * context = OpenSSL::SSL::SSLContext.new * - * === SSL Server + * === \SSL Server * - * An SSL server requires the certificate and private key to communicate + * An \SSL server requires the certificate and private key to communicate * securely with its clients: * * context.cert = cert * context.key = key * - * Then create an SSLServer with a TCP server socket and the context. Use the - * SSLServer like an ordinary TCP server. + * Then create an OpenSSL::SSL::SSLServer with a TCP server socket and the + * context. Use the SSLServer like an ordinary TCP server. * * require 'socket' * @@ -985,33 +933,40 @@ static void Init_ossl_locks(void) * loop do * ssl_connection = ssl_server.accept * - * data = connection.gets + * data = ssl_connection.gets * * response = "I got #{data.dump}" * puts response * - * connection.puts "I got #{data.dump}" - * connection.close + * ssl_connection.puts "I got #{data.dump}" + * ssl_connection.close * end * - * === SSL client + * === \SSL client * - * An SSL client is created with a TCP socket and the context. - * SSLSocket#connect must be called to initiate the SSL handshake and start - * encryption. A key and certificate are not required for the client socket. + * An \SSL client is created with a TCP socket and the context. + * OpenSSL::SSL::SSLSocket#connect must be called to initiate the \SSL handshake + * and start encryption. A key and certificate are not required for the client + * socket. + * + * Note that OpenSSL::SSL::SSLSocket#close doesn't close the underlying socket + * by default. Set OpenSSL::SSL::SSLSocket#sync_close to true if you want. * * require 'socket' * - * tcp_client = TCPSocket.new 'localhost', 5000 - * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context + * tcp_socket = TCPSocket.new 'localhost', 5000 + * ssl_client = OpenSSL::SSL::SSLSocket.new tcp_socket, context + * ssl_client.sync_close = true * ssl_client.connect * * ssl_client.puts "hello server!" * puts ssl_client.gets * + * ssl_client.close # shutdown the TLS connection and close tcp_socket + * * === Peer Verification * - * An unverified SSL connection does not provide much security. For enhanced + * An unverified \SSL connection does not provide much security. For enhanced * security the client or server can verify the certificate of its peer. * * The client can be modified to verify the server's certificate against the @@ -1022,8 +977,8 @@ static void Init_ossl_locks(void) * * require 'socket' * - * tcp_client = TCPSocket.new 'localhost', 5000 - * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context + * tcp_socket = TCPSocket.new 'localhost', 5000 + * ssl_client = OpenSSL::SSL::SSLSocket.new tcp_socket, context * ssl_client.connect * * ssl_client.puts "hello server!" @@ -1036,6 +991,11 @@ static void Init_ossl_locks(void) void Init_openssl(void) { +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + +#undef rb_intern /* * Init timezone info */ @@ -1046,76 +1006,109 @@ Init_openssl(void) /* * Init all digests, ciphers */ - /* CRYPTO_malloc_init(); */ - /* ENGINE_load_builtin_engines(); */ - OpenSSL_add_ssl_algorithms(); - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); - SSL_load_error_strings(); - - /* - * FIXME: - * On unload do: - */ -#if 0 - CONF_modules_unload(1); - destroy_ui_method(); - EVP_cleanup(); - ENGINE_cleanup(); - CRYPTO_cleanup_all_ex_data(); - ERR_remove_state(0); - ERR_free_strings(); -#endif + if (!OPENSSL_init_ssl(0, NULL)) + rb_raise(rb_eRuntimeError, "OPENSSL_init_ssl"); /* * Init main module */ - mOSSL = rb_define_module("OpenSSL"); rb_global_variable(&mOSSL); + mOSSL = rb_define_module("OpenSSL"); + rb_define_singleton_method(mOSSL, "fixed_length_secure_compare", ossl_crypto_fixed_length_secure_compare, 2); /* - * OpenSSL ruby extension version + * \OpenSSL library version string used to compile the Ruby/OpenSSL + * extension. This may differ from the version used at runtime. */ - rb_define_const(mOSSL, "VERSION", rb_str_new2(OSSL_VERSION)); + rb_define_const(mOSSL, "OPENSSL_VERSION", + rb_obj_freeze(rb_str_new_cstr(OPENSSL_VERSION_TEXT))); /* - * Version of OpenSSL the ruby OpenSSL extension was built with + * \OpenSSL library version string currently used at runtime. */ - rb_define_const(mOSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT)); + rb_define_const( + mOSSL, + "OPENSSL_LIBRARY_VERSION", + rb_obj_freeze(rb_str_new_cstr(OpenSSL_version(OPENSSL_VERSION))) + ); /* - * Version of OpenSSL the ruby OpenSSL extension is running with + * \OpenSSL library version number used to compile the Ruby/OpenSSL + * extension. This may differ from the version used at runtime. + * + * The version number is encoded into a single integer value. The number + * follows the format: + * + * [\OpenSSL 3.0.0 or later] + * <tt>0xMNN00PP0</tt> (major minor 00 patch 0) + * [\OpenSSL 1.1.1 or earlier] + * <tt>0xMNNFFPPS</tt> (major minor fix patch status) + * [LibreSSL] + * <tt>0x20000000</tt> (a fixed value) + * + * See also the man page OPENSSL_VERSION_NUMBER(3). */ - rb_define_const(mOSSL, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION))); + rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER)); +#if defined(LIBRESSL_VERSION_NUMBER) /* - * Version number of OpenSSL the ruby OpenSSL extension was built with - * (base 16) + * LibreSSL library version number used to compile the Ruby/OpenSSL + * extension. This may differ from the version used at runtime. + * + * This constant is only defined if the extension was compiled against + * LibreSSL. The number follows the format: + * <tt>0xMNNFF00f</tt> (major minor fix 00 status). + * + * See also the man page LIBRESSL_VERSION_NUMBER(3). */ - rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER)); + rb_define_const(mOSSL, "LIBRESSL_VERSION_NUMBER", INT2NUM(LIBRESSL_VERSION_NUMBER)); +#endif /* - * Boolean indicating whether OpenSSL is FIPS-enabled or not + * Boolean indicating whether the \OpenSSL library is FIPS-capable or not. + * Always <tt>true</tt> for \OpenSSL 3.0 and later. + * + * This is obsolete and will be removed in the future. + * See also OpenSSL.fips_mode. */ -#ifdef HAVE_OPENSSL_FIPS - rb_define_const(mOSSL, "OPENSSL_FIPS", Qtrue); + rb_define_const(mOSSL, "OPENSSL_FIPS", +/* OpenSSL 3 is FIPS-capable even when it is installed without fips option */ +#if OSSL_OPENSSL_PREREQ(3, 0, 0) + Qtrue +#elif defined(OPENSSL_FIPS) + Qtrue +#elif defined(OPENSSL_IS_AWSLC) // AWS-LC FIPS can only be enabled during compile time. + FIPS_mode() ? Qtrue : Qfalse #else - rb_define_const(mOSSL, "OPENSSL_FIPS", Qfalse); + Qfalse #endif + ); + + rb_define_module_function(mOSSL, "fips_mode", ossl_fips_mode_get, 0); rb_define_module_function(mOSSL, "fips_mode=", ossl_fips_mode_set, 1); + rb_global_variable(&eOSSLError); /* - * Generic error, - * common for all classes under OpenSSL module + * Generic error class for OpenSSL. All error classes in this library + * inherit from this class. + * + * This class indicates that an error was reported by the underlying + * \OpenSSL library. */ - eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError); - rb_global_variable(&eOSSLError); - + eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError); /* - * Verify callback Proc index for ext-data + * \OpenSSL error queue entries captured at the time the exception was + * raised. The same information is printed to stderr if OpenSSL.debug is + * set to +true+. + * + * This is an array of zero or more strings, ordered from the oldest to the + * newest. The format of the strings is not stable and may vary across + * versions of \OpenSSL or versions of this Ruby extension. + * + * See also the man page ERR_get_error(3). */ - if ((ossl_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"ossl_verify_cb_idx", 0, 0, 0)) < 0) - ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index"); + rb_attr(eOSSLError, rb_intern_const("errors"), 1, 0, 0); + rb_define_method(eOSSLError, "detailed_message", osslerror_detailed_message, -1); /* * Init debug core @@ -1131,38 +1124,27 @@ Init_openssl(void) * Get ID of to_der */ ossl_s_to_der = rb_intern("to_der"); - - Init_ossl_locks(); + id_i_errors = rb_intern("@errors"); /* * Init components */ + Init_ossl_asn1(); Init_ossl_bn(); Init_ossl_cipher(); Init_ossl_config(); Init_ossl_digest(); + Init_ossl_engine(); Init_ossl_hmac(); + Init_ossl_kdf(); Init_ossl_ns_spki(); + Init_ossl_ocsp(); Init_ossl_pkcs12(); Init_ossl_pkcs7(); - Init_ossl_pkcs5(); Init_ossl_pkey(); + Init_ossl_provider(); Init_ossl_rand(); Init_ossl_ssl(); + Init_ossl_ts(); Init_ossl_x509(); - Init_ossl_ocsp(); - Init_ossl_engine(); - Init_ossl_asn1(); } - -#if defined(OSSL_DEBUG) -/* - * Check if all symbols are OK with 'make LDSHARED=gcc all' - */ -int -main(int argc, char *argv[]) -{ - return 0; -} -#endif /* OSSL_DEBUG */ - diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index c843c06f5c..0b479a7200 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -1,84 +1,82 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(_OSSL_H_) #define _OSSL_H_ #include RUBY_EXTCONF_H -#if defined(__cplusplus) -extern "C" { -#endif - -#if 0 - mOSSL = rb_define_module("OpenSSL"); - mX509 = rb_define_module_under(mOSSL, "X509"); -#endif - -/* -* OpenSSL has defined RFILE and Ruby has defined RFILE - so undef it! -*/ -#if defined(RFILE) /*&& !defined(OSSL_DEBUG)*/ -# undef RFILE -#endif +#include <assert.h> #include <ruby.h> +#include <errno.h> #include <ruby/io.h> #include <ruby/thread.h> - -/* - * Check the OpenSSL version - * The only supported are: - * OpenSSL >= 0.9.7 - */ -#include <openssl/opensslv.h> - -#ifdef HAVE_ASSERT_H -# include <assert.h> +#ifdef HAVE_RUBY_RACTOR_H +#include <ruby/ractor.h> #else -# define assert(condition) +#define RUBY_TYPED_FROZEN_SHAREABLE 0 #endif -#if defined(_WIN32) -# include <openssl/e_os2.h> -# define OSSL_NO_CONF_API 1 -# if !defined(OPENSSL_SYS_WIN32) -# define OPENSSL_SYS_WIN32 1 -# endif -# include <winsock2.h> -#endif -#include <errno.h> +#include <openssl/opensslv.h> + #include <openssl/err.h> -#include <openssl/asn1_mac.h> +#include <openssl/asn1.h> #include <openssl/x509v3.h> #include <openssl/ssl.h> #include <openssl/pkcs12.h> #include <openssl/pkcs7.h> -#include <openssl/hmac.h> #include <openssl/rand.h> #include <openssl/conf.h> -#include <openssl/conf_api.h> -#undef X509_NAME -#undef PKCS7_SIGNER_INFO -#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_EVP_CIPHER_CTX_ENGINE) -# define OSSL_ENGINE_ENABLED -# include <openssl/engine.h> +#ifndef OPENSSL_NO_TS + #include <openssl/ts.h> #endif -#if defined(HAVE_OPENSSL_OCSP_H) -# define OSSL_OCSP_ENABLED +#include <openssl/crypto.h> +#if !defined(OPENSSL_NO_OCSP) # include <openssl/ocsp.h> #endif +#include <openssl/bn.h> +#include <openssl/rsa.h> +#include <openssl/dsa.h> +#include <openssl/evp.h> +#include <openssl/dh.h> +#include "openssl_missing.h" -/* OpenSSL requires passwords for PEM-encoded files to be at least four - * characters long - */ -#define OSSL_MIN_PWD_LEN 4 +#ifndef LIBRESSL_VERSION_NUMBER +# define OSSL_IS_LIBRESSL 0 +# define OSSL_OPENSSL_PREREQ(maj, min, pat) \ + (OPENSSL_VERSION_NUMBER >= ((maj << 28) | (min << 20) | (pat << 12))) +# define OSSL_LIBRESSL_PREREQ(maj, min, pat) 0 +#else +# define OSSL_IS_LIBRESSL 1 +# define OSSL_OPENSSL_PREREQ(maj, min, pat) 0 +# define OSSL_LIBRESSL_PREREQ(maj, min, pat) \ + (LIBRESSL_VERSION_NUMBER >= ((maj << 28) | (min << 20) | (pat << 12))) +#endif + +#if OSSL_OPENSSL_PREREQ(3, 0, 0) +# define OSSL_3_const const +#else +# define OSSL_3_const /* const */ +#endif + +#if !defined(OPENSSL_NO_ENGINE) && !OSSL_OPENSSL_PREREQ(3, 0, 0) +# define OSSL_USE_ENGINE +#endif + +#if OSSL_OPENSSL_PREREQ(3, 0, 0) +# define OSSL_USE_PROVIDER +# include <openssl/provider.h> +#endif + +#if OSSL_OPENSSL_PREREQ(3, 0, 0) +# define OSSL_HAVE_IMMUTABLE_PKEY +#endif /* * Common Module @@ -94,92 +92,79 @@ extern VALUE eOSSLError; * CheckTypes */ #define OSSL_Check_Kind(obj, klass) do {\ - if (!rb_obj_is_kind_of((obj), (klass))) {\ - ossl_raise(rb_eTypeError, "wrong argument (%"PRIsVALUE")! (Expected kind of %"PRIsVALUE")",\ - rb_obj_class(obj), (klass));\ - }\ -} while (0) - -#define OSSL_Check_Instance(obj, klass) do {\ - if (!rb_obj_is_instance_of((obj), (klass))) {\ - ossl_raise(rb_eTypeError, "wrong argument (%"PRIsVALUE")! (Expected instance of %"PRIsVALUE")",\ - rb_obj_class(obj), (klass));\ - }\ -} while (0) - -#define OSSL_Check_Same_Class(obj1, obj2) do {\ - if (!rb_obj_is_instance_of((obj1), rb_obj_class(obj2))) {\ - ossl_raise(rb_eTypeError, "wrong argument type");\ - }\ + if (!rb_obj_is_kind_of((obj), (klass))) {\ + ossl_raise(rb_eTypeError, "wrong argument (%"PRIsVALUE")! (Expected kind of %"PRIsVALUE")",\ + rb_obj_class(obj), (klass));\ + }\ } while (0) /* - * Compatibility + * Type conversions */ -#if OPENSSL_VERSION_NUMBER >= 0x10000000L -#define STACK _STACK +#if !defined(NUM2UINT64T) /* in case Ruby starts to provide */ +# if SIZEOF_LONG == 8 +# define NUM2UINT64T(x) ((uint64_t)NUM2ULONG(x)) +# elif defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8 +# define NUM2UINT64T(x) ((uint64_t)NUM2ULL(x)) +# else +# error "unknown platform; no 64-bit width integer" +# endif #endif /* - * String to HEXString conversion - */ -int string2hex(const unsigned char *, int, char **, int *); - -/* * Data Conversion */ -STACK_OF(X509) *ossl_x509_ary2sk0(VALUE); STACK_OF(X509) *ossl_x509_ary2sk(VALUE); STACK_OF(X509) *ossl_protect_x509_ary2sk(VALUE,int*); -VALUE ossl_x509_sk2ary(STACK_OF(X509) *certs); -VALUE ossl_x509crl_sk2ary(STACK_OF(X509_CRL) *crl); -VALUE ossl_x509name_sk2ary(STACK_OF(X509_NAME) *names); +VALUE ossl_x509_sk2ary(const STACK_OF(X509) *certs); +VALUE ossl_x509crl_sk2ary(const STACK_OF(X509_CRL) *crl); +VALUE ossl_x509name_sk2ary(const STACK_OF(X509_NAME) *names); VALUE ossl_buf2str(char *buf, int len); +VALUE ossl_str_new(const char *, long, int *); #define ossl_str_adjust(str, p) \ do{\ - long len = RSTRING_LEN(str);\ long newlen = (long)((p) - (unsigned char*)RSTRING_PTR(str));\ - assert(newlen <= len);\ + assert(newlen <= RSTRING_LEN(str));\ rb_str_set_len((str), newlen);\ }while(0) +/* + * Convert binary string to hex string. The caller is responsible for + * ensuring out has (2 * len) bytes of capacity. + */ +void ossl_bin2hex(const unsigned char *in, char *out, size_t len); /* - * our default PEM callback + * Our default PEM callback */ +/* Convert the argument to String and validate the length. Note this may raise. */ +VALUE ossl_pem_passwd_value(VALUE); +/* Can be casted to pem_password_cb. If a password (String) is passed as the + * "arbitrary data" (typically the last parameter of PEM_{read,write}_ + * functions), uses the value. If not, but a block is given, yields to it. + * If not either, fallbacks to PEM_def_callback() which reads from stdin. */ int ossl_pem_passwd_cb(char *, int, int, void *); /* * Clear BIO* with this in PEM/DER fallback scenarios to avoid decoding * errors piling up in OpenSSL::Errors */ -#define OSSL_BIO_reset(bio) (void)BIO_reset((bio)); \ - ERR_clear_error(); +#define OSSL_BIO_reset(bio) do { \ + (void)BIO_reset((bio)); \ + ossl_clear_error(); \ +} while (0) /* * ERRor messages */ -#define OSSL_ErrMsg() ERR_reason_error_string(ERR_get_error()) -NORETURN(void ossl_raise(VALUE, const char *, ...)); -VALUE ossl_exc_new(VALUE, const char *, ...); - -/* - * Verify callback - */ -extern int ossl_verify_cb_idx; - -struct ossl_verify_cb_args { - VALUE proc; - VALUE preverify_ok; - VALUE store_ctx; -}; - -VALUE ossl_call_verify_cb_proc(struct ossl_verify_cb_args *); -int ossl_verify_cb(int, X509_STORE_CTX *); +PRINTF_ARGS(NORETURN(void ossl_raise(VALUE, const char *, ...)), 2, 3); +/* Make exception instance from str and OpenSSL error reason string. */ +VALUE ossl_make_error(VALUE exc, VALUE str); +/* Clear OpenSSL error queue. If dOSSL is set, rb_warn() them. */ +void ossl_clear_error(void); /* * String to DER String */ -extern ID ossl_s_to_der; VALUE ossl_to_der(VALUE); VALUE ossl_to_der_if_possible(VALUE); @@ -188,60 +173,37 @@ VALUE ossl_to_der_if_possible(VALUE); */ extern VALUE dOSSL; -#if defined(HAVE_VA_ARGS_MACRO) #define OSSL_Debug(...) do { \ - if (dOSSL == Qtrue) { \ - fprintf(stderr, "OSSL_DEBUG: "); \ - fprintf(stderr, __VA_ARGS__); \ - fprintf(stderr, " [%s:%d]\n", __FILE__, __LINE__); \ - } \ -} while (0) - -#define OSSL_Warning(fmt, ...) do { \ - OSSL_Debug((fmt), ##__VA_ARGS__); \ - rb_warning((fmt), ##__VA_ARGS__); \ + if (dOSSL == Qtrue) { \ + fprintf(stderr, "OSSL_DEBUG: "); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, " [%s:%d]\n", __FILE__, __LINE__); \ + } \ } while (0) -#define OSSL_Warn(fmt, ...) do { \ - OSSL_Debug((fmt), ##__VA_ARGS__); \ - rb_warn((fmt), ##__VA_ARGS__); \ -} while (0) -#else -void ossl_debug(const char *, ...); -#define OSSL_Debug ossl_debug -#define OSSL_Warning rb_warning -#define OSSL_Warn rb_warn -#endif - /* * Include all parts */ -#include "openssl_missing.h" -#include "ruby_missing.h" #include "ossl_asn1.h" #include "ossl_bio.h" #include "ossl_bn.h" #include "ossl_cipher.h" #include "ossl_config.h" #include "ossl_digest.h" +#include "ossl_engine.h" #include "ossl_hmac.h" +#include "ossl_kdf.h" #include "ossl_ns_spki.h" #include "ossl_ocsp.h" #include "ossl_pkcs12.h" #include "ossl_pkcs7.h" -#include "ossl_pkcs5.h" #include "ossl_pkey.h" +#include "ossl_provider.h" #include "ossl_rand.h" #include "ossl_ssl.h" -#include "ossl_version.h" +#include "ossl_ts.h" #include "ossl_x509.h" -#include "ossl_engine.h" void Init_openssl(void); -#if defined(__cplusplus) -} -#endif - #endif /* _OSSL_H_ */ - diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c index 3a24d17db1..71a87f0463 100644 --- a/ext/openssl/ossl_asn1.c +++ b/ext/openssl/ossl_asn1.c @@ -1,229 +1,211 @@ /* - * $Id$ * 'OpenSSL for Ruby' team members * Copyright (C) 2003 * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#if defined(HAVE_SYS_TIME_H) -# include <sys/time.h> -#elif !defined(NT) && !defined(_WIN32) -struct timeval { - long tv_sec; /* seconds */ - long tv_usec; /* and microseconds */ -}; -#endif +/********/ +/* + * ASN1 module + */ +#define ossl_asn1_get_value(o) rb_attr_get((o),sivVALUE) +#define ossl_asn1_get_tag(o) rb_attr_get((o),sivTAG) +#define ossl_asn1_get_tagging(o) rb_attr_get((o),sivTAGGING) +#define ossl_asn1_get_tag_class(o) rb_attr_get((o),sivTAG_CLASS) +#define ossl_asn1_get_indefinite_length(o) rb_attr_get((o),sivINDEFINITE_LENGTH) -static VALUE join_der(VALUE enumerable); -static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset, - int depth, int yield, long *num_read); -static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self); -static VALUE ossl_asn1eoc_initialize(VALUE self); +#define ossl_asn1_set_value(o,v) rb_ivar_set((o),sivVALUE,(v)) +#define ossl_asn1_set_tag(o,v) rb_ivar_set((o),sivTAG,(v)) +#define ossl_asn1_set_tagging(o,v) rb_ivar_set((o),sivTAGGING,(v)) +#define ossl_asn1_set_tag_class(o,v) rb_ivar_set((o),sivTAG_CLASS,(v)) +#define ossl_asn1_set_indefinite_length(o,v) rb_ivar_set((o),sivINDEFINITE_LENGTH,(v)) + +VALUE mASN1; +static VALUE eASN1Error; + +VALUE cASN1Data; +static VALUE cASN1Primitive; +static VALUE cASN1Constructive; + +static VALUE cASN1EndOfContent; +static VALUE cASN1Boolean; /* BOOLEAN */ +static VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */ +static VALUE cASN1BitString; /* BIT STRING */ +static VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */ +static VALUE cASN1NumericString, cASN1PrintableString; +static VALUE cASN1T61String, cASN1VideotexString; +static VALUE cASN1IA5String, cASN1GraphicString; +static VALUE cASN1ISO64String, cASN1GeneralString; +static VALUE cASN1UniversalString, cASN1BMPString; +static VALUE cASN1Null; /* NULL */ +static VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */ +static VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */ +static VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */ + +static VALUE sym_IMPLICIT, sym_EXPLICIT; +static VALUE sym_UNIVERSAL, sym_APPLICATION, sym_CONTEXT_SPECIFIC, sym_PRIVATE; +static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINDEFINITE_LENGTH, sivUNUSED_BITS; +static ID id_each; /* * DATE conversion */ +static VALUE +time_utc_new(VALUE args) +{ + return rb_funcallv(rb_cTime, rb_intern("utc"), 6, (VALUE *)args); +} + +static VALUE +time_utc_new_rescue(VALUE args, VALUE exc) +{ + rb_raise(eASN1Error, "invalid time"); +} + VALUE -asn1time_to_time(ASN1_TIME *time) +asn1time_to_time(const ASN1_TIME *time) { struct tm tm; - VALUE argv[6]; - int count; - - if (!time || !time->data) return Qnil; - memset(&tm, 0, sizeof(struct tm)); - - switch (time->type) { - case V_ASN1_UTCTIME: - count = sscanf((const char *)time->data, "%2d%2d%2d%2d%2d%2dZ", - &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, - &tm.tm_sec); - - if (count == 5) { - tm.tm_sec = 0; - } else if (count != 6) { - ossl_raise(rb_eTypeError, "bad UTCTIME format: \"%s\"", - time->data); - } - if (tm.tm_year < 69) { - tm.tm_year += 2000; - } else { - tm.tm_year += 1900; - } - break; - case V_ASN1_GENERALIZEDTIME: - if (sscanf((const char *)time->data, "%4d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon, - &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { - ossl_raise(rb_eTypeError, "bad GENERALIZEDTIME format" ); - } - break; - default: - rb_warning("unknown time format"); - return Qnil; - } - argv[0] = INT2NUM(tm.tm_year); - argv[1] = INT2NUM(tm.tm_mon); - argv[2] = INT2NUM(tm.tm_mday); - argv[3] = INT2NUM(tm.tm_hour); - argv[4] = INT2NUM(tm.tm_min); - argv[5] = INT2NUM(tm.tm_sec); - - return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv); + if (!ASN1_TIME_to_tm(time, &tm)) + ossl_raise(eASN1Error, "ASN1_TIME_to_tm"); + + VALUE args[] = { + INT2NUM(tm.tm_year + 1900), + INT2NUM(tm.tm_mon + 1), + INT2NUM(tm.tm_mday), + INT2NUM(tm.tm_hour), + INT2NUM(tm.tm_min), + INT2NUM(tm.tm_sec), + }; + return rb_rescue2(time_utc_new, (VALUE)args, time_utc_new_rescue, Qnil, + rb_eArgError, 0); } -/* - * This function is not exported in Ruby's *.h - */ -extern struct timeval rb_time_timeval(VALUE); +static VALUE +asn1time_to_time_i(VALUE arg) +{ + return asn1time_to_time((ASN1_TIME *)arg); +} -time_t -time_to_time_t(VALUE time) +void +ossl_time_split(VALUE time, time_t *sec, int *days) { - return (time_t)NUM2LONG(rb_Integer(time)); + VALUE num = rb_Integer(time); + + if (FIXNUM_P(num)) { + time_t t = FIX2LONG(num); + *sec = t % 86400; + *days = rb_long2int(t / 86400); + } + else { + *days = NUM2INT(rb_funcall(num, rb_intern("/"), 1, INT2FIX(86400))); + *sec = NUM2TIMET(rb_funcall(num, rb_intern("%"), 1, INT2FIX(86400))); + } } /* * STRING conversion */ VALUE -asn1str_to_str(ASN1_STRING *str) +asn1str_to_str(const ASN1_STRING *str) { - return rb_str_new((const char *)str->data, str->length); + return rb_str_new((const char *)ASN1_STRING_get0_data(str), + ASN1_STRING_length(str)); } /* * ASN1_INTEGER conversions - * TODO: Make a decision what's the right way to do this. */ -#define DO_IT_VIA_RUBY 0 VALUE -asn1integer_to_num(ASN1_INTEGER *ai) +asn1integer_to_num(const ASN1_INTEGER *ai) { BIGNUM *bn; -#if DO_IT_VIA_RUBY - char *txt; -#endif VALUE num; if (!ai) { - ossl_raise(rb_eTypeError, "ASN1_INTEGER is NULL!"); - } - if (!(bn = ASN1_INTEGER_to_BN(ai, NULL))) { - ossl_raise(eOSSLError, NULL); + ossl_raise(rb_eTypeError, "ASN1_INTEGER is NULL!"); } -#if DO_IT_VIA_RUBY - if (!(txt = BN_bn2dec(bn))) { - BN_free(bn); - ossl_raise(eOSSLError, NULL); - } - num = rb_cstr_to_inum(txt, 10, Qtrue); - OPENSSL_free(txt); -#else + if (ASN1_STRING_type(ai) == V_ASN1_ENUMERATED) + bn = ASN1_ENUMERATED_to_BN(ai, NULL); + else + bn = ASN1_INTEGER_to_BN(ai, NULL); + + if (!bn) + ossl_raise(eOSSLError, NULL); num = ossl_bn_new(bn); -#endif BN_free(bn); return num; } -#if DO_IT_VIA_RUBY -ASN1_INTEGER * -num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai) -{ - BIGNUM *bn = NULL; - - if (RTEST(rb_obj_is_kind_of(obj, cBN))) { - bn = GetBNPtr(obj); - } else { - obj = rb_String(obj); - if (!BN_dec2bn(&bn, StringValuePtr(obj))) { - ossl_raise(eOSSLError, NULL); - } - } - if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) { - BN_free(bn); - ossl_raise(eOSSLError, NULL); - } - BN_free(bn); - return ai; -} -#else ASN1_INTEGER * num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai) { BIGNUM *bn; if (NIL_P(obj)) - ossl_raise(rb_eTypeError, "Can't convert nil into Integer"); + ossl_raise(rb_eTypeError, "Can't convert nil into Integer"); bn = GetBNPtr(obj); if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) - ossl_raise(eOSSLError, NULL); + ossl_raise(eOSSLError, NULL); return ai; } -#endif -/********/ +static VALUE +asn1integer_to_num_i(VALUE arg) +{ + return asn1integer_to_num((ASN1_INTEGER *)arg); +} + /* - * ASN1 module + * ASN1_OBJECT conversions */ -#define ossl_asn1_get_value(o) rb_attr_get((o),sivVALUE) -#define ossl_asn1_get_tag(o) rb_attr_get((o),sivTAG) -#define ossl_asn1_get_tagging(o) rb_attr_get((o),sivTAGGING) -#define ossl_asn1_get_tag_class(o) rb_attr_get((o),sivTAG_CLASS) -#define ossl_asn1_get_infinite_length(o) rb_attr_get((o),sivINFINITE_LENGTH) - -#define ossl_asn1_set_value(o,v) rb_ivar_set((o),sivVALUE,(v)) -#define ossl_asn1_set_tag(o,v) rb_ivar_set((o),sivTAG,(v)) -#define ossl_asn1_set_tagging(o,v) rb_ivar_set((o),sivTAGGING,(v)) -#define ossl_asn1_set_tag_class(o,v) rb_ivar_set((o),sivTAG_CLASS,(v)) -#define ossl_asn1_set_infinite_length(o,v) rb_ivar_set((o),sivINFINITE_LENGTH,(v)) - -VALUE mASN1; -VALUE eASN1Error; +VALUE +ossl_asn1obj_to_string_oid(const ASN1_OBJECT *a1obj) +{ + VALUE str; + int len; + + str = rb_usascii_str_new(NULL, 127); + len = OBJ_obj2txt(RSTRING_PTR(str), RSTRING_LENINT(str), a1obj, 1); + if (len <= 0 || len == INT_MAX) + ossl_raise(eOSSLError, "OBJ_obj2txt"); + if (len > RSTRING_LEN(str)) { + /* +1 is for the \0 terminator added by OBJ_obj2txt() */ + rb_str_resize(str, len + 1); + len = OBJ_obj2txt(RSTRING_PTR(str), len + 1, a1obj, 1); + if (len <= 0) + ossl_raise(eOSSLError, "OBJ_obj2txt"); + } + rb_str_set_len(str, len); + return str; +} -VALUE cASN1Data; -VALUE cASN1Primitive; -VALUE cASN1Constructive; - -VALUE cASN1EndOfContent; -VALUE cASN1Boolean; /* BOOLEAN */ -VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */ -VALUE cASN1BitString; /* BIT STRING */ -VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */ -VALUE cASN1NumericString, cASN1PrintableString; -VALUE cASN1T61String, cASN1VideotexString; -VALUE cASN1IA5String, cASN1GraphicString; -VALUE cASN1ISO64String, cASN1GeneralString; -VALUE cASN1UniversalString, cASN1BMPString; -VALUE cASN1Null; /* NULL */ -VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */ -VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */ -VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */ - -static ID sIMPLICIT, sEXPLICIT; -static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE; -static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINFINITE_LENGTH, sivUNUSED_BITS; +VALUE +ossl_asn1obj_to_string(const ASN1_OBJECT *obj) +{ + int nid = OBJ_obj2nid(obj); + if (nid != NID_undef) + return rb_str_new_cstr(OBJ_nid2sn(nid)); + return ossl_asn1obj_to_string_oid(obj); +} -/* - * We need to implement these for backward compatibility - * reasons, behavior of ASN1_put_object and ASN1_object_size - * for infinite length values is different in OpenSSL <= 0.9.7 - */ -#if OPENSSL_VERSION_NUMBER < 0x00908000L -#define ossl_asn1_object_size(cons, len, tag) (cons) == 2 ? (len) + ASN1_object_size((cons), 0, (tag)) : ASN1_object_size((cons), (len), (tag)) -#define ossl_asn1_put_object(pp, cons, len, tag, xc) (cons) == 2 ? ASN1_put_object((pp), (cons), 0, (tag), (xc)) : ASN1_put_object((pp), (cons), (len), (tag), (xc)) -#else -#define ossl_asn1_object_size(cons, len, tag) ASN1_object_size((cons), (len), (tag)) -#define ossl_asn1_put_object(pp, cons, len, tag, xc) ASN1_put_object((pp), (cons), (len), (tag), (xc)) -#endif +VALUE +ossl_asn1obj_to_string_long_name(const ASN1_OBJECT *obj) +{ + int nid = OBJ_obj2nid(obj); + if (nid != NID_undef) + return rb_str_new_cstr(OBJ_nid2ln(nid)); + return ossl_asn1obj_to_string_oid(obj); +} /* * Ruby to ASN1 converters @@ -232,13 +214,9 @@ static ASN1_BOOLEAN obj_to_asn1bool(VALUE obj) { if (NIL_P(obj)) - ossl_raise(rb_eTypeError, "Can't convert nil into Boolean"); + ossl_raise(rb_eTypeError, "Can't convert nil into Boolean"); -#if OPENSSL_VERSION_NUMBER < 0x00907000L - return RTEST(obj) ? 0xff : 0x100; -#else - return RTEST(obj) ? 0xff : 0x0; -#endif + return RTEST(obj) ? 0xff : 0x0; } static ASN1_INTEGER* @@ -252,13 +230,15 @@ obj_to_asn1bstr(VALUE obj, long unused_bits) { ASN1_BIT_STRING *bstr; - if(unused_bits < 0) unused_bits = 0; + if (unused_bits < 0 || unused_bits > 7) + ossl_raise(eASN1Error, "unused_bits for a bitstring value must be in "\ + "the range 0 to 7"); StringValue(obj); if(!(bstr = ASN1_BIT_STRING_new())) - ossl_raise(eASN1Error, NULL); + ossl_raise(eASN1Error, NULL); ASN1_BIT_STRING_set(bstr, (unsigned char *)RSTRING_PTR(obj), RSTRING_LENINT(obj)); bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */ - bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07); + bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT | unused_bits; return bstr; } @@ -270,7 +250,7 @@ obj_to_asn1str(VALUE obj) StringValue(obj); if(!(str = ASN1_STRING_new())) - ossl_raise(eASN1Error, NULL); + ossl_raise(eASN1Error, NULL); ASN1_STRING_set(str, RSTRING_PTR(obj), RSTRING_LENINT(obj)); return str; @@ -282,47 +262,51 @@ obj_to_asn1null(VALUE obj) ASN1_NULL *null; if(!NIL_P(obj)) - ossl_raise(eASN1Error, "nil expected"); + ossl_raise(eASN1Error, "nil expected"); if(!(null = ASN1_NULL_new())) - ossl_raise(eASN1Error, NULL); + ossl_raise(eASN1Error, NULL); return null; } -static ASN1_OBJECT* -obj_to_asn1obj(VALUE obj) +ASN1_OBJECT * +ossl_to_asn1obj(VALUE obj) { ASN1_OBJECT *a1obj; - StringValue(obj); + StringValueCStr(obj); a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0); if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1); - if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID"); + if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID %"PRIsVALUE, obj); return a1obj; } -static ASN1_UTCTIME* +static ASN1_UTCTIME * obj_to_asn1utime(VALUE time) { time_t sec; ASN1_UTCTIME *t; - sec = time_to_time_t(time); - if(!(t = ASN1_UTCTIME_set(NULL, sec))) + int off_days; + + ossl_time_split(time, &sec, &off_days); + if (!(t = ASN1_UTCTIME_adj(NULL, sec, off_days, 0))) ossl_raise(eASN1Error, NULL); return t; } -static ASN1_GENERALIZEDTIME* +static ASN1_GENERALIZEDTIME * obj_to_asn1gtime(VALUE time) { time_t sec; ASN1_GENERALIZEDTIME *t; - sec = time_to_time_t(time); - if(!(t =ASN1_GENERALIZEDTIME_set(NULL, sec))) + int off_days; + + ossl_time_split(time, &sec, &off_days); + if (!(t = ASN1_GENERALIZEDTIME_adj(NULL, sec, off_days, 0))) ossl_raise(eASN1Error, NULL); return t; @@ -336,7 +320,7 @@ obj_to_asn1derstr(VALUE obj) str = ossl_to_der(obj); if(!(a1str = ASN1_STRING_new())) - ossl_raise(eASN1Error, NULL); + ossl_raise(eASN1Error, NULL); ASN1_STRING_set(a1str, RSTRING_PTR(str), RSTRING_LENINT(str)); return a1str; @@ -348,14 +332,14 @@ obj_to_asn1derstr(VALUE obj) static VALUE decode_bool(unsigned char* der, long length) { - int val; - const unsigned char *p; + const unsigned char *p = der; - p = der; - if((val = d2i_ASN1_BOOLEAN(NULL, &p, length)) < 0) - ossl_raise(eASN1Error, NULL); + if (length != 3) + ossl_raise(eASN1Error, "invalid length for BOOLEAN"); + if (p[0] != 1 || p[1] != 1) + ossl_raise(eASN1Error, "invalid BOOLEAN"); - return val ? Qtrue : Qfalse; + return p[2] ? Qtrue : Qfalse; } static VALUE @@ -368,9 +352,9 @@ decode_int(unsigned char* der, long length) p = der; if(!(ai = d2i_ASN1_INTEGER(NULL, &p, length))) - ossl_raise(eASN1Error, NULL); - ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num, - (VALUE)ai, &status); + ossl_raise(eASN1Error, NULL); + ret = rb_protect(asn1integer_to_num_i, + (VALUE)ai, &status); ASN1_INTEGER_free(ai); if(status) rb_jump_tag(status); @@ -387,11 +371,11 @@ decode_bstr(unsigned char* der, long length, long *unused_bits) p = der; if(!(bstr = d2i_ASN1_BIT_STRING(NULL, &p, length))) - ossl_raise(eASN1Error, NULL); + ossl_raise(eASN1Error, NULL); len = bstr->length; *unused_bits = 0; if(bstr->flags & ASN1_STRING_FLAG_BITS_LEFT) - *unused_bits = bstr->flags & 0x07; + *unused_bits = bstr->flags & 0x07; ret = rb_str_new((const char *)bstr->data, len); ASN1_BIT_STRING_free(bstr); @@ -408,9 +392,9 @@ decode_enum(unsigned char* der, long length) p = der; if(!(ai = d2i_ASN1_ENUMERATED(NULL, &p, length))) - ossl_raise(eASN1Error, NULL); - ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num, - (VALUE)ai, &status); + ossl_raise(eASN1Error, NULL); + ret = rb_protect(asn1integer_to_num_i, + (VALUE)ai, &status); ASN1_ENUMERATED_free(ai); if(status) rb_jump_tag(status); @@ -425,38 +409,33 @@ decode_null(unsigned char* der, long length) p = der; if(!(null = d2i_ASN1_NULL(NULL, &p, length))) - ossl_raise(eASN1Error, NULL); + ossl_raise(eASN1Error, NULL); ASN1_NULL_free(null); return Qnil; } +VALUE +asn1obj_to_string_i(VALUE arg) +{ + return ossl_asn1obj_to_string((const ASN1_OBJECT *)arg); +} + static VALUE decode_obj(unsigned char* der, long length) { ASN1_OBJECT *obj; const unsigned char *p; VALUE ret; - int nid; - BIO *bio; + int state; p = der; - if(!(obj = d2i_ASN1_OBJECT(NULL, &p, length))) - ossl_raise(eASN1Error, NULL); - if((nid = OBJ_obj2nid(obj)) != NID_undef){ - ASN1_OBJECT_free(obj); - ret = rb_str_new2(OBJ_nid2sn(nid)); - } - else{ - if(!(bio = BIO_new(BIO_s_mem()))){ - ASN1_OBJECT_free(obj); - ossl_raise(eASN1Error, NULL); - } - i2a_ASN1_OBJECT(bio, obj); - ASN1_OBJECT_free(obj); - ret = ossl_membio2str(bio); - } - + if (!(obj = d2i_ASN1_OBJECT(NULL, &p, length))) + ossl_raise(eASN1Error, "d2i_ASN1_OBJECT"); + ret = rb_protect(asn1obj_to_string_i, (VALUE)obj, &state); + ASN1_OBJECT_free(obj); + if (state) + rb_jump_tag(state); return ret; } @@ -470,9 +449,9 @@ decode_time(unsigned char* der, long length) p = der; if(!(time = d2i_ASN1_TIME(NULL, &p, length))) - ossl_raise(eASN1Error, NULL); - ret = rb_protect((VALUE(*)_((VALUE)))asn1time_to_time, - (VALUE)time, &status); + ossl_raise(eASN1Error, NULL); + ret = rb_protect(asn1time_to_time_i, + (VALUE)time, &status); ASN1_TIME_free(time); if(status) rb_jump_tag(status); @@ -483,7 +462,7 @@ static VALUE decode_eoc(unsigned char *der, long length) { if (length != 2 || !(der[0] == 0x00 && der[1] == 0x00)) - ossl_raise(eASN1Error, NULL); + ossl_raise(eASN1Error, NULL); return rb_str_new("", 0); } @@ -535,75 +514,75 @@ static VALUE class_tag_map; static int ossl_asn1_default_tag(VALUE obj); -ASN1_TYPE* +static ASN1_TYPE * ossl_asn1_get_asn1type(VALUE obj) { ASN1_TYPE *ret; VALUE value, rflag; void *ptr; - void (*free_func)(); - int tag, flag; + typedef void free_func_type(void *); + free_func_type *free_func; + int tag; tag = ossl_asn1_default_tag(obj); value = ossl_asn1_get_value(obj); switch(tag){ - case V_ASN1_BOOLEAN: - ptr = (void*)(VALUE)obj_to_asn1bool(value); - free_func = NULL; - break; - case V_ASN1_INTEGER: /* FALLTHROUGH */ - case V_ASN1_ENUMERATED: - ptr = obj_to_asn1int(value); - free_func = ASN1_INTEGER_free; - break; - case V_ASN1_BIT_STRING: + case V_ASN1_BOOLEAN: + ptr = (void*)(VALUE)obj_to_asn1bool(value); + free_func = NULL; + break; + case V_ASN1_INTEGER: /* FALLTHROUGH */ + case V_ASN1_ENUMERATED: + ptr = obj_to_asn1int(value); + free_func = (free_func_type *)ASN1_INTEGER_free; + break; + case V_ASN1_BIT_STRING: rflag = rb_attr_get(obj, sivUNUSED_BITS); - flag = NIL_P(rflag) ? -1 : NUM2INT(rflag); - ptr = obj_to_asn1bstr(value, flag); - free_func = ASN1_BIT_STRING_free; - break; - case V_ASN1_NULL: - ptr = obj_to_asn1null(value); - free_func = ASN1_NULL_free; - break; - case V_ASN1_OCTET_STRING: /* FALLTHROUGH */ - case V_ASN1_UTF8STRING: /* FALLTHROUGH */ - case V_ASN1_NUMERICSTRING: /* FALLTHROUGH */ - case V_ASN1_PRINTABLESTRING: /* FALLTHROUGH */ - case V_ASN1_T61STRING: /* FALLTHROUGH */ - case V_ASN1_VIDEOTEXSTRING: /* FALLTHROUGH */ - case V_ASN1_IA5STRING: /* FALLTHROUGH */ - case V_ASN1_GRAPHICSTRING: /* FALLTHROUGH */ - case V_ASN1_ISO64STRING: /* FALLTHROUGH */ - case V_ASN1_GENERALSTRING: /* FALLTHROUGH */ - case V_ASN1_UNIVERSALSTRING: /* FALLTHROUGH */ - case V_ASN1_BMPSTRING: - ptr = obj_to_asn1str(value); - free_func = ASN1_STRING_free; - break; - case V_ASN1_OBJECT: - ptr = obj_to_asn1obj(value); - free_func = ASN1_OBJECT_free; - break; - case V_ASN1_UTCTIME: - ptr = obj_to_asn1utime(value); - free_func = ASN1_TIME_free; - break; - case V_ASN1_GENERALIZEDTIME: - ptr = obj_to_asn1gtime(value); - free_func = ASN1_TIME_free; - break; - case V_ASN1_SET: /* FALLTHROUGH */ - case V_ASN1_SEQUENCE: - ptr = obj_to_asn1derstr(obj); - free_func = ASN1_STRING_free; - break; - default: - ossl_raise(eASN1Error, "unsupported ASN.1 type"); + ptr = obj_to_asn1bstr(value, NUM2INT(rflag)); + free_func = (free_func_type *)ASN1_BIT_STRING_free; + break; + case V_ASN1_NULL: + ptr = obj_to_asn1null(value); + free_func = (free_func_type *)ASN1_NULL_free; + break; + case V_ASN1_OCTET_STRING: /* FALLTHROUGH */ + case V_ASN1_UTF8STRING: /* FALLTHROUGH */ + case V_ASN1_NUMERICSTRING: /* FALLTHROUGH */ + case V_ASN1_PRINTABLESTRING: /* FALLTHROUGH */ + case V_ASN1_T61STRING: /* FALLTHROUGH */ + case V_ASN1_VIDEOTEXSTRING: /* FALLTHROUGH */ + case V_ASN1_IA5STRING: /* FALLTHROUGH */ + case V_ASN1_GRAPHICSTRING: /* FALLTHROUGH */ + case V_ASN1_ISO64STRING: /* FALLTHROUGH */ + case V_ASN1_GENERALSTRING: /* FALLTHROUGH */ + case V_ASN1_UNIVERSALSTRING: /* FALLTHROUGH */ + case V_ASN1_BMPSTRING: + ptr = obj_to_asn1str(value); + free_func = (free_func_type *)ASN1_STRING_free; + break; + case V_ASN1_OBJECT: + ptr = ossl_to_asn1obj(value); + free_func = (free_func_type *)ASN1_OBJECT_free; + break; + case V_ASN1_UTCTIME: + ptr = obj_to_asn1utime(value); + free_func = (free_func_type *)ASN1_TIME_free; + break; + case V_ASN1_GENERALIZEDTIME: + ptr = obj_to_asn1gtime(value); + free_func = (free_func_type *)ASN1_TIME_free; + break; + case V_ASN1_SET: /* FALLTHROUGH */ + case V_ASN1_SEQUENCE: + ptr = obj_to_asn1derstr(obj); + free_func = (free_func_type *)ASN1_STRING_free; + break; + default: + ossl_raise(eASN1Error, "unsupported ASN.1 type"); } if(!(ret = OPENSSL_malloc(sizeof(ASN1_TYPE)))){ - if(free_func) free_func(ptr); - ossl_raise(eASN1Error, "ASN1_TYPE alloc failure"); + if(free_func) free_func(ptr); + ossl_raise(eASN1Error, "ASN1_TYPE alloc failure"); } memset(ret, 0, sizeof(ASN1_TYPE)); ASN1_TYPE_set(ret, tag, ptr); @@ -617,17 +596,14 @@ ossl_asn1_default_tag(VALUE obj) VALUE tmp_class, tag; tmp_class = CLASS_OF(obj); - while (tmp_class) { - tag = rb_hash_lookup(class_tag_map, tmp_class); - if (tag != Qnil) { - return NUM2INT(tag); - } - tmp_class = rb_class_superclass(tmp_class); + while (!NIL_P(tmp_class)) { + tag = rb_hash_lookup(class_tag_map, tmp_class); + if (tag != Qnil) + return NUM2INT(tag); + tmp_class = rb_class_superclass(tmp_class); } - ossl_raise(eASN1Error, "universal tag for %"PRIsVALUE" not found", - rb_obj_class(obj)); - return -1; /* dummy */ + return -1; } static int @@ -637,80 +613,52 @@ ossl_asn1_tag(VALUE obj) tag = ossl_asn1_get_tag(obj); if(NIL_P(tag)) - ossl_raise(eASN1Error, "tag number not specified"); + ossl_raise(eASN1Error, "tag number not specified"); return NUM2INT(tag); } static int -ossl_asn1_is_explicit(VALUE obj) -{ - VALUE s; - int ret = -1; - - s = ossl_asn1_get_tagging(obj); - if(NIL_P(s)) return 0; - else if(SYMBOL_P(s)){ - if (SYM2ID(s) == sIMPLICIT) - ret = 0; - else if (SYM2ID(s) == sEXPLICIT) - ret = 1; - } - if(ret < 0){ - ossl_raise(eASN1Error, "invalid tag default"); - } - - return ret; -} - -static int ossl_asn1_tag_class(VALUE obj) { VALUE s; - int ret = -1; s = ossl_asn1_get_tag_class(obj); - if(NIL_P(s)) ret = V_ASN1_UNIVERSAL; - else if(SYMBOL_P(s)){ - if (SYM2ID(s) == sUNIVERSAL) - ret = V_ASN1_UNIVERSAL; - else if (SYM2ID(s) == sAPPLICATION) - ret = V_ASN1_APPLICATION; - else if (SYM2ID(s) == sCONTEXT_SPECIFIC) - ret = V_ASN1_CONTEXT_SPECIFIC; - else if (SYM2ID(s) == sPRIVATE) - ret = V_ASN1_PRIVATE; - } - if(ret < 0){ - ossl_raise(eASN1Error, "invalid tag class"); - } - - return ret; + if (NIL_P(s) || s == sym_UNIVERSAL) + return V_ASN1_UNIVERSAL; + else if (s == sym_APPLICATION) + return V_ASN1_APPLICATION; + else if (s == sym_CONTEXT_SPECIFIC) + return V_ASN1_CONTEXT_SPECIFIC; + else if (s == sym_PRIVATE) + return V_ASN1_PRIVATE; + else + ossl_raise(eASN1Error, "invalid tag class"); } static VALUE ossl_asn1_class2sym(int tc) { if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE) - return ID2SYM(sPRIVATE); + return sym_PRIVATE; else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC) - return ID2SYM(sCONTEXT_SPECIFIC); + return sym_CONTEXT_SPECIFIC; else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION) - return ID2SYM(sAPPLICATION); + return sym_APPLICATION; else - return ID2SYM(sUNIVERSAL); + return sym_UNIVERSAL; } /* * call-seq: * OpenSSL::ASN1::ASN1Data.new(value, tag, tag_class) => ASN1Data * - * +value+: Please have a look at Constructive and Primitive to see how Ruby + * _value_: Please have a look at Constructive and Primitive to see how Ruby * types are mapped to ASN.1 types and vice versa. * - * +tag+: A +Number+ indicating the tag number. + * _tag_: An Integer indicating the tag number. * - * +tag_class+: A +Symbol+ indicating the tag class. Please cf. ASN1 for + * _tag_class_: A Symbol indicating the tag class. Please cf. ASN1 for * possible values. * * == Example @@ -721,79 +669,95 @@ static VALUE ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class) { if(!SYMBOL_P(tag_class)) - ossl_raise(eASN1Error, "invalid tag class"); - if((SYM2ID(tag_class) == sUNIVERSAL) && NUM2INT(tag) > 31) - ossl_raise(eASN1Error, "tag number for Universal too large"); + ossl_raise(eASN1Error, "invalid tag class"); ossl_asn1_set_tag(self, tag); ossl_asn1_set_value(self, value); ossl_asn1_set_tag_class(self, tag_class); - ossl_asn1_set_infinite_length(self, Qfalse); + ossl_asn1_set_indefinite_length(self, Qfalse); return self; } static VALUE -join_der_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, str)) +to_der_internal(VALUE self, int constructed, int indef_len, VALUE body) { - i = ossl_to_der_if_possible(i); - StringValue(i); - rb_str_append(str, i); - return Qnil; -} + int encoding = constructed ? indef_len ? 2 : 1 : 0; + int tag_class = ossl_asn1_tag_class(self); + int tag_number = ossl_asn1_tag(self); + int default_tag_number = ossl_asn1_default_tag(self); + int body_length, total_length; + VALUE str; + unsigned char *p; -static VALUE -join_der(VALUE enumerable) -{ - VALUE str = rb_str_new(0, 0); - rb_block_call(enumerable, rb_intern("each"), 0, 0, join_der_i, str); + body_length = RSTRING_LENINT(body); + if (ossl_asn1_get_tagging(self) == sym_EXPLICIT) { + int inner_length, e_encoding = indef_len ? 2 : 1; + + if (default_tag_number == -1) + ossl_raise(eASN1Error, "explicit tagging of unknown tag"); + + inner_length = ASN1_object_size(encoding, body_length, default_tag_number); + total_length = ASN1_object_size(e_encoding, inner_length, tag_number); + str = rb_str_new(NULL, total_length); + p = (unsigned char *)RSTRING_PTR(str); + /* Put explicit tag */ + ASN1_put_object(&p, e_encoding, inner_length, tag_number, tag_class); + /* Append inner object */ + ASN1_put_object(&p, encoding, body_length, default_tag_number, V_ASN1_UNIVERSAL); + memcpy(p, RSTRING_PTR(body), body_length); + p += body_length; + if (indef_len) { + ASN1_put_eoc(&p); /* For inner object */ + ASN1_put_eoc(&p); /* For wrapper object */ + } + } + else { + total_length = ASN1_object_size(encoding, body_length, tag_number); + str = rb_str_new(NULL, total_length); + p = (unsigned char *)RSTRING_PTR(str); + ASN1_put_object(&p, encoding, body_length, tag_number, tag_class); + memcpy(p, RSTRING_PTR(body), body_length); + p += body_length; + if (indef_len) + ASN1_put_eoc(&p); + } + assert(p - (unsigned char *)RSTRING_PTR(str) == total_length); return str; } +static VALUE ossl_asn1prim_to_der(VALUE); +static VALUE ossl_asn1cons_to_der(VALUE); /* * call-seq: * asn1.to_der => DER-encoded String * * Encodes this ASN1Data into a DER-encoded String value. The result is - * DER-encoded except for the possibility of infinite length encodings. - * Infinite length encodings are not allowed in strict DER, so strictly - * speaking the result of such an encoding would be a BER-encoding. + * DER-encoded except for the possibility of indefinite length forms. + * Indefinite length forms are not allowed in strict DER, so strictly speaking + * the result of such an encoding would be a BER-encoding. */ static VALUE ossl_asn1data_to_der(VALUE self) { - VALUE value, der, inf_length; - int tag, tag_class, is_cons = 0; - long length; - unsigned char *p; + VALUE value = ossl_asn1_get_value(self); - value = ossl_asn1_get_value(self); - if(rb_obj_is_kind_of(value, rb_cArray)){ - is_cons = 1; - value = join_der(value); - } - StringValue(value); - - tag = ossl_asn1_tag(self); - tag_class = ossl_asn1_tag_class(self); - inf_length = ossl_asn1_get_infinite_length(self); - if (inf_length == Qtrue) { - is_cons = 2; + if (rb_obj_is_kind_of(value, rb_cArray)) + return ossl_asn1cons_to_der(self); + else { + if (RTEST(ossl_asn1_get_indefinite_length(self))) + ossl_raise(eASN1Error, "indefinite length form cannot be used " \ + "with primitive encoding"); + return ossl_asn1prim_to_der(self); } - if((length = ossl_asn1_object_size(is_cons, RSTRING_LENINT(value), tag)) <= 0) - ossl_raise(eASN1Error, NULL); - der = rb_str_new(0, length); - p = (unsigned char *)RSTRING_PTR(der); - ossl_asn1_put_object(&p, is_cons, RSTRING_LENINT(value), tag, tag_class); - memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value)); - p += RSTRING_LEN(value); - ossl_str_adjust(der, p); - - return der; } +static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self); +static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset, + int depth, int yield, long *num_read); + static VALUE int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag, - VALUE tc, long *num_read) + VALUE tc, long *num_read) { VALUE value, asn1data; unsigned char *p; @@ -801,64 +765,65 @@ int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag, p = *pp; - if(tc == sUNIVERSAL && tag < ossl_asn1_info_size) { - switch(tag){ - case V_ASN1_EOC: - value = decode_eoc(p, hlen+length); - break; - case V_ASN1_BOOLEAN: - value = decode_bool(p, hlen+length); - break; - case V_ASN1_INTEGER: - value = decode_int(p, hlen+length); - break; - case V_ASN1_BIT_STRING: - value = decode_bstr(p, hlen+length, &flag); - break; - case V_ASN1_NULL: - value = decode_null(p, hlen+length); - break; - case V_ASN1_ENUMERATED: - value = decode_enum(p, hlen+length); - break; - case V_ASN1_OBJECT: - value = decode_obj(p, hlen+length); - break; - case V_ASN1_UTCTIME: /* FALLTHROUGH */ - case V_ASN1_GENERALIZEDTIME: - value = decode_time(p, hlen+length); - break; - default: - /* use original value */ - p += hlen; - value = rb_str_new((const char *)p, length); - break; - } + if(tc == sym_UNIVERSAL && tag < ossl_asn1_info_size) { + switch(tag){ + case V_ASN1_EOC: + value = decode_eoc(p, hlen+length); + break; + case V_ASN1_BOOLEAN: + value = decode_bool(p, hlen+length); + break; + case V_ASN1_INTEGER: + value = decode_int(p, hlen+length); + break; + case V_ASN1_BIT_STRING: + value = decode_bstr(p, hlen+length, &flag); + break; + case V_ASN1_NULL: + value = decode_null(p, hlen+length); + break; + case V_ASN1_ENUMERATED: + value = decode_enum(p, hlen+length); + break; + case V_ASN1_OBJECT: + value = decode_obj(p, hlen+length); + break; + case V_ASN1_UTCTIME: /* FALLTHROUGH */ + case V_ASN1_GENERALIZEDTIME: + value = decode_time(p, hlen+length); + break; + default: + /* use original value */ + p += hlen; + value = rb_str_new((const char *)p, length); + break; + } } else { - p += hlen; - value = rb_str_new((const char *)p, length); + p += hlen; + value = rb_str_new((const char *)p, length); } *pp += hlen + length; *num_read = hlen + length; - if (tc == sUNIVERSAL && tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass) { - VALUE klass = *ossl_asn1_info[tag].klass; - VALUE args[4]; - args[0] = value; - args[1] = INT2NUM(tag); - args[2] = Qnil; - args[3] = ID2SYM(tc); - asn1data = rb_obj_alloc(klass); - ossl_asn1_initialize(4, args, asn1data); - if(tag == V_ASN1_BIT_STRING){ - rb_ivar_set(asn1data, sivUNUSED_BITS, LONG2NUM(flag)); - } + if (tc == sym_UNIVERSAL && + tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass) { + VALUE klass = *ossl_asn1_info[tag].klass; + VALUE args[4]; + args[0] = value; + args[1] = INT2NUM(tag); + args[2] = Qnil; + args[3] = tc; + asn1data = rb_obj_alloc(klass); + ossl_asn1_initialize(4, args, asn1data); + if(tag == V_ASN1_BIT_STRING){ + rb_ivar_set(asn1data, sivUNUSED_BITS, LONG2NUM(flag)); + } } else { - asn1data = rb_obj_alloc(cASN1Data); - ossl_asn1data_initialize(asn1data, value, INT2NUM(tag), ID2SYM(tc)); + asn1data = rb_obj_alloc(cASN1Data); + ossl_asn1data_initialize(asn1data, value, INT2NUM(tag), tc); } return asn1data; @@ -866,66 +831,54 @@ int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag, static VALUE int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length, - long *offset, int depth, int yield, int j, - int tag, VALUE tc, long *num_read) + long *offset, int depth, int yield, int j, + int tag, VALUE tc, long *num_read) { VALUE value, asn1data, ary; - int infinite; - long off = *offset; + int indefinite; + long available_len, off = *offset; - infinite = (j == 0x21); + indefinite = (j == 0x21); ary = rb_ary_new(); - while (length > 0 || infinite) { - long inner_read = 0; - value = ossl_asn1_decode0(pp, max_len, &off, depth + 1, yield, &inner_read); - *num_read += inner_read; - max_len -= inner_read; - rb_ary_push(ary, value); - if (length > 0) - length -= inner_read; - - if (infinite && - NUM2INT(ossl_asn1_get_tag(value)) == V_ASN1_EOC && - SYM2ID(ossl_asn1_get_tag_class(value)) == sUNIVERSAL) { - break; - } + available_len = indefinite ? max_len : length; + while (available_len > 0) { + long inner_read = 0; + value = ossl_asn1_decode0(pp, available_len, &off, depth + 1, yield, &inner_read); + *num_read += inner_read; + available_len -= inner_read; + + if (indefinite) { + if (ossl_asn1_tag(value) == V_ASN1_EOC && + ossl_asn1_get_tag_class(value) == sym_UNIVERSAL) + break; + if (available_len == 0) + ossl_raise(eASN1Error, "EOC missing in indefinite length encoding"); + } + rb_ary_push(ary, value); } - if (tc == sUNIVERSAL) { - VALUE args[4]; - int not_sequence_or_set; - - not_sequence_or_set = tag != V_ASN1_SEQUENCE && tag != V_ASN1_SET; - - if (not_sequence_or_set) { - if (infinite) { - asn1data = rb_obj_alloc(cASN1Constructive); - } - else { - ossl_raise(eASN1Error, "invalid non-infinite tag"); - return Qnil; - } - } - else { - VALUE klass = *ossl_asn1_info[tag].klass; - asn1data = rb_obj_alloc(klass); - } - args[0] = ary; - args[1] = INT2NUM(tag); - args[2] = Qnil; - args[3] = ID2SYM(tc); - ossl_asn1_initialize(4, args, asn1data); + if (tc == sym_UNIVERSAL) { + VALUE args[4]; + if (tag == V_ASN1_SEQUENCE || tag == V_ASN1_SET) + asn1data = rb_obj_alloc(*ossl_asn1_info[tag].klass); + else + asn1data = rb_obj_alloc(cASN1Constructive); + args[0] = ary; + args[1] = INT2NUM(tag); + args[2] = Qnil; + args[3] = tc; + ossl_asn1_initialize(4, args, asn1data); } else { - asn1data = rb_obj_alloc(cASN1Data); - ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), ID2SYM(tc)); + asn1data = rb_obj_alloc(cASN1Data); + ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), tc); } - if (infinite) - ossl_asn1_set_infinite_length(asn1data, Qtrue); + if (indefinite) + ossl_asn1_set_indefinite_length(asn1data, Qtrue); else - ossl_asn1_set_infinite_length(asn1data, Qfalse); + ossl_asn1_set_indefinite_length(asn1data, Qfalse); *offset = off; return asn1data; @@ -933,7 +886,7 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length, static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth, - int yield, long *num_read) + int yield, long *num_read) { unsigned char *start, *p; const unsigned char *p0; @@ -949,45 +902,46 @@ ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth, if(j & 0x80) ossl_raise(eASN1Error, NULL); if(len > length) ossl_raise(eASN1Error, "value is too short"); if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE) - tag_class = sPRIVATE; + tag_class = sym_PRIVATE; else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC) - tag_class = sCONTEXT_SPECIFIC; + tag_class = sym_CONTEXT_SPECIFIC; else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION) - tag_class = sAPPLICATION; + tag_class = sym_APPLICATION; else - tag_class = sUNIVERSAL; + tag_class = sym_UNIVERSAL; hlen = p - start; if(yield) { - VALUE arg = rb_ary_new(); - rb_ary_push(arg, LONG2NUM(depth)); - rb_ary_push(arg, LONG2NUM(*offset)); - rb_ary_push(arg, LONG2NUM(hlen)); - rb_ary_push(arg, LONG2NUM(len)); - rb_ary_push(arg, (j & V_ASN1_CONSTRUCTED) ? Qtrue : Qfalse); - rb_ary_push(arg, ossl_asn1_class2sym(tc)); - rb_ary_push(arg, INT2NUM(tag)); - rb_yield(arg); + VALUE arg = rb_ary_new(); + rb_ary_push(arg, LONG2NUM(depth)); + rb_ary_push(arg, LONG2NUM(*offset)); + rb_ary_push(arg, LONG2NUM(hlen)); + rb_ary_push(arg, LONG2NUM(len)); + rb_ary_push(arg, (j & V_ASN1_CONSTRUCTED) ? Qtrue : Qfalse); + rb_ary_push(arg, ossl_asn1_class2sym(tc)); + rb_ary_push(arg, INT2NUM(tag)); + rb_yield(arg); } if(j & V_ASN1_CONSTRUCTED) { - *pp += hlen; - off += hlen; - asn1data = int_ossl_asn1_decode0_cons(pp, length, len, &off, depth, yield, j, tag, tag_class, &inner_read); - inner_read += hlen; + *pp += hlen; + off += hlen; + asn1data = int_ossl_asn1_decode0_cons(pp, length - hlen, len, &off, depth, yield, j, tag, tag_class, &inner_read); + inner_read += hlen; } else { - if ((j & 0x01) && (len == 0)) ossl_raise(eASN1Error, "Infinite length for primitive value"); - asn1data = int_ossl_asn1_decode0_prim(pp, len, hlen, tag, tag_class, &inner_read); - off += hlen + len; + if ((j & 0x01) && (len == 0)) + ossl_raise(eASN1Error, "indefinite length for primitive value"); + asn1data = int_ossl_asn1_decode0_prim(pp, len, hlen, tag, tag_class, &inner_read); + off += hlen + len; } if (num_read) - *num_read = inner_read; + *num_read = inner_read; if (len != 0 && inner_read != hlen + len) { - ossl_raise(eASN1Error, - "Type mismatch. Bytes read: %ld Bytes available: %ld", - inner_read, hlen + len); + ossl_raise(eASN1Error, + "Type mismatch. Bytes read: %ld Bytes available: %ld", + inner_read, hlen + len); } *offset = off; @@ -998,9 +952,9 @@ static void int_ossl_decode_sanity_check(long len, long read, long offset) { if (len != 0 && (read != len || offset != len)) { - ossl_raise(eASN1Error, - "Type mismatch. Total bytes read: %ld Bytes available: %ld Offset: %ld", - read, len, offset); + ossl_raise(eASN1Error, + "Type mismatch. Total bytes read: %ld Bytes available: %ld Offset: %ld", + read, len, offset); } } @@ -1010,13 +964,13 @@ int_ossl_decode_sanity_check(long len, long read, long offset) * * If a block is given, it prints out each of the elements encountered. * Block parameters are (in that order): - * * depth: The recursion depth, plus one with each constructed value being encountered (Number) - * * offset: Current byte offset (Number) - * * header length: Combined length in bytes of the Tag and Length headers. (Number) - * * length: The overall remaining length of the entire data (Number) + * * depth: The recursion depth, plus one with each constructed value being encountered (Integer) + * * offset: Current byte offset (Integer) + * * header length: Combined length in bytes of the Tag and Length headers. (Integer) + * * length: The overall remaining length of the entire data (Integer) * * constructed: Whether this value is constructed or not (Boolean) * * tag_class: Current tag class (Symbol) - * * tag: The current tag (Number) + * * tag: The current tag number (Integer) * * == Example * der = File.binread('asn1data.der') @@ -1029,7 +983,7 @@ static VALUE ossl_asn1_traverse(VALUE self, VALUE obj) { unsigned char *p; - volatile VALUE tmp; + VALUE tmp; long len, read = 0, offset = 0; obj = ossl_to_der_if_possible(obj); @@ -1037,6 +991,7 @@ ossl_asn1_traverse(VALUE self, VALUE obj) p = (unsigned char *)RSTRING_PTR(tmp); len = RSTRING_LEN(tmp); ossl_asn1_decode0(&p, len, &offset, 0, 1, &read); + RB_GC_GUARD(tmp); int_ossl_decode_sanity_check(len, read, offset); return Qnil; } @@ -1045,9 +1000,9 @@ ossl_asn1_traverse(VALUE self, VALUE obj) * call-seq: * OpenSSL::ASN1.decode(der) -> ASN1Data * - * Decodes a BER- or DER-encoded value and creates an ASN1Data instance. +der+ - * may be a +String+ or any object that features a +#to_der+ method transforming - * it into a BER-/DER-encoded +String+. + * Decodes a BER- or DER-encoded value and creates an ASN1Data instance. _der_ + * may be a String or any object that features a +.to_der+ method transforming + * it into a BER-/DER-encoded String+ * * == Example * der = File.binread('asn1data') @@ -1058,7 +1013,7 @@ ossl_asn1_decode(VALUE self, VALUE obj) { VALUE ret; unsigned char *p; - volatile VALUE tmp; + VALUE tmp; long len, read = 0, offset = 0; obj = ossl_to_der_if_possible(obj); @@ -1066,6 +1021,7 @@ ossl_asn1_decode(VALUE self, VALUE obj) p = (unsigned char *)RSTRING_PTR(tmp); len = RSTRING_LEN(tmp); ret = ossl_asn1_decode0(&p, len, &offset, 0, 0, &read); + RB_GC_GUARD(tmp); int_ossl_decode_sanity_check(len, read, offset); return ret; } @@ -1074,9 +1030,9 @@ ossl_asn1_decode(VALUE self, VALUE obj) * call-seq: * OpenSSL::ASN1.decode_all(der) -> Array of ASN1Data * - * Similar to +decode+ with the difference that +decode+ expects one - * distinct value represented in +der+. +decode_all+ on the contrary - * decodes a sequence of sequential BER/DER values lined up in +der+ + * Similar to #decode with the difference that #decode expects one + * distinct value represented in _der_. #decode_all on the contrary + * decodes a sequence of sequential BER/DER values lined up in _der_ * and returns them as an array. * * == Example @@ -1089,7 +1045,7 @@ ossl_asn1_decode_all(VALUE self, VALUE obj) VALUE ary, val; unsigned char *p; long len, tmp_len = 0, read = 0, offset = 0; - volatile VALUE tmp; + VALUE tmp; obj = ossl_to_der_if_possible(obj); tmp = rb_str_new4(StringValue(obj)); @@ -1098,31 +1054,32 @@ ossl_asn1_decode_all(VALUE self, VALUE obj) tmp_len = len; ary = rb_ary_new(); while (tmp_len > 0) { - long tmp_read = 0; - val = ossl_asn1_decode0(&p, tmp_len, &offset, 0, 0, &tmp_read); - rb_ary_push(ary, val); - read += tmp_read; - tmp_len -= tmp_read; + long tmp_read = 0; + val = ossl_asn1_decode0(&p, tmp_len, &offset, 0, 0, &tmp_read); + rb_ary_push(ary, val); + read += tmp_read; + tmp_len -= tmp_read; } + RB_GC_GUARD(tmp); int_ossl_decode_sanity_check(len, read, offset); return ary; } /* * call-seq: - * OpenSSL::ASN1::Primitive.new( value [, tag, tagging, tag_class ]) => Primitive + * OpenSSL::ASN1::Primitive.new(value [, tag, tagging, tag_class ]) => Primitive * - * +value+: is mandatory. + * _value_: is mandatory. * - * +tag+: optional, may be specified for tagged values. If no +tag+ is + * _tag_: optional, may be specified for tagged values. If no _tag_ is * specified, the UNIVERSAL tag corresponding to the Primitive sub-class * is used by default. * - * +tagging+: may be used as an encoding hint to encode a value either + * _tagging_: may be used as an encoding hint to encode a value either * explicitly or implicitly, see ASN1 for possible values. * - * +tag_class+: if +tag+ and +tagging+ are +nil+ then this is set to - * +:UNIVERSAL+ by default. If either +tag+ or +tagging+ are set then + * _tag_class_: if _tag_ and _tagging_ are +nil+ then this is set to + * +:UNIVERSAL+ by default. If either _tag_ or _tagging_ are set then * +:CONTEXT_SPECIFIC+ is used as the default. For possible values please * cf. ASN1. * @@ -1135,34 +1092,37 @@ static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self) { VALUE value, tag, tagging, tag_class; + int default_tag; rb_scan_args(argc, argv, "13", &value, &tag, &tagging, &tag_class); - if(argc > 1){ - if(NIL_P(tag)) - ossl_raise(eASN1Error, "must specify tag number"); - if(!NIL_P(tagging) && !SYMBOL_P(tagging)) - ossl_raise(eASN1Error, "invalid tagging method"); - if(NIL_P(tag_class)) { - if (NIL_P(tagging)) - tag_class = ID2SYM(sUNIVERSAL); - else - tag_class = ID2SYM(sCONTEXT_SPECIFIC); - } - if(!SYMBOL_P(tag_class)) - ossl_raise(eASN1Error, "invalid tag class"); - if(!NIL_P(tagging) && SYM2ID(tagging) == sIMPLICIT && NUM2INT(tag) > 31) - ossl_raise(eASN1Error, "tag number for Universal too large"); + default_tag = ossl_asn1_default_tag(self); + + if (default_tag == -1 || argc > 1) { + if(NIL_P(tag)) + ossl_raise(eASN1Error, "must specify tag number"); + if(!NIL_P(tagging) && !SYMBOL_P(tagging)) + ossl_raise(eASN1Error, "invalid tagging method"); + if(NIL_P(tag_class)) { + if (NIL_P(tagging)) + tag_class = sym_UNIVERSAL; + else + tag_class = sym_CONTEXT_SPECIFIC; + } + if(!SYMBOL_P(tag_class)) + ossl_raise(eASN1Error, "invalid tag class"); } else{ - tag = INT2NUM(ossl_asn1_default_tag(self)); - tagging = Qnil; - tag_class = ID2SYM(sUNIVERSAL); + tag = INT2NUM(default_tag); + tagging = Qnil; + tag_class = sym_UNIVERSAL; } ossl_asn1_set_tag(self, tag); ossl_asn1_set_value(self, value); ossl_asn1_set_tagging(self, tagging); ossl_asn1_set_tag_class(self, tag_class); - ossl_asn1_set_infinite_length(self, Qfalse); + ossl_asn1_set_indefinite_length(self, Qfalse); + if (default_tag == V_ASN1_BIT_STRING) + rb_ivar_set(self, sivUNUSED_BITS, INT2FIX(0)); return self; } @@ -1170,83 +1130,69 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self) static VALUE ossl_asn1eoc_initialize(VALUE self) { VALUE tag, tagging, tag_class, value; - tag = INT2NUM(ossl_asn1_default_tag(self)); + tag = INT2FIX(0); tagging = Qnil; - tag_class = ID2SYM(sUNIVERSAL); + tag_class = sym_UNIVERSAL; value = rb_str_new("", 0); ossl_asn1_set_tag(self, tag); ossl_asn1_set_value(self, value); ossl_asn1_set_tagging(self, tagging); ossl_asn1_set_tag_class(self, tag_class); - ossl_asn1_set_infinite_length(self, Qfalse); + ossl_asn1_set_indefinite_length(self, Qfalse); return self; } -static int -ossl_i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **pp) +static VALUE +ossl_asn1eoc_to_der(VALUE self) { -#if OPENSSL_VERSION_NUMBER < 0x00907000L - if(!a) return 0; - if(a->type == V_ASN1_BOOLEAN) - return i2d_ASN1_BOOLEAN(a->value.boolean, pp); -#endif - return i2d_ASN1_TYPE(a, pp); -} - -static void -ossl_ASN1_TYPE_free(ASN1_TYPE *a) -{ -#if OPENSSL_VERSION_NUMBER < 0x00907000L - if(!a) return; - if(a->type == V_ASN1_BOOLEAN){ - OPENSSL_free(a); - return; - } -#endif - ASN1_TYPE_free(a); + return rb_str_new("\0\0", 2); } /* * call-seq: * asn1.to_der => DER-encoded String * - * See ASN1Data#to_der for details. * + * See ASN1Data#to_der for details. */ static VALUE ossl_asn1prim_to_der(VALUE self) { ASN1_TYPE *asn1; - int tn, tc, explicit; - long len, reallen; - unsigned char *buf, *p; + long alllen, bodylen; + unsigned char *p0, *p1; + int j, tag, tc, state; VALUE str; - tn = NUM2INT(ossl_asn1_get_tag(self)); - tc = ossl_asn1_tag_class(self); - explicit = ossl_asn1_is_explicit(self); - asn1 = ossl_asn1_get_asn1type(self); + if (ossl_asn1_default_tag(self) == -1) { + str = ossl_asn1_get_value(self); + return to_der_internal(self, 0, 0, StringValue(str)); + } - len = ossl_asn1_object_size(1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn); - if(!(buf = OPENSSL_malloc(len))){ - ossl_ASN1_TYPE_free(asn1); - ossl_raise(eASN1Error, "cannot alloc buffer"); + asn1 = ossl_asn1_get_asn1type(self); + alllen = i2d_ASN1_TYPE(asn1, NULL); + if (alllen < 0) { + ASN1_TYPE_free(asn1); + ossl_raise(eASN1Error, "i2d_ASN1_TYPE"); } - p = buf; - if (tc == V_ASN1_UNIVERSAL) { - ossl_i2d_ASN1_TYPE(asn1, &p); - } else if (explicit) { - ossl_asn1_put_object(&p, 1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn, tc); - ossl_i2d_ASN1_TYPE(asn1, &p); - } else { - ossl_i2d_ASN1_TYPE(asn1, &p); - *buf = tc | tn | (*buf & V_ASN1_CONSTRUCTED); + str = ossl_str_new(NULL, alllen, &state); + if (state) { + ASN1_TYPE_free(asn1); + rb_jump_tag(state); } - ossl_ASN1_TYPE_free(asn1); - reallen = p - buf; - assert(reallen <= len); - str = ossl_buf2str((char *)buf, rb_long2int(reallen)); /* buf will be free in ossl_buf2str */ + p0 = p1 = (unsigned char *)RSTRING_PTR(str); + if (i2d_ASN1_TYPE(asn1, &p0) < 0) { + ASN1_TYPE_free(asn1); + ossl_raise(eASN1Error, "i2d_ASN1_TYPE"); + } + ASN1_TYPE_free(asn1); + ossl_str_adjust(str, p0); - return str; + /* Strip header since to_der_internal() wants only the payload */ + j = ASN1_get_object((const unsigned char **)&p1, &bodylen, &tag, &tc, alllen); + if (j & 0x80) + ossl_raise(eASN1Error, "ASN1_get_object"); /* should not happen */ + + return to_der_internal(self, 0, 0, rb_str_drop_bytes(str, alllen - bodylen)); } /* @@ -1258,92 +1204,41 @@ ossl_asn1prim_to_der(VALUE self) static VALUE ossl_asn1cons_to_der(VALUE self) { - int tag, tn, tc, explicit, constructed = 1; - int found_prim = 0, seq_len; - long length; - unsigned char *p; - VALUE value, str, inf_length; - - tn = NUM2INT(ossl_asn1_get_tag(self)); - tc = ossl_asn1_tag_class(self); - inf_length = ossl_asn1_get_infinite_length(self); - if (inf_length == Qtrue) { - VALUE ary, example; - constructed = 2; - if (CLASS_OF(self) == cASN1Sequence || - CLASS_OF(self) == cASN1Set) { - tag = ossl_asn1_default_tag(self); - } - else { /* must be a constructive encoding of a primitive value */ - ary = ossl_asn1_get_value(self); - if (!rb_obj_is_kind_of(ary, rb_cArray)) - ossl_raise(eASN1Error, "Constructive value must be an Array"); - /* Recursively descend until a primitive value is found. - The overall value of the entire constructed encoding - is of the type of the first primitive encoding to be - found. */ - while (!found_prim){ - example = rb_ary_entry(ary, 0); - if (rb_obj_is_kind_of(example, cASN1Primitive)){ - found_prim = 1; - } - else { - /* example is another ASN1Constructive */ - if (!rb_obj_is_kind_of(example, cASN1Constructive)){ - ossl_raise(eASN1Error, "invalid constructed encoding"); - return Qnil; /* dummy */ - } - ary = ossl_asn1_get_value(example); - } - } - tag = ossl_asn1_default_tag(example); - } + VALUE ary, str; + long i; + int indef_len; + + indef_len = RTEST(ossl_asn1_get_indefinite_length(self)); + ary = rb_convert_type(ossl_asn1_get_value(self), T_ARRAY, "Array", "to_a"); + str = rb_str_new(NULL, 0); + for (i = 0; i < RARRAY_LEN(ary); i++) { + VALUE item = RARRAY_AREF(ary, i); + + if (indef_len && rb_obj_is_kind_of(item, cASN1EndOfContent)) { + if (i != RARRAY_LEN(ary) - 1) + ossl_raise(eASN1Error, "illegal EOC octets in value"); + + /* + * EOC is not really part of the content, but we required to add one + * at the end in the past. + */ + break; + } + + item = ossl_to_der_if_possible(item); + StringValue(item); + rb_str_append(str, item); } - else { - if (CLASS_OF(self) == cASN1Constructive) - ossl_raise(eASN1Error, "Constructive shall only be used with infinite length"); - tag = ossl_asn1_default_tag(self); - } - explicit = ossl_asn1_is_explicit(self); - value = join_der(ossl_asn1_get_value(self)); - - seq_len = ossl_asn1_object_size(constructed, RSTRING_LENINT(value), tag); - length = ossl_asn1_object_size(constructed, seq_len, tn); - str = rb_str_new(0, length); - p = (unsigned char *)RSTRING_PTR(str); - if(tc == V_ASN1_UNIVERSAL) - ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc); - else{ - if(explicit){ - ossl_asn1_put_object(&p, constructed, seq_len, tn, tc); - ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tag, V_ASN1_UNIVERSAL); - } - else{ - ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc); - } - } - memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value)); - p += RSTRING_LEN(value); - - /* In this case we need an additional EOC (one for the explicit part and - * one for the Constructive itself. The EOC for the Constructive is - * supplied by the user, but that for the "explicit wrapper" must be - * added here. - */ - if (explicit && inf_length == Qtrue) { - ASN1_put_eoc(&p); - } - ossl_str_adjust(str, p); - return str; + return to_der_internal(self, 1, indef_len, str); } /* * call-seq: * asn1_ary.each { |asn1| block } => asn1_ary * - * Calls <i>block</i> once for each element in +self+, passing that element - * as parameter +asn1+. If no block is given, an enumerator is returned + * Calls the given block once for each element in self, passing that element + * as parameter _asn1_. If no block is given, an enumerator is returned * instead. * * == Example @@ -1354,41 +1249,41 @@ ossl_asn1cons_to_der(VALUE self) static VALUE ossl_asn1cons_each(VALUE self) { - rb_ary_each(ossl_asn1_get_value(self)); + rb_block_call(ossl_asn1_get_value(self), id_each, 0, 0, 0, 0); + return self; } /* * call-seq: - * ObjectId.register(object_id, short_name, long_name) + * OpenSSL::ASN1::ObjectId.register(object_id, short_name, long_name) * - * This adds a new ObjectId to the internal tables. Where +object_id+ is the - * numerical form, +short_name+ is the short name, and +long_name+ is the long + * This adds a new ObjectId to the internal tables. Where _object_id_ is the + * numerical form, _short_name_ is the short name, and _long_name_ is the long * name. * - * Returns +true+ if successful. Raises an ASN1Error otherwise. + * Returns +true+ if successful. Raises an OpenSSL::ASN1::ASN1Error if it fails. * */ static VALUE ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln) { - StringValue(oid); - StringValue(sn); - StringValue(ln); + StringValueCStr(oid); + StringValueCStr(sn); + StringValueCStr(ln); if(!OBJ_create(RSTRING_PTR(oid), RSTRING_PTR(sn), RSTRING_PTR(ln))) - ossl_raise(eASN1Error, NULL); + ossl_raise(eASN1Error, NULL); return Qtrue; } -/* Document-method: OpenSSL::ASN1::ObjectId#sn - * - * The short name of the ObjectId, as defined in +openssl/objects.h+. - */ -/* Document-method: OpenSSL::ASN1::ObjectId#short_name +/* + * call-seq: + * oid.sn -> string + * oid.short_name -> string * - * #short_name is an alias to #sn + * The short name of the ObjectId, as defined in <openssl/objects.h>. */ static VALUE ossl_asn1obj_get_sn(VALUE self) @@ -1397,19 +1292,18 @@ ossl_asn1obj_get_sn(VALUE self) int nid; val = ossl_asn1_get_value(self); - if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef) - ret = rb_str_new2(OBJ_nid2sn(nid)); + if ((nid = OBJ_txt2nid(StringValueCStr(val))) != NID_undef) + ret = rb_str_new2(OBJ_nid2sn(nid)); return ret; } -/* Document-method: OpenSSL::ASN1::ObjectId#ln - * - * The long name of the ObjectId, as defined in +openssl/objects.h+. - */ -/* Document-method: OpenSSL::ASN1::ObjectId.long_name +/* + * call-seq: + * oid.ln -> string + * oid.long_name -> string * - * #long_name is an alias to #ln + * The long name of the ObjectId, as defined in <openssl/objects.h>. */ static VALUE ossl_asn1obj_get_ln(VALUE self) @@ -1418,29 +1312,57 @@ ossl_asn1obj_get_ln(VALUE self) int nid; val = ossl_asn1_get_value(self); - if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef) - ret = rb_str_new2(OBJ_nid2ln(nid)); + if ((nid = OBJ_txt2nid(StringValueCStr(val))) != NID_undef) + ret = rb_str_new2(OBJ_nid2ln(nid)); return ret; } -/* Document-method: OpenSSL::ASN1::ObjectId#oid +static VALUE +asn1obj_get_oid_i(VALUE vobj) +{ + return ossl_asn1obj_to_string_oid((const ASN1_OBJECT *)vobj); +} + +/* + * call-seq: + * oid.oid -> string * - * The object identifier as a String. + * Returns a String representing the Object Identifier in the dot notation, + * e.g. "1.2.3.4.5" */ static VALUE ossl_asn1obj_get_oid(VALUE self) { - VALUE val; + VALUE str; ASN1_OBJECT *a1obj; - char buf[128]; + int state; - val = ossl_asn1_get_value(self); - a1obj = obj_to_asn1obj(val); - OBJ_obj2txt(buf, sizeof(buf), a1obj, 1); + a1obj = ossl_to_asn1obj(ossl_asn1_get_value(self)); + str = rb_protect(asn1obj_get_oid_i, (VALUE)a1obj, &state); ASN1_OBJECT_free(a1obj); + if (state) + rb_jump_tag(state); + return str; +} + +/* + * call-seq: + * oid == other_oid => true or false + * + * Returns +true+ if _other_oid_ is the same as _oid_. + */ +static VALUE +ossl_asn1obj_eq(VALUE self, VALUE other) +{ + VALUE oid1, oid2; + + if (!rb_obj_is_kind_of(other, cASN1ObjectId)) + return Qfalse; - return rb_str_new2(buf); + oid1 = ossl_asn1obj_get_oid(self); + oid2 = ossl_asn1obj_get_oid(other); + return rb_str_equal(oid1, oid2); } #define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \ @@ -1474,25 +1396,20 @@ OSSL_ASN1_IMPL_FACTORY_METHOD(EndOfContent) void Init_ossl_asn1(void) { - VALUE ary; - int i; +#undef rb_intern -#if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ -#endif - - sUNIVERSAL = rb_intern("UNIVERSAL"); - sCONTEXT_SPECIFIC = rb_intern("CONTEXT_SPECIFIC"); - sAPPLICATION = rb_intern("APPLICATION"); - sPRIVATE = rb_intern("PRIVATE"); - sEXPLICIT = rb_intern("EXPLICIT"); - sIMPLICIT = rb_intern("IMPLICIT"); + sym_UNIVERSAL = ID2SYM(rb_intern_const("UNIVERSAL")); + sym_CONTEXT_SPECIFIC = ID2SYM(rb_intern_const("CONTEXT_SPECIFIC")); + sym_APPLICATION = ID2SYM(rb_intern_const("APPLICATION")); + sym_PRIVATE = ID2SYM(rb_intern_const("PRIVATE")); + sym_EXPLICIT = ID2SYM(rb_intern_const("EXPLICIT")); + sym_IMPLICIT = ID2SYM(rb_intern_const("IMPLICIT")); sivVALUE = rb_intern("@value"); sivTAG = rb_intern("@tag"); sivTAGGING = rb_intern("@tagging"); sivTAG_CLASS = rb_intern("@tag_class"); - sivINFINITE_LENGTH = rb_intern("@infinite_length"); + sivINDEFINITE_LENGTH = rb_intern("@indefinite_length"); sivUNUSED_BITS = rb_intern("@unused_bits"); /* @@ -1518,24 +1435,21 @@ Init_ossl_asn1(void) * == ASN.1 class hierarchy * * The base class representing ASN.1 structures is ASN1Data. ASN1Data offers - * attributes to read and set the +tag+, the +tag_class+ and finally the - * +value+ of a particular ASN.1 item. Upon parsing, any tagged values + * attributes to read and set the _tag_, the _tag_class_ and finally the + * _value_ of a particular ASN.1 item. Upon parsing, any tagged values * (implicit or explicit) will be represented by ASN1Data instances because * their "real type" can only be determined using out-of-band information * from the ASN.1 type declaration. Since this information is normally * known when encoding a type, all sub-classes of ASN1Data offer an - * additional attribute +tagging+ that allows to encode a value implicitly + * additional attribute _tagging_ that allows to encode a value implicitly * (+:IMPLICIT+) or explicitly (+:EXPLICIT+). * * === Constructive * * Constructive is, as its name implies, the base class for all * constructed encodings, i.e. those that consist of several values, - * opposed to "primitive" encodings with just one single value. - * Primitive values that are encoded with "infinite length" are typically - * constructed (their values come in multiple chunks) and are therefore - * represented by instances of Constructive. The value of an Constructive - * is always an Array. + * opposed to "primitive" encodings with just one single value. The value of + * an Constructive is always an Array. * * ==== ASN1::Set and ASN1::Sequence * @@ -1552,18 +1466,18 @@ Init_ossl_asn1(void) * Please cf. Primitive documentation for details on sub-classes and * their respective mappings of ASN.1 data types to Ruby objects. * - * == Possible values for +tagging+ + * == Possible values for _tagging_ * * When constructing an ASN1Data object the ASN.1 type definition may * require certain elements to be either implicitly or explicitly tagged. - * This can be achieved by setting the +tagging+ attribute manually for + * This can be achieved by setting the _tagging_ attribute manually for * sub-classes of ASN1Data. Use the symbol +:IMPLICIT+ for implicit * tagging and +:EXPLICIT+ if the element requires explicit tagging. * - * == Possible values for +tag_class+ + * == Possible values for _tag_class_ * * It is possible to create arbitrary ASN1Data objects that also support - * a PRIVATE or APPLICATION tag class. Possible values for the +tag_class+ + * a PRIVATE or APPLICATION tag class. Possible values for the _tag_class_ * attribute are: * * +:UNIVERSAL+ (the default for untagged values) * * +:CONTEXT_SPECIFIC+ (the default for tagged values) @@ -1601,7 +1515,7 @@ Init_ossl_asn1(void) * * An Array that stores the name of a given tag number. These names are * the same as the name of the tag constant that is additionally defined, - * e.g. UNIVERSAL_TAG_NAME[2] = "INTEGER" and OpenSSL::ASN1::INTEGER = 2. + * e.g. <tt>UNIVERSAL_TAG_NAME[2] = "INTEGER"</tt> and <tt>OpenSSL::ASN1::INTEGER = 2</tt>. * * == Example usage * @@ -1632,17 +1546,20 @@ Init_ossl_asn1(void) rb_define_module_function(mASN1, "traverse", ossl_asn1_traverse, 1); rb_define_module_function(mASN1, "decode", ossl_asn1_decode, 1); rb_define_module_function(mASN1, "decode_all", ossl_asn1_decode_all, 1); - ary = rb_ary_new(); + VALUE ary = rb_ary_new_capa(ossl_asn1_info_size); + for (int i = 0; i < ossl_asn1_info_size; i++) { + const char *name = ossl_asn1_info[i].name; + if (name[0] == '[') + continue; + rb_define_const(mASN1, name, INT2NUM(i)); + rb_ary_store(ary, i, rb_obj_freeze(rb_str_new_cstr(name))); + } + rb_obj_freeze(ary); /* * Array storing tag names at the tag's index. */ rb_define_const(mASN1, "UNIVERSAL_TAG_NAME", ary); - for(i = 0; i < ossl_asn1_info_size; i++){ - if(ossl_asn1_info[i].name[0] == '[') continue; - rb_define_const(mASN1, ossl_asn1_info[i].name, INT2NUM(i)); - rb_ary_store(ary, i, rb_str_new2(ossl_asn1_info[i].name)); - } /* Document-class: OpenSSL::ASN1::ASN1Data * @@ -1665,9 +1582,9 @@ Init_ossl_asn1(void) * * An implicitly 1-tagged INTEGER value will be parsed as an * ASN1Data with - * * +tag+ equal to 1 - * * +tag_class+ equal to +:CONTEXT_SPECIFIC+ - * * +value+ equal to a +String+ that carries the raw encoding + * * _tag_ equal to 1 + * * _tag_class_ equal to +:CONTEXT_SPECIFIC+ + * * _value_ equal to a String that carries the raw encoding * of the INTEGER. * This implies that a subsequent decoding step is required to * completely decode implicitly tagged values. @@ -1676,9 +1593,9 @@ Init_ossl_asn1(void) * * An explicitly 1-tagged INTEGER value will be parsed as an * ASN1Data with - * * +tag+ equal to 1 - * * +tag_class+ equal to +:CONTEXT_SPECIFIC+ - * * +value+ equal to an +Array+ with one single element, an + * * _tag_ equal to 1 + * * _tag_class_ equal to +:CONTEXT_SPECIFIC+ + * * _value_ equal to an Array with one single element, an * instance of OpenSSL::ASN1::Integer, i.e. the inner element * is the non-tagged primitive value, and the tagging is represented * in the outer ASN1Data @@ -1689,13 +1606,13 @@ Init_ossl_asn1(void) * der = seq.to_der * asn1 = OpenSSL::ASN1.decode(der) * # pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0 - * # @infinite_length=false, + * # @indefinite_length=false, * # @tag=16, * # @tag_class=:UNIVERSAL, * # @tagging=nil, * # @value= * # [#<OpenSSL::ASN1::ASN1Data:0x87326f4 - * # @infinite_length=false, + * # @indefinite_length=false, * # @tag=0, * # @tag_class=:CONTEXT_SPECIFIC, * # @value="\x01">]> @@ -1712,18 +1629,18 @@ Init_ossl_asn1(void) * der = seq.to_der * asn1 = OpenSSL::ASN1.decode(der) * # pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0 - * # @infinite_length=false, + * # @indefinite_length=false, * # @tag=16, * # @tag_class=:UNIVERSAL, * # @tagging=nil, * # @value= * # [#<OpenSSL::ASN1::ASN1Data:0x87326f4 - * # @infinite_length=false, + * # @indefinite_length=false, * # @tag=0, * # @tag_class=:CONTEXT_SPECIFIC, * # @value= * # [#<OpenSSL::ASN1::Integer:0x85bf308 - * # @infinite_length=false, + * # @indefinite_length=false, * # @tag=2, * # @tag_class=:UNIVERSAL * # @tagging=nil, @@ -1739,90 +1656,92 @@ Init_ossl_asn1(void) */ rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0); /* - * A +Number+ representing the tag number of this ASN1Data. Never +nil+. + * An Integer representing the tag number of this ASN1Data. Never +nil+. */ rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0); /* - * A +Symbol+ representing the tag class of this ASN1Data. Never +nil+. + * A Symbol representing the tag class of this ASN1Data. Never +nil+. * See ASN1Data for possible values. */ rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0); /* - * Never +nil+. A +Boolean+ indicating whether the encoding was infinite - * length (in the case of parsing) or whether an infinite length encoding - * shall be used (in the encoding case). - * In DER, every value has a finite length associated with it. But in - * scenarios where large amounts of data need to be transferred it - * might be desirable to have some kind of streaming support available. + * Never +nil+. A boolean value indicating whether the encoding uses + * indefinite length (in the case of parsing) or whether an indefinite + * length form shall be used (in the encoding case). + * In DER, every value uses definite length form. But in scenarios where + * large amounts of data need to be transferred it might be desirable to + * have some kind of streaming support available. * For example, huge OCTET STRINGs are preferably sent in smaller-sized * chunks, each at a time. * This is possible in BER by setting the length bytes of an encoding * to zero and by this indicating that the following value will be - * sent in chunks. Infinite length encodings are always constructed. + * sent in chunks. Indefinite length encodings are always constructed. * The end of such a stream of chunks is indicated by sending a EOC - * (End of Content) tag. SETs and SEQUENCEs may use an infinite length + * (End of Content) tag. SETs and SEQUENCEs may use an indefinite length * encoding, but also primitive types such as e.g. OCTET STRINGS or * BIT STRINGS may leverage this functionality (cf. ITU-T X.690). */ - rb_attr(cASN1Data, rb_intern("infinite_length"), 1, 1, 0); + rb_attr(cASN1Data, rb_intern("indefinite_length"), 1, 1, 0); + rb_define_alias(cASN1Data, "infinite_length", "indefinite_length"); + rb_define_alias(cASN1Data, "infinite_length=", "indefinite_length="); rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3); rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0); /* Document-class: OpenSSL::ASN1::Primitive * * The parent class for all primitive encodings. Attributes are the same as - * for ASN1Data, with the addition of +tagging+. - * Primitive values can never be infinite length encodings, thus it is not - * possible to set the +infinite_length+ attribute for Primitive and its - * sub-classes. + * for ASN1Data, with the addition of _tagging_. + * Primitive values can never be encoded with indefinite length form, thus + * it is not possible to set the _indefinite_length_ attribute for Primitive + * and its sub-classes. * * == Primitive sub-classes and their mapping to Ruby classes - * * OpenSSL::ASN1::EndOfContent <=> +value+ is always +nil+ - * * OpenSSL::ASN1::Boolean <=> +value+ is a +Boolean+ - * * OpenSSL::ASN1::Integer <=> +value+ is a +Number+ - * * OpenSSL::ASN1::BitString <=> +value+ is a +String+ - * * OpenSSL::ASN1::OctetString <=> +value+ is a +String+ - * * OpenSSL::ASN1::Null <=> +value+ is always +nil+ - * * OpenSSL::ASN1::Object <=> +value+ is a +String+ - * * OpenSSL::ASN1::Enumerated <=> +value+ is a +Number+ - * * OpenSSL::ASN1::UTF8String <=> +value+ is a +String+ - * * OpenSSL::ASN1::NumericString <=> +value+ is a +String+ - * * OpenSSL::ASN1::PrintableString <=> +value+ is a +String+ - * * OpenSSL::ASN1::T61String <=> +value+ is a +String+ - * * OpenSSL::ASN1::VideotexString <=> +value+ is a +String+ - * * OpenSSL::ASN1::IA5String <=> +value+ is a +String+ - * * OpenSSL::ASN1::UTCTime <=> +value+ is a +Time+ - * * OpenSSL::ASN1::GeneralizedTime <=> +value+ is a +Time+ - * * OpenSSL::ASN1::GraphicString <=> +value+ is a +String+ - * * OpenSSL::ASN1::ISO64String <=> +value+ is a +String+ - * * OpenSSL::ASN1::GeneralString <=> +value+ is a +String+ - * * OpenSSL::ASN1::UniversalString <=> +value+ is a +String+ - * * OpenSSL::ASN1::BMPString <=> +value+ is a +String+ + * * OpenSSL::ASN1::EndOfContent <=> _value_ is always +nil+ + * * OpenSSL::ASN1::Boolean <=> _value_ is +true+ or +false+ + * * OpenSSL::ASN1::Integer <=> _value_ is an OpenSSL::BN + * * OpenSSL::ASN1::BitString <=> _value_ is a String + * * OpenSSL::ASN1::OctetString <=> _value_ is a String + * * OpenSSL::ASN1::Null <=> _value_ is always +nil+ + * * OpenSSL::ASN1::Object <=> _value_ is a String + * * OpenSSL::ASN1::Enumerated <=> _value_ is an OpenSSL::BN + * * OpenSSL::ASN1::UTF8String <=> _value_ is a String + * * OpenSSL::ASN1::NumericString <=> _value_ is a String + * * OpenSSL::ASN1::PrintableString <=> _value_ is a String + * * OpenSSL::ASN1::T61String <=> _value_ is a String + * * OpenSSL::ASN1::VideotexString <=> _value_ is a String + * * OpenSSL::ASN1::IA5String <=> _value_ is a String + * * OpenSSL::ASN1::UTCTime <=> _value_ is a Time + * * OpenSSL::ASN1::GeneralizedTime <=> _value_ is a Time + * * OpenSSL::ASN1::GraphicString <=> _value_ is a String + * * OpenSSL::ASN1::ISO64String <=> _value_ is a String + * * OpenSSL::ASN1::GeneralString <=> _value_ is a String + * * OpenSSL::ASN1::UniversalString <=> _value_ is a String + * * OpenSSL::ASN1::BMPString <=> _value_ is a String * * == OpenSSL::ASN1::BitString * * === Additional attributes - * +unused_bits+: if the underlying BIT STRING's - * length is a multiple of 8 then +unused_bits+ is 0. Otherwise - * +unused_bits+ indicates the number of bits that are to be ignored in - * the final octet of the +BitString+'s +value+. + * _unused_bits_: if the underlying BIT STRING's + * length is a multiple of 8 then _unused_bits_ is 0. Otherwise + * _unused_bits_ indicates the number of bits that are to be ignored in + * the final octet of the BitString's _value_. * * == OpenSSL::ASN1::ObjectId * - * While OpenSSL::ASN1::ObjectId.new will allocate a new ObjectId, it is - * not typically allocated this way, but rather that are received from + * NOTE: While OpenSSL::ASN1::ObjectId.new will allocate a new ObjectId, + * it is not typically allocated this way, but rather that are received from * parsed ASN1 encodings. * * === Additional attributes - * * +sn+: the short name as defined in <openssl/objects.h>. - * * +ln+: the long name as defined in <openssl/objects.h>. - * * +oid+: the object identifier as a +String+, e.g. "1.2.3.4.5" - * * +short_name+: alias for +sn+. - * * +long_name+: alias for +ln+. + * * _sn_: the short name as defined in <openssl/objects.h>. + * * _ln_: the long name as defined in <openssl/objects.h>. + * * _oid_: the object identifier as a String, e.g. "1.2.3.4.5" + * * _short_name_: alias for _sn_. + * * _long_name_: alias for _ln_. * * == Examples * With the Exception of OpenSSL::ASN1::EndOfContent, each Primitive class - * constructor takes at least one parameter, the +value+. + * constructor takes at least one parameter, the _value_. * * === Creating EndOfContent * eoc = OpenSSL::ASN1::EndOfContent.new @@ -1836,19 +1755,20 @@ Init_ossl_asn1(void) /* * May be used as a hint for encoding a value either implicitly or * explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+. - * +tagging+ is not set when a ASN.1 structure is parsed using + * _tagging_ is not set when a ASN.1 structure is parsed using * OpenSSL::ASN1.decode. */ rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue); + rb_undef_method(cASN1Primitive, "indefinite_length="); rb_undef_method(cASN1Primitive, "infinite_length="); rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1); rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0); /* Document-class: OpenSSL::ASN1::Constructive * - * The parent class for all constructed encodings. The +value+ attribute - * of a Constructive is always an +Array+. Attributes are the same as - * for ASN1Data, with the addition of +tagging+. + * The parent class for all constructed encodings. The _value_ attribute + * of a Constructive is always an Array. Attributes are the same as + * for ASN1Data, with the addition of _tagging_. * * == SET and SEQUENCE * @@ -1870,48 +1790,13 @@ Init_ossl_asn1(void) * int = OpenSSL::ASN1::Integer.new(1) * str = OpenSSL::ASN1::PrintableString.new('abc') * set = OpenSSL::ASN1::Set.new( [ int, str ] ) - * - * == Infinite length primitive values - * - * The only case where Constructive is used directly is for infinite - * length encodings of primitive values. These encodings are always - * constructed, with the contents of the +value+ +Array+ being either - * UNIVERSAL non-infinite length partial encodings of the actual value - * or again constructive encodings with infinite length (i.e. infinite - * length primitive encodings may be constructed recursively with another - * infinite length value within an already infinite length value). Each - * partial encoding must be of the same UNIVERSAL type as the overall - * encoding. The value of the overall encoding consists of the - * concatenation of each partial encoding taken in sequence. The +value+ - * array of the outer infinite length value must end with a - * OpenSSL::ASN1::EndOfContent instance. - * - * Please note that it is not possible to encode Constructive without - * the +infinite_length+ attribute being set to +true+, use - * OpenSSL::ASN1::Sequence or OpenSSL::ASN1::Set in these cases instead. - * - * === Example - Infinite length OCTET STRING - * partial1 = OpenSSL::ASN1::OctetString.new("\x01") - * partial2 = OpenSSL::ASN1::OctetString.new("\x02") - * inf_octets = OpenSSL::ASN1::Constructive.new( [ partial1, - * partial2, - * OpenSSL::ASN1::EndOfContent.new ], - * OpenSSL::ASN1::OCTET_STRING, - * nil, - * :UNIVERSAL ) - * # The real value of inf_octets is "\x01\x02", i.e. the concatenation - * # of partial1 and partial2 - * inf_octets.infinite_length = true - * der = inf_octets.to_der - * asn1 = OpenSSL::ASN1.decode(der) - * puts asn1.infinite_length # => true */ cASN1Constructive = rb_define_class_under(mASN1,"Constructive", cASN1Data); rb_include_module(cASN1Constructive, rb_mEnumerable); /* * May be used as a hint for encoding a value either implicitly or * explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+. - * +tagging+ is not set when a ASN.1 structure is parsed using + * _tagging_ is not set when a ASN.1 structure is parsed using * OpenSSL::ASN1.decode. */ rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue); @@ -1965,11 +1850,14 @@ do{\ rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0); rb_define_alias(cASN1ObjectId, "short_name", "sn"); rb_define_alias(cASN1ObjectId, "long_name", "ln"); + rb_define_method(cASN1ObjectId, "==", ossl_asn1obj_eq, 1); rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0); rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0); + rb_define_method(cASN1EndOfContent, "to_der", ossl_asn1eoc_to_der, 0); class_tag_map = rb_hash_new(); + rb_gc_register_mark_object(class_tag_map); rb_hash_aset(class_tag_map, cASN1EndOfContent, INT2NUM(V_ASN1_EOC)); rb_hash_aset(class_tag_map, cASN1Boolean, INT2NUM(V_ASN1_BOOLEAN)); rb_hash_aset(class_tag_map, cASN1Integer, INT2NUM(V_ASN1_INTEGER)); @@ -1993,5 +1881,7 @@ do{\ rb_hash_aset(class_tag_map, cASN1GeneralString, INT2NUM(V_ASN1_GENERALSTRING)); rb_hash_aset(class_tag_map, cASN1UniversalString, INT2NUM(V_ASN1_UNIVERSALSTRING)); rb_hash_aset(class_tag_map, cASN1BMPString, INT2NUM(V_ASN1_BMPSTRING)); - rb_global_variable(&class_tag_map); + rb_obj_freeze(class_tag_map); + + id_each = rb_intern_const("each"); } diff --git a/ext/openssl/ossl_asn1.h b/ext/openssl/ossl_asn1.h index 718f43f068..b605df8f3f 100644 --- a/ext/openssl/ossl_asn1.h +++ b/ext/openssl/ossl_asn1.h @@ -1,12 +1,11 @@ /* - * $Id$ * 'OpenSSL for Ruby' team members * Copyright (C) 2003 * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(_OSSL_ASN1_H_) #define _OSSL_ASN1_H_ @@ -14,45 +13,45 @@ /* * ASN1_DATE conversions */ -VALUE asn1time_to_time(ASN1_TIME *); -time_t time_to_time_t(VALUE); +VALUE asn1time_to_time(const ASN1_TIME *); +/* Splits VALUE to seconds and offset days. VALUE is typically a Time or an + * Integer. This is used when updating ASN1_*TIME with ASN1_TIME_adj() or + * X509_time_adj_ex(). We can't use ASN1_TIME_set() and X509_time_adj() because + * they have the Year 2038 issue on sizeof(time_t) == 4 environment */ +void ossl_time_split(VALUE, time_t *, int *); /* * ASN1_STRING conversions */ -VALUE asn1str_to_str(ASN1_STRING *); +VALUE asn1str_to_str(const ASN1_STRING *); /* * ASN1_INTEGER conversions */ -VALUE asn1integer_to_num(ASN1_INTEGER *); +VALUE asn1integer_to_num(const ASN1_INTEGER *); ASN1_INTEGER *num_to_asn1integer(VALUE, ASN1_INTEGER *); /* + * ASN1_OBJECT conversions + */ +ASN1_OBJECT *ossl_to_asn1obj(VALUE obj); +/* + * Returns the short name if available, the dotted decimal notation otherwise. + * This is the most common way to return ASN1_OBJECT to Ruby. + */ +VALUE ossl_asn1obj_to_string(const ASN1_OBJECT *a1obj); +/* + * However, some places use long names instead. This is likely unintentional, + * but we keep the current behavior in existing methods. + */ +VALUE ossl_asn1obj_to_string_long_name(const ASN1_OBJECT *a1obj); + +/* * ASN1 module */ extern VALUE mASN1; -extern VALUE eASN1Error; extern VALUE cASN1Data; -extern VALUE cASN1Primitive; -extern VALUE cASN1Constructive; - -extern VALUE cASN1Boolean; /* BOOLEAN */ -extern VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */ -extern VALUE cASN1BitString; /* BIT STRING */ -extern VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */ -extern VALUE cASN1NumericString, cASN1PrintableString; -extern VALUE cASN1T61String, cASN1VideotexString; -extern VALUE cASN1IA5String, cASN1GraphicString; -extern VALUE cASN1ISO64String, cASN1GeneralString; -extern VALUE cASN1UniversalString, cASN1BMPString; -extern VALUE cASN1Null; /* NULL */ -extern VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */ -extern VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */ -extern VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */ - -ASN1_TYPE *ossl_asn1_get_asn1type(VALUE); void Init_ossl_asn1(void); diff --git a/ext/openssl/ossl_bio.c b/ext/openssl/ossl_bio.c index e150de0ad9..4edde5091d 100644 --- a/ext/openssl/ossl_bio.c +++ b/ext/openssl/ossl_bio.c @@ -1,87 +1,42 @@ /* - * $Id$ * 'OpenSSL for Ruby' team members * Copyright (C) 2003 * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif BIO * -ossl_obj2bio(VALUE obj) +ossl_obj2bio(volatile VALUE *pobj) { + VALUE obj = *pobj; BIO *bio; - if (RB_TYPE_P(obj, T_FILE)) { - rb_io_t *fptr; - FILE *fp; - int fd; - - GetOpenFile(obj, fptr); - rb_io_check_readable(fptr); - if ((fd = rb_cloexec_dup(FPTR_TO_FD(fptr))) < 0){ - rb_sys_fail(0); - } - rb_update_max_fd(fd); - if (!(fp = fdopen(fd, "r"))){ - close(fd); - rb_sys_fail(0); - } - if (!(bio = BIO_new_fp(fp, BIO_CLOSE))){ - fclose(fp); - ossl_raise(eOSSLError, NULL); - } - } - else { - StringValue(obj); - bio = BIO_new_mem_buf(RSTRING_PTR(obj), RSTRING_LENINT(obj)); - if (!bio) ossl_raise(eOSSLError, NULL); - } - + if (RB_TYPE_P(obj, T_FILE)) + obj = rb_funcallv(obj, rb_intern("read"), 0, NULL); + StringValue(obj); + bio = BIO_new_mem_buf(RSTRING_PTR(obj), RSTRING_LENINT(obj)); + if (!bio) + ossl_raise(eOSSLError, "BIO_new_mem_buf"); + *pobj = obj; return bio; } -BIO * -ossl_protect_obj2bio(VALUE obj, int *status) -{ - BIO *ret = NULL; - ret = (BIO*)rb_protect((VALUE(*)_((VALUE)))ossl_obj2bio, obj, status); - return ret; -} - VALUE -ossl_membio2str0(BIO *bio) +ossl_membio2str(BIO *bio) { VALUE ret; + int state; BUF_MEM *buf; BIO_get_mem_ptr(bio, &buf); - ret = rb_str_new(buf->data, buf->length); - - return ret; -} - -VALUE -ossl_protect_membio2str(BIO *bio, int *status) -{ - return rb_protect((VALUE(*)_((VALUE)))ossl_membio2str0, (VALUE)bio, status); -} - -VALUE -ossl_membio2str(BIO *bio) -{ - VALUE ret; - int status = 0; - - ret = ossl_protect_membio2str(bio, &status); + ret = ossl_str_new(buf->data, buf->length, &state); BIO_free(bio); - if(status) rb_jump_tag(status); + if (state) + rb_jump_tag(state); return ret; } diff --git a/ext/openssl/ossl_bio.h b/ext/openssl/ossl_bio.h index 2d8f675c5b..1b871f1cd7 100644 --- a/ext/openssl/ossl_bio.h +++ b/ext/openssl/ossl_bio.h @@ -1,21 +1,16 @@ /* - * $Id$ * 'OpenSSL for Ruby' team members * Copyright (C) 2003 * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(_OSSL_BIO_H_) #define _OSSL_BIO_H_ -BIO *ossl_obj2bio(VALUE); -BIO *ossl_protect_obj2bio(VALUE,int*); -VALUE ossl_membio2str0(BIO*); +BIO *ossl_obj2bio(volatile VALUE *); VALUE ossl_membio2str(BIO*); -VALUE ossl_protect_membio2str(BIO*,int*); #endif - diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c index 58796fe2a4..9014f2df2b 100644 --- a/ext/openssl/ossl_bn.c +++ b/ext/openssl/ossl_bn.c @@ -1,33 +1,29 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Technorama team <oss-ruby@technorama.net> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ /* modified by Michal Rokos <m.rokos@sh.cvut.cz> */ #include "ossl.h" -#define WrapBN(klass, obj, bn) do { \ - if (!(bn)) { \ - ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \ - } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_bn_type, (bn)); \ +#define NewBN(klass) \ + TypedData_Wrap_Struct((klass), &ossl_bn_type, 0) +#define SetBN(obj, bn) do { \ + if (!(bn)) { \ + ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \ + } \ + RTYPEDDATA_DATA(obj) = (bn); \ } while (0) #define GetBN(obj, bn) do { \ - TypedData_Get_Struct((obj), BIGNUM, &ossl_bn_type, (bn)); \ - if (!(bn)) { \ - ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \ - } \ -} while (0) - -#define SafeGetBN(obj, bn) do { \ - OSSL_Check_Kind((obj), cBN); \ - GetBN((obj), (bn)); \ + TypedData_Get_Struct((obj), BIGNUM, &ossl_bn_type, (bn)); \ + if (!(bn)) { \ + ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \ + } \ } while (0) static void @@ -36,24 +32,24 @@ ossl_bn_free(void *ptr) BN_clear_free(ptr); } -static size_t -ossl_bn_size(const void *ptr) -{ - return sizeof(BIGNUM); -} - static const rb_data_type_t ossl_bn_type = { "OpenSSL/BN", - {0, ossl_bn_free, ossl_bn_size,}, - 0, 0, - RUBY_TYPED_FREE_IMMEDIATELY, + { + 0, ossl_bn_free, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE, }; /* * Classes */ VALUE cBN; -VALUE eBNError; + +/* Document-class: OpenSSL::BNError + * + * Generic Error for all of OpenSSL::BN (big num) + */ +static VALUE eBNError; /* * Public @@ -64,70 +60,187 @@ ossl_bn_new(const BIGNUM *bn) BIGNUM *newbn; VALUE obj; - newbn = bn ? BN_dup(bn) : BN_new(); - if (!newbn) { - ossl_raise(eBNError, NULL); - } - WrapBN(cBN, obj, newbn); + obj = NewBN(cBN); + newbn = BN_dup(bn); + if (!newbn) + ossl_raise(eBNError, "BN_dup"); + SetBN(obj, newbn); return obj; } -BIGNUM * -GetBNPtr(VALUE obj) -{ - BIGNUM *bn = NULL; - - if (RTEST(rb_obj_is_kind_of(obj, cBN))) { - GetBN(obj, bn); - } else switch (TYPE(obj)) { - case T_FIXNUM: - case T_BIGNUM: - obj = rb_String(obj); - if (!BN_dec2bn(&bn, StringValuePtr(obj))) { - ossl_raise(eBNError, NULL); - } - WrapBN(cBN, obj, bn); /* Handle potencial mem leaks */ - break; - case T_NIL: - break; - default: - ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN"); +static BIGNUM * +integer_to_bnptr(VALUE obj, BIGNUM *orig) +{ + BIGNUM *bn; + + if (FIXNUM_P(obj)) { + long i; + unsigned char bin[sizeof(long)]; + long n = FIX2LONG(obj); + unsigned long un = labs(n); + + for (i = sizeof(long) - 1; 0 <= i; i--) { + bin[i] = un & 0xff; + un >>= 8; + } + + bn = BN_bin2bn(bin, sizeof(bin), orig); + if (!bn) + ossl_raise(eBNError, "BN_bin2bn"); + if (n < 0) + BN_set_negative(bn, 1); + } + else { /* assuming Bignum */ + size_t len = rb_absint_size(obj, NULL); + unsigned char *bin; + VALUE buf; + int sign; + + if (INT_MAX < len) { + rb_raise(eBNError, "bignum too long"); + } + bin = (unsigned char*)ALLOCV_N(unsigned char, buf, len); + sign = rb_integer_pack(obj, bin, len, 1, 0, INTEGER_PACK_BIG_ENDIAN); + + bn = BN_bin2bn(bin, (int)len, orig); + ALLOCV_END(buf); + if (!bn) + ossl_raise(eBNError, "BN_bin2bn"); + if (sign < 0) + BN_set_negative(bn, 1); } + + return bn; +} + +static VALUE +try_convert_to_bn(VALUE obj) +{ + BIGNUM *bn; + VALUE newobj = Qnil; + + if (rb_obj_is_kind_of(obj, cBN)) + return obj; + if (RB_INTEGER_TYPE_P(obj)) { + newobj = NewBN(cBN); /* Handle potential mem leaks */ + bn = integer_to_bnptr(obj, NULL); + SetBN(newobj, bn); + } + + return newobj; +} + +BIGNUM * +ossl_bn_value_ptr(volatile VALUE *ptr) +{ + VALUE tmp; + BIGNUM *bn; + + tmp = try_convert_to_bn(*ptr); + if (NIL_P(tmp)) + ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN"); + GetBN(tmp, bn); + *ptr = tmp; + return bn; } /* * Private */ -/* - * BN_CTX - is used in more difficult math. ops - * (Why just 1? Because Ruby itself isn't thread safe, - * we don't need to care about threads) - */ -BN_CTX *ossl_bn_ctx; + +#ifdef HAVE_RB_EXT_RACTOR_SAFE +static void +ossl_bn_ctx_free(void *ptr) +{ + BN_CTX *ctx = (BN_CTX *)ptr; + BN_CTX_free(ctx); +} + +static struct rb_ractor_local_storage_type ossl_bn_ctx_key_type = { + NULL, // mark + ossl_bn_ctx_free, +}; + +static rb_ractor_local_key_t ossl_bn_ctx_key; + +BN_CTX * +ossl_bn_ctx_get(void) +{ + // stored in ractor local storage + + BN_CTX *ctx = rb_ractor_local_storage_ptr(ossl_bn_ctx_key); + if (!ctx) { + if (!(ctx = BN_CTX_new())) { + ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX"); + } + rb_ractor_local_storage_ptr_set(ossl_bn_ctx_key, ctx); + } + return ctx; +} +#else +// for ruby 2.x +static BN_CTX *gv_ossl_bn_ctx; + +BN_CTX * +ossl_bn_ctx_get(void) +{ + if (gv_ossl_bn_ctx == NULL) { + if (!(gv_ossl_bn_ctx = BN_CTX_new())) { + ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX"); + } + } + return gv_ossl_bn_ctx; +} + +void +ossl_bn_ctx_free(void) +{ + BN_CTX_free(gv_ossl_bn_ctx); + gv_ossl_bn_ctx = NULL; +} +#endif static VALUE ossl_bn_alloc(VALUE klass) { BIGNUM *bn; - VALUE obj; + VALUE obj = NewBN(klass); if (!(bn = BN_new())) { - ossl_raise(eBNError, NULL); + ossl_raise(eBNError, NULL); } - WrapBN(klass, obj, bn); + SetBN(obj, bn); return obj; } /* * call-seq: - * BN.new => aBN - * BN.new(bn) => aBN - * BN.new(integer) => aBN - * BN.new(string) => aBN - * BN.new(string, 0 | 2 | 10 | 16) => aBN + * OpenSSL::BN.new(bn) -> aBN + * OpenSSL::BN.new(integer) -> aBN + * OpenSSL::BN.new(string, base = 10) -> aBN + * + * Construct a new \OpenSSL BIGNUM object. + * + * If +bn+ is an Integer or OpenSSL::BN, a new instance of OpenSSL::BN + * representing the same value is returned. See also Integer#to_bn for the + * short-hand. + * + * If a String is given, the content will be parsed according to +base+. + * + * +string+:: + * The string to be parsed. + * +base+:: + * The format. Must be one of the following: + * - +0+ - MPI format. See the man page BN_mpi2bn(3) for details. + * - +2+ - Variable-length and big-endian binary encoding of a positive + * number. + * - +10+ - Decimal number representation, with a leading '-' for a negative + * number. + * - +16+ - Hexadecimal number representation, with a leading '-' for a + * negative number. */ static VALUE ossl_bn_initialize(int argc, VALUE *argv, VALUE self) @@ -135,102 +248,82 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self) BIGNUM *bn; VALUE str, bs; int base = 10; + char *ptr; if (rb_scan_args(argc, argv, "11", &str, &bs) == 2) { - base = NUM2INT(bs); - } - - if (RB_TYPE_P(str, T_FIXNUM)) { - long i; - unsigned char bin[sizeof(long)]; - long n = FIX2LONG(str); - unsigned long un = labs(n); - - for (i = sizeof(long) - 1; 0 <= i; i--) { - bin[i] = un&0xff; - un >>= 8; - } - - GetBN(self, bn); - if (!BN_bin2bn(bin, sizeof(bin), bn)) { - ossl_raise(eBNError, NULL); - } - if (n < 0) BN_set_negative(bn, 1); - return self; - } - else if (RB_TYPE_P(str, T_BIGNUM)) { - size_t len = rb_absint_size(str, NULL); - unsigned char *bin; - VALUE buf; - int sign; + base = NUM2INT(bs); + } - if (INT_MAX < len) { - rb_raise(eBNError, "bignum too long"); - } - bin = (unsigned char*)ALLOCV_N(unsigned char, buf, len); - sign = rb_integer_pack(str, bin, len, 1, 0, INTEGER_PACK_BIG_ENDIAN); + if (NIL_P(str)) { + ossl_raise(rb_eArgError, "invalid argument"); + } - GetBN(self, bn); - if (!BN_bin2bn(bin, (int)len, bn)) { - ALLOCV_END(buf); - ossl_raise(eBNError, NULL); - } - ALLOCV_END(buf); - if (sign < 0) BN_set_negative(bn, 1); - return self; + rb_check_frozen(self); + if (RB_INTEGER_TYPE_P(str)) { + GetBN(self, bn); + integer_to_bnptr(str, bn); + + return self; } + if (RTEST(rb_obj_is_kind_of(str, cBN))) { - BIGNUM *other; + BIGNUM *other; - GetBN(self, bn); - GetBN(str, other); /* Safe - we checked kind_of? above */ - if (!BN_copy(bn, other)) { - ossl_raise(eBNError, NULL); - } - return self; + GetBN(self, bn); + GetBN(str, other); /* Safe - we checked kind_of? above */ + if (!BN_copy(bn, other)) { + ossl_raise(eBNError, NULL); + } + return self; } - StringValue(str); GetBN(self, bn); switch (base) { - case 0: - if (!BN_mpi2bn((unsigned char *)RSTRING_PTR(str), RSTRING_LENINT(str), bn)) { - ossl_raise(eBNError, NULL); - } - break; - case 2: - if (!BN_bin2bn((unsigned char *)RSTRING_PTR(str), RSTRING_LENINT(str), bn)) { - ossl_raise(eBNError, NULL); - } - break; - case 10: - if (!BN_dec2bn(&bn, RSTRING_PTR(str))) { - ossl_raise(eBNError, NULL); - } - break; - case 16: - if (!BN_hex2bn(&bn, RSTRING_PTR(str))) { - ossl_raise(eBNError, NULL); - } - break; - default: - ossl_raise(rb_eArgError, "invalid radix %d", base); + case 0: + ptr = StringValuePtr(str); + if (!BN_mpi2bn((unsigned char *)ptr, RSTRING_LENINT(str), bn)) { + ossl_raise(eBNError, NULL); + } + break; + case 2: + ptr = StringValuePtr(str); + if (!BN_bin2bn((unsigned char *)ptr, RSTRING_LENINT(str), bn)) { + ossl_raise(eBNError, NULL); + } + break; + case 10: + if (!BN_dec2bn(&bn, StringValueCStr(str))) { + ossl_raise(eBNError, NULL); + } + break; + case 16: + if (!BN_hex2bn(&bn, StringValueCStr(str))) { + ossl_raise(eBNError, NULL); + } + break; + default: + ossl_raise(rb_eArgError, "invalid radix %d", base); } return self; } /* * call-seq: - * bn.to_s => string - * bn.to_s(base) => string + * bn.to_s(base = 10) -> string * - * === Parameters - * * +base+ - integer - * * * Valid values: - * * * * 0 - MPI - * * * * 2 - binary - * * * * 10 - the default - * * * * 16 - hex + * Returns the string representation of the bignum. + * + * BN.new can parse the encoded string to convert back into an OpenSSL::BN. + * + * +base+:: + * The format. Must be one of the following: + * - +0+ - MPI format. See the man page BN_bn2mpi(3) for details. + * - +2+ - Variable-length and big-endian binary encoding. The sign of + * the bignum is ignored. + * - +10+ - Decimal number representation, with a leading '-' for a negative + * bignum. + * - +16+ - Hexadecimal number representation, with a leading '-' for a + * negative bignum. */ static VALUE ossl_bn_to_s(int argc, VALUE *argv, VALUE self) @@ -241,32 +334,32 @@ ossl_bn_to_s(int argc, VALUE *argv, VALUE self) char *buf; if (rb_scan_args(argc, argv, "01", &bs) == 1) { - base = NUM2INT(bs); + base = NUM2INT(bs); } GetBN(self, bn); switch (base) { - case 0: - len = BN_bn2mpi(bn, NULL); + case 0: + len = BN_bn2mpi(bn, NULL); str = rb_str_new(0, len); - if (BN_bn2mpi(bn, (unsigned char *)RSTRING_PTR(str)) != len) - ossl_raise(eBNError, NULL); - break; - case 2: - len = BN_num_bytes(bn); + if (BN_bn2mpi(bn, (unsigned char *)RSTRING_PTR(str)) != len) + ossl_raise(eBNError, NULL); + break; + case 2: + len = BN_num_bytes(bn); str = rb_str_new(0, len); - if (BN_bn2bin(bn, (unsigned char *)RSTRING_PTR(str)) != len) - ossl_raise(eBNError, NULL); - break; - case 10: - if (!(buf = BN_bn2dec(bn))) ossl_raise(eBNError, NULL); - str = ossl_buf2str(buf, rb_long2int(strlen(buf))); - break; - case 16: - if (!(buf = BN_bn2hex(bn))) ossl_raise(eBNError, NULL); - str = ossl_buf2str(buf, rb_long2int(strlen(buf))); - break; - default: - ossl_raise(rb_eArgError, "invalid radix %d", base); + if (BN_bn2bin(bn, (unsigned char *)RSTRING_PTR(str)) != len) + ossl_raise(eBNError, NULL); + break; + case 10: + if (!(buf = BN_bn2dec(bn))) ossl_raise(eBNError, NULL); + str = ossl_buf2str(buf, rb_long2int(strlen(buf))); + break; + case 16: + if (!(buf = BN_bn2hex(bn))) ossl_raise(eBNError, NULL); + str = ossl_buf2str(buf, rb_long2int(strlen(buf))); + break; + default: + ossl_raise(rb_eArgError, "invalid radix %d", base); } return str; @@ -286,7 +379,7 @@ ossl_bn_to_i(VALUE self) GetBN(self, bn); if (!(txt = BN_bn2hex(bn))) { - ossl_raise(eBNError, NULL); + ossl_raise(eBNError, NULL); } num = rb_cstr_to_inum(txt, 16, Qtrue); OPENSSL_free(txt); @@ -304,200 +397,332 @@ static VALUE ossl_bn_coerce(VALUE self, VALUE other) { switch(TYPE(other)) { - case T_STRING: - self = ossl_bn_to_s(0, NULL, self); - break; - case T_FIXNUM: - case T_BIGNUM: - self = ossl_bn_to_i(self); - break; - default: - if (!RTEST(rb_obj_is_kind_of(other, cBN))) { - ossl_raise(rb_eTypeError, "Don't know how to coerce"); - } + case T_STRING: + self = ossl_bn_to_s(0, NULL, self); + break; + case T_FIXNUM: + case T_BIGNUM: + self = ossl_bn_to_i(self); + break; + default: + if (!RTEST(rb_obj_is_kind_of(other, cBN))) { + ossl_raise(rb_eTypeError, "Don't know how to coerce"); + } } return rb_assoc_new(other, self); } -#define BIGNUM_BOOL1(func) \ - /* \ - * call-seq: \ - * bn.##func -> true | false \ - * \ - */ \ - static VALUE \ - ossl_bn_##func(VALUE self) \ - { \ - BIGNUM *bn; \ - GetBN(self, bn); \ - if (BN_##func(bn)) { \ - return Qtrue; \ - } \ - return Qfalse; \ +#define BIGNUM_BOOL1(func) \ + static VALUE \ + ossl_bn_##func(VALUE self) \ + { \ + BIGNUM *bn; \ + GetBN(self, bn); \ + if (BN_##func(bn)) { \ + return Qtrue; \ + } \ + return Qfalse; \ } + +/* + * Document-method: OpenSSL::BN#zero? + * call-seq: + * bn.zero? => true | false + */ BIGNUM_BOOL1(is_zero) + +/* + * Document-method: OpenSSL::BN#one? + * call-seq: + * bn.one? => true | false + */ BIGNUM_BOOL1(is_one) + +/* + * Document-method: OpenSSL::BN#odd? + * call-seq: + * bn.odd? => true | false + */ BIGNUM_BOOL1(is_odd) -#define BIGNUM_1c(func) \ - /* \ - * call-seq: \ - * bn.##func -> aBN \ - * \ - */ \ - static VALUE \ - ossl_bn_##func(VALUE self) \ - { \ - BIGNUM *bn, *result; \ - VALUE obj; \ - GetBN(self, bn); \ - if (!(result = BN_new())) { \ - ossl_raise(eBNError, NULL); \ - } \ - if (!BN_##func(result, bn, ossl_bn_ctx)) { \ - BN_free(result); \ - ossl_raise(eBNError, NULL); \ - } \ - WrapBN(CLASS_OF(self), obj, result); \ - return obj; \ +/* + * call-seq: + * bn.negative? => true | false + */ +static VALUE +ossl_bn_is_negative(VALUE self) +{ + BIGNUM *bn; + + GetBN(self, bn); + if (BN_is_zero(bn)) + return Qfalse; + return BN_is_negative(bn) ? Qtrue : Qfalse; +} + +#define BIGNUM_1c(func) \ + static VALUE \ + ossl_bn_##func(VALUE self) \ + { \ + BIGNUM *bn, *result; \ + VALUE obj; \ + GetBN(self, bn); \ + obj = NewBN(rb_obj_class(self)); \ + if (!(result = BN_new())) { \ + ossl_raise(eBNError, NULL); \ + } \ + if (BN_##func(result, bn, ossl_bn_ctx) <= 0) { \ + BN_free(result); \ + ossl_raise(eBNError, NULL); \ + } \ + SetBN(obj, result); \ + return obj; \ } + +/* + * Document-method: OpenSSL::BN#sqr + * call-seq: + * bn.sqr => aBN + */ BIGNUM_1c(sqr) -#define BIGNUM_2(func) \ - /* \ - * call-seq: \ - * bn.##func(bn2) -> aBN \ - * \ - */ \ - static VALUE \ - ossl_bn_##func(VALUE self, VALUE other) \ - { \ - BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \ - VALUE obj; \ - GetBN(self, bn1); \ - if (!(result = BN_new())) { \ - ossl_raise(eBNError, NULL); \ - } \ - if (!BN_##func(result, bn1, bn2)) { \ - BN_free(result); \ - ossl_raise(eBNError, NULL); \ - } \ - WrapBN(CLASS_OF(self), obj, result); \ - return obj; \ +#define BIGNUM_2(func) \ + static VALUE \ + ossl_bn_##func(VALUE self, VALUE other) \ + { \ + BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \ + VALUE obj; \ + GetBN(self, bn1); \ + obj = NewBN(rb_obj_class(self)); \ + if (!(result = BN_new())) { \ + ossl_raise(eBNError, NULL); \ + } \ + if (BN_##func(result, bn1, bn2) <= 0) { \ + BN_free(result); \ + ossl_raise(eBNError, NULL); \ + } \ + SetBN(obj, result); \ + return obj; \ } + +/* + * Document-method: OpenSSL::BN#+ + * call-seq: + * bn + bn2 => aBN + */ BIGNUM_2(add) + +/* + * Document-method: OpenSSL::BN#- + * call-seq: + * bn - bn2 => aBN + */ BIGNUM_2(sub) -#define BIGNUM_2c(func) \ - /* \ - * call-seq: \ - * bn.##func(bn2) -> aBN \ - * \ - */ \ - static VALUE \ - ossl_bn_##func(VALUE self, VALUE other) \ - { \ - BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \ - VALUE obj; \ - GetBN(self, bn1); \ - if (!(result = BN_new())) { \ - ossl_raise(eBNError, NULL); \ - } \ - if (!BN_##func(result, bn1, bn2, ossl_bn_ctx)) { \ - BN_free(result); \ - ossl_raise(eBNError, NULL); \ - } \ - WrapBN(CLASS_OF(self), obj, result); \ - return obj; \ +#define BIGNUM_2c(func) \ + static VALUE \ + ossl_bn_##func(VALUE self, VALUE other) \ + { \ + BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \ + VALUE obj; \ + GetBN(self, bn1); \ + obj = NewBN(rb_obj_class(self)); \ + if (!(result = BN_new())) { \ + ossl_raise(eBNError, NULL); \ + } \ + if (BN_##func(result, bn1, bn2, ossl_bn_ctx) <= 0) { \ + BN_free(result); \ + ossl_raise(eBNError, NULL); \ + } \ + SetBN(obj, result); \ + return obj; \ } + +/* + * Document-method: OpenSSL::BN#* + * call-seq: + * bn * bn2 => aBN + */ BIGNUM_2c(mul) + +/* + * Document-method: OpenSSL::BN#% + * call-seq: + * bn % bn2 => aBN + */ BIGNUM_2c(mod) + +/* + * Document-method: OpenSSL::BN#** + * call-seq: + * bn ** bn2 => aBN + */ BIGNUM_2c(exp) + +/* + * Document-method: OpenSSL::BN#gcd + * call-seq: + * bn.gcd(bn2) => aBN + */ BIGNUM_2c(gcd) + +/* + * Document-method: OpenSSL::BN#mod_sqr + * call-seq: + * bn.mod_sqr(bn2) => aBN + */ BIGNUM_2c(mod_sqr) -BIGNUM_2c(mod_inverse) + +#define BIGNUM_2cr(func) \ + static VALUE \ + ossl_bn_##func(VALUE self, VALUE other) \ + { \ + BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \ + VALUE obj; \ + GetBN(self, bn1); \ + obj = NewBN(rb_obj_class(self)); \ + if (!(result = BN_##func(NULL, bn1, bn2, ossl_bn_ctx))) \ + ossl_raise(eBNError, NULL); \ + SetBN(obj, result); \ + return obj; \ + } + +/* + * Document-method: OpenSSL::BN#mod_sqrt + * call-seq: + * bn.mod_sqrt(bn2) => aBN + */ +BIGNUM_2cr(mod_sqrt) + +/* + * Document-method: OpenSSL::BN#mod_inverse + * call-seq: + * bn.mod_inverse(bn2) => aBN + */ +BIGNUM_2cr(mod_inverse) /* * call-seq: * bn1 / bn2 => [result, remainder] + * + * Division of OpenSSL::BN instances */ static VALUE ossl_bn_div(VALUE self, VALUE other) { BIGNUM *bn1, *bn2 = GetBNPtr(other), *r1, *r2; - VALUE obj1, obj2; + VALUE klass, obj1, obj2; GetBN(self, bn1); + klass = rb_obj_class(self); + obj1 = NewBN(klass); + obj2 = NewBN(klass); if (!(r1 = BN_new())) { - ossl_raise(eBNError, NULL); + ossl_raise(eBNError, NULL); } if (!(r2 = BN_new())) { - BN_free(r1); - ossl_raise(eBNError, NULL); + BN_free(r1); + ossl_raise(eBNError, NULL); } if (!BN_div(r1, r2, bn1, bn2, ossl_bn_ctx)) { - BN_free(r1); - BN_free(r2); - ossl_raise(eBNError, NULL); + BN_free(r1); + BN_free(r2); + ossl_raise(eBNError, NULL); } - WrapBN(CLASS_OF(self), obj1, r1); - WrapBN(CLASS_OF(self), obj2, r2); + SetBN(obj1, r1); + SetBN(obj2, r2); return rb_ary_new3(2, obj1, obj2); } -#define BIGNUM_3c(func) \ - /* \ - * call-seq: \ - * bn.##func(bn1, bn2) -> aBN \ - * \ - */ \ - static VALUE \ - ossl_bn_##func(VALUE self, VALUE other1, VALUE other2) \ - { \ - BIGNUM *bn1, *bn2 = GetBNPtr(other1); \ - BIGNUM *bn3 = GetBNPtr(other2), *result; \ - VALUE obj; \ - GetBN(self, bn1); \ - if (!(result = BN_new())) { \ - ossl_raise(eBNError, NULL); \ - } \ - if (!BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx)) { \ - BN_free(result); \ - ossl_raise(eBNError, NULL); \ - } \ - WrapBN(CLASS_OF(self), obj, result); \ - return obj; \ +#define BIGNUM_3c(func) \ + static VALUE \ + ossl_bn_##func(VALUE self, VALUE other1, VALUE other2) \ + { \ + BIGNUM *bn1, *bn2 = GetBNPtr(other1); \ + BIGNUM *bn3 = GetBNPtr(other2), *result; \ + VALUE obj; \ + GetBN(self, bn1); \ + obj = NewBN(rb_obj_class(self)); \ + if (!(result = BN_new())) { \ + ossl_raise(eBNError, NULL); \ + } \ + if (BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx) <= 0) { \ + BN_free(result); \ + ossl_raise(eBNError, NULL); \ + } \ + SetBN(obj, result); \ + return obj; \ } + +/* + * Document-method: OpenSSL::BN#mod_add + * call-seq: + * bn.mod_add(bn1, bn2) -> aBN + */ BIGNUM_3c(mod_add) + +/* + * Document-method: OpenSSL::BN#mod_sub + * call-seq: + * bn.mod_sub(bn1, bn2) -> aBN + */ BIGNUM_3c(mod_sub) + +/* + * Document-method: OpenSSL::BN#mod_mul + * call-seq: + * bn.mod_mul(bn1, bn2) -> aBN + */ BIGNUM_3c(mod_mul) + +/* + * Document-method: OpenSSL::BN#mod_exp + * call-seq: + * bn.mod_exp(bn1, bn2) -> aBN + */ BIGNUM_3c(mod_exp) -#define BIGNUM_BIT(func) \ - /* \ - * call-seq: \ - * bn.##func(bit) -> self \ - * \ - */ \ - static VALUE \ - ossl_bn_##func(VALUE self, VALUE bit) \ - { \ - BIGNUM *bn; \ - GetBN(self, bn); \ - if (!BN_##func(bn, NUM2INT(bit))) { \ - ossl_raise(eBNError, NULL); \ - } \ - return self; \ +#define BIGNUM_BIT(func) \ + static VALUE \ + ossl_bn_##func(VALUE self, VALUE bit) \ + { \ + BIGNUM *bn; \ + rb_check_frozen(self); \ + GetBN(self, bn); \ + if (BN_##func(bn, NUM2INT(bit)) <= 0) { \ + ossl_raise(eBNError, NULL); \ + } \ + return self; \ } + +/* + * Document-method: OpenSSL::BN#set_bit! + * call-seq: + * bn.set_bit!(bit) -> self + */ BIGNUM_BIT(set_bit) + +/* + * Document-method: OpenSSL::BN#clear_bit! + * call-seq: + * bn.clear_bit!(bit) -> self + */ BIGNUM_BIT(clear_bit) + +/* + * Document-method: OpenSSL::BN#mask_bit! + * call-seq: + * bn.mask_bit!(bit) -> self + */ BIGNUM_BIT(mask_bits) /* * call-seq: - * bn.bit_set?(bit) => true | false + * bn.bit_set?(bit) => true | false + * + * Tests bit _bit_ in _bn_ and returns +true+ if set, +false+ if not set. */ static VALUE ossl_bn_is_bit_set(VALUE self, VALUE bit) @@ -508,125 +733,146 @@ ossl_bn_is_bit_set(VALUE self, VALUE bit) b = NUM2INT(bit); GetBN(self, bn); if (BN_is_bit_set(bn, b)) { - return Qtrue; + return Qtrue; } return Qfalse; } -#define BIGNUM_SHIFT(func) \ - /* \ - * call-seq: \ - * bn.##func(bits) -> aBN \ - * \ - */ \ - static VALUE \ - ossl_bn_##func(VALUE self, VALUE bits) \ - { \ - BIGNUM *bn, *result; \ - int b; \ - VALUE obj; \ - b = NUM2INT(bits); \ - GetBN(self, bn); \ - if (!(result = BN_new())) { \ - ossl_raise(eBNError, NULL); \ - } \ - if (!BN_##func(result, bn, b)) { \ - BN_free(result); \ - ossl_raise(eBNError, NULL); \ - } \ - WrapBN(CLASS_OF(self), obj, result); \ - return obj; \ +#define BIGNUM_SHIFT(func) \ + static VALUE \ + ossl_bn_##func(VALUE self, VALUE bits) \ + { \ + BIGNUM *bn, *result; \ + int b; \ + VALUE obj; \ + b = NUM2INT(bits); \ + GetBN(self, bn); \ + obj = NewBN(rb_obj_class(self)); \ + if (!(result = BN_new())) { \ + ossl_raise(eBNError, NULL); \ + } \ + if (BN_##func(result, bn, b) <= 0) { \ + BN_free(result); \ + ossl_raise(eBNError, NULL); \ + } \ + SetBN(obj, result); \ + return obj; \ } + +/* + * Document-method: OpenSSL::BN#<< + * call-seq: + * bn << bits -> aBN + */ BIGNUM_SHIFT(lshift) + +/* + * Document-method: OpenSSL::BN#>> + * call-seq: + * bn >> bits -> aBN + */ BIGNUM_SHIFT(rshift) -#define BIGNUM_SELF_SHIFT(func) \ - /* \ - * call-seq: \ - * bn.##func!(bits) -> self \ - * \ - */ \ - static VALUE \ - ossl_bn_self_##func(VALUE self, VALUE bits) \ - { \ - BIGNUM *bn; \ - int b; \ - b = NUM2INT(bits); \ - GetBN(self, bn); \ - if (!BN_##func(bn, bn, b)) \ - ossl_raise(eBNError, NULL); \ - return self; \ +#define BIGNUM_SELF_SHIFT(func) \ + static VALUE \ + ossl_bn_self_##func(VALUE self, VALUE bits) \ + { \ + BIGNUM *bn; \ + int b; \ + rb_check_frozen(self); \ + b = NUM2INT(bits); \ + GetBN(self, bn); \ + if (BN_##func(bn, bn, b) <= 0) \ + ossl_raise(eBNError, NULL); \ + return self; \ } + +/* + * Document-method: OpenSSL::BN#lshift! + * call-seq: + * bn.lshift!(bits) -> self + */ BIGNUM_SELF_SHIFT(lshift) + +/* + * Document-method: OpenSSL::BN#rshift! + * call-seq: + * bn.rshift!(bits) -> self + */ BIGNUM_SELF_SHIFT(rshift) -#define BIGNUM_RAND(func) \ - /* \ - * call-seq: \ - * BN.##func(bits [, fill [, odd]]) -> aBN \ - * \ - */ \ - static VALUE \ - ossl_bn_s_##func(int argc, VALUE *argv, VALUE klass) \ - { \ - BIGNUM *result; \ - int bottom = 0, top = 0, b; \ - VALUE bits, fill, odd, obj; \ - \ - switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) { \ - case 3: \ - bottom = (odd == Qtrue) ? 1 : 0; \ - /* FALLTHROUGH */ \ - case 2: \ - top = NUM2INT(fill); \ - } \ - b = NUM2INT(bits); \ - if (!(result = BN_new())) { \ - ossl_raise(eBNError, NULL); \ - } \ - if (!BN_##func(result, b, top, bottom)) { \ - BN_free(result); \ - ossl_raise(eBNError, NULL); \ - } \ - WrapBN(klass, obj, result); \ - return obj; \ - } -BIGNUM_RAND(rand) -BIGNUM_RAND(pseudo_rand) - -#define BIGNUM_RAND_RANGE(func) \ - /* \ - * call-seq: \ - * BN.##func(range) -> aBN \ - * \ - */ \ - static VALUE \ - ossl_bn_s_##func##_range(VALUE klass, VALUE range) \ - { \ - BIGNUM *bn = GetBNPtr(range), *result; \ - VALUE obj; \ - if (!(result = BN_new())) { \ - ossl_raise(eBNError, NULL); \ - } \ - if (!BN_##func##_range(result, bn)) { \ - BN_free(result); \ - ossl_raise(eBNError, NULL); \ - } \ - WrapBN(klass, obj, result); \ - return obj; \ - } -BIGNUM_RAND_RANGE(rand) -BIGNUM_RAND_RANGE(pseudo_rand) +/* + * call-seq: + * BN.rand(bits [, fill [, odd]]) -> aBN + * + * Generates a cryptographically strong pseudo-random number of +bits+. + * + * See also the man page BN_rand(3). + */ +static VALUE +ossl_bn_s_rand(int argc, VALUE *argv, VALUE klass) +{ + BIGNUM *result; + int bottom = 0, top = 0, b; + VALUE bits, fill, odd, obj; + + switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) { + case 3: + bottom = (odd == Qtrue) ? 1 : 0; + /* FALLTHROUGH */ + case 2: + top = NUM2INT(fill); + } + b = NUM2INT(bits); + obj = NewBN(klass); + if (!(result = BN_new())) { + ossl_raise(eBNError, "BN_new"); + } + if (BN_rand(result, b, top, bottom) <= 0) { + BN_free(result); + ossl_raise(eBNError, "BN_rand"); + } + SetBN(obj, result); + return obj; +} + +/* + * call-seq: + * BN.rand_range(range) -> aBN + * + * Generates a cryptographically strong pseudo-random number in the range + * 0...+range+. + * + * See also the man page BN_rand_range(3). + */ +static VALUE +ossl_bn_s_rand_range(VALUE klass, VALUE range) +{ + BIGNUM *bn = GetBNPtr(range), *result; + VALUE obj = NewBN(klass); + if (!(result = BN_new())) + ossl_raise(eBNError, "BN_new"); + if (BN_rand_range(result, bn) <= 0) { + BN_free(result); + ossl_raise(eBNError, "BN_rand_range"); + } + SetBN(obj, result); + return obj; +} /* * call-seq: * BN.generate_prime(bits, [, safe [, add [, rem]]]) => bn * + * Generates a random prime number of bit length _bits_. If _safe_ is set to + * +true+, generates a safe prime. If _add_ is specified, generates a prime that + * fulfills condition <tt>p % add = rem</tt>. + * * === Parameters - * * +bits+ - integer - * * +safe+ - boolean - * * +add+ - BN - * * +rem+ - BN + * * _bits_ - integer + * * _safe_ - boolean + * * _add_ - BN + * * _rem_ - BN */ static VALUE ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass) @@ -640,40 +886,49 @@ ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass) num = NUM2INT(vnum); if (vsafe == Qfalse) { - safe = 0; + safe = 0; } if (!NIL_P(vadd)) { - add = GetBNPtr(vadd); - rem = NIL_P(vrem) ? NULL : GetBNPtr(vrem); + add = GetBNPtr(vadd); + rem = NIL_P(vrem) ? NULL : GetBNPtr(vrem); } + obj = NewBN(klass); if (!(result = BN_new())) { - ossl_raise(eBNError, NULL); + ossl_raise(eBNError, NULL); } - if (!BN_generate_prime(result, num, safe, add, rem, NULL, NULL)) { - BN_free(result); - ossl_raise(eBNError, NULL); + if (!BN_generate_prime_ex(result, num, safe, add, rem, NULL)) { + BN_free(result); + ossl_raise(eBNError, NULL); } - WrapBN(klass, obj, result); + SetBN(obj, result); return obj; } -#define BIGNUM_NUM(func) \ - /* \ - * call-seq: \ - * bn.##func -> integer \ - * \ - */ \ - static VALUE \ - ossl_bn_##func(VALUE self) \ - { \ - BIGNUM *bn; \ - GetBN(self, bn); \ - return INT2FIX(BN_##func(bn)); \ +#define BIGNUM_NUM(func) \ + static VALUE \ + ossl_bn_##func(VALUE self) \ + { \ + BIGNUM *bn; \ + GetBN(self, bn); \ + return INT2NUM(BN_##func(bn)); \ } + +/* + * Document-method: OpenSSL::BN#num_bytes + * call-seq: + * bn.num_bytes => integer + */ BIGNUM_NUM(num_bytes) + +/* + * Document-method: OpenSSL::BN#num_bits + * call-seq: + * bn.num_bits => integer + */ BIGNUM_NUM(num_bits) +/* :nodoc: */ static VALUE ossl_bn_copy(VALUE self, VALUE other) { @@ -687,65 +942,201 @@ ossl_bn_copy(VALUE self, VALUE other) bn2 = GetBNPtr(other); if (!BN_copy(bn1, bn2)) { - ossl_raise(eBNError, NULL); + ossl_raise(eBNError, NULL); } return self; } -#define BIGNUM_CMP(func) \ - /* \ - * call-seq: \ - * bn.##func(bn2) -> integer \ - * \ - */ \ - static VALUE \ - ossl_bn_##func(VALUE self, VALUE other) \ - { \ - BIGNUM *bn1, *bn2 = GetBNPtr(other); \ - GetBN(self, bn1); \ - return INT2FIX(BN_##func(bn1, bn2)); \ +/* + * call-seq: + * +bn -> aBN + */ +static VALUE +ossl_bn_uplus(VALUE self) +{ + VALUE obj; + BIGNUM *bn1, *bn2; + + GetBN(self, bn1); + obj = NewBN(cBN); + bn2 = BN_dup(bn1); + if (!bn2) + ossl_raise(eBNError, "BN_dup"); + SetBN(obj, bn2); + + return obj; +} + +/* + * call-seq: + * -bn -> aBN + */ +static VALUE +ossl_bn_uminus(VALUE self) +{ + VALUE obj; + BIGNUM *bn1, *bn2; + + GetBN(self, bn1); + obj = NewBN(cBN); + bn2 = BN_dup(bn1); + if (!bn2) + ossl_raise(eBNError, "BN_dup"); + SetBN(obj, bn2); + BN_set_negative(bn2, !BN_is_negative(bn2)); + + return obj; +} + +/* + * call-seq: + * bn.abs -> aBN + */ +static VALUE +ossl_bn_abs(VALUE self) +{ + BIGNUM *bn1; + + GetBN(self, bn1); + if (BN_is_negative(bn1)) { + return ossl_bn_uminus(self); + } + else { + return ossl_bn_uplus(self); } +} + +#define BIGNUM_CMP(func) \ + static VALUE \ + ossl_bn_##func(VALUE self, VALUE other) \ + { \ + BIGNUM *bn1, *bn2 = GetBNPtr(other); \ + GetBN(self, bn1); \ + return INT2NUM(BN_##func(bn1, bn2)); \ + } + +/* + * Document-method: OpenSSL::BN#cmp + * call-seq: + * bn.cmp(bn2) => integer + */ +/* + * Document-method: OpenSSL::BN#<=> + * call-seq: + * bn <=> bn2 => integer + */ BIGNUM_CMP(cmp) + +/* + * Document-method: OpenSSL::BN#ucmp + * call-seq: + * bn.ucmp(bn2) => integer + */ BIGNUM_CMP(ucmp) +/* + * call-seq: + * bn == obj => true or false + * + * Returns +true+ only if _obj_ has the same value as _bn_. Contrast this + * with OpenSSL::BN#eql?, which requires obj to be OpenSSL::BN. + */ static VALUE -ossl_bn_eql(VALUE self, VALUE other) +ossl_bn_eq(VALUE self, VALUE other) { - if (ossl_bn_cmp(self, other) == INT2FIX(0)) { - return Qtrue; + BIGNUM *bn1, *bn2; + + GetBN(self, bn1); + other = try_convert_to_bn(other); + if (NIL_P(other)) + return Qfalse; + GetBN(other, bn2); + + if (!BN_cmp(bn1, bn2)) { + return Qtrue; } return Qfalse; } /* + * call-seq: + * bn.eql?(obj) => true or false + * + * Returns <code>true</code> only if <i>obj</i> is a + * <code>OpenSSL::BN</code> with the same value as <i>bn</i>. Contrast this + * with OpenSSL::BN#==, which performs type conversions. + */ +static VALUE +ossl_bn_eql(VALUE self, VALUE other) +{ + BIGNUM *bn1, *bn2; + + if (!rb_obj_is_kind_of(other, cBN)) + return Qfalse; + GetBN(self, bn1); + GetBN(other, bn2); + + return BN_cmp(bn1, bn2) ? Qfalse : Qtrue; +} + +/* + * call-seq: + * bn.hash => Integer + * + * Returns a hash code for this object. + * + * See also Object#hash. + */ +static VALUE +ossl_bn_hash(VALUE self) +{ + BIGNUM *bn; + VALUE tmp, hash; + unsigned char *buf; + int len; + + GetBN(self, bn); + len = BN_num_bytes(bn); + buf = ALLOCV(tmp, len); + if (BN_bn2bin(bn, buf) != len) { + ALLOCV_END(tmp); + ossl_raise(eBNError, "BN_bn2bin"); + } + + hash = ST2FIX(rb_memhash(buf, len)); + ALLOCV_END(tmp); + + return hash; +} + +/* * call-seq: * bn.prime? => true | false * bn.prime?(checks) => true | false * - * === Parameters - * * +checks+ - integer + * Performs a Miller-Rabin probabilistic primality test for +bn+. + * + * <b>+checks+ parameter is deprecated in version 3.0.</b> It has no effect. */ static VALUE ossl_bn_is_prime(int argc, VALUE *argv, VALUE self) { BIGNUM *bn; - VALUE vchecks; - int checks = BN_prime_checks; + int ret; - if (rb_scan_args(argc, argv, "01", &vchecks) == 1) { - checks = NUM2INT(vchecks); - } + rb_check_arity(argc, 0, 1); GetBN(self, bn); - switch (BN_is_prime(bn, checks, NULL, ossl_bn_ctx, NULL)) { - case 1: - return Qtrue; - case 0: - return Qfalse; - default: - ossl_raise(eBNError, NULL); - } - /* not reachable */ - return Qnil; + +#ifdef HAVE_BN_CHECK_PRIME + ret = BN_check_prime(bn, ossl_bn_ctx, NULL); + if (ret < 0) + ossl_raise(eBNError, "BN_check_prime"); +#else + ret = BN_is_prime_fasttest_ex(bn, BN_prime_checks, ossl_bn_ctx, 1, NULL); + if (ret < 0) + ossl_raise(eBNError, "BN_is_prime_fasttest_ex"); +#endif + return ret ? Qtrue : Qfalse; } /* @@ -754,36 +1145,53 @@ ossl_bn_is_prime(int argc, VALUE *argv, VALUE self) * bn.prime_fasttest?(checks) => true | false * bn.prime_fasttest?(checks, trial_div) => true | false * - * === Parameters - * * +checks+ - integer - * * +trial_div+ - boolean + * Performs a Miller-Rabin probabilistic primality test for +bn+. + * + * <b>Deprecated in version 3.0.</b> Use #prime? instead. + * + * +checks+ and +trial_div+ parameters no longer have any effect. */ static VALUE ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self) { + rb_check_arity(argc, 0, 2); + return ossl_bn_is_prime(0, argv, self); +} + +/* + * call-seq: + * bn.get_flags(flags) => flags + * + * Returns the flags on the BN object. + * The argument is used as a bit mask. + * + * === Parameters + * * _flags_ - integer + */ +static VALUE +ossl_bn_get_flags(VALUE self, VALUE arg) +{ BIGNUM *bn; - VALUE vchecks, vtrivdiv; - int checks = BN_prime_checks, do_trial_division = 1; + GetBN(self, bn); - rb_scan_args(argc, argv, "02", &vchecks, &vtrivdiv); + return INT2NUM(BN_get_flags(bn, NUM2INT(arg))); +} - if (!NIL_P(vchecks)) { - checks = NUM2INT(vchecks); - } +/* + * call-seq: + * bn.set_flags(flags) => nil + * + * Enables the flags on the BN object. + * Currently, the flags argument can contain zero of OpenSSL::BN::CONSTTIME. + */ +static VALUE +ossl_bn_set_flags(VALUE self, VALUE arg) +{ + BIGNUM *bn; GetBN(self, bn); - /* handle true/false */ - if (vtrivdiv == Qfalse) { - do_trial_division = 0; - } - switch (BN_is_prime_fasttest(bn, checks, NULL, ossl_bn_ctx, NULL, do_trial_division)) { - case 1: - return Qtrue; - case 0: - return Qfalse; - default: - ossl_raise(eBNError, NULL); - } - /* not reachable */ + + rb_check_frozen(self); + BN_set_flags(bn, NUM2INT(arg)); return Qnil; } @@ -794,14 +1202,12 @@ ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self) void Init_ossl_bn(void) { -#if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ +#ifdef HAVE_RB_EXT_RACTOR_SAFE + ossl_bn_ctx_key = rb_ractor_local_storage_ptr_newkey(&ossl_bn_ctx_key_type); +#else + ossl_bn_ctx_get(); #endif - if (!(ossl_bn_ctx = BN_CTX_new())) { - ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX"); - } - eBNError = rb_define_class_under(mOSSL, "BNError", eOSSLError); cBN = rb_define_class_under(mOSSL, "BN", rb_cObject); @@ -809,7 +1215,7 @@ Init_ossl_bn(void) rb_define_alloc_func(cBN, ossl_bn_alloc); rb_define_method(cBN, "initialize", ossl_bn_initialize, -1); - rb_define_copy_func(cBN, ossl_bn_copy); + rb_define_method(cBN, "initialize_copy", ossl_bn_copy, 1); rb_define_method(cBN, "copy", ossl_bn_copy, 1); /* swap (=coerce?) */ @@ -818,6 +1224,10 @@ Init_ossl_bn(void) rb_define_method(cBN, "num_bits", ossl_bn_num_bits, 0); /* num_bits_word */ + rb_define_method(cBN, "+@", ossl_bn_uplus, 0); + rb_define_method(cBN, "-@", ossl_bn_uminus, 0); + rb_define_method(cBN, "abs", ossl_bn_abs, 0); + rb_define_method(cBN, "+", ossl_bn_add, 1); rb_define_method(cBN, "-", ossl_bn_sub, 1); rb_define_method(cBN, "*", ossl_bn_mul, 1); @@ -830,6 +1240,7 @@ Init_ossl_bn(void) rb_define_method(cBN, "mod_sub", ossl_bn_mod_sub, 2); rb_define_method(cBN, "mod_mul", ossl_bn_mod_mul, 2); rb_define_method(cBN, "mod_sqr", ossl_bn_mod_sqr, 1); + rb_define_method(cBN, "mod_sqrt", ossl_bn_mod_sqrt, 1); rb_define_method(cBN, "**", ossl_bn_exp, 1); rb_define_method(cBN, "mod_exp", ossl_bn_mod_exp, 2); rb_define_method(cBN, "gcd", ossl_bn_gcd, 1); @@ -844,12 +1255,14 @@ Init_ossl_bn(void) rb_define_alias(cBN, "<=>", "cmp"); rb_define_method(cBN, "ucmp", ossl_bn_ucmp, 1); rb_define_method(cBN, "eql?", ossl_bn_eql, 1); - rb_define_alias(cBN, "==", "eql?"); - rb_define_alias(cBN, "===", "eql?"); + rb_define_method(cBN, "hash", ossl_bn_hash, 0); + rb_define_method(cBN, "==", ossl_bn_eq, 1); + rb_define_alias(cBN, "===", "=="); rb_define_method(cBN, "zero?", ossl_bn_is_zero, 0); rb_define_method(cBN, "one?", ossl_bn_is_one, 0); /* is_word */ rb_define_method(cBN, "odd?", ossl_bn_is_odd, 0); + rb_define_method(cBN, "negative?", ossl_bn_is_negative, 0); /* zero * one @@ -858,12 +1271,13 @@ Init_ossl_bn(void) * get_word */ rb_define_singleton_method(cBN, "rand", ossl_bn_s_rand, -1); - rb_define_singleton_method(cBN, "pseudo_rand", ossl_bn_s_pseudo_rand, -1); rb_define_singleton_method(cBN, "rand_range", ossl_bn_s_rand_range, 1); - rb_define_singleton_method(cBN, "pseudo_rand_range", ossl_bn_s_pseudo_rand_range, 1); + rb_define_alias(rb_singleton_class(cBN), "pseudo_rand", "rand"); + rb_define_alias(rb_singleton_class(cBN), "pseudo_rand_range", "rand_range"); rb_define_singleton_method(cBN, "generate_prime", ossl_bn_s_generate_prime, -1); rb_define_method(cBN, "prime?", ossl_bn_is_prime, -1); + rb_define_method(cBN, "prime_fasttest?", ossl_bn_is_prime_fasttest, -1); rb_define_method(cBN, "set_bit!", ossl_bn_set_bit, 1); rb_define_method(cBN, "clear_bit!", ossl_bn_clear_bit, 1); @@ -876,6 +1290,23 @@ Init_ossl_bn(void) /* lshift1 - DON'T IMPL. */ /* rshift1 - DON'T IMPL. */ + rb_define_method(cBN, "get_flags", ossl_bn_get_flags, 1); + rb_define_method(cBN, "set_flags", ossl_bn_set_flags, 1); + +#ifdef BN_FLG_CONSTTIME + rb_define_const(cBN, "CONSTTIME", INT2NUM(BN_FLG_CONSTTIME)); +#endif + /* BN_FLG_MALLOCED and BN_FLG_STATIC_DATA seems for C programming. + * Allowing them leads to memory leak. + * So, for now, they are not exported +#ifdef BN_FLG_MALLOCED + rb_define_const(cBN, "MALLOCED", INT2NUM(BN_FLG_MALLOCED)); +#endif +#ifdef BN_FLG_STATIC_DATA + rb_define_const(cBN, "STATIC_DATA", INT2NUM(BN_FLG_STATIC_DATA)); +#endif + */ + /* * bn2bin * bin2bn @@ -905,11 +1336,4 @@ Init_ossl_bn(void) /* RECiProcal * MONTgomery */ - - /* - * TODO: - * Where to belong these? - */ - rb_define_method(cBN, "prime_fasttest?", ossl_bn_is_prime_fasttest, -1); } - diff --git a/ext/openssl/ossl_bn.h b/ext/openssl/ossl_bn.h index d6c396227b..0c186bd1c5 100644 --- a/ext/openssl/ossl_bn.h +++ b/ext/openssl/ossl_bn.h @@ -1,25 +1,25 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(_OSSL_BN_H_) #define _OSSL_BN_H_ extern VALUE cBN; -extern VALUE eBNError; -extern BN_CTX *ossl_bn_ctx; +BN_CTX *ossl_bn_ctx_get(void); +#define ossl_bn_ctx ossl_bn_ctx_get() + +#define GetBNPtr(obj) ossl_bn_value_ptr(&(obj)) VALUE ossl_bn_new(const BIGNUM *); -BIGNUM *GetBNPtr(VALUE); +BIGNUM *ossl_bn_value_ptr(volatile VALUE *); void Init_ossl_bn(void); #endif /* _OSS_BN_H_ */ - diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c index 08fdacfb4a..f3cd247c8f 100644 --- a/ext/openssl/ossl_cipher.c +++ b/ext/openssl/ossl_cipher.c @@ -1,63 +1,103 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#define WrapCipher(obj, klass, ctx) \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_cipher_type, (ctx)) -#define MakeCipher(obj, klass, ctx) \ - (obj) = TypedData_Make_Struct((klass), EVP_CIPHER_CTX, &ossl_cipher_type, (ctx)) -#define AllocCipher(obj, ctx) \ - (DATA_PTR(obj) = (ctx) = ZALLOC(EVP_CIPHER_CTX)) +#define NewCipher(klass) \ + TypedData_Wrap_Struct((klass), &ossl_cipher_type, 0) +#define AllocCipher(obj, ctx) do { \ + (ctx) = EVP_CIPHER_CTX_new(); \ + if (!(ctx)) \ + ossl_raise(rb_eRuntimeError, NULL); \ + RTYPEDDATA_DATA(obj) = (ctx); \ +} while (0) #define GetCipherInit(obj, ctx) do { \ TypedData_Get_Struct((obj), EVP_CIPHER_CTX, &ossl_cipher_type, (ctx)); \ } while (0) #define GetCipher(obj, ctx) do { \ GetCipherInit((obj), (ctx)); \ if (!(ctx)) { \ - ossl_raise(rb_eRuntimeError, "Cipher not inititalized!"); \ + ossl_raise(rb_eRuntimeError, "Cipher not initialized!"); \ } \ } while (0) -#define SafeGetCipher(obj, ctx) do { \ - OSSL_Check_Kind((obj), cCipher); \ - GetCipher((obj), (ctx)); \ -} while (0) /* * Classes */ -VALUE cCipher; -VALUE eCipherError; +static VALUE cCipher; +static VALUE eCipherError; +static VALUE eAuthTagError; +static ID id_auth_tag_len, id_key_set, id_cipher_holder; static VALUE ossl_cipher_alloc(VALUE klass); static void ossl_cipher_free(void *ptr); -static size_t ossl_cipher_memsize(const void *ptr); static const rb_data_type_t ossl_cipher_type = { "OpenSSL/Cipher", - {0, ossl_cipher_free, ossl_cipher_memsize,}, - 0, 0, - RUBY_TYPED_FREE_IMMEDIATELY, + { + 0, ossl_cipher_free, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; +#ifdef OSSL_USE_PROVIDER +static void +ossl_evp_cipher_free(void *ptr) +{ + // This is safe to call against const EVP_CIPHER * returned by + // EVP_get_cipherbyname() + EVP_CIPHER_free(ptr); +} + +static const rb_data_type_t ossl_evp_cipher_holder_type = { + "OpenSSL/EVP_CIPHER", + { + .dfree = ossl_evp_cipher_free, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, +}; +#endif + /* * PUBLIC */ const EVP_CIPHER * -GetCipherPtr(VALUE obj) +ossl_evp_cipher_fetch(VALUE obj, volatile VALUE *holder) { - EVP_CIPHER_CTX *ctx; - - SafeGetCipher(obj, ctx); + *holder = Qnil; + if (rb_obj_is_kind_of(obj, cCipher)) { + EVP_CIPHER_CTX *ctx; + GetCipher(obj, ctx); + EVP_CIPHER *cipher = (EVP_CIPHER *)EVP_CIPHER_CTX_cipher(ctx); +#ifdef OSSL_USE_PROVIDER + *holder = TypedData_Wrap_Struct(0, &ossl_evp_cipher_holder_type, NULL); + if (!EVP_CIPHER_up_ref(cipher)) + ossl_raise(eCipherError, "EVP_CIPHER_up_ref"); + RTYPEDDATA_DATA(*holder) = cipher; +#endif + return cipher; + } - return EVP_CIPHER_CTX_cipher(ctx); + const char *name = StringValueCStr(obj); + EVP_CIPHER *cipher = (EVP_CIPHER *)EVP_get_cipherbyname(name); +#ifdef OSSL_USE_PROVIDER + if (!cipher) { + ossl_clear_error(); + *holder = TypedData_Wrap_Struct(0, &ossl_evp_cipher_holder_type, NULL); + cipher = EVP_CIPHER_fetch(NULL, name, NULL); + RTYPEDDATA_DATA(*holder) = cipher; + } +#endif + if (!cipher) + ossl_raise(eCipherError, "unsupported cipher algorithm: %"PRIsVALUE, + obj); + return cipher; } VALUE @@ -66,11 +106,13 @@ ossl_cipher_new(const EVP_CIPHER *cipher) VALUE ret; EVP_CIPHER_CTX *ctx; + // NOTE: This does not set id_cipher_holder because this function should + // only be called from ossl_engine.c, which will not use any + // reference-counted ciphers. ret = ossl_cipher_alloc(cCipher); AllocCipher(ret, ctx); - EVP_CIPHER_CTX_init(ctx); if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1) - ossl_raise(eCipherError, NULL); + ossl_raise(eCipherError, NULL); return ret; } @@ -81,35 +123,20 @@ ossl_cipher_new(const EVP_CIPHER *cipher) static void ossl_cipher_free(void *ptr) { - EVP_CIPHER_CTX *ctx = ptr; - if (ctx) { - EVP_CIPHER_CTX_cleanup(ctx); - ruby_xfree(ctx); - } -} - -static size_t -ossl_cipher_memsize(const void *ptr) -{ - const EVP_CIPHER_CTX *ctx = ptr; - return ctx ? sizeof(*ctx) : 0; + EVP_CIPHER_CTX_free(ptr); } static VALUE ossl_cipher_alloc(VALUE klass) { - VALUE obj; - - WrapCipher(obj, klass, 0); - - return obj; + return NewCipher(klass); } /* * call-seq: * Cipher.new(string) -> cipher * - * The string must contain a valid cipher name like "AES-128-CBC" or "3DES". + * The string must contain a valid cipher name like "aes-256-cbc". * * A list of cipher names is available by calling OpenSSL::Cipher.ciphers. */ @@ -118,32 +145,22 @@ ossl_cipher_initialize(VALUE self, VALUE str) { EVP_CIPHER_CTX *ctx; const EVP_CIPHER *cipher; - char *name; - unsigned char key[EVP_MAX_KEY_LENGTH]; + VALUE cipher_holder; - name = StringValuePtr(str); GetCipherInit(self, ctx); if (ctx) { - ossl_raise(rb_eRuntimeError, "Cipher already inititalized!"); + ossl_raise(rb_eRuntimeError, "Cipher already initialized!"); } + cipher = ossl_evp_cipher_fetch(str, &cipher_holder); AllocCipher(self, ctx); - EVP_CIPHER_CTX_init(ctx); - if (!(cipher = EVP_get_cipherbyname(name))) { - ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%s)", name); - } - /* - * The EVP which has EVP_CIPH_RAND_KEY flag (such as DES3) allows - * uninitialized key, but other EVPs (such as AES) does not allow it. - * Calling EVP_CipherUpdate() without initializing key causes SEGV so we - * set the data filled with "\0" as the key by default. - */ - memset(key, 0, EVP_MAX_KEY_LENGTH); - if (EVP_CipherInit_ex(ctx, cipher, NULL, key, NULL, -1) != 1) - ossl_raise(eCipherError, NULL); + if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1) + ossl_raise(eCipherError, "EVP_CipherInit_ex"); + rb_ivar_set(self, id_cipher_holder, cipher_holder); return self; } +/* :nodoc: */ static VALUE ossl_cipher_copy(VALUE self, VALUE other) { @@ -154,25 +171,22 @@ ossl_cipher_copy(VALUE self, VALUE other) GetCipherInit(self, ctx1); if (!ctx1) { - AllocCipher(self, ctx1); + AllocCipher(self, ctx1); } - SafeGetCipher(other, ctx2); + GetCipher(other, ctx2); if (EVP_CIPHER_CTX_copy(ctx1, ctx2) != 1) - ossl_raise(eCipherError, NULL); + ossl_raise(eCipherError, NULL); return self; } -#ifdef HAVE_OBJ_NAME_DO_ALL_SORTED -static void* -add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary) +static void +add_cipher_name_to_ary(const OBJ_NAME *name, void *arg) { + VALUE ary = (VALUE)arg; rb_ary_push(ary, rb_str_new2(name->name)); - return NULL; } -#endif -#ifdef HAVE_OBJ_NAME_DO_ALL_SORTED /* * call-seq: * OpenSSL::Cipher.ciphers -> array[string...] @@ -186,14 +200,11 @@ ossl_s_ciphers(VALUE self) ary = rb_ary_new(); OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, - (void(*)(const OBJ_NAME*,void*))add_cipher_name_to_ary, - (void*)ary); + add_cipher_name_to_ary, + (void*)ary); return ary; } -#else -#define ossl_s_ciphers rb_f_notimplement -#endif /* * call-seq: @@ -211,52 +222,23 @@ ossl_cipher_reset(VALUE self) GetCipher(self, ctx); if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1) != 1) - ossl_raise(eCipherError, NULL); + ossl_raise(eCipherError, NULL); return self; } static VALUE -ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode) +ossl_cipher_init(VALUE self, int enc) { EVP_CIPHER_CTX *ctx; - unsigned char key[EVP_MAX_KEY_LENGTH], *p_key = NULL; - unsigned char iv[EVP_MAX_IV_LENGTH], *p_iv = NULL; - VALUE pass, init_v; - - if(rb_scan_args(argc, argv, "02", &pass, &init_v) > 0){ - /* - * oops. this code mistakes salt for IV. - * We deprecated the arguments for this method, but we decided - * keeping this behaviour for backward compatibility. - */ - VALUE cname = rb_class_path(rb_obj_class(self)); - rb_warn("arguments for %"PRIsVALUE"#encrypt and %"PRIsVALUE"#decrypt were deprecated; " - "use %"PRIsVALUE"#pkcs5_keyivgen to derive key and IV", - cname, cname, cname); - StringValue(pass); - GetCipher(self, ctx); - if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv)); - else{ - StringValue(init_v); - if (EVP_MAX_IV_LENGTH > RSTRING_LEN(init_v)) { - memset(iv, 0, EVP_MAX_IV_LENGTH); - memcpy(iv, RSTRING_PTR(init_v), RSTRING_LEN(init_v)); - } - else memcpy(iv, RSTRING_PTR(init_v), sizeof(iv)); - } - EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv, - (unsigned char *)RSTRING_PTR(pass), RSTRING_LENINT(pass), 1, key, NULL); - p_key = key; - p_iv = iv; - } - else { - GetCipher(self, ctx); - } - if (EVP_CipherInit_ex(ctx, NULL, NULL, p_key, p_iv, mode) != 1) { - ossl_raise(eCipherError, NULL); + + GetCipher(self, ctx); + if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, enc) != 1) { + ossl_raise(eCipherError, "EVP_CipherInit_ex"); } + rb_ivar_set(self, id_key_set, Qfalse); + return self; } @@ -266,16 +248,15 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode) * * Initializes the Cipher for encryption. * - * Make sure to call Cipher#encrypt or Cipher#decrypt before using any of the - * following methods: - * * [key=, iv=, random_key, random_iv, pkcs5_keyivgen] + * Make sure to call either #encrypt or #decrypt before using the Cipher for + * any operation or setting any parameters. * * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 1). */ static VALUE -ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self) +ossl_cipher_encrypt(VALUE self) { - return ossl_cipher_init(argc, argv, self, 1); + return ossl_cipher_init(self, 1); } /* @@ -284,92 +265,89 @@ ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self) * * Initializes the Cipher for decryption. * - * Make sure to call Cipher#encrypt or Cipher#decrypt before using any of the - * following methods: - * * [key=, iv=, random_key, random_iv, pkcs5_keyivgen] + * Make sure to call either #encrypt or #decrypt before using the Cipher for + * any operation or setting any parameters. * * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 0). */ static VALUE -ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self) +ossl_cipher_decrypt(VALUE self) { - return ossl_cipher_init(argc, argv, self, 0); + return ossl_cipher_init(self, 0); } /* * call-seq: - * cipher.pkcs5_keyivgen(pass [, salt [, iterations [, digest]]] ) -> nil + * cipher.pkcs5_keyivgen(pass, salt = nil, iterations = 2048, digest = "MD5") -> nil * * Generates and sets the key/IV based on a password. * - * WARNING: This method is only PKCS5 v1.5 compliant when using RC2, RC4-40, - * or DES with MD5 or SHA1. Using anything else (like AES) will generate the - * key/iv using an OpenSSL specific method. This method is deprecated and - * should no longer be used. Use a PKCS5 v2 key generation method from - * OpenSSL::PKCS5 instead. + * *WARNING*: This method is deprecated and should not be used. This method + * corresponds to EVP_BytesToKey(), a non-standard OpenSSL extension of the + * legacy PKCS #5 v1.5 key derivation function. See OpenSSL::KDF for other + * options to derive keys from passwords. * * === Parameters - * +salt+ must be an 8 byte string if provided. - * +iterations+ is a integer with a default of 2048. - * +digest+ is a Digest object that defaults to 'MD5' - * - * A minimum of 1000 iterations is recommended. - * + * * _salt_ must be an 8 byte string if provided. + * * _iterations_ is an integer with a default of 2048. + * * _digest_ is a Digest object that defaults to 'MD5' */ static VALUE ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self) { EVP_CIPHER_CTX *ctx; const EVP_MD *digest; - VALUE vpass, vsalt, viter, vdigest; + VALUE vpass, vsalt, viter, vdigest, md_holder; unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH], *salt = NULL; int iter; rb_scan_args(argc, argv, "13", &vpass, &vsalt, &viter, &vdigest); StringValue(vpass); if(!NIL_P(vsalt)){ - StringValue(vsalt); - if(RSTRING_LEN(vsalt) != PKCS5_SALT_LEN) - ossl_raise(eCipherError, "salt must be an 8-octet string"); - salt = (unsigned char *)RSTRING_PTR(vsalt); + StringValue(vsalt); + if(RSTRING_LEN(vsalt) != PKCS5_SALT_LEN) + ossl_raise(eCipherError, "salt must be an 8-octet string"); + salt = (unsigned char *)RSTRING_PTR(vsalt); } iter = NIL_P(viter) ? 2048 : NUM2INT(viter); - digest = NIL_P(vdigest) ? EVP_md5() : GetDigestPtr(vdigest); + if (iter <= 0) + rb_raise(rb_eArgError, "iterations must be a positive integer"); + digest = NIL_P(vdigest) ? EVP_md5() : ossl_evp_md_fetch(vdigest, &md_holder); GetCipher(self, ctx); EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt, - (unsigned char *)RSTRING_PTR(vpass), RSTRING_LENINT(vpass), iter, key, iv); + (unsigned char *)RSTRING_PTR(vpass), RSTRING_LENINT(vpass), iter, key, iv); if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, -1) != 1) - ossl_raise(eCipherError, NULL); + ossl_raise(eCipherError, NULL); OPENSSL_cleanse(key, sizeof key); OPENSSL_cleanse(iv, sizeof iv); + rb_ivar_set(self, id_key_set, Qtrue); + return Qnil; } static int ossl_cipher_update_long(EVP_CIPHER_CTX *ctx, unsigned char *out, long *out_len_ptr, - const unsigned char *in, long in_len) + const unsigned char *in, long in_len) { int out_part_len; + int limit = INT_MAX / 2 + 1; long out_len = 0; -#define UPDATE_LENGTH_LIMIT INT_MAX - -#if SIZEOF_LONG > UPDATE_LENGTH_LIMIT - if (in_len > UPDATE_LENGTH_LIMIT) { - const int in_part_len = (UPDATE_LENGTH_LIMIT / 2 + 1) & ~1; - do { - if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0, - &out_part_len, in, in_part_len)) - return 0; - out_len += out_part_len; - in += in_part_len; - } while ((in_len -= in_part_len) > UPDATE_LENGTH_LIMIT); - } -#endif - if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0, - &out_part_len, in, (int)in_len)) - return 0; - if (out_len_ptr) *out_len_ptr = out_len += out_part_len; + + do { + int in_part_len = in_len > limit ? limit : (int)in_len; + + if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0, + &out_part_len, in, in_part_len)) + return 0; + + out_len += out_part_len; + in += in_part_len; + } while ((in_len -= limit) > 0); + + if (out_len_ptr) + *out_len_ptr = out_len; + return 1; } @@ -378,13 +356,15 @@ ossl_cipher_update_long(EVP_CIPHER_CTX *ctx, unsigned char *out, long *out_len_p * cipher.update(data [, buffer]) -> string or buffer * * Encrypts data in a streaming fashion. Hand consecutive blocks of data - * to the +update+ method in order to encrypt it. Returns the encrypted + * to the #update method in order to encrypt it. Returns the encrypted * data chunk. When done, the output of Cipher#final should be additionally * added to the result. * - * === Parameters - * +data+ is a nonempty string. - * +buffer+ is an optional string to store the result. + * If _buffer_ is given, the encryption/decryption result will be written to + * it. _buffer_ will be resized automatically. + * + * *NOTE*: When decrypting using an AEAD cipher, the integrity of the output + * is not verified until #final has been called. */ static VALUE ossl_cipher_update(int argc, VALUE *argv, VALUE self) @@ -396,27 +376,44 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "11", &data, &str); + if (!RTEST(rb_attr_get(self, id_key_set))) + ossl_raise(eCipherError, "key not set"); + StringValue(data); in = (unsigned char *)RSTRING_PTR(data); - if ((in_len = RSTRING_LEN(data)) == 0) - ossl_raise(rb_eArgError, "data must not be empty"); + in_len = RSTRING_LEN(data); GetCipher(self, ctx); - out_len = in_len+EVP_CIPHER_CTX_block_size(ctx); - if (out_len <= 0) { - ossl_raise(rb_eRangeError, - "data too big to make output buffer: %ld bytes", in_len); + + /* + * As of OpenSSL 3.2, there is no reliable way to determine the required + * output buffer size for arbitrary cipher modes. + * https://github.com/openssl/openssl/issues/22628 + * + * in_len+block_size is usually sufficient, but AES key wrap with padding + * ciphers require in_len+15 even though they have a block size of 8 bytes. + * + * Using EVP_MAX_BLOCK_LENGTH (32) as a safe upper bound for ciphers + * currently implemented in OpenSSL, but this can change in the future. + */ + if (in_len > LONG_MAX - EVP_MAX_BLOCK_LENGTH) { + ossl_raise(rb_eRangeError, + "data too big to make output buffer: %ld bytes", in_len); } + out_len = in_len + EVP_MAX_BLOCK_LENGTH; - if (NIL_P(str)) { - str = rb_str_new(0, out_len); - } else { + if (NIL_P(str)) + str = rb_str_buf_new(out_len); + else { StringValue(str); - rb_str_resize(str, out_len); + if ((long)rb_str_capacity(str) >= out_len) + rb_str_modify(str); + else + rb_str_modify_expand(str, out_len - RSTRING_LEN(str)); } - if (!ossl_cipher_update_long(ctx, (unsigned char *)RSTRING_PTR(str), &out_len, in, in_len)) - ossl_raise(eCipherError, NULL); - assert(out_len < RSTRING_LEN(str)); + if (!ossl_cipher_update_long(ctx, (unsigned char *)RSTRING_PTR(str), + &out_len, in, in_len)) + ossl_raise(eCipherError, "EVP_CipherUpdate"); rb_str_set_len(str, out_len); return str; @@ -427,14 +424,17 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self) * cipher.final -> string * * Returns the remaining data held in the cipher object. Further calls to - * Cipher#update or Cipher#final will return garbage. This call should always + * Cipher#update or Cipher#final are invalid. This call should always * be made as the last call of an encryption or decryption operation, after - * after having fed the entire plaintext or ciphertext to the Cipher instance. + * having fed the entire plaintext or ciphertext to the Cipher instance. * - * If an authenticated cipher was used, a CipherError is raised if the tag - * could not be authenticated successfully. Only call this method after - * setting the authentication tag and passing the entire contents of the - * ciphertext into the cipher. + * When encrypting using an AEAD cipher, the authentication tag can be + * retrieved by #auth_tag after #final has been called. + * + * When decrypting using an AEAD cipher, this method will verify the integrity + * of the ciphertext and the associated data with the authentication tag, + * which must be set by #auth_tag= prior to calling this method. + * If the verification fails, CipherError will be raised. */ static VALUE ossl_cipher_final(VALUE self) @@ -445,9 +445,17 @@ ossl_cipher_final(VALUE self) GetCipher(self, ctx); str = rb_str_new(0, EVP_CIPHER_CTX_block_size(ctx)); - if (!EVP_CipherFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), &out_len)) - ossl_raise(eCipherError, NULL); - assert(out_len <= RSTRING_LEN(str)); + if (!EVP_CipherFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), &out_len)) { + /* For AEAD ciphers, this is likely an authentication failure */ + if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER) { + /* For AEAD ciphers, EVP_CipherFinal_ex failures are authentication tag verification failures */ + ossl_raise(eAuthTagError, "AEAD authentication tag verification failed"); + } + else { + /* For non-AEAD ciphers */ + ossl_raise(eCipherError, "cipher final failed"); + } + } rb_str_set_len(str, out_len); return str; @@ -457,8 +465,8 @@ ossl_cipher_final(VALUE self) * call-seq: * cipher.name -> string * - * Returns the name of the cipher which may differ slightly from the original - * name provided. + * Returns the short name of the cipher which may differ slightly from the + * original name provided. */ static VALUE ossl_cipher_name(VALUE self) @@ -472,7 +480,7 @@ ossl_cipher_name(VALUE self) /* * call-seq: - * cipher.key = string -> string + * cipher.key = string * * Sets the cipher key. To generate a key, you should either use a secure * random byte string or, if the key is to be derived from a password, you @@ -480,74 +488,105 @@ ossl_cipher_name(VALUE self) * generate a secure random-based key, Cipher#random_key may be used. * * Only call this method after calling Cipher#encrypt or Cipher#decrypt. + * + * See also the man page EVP_CipherInit_ex(3). */ static VALUE ossl_cipher_set_key(VALUE self, VALUE key) { EVP_CIPHER_CTX *ctx; + int key_len; StringValue(key); GetCipher(self, ctx); - if (RSTRING_LEN(key) < EVP_CIPHER_CTX_key_length(ctx)) - ossl_raise(eCipherError, "key length too short"); + key_len = EVP_CIPHER_CTX_key_length(ctx); + if (RSTRING_LEN(key) != key_len) + ossl_raise(rb_eArgError, "key must be %d bytes", key_len); if (EVP_CipherInit_ex(ctx, NULL, NULL, (unsigned char *)RSTRING_PTR(key), NULL, -1) != 1) ossl_raise(eCipherError, NULL); + rb_ivar_set(self, id_key_set, Qtrue); + return key; } /* * call-seq: - * cipher.iv = string -> string + * cipher.iv = string * * Sets the cipher IV. Please note that since you should never be using ECB * mode, an IV is always explicitly required and should be set prior to - * encryption. The IV itself can be safely transmitted in public, but it - * should be unpredictable to prevent certain kinds of attacks. You may use - * Cipher#random_iv to create a secure random IV. + * encryption. The IV itself can be safely transmitted in public. * - * Only call this method after calling Cipher#encrypt or Cipher#decrypt. + * This method expects the String to have the length equal to #iv_len. To use + * a different IV length with an AEAD cipher, #iv_len= must be set prior to + * calling this method. + * + * *NOTE*: In OpenSSL API conventions, the IV value may correspond to the + * "nonce" instead in some cipher modes. Refer to the OpenSSL man pages for + * details. * - * If not explicitly set, the OpenSSL default of an all-zeroes ("\\0") IV is - * used. + * See also the man page EVP_CipherInit_ex(3). */ static VALUE ossl_cipher_set_iv(VALUE self, VALUE iv) { EVP_CIPHER_CTX *ctx; + int iv_len = 0; StringValue(iv); GetCipher(self, ctx); - if (RSTRING_LEN(iv) < EVP_CIPHER_CTX_iv_length(ctx)) - ossl_raise(eCipherError, "iv length too short"); + if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER) + iv_len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx); + if (!iv_len) + iv_len = EVP_CIPHER_CTX_iv_length(ctx); + if (RSTRING_LEN(iv) != iv_len) + ossl_raise(rb_eArgError, "iv must be %d bytes", iv_len); if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, (unsigned char *)RSTRING_PTR(iv), -1) != 1) - ossl_raise(eCipherError, NULL); + ossl_raise(eCipherError, NULL); return iv; } -#ifdef HAVE_AUTHENTICATED_ENCRYPTION /* * call-seq: - * cipher.auth_data = string -> string + * cipher.authenticated? -> true | false + * + * Indicates whether this Cipher instance uses an AEAD mode. + */ +static VALUE +ossl_cipher_is_authenticated(VALUE self) +{ + EVP_CIPHER_CTX *ctx; + + GetCipher(self, ctx); + + return (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER) ? Qtrue : Qfalse; +} + +/* + * call-seq: + * cipher.auth_data = string + * + * Sets additional authenticated data (AAD), also called associated data, for + * this Cipher. This method is available for AEAD ciphers. * - * Sets the cipher's additional authenticated data. This field must be - * set when using AEAD cipher modes such as GCM or CCM. If no associated - * data shall be used, this method must *still* be called with a value of "". * The contents of this field should be non-sensitive data which will be * added to the ciphertext to generate the authentication tag which validates * the contents of the ciphertext. * - * The AAD must be set prior to encryption or decryption. In encryption mode, - * it must be set after calling Cipher#encrypt and setting Cipher#key= and - * Cipher#iv=. When decrypting, the authenticated data must be set after key, - * iv and especially *after* the authentication tag has been set. I.e. set it - * only after calling Cipher#decrypt, Cipher#key=, Cipher#iv= and - * Cipher#auth_tag= first. + * This method must be called after #key= and #iv= have been set, but before + * starting actual encryption or decryption with #update. In some cipher modes, + * #auth_tag_len= and #ccm_data_len= may also need to be called before this + * method. + * + * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3). + * This method internally calls EVP_CipherUpdate() with the output buffer + * set to NULL. */ static VALUE ossl_cipher_set_auth_data(VALUE self, VALUE data) @@ -562,6 +601,8 @@ ossl_cipher_set_auth_data(VALUE self, VALUE data) in_len = RSTRING_LEN(data); GetCipher(self, ctx); + if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER)) + ossl_raise(eCipherError, "AEAD not supported by this cipher"); if (!ossl_cipher_update_long(ctx, NULL, &out_len, in, in_len)) ossl_raise(eCipherError, "couldn't set additional authenticated data"); @@ -569,88 +610,72 @@ ossl_cipher_set_auth_data(VALUE self, VALUE data) return data; } -#define ossl_is_gcm(nid) (nid) == NID_aes_128_gcm || \ - (nid) == NID_aes_192_gcm || \ - (nid) == NID_aes_256_gcm - -static VALUE -ossl_get_gcm_auth_tag(EVP_CIPHER_CTX *ctx, int len) -{ - unsigned char *tag; - VALUE ret; - - tag = ALLOC_N(unsigned char, len); - - if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, len, tag)) - ossl_raise(eCipherError, "retrieving the authentication tag failed"); - - ret = rb_str_new((const char *) tag, len); - xfree(tag); - return ret; -} - /* * call-seq: - * cipher.auth_tag([ tag_len ] -> string + * cipher.auth_tag(tag_len = 16) -> String + * + * Gets the generated authentication tag. This method is available for AEAD + * ciphers, and should be called after encryption has been finalized by calling + * #final. * - * Gets the authentication tag generated by Authenticated Encryption Cipher - * modes (GCM for example). This tag may be stored along with the ciphertext, - * then set on the decryption cipher to authenticate the contents of the - * ciphertext against changes. If the optional integer parameter +tag_len+ is - * given, the returned tag will be +tag_len+ bytes long. If the parameter is - * omitted, the maximum length of 16 bytes will be returned. For maximum - * security, the default of 16 bytes should be chosen. + * The returned tag will be _tag_len_ bytes long. Some cipher modes require + * the desired length in advance using a separate call to #auth_tag_len=, + * before starting encryption. * - * The tag may only be retrieved after calling Cipher#final. + * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3). + * This method internally calls EVP_CIPHER_CTX_ctrl() with + * EVP_CTRL_AEAD_GET_TAG. */ static VALUE ossl_cipher_get_auth_tag(int argc, VALUE *argv, VALUE self) { - VALUE vtag_len; + VALUE vtag_len, ret; EVP_CIPHER_CTX *ctx; - int nid, tag_len; + int tag_len = 16; - if (rb_scan_args(argc, argv, "01", &vtag_len) == 0) { - tag_len = 16; - } else { - tag_len = NUM2INT(vtag_len); - } + rb_scan_args(argc, argv, "01", &vtag_len); + if (NIL_P(vtag_len)) + vtag_len = rb_attr_get(self, id_auth_tag_len); + if (!NIL_P(vtag_len)) + tag_len = NUM2INT(vtag_len); GetCipher(self, ctx); - nid = EVP_CIPHER_CTX_nid(ctx); - if (ossl_is_gcm(nid)) { - return ossl_get_gcm_auth_tag(ctx, tag_len); - } else { - ossl_raise(eCipherError, "authentication tag not supported by this cipher"); - return Qnil; /* dummy */ - } -} + if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER)) + ossl_raise(eCipherError, "authentication tag not supported by this cipher"); -static inline void -ossl_set_gcm_auth_tag(EVP_CIPHER_CTX *ctx, unsigned char *tag, int tag_len) -{ - if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag_len, tag)) - ossl_raise(eCipherError, "unable to set GCM tag"); + ret = rb_str_new(NULL, tag_len); + if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tag_len, RSTRING_PTR(ret))) + ossl_raise(eCipherError, "retrieving the authentication tag failed"); + + return ret; } /* * call-seq: - * cipher.auth_tag = string -> string - * - * Sets the authentication tag to verify the contents of the - * ciphertext. The tag must be set after calling Cipher#decrypt, - * Cipher#key= and Cipher#iv=, but before assigning the associated - * authenticated data using Cipher#auth_data= and of course, before - * decrypting any of the ciphertext. After all decryption is - * performed, the tag is verified automatically in the call to - * Cipher#final. + * cipher.auth_tag = string + * + * Sets the authentication tag to verify the integrity of the ciphertext. + * + * The authentication tag must be set before #final is called. The tag is + * verified during the #final call. + * + * Note that, for CCM mode and OCB mode, the expected length of the tag must + * be set before starting decryption by a separate call to #auth_tag_len=. + * The content of the tag can be provided at any time before #final is called. + * + * *NOTE*: The caller must ensure that the String passed to this method has + * the desired length. Some cipher modes support variable tag lengths, and + * this method may accept a truncated tag without raising an exception. + * + * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3). + * This method internally calls EVP_CIPHER_CTX_ctrl() with + * EVP_CTRL_AEAD_SET_TAG. */ static VALUE ossl_cipher_set_auth_tag(VALUE self, VALUE vtag) { EVP_CIPHER_CTX *ctx; - int nid; unsigned char *tag; int tag_len; @@ -659,55 +684,93 @@ ossl_cipher_set_auth_tag(VALUE self, VALUE vtag) tag_len = RSTRING_LENINT(vtag); GetCipher(self, ctx); - nid = EVP_CIPHER_CTX_nid(ctx); + if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER)) + ossl_raise(eCipherError, "authentication tag not supported by this cipher"); - if (ossl_is_gcm(nid)) { - ossl_set_gcm_auth_tag(ctx, tag, tag_len); - } else { - ossl_raise(eCipherError, "authentication tag not supported by this cipher"); - } + if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, tag)) + ossl_raise(eCipherError, "unable to set AEAD tag"); return vtag; } /* * call-seq: - * cipher.authenticated? -> boolean + * cipher.auth_tag_len = integer + * + * Sets the length of the expected authentication tag for this Cipher. This + * method is available for some of AEAD ciphers that require the length to be + * set before starting encryption or decryption, such as CCM mode or OCB mode. * - * Indicated whether this Cipher instance uses an Authenticated Encryption - * mode. + * For CCM mode and OCB mode, the tag length must be set before #iv= is set. + * + * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3). + * This method internally calls EVP_CIPHER_CTX_ctrl() with + * EVP_CTRL_AEAD_SET_TAG and a NULL buffer. */ static VALUE -ossl_cipher_is_authenticated(VALUE self) +ossl_cipher_set_auth_tag_len(VALUE self, VALUE vlen) { + int tag_len = NUM2INT(vlen); EVP_CIPHER_CTX *ctx; - int nid; GetCipher(self, ctx); - nid = EVP_CIPHER_CTX_nid(ctx); + if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER)) + ossl_raise(eCipherError, "AEAD not supported by this cipher"); - if (ossl_is_gcm(nid)) { - return Qtrue; - } else { - return Qfalse; - } + if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, NULL)) + ossl_raise(eCipherError, "unable to set authentication tag length"); + + /* for #auth_tag */ + rb_ivar_set(self, id_auth_tag_len, INT2NUM(tag_len)); + + return vlen; +} + +/* + * call-seq: + * cipher.iv_len = integer + * + * Sets the IV/nonce length for this Cipher. This method is available for AEAD + * ciphers that support variable IV lengths. This method can be called if a + * different IV length than OpenSSL's default is desired, prior to calling + * #iv=. + * + * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3). + * This method internally calls EVP_CIPHER_CTX_ctrl() with + * EVP_CTRL_AEAD_SET_IVLEN. + */ +static VALUE +ossl_cipher_set_iv_length(VALUE self, VALUE iv_length) +{ + int len = NUM2INT(iv_length); + EVP_CIPHER_CTX *ctx; + + GetCipher(self, ctx); + if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER)) + ossl_raise(eCipherError, "cipher does not support AEAD"); + + if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, len, NULL)) + ossl_raise(eCipherError, "unable to set IV length"); + + /* + * EVP_CIPHER_CTX_iv_length() returns the default length. So we need to save + * the length somewhere. Luckily currently we aren't using app_data. + */ + EVP_CIPHER_CTX_set_app_data(ctx, (void *)(VALUE)len); + + return iv_length; } -#else -#define ossl_cipher_set_auth_data rb_f_notimplement -#define ossl_cipher_get_auth_tag rb_f_notimplement -#define ossl_cipher_set_auth_tag rb_f_notimplement -#define ossl_cipher_is_authenticated rb_f_notimplement -#endif /* * call-seq: - * cipher.key_len = integer -> integer + * cipher.key_len = integer * * Sets the key length of the cipher. If the cipher is a fixed length cipher * then attempting to set the key length to any value other than the fixed * value is an error. * - * Under normal circumstances you do not need to call this method (and probably shouldn't). + * Under normal circumstances you do not need to call this method (and + * probably shouldn't). * * See EVP_CIPHER_CTX_set_key_length for further information. */ @@ -724,14 +787,16 @@ ossl_cipher_set_key_length(VALUE self, VALUE key_length) return key_length; } -#if defined(HAVE_EVP_CIPHER_CTX_SET_PADDING) +// TODO: Should #padding= take a boolean value instead? /* * call-seq: - * cipher.padding = integer -> integer + * cipher.padding = 1 or 0 * - * Enables or disables padding. By default encryption operations are padded using standard block padding and the - * padding is checked and removed when decrypting. If the pad parameter is zero then no padding is performed, the - * total amount of data encrypted or decrypted must then be a multiple of the block size or an error will occur. + * Enables or disables padding. By default encryption operations are padded + * using standard block padding and the padding is checked and removed when + * decrypting. If the pad parameter is zero then no padding is performed, the + * total amount of data encrypted or decrypted must then be a multiple of the + * block size or an error will occur. * * See EVP_CIPHER_CTX_set_padding for further information. */ @@ -743,21 +808,9 @@ ossl_cipher_set_padding(VALUE self, VALUE padding) GetCipher(self, ctx); if (EVP_CIPHER_CTX_set_padding(ctx, pad) != 1) - ossl_raise(eCipherError, NULL); + ossl_raise(eCipherError, NULL); return padding; } -#else -#define ossl_cipher_set_padding rb_f_notimplement -#endif - -#define CIPHER_0ARG_INT(func) \ - static VALUE \ - ossl_cipher_##func(VALUE self) \ - { \ - EVP_CIPHER_CTX *ctx; \ - GetCipher(self, ctx); \ - return INT2NUM(EVP_CIPHER_##func(EVP_CIPHER_CTX_cipher(ctx))); \ - } /* * call-seq: @@ -765,21 +818,81 @@ ossl_cipher_set_padding(VALUE self, VALUE padding) * * Returns the key length in bytes of the Cipher. */ -CIPHER_0ARG_INT(key_length) +static VALUE +ossl_cipher_key_length(VALUE self) +{ + EVP_CIPHER_CTX *ctx; + + GetCipher(self, ctx); + + return INT2NUM(EVP_CIPHER_CTX_key_length(ctx)); +} + /* * call-seq: * cipher.iv_len -> integer * * Returns the expected length in bytes for an IV for this Cipher. */ -CIPHER_0ARG_INT(iv_length) +static VALUE +ossl_cipher_iv_length(VALUE self) +{ + EVP_CIPHER_CTX *ctx; + int len = 0; + + GetCipher(self, ctx); + if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER) + len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx); + if (!len) + len = EVP_CIPHER_CTX_iv_length(ctx); + + return INT2NUM(len); +} + /* * call-seq: * cipher.block_size -> integer * * Returns the size in bytes of the blocks on which this Cipher operates on. */ -CIPHER_0ARG_INT(block_size) +static VALUE +ossl_cipher_block_size(VALUE self) +{ + EVP_CIPHER_CTX *ctx; + + GetCipher(self, ctx); + + return INT2NUM(EVP_CIPHER_CTX_block_size(ctx)); +} + +/* + * call-seq: + * cipher.ccm_data_len = integer + * + * Sets the total length of the plaintext / ciphertext message that will be + * processed by #update in CCM mode. + * + * Make sure to call this method after #key= and #iv= have been set, and + * before #auth_data= or #update are called. + * + * This method is only available for CCM mode ciphers. + * + * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3). + */ +static VALUE +ossl_cipher_set_ccm_data_len(VALUE self, VALUE data_len) +{ + int in_len, out_len; + EVP_CIPHER_CTX *ctx; + + in_len = NUM2INT(data_len); + + GetCipher(self, ctx); + if (EVP_CipherUpdate(ctx, NULL, &out_len, NULL, in_len) != 1) + ossl_raise(eCipherError, NULL); + + return data_len; +} /* * INIT @@ -787,10 +900,6 @@ CIPHER_0ARG_INT(block_size) void Init_ossl_cipher(void) { -#if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ -#endif - /* Document-class: OpenSSL::Cipher * * Provides symmetric algorithms for encryption and decryption. The @@ -816,23 +925,7 @@ Init_ossl_cipher(void) * individual components name, key length and mode. Either all uppercase * or all lowercase strings may be used, for example: * - * cipher = OpenSSL::Cipher.new('AES-128-CBC') - * - * For each algorithm supported, there is a class defined under the - * Cipher class that goes by the name of the cipher, e.g. to obtain an - * instance of AES, you could also use - * - * # these are equivalent - * cipher = OpenSSL::Cipher::AES.new(128, :CBC) - * cipher = OpenSSL::Cipher::AES.new(128, 'CBC') - * cipher = OpenSSL::Cipher::AES.new('128-CBC') - * - * Finally, due to its wide-spread use, there are also extra classes - * defined for the different key sizes of AES - * - * cipher = OpenSSL::Cipher::AES128.new(:CBC) - * cipher = OpenSSL::Cipher::AES192.new(:CBC) - * cipher = OpenSSL::Cipher::AES256.new(:CBC) + * cipher = OpenSSL::Cipher.new('aes-128-cbc') * * === Choosing either encryption or decryption mode * @@ -862,7 +955,7 @@ Init_ossl_cipher(void) * without processing the password further. A simple and secure way to * create a key for a particular Cipher is * - * cipher = OpenSSL::AES256.new(:CFB) + * cipher = OpenSSL::Cipher.new('aes-256-cfb') * cipher.encrypt * key = cipher.random_key # also sets the generated key on the Cipher * @@ -887,12 +980,10 @@ Init_ossl_cipher(void) * you absolutely need it</b> * * Because of this, you will end up with a mode that explicitly requires - * an IV in any case. Note that for backwards compatibility reasons, - * setting an IV is not explicitly mandated by the Cipher API. If not - * set, OpenSSL itself defaults to an all-zeroes IV ("\\0", not the - * character). Although the IV can be seen as public information, i.e. - * it may be transmitted in public once generated, it should still stay - * unpredictable to prevent certain kinds of attacks. Therefore, ideally + * an IV in any case. Although the IV can be seen as public information, + * i.e. it may be transmitted in public once generated, it should still + * stay unpredictable to prevent certain kinds of attacks. Therefore, + * ideally * * <b>Always create a secure random IV for every encryption of your * Cipher</b> @@ -901,16 +992,16 @@ Init_ossl_cipher(void) * of the IV as a nonce (number used once) - it's public but random and * unpredictable. A secure random IV can be created as follows * - * cipher = ... - * cipher.encrypt - * key = cipher.random_key - * iv = cipher.random_iv # also sets the generated IV on the Cipher + * cipher = ... + * cipher.encrypt + * key = cipher.random_key + * iv = cipher.random_iv # also sets the generated IV on the Cipher * - * Although the key is generally a random value, too, it is a bad choice - * as an IV. There are elaborate ways how an attacker can take advantage - * of such an IV. As a general rule of thumb, exposing the key directly - * or indirectly should be avoided at all cost and exceptions only be - * made with good reason. + * Although the key is generally a random value, too, it is a bad choice + * as an IV. There are elaborate ways how an attacker can take advantage + * of such an IV. As a general rule of thumb, exposing the key directly + * or indirectly should be avoided at all cost and exceptions only be + * made with good reason. * * === Calling Cipher#final * @@ -932,14 +1023,14 @@ Init_ossl_cipher(void) * * data = "Very, very confidential data" * - * cipher = OpenSSL::Cipher::AES.new(128, :CBC) + * cipher = OpenSSL::Cipher.new('aes-128-cbc') * cipher.encrypt * key = cipher.random_key * iv = cipher.random_iv * * encrypted = cipher.update(data) + cipher.final * ... - * decipher = OpenSSL::Cipher::AES.new(128, :CBC) + * decipher = OpenSSL::Cipher.new('aes-128-cbc') * decipher.decrypt * decipher.key = key * decipher.iv = iv @@ -964,40 +1055,63 @@ Init_ossl_cipher(void) * could otherwise be exploited to modify ciphertexts in ways beneficial to * potential attackers. * - * If no associated data is needed for encryption and later decryption, - * the OpenSSL library still requires a value to be set - "" may be used in - * case none is available. An example using the GCM (Galois Counter Mode): + * Associated data, also called additional authenticated data (AAD), is + * optionally used where there is additional information, such as + * headers or some metadata, that must be also authenticated but not + * necessarily need to be encrypted. * - * cipher = OpenSSL::Cipher::AES.new(128, :GCM) - * cipher.encrypt - * key = cipher.random_key - * iv = cipher.random_iv - * cipher.auth_data = "" + * An example using the GCM (Galois/Counter Mode). You have 16 bytes _key_, + * 12 bytes (96 bits) _nonce_ and the associated data _auth_data_. Be sure + * not to reuse the _key_ and _nonce_ pair. Reusing an nonce ruins the + * security guarantees of GCM mode. + * + * key = OpenSSL::Random.random_bytes(16) + * nonce = OpenSSL::Random.random_bytes(12) + * auth_data = "authenticated but unencrypted data" + * data = "encrypted data" + * + * cipher = OpenSSL::Cipher.new('aes-128-gcm').encrypt + * cipher.key = key + * cipher.iv = nonce + * cipher.auth_data = auth_data * * encrypted = cipher.update(data) + cipher.final - * tag = cipher.auth_tag + * tag = cipher.auth_tag(16) * - * decipher = OpenSSL::Cipher::AES.new(128, :GCM) - * decipher.decrypt + * Now you are the receiver. You know the _key_ and have received _nonce_, + * _auth_data_, _encrypted_ and _tag_ through an untrusted network. Note + * that GCM accepts an arbitrary length tag between 1 and 16 bytes. You may + * additionally need to check that the received tag has the correct length, + * or you allow attackers to forge a valid single byte tag for the tampered + * ciphertext with a probability of 1/256. + * + * raise "tag is truncated!" unless tag.bytesize == 16 + * decipher = OpenSSL::Cipher.new('aes-128-gcm').decrypt * decipher.key = key - * decipher.iv = iv - * decipher.auth_tag = tag - * decipher.auth_data = "" + * decipher.iv = nonce + * decipher.auth_tag = tag # could be called at any time before #final + * decipher.auth_data = auth_data * - * plain = decipher.update(encrypted) + decipher.final + * decrypted = decipher.update(encrypted) + decipher.final * - * puts data == plain #=> true + * puts data == decrypted #=> true + * + * Note that other AEAD ciphers may require additional steps, such as + * setting the expected tag length (#auth_tag_len=) or the total data + * length (#ccm_data_len=) in advance. Make sure to read the relevant man + * page for details. */ cCipher = rb_define_class_under(mOSSL, "Cipher", rb_cObject); eCipherError = rb_define_class_under(cCipher, "CipherError", eOSSLError); + eAuthTagError = rb_define_class_under(cCipher, "AuthTagError", eCipherError); rb_define_alloc_func(cCipher, ossl_cipher_alloc); - rb_define_copy_func(cCipher, ossl_cipher_copy); + rb_define_method(cCipher, "initialize_copy", ossl_cipher_copy, 1); rb_define_module_function(cCipher, "ciphers", ossl_s_ciphers, 0); rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1); rb_define_method(cCipher, "reset", ossl_cipher_reset, 0); - rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1); - rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1); + rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, 0); + rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, 0); rb_define_method(cCipher, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1); rb_define_method(cCipher, "update", ossl_cipher_update, -1); rb_define_method(cCipher, "final", ossl_cipher_final, 0); @@ -1006,12 +1120,18 @@ Init_ossl_cipher(void) rb_define_method(cCipher, "auth_data=", ossl_cipher_set_auth_data, 1); rb_define_method(cCipher, "auth_tag=", ossl_cipher_set_auth_tag, 1); rb_define_method(cCipher, "auth_tag", ossl_cipher_get_auth_tag, -1); + rb_define_method(cCipher, "auth_tag_len=", ossl_cipher_set_auth_tag_len, 1); rb_define_method(cCipher, "authenticated?", ossl_cipher_is_authenticated, 0); rb_define_method(cCipher, "key_len=", ossl_cipher_set_key_length, 1); rb_define_method(cCipher, "key_len", ossl_cipher_key_length, 0); rb_define_method(cCipher, "iv=", ossl_cipher_set_iv, 1); + rb_define_method(cCipher, "iv_len=", ossl_cipher_set_iv_length, 1); rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0); rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0); rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1); -} + rb_define_method(cCipher, "ccm_data_len=", ossl_cipher_set_ccm_data_len, 1); + id_auth_tag_len = rb_intern_const("auth_tag_len"); + id_key_set = rb_intern_const("key_set"); + id_cipher_holder = rb_intern_const("EVP_CIPHER_holder"); +} diff --git a/ext/openssl/ossl_cipher.h b/ext/openssl/ossl_cipher.h index bed4fa853b..fba63a140f 100644 --- a/ext/openssl/ossl_cipher.h +++ b/ext/openssl/ossl_cipher.h @@ -1,22 +1,26 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(_OSSL_CIPHER_H_) #define _OSSL_CIPHER_H_ -extern VALUE cCipher; -extern VALUE eCipherError; - -const EVP_CIPHER *GetCipherPtr(VALUE); +/* + * Gets EVP_CIPHER from a String or an OpenSSL::Digest instance (discouraged, + * but still supported for compatibility). A holder object is created if the + * EVP_CIPHER is a "fetched" algorithm. + */ +const EVP_CIPHER *ossl_evp_cipher_fetch(VALUE obj, volatile VALUE *holder); +/* + * This is meant for OpenSSL::Engine#cipher. EVP_CIPHER must not be a fetched + * one. + */ VALUE ossl_cipher_new(const EVP_CIPHER *); void Init_ossl_cipher(void); #endif /* _OSSL_CIPHER_H_ */ - diff --git a/ext/openssl/ossl_config.c b/ext/openssl/ossl_config.c index 74a52f71a2..274875a978 100644 --- a/ext/openssl/ossl_config.c +++ b/ext/openssl/ossl_config.c @@ -1,83 +1,456 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" +static VALUE cConfig, eConfigError; + +static void +nconf_free(void *conf) +{ + NCONF_free(conf); +} + +static const rb_data_type_t ossl_config_type = { + "OpenSSL/CONF", + { + 0, nconf_free, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE, +}; + +CONF * +GetConfig(VALUE obj) +{ + CONF *conf; + + TypedData_Get_Struct(obj, CONF, &ossl_config_type, conf); + if (!conf) + rb_raise(rb_eRuntimeError, "CONF is not initialized"); + return conf; +} + +static VALUE +config_s_alloc(VALUE klass) +{ + VALUE obj; + CONF *conf; + + obj = TypedData_Wrap_Struct(klass, &ossl_config_type, 0); + conf = NCONF_new(NULL); + if (!conf) + ossl_raise(eConfigError, "NCONF_new"); + RTYPEDDATA_DATA(obj) = conf; + return obj; +} + +static void +config_load_bio(CONF *conf, BIO *bio) +{ + long eline = -1; + + if (!NCONF_load_bio(conf, bio, &eline)) { + BIO_free(bio); + if (eline <= 0) + ossl_raise(eConfigError, "wrong config format"); + else + ossl_raise(eConfigError, "error in line %ld", eline); + } + BIO_free(bio); + + /* + * Clear the error queue even if it is parsed successfully. + * Particularly, when the .include directive refers to a non-existent file, + * it is only reported in the error queue. + */ + ossl_clear_error(); +} /* - * Classes - */ -VALUE cConfig; -/* Document-class: OpenSSL::ConfigError + * call-seq: + * Config.parse(string) -> OpenSSL::Config * - * General error for openssl library configuration files. Including formatting, - * parsing errors, etc. + * Parses a given _string_ as a blob that contains configuration for OpenSSL. */ -VALUE eConfigError; +static VALUE +config_s_parse(VALUE klass, VALUE str) +{ + VALUE obj = config_s_alloc(klass); + CONF *conf = GetConfig(obj); + BIO *bio; + + bio = ossl_obj2bio(&str); + config_load_bio(conf, bio); /* Consumes BIO */ + rb_obj_freeze(obj); + return obj; +} + +static VALUE config_get_sections(VALUE self); +static VALUE config_get_section(VALUE self, VALUE section); /* - * Public + * call-seq: + * Config.parse_config(io) -> hash + * + * Parses the configuration data read from _io_ and returns the whole content + * as a Hash. */ +static VALUE +config_s_parse_config(VALUE klass, VALUE io) +{ + VALUE obj, sections, ret; + long i; + + obj = config_s_parse(klass, io); + sections = config_get_sections(obj); + ret = rb_hash_new(); + for (i = 0; i < RARRAY_LEN(sections); i++) { + VALUE section = rb_ary_entry(sections, i); + rb_hash_aset(ret, section, config_get_section(obj, section)); + } + return ret; +} /* - * GetConfigPtr is a public C-level function for getting OpenSSL CONF struct - * from an OpenSSL::Config(eConfig) instance. We decided to implement - * OpenSSL::Config in Ruby level but we need to pass native CONF struct for - * some OpenSSL features such as X509V3_EXT_*. + * call-seq: + * Config.new(filename) -> OpenSSL::Config + * + * Creates an instance of OpenSSL::Config from the content of the file + * specified by _filename_. + * + * This can be used in contexts like OpenSSL::X509::ExtensionFactory.config= + * + * This can raise IO exceptions based on the access, or availability of the + * file. A ConfigError exception may be raised depending on the validity of + * the data being configured. */ -CONF * -GetConfigPtr(VALUE obj) +static VALUE +config_initialize(int argc, VALUE *argv, VALUE self) { - CONF *conf; + CONF *conf = GetConfig(self); + VALUE filename; + + /* 0-arguments call has no use-case, but is kept for compatibility */ + rb_scan_args(argc, argv, "01", &filename); + rb_check_frozen(self); + if (!NIL_P(filename)) { + BIO *bio = BIO_new_file(StringValueCStr(filename), "rb"); + if (!bio) + ossl_raise(eConfigError, "BIO_new_file"); + config_load_bio(conf, bio); /* Consumes BIO */ + } + rb_obj_freeze(self); + return self; +} + +static VALUE +config_initialize_copy(VALUE self, VALUE other) +{ + CONF *conf = GetConfig(self); VALUE str; BIO *bio; - long eline = -1; - OSSL_Check_Kind(obj, cConfig); - str = rb_funcall(obj, rb_intern("to_s"), 0); - bio = ossl_obj2bio(str); - conf = NCONF_new(NULL); - if(!conf){ - BIO_free(bio); - ossl_raise(eConfigError, NULL); + str = rb_funcall(other, rb_intern("to_s"), 0); + rb_check_frozen(self); + bio = ossl_obj2bio(&str); + config_load_bio(conf, bio); /* Consumes BIO */ + rb_obj_freeze(self); + return self; +} + +/* + * call-seq: + * config.get_value(section, key) -> string + * + * Gets the value of _key_ from the given _section_. + * + * Given the following configurating file being loaded: + * + * config = OpenSSL::Config.load('foo.cnf') + * #=> #<OpenSSL::Config sections=["default"]> + * puts config.to_s + * #=> [ default ] + * # foo=bar + * + * You can get a specific value from the config if you know the _section_ + * and _key_ like so: + * + * config.get_value('default','foo') + * #=> "bar" + */ +static VALUE +config_get_value(VALUE self, VALUE section, VALUE key) +{ + CONF *conf = GetConfig(self); + const char *str, *sectionp; + + StringValueCStr(section); + StringValueCStr(key); + /* For compatibility; NULL means "default". */ + sectionp = RSTRING_LEN(section) ? RSTRING_PTR(section) : NULL; + str = NCONF_get_string(conf, sectionp, RSTRING_PTR(key)); + if (!str) { + ossl_clear_error(); + return Qnil; + } + return rb_str_new_cstr(str); +} + +/* + * call-seq: + * config[section] -> hash + * + * Gets all key-value pairs in a specific _section_ from the current + * configuration. + * + * Given the following configurating file being loaded: + * + * config = OpenSSL::Config.load('foo.cnf') + * #=> #<OpenSSL::Config sections=["default"]> + * puts config.to_s + * #=> [ default ] + * # foo=bar + * + * You can get a hash of the specific section like so: + * + * config['default'] + * #=> {"foo"=>"bar"} + * + */ +static VALUE +config_get_section(VALUE self, VALUE section) +{ + CONF *conf = GetConfig(self); + STACK_OF(CONF_VALUE) *sk; + int i, entries; + VALUE hash; + + hash = rb_hash_new(); + StringValueCStr(section); + if (!(sk = NCONF_get_section(conf, RSTRING_PTR(section)))) { + ossl_clear_error(); + return hash; } - if(!NCONF_load_bio(conf, bio, &eline)){ - BIO_free(bio); - NCONF_free(conf); - if (eline <= 0) ossl_raise(eConfigError, "wrong config format"); - else ossl_raise(eConfigError, "error in line %d", eline); - ossl_raise(eConfigError, NULL); + entries = sk_CONF_VALUE_num(sk); + for (i = 0; i < entries; i++) { + CONF_VALUE *entry = sk_CONF_VALUE_value(sk, i); + rb_hash_aset(hash, rb_str_new_cstr(entry->name), + rb_str_new_cstr(entry->value)); } - BIO_free(bio); + return hash; +} - return conf; +static void +get_conf_section_doall_arg(CONF_VALUE *cv, VALUE *aryp) +{ + if (cv->name) + return; + rb_ary_push(*aryp, rb_str_new_cstr(cv->section)); } -/* Document-const: DEFAULT_CONFIG_FILE +/* IMPLEMENT_LHASH_DOALL_ARG_CONST() requires >= OpenSSL 1.1.0 */ +static IMPLEMENT_LHASH_DOALL_ARG_FN(get_conf_section, CONF_VALUE, VALUE) + +/* + * call-seq: + * config.sections -> array of string * - * The default system configuration file for openssl + * Get the names of all sections in the current configuration. */ +static VALUE +config_get_sections(VALUE self) +{ + CONF *conf = GetConfig(self); + VALUE ary; + + ary = rb_ary_new(); + lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(get_conf_section), + &ary); + return ary; +} + +static void +dump_conf_value_doall_arg(CONF_VALUE *cv, VALUE *strp) +{ + VALUE str = *strp; + STACK_OF(CONF_VALUE) *sk; + int i, num; + + if (cv->name) + return; + sk = (STACK_OF(CONF_VALUE) *)cv->value; + num = sk_CONF_VALUE_num(sk); + rb_str_cat_cstr(str, "[ "); + rb_str_cat_cstr(str, cv->section); + rb_str_cat_cstr(str, " ]\n"); + for (i = 0; i < num; i++){ + CONF_VALUE *v = sk_CONF_VALUE_value(sk, i); + rb_str_cat_cstr(str, v->name ? v->name : "None"); + rb_str_cat_cstr(str, "="); + rb_str_cat_cstr(str, v->value ? v->value : "None"); + rb_str_cat_cstr(str, "\n"); + } + rb_str_cat_cstr(str, "\n"); +} + +static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_conf_value, CONF_VALUE, VALUE) /* - * INIT + * call-seq: + * config.to_s -> string + * + * + * Gets the parsable form of the current configuration. + * + * Given the following configuration file being loaded: + * + * config = OpenSSL::Config.load('baz.cnf') + * #=> #<OpenSSL::Config sections=["default"]> + * puts config.to_s + * #=> [ default ] + * # foo=bar + * # baz=buz + * + * You can get the serialized configuration using #to_s and then parse + * it later: + * + * serialized_config = config.to_s + * # much later... + * new_config = OpenSSL::Config.parse(serialized_config) + * #=> #<OpenSSL::Config sections=["default"]> + * puts new_config + * #=> [ default ] + * foo=bar + * baz=buz */ +static VALUE +config_to_s(VALUE self) +{ + CONF *conf = GetConfig(self); + VALUE str; + + str = rb_str_new(NULL, 0); + lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(dump_conf_value), + &str); + return str; +} + +static void +each_conf_value_doall_arg(CONF_VALUE *cv, void *unused) +{ + STACK_OF(CONF_VALUE) *sk; + VALUE section; + int i, num; + + if (cv->name) + return; + sk = (STACK_OF(CONF_VALUE) *)cv->value; + num = sk_CONF_VALUE_num(sk); + section = rb_str_new_cstr(cv->section); + for (i = 0; i < num; i++){ + CONF_VALUE *v = sk_CONF_VALUE_value(sk, i); + VALUE name = v->name ? rb_str_new_cstr(v->name) : Qnil; + VALUE value = v->value ? rb_str_new_cstr(v->value) : Qnil; + rb_yield(rb_ary_new3(3, section, name, value)); + } +} + +static IMPLEMENT_LHASH_DOALL_ARG_FN(each_conf_value, CONF_VALUE, void) + +/* + * call-seq: + * config.each { |section, key, value| } + * + * Retrieves the section and its pairs for the current configuration. + * + * config.each do |section, key, value| + * # ... + * end + */ +static VALUE +config_each(VALUE self) +{ + CONF *conf = GetConfig(self); + + RETURN_ENUMERATOR(self, 0, 0); + + lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(each_conf_value), + NULL); + return self; +} + +/* + * call-seq: + * config.inspect -> string + * + * String representation of this configuration object, including the class + * name and its sections. + */ +static VALUE +config_inspect(VALUE self) +{ + VALUE str, ary = config_get_sections(self); + const char *cname = rb_class2name(rb_obj_class(self)); + + str = rb_str_new_cstr("#<"); + rb_str_cat_cstr(str, cname); + rb_str_cat_cstr(str, " sections="); + rb_str_append(str, rb_inspect(ary)); + rb_str_cat_cstr(str, ">"); + + return str; +} + void Init_ossl_config(void) { - char *default_config_file; - eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError); + char *path; + VALUE path_str; + + /* Document-class: OpenSSL::Config + * + * Configuration for the openssl library. + * + * Many system's installation of openssl library will depend on your system + * configuration. See the value of OpenSSL::Config::DEFAULT_CONFIG_FILE for + * the location of the file for your host. + * + * See also https://docs.openssl.org/master/man5/config/ + */ cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject); - default_config_file = CONF_get1_default_config_file(); - rb_define_const(cConfig, "DEFAULT_CONFIG_FILE", - rb_str_new2(default_config_file)); - OPENSSL_free(default_config_file); - /* methods are defined by openssl/config.rb */ + /* Document-class: OpenSSL::ConfigError + * + * General error for openssl library configuration files. Including formatting, + * parsing errors, etc. + */ + eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError); + + rb_include_module(cConfig, rb_mEnumerable); + rb_define_singleton_method(cConfig, "parse", config_s_parse, 1); + rb_define_singleton_method(cConfig, "parse_config", config_s_parse_config, 1); + rb_define_alias(CLASS_OF(cConfig), "load", "new"); + rb_define_alloc_func(cConfig, config_s_alloc); + rb_define_method(cConfig, "initialize", config_initialize, -1); + rb_define_method(cConfig, "initialize_copy", config_initialize_copy, 1); + rb_define_method(cConfig, "get_value", config_get_value, 2); + rb_define_method(cConfig, "[]", config_get_section, 1); + rb_define_method(cConfig, "sections", config_get_sections, 0); + rb_define_method(cConfig, "to_s", config_to_s, 0); + rb_define_method(cConfig, "each", config_each, 0); + rb_define_method(cConfig, "inspect", config_inspect, 0); + + /* Document-const: DEFAULT_CONFIG_FILE + * + * The default system configuration file for OpenSSL. + */ + path = CONF_get1_default_config_file(); + path_str = rb_obj_freeze(ossl_buf2str(path, rb_long2int(strlen(path)))); + rb_define_const(cConfig, "DEFAULT_CONFIG_FILE", path_str); } diff --git a/ext/openssl/ossl_config.h b/ext/openssl/ossl_config.h index cb226b27e5..a254360c2c 100644 --- a/ext/openssl/ossl_config.h +++ b/ext/openssl/ossl_config.h @@ -1,22 +1,16 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ -#if !defined(_OSSL_CONFIG_H_) -#define _OSSL_CONFIG_H_ +#ifndef OSSL_CONFIG_H +#define OSSL_CONFIG_H -extern VALUE cConfig; -extern VALUE eConfigError; - -CONF* GetConfigPtr(VALUE obj); -CONF* DupConfigPtr(VALUE obj); +CONF *GetConfig(VALUE obj); void Init_ossl_config(void); -#endif /* _OSSL_CONFIG_H_ */ - +#endif /* OSSL_CONFIG_H */ diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c index 6ce5316fd9..e23968b1e3 100644 --- a/ext/openssl/ossl_digest.c +++ b/ext/openssl/ossl_digest.c @@ -1,31 +1,27 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" #define GetDigest(obj, ctx) do { \ TypedData_Get_Struct((obj), EVP_MD_CTX, &ossl_digest_type, (ctx)); \ if (!(ctx)) { \ - ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \ } \ } while (0) -#define SafeGetDigest(obj, ctx) do { \ - OSSL_Check_Kind((obj), cDigest); \ - GetDigest((obj), (ctx)); \ -} while (0) /* * Classes */ -VALUE cDigest; -VALUE eDigestError; +static VALUE cDigest; +static VALUE eDigestError; +static ID id_md_holder; static VALUE ossl_digest_alloc(VALUE klass); @@ -38,39 +34,67 @@ ossl_digest_free(void *ctx) static const rb_data_type_t ossl_digest_type = { "OpenSSL/Digest", { - 0, ossl_digest_free, + 0, ossl_digest_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; +#ifdef OSSL_USE_PROVIDER +static void +ossl_evp_md_free(void *ptr) +{ + // This is safe to call against const EVP_MD * returned by + // EVP_get_digestbyname() + EVP_MD_free(ptr); +} + +static const rb_data_type_t ossl_evp_md_holder_type = { + "OpenSSL/EVP_MD", + { + .dfree = ossl_evp_md_free, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, +}; +#endif + /* * Public */ const EVP_MD * -GetDigestPtr(VALUE obj) +ossl_evp_md_fetch(VALUE obj, volatile VALUE *holder) { - const EVP_MD *md; - ASN1_OBJECT *oid = NULL; - - if (RB_TYPE_P(obj, T_STRING)) { - const char *name = StringValueCStr(obj); - - md = EVP_get_digestbyname(name); - if (!md) { - oid = OBJ_txt2obj(name, 0); - md = EVP_get_digestbyobj(oid); - ASN1_OBJECT_free(oid); - } - if(!md) - ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name); - } else { + *holder = Qnil; + if (rb_obj_is_kind_of(obj, cDigest)) { EVP_MD_CTX *ctx; - - SafeGetDigest(obj, ctx); - - md = EVP_MD_CTX_md(ctx); + GetDigest(obj, ctx); + EVP_MD *md = (EVP_MD *)EVP_MD_CTX_get0_md(ctx); +#ifdef OSSL_USE_PROVIDER + *holder = TypedData_Wrap_Struct(0, &ossl_evp_md_holder_type, NULL); + if (!EVP_MD_up_ref(md)) + ossl_raise(eDigestError, "EVP_MD_up_ref"); + RTYPEDDATA_DATA(*holder) = md; +#endif + return md; } + const char *name = StringValueCStr(obj); + EVP_MD *md = (EVP_MD *)EVP_get_digestbyname(name); + if (!md) { + ASN1_OBJECT *oid = OBJ_txt2obj(name, 0); + md = (EVP_MD *)EVP_get_digestbyobj(oid); + ASN1_OBJECT_free(oid); + } +#ifdef OSSL_USE_PROVIDER + if (!md) { + ossl_clear_error(); + *holder = TypedData_Wrap_Struct(0, &ossl_evp_md_holder_type, NULL); + md = EVP_MD_fetch(NULL, name, NULL); + RTYPEDDATA_DATA(*holder) = md; + } +#endif + if (!md) + ossl_raise(eDigestError, "unsupported digest algorithm: %"PRIsVALUE, + obj); return md; } @@ -80,11 +104,17 @@ ossl_digest_new(const EVP_MD *md) VALUE ret; EVP_MD_CTX *ctx; + // NOTE: This does not set id_md_holder because this function should + // only be called from ossl_engine.c, which will not use any + // reference-counted digests. ret = ossl_digest_alloc(cDigest); - GetDigest(ret, ctx); - if (EVP_DigestInit_ex(ctx, md, NULL) != 1) { - ossl_raise(eDigestError, "Digest initialization failed."); - } + ctx = EVP_MD_CTX_new(); + if (!ctx) + ossl_raise(eDigestError, "EVP_MD_CTX_new"); + RTYPEDDATA_DATA(ret) = ctx; + + if (!EVP_DigestInit_ex(ctx, md, NULL)) + ossl_raise(eDigestError, "Digest initialization failed"); return ret; } @@ -95,57 +125,56 @@ ossl_digest_new(const EVP_MD *md) static VALUE ossl_digest_alloc(VALUE klass) { - EVP_MD_CTX *ctx; - VALUE obj; - - ctx = EVP_MD_CTX_create(); - if (ctx == NULL) - ossl_raise(rb_eRuntimeError, "EVP_MD_CTX_create() failed"); - obj = TypedData_Wrap_Struct(klass, &ossl_digest_type, ctx); - - return obj; + return TypedData_Wrap_Struct(klass, &ossl_digest_type, 0); } -VALUE ossl_digest_update(VALUE, VALUE); +static VALUE ossl_digest_update(VALUE, VALUE); /* * call-seq: * Digest.new(string [, data]) -> Digest * - * Creates a Digest instance based on +string+, which is either the ln - * (long name) or sn (short name) of a supported digest algorithm. - * If +data+ (a +String+) is given, it is used as the initial input to the + * Creates a Digest instance based on _string_, which is either the ln + * (long name) or sn (short name) of a supported digest algorithm. A list of + * supported algorithms can be obtained by calling OpenSSL::Digest.digests. + * + * If _data_ (a String) is given, it is used as the initial input to the * Digest instance, i.e. - * digest = OpenSSL::Digest.new('sha256', 'digestdata') - * is equal to - * digest = OpenSSL::Digest.new('sha256') - * digest.update('digestdata') * - * === Example - * digest = OpenSSL::Digest.new('sha1') + * digest = OpenSSL::Digest.new('sha256', 'digestdata') * + * is equivalent to * + * digest = OpenSSL::Digest.new('sha256') + * digest.update('digestdata') */ static VALUE ossl_digest_initialize(int argc, VALUE *argv, VALUE self) { EVP_MD_CTX *ctx; const EVP_MD *md; - VALUE type, data; + VALUE type, data, md_holder; rb_scan_args(argc, argv, "11", &type, &data); - md = GetDigestPtr(type); + md = ossl_evp_md_fetch(type, &md_holder); if (!NIL_P(data)) StringValue(data); - GetDigest(self, ctx); - if (EVP_DigestInit_ex(ctx, md, NULL) != 1) { - ossl_raise(eDigestError, "Digest initialization failed."); + TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx); + if (!ctx) { + RTYPEDDATA_DATA(self) = ctx = EVP_MD_CTX_new(); + if (!ctx) + ossl_raise(eDigestError, "EVP_MD_CTX_new"); } + if (!EVP_DigestInit_ex(ctx, md, NULL)) + ossl_raise(eDigestError, "Digest initialization failed"); + rb_ivar_set(self, id_md_holder, md_holder); + if (!NIL_P(data)) return ossl_digest_update(self, data); return self; } +/* :nodoc: */ static VALUE ossl_digest_copy(VALUE self, VALUE other) { @@ -154,15 +183,46 @@ ossl_digest_copy(VALUE self, VALUE other) rb_check_frozen(self); if (self == other) return self; - GetDigest(self, ctx1); - SafeGetDigest(other, ctx2); + TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx1); + if (!ctx1) { + RTYPEDDATA_DATA(self) = ctx1 = EVP_MD_CTX_new(); + if (!ctx1) + ossl_raise(eDigestError, "EVP_MD_CTX_new"); + } + GetDigest(other, ctx2); if (!EVP_MD_CTX_copy(ctx1, ctx2)) { - ossl_raise(eDigestError, NULL); + ossl_raise(eDigestError, NULL); } return self; } +static void +add_digest_name_to_ary(const OBJ_NAME *name, void *arg) +{ + VALUE ary = (VALUE)arg; + rb_ary_push(ary, rb_str_new2(name->name)); +} + +/* + * call-seq: + * OpenSSL::Digest.digests -> array[string...] + * + * Returns the names of all available digests in an array. + */ +static VALUE +ossl_s_digests(VALUE self) +{ + VALUE ary; + + ary = rb_ary_new(); + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, + add_digest_name_to_ary, + (void*)ary); + + return ary; +} + /* * call-seq: * digest.reset -> self @@ -177,8 +237,8 @@ ossl_digest_reset(VALUE self) EVP_MD_CTX *ctx; GetDigest(self, ctx); - if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL) != 1) { - ossl_raise(eDigestError, "Digest initialization failed."); + if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_get0_md(ctx), NULL) != 1) { + ossl_raise(eDigestError, "Digest initialization failed."); } return self; @@ -193,20 +253,22 @@ ossl_digest_reset(VALUE self) * be passed individually to the Digest instance. * * === Example - * digest = OpenSSL::Digest::SHA256.new + * digest = OpenSSL::Digest.new('SHA256') * digest.update('First input') * digest << 'Second input' # equivalent to digest.update('Second input') * result = digest.digest * */ -VALUE +static VALUE ossl_digest_update(VALUE self, VALUE data) { EVP_MD_CTX *ctx; StringValue(data); GetDigest(self, ctx); - EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)); + + if (!EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data))) + ossl_raise(eDigestError, "EVP_DigestUpdate"); return self; } @@ -217,23 +279,15 @@ ossl_digest_update(VALUE self, VALUE data) * */ static VALUE -ossl_digest_finish(int argc, VALUE *argv, VALUE self) +ossl_digest_finish(VALUE self) { EVP_MD_CTX *ctx; VALUE str; - rb_scan_args(argc, argv, "01", &str); - GetDigest(self, ctx); - - if (NIL_P(str)) { - str = rb_str_new(NULL, EVP_MD_CTX_size(ctx)); - } else { - StringValue(str); - rb_str_resize(str, EVP_MD_CTX_size(ctx)); - } - - EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL); + str = rb_str_new(NULL, EVP_MD_CTX_size(ctx)); + if (!EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL)) + ossl_raise(eDigestError, "EVP_DigestFinal_ex"); return str; } @@ -242,10 +296,11 @@ ossl_digest_finish(int argc, VALUE *argv, VALUE self) * call-seq: * digest.name -> string * - * Returns the sn of this Digest instance. + * Returns the short name of this Digest algorithm which may differ slightly + * from the original name provided. * * === Example - * digest = OpenSSL::Digest::SHA512.new + * digest = OpenSSL::Digest.new('SHA512') * puts digest.name # => SHA512 * */ @@ -256,7 +311,7 @@ ossl_digest_name(VALUE self) GetDigest(self, ctx); - return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx))); + return rb_str_new_cstr(EVP_MD_name(EVP_MD_CTX_get0_md(ctx))); } /* @@ -267,7 +322,7 @@ ossl_digest_name(VALUE self) * final message digest result. * * === Example - * digest = OpenSSL::Digest::SHA1.new + * digest = OpenSSL::Digest.new('SHA1') * puts digest.digest_length # => 20 * */ @@ -291,7 +346,7 @@ ossl_digest_size(VALUE self) * consecutively. * * === Example - * digest = OpenSSL::Digest::SHA1.new + * digest = OpenSSL::Digest.new('SHA1') * puts digest.block_length # => 64 */ static VALUE @@ -310,12 +365,6 @@ ossl_digest_block_length(VALUE self) void Init_ossl_digest(void) { - rb_require("digest"); - -#if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ -#endif - /* Document-class: OpenSSL::Digest * * OpenSSL::Digest allows you to compute message digests (sometimes @@ -344,54 +393,19 @@ Init_ossl_digest(void) * the integrity of a signed document, it suffices to re-compute the hash * and verify that it is equal to that in the signature. * - * Among the supported message digest algorithms are: - * * SHA, SHA1, SHA224, SHA256, SHA384 and SHA512 - * * MD2, MD4, MDC2 and MD5 - * * RIPEMD160 - * * DSS, DSS1 (Pseudo algorithms to be used for DSA signatures. DSS is - * equal to SHA and DSS1 is equal to SHA1) + * You can get a list of all digest algorithms supported on your system by + * running this command in your terminal: * - * For each of these algorithms, there is a sub-class of Digest that - * can be instantiated as simply as e.g. + * openssl list -digest-algorithms * - * digest = OpenSSL::Digest::SHA1.new + * Among the OpenSSL 1.1.1 supported message digest algorithms are: + * * SHA224, SHA256, SHA384, SHA512, SHA512-224 and SHA512-256 + * * SHA3-224, SHA3-256, SHA3-384 and SHA3-512 + * * BLAKE2s256 and BLAKE2b512 * - * === Mapping between Digest class and sn/ln + * Each of these algorithms can be instantiated using the name: * - * The sn (short names) and ln (long names) are defined in - * <openssl/object.h> and <openssl/obj_mac.h>. They are textual - * representations of ASN.1 OBJECT IDENTIFIERs. Each supported digest - * algorithm has an OBJECT IDENTIFIER associated to it and those again - * have short/long names assigned to them. - * E.g. the OBJECT IDENTIFIER for SHA-1 is 1.3.14.3.2.26 and its - * sn is "SHA1" and its ln is "sha1". - * ==== MD2 - * * sn: MD2 - * * ln: md2 - * ==== MD4 - * * sn: MD4 - * * ln: md4 - * ==== MD5 - * * sn: MD5 - * * ln: md5 - * ==== SHA - * * sn: SHA - * * ln: SHA - * ==== SHA-1 - * * sn: SHA1 - * * ln: sha1 - * ==== SHA-224 - * * sn: SHA224 - * * ln: sha224 - * ==== SHA-256 - * * sn: SHA256 - * * ln: sha256 - * ==== SHA-384 - * * sn: SHA384 - * * ln: sha384 - * ==== SHA-512 - * * sn: SHA512 - * * ln: sha512 + * digest = OpenSSL::Digest.new('SHA256') * * "Breaking" a message digest algorithm means defying its one-way * function characteristics, i.e. producing a collision or finding a way @@ -403,16 +417,16 @@ Init_ossl_digest(void) * * === Hashing a file * - * data = File.read('document') - * sha256 = OpenSSL::Digest::SHA256.new + * data = File.binread('document') + * sha256 = OpenSSL::Digest.new('SHA256') * digest = sha256.digest(data) * * === Hashing several pieces of data at once * - * data1 = File.read('file1') - * data2 = File.read('file2') - * data3 = File.read('file3') - * sha256 = OpenSSL::Digest::SHA256.new + * data1 = File.binread('file1') + * data2 = File.binread('file2') + * data3 = File.binread('file3') + * sha256 = OpenSSL::Digest.new('SHA256') * sha256 << data1 * sha256 << data2 * sha256 << data3 @@ -420,15 +434,21 @@ Init_ossl_digest(void) * * === Reuse a Digest instance * - * data1 = File.read('file1') - * sha256 = OpenSSL::Digest::SHA256.new + * data1 = File.binread('file1') + * sha256 = OpenSSL::Digest.new('SHA256') * digest1 = sha256.digest(data1) * - * data2 = File.read('file2') + * data2 = File.binread('file2') * sha256.reset * digest2 = sha256.digest(data2) * */ + + /* + * Digest::Class is defined by the digest library. rb_require() cannot be + * used here because it bypasses RubyGems. + */ + rb_funcall(Qnil, rb_intern_const("require"), 1, rb_str_new_cstr("digest")); cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class")); /* Document-class: OpenSSL::Digest::DigestError * @@ -439,14 +459,17 @@ Init_ossl_digest(void) rb_define_alloc_func(cDigest, ossl_digest_alloc); + rb_define_module_function(cDigest, "digests", ossl_s_digests, 0); rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1); - rb_define_copy_func(cDigest, ossl_digest_copy); + rb_define_method(cDigest, "initialize_copy", ossl_digest_copy, 1); rb_define_method(cDigest, "reset", ossl_digest_reset, 0); rb_define_method(cDigest, "update", ossl_digest_update, 1); rb_define_alias(cDigest, "<<", "update"); - rb_define_private_method(cDigest, "finish", ossl_digest_finish, -1); + rb_define_private_method(cDigest, "finish", ossl_digest_finish, 0); rb_define_method(cDigest, "digest_length", ossl_digest_size, 0); rb_define_method(cDigest, "block_length", ossl_digest_block_length, 0); rb_define_method(cDigest, "name", ossl_digest_name, 0); + + id_md_holder = rb_intern_const("EVP_MD_holder"); } diff --git a/ext/openssl/ossl_digest.h b/ext/openssl/ossl_digest.h index 8cc5b1bc56..9c3bb2b149 100644 --- a/ext/openssl/ossl_digest.h +++ b/ext/openssl/ossl_digest.h @@ -1,22 +1,25 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(_OSSL_DIGEST_H_) #define _OSSL_DIGEST_H_ -extern VALUE cDigest; -extern VALUE eDigestError; - -const EVP_MD *GetDigestPtr(VALUE); +/* + * Gets EVP_MD from a String or an OpenSSL::Digest instance (discouraged, but + * still supported for compatibility). A holder object is created if the EVP_MD + * is a "fetched" algorithm. + */ +const EVP_MD *ossl_evp_md_fetch(VALUE obj, volatile VALUE *holder); +/* + * This is meant for OpenSSL::Engine#digest. EVP_MD must not be a fetched one. + */ VALUE ossl_digest_new(const EVP_MD *); void Init_ossl_digest(void); #endif /* _OSSL_DIGEST_H_ */ - diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c index 04b5879bbc..a2bcb07ea4 100644 --- a/ext/openssl/ossl_engine.c +++ b/ext/openssl/ossl_engine.c @@ -1,22 +1,24 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#if defined(OSSL_ENGINE_ENABLED) +#ifdef OSSL_USE_ENGINE +# include <openssl/engine.h> -#define WrapEngine(klass, obj, engine) do { \ +#define NewEngine(klass) \ + TypedData_Wrap_Struct((klass), &ossl_engine_type, 0) +#define SetEngine(obj, engine) do { \ if (!(engine)) { \ - ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \ + ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \ } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_engine_type, (engine)); \ + RTYPEDDATA_DATA(obj) = (engine); \ } while(0) #define GetEngine(obj, engine) do { \ TypedData_Get_Struct((obj), ENGINE, &ossl_engine_type, (engine)); \ @@ -24,10 +26,6 @@ ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \ } \ } while (0) -#define SafeGetEngine(obj, engine) do { \ - OSSL_Check_Kind((obj), cEngine); \ - GetPKCS7((obj), (engine)); \ -} while (0) /* * Classes @@ -39,22 +37,24 @@ * * See also, https://www.openssl.org/docs/crypto/engine.html */ -VALUE cEngine; +static VALUE cEngine; /* Document-class: OpenSSL::Engine::EngineError * * This is the generic exception for OpenSSL::Engine related errors */ -VALUE eEngineError; +static VALUE eEngineError; /* * Private */ -#define OSSL_ENGINE_LOAD_IF_MATCH(x) \ +#define OSSL_ENGINE_LOAD_IF_MATCH(engine_name, x) \ do{\ - if(!strcmp(#x, RSTRING_PTR(name))){\ - ENGINE_load_##x();\ - return Qtrue;\ - }\ + if(!strcmp(#engine_name, RSTRING_PTR(name))){\ + if (OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_##x, NULL))\ + return Qtrue;\ + else\ + ossl_raise(eEngineError, "OPENSSL_init_crypto"); \ + }\ }while(0) static void @@ -66,28 +66,24 @@ ossl_engine_free(void *engine) static const rb_data_type_t ossl_engine_type = { "OpenSSL/Engine", { - 0, ossl_engine_free, + 0, ossl_engine_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; -/* Document-method: OpenSSL::Engine.load - * +/* * call-seq: - * load(enginename = nil) + * OpenSSL::Engine.load(name = nil) * - * This method loads engines. If +name+ is nil, then all builtin engines are - * loaded. Otherwise, the given +name+, as a string, is loaded if available to - * your runtime, and returns true. If +name+ is not found, then nil is + * This method loads engines. If _name_ is nil, then all builtin engines are + * loaded. Otherwise, the given _name_, as a String, is loaded if available to + * your runtime, and returns true. If _name_ is not found, then nil is * returned. * */ static VALUE ossl_engine_s_load(int argc, VALUE *argv, VALUE klass) { -#if !defined(HAVE_ENGINE_LOAD_BUILTIN_ENGINES) - return Qnil; -#else VALUE name; rb_scan_args(argc, argv, "01", &name); @@ -95,82 +91,34 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass) ENGINE_load_builtin_engines(); return Qtrue; } - StringValue(name); -#ifndef OPENSSL_NO_STATIC_ENGINE -#if HAVE_ENGINE_LOAD_DYNAMIC - OSSL_ENGINE_LOAD_IF_MATCH(dynamic); -#endif -#if HAVE_ENGINE_LOAD_4758CCA - OSSL_ENGINE_LOAD_IF_MATCH(4758cca); -#endif -#if HAVE_ENGINE_LOAD_AEP - OSSL_ENGINE_LOAD_IF_MATCH(aep); -#endif -#if HAVE_ENGINE_LOAD_ATALLA - OSSL_ENGINE_LOAD_IF_MATCH(atalla); -#endif -#if HAVE_ENGINE_LOAD_CHIL - OSSL_ENGINE_LOAD_IF_MATCH(chil); -#endif -#if HAVE_ENGINE_LOAD_CSWIFT - OSSL_ENGINE_LOAD_IF_MATCH(cswift); -#endif -#if HAVE_ENGINE_LOAD_NURON - OSSL_ENGINE_LOAD_IF_MATCH(nuron); -#endif -#if HAVE_ENGINE_LOAD_SUREWARE - OSSL_ENGINE_LOAD_IF_MATCH(sureware); -#endif -#if HAVE_ENGINE_LOAD_UBSEC - OSSL_ENGINE_LOAD_IF_MATCH(ubsec); -#endif -#if HAVE_ENGINE_LOAD_PADLOCK - OSSL_ENGINE_LOAD_IF_MATCH(padlock); -#endif -#if HAVE_ENGINE_LOAD_CAPI - OSSL_ENGINE_LOAD_IF_MATCH(capi); -#endif -#if HAVE_ENGINE_LOAD_GMP - OSSL_ENGINE_LOAD_IF_MATCH(gmp); -#endif -#if HAVE_ENGINE_LOAD_GOST - OSSL_ENGINE_LOAD_IF_MATCH(gost); -#endif -#if HAVE_ENGINE_LOAD_CRYPTODEV - OSSL_ENGINE_LOAD_IF_MATCH(cryptodev); -#endif -#if HAVE_ENGINE_LOAD_AESNI - OSSL_ENGINE_LOAD_IF_MATCH(aesni); -#endif -#endif -#ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO - OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto); -#endif - OSSL_ENGINE_LOAD_IF_MATCH(openssl); - rb_warning("no such builtin loader for `%s'", RSTRING_PTR(name)); + StringValueCStr(name); + OSSL_ENGINE_LOAD_IF_MATCH(dynamic, DYNAMIC); + OSSL_ENGINE_LOAD_IF_MATCH(padlock, PADLOCK); + OSSL_ENGINE_LOAD_IF_MATCH(capi, CAPI); + OSSL_ENGINE_LOAD_IF_MATCH(cryptodev, CRYPTODEV); + OSSL_ENGINE_LOAD_IF_MATCH(openssl, OPENSSL); + rb_warning("no such builtin loader for `%"PRIsVALUE"'", name); return Qnil; -#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ } -/* Document-method: OpenSSL::Engine.cleanup +/* * call-seq: - * OpenSSL::Engine.cleanup + * OpenSSL::Engine.cleanup * * It is only necessary to run cleanup when engines are loaded via * OpenSSL::Engine.load. However, running cleanup before exit is recommended. * - * See also, https://www.openssl.org/docs/crypto/engine.html + * Note that this is needed and works only in OpenSSL < 1.1.0. */ static VALUE ossl_engine_s_cleanup(VALUE self) { -#if defined(HAVE_ENGINE_CLEANUP) - ENGINE_cleanup(); -#endif return Qnil; } -/* Document-method: OpenSSL::Engine.engines +/* + * call-seq: + * OpenSSL::Engine.engines -> [engine, ...] * * Returns an array of currently loaded engines. */ @@ -182,28 +130,28 @@ ossl_engine_s_engines(VALUE klass) ary = rb_ary_new(); for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)){ - /* Need a ref count of two here because of ENGINE_free being - * called internally by OpenSSL when moving to the next ENGINE - * and by us when releasing the ENGINE reference */ - ENGINE_up_ref(e); - WrapEngine(klass, obj, e); + obj = NewEngine(klass); + /* Need a ref count of two here because of ENGINE_free being + * called internally by OpenSSL when moving to the next ENGINE + * and by us when releasing the ENGINE reference */ + ENGINE_up_ref(e); + SetEngine(obj, e); rb_ary_push(ary, obj); } return ary; } -/* Document-method: OpenSSL::Engine.by_id - * +/* * call-seq: - * by_id(name) -> engine + * OpenSSL::Engine.by_id(name) -> engine * - * Fetch the engine as specified by the +id+ String + * Fetches the engine as specified by the _id_ String. * * OpenSSL::Engine.by_id("openssl") * => #<OpenSSL::Engine id="openssl" name="Software engine support"> * - * See OpenSSL::Engine.engines for the currently loaded engines + * See OpenSSL::Engine.engines for the currently loaded engines. */ static VALUE ossl_engine_s_by_id(VALUE klass, VALUE id) @@ -211,43 +159,32 @@ ossl_engine_s_by_id(VALUE klass, VALUE id) ENGINE *e; VALUE obj; - StringValue(id); + StringValueCStr(id); ossl_engine_s_load(1, &id, klass); + obj = NewEngine(klass); if(!(e = ENGINE_by_id(RSTRING_PTR(id)))) - ossl_raise(eEngineError, NULL); - WrapEngine(klass, obj, e); + ossl_raise(eEngineError, NULL); + SetEngine(obj, e); if(rb_block_given_p()) rb_yield(obj); if(!ENGINE_init(e)) - ossl_raise(eEngineError, NULL); + ossl_raise(eEngineError, NULL); ENGINE_ctrl(e, ENGINE_CTRL_SET_PASSWORD_CALLBACK, - 0, NULL, (void(*)(void))ossl_pem_passwd_cb); - ERR_clear_error(); - - return obj; -} - -static VALUE -ossl_engine_s_alloc(VALUE klass) -{ - ENGINE *e; - VALUE obj; - - if (!(e = ENGINE_new())) { - ossl_raise(eEngineError, NULL); - } - WrapEngine(klass, obj, e); + 0, NULL, (void(*)(void))ossl_pem_passwd_cb); + ossl_clear_error(); return obj; } -/* Document-method: OpenSSL::Engine#id +/* + * call-seq: + * engine.id -> string * - * Get the id for this engine + * Gets the id for this engine. * * OpenSSL::Engine.load * OpenSSL::Engine.engines #=> [#<OpenSSL::Engine#>, ...] * OpenSSL::Engine.engines.first.id - * #=> "rsax" + * #=> "rsax" */ static VALUE ossl_engine_get_id(VALUE self) @@ -257,14 +194,16 @@ ossl_engine_get_id(VALUE self) return rb_str_new2(ENGINE_get_id(e)); } -/* Document-method: OpenSSL::Engine#name +/* + * call-seq: + * engine.name -> string * - * Get the descriptive name for this engine + * Get the descriptive name for this engine. * * OpenSSL::Engine.load * OpenSSL::Engine.engines #=> [#<OpenSSL::Engine#>, ...] * OpenSSL::Engine.engines.first.name - * #=> "RSAX engine support" + * #=> "RSAX engine support" * */ static VALUE @@ -275,7 +214,9 @@ ossl_engine_get_name(VALUE self) return rb_str_new2(ENGINE_get_name(e)); } -/* Document-method: OpenSSL::Engine#finish +/* + * call-seq: + * engine.finish -> nil * * Releases all internal structural references for this engine. * @@ -292,16 +233,14 @@ ossl_engine_finish(VALUE self) return Qnil; } -#if defined(HAVE_ENGINE_GET_CIPHER) -/* Document-method: OpenSSL::Engine#cipher - * +/* * call-seq: * engine.cipher(name) -> OpenSSL::Cipher * - * This returns an OpenSSL::Cipher by +name+, if it is available in this - * engine. + * Returns a new instance of OpenSSL::Cipher by _name_, if it is available in + * this engine. * - * A EngineError will be raised if the cipher is unavailable. + * An EngineError will be raised if the cipher is unavailable. * * e = OpenSSL::Engine.by_id("openssl") * => #<OpenSSL::Engine id="openssl" name="Software engine support"> @@ -314,12 +253,10 @@ ossl_engine_get_cipher(VALUE self, VALUE name) { ENGINE *e; const EVP_CIPHER *ciph, *tmp; - char *s; int nid; - s = StringValuePtr(name); - tmp = EVP_get_cipherbyname(s); - if(!tmp) ossl_raise(eEngineError, "no such cipher `%s'", s); + tmp = EVP_get_cipherbyname(StringValueCStr(name)); + if(!tmp) ossl_raise(eEngineError, "no such cipher `%"PRIsVALUE"'", name); nid = EVP_CIPHER_nid(tmp); GetEngine(self, e); ciph = ENGINE_get_cipher(e, nid); @@ -327,38 +264,31 @@ ossl_engine_get_cipher(VALUE self, VALUE name) return ossl_cipher_new(ciph); } -#else -#define ossl_engine_get_cipher rb_f_notimplement -#endif -#if defined(HAVE_ENGINE_GET_DIGEST) -/* Document-method: OpenSSL::Engine#digest - * +/* * call-seq: * engine.digest(name) -> OpenSSL::Digest * - * This returns an OpenSSL::Digest by +name+. + * Returns a new instance of OpenSSL::Digest by _name_. * * Will raise an EngineError if the digest is unavailable. * * e = OpenSSL::Engine.by_id("openssl") - * #=> #<OpenSSL::Engine id="openssl" name="Software engine support"> + * #=> #<OpenSSL::Engine id="openssl" name="Software engine support"> * e.digest("SHA1") - * #=> #<OpenSSL::Digest: da39a3ee5e6b4b0d3255bfef95601890afd80709> + * #=> #<OpenSSL::Digest: da39a3ee5e6b4b0d3255bfef95601890afd80709> * e.digest("zomg") - * #=> OpenSSL::Engine::EngineError: no such digest `zomg' + * #=> OpenSSL::Engine::EngineError: no such digest `zomg' */ static VALUE ossl_engine_get_digest(VALUE self, VALUE name) { ENGINE *e; const EVP_MD *md, *tmp; - char *s; int nid; - s = StringValuePtr(name); - tmp = EVP_get_digestbyname(s); - if(!tmp) ossl_raise(eEngineError, "no such digest `%s'", s); + tmp = EVP_get_digestbyname(StringValueCStr(name)); + if(!tmp) ossl_raise(eEngineError, "no such digest `%"PRIsVALUE"'", name); nid = EVP_MD_nid(tmp); GetEngine(self, e); md = ENGINE_get_digest(e, nid); @@ -366,16 +296,12 @@ ossl_engine_get_digest(VALUE self, VALUE name) return ossl_digest_new(md); } -#else -#define ossl_engine_get_digest rb_f_notimplement -#endif -/* Document-method: OpenSSL::Engine#load_private_key - * +/* * call-seq: * engine.load_private_key(id = nil, data = nil) -> OpenSSL::PKey * - * Loads the given private key by +id+ and +data+. + * Loads the given private key identified by _id_ and _data_. * * An EngineError is raised of the OpenSSL::PKey is unavailable. * @@ -389,27 +315,22 @@ ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self) char *sid, *sdata; rb_scan_args(argc, argv, "02", &id, &data); - sid = NIL_P(id) ? NULL : StringValuePtr(id); - sdata = NIL_P(data) ? NULL : StringValuePtr(data); + sid = NIL_P(id) ? NULL : StringValueCStr(id); + sdata = NIL_P(data) ? NULL : StringValueCStr(data); GetEngine(self, e); -#if OPENSSL_VERSION_NUMBER < 0x00907000L - pkey = ENGINE_load_private_key(e, sid, sdata); -#else pkey = ENGINE_load_private_key(e, sid, NULL, sdata); -#endif if (!pkey) ossl_raise(eEngineError, NULL); - obj = ossl_pkey_new(pkey); + obj = ossl_pkey_wrap(pkey); OSSL_PKEY_SET_PRIVATE(obj); return obj; } -/* Document-method: OpenSSL::Engine#load_public_key - * +/* * call-seq: * engine.load_public_key(id = nil, data = nil) -> OpenSSL::PKey * - * Loads the given private key by +id+ and +data+. + * Loads the given public key identified by _id_ and _data_. * * An EngineError is raised of the OpenSSL::PKey is unavailable. * @@ -423,33 +344,28 @@ ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self) char *sid, *sdata; rb_scan_args(argc, argv, "02", &id, &data); - sid = NIL_P(id) ? NULL : StringValuePtr(id); - sdata = NIL_P(data) ? NULL : StringValuePtr(data); + sid = NIL_P(id) ? NULL : StringValueCStr(id); + sdata = NIL_P(data) ? NULL : StringValueCStr(data); GetEngine(self, e); -#if OPENSSL_VERSION_NUMBER < 0x00907000L - pkey = ENGINE_load_public_key(e, sid, sdata); -#else pkey = ENGINE_load_public_key(e, sid, NULL, sdata); -#endif if (!pkey) ossl_raise(eEngineError, NULL); - return ossl_pkey_new(pkey); + return ossl_pkey_wrap(pkey); } -/* Document-method: OpenSSL::Engine#set_default - * +/* * call-seq: * engine.set_default(flag) * - * Set the defaults for this engine with the given +flag+. + * Set the defaults for this engine with the given _flag_. * * These flags are used to control combinations of algorithm methods. * - * +flag+ can be one of the following, other flags are available depending on + * _flag_ can be one of the following, other flags are available depending on * your OS. * * [All flags] 0xFFFF - * [No flags] 0x0000 + * [No flags] 0x0000 * * See also <openssl/engine.h> */ @@ -465,14 +381,13 @@ ossl_engine_set_default(VALUE self, VALUE flag) return Qtrue; } -/* Document-method: OpenSSL::Engine#ctrl_cmd - * +/* * call-seq: * engine.ctrl_cmd(command, value = nil) -> engine * - * Send the given +command+ to this engine. + * Sends the given _command_ to this engine. * - * Raises an EngineError if the +command+ fails. + * Raises an EngineError if the command fails. */ static VALUE ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self) @@ -483,10 +398,8 @@ ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self) GetEngine(self, e); rb_scan_args(argc, argv, "11", &cmd, &val); - StringValue(cmd); - if (!NIL_P(val)) StringValue(val); - ret = ENGINE_ctrl_cmd_string(e, RSTRING_PTR(cmd), - NIL_P(val) ? NULL : RSTRING_PTR(val), 0); + ret = ENGINE_ctrl_cmd_string(e, StringValueCStr(cmd), + NIL_P(val) ? NULL : StringValueCStr(val), 0); if (!ret) ossl_raise(eEngineError, NULL); return self; @@ -496,15 +409,17 @@ static VALUE ossl_engine_cmd_flag_to_name(int flag) { switch(flag){ - case ENGINE_CMD_FLAG_NUMERIC: return rb_str_new2("NUMERIC"); - case ENGINE_CMD_FLAG_STRING: return rb_str_new2("STRING"); - case ENGINE_CMD_FLAG_NO_INPUT: return rb_str_new2("NO_INPUT"); - case ENGINE_CMD_FLAG_INTERNAL: return rb_str_new2("INTERNAL"); - default: return rb_str_new2("UNKNOWN"); + case ENGINE_CMD_FLAG_NUMERIC: return rb_str_new2("NUMERIC"); + case ENGINE_CMD_FLAG_STRING: return rb_str_new2("STRING"); + case ENGINE_CMD_FLAG_NO_INPUT: return rb_str_new2("NO_INPUT"); + case ENGINE_CMD_FLAG_INTERNAL: return rb_str_new2("INTERNAL"); + default: return rb_str_new2("UNKNOWN"); } } -/* Document-method: OpenSSL::Engine#cmds +/* + * call-seq: + * engine.cmds -> [["name", "description", "flags"], ...] * * Returns an array of command definitions for the current engine */ @@ -518,21 +433,23 @@ ossl_engine_get_cmds(VALUE self) GetEngine(self, e); ary = rb_ary_new(); if ((defn = ENGINE_get_cmd_defns(e)) != NULL){ - for (p = defn; p->cmd_num > 0; p++){ - tmp = rb_ary_new(); - rb_ary_push(tmp, rb_str_new2(p->cmd_name)); - rb_ary_push(tmp, rb_str_new2(p->cmd_desc)); - rb_ary_push(tmp, ossl_engine_cmd_flag_to_name(p->cmd_flags)); - rb_ary_push(ary, tmp); - } + for (p = defn; p->cmd_num > 0; p++){ + tmp = rb_ary_new(); + rb_ary_push(tmp, rb_str_new2(p->cmd_name)); + rb_ary_push(tmp, rb_str_new2(p->cmd_desc)); + rb_ary_push(tmp, ossl_engine_cmd_flag_to_name(p->cmd_flags)); + rb_ary_push(ary, tmp); + } } return ary; } -/* Document-method: OpenSSL::Engine#inspect +/* + * call-seq: + * engine.inspect -> string * - * Pretty print this engine + * Pretty prints this engine. */ static VALUE ossl_engine_inspect(VALUE self) @@ -541,7 +458,7 @@ ossl_engine_inspect(VALUE self) GetEngine(self, e); return rb_sprintf("#<%"PRIsVALUE" id=\"%s\" name=\"%s\">", - rb_obj_class(self), ENGINE_get_id(e), ENGINE_get_name(e)); + rb_obj_class(self), ENGINE_get_id(e), ENGINE_get_name(e)); } #define DefEngineConst(x) rb_define_const(cEngine, #x, INT2NUM(ENGINE_##x)) @@ -552,12 +469,11 @@ Init_ossl_engine(void) cEngine = rb_define_class_under(mOSSL, "Engine", rb_cObject); eEngineError = rb_define_class_under(cEngine, "EngineError", eOSSLError); - rb_define_alloc_func(cEngine, ossl_engine_s_alloc); + rb_undef_alloc_func(cEngine); rb_define_singleton_method(cEngine, "load", ossl_engine_s_load, -1); rb_define_singleton_method(cEngine, "cleanup", ossl_engine_s_cleanup, 0); rb_define_singleton_method(cEngine, "engines", ossl_engine_s_engines, 0); rb_define_singleton_method(cEngine, "by_id", ossl_engine_s_by_id, 1); - rb_undef_method(CLASS_OF(cEngine), "new"); rb_define_method(cEngine, "id", ossl_engine_get_id, 0); rb_define_method(cEngine, "name", ossl_engine_get_name, 0); @@ -575,18 +491,8 @@ Init_ossl_engine(void) DefEngineConst(METHOD_DSA); DefEngineConst(METHOD_DH); DefEngineConst(METHOD_RAND); -#ifdef ENGINE_METHOD_BN_MOD_EXP - DefEngineConst(METHOD_BN_MOD_EXP); -#endif -#ifdef ENGINE_METHOD_BN_MOD_EXP_CRT - DefEngineConst(METHOD_BN_MOD_EXP_CRT); -#endif -#ifdef ENGINE_METHOD_CIPHERS DefEngineConst(METHOD_CIPHERS); -#endif -#ifdef ENGINE_METHOD_DIGESTS DefEngineConst(METHOD_DIGESTS); -#endif DefEngineConst(METHOD_ALL); DefEngineConst(METHOD_NONE); } diff --git a/ext/openssl/ossl_engine.h b/ext/openssl/ossl_engine.h index ea2f256912..cedcebb772 100644 --- a/ext/openssl/ossl_engine.h +++ b/ext/openssl/ossl_engine.h @@ -1,20 +1,16 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz> * Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(OSSL_ENGINE_H) #define OSSL_ENGINE_H -extern VALUE cEngine; -extern VALUE eEngineError; - void Init_ossl_engine(void); #endif /* OSSL_ENGINE_H */ diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c index 74fc962b2a..ddcc6a5f8d 100644 --- a/ext/openssl/ossl_hmac.c +++ b/ext/openssl/ossl_hmac.c @@ -1,35 +1,29 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ -#if !defined(OPENSSL_NO_HMAC) - #include "ossl.h" -#define MakeHMAC(obj, klass, ctx) \ - (obj) = TypedData_Make_Struct((klass), HMAC_CTX, &ossl_hmac_type, (ctx)) +#define NewHMAC(klass) \ + TypedData_Wrap_Struct((klass), &ossl_hmac_type, 0) #define GetHMAC(obj, ctx) do { \ - TypedData_Get_Struct((obj), HMAC_CTX, &ossl_hmac_type, (ctx)); \ + TypedData_Get_Struct((obj), EVP_MD_CTX, &ossl_hmac_type, (ctx)); \ if (!(ctx)) { \ - ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \ + ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \ } \ } while (0) -#define SafeGetHMAC(obj, ctx) do { \ - OSSL_Check_Kind((obj), cHMAC); \ - GetHMAC((obj), (ctx)); \ -} while (0) /* * Classes */ -VALUE cHMAC; -VALUE eHMACError; +static VALUE cHMAC; +static VALUE eHMACError; +static ID id_md_holder; /* * Public @@ -41,26 +35,28 @@ VALUE eHMACError; static void ossl_hmac_free(void *ctx) { - HMAC_CTX_cleanup(ctx); - ruby_xfree(ctx); + EVP_MD_CTX_free(ctx); } static const rb_data_type_t ossl_hmac_type = { "OpenSSL/HMAC", { - 0, ossl_hmac_free, + 0, ossl_hmac_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; static VALUE ossl_hmac_alloc(VALUE klass) { - HMAC_CTX *ctx; VALUE obj; + EVP_MD_CTX *ctx; - MakeHMAC(obj, klass, ctx); - HMAC_CTX_init(ctx); + obj = NewHMAC(klass); + ctx = EVP_MD_CTX_new(); + if (!ctx) + ossl_raise(eHMACError, "EVP_MD_CTX"); + RTYPEDDATA_DATA(obj) = ctx; return obj; } @@ -78,54 +74,62 @@ ossl_hmac_alloc(VALUE klass) * * === Example * - * key = 'key' - * digest = OpenSSL::Digest.new('sha1') - * instance = OpenSSL::HMAC.new(key, digest) - * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f - * instance.class - * #=> OpenSSL::HMAC + * key = 'key' + * instance = OpenSSL::HMAC.new(key, 'SHA1') + * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f + * instance.class + * #=> OpenSSL::HMAC * * === A note about comparisons * - * Two instances won't be equal when they're compared, even if they have the - * same value. Use #to_s or #hexdigest to return the authentication code that - * the instance represents. For example: + * Two instances can be securely compared with #== in constant time: * - * other_instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1')) - * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f - * instance - * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f - * instance == other_instance - * #=> false - * instance.to_s == other_instance.to_s - * #=> true + * other_instance = OpenSSL::HMAC.new('key', 'SHA1') + * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f + * instance == other_instance + * #=> true * */ static VALUE ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest) { - HMAC_CTX *ctx; + EVP_MD_CTX *ctx; + EVP_PKEY *pkey; + const EVP_MD *md; + VALUE md_holder; - StringValue(key); GetHMAC(self, ctx); - HMAC_Init(ctx, RSTRING_PTR(key), RSTRING_LENINT(key), - GetDigestPtr(digest)); + StringValue(key); + md = ossl_evp_md_fetch(digest, &md_holder); + pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, + (unsigned char *)RSTRING_PTR(key), + RSTRING_LENINT(key)); + if (!pkey) + ossl_raise(eHMACError, "EVP_PKEY_new_raw_private_key"); + if (EVP_DigestSignInit(ctx, NULL, md, NULL, pkey) != 1) { + EVP_PKEY_free(pkey); + ossl_raise(eHMACError, "EVP_DigestSignInit"); + } + rb_ivar_set(self, id_md_holder, md_holder); + /* Decrement reference counter; EVP_MD_CTX still keeps it */ + EVP_PKEY_free(pkey); return self; } +/* :nodoc: */ static VALUE ossl_hmac_copy(VALUE self, VALUE other) { - HMAC_CTX *ctx1, *ctx2; + EVP_MD_CTX *ctx1, *ctx2; rb_check_frozen(self); if (self == other) return self; GetHMAC(self, ctx1); - SafeGetHMAC(other, ctx2); - - HMAC_CTX_copy(ctx1, ctx2); + GetHMAC(other, ctx2); + if (EVP_MD_CTX_copy(ctx1, ctx2) != 1) + ossl_raise(eHMACError, "EVP_MD_CTX_copy"); return self; } @@ -133,47 +137,33 @@ ossl_hmac_copy(VALUE self, VALUE other) * call-seq: * hmac.update(string) -> self * - * Returns +self+ updated with the message to be authenticated. + * Returns _hmac_ updated with the message to be authenticated. * Can be called repeatedly with chunks of the message. * * === Example * - * first_chunk = 'The quick brown fox jumps ' - * second_chunk = 'over the lazy dog' + * first_chunk = 'The quick brown fox jumps ' + * second_chunk = 'over the lazy dog' * - * instance.update(first_chunk) - * #=> 5b9a8038a65d571076d97fe783989e52278a492a - * instance.update(second_chunk) - * #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9 + * instance.update(first_chunk) + * #=> 5b9a8038a65d571076d97fe783989e52278a492a + * instance.update(second_chunk) + * #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9 * */ static VALUE ossl_hmac_update(VALUE self, VALUE data) { - HMAC_CTX *ctx; + EVP_MD_CTX *ctx; StringValue(data); GetHMAC(self, ctx); - HMAC_Update(ctx, (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data)); + if (EVP_DigestSignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1) + ossl_raise(eHMACError, "EVP_DigestSignUpdate"); return self; } -static void -hmac_final(HMAC_CTX *ctx, unsigned char **buf, unsigned int *buf_len) -{ - HMAC_CTX final; - - HMAC_CTX_copy(&final, ctx); - if (!(*buf = OPENSSL_malloc(HMAC_size(&final)))) { - HMAC_CTX_cleanup(&final); - OSSL_Debug("Allocating %d mem", HMAC_size(&final)); - ossl_raise(eHMACError, "Cannot allocate memory for hmac"); - } - HMAC_Final(&final, *buf, buf_len); - HMAC_CTX_cleanup(&final); -} - /* * call-seq: * hmac.digest -> string @@ -181,26 +171,26 @@ hmac_final(HMAC_CTX *ctx, unsigned char **buf, unsigned int *buf_len) * Returns the authentication code an instance represents as a binary string. * * === Example - * - * instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1')) - * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f - * instance.digest - * #=> "\xF4+\xB0\xEE\xB0\x18\xEB\xBDE\x97\xAEr\x13q\x1E\xC6\a`\x84?" - * + * instance = OpenSSL::HMAC.new('key', 'SHA1') + * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f + * instance.digest + * #=> "\xF4+\xB0\xEE\xB0\x18\xEB\xBDE\x97\xAEr\x13q\x1E\xC6\a`\x84?" */ static VALUE ossl_hmac_digest(VALUE self) { - HMAC_CTX *ctx; - unsigned char *buf; - unsigned int buf_len; - VALUE digest; + EVP_MD_CTX *ctx; + size_t buf_len = EVP_MAX_MD_SIZE; + VALUE ret; GetHMAC(self, ctx); - hmac_final(ctx, &buf, &buf_len); - digest = ossl_buf2str((char *)buf, buf_len); + ret = rb_str_new(NULL, EVP_MAX_MD_SIZE); + if (EVP_DigestSignFinal(ctx, (unsigned char *)RSTRING_PTR(ret), + &buf_len) != 1) + ossl_raise(eHMACError, "EVP_DigestSignFinal"); + rb_str_set_len(ret, (long)buf_len); - return digest; + return ret; } /* @@ -209,149 +199,98 @@ ossl_hmac_digest(VALUE self) * * Returns the authentication code an instance represents as a hex-encoded * string. - * */ static VALUE ossl_hmac_hexdigest(VALUE self) { - HMAC_CTX *ctx; - unsigned char *buf; - char *hexbuf; - unsigned int buf_len; - VALUE hexdigest; + EVP_MD_CTX *ctx; + unsigned char buf[EVP_MAX_MD_SIZE]; + size_t buf_len = EVP_MAX_MD_SIZE; + VALUE ret; GetHMAC(self, ctx); - hmac_final(ctx, &buf, &buf_len); - if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * (int)buf_len) { - OPENSSL_free(buf); - ossl_raise(eHMACError, "Memory alloc error"); - } - OPENSSL_free(buf); - hexdigest = ossl_buf2str(hexbuf, 2 * buf_len); + if (EVP_DigestSignFinal(ctx, buf, &buf_len) != 1) + ossl_raise(eHMACError, "EVP_DigestSignFinal"); + ret = rb_str_new(NULL, buf_len * 2); + ossl_bin2hex(buf, RSTRING_PTR(ret), buf_len); - return hexdigest; + return ret; } /* * call-seq: * hmac.reset -> self * - * Returns +self+ as it was when it was first initialized, with all processed + * Returns _hmac_ as it was when it was first initialized, with all processed * data cleared from it. * * === Example * - * data = "The quick brown fox jumps over the lazy dog" - * instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1')) - * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f + * data = "The quick brown fox jumps over the lazy dog" + * instance = OpenSSL::HMAC.new('key', 'SHA1') + * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f * - * instance.update(data) - * #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9 - * instance.reset - * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f + * instance.update(data) + * #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9 + * instance.reset + * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f * */ static VALUE ossl_hmac_reset(VALUE self) { - HMAC_CTX *ctx; + EVP_MD_CTX *ctx; + EVP_PKEY *pkey; GetHMAC(self, ctx); - HMAC_Init(ctx, NULL, 0, NULL); + pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx)); + if (EVP_DigestSignInit(ctx, NULL, EVP_MD_CTX_get0_md(ctx), NULL, pkey) != 1) + ossl_raise(eHMACError, "EVP_DigestSignInit"); return self; } /* - * call-seq: - * HMAC.digest(digest, key, data) -> aString - * - * Returns the authentication code as a binary string. The +digest+ parameter - * must be an instance of OpenSSL::Digest. - * - * === Example - * - * key = 'key' - * data = 'The quick brown fox jumps over the lazy dog' - * digest = OpenSSL::Digest.new('sha1') - * - * hmac = OpenSSL::HMAC.digest(digest, key, data) - * #=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9" - * - */ -static VALUE -ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data) -{ - unsigned char *buf; - unsigned int buf_len; - - StringValue(key); - StringValue(data); - buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LENINT(key), - (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len); - - return rb_str_new((const char *)buf, buf_len); -} - -/* - * call-seq: - * HMAC.hexdigest(digest, key, data) -> aString - * - * Returns the authentication code as a hex-encoded string. The +digest+ - * parameter must be an instance of OpenSSL::Digest. - * - * === Example - * - * key = 'key' - * data = 'The quick brown fox jumps over the lazy dog' - * digest = OpenSSL::Digest.new('sha1') - * - * hmac = OpenSSL::HMAC.hexdigest(digest, key, data) - * #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9" - * - */ -static VALUE -ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data) -{ - unsigned char *buf; - char *hexbuf; - unsigned int buf_len; - VALUE hexdigest; - - StringValue(key); - StringValue(data); - - buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LENINT(key), - (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len); - if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * (int)buf_len) { - ossl_raise(eHMACError, "Cannot convert buf to hexbuf"); - } - hexdigest = ossl_buf2str(hexbuf, 2 * buf_len); - - return hexdigest; -} - -/* * INIT */ void Init_ossl_hmac(void) { -#if 0 - /* :nodoc: */ - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ -#endif - + /* + * Document-class: OpenSSL::HMAC + * + * OpenSSL::HMAC allows computing Hash-based Message Authentication Code + * (HMAC). It is a type of message authentication code (MAC) involving a + * hash function in combination with a key. HMAC can be used to verify the + * integrity of a message as well as the authenticity. + * + * OpenSSL::HMAC has a similar interface to OpenSSL::Digest. + * + * === HMAC-SHA256 using one-shot interface + * + * key = "key" + * data = "message-to-be-authenticated" + * mac = OpenSSL::HMAC.hexdigest("SHA256", key, data) + * #=> "cddb0db23f469c8bf072b21fd837149bd6ace9ab771cceef14c9e517cc93282e" + * + * === HMAC-SHA256 using incremental interface + * + * data1 = File.binread("file1") + * data2 = File.binread("file2") + * key = "key" + * hmac = OpenSSL::HMAC.new(key, 'SHA256') + * hmac << data1 + * hmac << data2 + * mac = hmac.digest + */ eHMACError = rb_define_class_under(mOSSL, "HMACError", eOSSLError); cHMAC = rb_define_class_under(mOSSL, "HMAC", rb_cObject); rb_define_alloc_func(cHMAC, ossl_hmac_alloc); - rb_define_singleton_method(cHMAC, "digest", ossl_hmac_s_digest, 3); - rb_define_singleton_method(cHMAC, "hexdigest", ossl_hmac_s_hexdigest, 3); rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2); - rb_define_copy_func(cHMAC, ossl_hmac_copy); + rb_define_method(cHMAC, "initialize_copy", ossl_hmac_copy, 1); rb_define_method(cHMAC, "reset", ossl_hmac_reset, 0); rb_define_method(cHMAC, "update", ossl_hmac_update, 1); @@ -360,13 +299,6 @@ Init_ossl_hmac(void) rb_define_method(cHMAC, "hexdigest", ossl_hmac_hexdigest, 0); rb_define_alias(cHMAC, "inspect", "hexdigest"); rb_define_alias(cHMAC, "to_s", "hexdigest"); -} -#else /* NO_HMAC */ -# warning >>> OpenSSL is compiled without HMAC support <<< -void -Init_ossl_hmac(void) -{ - rb_warning("HMAC is not available: OpenSSL is compiled without HMAC."); + id_md_holder = rb_intern_const("EVP_MD_holder"); } -#endif /* NO_HMAC */ diff --git a/ext/openssl/ossl_hmac.h b/ext/openssl/ossl_hmac.h index 1a2978b39a..e5bed37c9f 100644 --- a/ext/openssl/ossl_hmac.h +++ b/ext/openssl/ossl_hmac.h @@ -1,19 +1,15 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(_OSSL_HMAC_H_) #define _OSSL_HMAC_H_ -extern VALUE cHMAC; -extern VALUE eHMACError; - void Init_ossl_hmac(void); #endif /* _OSSL_HMAC_H_ */ diff --git a/ext/openssl/ossl_kdf.c b/ext/openssl/ossl_kdf.c new file mode 100644 index 0000000000..1f28016440 --- /dev/null +++ b/ext/openssl/ossl_kdf.c @@ -0,0 +1,300 @@ +/* + * Ruby/OpenSSL Project + * Copyright (C) 2007, 2017 Ruby/OpenSSL Project Authors + */ +#include "ossl.h" +#include <openssl/kdf.h> + +static VALUE mKDF, eKDF; + +/* + * call-seq: + * KDF.pbkdf2_hmac(pass, salt:, iterations:, length:, hash:) -> aString + * + * PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in combination + * with HMAC. Takes _pass_, _salt_ and _iterations_, and then derives a key + * of _length_ bytes. + * + * For more information about PBKDF2, see RFC 2898 Section 5.2 + * (https://www.rfc-editor.org/rfc/rfc2898#section-5.2). + * + * === Parameters + * pass :: The password. + * salt :: The salt. Salts prevent attacks based on dictionaries of common + * passwords and attacks based on rainbow tables. It is a public + * value that can be safely stored along with the password (e.g. + * if the derived value is used for password storage). + * iterations :: The iteration count. This provides the ability to tune the + * algorithm. It is better to use the highest count possible for + * the maximum resistance to brute-force attacks. + * length :: The desired length of the derived key in octets. + * hash :: The hash algorithm used with HMAC for the PRF. May be a String + * representing the algorithm name, or an instance of + * OpenSSL::Digest. + */ +static VALUE +kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self) +{ + VALUE pass, salt, opts, kwargs[4], str, md_holder; + static ID kwargs_ids[4]; + int iters, len; + const EVP_MD *md; + + if (!kwargs_ids[0]) { + kwargs_ids[0] = rb_intern_const("salt"); + kwargs_ids[1] = rb_intern_const("iterations"); + kwargs_ids[2] = rb_intern_const("length"); + kwargs_ids[3] = rb_intern_const("hash"); + } + rb_scan_args(argc, argv, "1:", &pass, &opts); + rb_get_kwargs(opts, kwargs_ids, 4, 0, kwargs); + + StringValue(pass); + salt = StringValue(kwargs[0]); + iters = NUM2INT(kwargs[1]); + len = NUM2INT(kwargs[2]); + md = ossl_evp_md_fetch(kwargs[3], &md_holder); + + str = rb_str_new(0, len); + if (!PKCS5_PBKDF2_HMAC(RSTRING_PTR(pass), RSTRING_LENINT(pass), + (unsigned char *)RSTRING_PTR(salt), + RSTRING_LENINT(salt), iters, md, len, + (unsigned char *)RSTRING_PTR(str))) + ossl_raise(eKDF, "PKCS5_PBKDF2_HMAC"); + + return str; +} + +#if defined(HAVE_EVP_PBE_SCRYPT) +/* + * call-seq: + * KDF.scrypt(pass, salt:, N:, r:, p:, length:) -> aString + * + * Derives a key from _pass_ using given parameters with the scrypt + * password-based key derivation function. The result can be used for password + * storage. + * + * scrypt is designed to be memory-hard and more secure against brute-force + * attacks using custom hardwares than alternative KDFs such as PBKDF2 or + * bcrypt. + * + * The keyword arguments _N_, _r_ and _p_ can be used to tune scrypt. RFC 7914 + * (published on 2016-08, https://www.rfc-editor.org/rfc/rfc7914#section-2) states + * that using values r=8 and p=1 appears to yield good results. + * + * See RFC 7914 (https://www.rfc-editor.org/rfc/rfc7914) for more information. + * + * === Parameters + * pass :: Passphrase. + * salt :: Salt. + * N :: CPU/memory cost parameter. This must be a power of 2. + * r :: Block size parameter. + * p :: Parallelization parameter. + * length :: Length in octets of the derived key. + * + * === Example + * pass = "password" + * salt = SecureRandom.random_bytes(16) + * dk = OpenSSL::KDF.scrypt(pass, salt: salt, N: 2**14, r: 8, p: 1, length: 32) + * p dk #=> "\xDA\xE4\xE2...\x7F\xA1\x01T" + */ +static VALUE +kdf_scrypt(int argc, VALUE *argv, VALUE self) +{ + VALUE pass, salt, opts, kwargs[5], str; + static ID kwargs_ids[5]; + size_t len; + uint64_t N, r, p, maxmem; + + if (!kwargs_ids[0]) { + kwargs_ids[0] = rb_intern_const("salt"); + kwargs_ids[1] = rb_intern_const("N"); + kwargs_ids[2] = rb_intern_const("r"); + kwargs_ids[3] = rb_intern_const("p"); + kwargs_ids[4] = rb_intern_const("length"); + } + rb_scan_args(argc, argv, "1:", &pass, &opts); + rb_get_kwargs(opts, kwargs_ids, 5, 0, kwargs); + + StringValue(pass); + salt = StringValue(kwargs[0]); + N = NUM2UINT64T(kwargs[1]); + r = NUM2UINT64T(kwargs[2]); + p = NUM2UINT64T(kwargs[3]); + len = NUM2LONG(kwargs[4]); + /* + * OpenSSL uses 32MB by default (if zero is specified), which is too small. + * Let's not limit memory consumption but just let malloc() fail inside + * OpenSSL. The amount is controllable by other parameters. + */ + maxmem = SIZE_MAX; + + str = rb_str_new(0, len); + if (!EVP_PBE_scrypt(RSTRING_PTR(pass), RSTRING_LEN(pass), + (unsigned char *)RSTRING_PTR(salt), RSTRING_LEN(salt), + N, r, p, maxmem, (unsigned char *)RSTRING_PTR(str), len)) + ossl_raise(eKDF, "EVP_PBE_scrypt"); + + return str; +} +#endif + +/* + * call-seq: + * KDF.hkdf(ikm, salt:, info:, length:, hash:) -> String + * + * HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as specified in + * {RFC 5869}[https://www.rfc-editor.org/rfc/rfc5869]. + * + * New in OpenSSL 1.1.0. + * + * === Parameters + * _ikm_:: + * The input keying material. + * _salt_:: + * The salt. + * _info_:: + * The context and application specific information. + * _length_:: + * The output length in octets. Must be <= <tt>255 * HashLen</tt>, where + * HashLen is the length of the hash function output in octets. + * _hash_:: + * The hash function. + * + * === Example + * # The values from https://www.rfc-editor.org/rfc/rfc5869#appendix-A.1 + * ikm = ["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*") + * salt = ["000102030405060708090a0b0c"].pack("H*") + * info = ["f0f1f2f3f4f5f6f7f8f9"].pack("H*") + * p OpenSSL::KDF.hkdf(ikm, salt: salt, info: info, length: 42, hash: "SHA256").unpack1("H*") + * # => "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865" + */ +static VALUE +kdf_hkdf(int argc, VALUE *argv, VALUE self) +{ + VALUE ikm, salt, info, opts, kwargs[4], str, md_holder; + static ID kwargs_ids[4]; + int saltlen, ikmlen, infolen; + size_t len; + const EVP_MD *md; + EVP_PKEY_CTX *pctx; + + if (!kwargs_ids[0]) { + kwargs_ids[0] = rb_intern_const("salt"); + kwargs_ids[1] = rb_intern_const("info"); + kwargs_ids[2] = rb_intern_const("length"); + kwargs_ids[3] = rb_intern_const("hash"); + } + rb_scan_args(argc, argv, "1:", &ikm, &opts); + rb_get_kwargs(opts, kwargs_ids, 4, 0, kwargs); + + StringValue(ikm); + ikmlen = RSTRING_LENINT(ikm); + salt = StringValue(kwargs[0]); + saltlen = RSTRING_LENINT(salt); + info = StringValue(kwargs[1]); + infolen = RSTRING_LENINT(info); + len = (size_t)NUM2LONG(kwargs[2]); + if (len > LONG_MAX) + rb_raise(rb_eArgError, "length must be non-negative"); + md = ossl_evp_md_fetch(kwargs[3], &md_holder); + + str = rb_str_new(NULL, (long)len); + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); + if (!pctx) + ossl_raise(eKDF, "EVP_PKEY_CTX_new_id"); + if (EVP_PKEY_derive_init(pctx) <= 0) { + EVP_PKEY_CTX_free(pctx); + ossl_raise(eKDF, "EVP_PKEY_derive_init"); + } + if (EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0) { + EVP_PKEY_CTX_free(pctx); + ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_md"); + } + if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, (unsigned char *)RSTRING_PTR(salt), + saltlen) <= 0) { + EVP_PKEY_CTX_free(pctx); + ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_salt"); + } + if (EVP_PKEY_CTX_set1_hkdf_key(pctx, (unsigned char *)RSTRING_PTR(ikm), + ikmlen) <= 0) { + EVP_PKEY_CTX_free(pctx); + ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_key"); + } + if (EVP_PKEY_CTX_add1_hkdf_info(pctx, (unsigned char *)RSTRING_PTR(info), + infolen) <= 0) { + EVP_PKEY_CTX_free(pctx); + ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_info"); + } + if (EVP_PKEY_derive(pctx, (unsigned char *)RSTRING_PTR(str), &len) <= 0) { + EVP_PKEY_CTX_free(pctx); + ossl_raise(eKDF, "EVP_PKEY_derive"); + } + rb_str_set_len(str, (long)len); + EVP_PKEY_CTX_free(pctx); + + return str; +} + +void +Init_ossl_kdf(void) +{ + /* + * Document-module: OpenSSL::KDF + * + * Provides functionality of various KDFs (key derivation function). + * + * KDF is typically used for securely deriving arbitrary length symmetric + * keys to be used with an OpenSSL::Cipher from passwords. Another use case + * is for storing passwords: Due to the ability to tweak the effort of + * computation by increasing the iteration count, computation can be slowed + * down artificially in order to render possible attacks infeasible. + * + * Currently, OpenSSL::KDF provides implementations for the following KDF: + * + * * PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in + * combination with HMAC + * * scrypt + * * HKDF + * + * == Examples + * === Generating a 128 bit key for a Cipher (e.g. AES) + * pass = "secret" + * salt = OpenSSL::Random.random_bytes(16) + * iter = 20_000 + * key_len = 16 + * key = OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter, + * length: key_len, hash: "sha1") + * + * === Storing Passwords + * pass = "secret" + * # store this with the generated value + * salt = OpenSSL::Random.random_bytes(16) + * iter = 20_000 + * hash = OpenSSL::Digest.new('SHA256') + * len = hash.digest_length + * # the final value to be stored + * value = OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter, + * length: len, hash: hash) + * + * == Important Note on Checking Passwords + * When comparing passwords provided by the user with previously stored + * values, a common mistake made is comparing the two values using "==". + * Typically, "==" short-circuits on evaluation, and is therefore + * vulnerable to timing attacks. The proper way is to use a method that + * always takes the same amount of time when comparing two values, thus + * not leaking any information to potential attackers. To do this, use + * +OpenSSL.fixed_length_secure_compare+. + */ + mKDF = rb_define_module_under(mOSSL, "KDF"); + /* + * Generic exception class raised if an error occurs in OpenSSL::KDF module. + */ + eKDF = rb_define_class_under(mKDF, "KDFError", eOSSLError); + + rb_define_module_function(mKDF, "pbkdf2_hmac", kdf_pbkdf2_hmac, -1); +#if defined(HAVE_EVP_PBE_SCRYPT) + rb_define_module_function(mKDF, "scrypt", kdf_scrypt, -1); +#endif + rb_define_module_function(mKDF, "hkdf", kdf_hkdf, -1); +} diff --git a/ext/openssl/ossl_kdf.h b/ext/openssl/ossl_kdf.h new file mode 100644 index 0000000000..b6503f8d9d --- /dev/null +++ b/ext/openssl/ossl_kdf.h @@ -0,0 +1,6 @@ +#if !defined(OSSL_KDF_H) +#define OSSL_KDF_H + +void Init_ossl_kdf(void); + +#endif diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c index d2a52e6f05..8440c2ee82 100644 --- a/ext/openssl/ossl_ns_spki.c +++ b/ext/openssl/ossl_ns_spki.c @@ -1,34 +1,35 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#define WrapSPKI(klass, obj, spki) do { \ +#define NewSPKI(klass) \ + TypedData_Wrap_Struct((klass), &ossl_netscape_spki_type, 0) +#define SetSPKI(obj, spki) do { \ if (!(spki)) { \ - ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \ } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_netscape_spki_type, (spki)); \ + RTYPEDDATA_DATA(obj) = (spki); \ } while (0) #define GetSPKI(obj, spki) do { \ TypedData_Get_Struct((obj), NETSCAPE_SPKI, &ossl_netscape_spki_type, (spki)); \ if (!(spki)) { \ - ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \ } \ } while (0) /* * Classes */ -VALUE mNetscape; -VALUE cSPKI; -VALUE eSPKIError; +static VALUE mNetscape; +static VALUE cSPKI; +static VALUE eSPKIError; /* * Public functions @@ -47,9 +48,9 @@ ossl_netscape_spki_free(void *spki) static const rb_data_type_t ossl_netscape_spki_type = { "OpenSSL/NETSCAPE_SPKI", { - 0, ossl_netscape_spki_free, + 0, ossl_netscape_spki_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; static VALUE @@ -58,10 +59,11 @@ ossl_spki_alloc(VALUE klass) NETSCAPE_SPKI *spki; VALUE obj; + obj = NewSPKI(klass); if (!(spki = NETSCAPE_SPKI_new())) { - ossl_raise(eSPKIError, NULL); + ossl_raise(eSPKIError, NULL); } - WrapSPKI(klass, obj, spki); + SetSPKI(obj, spki); return obj; } @@ -71,7 +73,7 @@ ossl_spki_alloc(VALUE klass) * SPKI.new([request]) => spki * * === Parameters - * * +request+ - optional raw request, either in PEM or DER format. + * * _request_ - optional raw request, either in PEM or DER format. */ static VALUE ossl_spki_initialize(int argc, VALUE *argv, VALUE self) @@ -81,18 +83,18 @@ ossl_spki_initialize(int argc, VALUE *argv, VALUE self) const unsigned char *p; if (rb_scan_args(argc, argv, "01", &buffer) == 0) { - return self; + return self; } StringValue(buffer); - if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING_PTR(buffer), -1))) { - p = (unsigned char *)RSTRING_PTR(buffer); - if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING_LEN(buffer)))) { - ossl_raise(eSPKIError, NULL); - } + if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING_PTR(buffer), RSTRING_LENINT(buffer)))) { + ossl_clear_error(); + p = (unsigned char *)RSTRING_PTR(buffer); + if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING_LEN(buffer)))) { + ossl_raise(eSPKIError, NULL); + } } NETSCAPE_SPKI_free(DATA_PTR(self)); - DATA_PTR(self) = spki; - ERR_clear_error(); + SetSPKI(self, spki); return self; } @@ -113,11 +115,11 @@ ossl_spki_to_der(VALUE self) GetSPKI(self, spki); if ((len = i2d_NETSCAPE_SPKI(spki, NULL)) <= 0) - ossl_raise(eX509CertError, NULL); + ossl_raise(eSPKIError, "i2d_NETSCAPE_SPKI"); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); if (i2d_NETSCAPE_SPKI(spki, &p) <= 0) - ossl_raise(eX509CertError, NULL); + ossl_raise(eSPKIError, "i2d_NETSCAPE_SPKI"); ossl_str_adjust(str, p); return str; @@ -138,7 +140,7 @@ ossl_spki_to_pem(VALUE self) GetSPKI(self, spki); if (!(data = NETSCAPE_SPKI_b64_encode(spki))) { - ossl_raise(eSPKIError, NULL); + ossl_raise(eSPKIError, NULL); } str = ossl_buf2str(data, rb_long2int(strlen(data))); @@ -157,22 +159,17 @@ ossl_spki_print(VALUE self) { NETSCAPE_SPKI *spki; BIO *out; - BUF_MEM *buf; - VALUE str; GetSPKI(self, spki); if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eSPKIError, NULL); + ossl_raise(eSPKIError, NULL); } if (!NETSCAPE_SPKI_print(out, spki)) { - BIO_free(out); - ossl_raise(eSPKIError, NULL); + BIO_free(out); + ossl_raise(eSPKIError, NULL); } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); - return str; + return ossl_membio2str(out); } /* @@ -190,10 +187,10 @@ ossl_spki_get_public_key(VALUE self) GetSPKI(self, spki); if (!(pkey = NETSCAPE_SPKI_get_pubkey(spki))) { /* adds an reference */ - ossl_raise(eSPKIError, NULL); + ossl_raise(eSPKIError, NULL); } - return ossl_pkey_new(pkey); /* NO DUP - OK */ + return ossl_pkey_wrap(pkey); } /* @@ -201,7 +198,7 @@ ossl_spki_get_public_key(VALUE self) * spki.public_key = pub => pkey * * === Parameters - * * +pub+ - the public key to be set for this instance + * * _pub_ - the public key to be set for this instance * * Sets the public key to be associated with the SPKI, an instance of * OpenSSL::PKey. This should be the public key corresponding to the @@ -211,12 +208,13 @@ static VALUE ossl_spki_set_public_key(VALUE self, VALUE key) { NETSCAPE_SPKI *spki; + EVP_PKEY *pkey; GetSPKI(self, spki); - if (!NETSCAPE_SPKI_set_pubkey(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */ - ossl_raise(eSPKIError, NULL); - } - + pkey = GetPKeyPtr(key); + ossl_pkey_check_public_key(pkey); + if (!NETSCAPE_SPKI_set_pubkey(spki, pkey)) + ossl_raise(eSPKIError, "NETSCAPE_SPKI_set_pubkey"); return key; } @@ -232,13 +230,12 @@ ossl_spki_get_challenge(VALUE self) NETSCAPE_SPKI *spki; GetSPKI(self, spki); - if (spki->spkac->challenge->length <= 0) { - OSSL_Debug("Challenge.length <= 0?"); - return rb_str_new(0, 0); + if (ASN1_STRING_length(spki->spkac->challenge) <= 0) { + OSSL_Debug("Challenge.length <= 0?"); + return rb_str_new(0, 0); } - return rb_str_new((const char *)spki->spkac->challenge->data, - spki->spkac->challenge->length); + return asn1str_to_str(spki->spkac->challenge); } /* @@ -246,7 +243,7 @@ ossl_spki_get_challenge(VALUE self) * spki.challenge = str => string * * === Parameters - * * +str+ - the challenge string to be set for this instance + * * _str_ - the challenge string to be set for this instance * * Sets the challenge to be associated with the SPKI. May be used by the * server, e.g. to prevent replay. @@ -259,8 +256,8 @@ ossl_spki_set_challenge(VALUE self, VALUE str) StringValue(str); GetSPKI(self, spki); if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING_PTR(str), - RSTRING_LENINT(str))) { - ossl_raise(eSPKIError, NULL); + RSTRING_LENINT(str))) { + ossl_raise(eSPKIError, NULL); } return str; @@ -271,8 +268,8 @@ ossl_spki_set_challenge(VALUE self, VALUE str) * spki.sign(key, digest) => spki * * === Parameters - * * +key+ - the private key to be used for signing this instance - * * +digest+ - the digest to be used for signing this instance + * * _key_ - the private key to be used for signing this instance + * * _digest_ - the digest to be used for signing this instance * * To sign an SPKI, the private key corresponding to the public key set * for this instance should be used, in addition to a digest algorithm in @@ -285,13 +282,13 @@ ossl_spki_sign(VALUE self, VALUE key, VALUE digest) NETSCAPE_SPKI *spki; EVP_PKEY *pkey; const EVP_MD *md; + VALUE md_holder; pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ - md = GetDigestPtr(digest); + md = ossl_evp_md_fetch(digest, &md_holder); GetSPKI(self, spki); - if (!NETSCAPE_SPKI_sign(spki, pkey, md)) { - ossl_raise(eSPKIError, NULL); - } + if (!NETSCAPE_SPKI_sign(spki, pkey, md)) + ossl_raise(eSPKIError, "NETSCAPE_SPKI_sign"); return self; } @@ -301,7 +298,7 @@ ossl_spki_sign(VALUE self, VALUE key, VALUE digest) * spki.verify(key) => boolean * * === Parameters - * * +key+ - the public key to be used for verifying the SPKI signature + * * _key_ - the public key to be used for verifying the SPKI signature * * Returns +true+ if the signature is valid, +false+ otherwise. To verify an * SPKI, the public key contained within the SPKI should be used. @@ -310,22 +307,25 @@ static VALUE ossl_spki_verify(VALUE self, VALUE key) { NETSCAPE_SPKI *spki; + EVP_PKEY *pkey; GetSPKI(self, spki); - switch (NETSCAPE_SPKI_verify(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */ - case 0: - return Qfalse; - case 1: - return Qtrue; - default: - ossl_raise(eSPKIError, NULL); + pkey = GetPKeyPtr(key); + ossl_pkey_check_public_key(pkey); + switch (NETSCAPE_SPKI_verify(spki, pkey)) { + case 0: + ossl_clear_error(); + return Qfalse; + case 1: + return Qtrue; + default: + ossl_raise(eSPKIError, "NETSCAPE_SPKI_verify"); } - return Qnil; /* dummy */ } /* Document-class: OpenSSL::Netscape::SPKI * - * A Simple Public Key Infrastructure implementation (pronounced "spookey"). + * A Simple Public Key Infrastructure implementation (pronounced "spooky"). * The structure is defined as * PublicKeyAndChallenge ::= SEQUENCE { * spki SubjectPublicKeyInfo, @@ -349,9 +349,9 @@ ossl_spki_verify(VALUE self, VALUE key) * spki = OpenSSL::Netscape::SPKI.new * spki.challenge = "RandomChallenge" * spki.public_key = key.public_key - * spki.sign(key, OpenSSL::Digest::SHA256.new) + * spki.sign(key, OpenSSL::Digest.new('SHA256')) * #send a request containing this to a server generating a certificate - * === Verifiying an SPKI request + * === Verifying an SPKI request * request = #... * spki = OpenSSL::Netscape::SPKI.new request * unless spki.verify(spki.public_key) @@ -364,8 +364,8 @@ ossl_spki_verify(VALUE self, VALUE key) * * OpenSSL::Netscape is a namespace for SPKI (Simple Public Key * Infrastructure) which implements Signed Public Key and Challenge. - * See {RFC 2692}[http://tools.ietf.org/html/rfc2692] and {RFC - * 2693}[http://tools.ietf.org/html/rfc2692] for details. + * See {RFC 2692}[https://www.rfc-editor.org/rfc/rfc2692] and {RFC + * 2693}[https://www.rfc-editor.org/rfc/rfc2692] for details. */ /* Document-class: OpenSSL::Netscape::SPKIError @@ -377,10 +377,6 @@ ossl_spki_verify(VALUE self, VALUE key) void Init_ossl_ns_spki(void) { -#if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ -#endif - mNetscape = rb_define_module_under(mOSSL, "Netscape"); eSPKIError = rb_define_class_under(mNetscape, "SPKIError", eOSSLError); @@ -401,4 +397,3 @@ Init_ossl_ns_spki(void) rb_define_method(cSPKI, "challenge", ossl_spki_get_challenge, 0); rb_define_method(cSPKI, "challenge=", ossl_spki_set_challenge, 1); } - diff --git a/ext/openssl/ossl_ns_spki.h b/ext/openssl/ossl_ns_spki.h index 9977035a9c..043b6cdb66 100644 --- a/ext/openssl/ossl_ns_spki.h +++ b/ext/openssl/ossl_ns_spki.h @@ -1,21 +1,15 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(_OSSL_NS_SPKI_H_) #define _OSSL_NS_SPKI_H_ -extern VALUE mNetscape; -extern VALUE cSPKI; -extern VALUE eSPKIError; - void Init_ossl_ns_spki(void); #endif /* _OSSL_NS_SPKI_H_ */ - diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c index dc31d79cf7..93d8bc8567 100644 --- a/ext/openssl/ossl_ocsp.c +++ b/ext/openssl/ossl_ocsp.c @@ -1,76 +1,79 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz> * Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#if defined(OSSL_OCSP_ENABLED) +#if !defined(OPENSSL_NO_OCSP) -#define WrapOCSPReq(klass, obj, req) do { \ +#define NewOCSPReq(klass) \ + TypedData_Wrap_Struct((klass), &ossl_ocsp_request_type, 0) +#define SetOCSPReq(obj, req) do { \ if(!(req)) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_ocsp_request_type, (req)); \ + RTYPEDDATA_DATA(obj) = (req); \ } while (0) #define GetOCSPReq(obj, req) do { \ TypedData_Get_Struct((obj), OCSP_REQUEST, &ossl_ocsp_request_type, (req)); \ if(!(req)) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \ } while (0) -#define SafeGetOCSPReq(obj, req) do { \ - OSSL_Check_Kind((obj), cOCSPReq); \ - GetOCSPReq((obj), (req)); \ -} while (0) -#define WrapOCSPRes(klass, obj, res) do { \ +#define NewOCSPRes(klass) \ + TypedData_Wrap_Struct((klass), &ossl_ocsp_response_type, 0) +#define SetOCSPRes(obj, res) do { \ if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_ocsp_response_type, (res)); \ + RTYPEDDATA_DATA(obj) = (res); \ } while (0) #define GetOCSPRes(obj, res) do { \ TypedData_Get_Struct((obj), OCSP_RESPONSE, &ossl_ocsp_response_type, (res)); \ if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \ } while (0) -#define SafeGetOCSPRes(obj, res) do { \ - OSSL_Check_Kind((obj), cOCSPRes); \ - GetOCSPRes((obj), (res)); \ -} while (0) -#define WrapOCSPBasicRes(klass, obj, res) do { \ +#define NewOCSPBasicRes(klass) \ + TypedData_Wrap_Struct((klass), &ossl_ocsp_basicresp_type, 0) +#define SetOCSPBasicRes(obj, res) do { \ if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_ocsp_basicresp_type, (res)); \ + RTYPEDDATA_DATA(obj) = (res); \ } while (0) #define GetOCSPBasicRes(obj, res) do { \ TypedData_Get_Struct((obj), OCSP_BASICRESP, &ossl_ocsp_basicresp_type, (res)); \ if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \ } while (0) -#define SafeGetOCSPBasicRes(obj, res) do { \ - OSSL_Check_Kind((obj), cOCSPBasicRes); \ - GetOCSPBasicRes((obj), (res)); \ + +#define NewOCSPSingleRes(klass) \ + TypedData_Wrap_Struct((klass), &ossl_ocsp_singleresp_type, 0) +#define SetOCSPSingleRes(obj, res) do { \ + if(!(res)) ossl_raise(rb_eRuntimeError, "SingleResponse wasn't initialized!"); \ + RTYPEDDATA_DATA(obj) = (res); \ +} while (0) +#define GetOCSPSingleRes(obj, res) do { \ + TypedData_Get_Struct((obj), OCSP_SINGLERESP, &ossl_ocsp_singleresp_type, (res)); \ + if(!(res)) ossl_raise(rb_eRuntimeError, "SingleResponse wasn't initialized!"); \ } while (0) -#define WrapOCSPCertId(klass, obj, cid) do { \ +#define NewOCSPCertId(klass) \ + TypedData_Wrap_Struct((klass), &ossl_ocsp_certid_type, 0) +#define SetOCSPCertId(obj, cid) do { \ if(!(cid)) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_ocsp_certid_type, (cid)); \ + RTYPEDDATA_DATA(obj) = (cid); \ } while (0) #define GetOCSPCertId(obj, cid) do { \ TypedData_Get_Struct((obj), OCSP_CERTID, &ossl_ocsp_certid_type, (cid)); \ if(!(cid)) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \ } while (0) -#define SafeGetOCSPCertId(obj, cid) do { \ - OSSL_Check_Kind((obj), cOCSPCertId); \ - GetOCSPCertId((obj), (cid)); \ -} while (0) -VALUE mOCSP; -VALUE eOCSPError; -VALUE cOCSPReq; -VALUE cOCSPRes; -VALUE cOCSPBasicRes; -VALUE cOCSPCertId; +static VALUE mOCSP; +static VALUE eOCSPError; +static VALUE cOCSPReq; +static VALUE cOCSPRes; +static VALUE cOCSPBasicRes; +static VALUE cOCSPSingleRes; +static VALUE cOCSPCertId; static void ossl_ocsp_request_free(void *ptr) @@ -81,9 +84,9 @@ ossl_ocsp_request_free(void *ptr) static const rb_data_type_t ossl_ocsp_request_type = { "OpenSSL/OCSP/REQUEST", { - 0, ossl_ocsp_request_free, + 0, ossl_ocsp_request_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; static void @@ -95,9 +98,9 @@ ossl_ocsp_response_free(void *ptr) static const rb_data_type_t ossl_ocsp_response_type = { "OpenSSL/OCSP/RESPONSE", { - 0, ossl_ocsp_response_free, + 0, ossl_ocsp_response_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; static void @@ -109,9 +112,23 @@ ossl_ocsp_basicresp_free(void *ptr) static const rb_data_type_t ossl_ocsp_basicresp_type = { "OpenSSL/OCSP/BASICRESP", { - 0, ossl_ocsp_basicresp_free, + 0, ossl_ocsp_basicresp_free, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, +}; + +static void +ossl_ocsp_singleresp_free(void *ptr) +{ + OCSP_SINGLERESP_free(ptr); +} + +static const rb_data_type_t ossl_ocsp_singleresp_type = { + "OpenSSL/OCSP/SINGLERESP", + { + 0, ossl_ocsp_singleresp_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; static void @@ -123,24 +140,28 @@ ossl_ocsp_certid_free(void *ptr) static const rb_data_type_t ossl_ocsp_certid_type = { "OpenSSL/OCSP/CERTID", { - 0, ossl_ocsp_certid_free, + 0, ossl_ocsp_certid_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; /* * Public */ static VALUE -ossl_ocspcertid_new(OCSP_CERTID *cid) +ossl_ocspcid_new(const OCSP_CERTID *cid) { - VALUE obj; - WrapOCSPCertId(cOCSPCertId, obj, cid); + VALUE obj = NewOCSPCertId(cOCSPCertId); + /* OpenSSL 1.1.1 takes a non-const pointer */ + OCSP_CERTID *cid_new = OCSP_CERTID_dup((OCSP_CERTID *)cid); + if (!cid_new) + ossl_raise(eOCSPError, "OCSP_CERTID_dup"); + SetOCSPCertId(obj, cid_new); return obj; } /* - * OCSP::Resquest + * OCSP::Request */ static VALUE ossl_ocspreq_alloc(VALUE klass) @@ -148,39 +169,61 @@ ossl_ocspreq_alloc(VALUE klass) OCSP_REQUEST *req; VALUE obj; + obj = NewOCSPReq(klass); if (!(req = OCSP_REQUEST_new())) - ossl_raise(eOCSPError, NULL); - WrapOCSPReq(klass, obj, req); + ossl_raise(eOCSPError, NULL); + SetOCSPReq(obj, req); return obj; } +/* :nodoc: */ +static VALUE +ossl_ocspreq_initialize_copy(VALUE self, VALUE other) +{ + OCSP_REQUEST *req, *req_old, *req_new; + + rb_check_frozen(self); + GetOCSPReq(self, req_old); + GetOCSPReq(other, req); + + req_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_REQUEST), req); + if (!req_new) + ossl_raise(eOCSPError, "ASN1_item_dup"); + + SetOCSPReq(self, req_new); + OCSP_REQUEST_free(req_old); + + return self; +} + /* * call-seq: * OpenSSL::OCSP::Request.new -> request * OpenSSL::OCSP::Request.new(request_der) -> request * * Creates a new OpenSSL::OCSP::Request. The request may be created empty or - * from a +request_der+ string. + * from a _request_der_ string. */ static VALUE ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self) { VALUE arg; + OCSP_REQUEST *req, *req_new; const unsigned char *p; rb_scan_args(argc, argv, "01", &arg); if(!NIL_P(arg)){ - OCSP_REQUEST *req = DATA_PTR(self), *x; - arg = ossl_to_der_if_possible(arg); - StringValue(arg); - p = (unsigned char*)RSTRING_PTR(arg); - x = d2i_OCSP_REQUEST(&req, &p, RSTRING_LEN(arg)); - DATA_PTR(self) = req; - if(!x){ - ossl_raise(eOCSPError, "cannot load DER encoded request"); - } + GetOCSPReq(self, req); + arg = ossl_to_der_if_possible(arg); + StringValue(arg); + p = (unsigned char *)RSTRING_PTR(arg); + req_new = d2i_OCSP_REQUEST(NULL, &p, RSTRING_LEN(arg)); + if (!req_new) + ossl_raise(eOCSPError, "d2i_OCSP_REQUEST"); + SetOCSPReq(self, req_new); + OCSP_REQUEST_free(req); } return self; @@ -190,7 +233,7 @@ ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self) * call-seq: * request.add_nonce(nonce = nil) -> request * - * Adds a +nonce+ to the OCSP request. If no nonce is given a random one will + * Adds a _nonce_ to the OCSP request. If no nonce is given a random one will * be generated. * * The nonce is used to prevent replay attacks but some servers do not support @@ -206,13 +249,13 @@ ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "01", &val); if(NIL_P(val)) { - GetOCSPReq(self, req); - ret = OCSP_request_add1_nonce(req, NULL, -1); + GetOCSPReq(self, req); + ret = OCSP_request_add1_nonce(req, NULL, -1); } else{ - StringValue(val); - GetOCSPReq(self, req); - ret = OCSP_request_add1_nonce(req, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val)); + StringValue(val); + GetOCSPReq(self, req); + ret = OCSP_request_add1_nonce(req, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val)); } if(!ret) ossl_raise(eOCSPError, NULL); @@ -223,7 +266,7 @@ ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self) * call-seq: * request.check_nonce(response) -> result * - * Checks the nonce validity for this request and +response+. + * Checks the nonce validity for this request and _response_. * * The return value is one of the following: * @@ -233,7 +276,7 @@ ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self) * 2 :: nonces both absent. * 3 :: nonce present in response only. * - * For most responses, clients can check +result+ > 0. If a responder doesn't + * For most responses, clients can check _result_ > 0. If a responder doesn't * handle nonces <code>result.nonzero?</code> may be necessary. A result of * <code>0</code> is always an error. */ @@ -246,7 +289,7 @@ ossl_ocspreq_check_nonce(VALUE self, VALUE basic_resp) int res; GetOCSPReq(self, req); - SafeGetOCSPBasicRes(basic_resp, bs); + GetOCSPBasicRes(basic_resp, bs); res = OCSP_check_nonce(req, bs); return INT2NUM(res); @@ -256,19 +299,24 @@ ossl_ocspreq_check_nonce(VALUE self, VALUE basic_resp) * call-seq: * request.add_certid(certificate_id) -> request * - * Adds +certificate_id+ to the request. + * Adds _certificate_id_ to the request. */ static VALUE ossl_ocspreq_add_certid(VALUE self, VALUE certid) { OCSP_REQUEST *req; - OCSP_CERTID *id; + OCSP_CERTID *id, *id_new; GetOCSPReq(self, req); GetOCSPCertId(certid, id); - if(!OCSP_request_add0_id(req, OCSP_CERTID_dup(id))) - ossl_raise(eOCSPError, NULL); + + if (!(id_new = OCSP_CERTID_dup(id))) + ossl_raise(eOCSPError, "OCSP_CERTID_dup"); + if (!OCSP_request_add0_id(req, id_new)) { + OCSP_CERTID_free(id_new); + ossl_raise(eOCSPError, "OCSP_request_add0_id"); + } return self; } @@ -284,20 +332,19 @@ static VALUE ossl_ocspreq_get_certid(VALUE self) { OCSP_REQUEST *req; - OCSP_ONEREQ *one; - OCSP_CERTID *id; - VALUE ary, tmp; - int i, count; GetOCSPReq(self, req); - count = OCSP_request_onereq_count(req); - ary = (count > 0) ? rb_ary_new() : Qnil; - for(i = 0; i < count; i++){ - one = OCSP_request_onereq_get0(req, i); - if(!(id = OCSP_CERTID_dup(OCSP_onereq_get0_id(one)))) - ossl_raise(eOCSPError, NULL); - WrapOCSPCertId(cOCSPCertId, tmp, id); - rb_ary_push(ary, tmp); + int count = OCSP_request_onereq_count(req); + if (count < 0) + ossl_raise(eOCSPError, "OCSP_request_onereq_count"); + if (count == 0) + return Qnil; + + VALUE ary = rb_ary_new_capa(count); + for (int i = 0; i < count; i++) { + OCSP_ONEREQ *one = OCSP_request_onereq_get0(req, i); + OCSP_CERTID *cid = OCSP_onereq_get0_id(one); + rb_ary_push(ary, ossl_ocspcid_new(cid)); } return ary; @@ -305,49 +352,62 @@ ossl_ocspreq_get_certid(VALUE self) /* * call-seq: - * request.sign(signer_cert, signer_key) -> self - * request.sign(signer_cert, signer_key, certificates) -> self - * request.sign(signer_cert, signer_key, certificates, flags) -> self + * request.sign(cert, key, certs = nil, flags = 0, digest = nil) -> self * - * Signs this OCSP request using +signer_cert+ and +signer_key+. - * +certificates+ is an optional Array of certificates that may be included in - * the request. + * Signs this OCSP request using _cert_, _key_ and optional _digest_. If + * _digest_ is not specified, SHA-1 is used. _certs_ is an optional Array of + * additional certificates which are included in the request in addition to + * the signer certificate. Note that if _certs_ is +nil+ or not given, flag + * OpenSSL::OCSP::NOCERTS is enabled. Pass an empty array to include only the + * signer certificate. + * + * _flags_ is a bitwise OR of the following constants: + * + * OpenSSL::OCSP::NOCERTS:: + * Don't include any certificates in the request. _certs_ will be ignored. */ - static VALUE ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self) { - VALUE signer_cert, signer_key, certs, flags; + VALUE signer_cert, signer_key, certs, flags, digest, md_holder; OCSP_REQUEST *req; X509 *signer; EVP_PKEY *key; - STACK_OF(X509) *x509s; - unsigned long flg; + STACK_OF(X509) *x509s = NULL; + unsigned long flg = 0; + const EVP_MD *md; int ret; - rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags); + rb_scan_args(argc, argv, "23", &signer_cert, &signer_key, &certs, &flags, &digest); + GetOCSPReq(self, req); signer = GetX509CertPtr(signer_cert); key = GetPrivPKeyPtr(signer_key); - flg = NIL_P(flags) ? 0 : NUM2INT(flags); - if(NIL_P(certs)){ - x509s = sk_X509_new_null(); - flags |= OCSP_NOCERTS; - } - else x509s = ossl_x509_ary2sk(certs); - GetOCSPReq(self, req); - ret = OCSP_request_sign(req, signer, key, EVP_sha1(), x509s, flg); + if (!NIL_P(flags)) + flg = NUM2INT(flags); + md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder); + if (NIL_P(certs)) + flg |= OCSP_NOCERTS; + else + x509s = ossl_x509_ary2sk(certs); + + ret = OCSP_request_sign(req, signer, key, md, x509s, flg); sk_X509_pop_free(x509s, X509_free); - if(!ret) ossl_raise(eOCSPError, NULL); + if (!ret) + ossl_raise(eOCSPError, "OCSP_request_sign"); return self; } /* * call-seq: - * request.verify(certificates, store) -> true or false - * request.verify(certificates, store, flags) -> true or false + * request.verify(certificates, store, flags = 0) -> true or false + * + * Verifies this request using the given _certificates_ and _store_. + * _certificates_ is an array of OpenSSL::X509::Certificate, _store_ is an + * OpenSSL::X509::Store. * - * Verifies this request using the given +certificates+ and X509 +store+. + * Note that +false+ is returned if the request does not have a signature. + * Use #signed? to check whether the request is signed or not. */ static VALUE @@ -360,15 +420,16 @@ ossl_ocspreq_verify(int argc, VALUE *argv, VALUE self) int flg, result; rb_scan_args(argc, argv, "21", &certs, &store, &flags); + GetOCSPReq(self, req); x509st = GetX509StorePtr(store); flg = NIL_P(flags) ? 0 : NUM2INT(flags); x509s = ossl_x509_ary2sk(certs); - GetOCSPReq(self, req); result = OCSP_request_verify(req, x509s, x509st, flg); sk_X509_pop_free(x509s, X509_free); - if(!result) rb_warn("%s", ERR_error_string(ERR_peek_error(), NULL)); + if (result <= 0) + ossl_clear_error(); - return result ? Qtrue : Qfalse; + return result > 0 ? Qtrue : Qfalse; } /* @@ -385,24 +446,40 @@ ossl_ocspreq_to_der(VALUE self) GetOCSPReq(self, req); if((len = i2d_OCSP_REQUEST(req, NULL)) <= 0) - ossl_raise(eOCSPError, NULL); + ossl_raise(eOCSPError, NULL); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); if(i2d_OCSP_REQUEST(req, &p) <= 0) - ossl_raise(eOCSPError, NULL); + ossl_raise(eOCSPError, NULL); ossl_str_adjust(str, p); return str; } /* + * call-seq: + * request.signed? -> true or false + * + * Returns +true+ if the request is signed, +false+ otherwise. Note that the + * validity of the signature is *not* checked. Use #verify to verify that. + */ +static VALUE +ossl_ocspreq_signed_p(VALUE self) +{ + OCSP_REQUEST *req; + + GetOCSPReq(self, req); + return OCSP_request_is_signed(req) ? Qtrue : Qfalse; +} + +/* * OCSP::Response */ /* call-seq: * OpenSSL::OCSP::Response.create(status, basic_response = nil) -> response * - * Creates an OpenSSL::OCSP::Response from +status+ and +basic_response+. + * Creates an OpenSSL::OCSP::Response from _status_ and _basic_response_. */ static VALUE @@ -415,9 +492,10 @@ ossl_ocspres_s_create(VALUE klass, VALUE status, VALUE basic_resp) if(NIL_P(basic_resp)) bs = NULL; else GetOCSPBasicRes(basic_resp, bs); /* NO NEED TO DUP */ + obj = NewOCSPRes(klass); if(!(res = OCSP_response_create(st, bs))) - ossl_raise(eOCSPError, NULL); - WrapOCSPRes(klass, obj, res); + ossl_raise(eOCSPError, NULL); + SetOCSPRes(obj, res); return obj; } @@ -428,39 +506,61 @@ ossl_ocspres_alloc(VALUE klass) OCSP_RESPONSE *res; VALUE obj; + obj = NewOCSPRes(klass); if(!(res = OCSP_RESPONSE_new())) - ossl_raise(eOCSPError, NULL); - WrapOCSPRes(klass, obj, res); + ossl_raise(eOCSPError, NULL); + SetOCSPRes(obj, res); return obj; } +/* :nodoc: */ +static VALUE +ossl_ocspres_initialize_copy(VALUE self, VALUE other) +{ + OCSP_RESPONSE *res, *res_old, *res_new; + + rb_check_frozen(self); + GetOCSPRes(self, res_old); + GetOCSPRes(other, res); + + res_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_RESPONSE), res); + if (!res_new) + ossl_raise(eOCSPError, "ASN1_item_dup"); + + SetOCSPRes(self, res_new); + OCSP_RESPONSE_free(res_old); + + return self; +} + /* * call-seq: * OpenSSL::OCSP::Response.new -> response * OpenSSL::OCSP::Response.new(response_der) -> response * * Creates a new OpenSSL::OCSP::Response. The response may be created empty or - * from a +response_der+ string. + * from a _response_der_ string. */ static VALUE ossl_ocspres_initialize(int argc, VALUE *argv, VALUE self) { VALUE arg; + OCSP_RESPONSE *res, *res_new; const unsigned char *p; rb_scan_args(argc, argv, "01", &arg); if(!NIL_P(arg)){ - OCSP_RESPONSE *res = DATA_PTR(self), *x; - arg = ossl_to_der_if_possible(arg); - StringValue(arg); - p = (unsigned char *)RSTRING_PTR(arg); - x = d2i_OCSP_RESPONSE(&res, &p, RSTRING_LEN(arg)); - DATA_PTR(self) = res; - if(!x){ - ossl_raise(eOCSPError, "cannot load DER encoded response"); - } + GetOCSPRes(self, res); + arg = ossl_to_der_if_possible(arg); + StringValue(arg); + p = (unsigned char *)RSTRING_PTR(arg); + res_new = d2i_OCSP_RESPONSE(NULL, &p, RSTRING_LEN(arg)); + if (!res_new) + ossl_raise(eOCSPError, "d2i_OCSP_RESPONSE"); + SetOCSPRes(self, res_new); + OCSP_RESPONSE_free(res); } return self; @@ -519,9 +619,10 @@ ossl_ocspres_get_basic(VALUE self) VALUE ret; GetOCSPRes(self, res); + ret = NewOCSPBasicRes(cOCSPBasicRes); if(!(bs = OCSP_response_get1_basic(res))) - return Qnil; - WrapOCSPBasicRes(cOCSPBasicRes, ret, bs); + return Qnil; + SetOCSPBasicRes(ret, bs); return ret; } @@ -543,11 +644,11 @@ ossl_ocspres_to_der(VALUE self) GetOCSPRes(self, res); if((len = i2d_OCSP_RESPONSE(res, NULL)) <= 0) - ossl_raise(eOCSPError, NULL); + ossl_raise(eOCSPError, NULL); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); if(i2d_OCSP_RESPONSE(res, &p) <= 0) - ossl_raise(eOCSPError, NULL); + ossl_raise(eOCSPError, NULL); ossl_str_adjust(str, p); return str; @@ -562,23 +663,62 @@ ossl_ocspbres_alloc(VALUE klass) OCSP_BASICRESP *bs; VALUE obj; + obj = NewOCSPBasicRes(klass); if(!(bs = OCSP_BASICRESP_new())) - ossl_raise(eOCSPError, NULL); - WrapOCSPBasicRes(klass, obj, bs); + ossl_raise(eOCSPError, NULL); + SetOCSPBasicRes(obj, bs); return obj; } +/* :nodoc: */ +static VALUE +ossl_ocspbres_initialize_copy(VALUE self, VALUE other) +{ + OCSP_BASICRESP *bs, *bs_old, *bs_new; + + rb_check_frozen(self); + GetOCSPBasicRes(self, bs_old); + GetOCSPBasicRes(other, bs); + + bs_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_BASICRESP), bs); + if (!bs_new) + ossl_raise(eOCSPError, "ASN1_item_dup"); + + SetOCSPBasicRes(self, bs_new); + OCSP_BASICRESP_free(bs_old); + + return self; +} + /* * call-seq: - * OpenSSL::OCSP::BasicResponse.new(*) -> basic_response + * OpenSSL::OCSP::BasicResponse.new(der_string = nil) -> basic_response * - * Creates a new BasicResponse and ignores all arguments. + * Creates a new BasicResponse. If _der_string_ is given, decodes _der_string_ + * as DER. */ static VALUE ossl_ocspbres_initialize(int argc, VALUE *argv, VALUE self) { + VALUE arg; + OCSP_BASICRESP *res, *res_new; + const unsigned char *p; + + rb_scan_args(argc, argv, "01", &arg); + if (!NIL_P(arg)) { + GetOCSPBasicRes(self, res); + arg = ossl_to_der_if_possible(arg); + StringValue(arg); + p = (unsigned char *)RSTRING_PTR(arg); + res_new = d2i_OCSP_BASICRESP(NULL, &p, RSTRING_LEN(arg)); + if (!res_new) + ossl_raise(eOCSPError, "d2i_OCSP_BASICRESP"); + SetOCSPBasicRes(self, res_new); + OCSP_BASICRESP_free(res); + } + return self; } @@ -586,7 +726,7 @@ ossl_ocspbres_initialize(int argc, VALUE *argv, VALUE self) * call-seq: * basic_response.copy_nonce(request) -> Integer * - * Copies the nonce from +request+ into this response. Returns 1 on success + * Copies the nonce from _request_ into this response. Returns 1 on success * and 0 on failure. */ @@ -598,7 +738,7 @@ ossl_ocspbres_copy_nonce(VALUE self, VALUE request) int ret; GetOCSPBasicRes(self, bs); - SafeGetOCSPReq(request, req); + GetOCSPReq(request, req); ret = OCSP_copy_nonce(bs, req); return INT2NUM(ret); @@ -608,7 +748,7 @@ ossl_ocspbres_copy_nonce(VALUE self, VALUE request) * call-seq: * basic_response.add_nonce(nonce = nil) * - * Adds +nonce+ to this response. If no nonce was provided a random nonce + * Adds _nonce_ to this response. If no nonce was provided a random nonce * will be added. */ @@ -621,94 +761,119 @@ ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "01", &val); if(NIL_P(val)) { - GetOCSPBasicRes(self, bs); - ret = OCSP_basic_add1_nonce(bs, NULL, -1); + GetOCSPBasicRes(self, bs); + ret = OCSP_basic_add1_nonce(bs, NULL, -1); } else{ - StringValue(val); - GetOCSPBasicRes(self, bs); - ret = OCSP_basic_add1_nonce(bs, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val)); + StringValue(val); + GetOCSPBasicRes(self, bs); + ret = OCSP_basic_add1_nonce(bs, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val)); } if(!ret) ossl_raise(eOCSPError, NULL); return self; } +static VALUE +add_status_convert_time(VALUE obj) +{ + ASN1_TIME *time; + + if (RB_INTEGER_TYPE_P(obj)) + time = X509_gmtime_adj(NULL, NUM2INT(obj)); + else + time = ossl_x509_time_adjust(NULL, obj); + + if (!time) + ossl_raise(eOCSPError, NULL); + + return (VALUE)time; +} + /* * call-seq: * basic_response.add_status(certificate_id, status, reason, revocation_time, this_update, next_update, extensions) -> basic_response * - * Adds a validation +status+ (0 for revoked, 1 for success) to this - * response for +certificate_id+. +reason+ describes the reason for the - * revocation, if any. + * Adds a certificate status for _certificate_id_. _status_ is the status, and + * must be one of these: + * + * - OpenSSL::OCSP::V_CERTSTATUS_GOOD + * - OpenSSL::OCSP::V_CERTSTATUS_REVOKED + * - OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN * - * The +revocation_time+, +this_update+ and +next_update+ are times for the - * certificate's revocation time, the time of this status and the next update - * time for a new status, respectively. + * _reason_ and _revocation_time_ can be given only when _status_ is + * OpenSSL::OCSP::V_CERTSTATUS_REVOKED. _reason_ describes the reason for the + * revocation, and must be one of OpenSSL::OCSP::REVOKED_STATUS_* constants. + * _revocation_time_ is the time when the certificate is revoked. * - * +extensions+ may be an Array of OpenSSL::X509::Extension that will - * be added to this response or nil. + * _this_update_ and _next_update_ indicate the time at which the status is + * verified to be correct and the time at or before which newer information + * will be available, respectively. _next_update_ is optional. + * + * _extensions_ is an Array of OpenSSL::X509::Extension to be included in the + * SingleResponse. This is also optional. + * + * Note that the times, _revocation_time_, _this_update_ and _next_update_ + * can be specified in either of Integer or Time object. If they are Integer, it + * is treated as the relative seconds from the current time. */ - static VALUE ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status, - VALUE reason, VALUE revtime, - VALUE thisupd, VALUE nextupd, VALUE ext) + VALUE reason, VALUE revtime, + VALUE thisupd, VALUE nextupd, VALUE ext) { OCSP_BASICRESP *bs; OCSP_SINGLERESP *single; OCSP_CERTID *id; - int st, rsn; - ASN1_TIME *ths, *nxt, *rev; - int error, i, rstatus = 0; + ASN1_TIME *ths = NULL, *nxt = NULL, *rev = NULL; + int st, rsn = 0, error = 0, rstatus = 0; + long i; VALUE tmp; + GetOCSPBasicRes(self, bs); + GetOCSPCertId(cid, id); st = NUM2INT(status); - rsn = NIL_P(status) ? 0 : NUM2INT(reason); - if(!NIL_P(ext)){ - /* All ary's members should be X509Extension */ - Check_Type(ext, T_ARRAY); - for (i = 0; i < RARRAY_LEN(ext); i++) - OSSL_Check_Kind(RARRAY_PTR(ext)[i], cX509Ext); + if (!NIL_P(ext)) { /* All ext's members must be X509::Extension */ + ext = rb_check_array_type(ext); + for (i = 0; i < RARRAY_LEN(ext); i++) + OSSL_Check_Kind(RARRAY_AREF(ext, i), cX509Ext); } - error = 0; - ths = nxt = rev = NULL; - if(!NIL_P(revtime)){ - tmp = rb_protect(rb_Integer, revtime, &rstatus); - if(rstatus) goto err; - rev = X509_gmtime_adj(NULL, NUM2INT(tmp)); + if (st == V_OCSP_CERTSTATUS_REVOKED) { + rsn = NUM2INT(reason); + tmp = rb_protect(add_status_convert_time, revtime, &rstatus); + if (rstatus) goto err; + rev = (ASN1_TIME *)tmp; + } + + tmp = rb_protect(add_status_convert_time, thisupd, &rstatus); + if (rstatus) goto err; + ths = (ASN1_TIME *)tmp; + + if (!NIL_P(nextupd)) { + tmp = rb_protect(add_status_convert_time, nextupd, &rstatus); + if (rstatus) goto err; + nxt = (ASN1_TIME *)tmp; } - tmp = rb_protect(rb_Integer, thisupd, &rstatus); - if(rstatus) goto err; - ths = X509_gmtime_adj(NULL, NUM2INT(tmp)); - tmp = rb_protect(rb_Integer, nextupd, &rstatus); - if(rstatus) goto err; - nxt = X509_gmtime_adj(NULL, NUM2INT(tmp)); - GetOCSPBasicRes(self, bs); - SafeGetOCSPCertId(cid, id); if(!(single = OCSP_basic_add1_status(bs, id, st, rsn, rev, ths, nxt))){ - error = 1; - goto err; + error = 1; + goto err; } if(!NIL_P(ext)){ - X509_EXTENSION *x509ext; - sk_X509_EXTENSION_pop_free(single->singleExtensions, X509_EXTENSION_free); - single->singleExtensions = NULL; - for(i = 0; i < RARRAY_LEN(ext); i++){ - x509ext = DupX509ExtPtr(RARRAY_PTR(ext)[i]); - if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){ - X509_EXTENSION_free(x509ext); - error = 1; - goto err; - } - X509_EXTENSION_free(x509ext); - } + X509_EXTENSION *x509ext; + + for(i = 0; i < RARRAY_LEN(ext); i++){ + x509ext = GetX509ExtPtr(RARRAY_AREF(ext, i)); + if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){ + error = 1; + goto err; + } + } } - err: + err: ASN1_TIME_free(ths); ASN1_TIME_free(nxt); ASN1_TIME_free(rev); @@ -723,125 +888,502 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status, * basic_response.status -> statuses * * Returns an Array of statuses for this response. Each status contains a - * CertificateId, the status (0 for success, 1 for revoked), the reason for - * the status, the revocation time, the time of this update, the time for the - * next update and a list of OpenSSL::X509::Extensions. + * CertificateId, the status (0 for good, 1 for revoked, 2 for unknown), the + * reason for the status, the revocation time, the time of this update, the time + * for the next update and a list of OpenSSL::X509::Extension. + * + * This should be superseded by BasicResponse#responses and #find_response that + * return SingleResponse. */ - static VALUE ossl_ocspbres_get_status(VALUE self) { OCSP_BASICRESP *bs; - OCSP_SINGLERESP *single; - OCSP_CERTID *cid; - ASN1_TIME *revtime, *thisupd, *nextupd; - int status, reason; - X509_EXTENSION *x509ext; - VALUE ret, ary, ext; - int count, ext_count, i, j; GetOCSPBasicRes(self, bs); - ret = rb_ary_new(); + VALUE ret = rb_ary_new(); + int count = OCSP_resp_count(bs); + for (int i = 0; i < count; i++) { + OCSP_SINGLERESP *single = OCSP_resp_get0(bs, i); + ASN1_TIME *revtime, *thisupd, *nextupd; + int reason; + + int status = OCSP_single_get0_status(single, &reason, &revtime, &thisupd, &nextupd); + if (status < 0) + ossl_raise(eOCSPError, "OCSP_single_get0_status"); + + VALUE ary = rb_ary_new(); + rb_ary_push(ary, ossl_ocspcid_new(OCSP_SINGLERESP_get0_id(single))); + rb_ary_push(ary, INT2NUM(status)); + rb_ary_push(ary, INT2NUM(reason)); + rb_ary_push(ary, revtime ? asn1time_to_time(revtime) : Qnil); + rb_ary_push(ary, thisupd ? asn1time_to_time(thisupd) : Qnil); + rb_ary_push(ary, nextupd ? asn1time_to_time(nextupd) : Qnil); + VALUE ext = rb_ary_new(); + int ext_count = OCSP_SINGLERESP_get_ext_count(single); + for (int j = 0; j < ext_count; j++) { + X509_EXTENSION *x509ext = OCSP_SINGLERESP_get_ext(single, j); + rb_ary_push(ext, ossl_x509ext_new(x509ext)); + } + rb_ary_push(ary, ext); + rb_ary_push(ret, ary); + } + + return ret; +} + +static VALUE ossl_ocspsres_new(const OCSP_SINGLERESP *); + +/* + * call-seq: + * basic_response.responses -> Array of SingleResponse + * + * Returns an Array of SingleResponse for this BasicResponse. + */ + +static VALUE +ossl_ocspbres_get_responses(VALUE self) +{ + OCSP_BASICRESP *bs; + VALUE ret; + int count, i; + + GetOCSPBasicRes(self, bs); count = OCSP_resp_count(bs); - for(i = 0; i < count; i++){ - single = OCSP_resp_get0(bs, i); - if(!single) continue; - - revtime = thisupd = nextupd = NULL; - status = OCSP_single_get0_status(single, &reason, &revtime, - &thisupd, &nextupd); - if(status < 0) continue; - if(!(cid = OCSP_CERTID_dup(single->certId))) - ossl_raise(eOCSPError, NULL); - ary = rb_ary_new(); - rb_ary_push(ary, ossl_ocspcertid_new(cid)); - rb_ary_push(ary, INT2NUM(status)); - rb_ary_push(ary, INT2NUM(reason)); - rb_ary_push(ary, revtime ? asn1time_to_time(revtime) : Qnil); - rb_ary_push(ary, thisupd ? asn1time_to_time(thisupd) : Qnil); - rb_ary_push(ary, nextupd ? asn1time_to_time(nextupd) : Qnil); - ext = rb_ary_new(); - ext_count = OCSP_SINGLERESP_get_ext_count(single); - for(j = 0; j < ext_count; j++){ - x509ext = OCSP_SINGLERESP_get_ext(single, j); - rb_ary_push(ext, ossl_x509ext_new(x509ext)); - } - rb_ary_push(ary, ext); - rb_ary_push(ret, ary); + ret = rb_ary_new_capa(count); + + for (i = 0; i < count; i++) { + rb_ary_push(ret, ossl_ocspsres_new(OCSP_resp_get0(bs, i))); } return ret; } + /* * call-seq: - * basic_response.sign(signer_cert, signer_key) -> self - * basic_response.sign(signer_cert, signer_key, certificates) -> self - * basic_response.sign(signer_cert, signer_key, certificates, flags) -> self + * basic_response.find_response(certificate_id) -> SingleResponse | nil * - * Signs this response using the +signer_cert+ and +signer_key+. Additional - * +certificates+ may be added to the signature along with a set of +flags+. + * Returns a SingleResponse whose CertId matches with _certificate_id_, or +nil+ + * if this BasicResponse does not contain it. + */ +static VALUE +ossl_ocspbres_find_response(VALUE self, VALUE target) +{ + OCSP_BASICRESP *bs; + OCSP_CERTID *id; + int n; + + GetOCSPCertId(target, id); + GetOCSPBasicRes(self, bs); + + if ((n = OCSP_resp_find(bs, id, -1)) == -1) + return Qnil; + return ossl_ocspsres_new(OCSP_resp_get0(bs, n)); +} + +/* + * call-seq: + * basic_response.sign(cert, key, certs = nil, flags = 0, digest = nil) -> self + * + * Signs this OCSP response using the _cert_, _key_ and optional _digest_. This + * behaves in the similar way as OpenSSL::OCSP::Request#sign. + * + * _flags_ can include: + * OpenSSL::OCSP::NOCERTS:: don't include certificates + * OpenSSL::OCSP::NOTIME:: don't set producedAt + * OpenSSL::OCSP::RESPID_KEY:: use signer's public key hash as responderID */ static VALUE ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self) { - VALUE signer_cert, signer_key, certs, flags; + VALUE signer_cert, signer_key, certs, flags, digest, md_holder; OCSP_BASICRESP *bs; X509 *signer; EVP_PKEY *key; - STACK_OF(X509) *x509s; - unsigned long flg; + STACK_OF(X509) *x509s = NULL; + unsigned long flg = 0; + const EVP_MD *md; int ret; - rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags); + rb_scan_args(argc, argv, "23", &signer_cert, &signer_key, &certs, &flags, &digest); + GetOCSPBasicRes(self, bs); signer = GetX509CertPtr(signer_cert); key = GetPrivPKeyPtr(signer_key); - flg = NIL_P(flags) ? 0 : NUM2INT(flags); - if(NIL_P(certs)){ - x509s = sk_X509_new_null(); - flg |= OCSP_NOCERTS; - } - else{ - x509s = ossl_x509_ary2sk(certs); - } - GetOCSPBasicRes(self, bs); - ret = OCSP_basic_sign(bs, signer, key, EVP_sha1(), x509s, flg); + if (!NIL_P(flags)) + flg = NUM2INT(flags); + md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder); + if (NIL_P(certs)) + flg |= OCSP_NOCERTS; + else + x509s = ossl_x509_ary2sk(certs); + + ret = OCSP_basic_sign(bs, signer, key, md, x509s, flg); sk_X509_pop_free(x509s, X509_free); - if(!ret) ossl_raise(eOCSPError, NULL); + if (!ret) + ossl_raise(eOCSPError, "OCSP_basic_sign"); return self; } /* * call-seq: - * basic_response.verify(certificates, store) -> true or false - * basic_response.verify(certificates, store, flags) -> true or false + * basic_response.verify(certificates, store, flags = 0) -> true or false * - * Verifies the signature of the response using the given +certificates+, - * +store+ and +flags+. + * Verifies the signature of the response using the given _certificates_ and + * _store_. This works in the similar way as OpenSSL::OCSP::Request#verify. */ static VALUE ossl_ocspbres_verify(int argc, VALUE *argv, VALUE self) { - VALUE certs, store, flags, result; + VALUE certs, store, flags; OCSP_BASICRESP *bs; STACK_OF(X509) *x509s; X509_STORE *x509st; - int flg; + int flg, result; rb_scan_args(argc, argv, "21", &certs, &store, &flags); + GetOCSPBasicRes(self, bs); x509st = GetX509StorePtr(store); flg = NIL_P(flags) ? 0 : NUM2INT(flags); x509s = ossl_x509_ary2sk(certs); - GetOCSPBasicRes(self, bs); - result = OCSP_basic_verify(bs, x509s, x509st, flg) > 0 ? Qtrue : Qfalse; + result = OCSP_basic_verify(bs, x509s, x509st, flg); sk_X509_pop_free(x509s, X509_free); - if(!result) rb_warn("%s", ERR_error_string(ERR_peek_error(), NULL)); + if (result <= 0) + ossl_clear_error(); + + return result > 0 ? Qtrue : Qfalse; +} + +/* + * call-seq: + * basic_response.to_der -> String + * + * Encodes this basic response into a DER-encoded string. + */ +static VALUE +ossl_ocspbres_to_der(VALUE self) +{ + OCSP_BASICRESP *res; + VALUE str; + long len; + unsigned char *p; + + GetOCSPBasicRes(self, res); + if ((len = i2d_OCSP_BASICRESP(res, NULL)) <= 0) + ossl_raise(eOCSPError, NULL); + str = rb_str_new(0, len); + p = (unsigned char *)RSTRING_PTR(str); + if (i2d_OCSP_BASICRESP(res, &p) <= 0) + ossl_raise(eOCSPError, NULL); + ossl_str_adjust(str, p); + + return str; +} + +/* + * OCSP::SingleResponse + */ +static VALUE +ossl_ocspsres_new(const OCSP_SINGLERESP *sres) +{ + VALUE obj; + OCSP_SINGLERESP *sres_new; + + obj = NewOCSPSingleRes(cOCSPSingleRes); + /* OpenSSL 1.1.1 takes a non-const pointer */ + sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP), + (OCSP_SINGLERESP *)sres); + if (!sres_new) + ossl_raise(eOCSPError, "ASN1_item_dup"); + SetOCSPSingleRes(obj, sres_new); + + return obj; +} + +static VALUE +ossl_ocspsres_alloc(VALUE klass) +{ + OCSP_SINGLERESP *sres; + VALUE obj; + + obj = NewOCSPSingleRes(klass); + if (!(sres = OCSP_SINGLERESP_new())) + ossl_raise(eOCSPError, NULL); + SetOCSPSingleRes(obj, sres); + + return obj; +} + +/* + * call-seq: + * OpenSSL::OCSP::SingleResponse.new(der_string) -> SingleResponse + * + * Creates a new SingleResponse from _der_string_. + */ +static VALUE +ossl_ocspsres_initialize(VALUE self, VALUE arg) +{ + OCSP_SINGLERESP *res, *res_new; + const unsigned char *p; + + arg = ossl_to_der_if_possible(arg); + StringValue(arg); + GetOCSPSingleRes(self, res); - return result; + p = (unsigned char*)RSTRING_PTR(arg); + res_new = d2i_OCSP_SINGLERESP(NULL, &p, RSTRING_LEN(arg)); + if (!res_new) + ossl_raise(eOCSPError, "d2i_OCSP_SINGLERESP"); + SetOCSPSingleRes(self, res_new); + OCSP_SINGLERESP_free(res); + + return self; +} + +/* :nodoc: */ +static VALUE +ossl_ocspsres_initialize_copy(VALUE self, VALUE other) +{ + OCSP_SINGLERESP *sres, *sres_old, *sres_new; + + rb_check_frozen(self); + GetOCSPSingleRes(self, sres_old); + GetOCSPSingleRes(other, sres); + + sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP), sres); + if (!sres_new) + ossl_raise(eOCSPError, "ASN1_item_dup"); + + SetOCSPSingleRes(self, sres_new); + OCSP_SINGLERESP_free(sres_old); + + return self; +} + +/* + * call-seq: + * single_response.check_validity(nsec = 0, maxsec = -1) -> true | false + * + * Checks the validity of thisUpdate and nextUpdate fields of this + * SingleResponse. This checks the current time is within the range thisUpdate + * to nextUpdate. + * + * It is possible that the OCSP request takes a few seconds or the time is not + * accurate. To avoid rejecting a valid response, this method allows the times + * to be within _nsec_ seconds of the current time. + * + * Some responders don't set the nextUpdate field. This may cause a very old + * response to be considered valid. The _maxsec_ parameter can be used to limit + * the age of responses. + */ +static VALUE +ossl_ocspsres_check_validity(int argc, VALUE *argv, VALUE self) +{ + OCSP_SINGLERESP *sres; + ASN1_GENERALIZEDTIME *this_update, *next_update; + VALUE nsec_v, maxsec_v; + int nsec, maxsec, status, ret; + + rb_scan_args(argc, argv, "02", &nsec_v, &maxsec_v); + nsec = NIL_P(nsec_v) ? 0 : NUM2INT(nsec_v); + maxsec = NIL_P(maxsec_v) ? -1 : NUM2INT(maxsec_v); + + GetOCSPSingleRes(self, sres); + status = OCSP_single_get0_status(sres, NULL, NULL, &this_update, &next_update); + if (status < 0) + ossl_raise(eOCSPError, "OCSP_single_get0_status"); + + ret = OCSP_check_validity(this_update, next_update, nsec, maxsec); + + if (ret) + return Qtrue; + else { + ossl_clear_error(); + return Qfalse; + } +} + +/* + * call-seq: + * single_response.certid -> CertificateId + * + * Returns the CertificateId for which this SingleResponse is. + */ +static VALUE +ossl_ocspsres_get_certid(VALUE self) +{ + OCSP_SINGLERESP *sres; + + GetOCSPSingleRes(self, sres); + return ossl_ocspcid_new(OCSP_SINGLERESP_get0_id(sres)); +} + +/* + * call-seq: + * single_response.cert_status -> Integer + * + * Returns the status of the certificate identified by the certid. + * The return value may be one of these constant: + * + * - V_CERTSTATUS_GOOD + * - V_CERTSTATUS_REVOKED + * - V_CERTSTATUS_UNKNOWN + * + * When the status is V_CERTSTATUS_REVOKED, the time at which the certificate + * was revoked can be retrieved by #revocation_time. + */ +static VALUE +ossl_ocspsres_get_cert_status(VALUE self) +{ + OCSP_SINGLERESP *sres; + int status; + + GetOCSPSingleRes(self, sres); + status = OCSP_single_get0_status(sres, NULL, NULL, NULL, NULL); + if (status < 0) + ossl_raise(eOCSPError, "OCSP_single_get0_status"); + + return INT2NUM(status); +} + +/* + * call-seq: + * single_response.this_update -> Time + */ +static VALUE +ossl_ocspsres_get_this_update(VALUE self) +{ + OCSP_SINGLERESP *sres; + int status; + ASN1_GENERALIZEDTIME *time; + + GetOCSPSingleRes(self, sres); + status = OCSP_single_get0_status(sres, NULL, NULL, &time, NULL); + if (status < 0) + ossl_raise(eOCSPError, "OCSP_single_get0_status"); + if (!time) + return Qnil; + + return asn1time_to_time(time); +} + +/* + * call-seq: + * single_response.next_update -> Time | nil + */ +static VALUE +ossl_ocspsres_get_next_update(VALUE self) +{ + OCSP_SINGLERESP *sres; + int status; + ASN1_GENERALIZEDTIME *time; + + GetOCSPSingleRes(self, sres); + status = OCSP_single_get0_status(sres, NULL, NULL, NULL, &time); + if (status < 0) + ossl_raise(eOCSPError, "OCSP_single_get0_status"); + if (!time) + return Qnil; + + return asn1time_to_time(time); +} + +/* + * call-seq: + * single_response.revocation_time -> Time | nil + */ +static VALUE +ossl_ocspsres_get_revocation_time(VALUE self) +{ + OCSP_SINGLERESP *sres; + int status; + ASN1_GENERALIZEDTIME *time; + + GetOCSPSingleRes(self, sres); + status = OCSP_single_get0_status(sres, NULL, &time, NULL, NULL); + if (status < 0) + ossl_raise(eOCSPError, "OCSP_single_get0_status"); + if (status != V_OCSP_CERTSTATUS_REVOKED) + ossl_raise(eOCSPError, "certificate is not revoked"); + if (!time) + return Qnil; + + return asn1time_to_time(time); +} + +/* + * call-seq: + * single_response.revocation_reason -> Integer | nil + */ +static VALUE +ossl_ocspsres_get_revocation_reason(VALUE self) +{ + OCSP_SINGLERESP *sres; + int status, reason; + + GetOCSPSingleRes(self, sres); + status = OCSP_single_get0_status(sres, &reason, NULL, NULL, NULL); + if (status < 0) + ossl_raise(eOCSPError, "OCSP_single_get0_status"); + if (status != V_OCSP_CERTSTATUS_REVOKED) + ossl_raise(eOCSPError, "certificate is not revoked"); + + return INT2NUM(reason); +} + +/* + * call-seq: + * single_response.extensions -> Array of X509::Extension + */ +static VALUE +ossl_ocspsres_get_extensions(VALUE self) +{ + OCSP_SINGLERESP *sres; + X509_EXTENSION *ext; + int count, i; + VALUE ary; + + GetOCSPSingleRes(self, sres); + + count = OCSP_SINGLERESP_get_ext_count(sres); + ary = rb_ary_new2(count); + for (i = 0; i < count; i++) { + ext = OCSP_SINGLERESP_get_ext(sres, i); + rb_ary_push(ary, ossl_x509ext_new(ext)); /* will dup */ + } + + return ary; +} + +/* + * call-seq: + * single_response.to_der -> String + * + * Encodes this SingleResponse into a DER-encoded string. + */ +static VALUE +ossl_ocspsres_to_der(VALUE self) +{ + OCSP_SINGLERESP *sres; + VALUE str; + long len; + unsigned char *p; + + GetOCSPSingleRes(self, sres); + if ((len = i2d_OCSP_SINGLERESP(sres, NULL)) <= 0) + ossl_raise(eOCSPError, NULL); + str = rb_str_new(0, len); + p = (unsigned char *)RSTRING_PTR(str); + if (i2d_OCSP_SINGLERESP(sres, &p) <= 0) + ossl_raise(eOCSPError, NULL); + ossl_str_adjust(str, p); + + return str; } + /* * OCSP::CertificateId */ @@ -851,48 +1393,82 @@ ossl_ocspcid_alloc(VALUE klass) OCSP_CERTID *id; VALUE obj; + obj = NewOCSPCertId(klass); if(!(id = OCSP_CERTID_new())) - ossl_raise(eOCSPError, NULL); - WrapOCSPCertId(klass, obj, id); + ossl_raise(eOCSPError, NULL); + SetOCSPCertId(obj, id); return obj; } +/* :nodoc: */ +static VALUE +ossl_ocspcid_initialize_copy(VALUE self, VALUE other) +{ + OCSP_CERTID *cid, *cid_old, *cid_new; + + rb_check_frozen(self); + GetOCSPCertId(self, cid_old); + GetOCSPCertId(other, cid); + + cid_new = OCSP_CERTID_dup(cid); + if (!cid_new) + ossl_raise(eOCSPError, "OCSP_CERTID_dup"); + + SetOCSPCertId(self, cid_new); + OCSP_CERTID_free(cid_old); + + return self; +} + /* * call-seq: * OpenSSL::OCSP::CertificateId.new(subject, issuer, digest = nil) -> certificate_id + * OpenSSL::OCSP::CertificateId.new(der_string) -> certificate_id + * OpenSSL::OCSP::CertificateId.new(obj) -> certificate_id + * + * Creates a new OpenSSL::OCSP::CertificateId for the given _subject_ and + * _issuer_ X509 certificates. The _digest_ is a digest algorithm that is used + * to compute the hash values. This defaults to SHA-1. * - * Creates a new OpenSSL::OCSP::CertificateId for the given +subject+ and - * +issuer+ X509 certificates. The +digest+ is used to compute the - * certificate ID and must be an OpenSSL::Digest instance. + * If only one argument is given, decodes it as DER representation of a + * certificate ID or generates certificate ID from the object that responds to + * the to_der method. */ - static VALUE ossl_ocspcid_initialize(int argc, VALUE *argv, VALUE self) { OCSP_CERTID *id, *newid; - X509 *x509s, *x509i; VALUE subject, issuer, digest; - const EVP_MD *md; - if (rb_scan_args(argc, argv, "21", &subject, &issuer, &digest) == 0) { - return self; + GetOCSPCertId(self, id); + if (rb_scan_args(argc, argv, "12", &subject, &issuer, &digest) == 1) { + VALUE arg; + const unsigned char *p; + + arg = ossl_to_der_if_possible(subject); + StringValue(arg); + p = (unsigned char *)RSTRING_PTR(arg); + newid = d2i_OCSP_CERTID(NULL, &p, RSTRING_LEN(arg)); + if (!newid) + ossl_raise(eOCSPError, "d2i_OCSP_CERTID"); } - - x509s = GetX509CertPtr(subject); /* NO NEED TO DUP */ - x509i = GetX509CertPtr(issuer); /* NO NEED TO DUP */ - - if (!NIL_P(digest)) { - md = GetDigestPtr(digest); - newid = OCSP_cert_to_id(md, x509s, x509i); - } else { - newid = OCSP_cert_to_id(NULL, x509s, x509i); + else { + X509 *x509s, *x509i; + const EVP_MD *md; + VALUE md_holder; + + x509s = GetX509CertPtr(subject); /* NO NEED TO DUP */ + x509i = GetX509CertPtr(issuer); /* NO NEED TO DUP */ + md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder); + + newid = OCSP_cert_to_id(md, x509s, x509i); + if (!newid) + ossl_raise(eOCSPError, "OCSP_cert_to_id"); } - if(!newid) - ossl_raise(eOCSPError, NULL); - GetOCSPCertId(self, id); + + SetOCSPCertId(self, newid); OCSP_CERTID_free(id); - RDATA(self)->data = newid; return self; } @@ -901,7 +1477,7 @@ ossl_ocspcid_initialize(int argc, VALUE *argv, VALUE self) * call-seq: * certificate_id.cmp(other) -> true or false * - * Compares this certificate id with +other+ and returns true if they are the + * Compares this certificate id with _other_ and returns +true+ if they are the * same. */ static VALUE @@ -911,7 +1487,7 @@ ossl_ocspcid_cmp(VALUE self, VALUE other) int result; GetOCSPCertId(self, id); - SafeGetOCSPCertId(other, id2); + GetOCSPCertId(other, id2); result = OCSP_id_cmp(id, id2); return (result == 0) ? Qtrue : Qfalse; @@ -921,7 +1497,7 @@ ossl_ocspcid_cmp(VALUE self, VALUE other) * call-seq: * certificate_id.cmp_issuer(other) -> true or false * - * Compares this certificate id's issuer with +other+ and returns true if + * Compares this certificate id's issuer with _other_ and returns +true+ if * they are the same. */ @@ -932,7 +1508,7 @@ ossl_ocspcid_cmp_issuer(VALUE self, VALUE other) int result; GetOCSPCertId(self, id); - SafeGetOCSPCertId(other, id2); + GetOCSPCertId(other, id2); result = OCSP_id_issuer_cmp(id, id2); return (result == 0) ? Qtrue : Qfalse; @@ -940,19 +1516,113 @@ ossl_ocspcid_cmp_issuer(VALUE self, VALUE other) /* * call-seq: - * certificate_id.get_serial -> Integer + * certificate_id.serial -> Integer * - * Returns the serial number of the issuing certificate. + * Returns the serial number of the certificate for which status is being + * requested. */ - static VALUE ossl_ocspcid_get_serial(VALUE self) { OCSP_CERTID *id; + ASN1_INTEGER *serial; + + GetOCSPCertId(self, id); + OCSP_id_get0_info(NULL, NULL, NULL, &serial, id); + + return asn1integer_to_num(serial); +} + +/* + * call-seq: + * certificate_id.issuer_name_hash -> String + * + * Returns the issuerNameHash of this certificate ID, the hash of the + * issuer's distinguished name calculated with the hashAlgorithm. + */ +static VALUE +ossl_ocspcid_get_issuer_name_hash(VALUE self) +{ + OCSP_CERTID *id; + ASN1_OCTET_STRING *name_hash; + VALUE ret; + + GetOCSPCertId(self, id); + OCSP_id_get0_info(&name_hash, NULL, NULL, NULL, id); + + ret = rb_str_new(NULL, ASN1_STRING_length(name_hash) * 2); + ossl_bin2hex(ASN1_STRING_get0_data(name_hash), RSTRING_PTR(ret), + ASN1_STRING_length(name_hash)); + + return ret; +} + +/* + * call-seq: + * certificate_id.issuer_key_hash -> String + * + * Returns the issuerKeyHash of this certificate ID, the hash of the issuer's + * public key. + */ +static VALUE +ossl_ocspcid_get_issuer_key_hash(VALUE self) +{ + OCSP_CERTID *id; + ASN1_OCTET_STRING *key_hash; + VALUE ret; GetOCSPCertId(self, id); + OCSP_id_get0_info(NULL, NULL, &key_hash, NULL, id); + + ret = rb_str_new(NULL, ASN1_STRING_length(key_hash) * 2); + ossl_bin2hex(ASN1_STRING_get0_data(key_hash), RSTRING_PTR(ret), + ASN1_STRING_length(key_hash)); + + return ret; +} + +/* + * call-seq: + * certificate_id.hash_algorithm -> String + * + * Returns the ln (long name) of the hash algorithm used to generate + * the issuerNameHash and the issuerKeyHash values. + */ +static VALUE +ossl_ocspcid_get_hash_algorithm(VALUE self) +{ + OCSP_CERTID *id; + ASN1_OBJECT *oid; - return asn1integer_to_num(id->serialNumber); + GetOCSPCertId(self, id); + OCSP_id_get0_info(NULL, &oid, NULL, NULL, id); + return ossl_asn1obj_to_string_long_name(oid); +} + +/* + * call-seq: + * certificate_id.to_der -> String + * + * Encodes this certificate identifier into a DER-encoded string. + */ +static VALUE +ossl_ocspcid_to_der(VALUE self) +{ + OCSP_CERTID *id; + VALUE str; + long len; + unsigned char *p; + + GetOCSPCertId(self, id); + if ((len = i2d_OCSP_CERTID(id, NULL)) <= 0) + ossl_raise(eOCSPError, NULL); + str = rb_str_new(0, len); + p = (unsigned char *)RSTRING_PTR(str); + if (i2d_OCSP_CERTID(id, &p) <= 0) + ossl_raise(eOCSPError, NULL); + ossl_str_adjust(str, p); + + return str; } void @@ -974,7 +1644,7 @@ Init_ossl_ocsp(void) * subject certificate so the CA knows which certificate we are asking * about: * - * digest = OpenSSL::Digest::SHA1.new + * digest = OpenSSL::Digest.new('SHA1') * certificate_id = * OpenSSL::OCSP::CertificateId.new subject, issuer, digest * @@ -991,18 +1661,11 @@ Init_ossl_ocsp(void) * To submit the request to the CA for verification we need to extract the * OCSP URI from the subject certificate: * - * authority_info_access = subject.extensions.find do |extension| - * extension.oid == 'authorityInfoAccess' - * end - * - * descriptions = authority_info_access.value.split "\n" - * ocsp = descriptions.find do |description| - * description.start_with? 'OCSP' - * end + * ocsp_uris = subject.ocsp_uris * * require 'uri' * - * ocsp_uri = URI ocsp[/URI:(.*)/, 1] + * ocsp_uri = URI ocsp_uris[0] * * To submit the request we'll POST the request to the OCSP URI (per RFC * 2560). Note that we only handle HTTP requests and don't handle any @@ -1011,7 +1674,7 @@ Init_ossl_ocsp(void) * require 'net/http' * * http_response = - * Net::HTTP.start ocsp_uri.hostname, ocsp.port do |http| + * Net::HTTP.start ocsp_uri.hostname, ocsp_uri.port do |http| * http.post ocsp_uri.path, request.to_der, * 'content-type' => 'application/ocsp-request' * end @@ -1027,7 +1690,7 @@ Init_ossl_ocsp(void) * store = OpenSSL::X509::Store.new * store.set_default_paths * - * unless response.verify [], store then + * unless response_basic.verify [], store then * raise 'response is not signed by a trusted certificate' * end * @@ -1043,27 +1706,28 @@ Init_ossl_ocsp(void) * * p request.check_nonce basic_response #=> value from -1 to 3 * - * Then extract the status information from the basic response. (You can - * check multiple certificates in a request, but for this example we only - * submitted one.) + * Then extract the status information for the certificate from the basic + * response. * - * response_certificate_id, status, reason, revocation_time, - * this_update, next_update, extensions = basic_response.status + * single_response = basic_response.find_response(certificate_id) * - * Then check the various fields. - * - * unless response_certificate_id == certificate_id then - * raise 'certificate id mismatch' + * unless single_response + * raise 'basic_response does not have the status for the certificate' * end * - * now = Time.now + * Then check the validity. A status issued in the future must be rejected. * - * if this_update > now then - * raise 'update date is in the future' + * unless single_response.check_validity + * raise 'this_update is in the future or next_update time has passed' * end * - * if now > next_update then - * raise 'next update time has passed' + * case single_response.cert_status + * when OpenSSL::OCSP::V_CERTSTATUS_GOOD + * puts 'certificate is still valid' + * when OpenSSL::OCSP::V_CERTSTATUS_REVOKED + * puts "certificate has been revoked at #{single_response.revocation_time}" + * when OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN + * puts 'responder doesn't know about the certificate' * end */ @@ -1084,11 +1748,13 @@ Init_ossl_ocsp(void) cOCSPReq = rb_define_class_under(mOCSP, "Request", rb_cObject); rb_define_alloc_func(cOCSPReq, ossl_ocspreq_alloc); + rb_define_method(cOCSPReq, "initialize_copy", ossl_ocspreq_initialize_copy, 1); rb_define_method(cOCSPReq, "initialize", ossl_ocspreq_initialize, -1); rb_define_method(cOCSPReq, "add_nonce", ossl_ocspreq_add_nonce, -1); rb_define_method(cOCSPReq, "check_nonce", ossl_ocspreq_check_nonce, 1); rb_define_method(cOCSPReq, "add_certid", ossl_ocspreq_add_certid, 1); rb_define_method(cOCSPReq, "certid", ossl_ocspreq_get_certid, 0); + rb_define_method(cOCSPReq, "signed?", ossl_ocspreq_signed_p, 0); rb_define_method(cOCSPReq, "sign", ossl_ocspreq_sign, -1); rb_define_method(cOCSPReq, "verify", ossl_ocspreq_verify, -1); rb_define_method(cOCSPReq, "to_der", ossl_ocspreq_to_der, 0); @@ -1101,6 +1767,7 @@ Init_ossl_ocsp(void) cOCSPRes = rb_define_class_under(mOCSP, "Response", rb_cObject); rb_define_singleton_method(cOCSPRes, "create", ossl_ocspres_s_create, 2); rb_define_alloc_func(cOCSPRes, ossl_ocspres_alloc); + rb_define_method(cOCSPRes, "initialize_copy", ossl_ocspres_initialize_copy, 1); rb_define_method(cOCSPRes, "initialize", ossl_ocspres_initialize, -1); rb_define_method(cOCSPRes, "status", ossl_ocspres_status, 0); rb_define_method(cOCSPRes, "status_string", ossl_ocspres_status_string, 0); @@ -1115,13 +1782,36 @@ Init_ossl_ocsp(void) cOCSPBasicRes = rb_define_class_under(mOCSP, "BasicResponse", rb_cObject); rb_define_alloc_func(cOCSPBasicRes, ossl_ocspbres_alloc); + rb_define_method(cOCSPBasicRes, "initialize_copy", ossl_ocspbres_initialize_copy, 1); rb_define_method(cOCSPBasicRes, "initialize", ossl_ocspbres_initialize, -1); rb_define_method(cOCSPBasicRes, "copy_nonce", ossl_ocspbres_copy_nonce, 1); rb_define_method(cOCSPBasicRes, "add_nonce", ossl_ocspbres_add_nonce, -1); rb_define_method(cOCSPBasicRes, "add_status", ossl_ocspbres_add_status, 7); rb_define_method(cOCSPBasicRes, "status", ossl_ocspbres_get_status, 0); + rb_define_method(cOCSPBasicRes, "responses", ossl_ocspbres_get_responses, 0); + rb_define_method(cOCSPBasicRes, "find_response", ossl_ocspbres_find_response, 1); rb_define_method(cOCSPBasicRes, "sign", ossl_ocspbres_sign, -1); rb_define_method(cOCSPBasicRes, "verify", ossl_ocspbres_verify, -1); + rb_define_method(cOCSPBasicRes, "to_der", ossl_ocspbres_to_der, 0); + + /* + * An OpenSSL::OCSP::SingleResponse represents an OCSP SingleResponse + * structure, which contains the basic information of the status of the + * certificate. + */ + cOCSPSingleRes = rb_define_class_under(mOCSP, "SingleResponse", rb_cObject); + rb_define_alloc_func(cOCSPSingleRes, ossl_ocspsres_alloc); + rb_define_method(cOCSPSingleRes, "initialize_copy", ossl_ocspsres_initialize_copy, 1); + rb_define_method(cOCSPSingleRes, "initialize", ossl_ocspsres_initialize, 1); + rb_define_method(cOCSPSingleRes, "check_validity", ossl_ocspsres_check_validity, -1); + rb_define_method(cOCSPSingleRes, "certid", ossl_ocspsres_get_certid, 0); + rb_define_method(cOCSPSingleRes, "cert_status", ossl_ocspsres_get_cert_status, 0); + rb_define_method(cOCSPSingleRes, "this_update", ossl_ocspsres_get_this_update, 0); + rb_define_method(cOCSPSingleRes, "next_update", ossl_ocspsres_get_next_update, 0); + rb_define_method(cOCSPSingleRes, "revocation_time", ossl_ocspsres_get_revocation_time, 0); + rb_define_method(cOCSPSingleRes, "revocation_reason", ossl_ocspsres_get_revocation_reason, 0); + rb_define_method(cOCSPSingleRes, "extensions", ossl_ocspsres_get_extensions, 0); + rb_define_method(cOCSPSingleRes, "to_der", ossl_ocspsres_to_der, 0); /* * An OpenSSL::OCSP::CertificateId identifies a certificate to the CA so @@ -1130,10 +1820,15 @@ Init_ossl_ocsp(void) cOCSPCertId = rb_define_class_under(mOCSP, "CertificateId", rb_cObject); rb_define_alloc_func(cOCSPCertId, ossl_ocspcid_alloc); + rb_define_method(cOCSPCertId, "initialize_copy", ossl_ocspcid_initialize_copy, 1); rb_define_method(cOCSPCertId, "initialize", ossl_ocspcid_initialize, -1); rb_define_method(cOCSPCertId, "cmp", ossl_ocspcid_cmp, 1); rb_define_method(cOCSPCertId, "cmp_issuer", ossl_ocspcid_cmp_issuer, 1); rb_define_method(cOCSPCertId, "serial", ossl_ocspcid_get_serial, 0); + rb_define_method(cOCSPCertId, "issuer_name_hash", ossl_ocspcid_get_issuer_name_hash, 0); + rb_define_method(cOCSPCertId, "issuer_key_hash", ossl_ocspcid_get_issuer_key_hash, 0); + rb_define_method(cOCSPCertId, "hash_algorithm", ossl_ocspcid_get_hash_algorithm, 0); + rb_define_method(cOCSPCertId, "to_der", ossl_ocspcid_to_der, 0); /* Internal error in issuer */ rb_define_const(mOCSP, "RESPONSE_STATUS_INTERNALERROR", INT2NUM(OCSP_RESPONSE_STATUS_INTERNALERROR)); @@ -1235,8 +1930,7 @@ Init_ossl_ocsp(void) /* The responder ID is based on the public key. */ rb_define_const(mOCSP, "V_RESPID_KEY", INT2NUM(V_OCSP_RESPID_KEY)); } - -#else /* ! OSSL_OCSP_ENABLED */ +#else void Init_ossl_ocsp(void) { diff --git a/ext/openssl/ossl_ocsp.h b/ext/openssl/ossl_ocsp.h index 65b4f2e23f..becd70ffed 100644 --- a/ext/openssl/ossl_ocsp.h +++ b/ext/openssl/ossl_ocsp.h @@ -1,24 +1,16 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz> * Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(_OSSL_OCSP_H_) #define _OSSL_OCSP_H_ -#if defined(OSSL_OCSP_ENABLED) -extern VALUE mOCSP; -extern VALUE cOPCSReq; -extern VALUE cOPCSRes; -extern VALUE cOPCSBasicRes; -#endif - void Init_ossl_ocsp(void); #endif /* _OSSL_OCSP_H_ */ diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c index 53e0e619ca..32b82a881c 100644 --- a/ext/openssl/ossl_pkcs12.c +++ b/ext/openssl/ossl_pkcs12.c @@ -1,13 +1,15 @@ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) - * $Id$ + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#define WrapPKCS12(klass, obj, p12) do { \ +#define NewPKCS12(klass) \ + TypedData_Wrap_Struct((klass), &ossl_pkcs12_type, 0) + +#define SetPKCS12(obj, p12) do { \ if(!(p12)) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_pkcs12_type, (p12)); \ + RTYPEDDATA_DATA(obj) = (p12); \ } while (0) #define GetPKCS12(obj, p12) do { \ @@ -15,11 +17,6 @@ if(!(p12)) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \ } while (0) -#define SafeGetPKCS12(obj, p12) do { \ - OSSL_Check_Kind((obj), cPKCS12); \ - GetPKCS12((obj), (p12)); \ -} while (0) - #define ossl_pkcs12_set_key(o,v) rb_iv_set((o), "@key", (v)) #define ossl_pkcs12_set_cert(o,v) rb_iv_set((o), "@certificate", (v)) #define ossl_pkcs12_set_ca_certs(o,v) rb_iv_set((o), "@ca_certs", (v)) @@ -30,8 +27,8 @@ /* * Classes */ -VALUE cPKCS12; -VALUE ePKCS12Error; +static VALUE cPKCS12; +static VALUE ePKCS12Error; /* * Private @@ -45,9 +42,9 @@ ossl_pkcs12_free(void *ptr) static const rb_data_type_t ossl_pkcs12_type = { "OpenSSL/PKCS12", { - 0, ossl_pkcs12_free, + 0, ossl_pkcs12_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; static VALUE @@ -56,31 +53,52 @@ ossl_pkcs12_s_allocate(VALUE klass) PKCS12 *p12; VALUE obj; + obj = NewPKCS12(klass); if(!(p12 = PKCS12_new())) ossl_raise(ePKCS12Error, NULL); - WrapPKCS12(klass, obj, p12); + SetPKCS12(obj, p12); return obj; } +/* :nodoc: */ +static VALUE +ossl_pkcs12_initialize_copy(VALUE self, VALUE other) +{ + PKCS12 *p12, *p12_old, *p12_new; + + rb_check_frozen(self); + GetPKCS12(self, p12_old); + GetPKCS12(other, p12); + + p12_new = ASN1_dup((i2d_of_void *)i2d_PKCS12, (d2i_of_void *)d2i_PKCS12, (char *)p12); + if (!p12_new) + ossl_raise(ePKCS12Error, "ASN1_dup"); + + SetPKCS12(self, p12_new); + PKCS12_free(p12_old); + + return self; +} + /* * call-seq: * PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]]) * * === Parameters - * * +pass+ - string - * * +name+ - A string describing the key. - * * +key+ - Any PKey. - * * +cert+ - A X509::Certificate. - * * * The public_key portion of the certificate must contain a valid public key. - * * * The not_before and not_after fields must be filled in. - * * +ca+ - An optional array of X509::Certificate's. - * * +key_pbe+ - string - * * +cert_pbe+ - string - * * +key_iter+ - integer - * * +mac_iter+ - integer - * * +keytype+ - An integer representing an MSIE specific extension. + * * _pass_ - string + * * _name_ - A string describing the key. + * * _key_ - Any PKey. + * * _cert_ - A X509::Certificate. + * * The public_key portion of the certificate must contain a valid public key. + * * The not_before and not_after fields must be filled in. + * * _ca_ - An optional array of X509::Certificate's. + * * _key_pbe_ - string + * * _cert_pbe_ - string + * * _key_iter_ - integer + * * _mac_iter_ - integer + * * _keytype_ - An integer representing an MSIE specific extension. * - * Any optional arguments may be supplied as nil to preserve the OpenSSL defaults. + * Any optional arguments may be supplied as +nil+ to preserve the OpenSSL defaults. * * See the OpenSSL documentation for PKCS12_create(). */ @@ -97,19 +115,18 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self) PKCS12 *p12; rb_scan_args(argc, argv, "46", &pass, &name, &pkey, &cert, &ca, &key_nid, &cert_nid, &key_iter, &mac_iter, &keytype); - passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass); - friendlyname = NIL_P(name) ? NULL : StringValuePtr(name); + passphrase = NIL_P(pass) ? NULL : StringValueCStr(pass); + friendlyname = NIL_P(name) ? NULL : StringValueCStr(name); key = GetPKeyPtr(pkey); x509 = GetX509CertPtr(cert); - x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca); /* TODO: make a VALUE to nid function */ if (!NIL_P(key_nid)) { - if ((nkey = OBJ_txt2nid(StringValuePtr(key_nid))) == NID_undef) - ossl_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(key_nid)); + if ((nkey = OBJ_txt2nid(StringValueCStr(key_nid))) == NID_undef) + ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, key_nid); } if (!NIL_P(cert_nid)) { - if ((ncert = OBJ_txt2nid(StringValuePtr(cert_nid))) == NID_undef) - ossl_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(cert_nid)); + if ((ncert = OBJ_txt2nid(StringValueCStr(cert_nid))) == NID_undef) + ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, cert_nid); } if (!NIL_P(key_iter)) kiter = NUM2INT(key_iter); @@ -118,11 +135,23 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self) if (!NIL_P(keytype)) ktype = NUM2INT(keytype); +#if defined(OPENSSL_IS_AWSLC) + if (ktype != 0) { + ossl_raise(rb_eArgError, "Unknown key usage type %"PRIsVALUE, INT2NUM(ktype)); + } +#else + if (ktype != 0 && ktype != KEY_SIG && ktype != KEY_EX) { + ossl_raise(rb_eArgError, "Unknown key usage type %"PRIsVALUE, INT2NUM(ktype)); + } +#endif + + obj = NewPKCS12(cPKCS12); + x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca); p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s, nkey, ncert, kiter, miter, ktype); sk_X509_pop_free(x509s, X509_free); if(!p12) ossl_raise(ePKCS12Error, NULL); - WrapPKCS12(cPKCS12, obj, p12); + SetPKCS12(obj, p12); ossl_pkcs12_set_key(obj, pkey); ossl_pkcs12_set_cert(obj, cert); @@ -131,6 +160,24 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self) return obj; } +static VALUE +ossl_pkey_wrap_i(VALUE arg) +{ + return ossl_pkey_wrap((EVP_PKEY *)arg); +} + +static VALUE +ossl_x509_new_i(VALUE arg) +{ + return ossl_x509_new((X509 *)arg); +} + +static VALUE +ossl_x509_sk2ary_i(VALUE arg) +{ + return ossl_x509_sk2ary((STACK_OF(X509) *)arg); +} + /* * call-seq: * PKCS12.new -> pkcs12 @@ -138,8 +185,8 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self) * PKCS12.new(str, pass) -> pkcs12 * * === Parameters - * * +str+ - Must be a DER encoded PKCS12 string. - * * +pass+ - string + * * _str_ - Must be a DER encoded PKCS12 string. + * * _pass_ - string */ static VALUE ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self) @@ -154,24 +201,26 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self) PKCS12 *pkcs = DATA_PTR(self); if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self; - passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass); - in = ossl_obj2bio(arg); + passphrase = NIL_P(pass) ? NULL : StringValueCStr(pass); + in = ossl_obj2bio(&arg); d2i_PKCS12_bio(in, &pkcs); DATA_PTR(self) = pkcs; BIO_free(in); pkey = cert = ca = Qnil; if(!PKCS12_parse(pkcs, passphrase, &key, &x509, &x509s)) - ossl_raise(ePKCS12Error, "PKCS12_parse"); - pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key, - &st); /* NO DUP */ - if(st) goto err; - cert = rb_protect((VALUE(*)_((VALUE)))ossl_x509_new, (VALUE)x509, &st); - if(st) goto err; - if(x509s){ - ca = - rb_protect((VALUE(*)_((VALUE)))ossl_x509_sk2ary, (VALUE)x509s, &st); - if(st) goto err; + ossl_raise(ePKCS12Error, "PKCS12_parse"); + if (key) { + pkey = rb_protect(ossl_pkey_wrap_i, (VALUE)key, &st); + if (st) goto err; + } + if (x509) { + cert = rb_protect(ossl_x509_new_i, (VALUE)x509, &st); + if (st) goto err; + } + if (x509s) { + ca = rb_protect(ossl_x509_sk2ary_i, (VALUE)x509s, &st); + if (st) goto err; } err: @@ -195,19 +244,62 @@ ossl_pkcs12_to_der(VALUE self) GetPKCS12(self, p12); if((len = i2d_PKCS12(p12, NULL)) <= 0) - ossl_raise(ePKCS12Error, NULL); + ossl_raise(ePKCS12Error, NULL); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); if(i2d_PKCS12(p12, &p) <= 0) - ossl_raise(ePKCS12Error, NULL); + ossl_raise(ePKCS12Error, NULL); ossl_str_adjust(str, p); return str; } +/* + * call-seq: + * pkcs12.set_mac(pass, salt = nil, iter = nil, md_type = nil) + * + * Sets MAC parameters and generates MAC over the PKCS #12 structure. + * + * This method uses HMAC and the PKCS #12 specific password-based KDF as + * specified in the original PKCS #12. + * + * See also the man page PKCS12_set_mac(3). + * + * Added in version 3.3.0. + */ +static VALUE +pkcs12_set_mac(int argc, VALUE *argv, VALUE self) +{ + PKCS12 *p12; + VALUE pass, salt, iter, md_name, md_holder = Qnil; + int iter_i = 0; + const EVP_MD *md_type = NULL; + + rb_scan_args(argc, argv, "13", &pass, &salt, &iter, &md_name); + rb_check_frozen(self); + GetPKCS12(self, p12); + + StringValue(pass); + if (!NIL_P(salt)) + StringValue(salt); + if (!NIL_P(iter)) + iter_i = NUM2INT(iter); + if (!NIL_P(md_name)) + md_type = ossl_evp_md_fetch(md_name, &md_holder); + + if (!PKCS12_set_mac(p12, RSTRING_PTR(pass), RSTRING_LENINT(pass), + !NIL_P(salt) ? (unsigned char *)RSTRING_PTR(salt) : NULL, + !NIL_P(salt) ? RSTRING_LENINT(salt) : 0, + iter_i, md_type)) + ossl_raise(ePKCS12Error, "PKCS12_set_mac"); + + return Qnil; +} + void Init_ossl_pkcs12(void) { +#undef rb_intern /* * Defines a file format commonly used to store private keys with * accompanying public key certificates, protected with a password-based @@ -218,9 +310,17 @@ Init_ossl_pkcs12(void) rb_define_singleton_method(cPKCS12, "create", ossl_pkcs12_s_create, -1); rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate); + rb_define_method(cPKCS12, "initialize_copy", ossl_pkcs12_initialize_copy, 1); rb_attr(cPKCS12, rb_intern("key"), 1, 0, Qfalse); rb_attr(cPKCS12, rb_intern("certificate"), 1, 0, Qfalse); rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse); rb_define_method(cPKCS12, "initialize", ossl_pkcs12_initialize, -1); rb_define_method(cPKCS12, "to_der", ossl_pkcs12_to_der, 0); + rb_define_method(cPKCS12, "set_mac", pkcs12_set_mac, -1); + +#if !defined(OPENSSL_IS_AWSLC) + /* MSIE specific PKCS12 key usage extensions */ + rb_define_const(cPKCS12, "KEY_EX", INT2NUM(KEY_EX)); + rb_define_const(cPKCS12, "KEY_SIG", INT2NUM(KEY_SIG)); +#endif } diff --git a/ext/openssl/ossl_pkcs12.h b/ext/openssl/ossl_pkcs12.h index 24d25d00bb..6d2cd901cb 100644 --- a/ext/openssl/ossl_pkcs12.h +++ b/ext/openssl/ossl_pkcs12.h @@ -1,15 +1,10 @@ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) - * $Id$ + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(_OSSL_PKCS12_H_) #define _OSSL_PKCS12_H_ -extern VALUE cPKCS12; -extern VALUE ePKCS12Error; - void Init_ossl_pkcs12(void); #endif /* _OSSL_PKCS12_H_ */ - diff --git a/ext/openssl/ossl_pkcs5.c b/ext/openssl/ossl_pkcs5.c deleted file mode 100644 index 6c7738a2b2..0000000000 --- a/ext/openssl/ossl_pkcs5.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * $Id$ - * Copyright (C) 2007 Technorama Ltd. <oss-ruby@technorama.net> - */ -#include "ossl.h" - -VALUE mPKCS5; -VALUE ePKCS5; - -#ifdef HAVE_PKCS5_PBKDF2_HMAC -/* - * call-seq: - * PKCS5.pbkdf2_hmac(pass, salt, iter, keylen, digest) => string - * - * === Parameters - * * +pass+ - string - * * +salt+ - string - should be at least 8 bytes long. - * * +iter+ - integer - should be greater than 1000. 20000 is better. - * * +keylen+ - integer - * * +digest+ - a string or OpenSSL::Digest object. - * - * Available in OpenSSL 0.9.4. - * - * Digests other than SHA1 may not be supported by other cryptography libraries. - */ -static VALUE -ossl_pkcs5_pbkdf2_hmac(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen, VALUE digest) -{ - VALUE str; - const EVP_MD *md; - int len = NUM2INT(keylen); - - StringValue(pass); - StringValue(salt); - md = GetDigestPtr(digest); - - str = rb_str_new(0, len); - - if (PKCS5_PBKDF2_HMAC(RSTRING_PTR(pass), RSTRING_LENINT(pass), - (unsigned char *)RSTRING_PTR(salt), RSTRING_LENINT(salt), - NUM2INT(iter), md, len, - (unsigned char *)RSTRING_PTR(str)) != 1) - ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC"); - - return str; -} -#else -#define ossl_pkcs5_pbkdf2_hmac rb_f_notimplement -#endif - - -#ifdef HAVE_PKCS5_PBKDF2_HMAC_SHA1 -/* - * call-seq: - * PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, keylen) => string - * - * === Parameters - * * +pass+ - string - * * +salt+ - string - should be at least 8 bytes long. - * * +iter+ - integer - should be greater than 1000. 20000 is better. - * * +keylen+ - integer - * - * This method is available in almost any version of OpenSSL. - * - * Conforms to rfc2898. - */ -static VALUE -ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen) -{ - VALUE str; - int len = NUM2INT(keylen); - - StringValue(pass); - StringValue(salt); - - str = rb_str_new(0, len); - - if (PKCS5_PBKDF2_HMAC_SHA1(RSTRING_PTR(pass), RSTRING_LENINT(pass), - (const unsigned char *)RSTRING_PTR(salt), RSTRING_LENINT(salt), NUM2INT(iter), - len, (unsigned char *)RSTRING_PTR(str)) != 1) - ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC_SHA1"); - - return str; -} -#else -#define ossl_pkcs5_pbkdf2_hmac_sha1 rb_f_notimplement -#endif - -void -Init_ossl_pkcs5(void) -{ - /* - * Password-based Encryption - * - */ - - #if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ - #endif - - /* Document-class: OpenSSL::PKCS5 - * - * Provides password-based encryption functionality based on PKCS#5. - * Typically used for securely deriving arbitrary length symmetric keys - * to be used with an OpenSSL::Cipher from passwords. Another use case - * is for storing passwords: Due to the ability to tweak the effort of - * computation by increasing the iteration count, computation can be - * slowed down artificially in order to render possible attacks infeasible. - * - * PKCS5 offers support for PBKDF2 with an OpenSSL::Digest::SHA1-based - * HMAC, or an arbitrary Digest if the underlying version of OpenSSL - * already supports it (>= 0.9.4). - * - * === Parameters - * ==== Password - * Typically an arbitrary String that represents the password to be used - * for deriving a key. - * ==== Salt - * Prevents attacks based on dictionaries of common passwords. It is a - * public value that can be safely stored along with the password (e.g. - * if PBKDF2 is used for password storage). For maximum security, a fresh, - * random salt should be generated for each stored password. According - * to PKCS#5, a salt should be at least 8 bytes long. - * ==== Iteration Count - * Allows to tweak the length that the actual computation will take. The - * larger the iteration count, the longer it will take. - * ==== Key Length - * Specifies the length in bytes of the output that will be generated. - * Typically, the key length should be larger than or equal to the output - * length of the underlying digest function, otherwise an attacker could - * simply try to brute-force the key. According to PKCS#5, security is - * limited by the output length of the underlying digest function, i.e. - * security is not improved if a key length strictly larger than the - * digest output length is chosen. Therefore, when using PKCS5 for - * password storage, it suffices to store values equal to the digest - * output length, nothing is gained by storing larger values. - * - * == Examples - * === Generating a 128 bit key for a Cipher (e.g. AES) - * pass = "secret" - * salt = OpenSSL::Random.random_bytes(16) - * iter = 20000 - * key_len = 16 - * key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, key_len) - * - * === Storing Passwords - * pass = "secret" - * salt = OpenSSL::Random.random_bytes(16) #store this with the generated value - * iter = 20000 - * digest = OpenSSL::Digest::SHA256.new - * len = digest.digest_length - * #the final value to be stored - * value = OpenSSL::PKCS5.pbkdf2_hmac(pass, salt, iter, len, digest) - * - * === Important Note on Checking Passwords - * When comparing passwords provided by the user with previously stored - * values, a common mistake made is comparing the two values using "==". - * Typically, "==" short-circuits on evaluation, and is therefore - * vulnerable to timing attacks. The proper way is to use a method that - * always takes the same amount of time when comparing two values, thus - * not leaking any information to potential attackers. To compare two - * values, the following could be used: - * def eql_time_cmp(a, b) - * unless a.length == b.length - * return false - * end - * cmp = b.bytes.to_a - * result = 0 - * a.bytes.each_with_index {|c,i| - * result |= c ^ cmp[i] - * } - * result == 0 - * end - * Please note that the premature return in case of differing lengths - * typically does not leak valuable information - when using PKCS#5, the - * length of the values to be compared is of fixed size. - */ - - mPKCS5 = rb_define_module_under(mOSSL, "PKCS5"); - /* Document-class: OpenSSL::PKCS5::PKCS5Error - * - * Generic Exception class that is raised if an error occurs during a - * computation. - */ - ePKCS5 = rb_define_class_under(mPKCS5, "PKCS5Error", eOSSLError); - - rb_define_module_function(mPKCS5, "pbkdf2_hmac", ossl_pkcs5_pbkdf2_hmac, 5); - rb_define_module_function(mPKCS5, "pbkdf2_hmac_sha1", ossl_pkcs5_pbkdf2_hmac_sha1, 4); -} diff --git a/ext/openssl/ossl_pkcs5.h b/ext/openssl/ossl_pkcs5.h deleted file mode 100644 index a3b132bc50..0000000000 --- a/ext/openssl/ossl_pkcs5.h +++ /dev/null @@ -1,6 +0,0 @@ -#if !defined(_OSSL_PKCS5_H_) -#define _OSSL_PKCS5_H_ - -void Init_ossl_pkcs5(void); - -#endif /* _OSSL_PKCS5_H_ */ diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c index f4a5088ea3..6e51fd42b9 100644 --- a/ext/openssl/ossl_pkcs7.c +++ b/ext/openssl/ossl_pkcs7.c @@ -1,65 +1,58 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#define WrapPKCS7(klass, obj, pkcs7) do { \ +#define NewPKCS7(klass) \ + TypedData_Wrap_Struct((klass), &ossl_pkcs7_type, 0) +#define SetPKCS7(obj, pkcs7) do { \ if (!(pkcs7)) { \ - ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \ + ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \ } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_pkcs7_type, (pkcs7)); \ + RTYPEDDATA_DATA(obj) = (pkcs7); \ } while (0) #define GetPKCS7(obj, pkcs7) do { \ TypedData_Get_Struct((obj), PKCS7, &ossl_pkcs7_type, (pkcs7)); \ if (!(pkcs7)) { \ - ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \ + ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \ } \ } while (0) -#define SafeGetPKCS7(obj, pkcs7) do { \ - OSSL_Check_Kind((obj), cPKCS7); \ - GetPKCS7((obj), (pkcs7)); \ -} while (0) -#define WrapPKCS7si(klass, obj, p7si) do { \ +#define NewPKCS7si(klass) \ + TypedData_Wrap_Struct((klass), &ossl_pkcs7_signer_info_type, 0) +#define SetPKCS7si(obj, p7si) do { \ if (!(p7si)) { \ - ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \ + ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \ } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_pkcs7_signer_info_type, (p7si)); \ + RTYPEDDATA_DATA(obj) = (p7si); \ } while (0) #define GetPKCS7si(obj, p7si) do { \ TypedData_Get_Struct((obj), PKCS7_SIGNER_INFO, &ossl_pkcs7_signer_info_type, (p7si)); \ if (!(p7si)) { \ - ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \ + ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \ } \ } while (0) -#define SafeGetPKCS7si(obj, p7si) do { \ - OSSL_Check_Kind((obj), cPKCS7Signer); \ - GetPKCS7si((obj), (p7si)); \ -} while (0) -#define WrapPKCS7ri(klass, obj, p7ri) do { \ +#define NewPKCS7ri(klass) \ + TypedData_Wrap_Struct((klass), &ossl_pkcs7_recip_info_type, 0) +#define SetPKCS7ri(obj, p7ri) do { \ if (!(p7ri)) { \ - ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \ + ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \ } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_pkcs7_recip_info_type, (p7ri)); \ + RTYPEDDATA_DATA(obj) = (p7ri); \ } while (0) #define GetPKCS7ri(obj, p7ri) do { \ TypedData_Get_Struct((obj), PKCS7_RECIP_INFO, &ossl_pkcs7_recip_info_type, (p7ri)); \ if (!(p7ri)) { \ - ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \ + ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \ } \ } while (0) -#define SafeGetPKCS7ri(obj, p7ri) do { \ - OSSL_Check_Kind((obj), cPKCS7Recipient); \ - GetPKCS7ri((obj), (p7ri)); \ -} while (0) #define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0])) @@ -71,10 +64,11 @@ /* * Classes */ -VALUE cPKCS7; -VALUE cPKCS7Signer; -VALUE cPKCS7Recipient; -VALUE ePKCS7Error; +static VALUE cPKCS7; +static VALUE cPKCS7Signer; +static VALUE cPKCS7Recipient; +static VALUE ePKCS7Error; +static ID id_md_holder, id_cipher_holder; static void ossl_pkcs7_free(void *ptr) @@ -85,11 +79,25 @@ ossl_pkcs7_free(void *ptr) static const rb_data_type_t ossl_pkcs7_type = { "OpenSSL/PKCS7", { - 0, ossl_pkcs7_free, + 0, ossl_pkcs7_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; +VALUE +ossl_pkcs7_new(PKCS7 *p7) +{ + PKCS7 *new; + VALUE obj = NewPKCS7(cPKCS7); + + new = PKCS7_dup(p7); + if (!new) + ossl_raise(ePKCS7Error, "PKCS7_dup"); + SetPKCS7(obj, new); + + return obj; +} + static void ossl_pkcs7_signer_info_free(void *ptr) { @@ -99,9 +107,9 @@ ossl_pkcs7_signer_info_free(void *ptr) static const rb_data_type_t ossl_pkcs7_signer_info_type = { "OpenSSL/PKCS7/SIGNER_INFO", { - 0, ossl_pkcs7_signer_info_free, + 0, ossl_pkcs7_signer_info_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; static void @@ -113,65 +121,72 @@ ossl_pkcs7_recip_info_free(void *ptr) static const rb_data_type_t ossl_pkcs7_recip_info_type = { "OpenSSL/PKCS7/RECIP_INFO", { - 0, ossl_pkcs7_recip_info_free, + 0, ossl_pkcs7_recip_info_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; /* * Public * (MADE PRIVATE UNTIL SOMEBODY WILL NEED THEM) */ -static VALUE -ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si) +static PKCS7_SIGNER_INFO * +ossl_PKCS7_SIGNER_INFO_dup(PKCS7_SIGNER_INFO *si) { - PKCS7_SIGNER_INFO *pkcs7; - VALUE obj; - - pkcs7 = p7si ? PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new(); - if (!pkcs7) ossl_raise(ePKCS7Error, NULL); - WrapPKCS7si(cPKCS7Signer, obj, pkcs7); - - return obj; + PKCS7_SIGNER_INFO *si_new = ASN1_dup((i2d_of_void *)i2d_PKCS7_SIGNER_INFO, + (d2i_of_void *)d2i_PKCS7_SIGNER_INFO, + si); + if (si_new && si->pkey) { + EVP_PKEY_up_ref(si->pkey); + si_new->pkey = si->pkey; + } + return si_new; } -static PKCS7_SIGNER_INFO * -DupPKCS7SignerPtr(VALUE obj) +static PKCS7_RECIP_INFO * +ossl_PKCS7_RECIP_INFO_dup(PKCS7_RECIP_INFO *ri) { - PKCS7_SIGNER_INFO *p7si, *pkcs7; - - SafeGetPKCS7si(obj, p7si); - if (!(pkcs7 = PKCS7_SIGNER_INFO_dup(p7si))) { - ossl_raise(ePKCS7Error, NULL); + PKCS7_RECIP_INFO *ri_new = ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO, + (d2i_of_void *)d2i_PKCS7_RECIP_INFO, + ri); + if (ri_new && ri->cert) { + if (!X509_up_ref(ri->cert)) { + PKCS7_RECIP_INFO_free(ri_new); + return NULL; + } + ri_new->cert = ri->cert; } - - return pkcs7; + return ri_new; } static VALUE -ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri) +ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si) { - PKCS7_RECIP_INFO *pkcs7; + PKCS7_SIGNER_INFO *p7si_new; VALUE obj; - pkcs7 = p7ri ? PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new(); - if (!pkcs7) ossl_raise(ePKCS7Error, NULL); - WrapPKCS7ri(cPKCS7Recipient, obj, pkcs7); + obj = NewPKCS7si(cPKCS7Signer); + p7si_new = ossl_PKCS7_SIGNER_INFO_dup(p7si); + if (!p7si_new) + ossl_raise(ePKCS7Error, "ASN1_dup"); + SetPKCS7si(obj, p7si_new); return obj; } -static PKCS7_RECIP_INFO * -DupPKCS7RecipientPtr(VALUE obj) +static VALUE +ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri) { - PKCS7_RECIP_INFO *p7ri, *pkcs7; + PKCS7_RECIP_INFO *p7ri_new; + VALUE obj; - SafeGetPKCS7ri(obj, p7ri); - if (!(pkcs7 = PKCS7_RECIP_INFO_dup(p7ri))) { - ossl_raise(ePKCS7Error, NULL); - } + obj = NewPKCS7ri(cPKCS7Recipient); + p7ri_new = ossl_PKCS7_RECIP_INFO_dup(p7ri); + if (!p7ri_new) + ossl_raise(ePKCS7Error,"ASN1_dup"); + SetPKCS7ri(obj, p7ri_new); - return pkcs7; + return obj; } /* @@ -185,13 +200,20 @@ ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg) PKCS7 *pkcs7; VALUE ret, data; - in = ossl_obj2bio(arg); + ret = NewPKCS7(cPKCS7); + in = ossl_obj2bio(&arg); out = NULL; pkcs7 = SMIME_read_PKCS7(in, &out); BIO_free(in); - if(!pkcs7) ossl_raise(ePKCS7Error, NULL); + if (!pkcs7) + ossl_raise(ePKCS7Error, "Could not parse the PKCS7"); + if (!pkcs7->d.ptr) { + PKCS7_free(pkcs7); + ossl_raise(ePKCS7Error, "No content in PKCS7"); + } + data = out ? ossl_membio2str(out) : Qnil; - WrapPKCS7(cPKCS7, ret, pkcs7); + SetPKCS7(ret, pkcs7); ossl_pkcs7_set_data(ret, data); ossl_pkcs7_set_err_string(ret, Qnil); @@ -214,10 +236,10 @@ ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass) rb_scan_args(argc, argv, "12", &pkcs7, &data, &flags); flg = NIL_P(flags) ? 0 : NUM2INT(flags); if(NIL_P(data)) data = ossl_pkcs7_get_data(pkcs7); - SafeGetPKCS7(pkcs7, p7); + GetPKCS7(pkcs7, p7); if(!NIL_P(data) && PKCS7_is_detached(p7)) - flg |= PKCS7_DETACHED; - in = NIL_P(data) ? NULL : ossl_obj2bio(data); + flg |= PKCS7_DETACHED; + in = NIL_P(data) ? NULL : ossl_obj2bio(&data); if(!(out = BIO_new(BIO_s_mem()))){ BIO_free(in); ossl_raise(ePKCS7Error, NULL); @@ -253,21 +275,22 @@ ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass) x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ flg = NIL_P(flags) ? 0 : NUM2INT(flags); - in = ossl_obj2bio(data); + ret = NewPKCS7(cPKCS7); + in = ossl_obj2bio(&data); if(NIL_P(certs)) x509s = NULL; else{ - x509s = ossl_protect_x509_ary2sk(certs, &status); - if(status){ - BIO_free(in); - rb_jump_tag(status); - } + x509s = ossl_protect_x509_ary2sk(certs, &status); + if(status){ + BIO_free(in); + rb_jump_tag(status); + } } if(!(pkcs7 = PKCS7_sign(x509, pkey, x509s, in, flg))){ - BIO_free(in); - sk_X509_pop_free(x509s, X509_free); - ossl_raise(ePKCS7Error, NULL); + BIO_free(in); + sk_X509_pop_free(x509s, X509_free); + ossl_raise(ePKCS7Error, NULL); } - WrapPKCS7(cPKCS7, ret, pkcs7); + SetPKCS7(ret, pkcs7); ossl_pkcs7_set_data(ret, data); ossl_pkcs7_set_err_string(ret, Qnil); BIO_free(in); @@ -278,12 +301,19 @@ ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * PKCS7.encrypt(certs, data, [, cipher [, flags]]) => pkcs7 + * PKCS7.encrypt(certs, data, cipher, flags = 0) => pkcs7 + * + * Creates a PKCS #7 enveloped-data structure. + * + * Before version 3.3.0, +cipher+ was optional and defaulted to + * <tt>"RC2-40-CBC"</tt>. + * + * See also the man page PKCS7_encrypt(3). */ static VALUE ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass) { - VALUE certs, data, cipher, flags; + VALUE certs, data, cipher, flags, cipher_holder; STACK_OF(X509) *x509s; BIO *in; const EVP_CIPHER *ciph; @@ -292,36 +322,29 @@ ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass) PKCS7 *p7; rb_scan_args(argc, argv, "22", &certs, &data, &cipher, &flags); - if(NIL_P(cipher)){ -#if !defined(OPENSSL_NO_RC2) - ciph = EVP_rc2_40_cbc(); -#elif !defined(OPENSSL_NO_DES) - ciph = EVP_des_ede3_cbc(); -#elif !defined(OPENSSL_NO_RC2) - ciph = EVP_rc2_40_cbc(); -#elif !defined(OPENSSL_NO_AES) - ciph = EVP_EVP_aes_128_cbc(); -#else - ossl_raise(ePKCS7Error, "Must specify cipher"); -#endif - + if (NIL_P(cipher)) { + rb_raise(rb_eArgError, + "cipher must be specified. Before version 3.3, " \ + "the default cipher was RC2-40-CBC."); } - else ciph = GetCipherPtr(cipher); /* NO NEED TO DUP */ + ciph = ossl_evp_cipher_fetch(cipher, &cipher_holder); flg = NIL_P(flags) ? 0 : NUM2INT(flags); - in = ossl_obj2bio(data); + ret = NewPKCS7(cPKCS7); + in = ossl_obj2bio(&data); x509s = ossl_protect_x509_ary2sk(certs, &status); if(status){ - BIO_free(in); - rb_jump_tag(status); + BIO_free(in); + rb_jump_tag(status); } - if(!(p7 = PKCS7_encrypt(x509s, in, (EVP_CIPHER*)ciph, flg))){ - BIO_free(in); - sk_X509_pop_free(x509s, X509_free); - ossl_raise(ePKCS7Error, NULL); + if (!(p7 = PKCS7_encrypt(x509s, in, ciph, flg))) { + BIO_free(in); + sk_X509_pop_free(x509s, X509_free); + ossl_raise(ePKCS7Error, NULL); } BIO_free(in); - WrapPKCS7(cPKCS7, ret, p7); + SetPKCS7(ret, p7); ossl_pkcs7_set_data(ret, data); + rb_ivar_set(ret, id_cipher_holder, cipher_holder); sk_X509_pop_free(x509s, X509_free); return ret; @@ -333,10 +356,11 @@ ossl_pkcs7_alloc(VALUE klass) PKCS7 *pkcs7; VALUE obj; + obj = NewPKCS7(klass); if (!(pkcs7 = PKCS7_new())) { - ossl_raise(ePKCS7Error, NULL); + ossl_raise(ePKCS7Error, NULL); } - WrapPKCS7(klass, obj, pkcs7); + SetPKCS7(obj, pkcs7); return obj; } @@ -351,33 +375,36 @@ ossl_pkcs7_alloc(VALUE klass) static VALUE ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self) { - PKCS7 *p7, *pkcs = DATA_PTR(self); + PKCS7 *p7, *p7_orig = RTYPEDDATA_DATA(self); BIO *in; VALUE arg; if(rb_scan_args(argc, argv, "01", &arg) == 0) - return self; + return self; arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(arg); - p7 = PEM_read_bio_PKCS7(in, &pkcs, NULL, NULL); + in = ossl_obj2bio(&arg); + p7 = d2i_PKCS7_bio(in, NULL); if (!p7) { - OSSL_BIO_reset(in); - p7 = d2i_PKCS7_bio(in, &pkcs); - if (!p7) { - BIO_free(in); - PKCS7_free(pkcs); - DATA_PTR(self) = NULL; - ossl_raise(rb_eArgError, "Could not parse the PKCS7"); - } + OSSL_BIO_reset(in); + p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); } - DATA_PTR(self) = pkcs; BIO_free(in); + if (!p7) + ossl_raise(ePKCS7Error, "Could not parse the PKCS7"); + if (!p7->d.ptr) { + PKCS7_free(p7); + ossl_raise(ePKCS7Error, "No content in PKCS7"); + } + + RTYPEDDATA_DATA(self) = p7; + PKCS7_free(p7_orig); ossl_pkcs7_set_data(self, Qnil); ossl_pkcs7_set_err_string(self, Qnil); return self; } +/* :nodoc: */ static VALUE ossl_pkcs7_copy(VALUE self, VALUE other) { @@ -387,11 +414,11 @@ ossl_pkcs7_copy(VALUE self, VALUE other) if (self == other) return self; GetPKCS7(self, a); - SafeGetPKCS7(other, b); + GetPKCS7(other, b); pkcs7 = PKCS7_dup(b); if (!pkcs7) { - ossl_raise(ePKCS7Error, NULL); + ossl_raise(ePKCS7Error, NULL); } DATA_PTR(self) = pkcs7; PKCS7_free(a); @@ -418,17 +445,18 @@ ossl_pkcs7_sym2typeid(VALUE sym) { "digest", NID_pkcs7_digest }, }; - if (RB_TYPE_P(sym, T_SYMBOL)) sym = rb_sym2str(sym); + if (SYMBOL_P(sym)) sym = rb_sym2str(sym); else StringValue(sym); RSTRING_GETMEM(sym, s, l); + for(i = 0; ; i++){ - if(i == numberof(p7_type_tab)) - ossl_raise(ePKCS7Error, "unknown type \"%s\"", s); - if(strlen(p7_type_tab[i].name) != l) continue; - if(strcmp(p7_type_tab[i].name, s) == 0){ - ret = p7_type_tab[i].nid; - break; - } + if(i == numberof(p7_type_tab)) + ossl_raise(ePKCS7Error, "unknown type \"%"PRIsVALUE"\"", sym); + if(strlen(p7_type_tab[i].name) != l) continue; + if(strcmp(p7_type_tab[i].name, s) == 0){ + ret = p7_type_tab[i].nid; + break; + } } return ret; @@ -445,7 +473,7 @@ ossl_pkcs7_set_type(VALUE self, VALUE type) GetPKCS7(self, p7); if(!PKCS7_set_type(p7, ossl_pkcs7_sym2typeid(type))) - ossl_raise(ePKCS7Error, NULL); + ossl_raise(ePKCS7Error, NULL); return type; } @@ -461,15 +489,15 @@ ossl_pkcs7_get_type(VALUE self) GetPKCS7(self, p7); if(PKCS7_type_is_signed(p7)) - return ID2SYM(rb_intern("signed")); + return ID2SYM(rb_intern("signed")); if(PKCS7_type_is_encrypted(p7)) - return ID2SYM(rb_intern("encrypted")); + return ID2SYM(rb_intern("encrypted")); if(PKCS7_type_is_enveloped(p7)) - return ID2SYM(rb_intern("enveloped")); + return ID2SYM(rb_intern("enveloped")); if(PKCS7_type_is_signedAndEnveloped(p7)) - return ID2SYM(rb_intern("signedAndEnveloped")); + return ID2SYM(rb_intern("signedAndEnveloped")); if(PKCS7_type_is_data(p7)) - return ID2SYM(rb_intern("data")); + return ID2SYM(rb_intern("data")); return Qnil; } @@ -480,9 +508,9 @@ ossl_pkcs7_set_detached(VALUE self, VALUE flag) GetPKCS7(self, p7); if(flag != Qtrue && flag != Qfalse) - ossl_raise(ePKCS7Error, "must specify a boolean"); + ossl_raise(ePKCS7Error, "must specify a boolean"); if(!PKCS7_set_detached(p7, flag == Qtrue ? 1 : 0)) - ossl_raise(ePKCS7Error, NULL); + ossl_raise(ePKCS7Error, NULL); return flag; } @@ -492,6 +520,8 @@ ossl_pkcs7_get_detached(VALUE self) { PKCS7 *p7; GetPKCS7(self, p7); + if (!PKCS7_type_is_signed(p7)) + return Qfalse; return PKCS7_get_detached(p7) ? Qtrue : Qfalse; } @@ -507,11 +537,14 @@ static VALUE ossl_pkcs7_set_cipher(VALUE self, VALUE cipher) { PKCS7 *pkcs7; + const EVP_CIPHER *ciph; + VALUE cipher_holder; GetPKCS7(self, pkcs7); - if (!PKCS7_set_cipher(pkcs7, GetCipherPtr(cipher))) { - ossl_raise(ePKCS7Error, NULL); - } + ciph = ossl_evp_cipher_fetch(cipher, &cipher_holder); + if (!PKCS7_set_cipher(pkcs7, ciph)) + ossl_raise(ePKCS7Error, "PKCS7_set_cipher"); + rb_ivar_set(self, id_cipher_holder, cipher_holder); return cipher; } @@ -520,17 +553,18 @@ static VALUE ossl_pkcs7_add_signer(VALUE self, VALUE signer) { PKCS7 *pkcs7; - PKCS7_SIGNER_INFO *p7si; + PKCS7_SIGNER_INFO *si, *si_new; - p7si = DupPKCS7SignerPtr(signer); /* NEED TO DUP */ GetPKCS7(self, pkcs7); - if (!PKCS7_add_signer(pkcs7, p7si)) { - PKCS7_SIGNER_INFO_free(p7si); - ossl_raise(ePKCS7Error, "Could not add signer."); - } - if (PKCS7_type_is_signed(pkcs7)){ - PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType, - V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data)); + GetPKCS7si(signer, si); + + si_new = ossl_PKCS7_SIGNER_INFO_dup(si); + if (!si_new) + ossl_raise(ePKCS7Error, "PKCS7_SIGNER_INFO_dup"); + + if (PKCS7_add_signer(pkcs7, si_new) != 1) { + PKCS7_SIGNER_INFO_free(si_new); + ossl_raise(ePKCS7Error, "PKCS7_add_signer"); } return self; @@ -541,22 +575,17 @@ ossl_pkcs7_get_signer(VALUE self) { PKCS7 *pkcs7; STACK_OF(PKCS7_SIGNER_INFO) *sk; - PKCS7_SIGNER_INFO *si; int num, i; VALUE ary; GetPKCS7(self, pkcs7); - if (!(sk = PKCS7_get_signer_info(pkcs7))) { - OSSL_Debug("OpenSSL::PKCS7#get_signer_info == NULL!"); - return rb_ary_new(); - } - if ((num = sk_PKCS7_SIGNER_INFO_num(sk)) < 0) { - ossl_raise(ePKCS7Error, "Negative number of signers!"); - } - ary = rb_ary_new2(num); + if (!(sk = PKCS7_get_signer_info(pkcs7))) + return rb_ary_new(); + num = sk_PKCS7_SIGNER_INFO_num(sk); + ary = rb_ary_new_capa(num); for (i=0; i<num; i++) { - si = sk_PKCS7_SIGNER_INFO_value(sk, i); - rb_ary_push(ary, ossl_pkcs7si_new(si)); + PKCS7_SIGNER_INFO *si = sk_PKCS7_SIGNER_INFO_value(sk, i); + rb_ary_push(ary, ossl_pkcs7si_new(si)); } return ary; @@ -566,13 +595,18 @@ static VALUE ossl_pkcs7_add_recipient(VALUE self, VALUE recip) { PKCS7 *pkcs7; - PKCS7_RECIP_INFO *ri; + PKCS7_RECIP_INFO *ri, *ri_new; - ri = DupPKCS7RecipientPtr(recip); /* NEED TO DUP */ GetPKCS7(self, pkcs7); - if (!PKCS7_add_recipient_info(pkcs7, ri)) { - PKCS7_RECIP_INFO_free(ri); - ossl_raise(ePKCS7Error, "Could not add recipient."); + GetPKCS7ri(recip, ri); + + ri_new = ossl_PKCS7_RECIP_INFO_dup(ri); + if (!ri_new) + ossl_raise(ePKCS7Error, "PKCS7_RECIP_INFO_dup"); + + if (PKCS7_add_recipient_info(pkcs7, ri_new) != 1) { + PKCS7_RECIP_INFO_free(ri_new); + ossl_raise(ePKCS7Error, "PKCS7_add_recipient_info"); } return self; @@ -583,24 +617,21 @@ ossl_pkcs7_get_recipient(VALUE self) { PKCS7 *pkcs7; STACK_OF(PKCS7_RECIP_INFO) *sk; - PKCS7_RECIP_INFO *si; int num, i; VALUE ary; GetPKCS7(self, pkcs7); if (PKCS7_type_is_enveloped(pkcs7)) - sk = pkcs7->d.enveloped->recipientinfo; + sk = pkcs7->d.enveloped->recipientinfo; else if (PKCS7_type_is_signedAndEnveloped(pkcs7)) - sk = pkcs7->d.signed_and_enveloped->recipientinfo; + sk = pkcs7->d.signed_and_enveloped->recipientinfo; else sk = NULL; if (!sk) return rb_ary_new(); - if ((num = sk_PKCS7_RECIP_INFO_num(sk)) < 0) { - ossl_raise(ePKCS7Error, "Negative number of recipient!"); - } - ary = rb_ary_new2(num); + num = sk_PKCS7_RECIP_INFO_num(sk); + ary = rb_ary_new_capa(num); for (i=0; i<num; i++) { - si = sk_PKCS7_RECIP_INFO_value(sk, i); - rb_ary_push(ary, ossl_pkcs7ri_new(si)); + PKCS7_RECIP_INFO *ri = sk_PKCS7_RECIP_INFO_value(sk, i); + rb_ary_push(ary, ossl_pkcs7ri_new(ri)); } return ary; @@ -615,7 +646,7 @@ ossl_pkcs7_add_certificate(VALUE self, VALUE cert) GetPKCS7(self, pkcs7); x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ if (!PKCS7_add_certificate(pkcs7, x509)){ - ossl_raise(ePKCS7Error, NULL); + ossl_raise(ePKCS7Error, NULL); } return self; @@ -631,13 +662,13 @@ pkcs7_get_certs(VALUE self) GetPKCS7(self, pkcs7); i = OBJ_obj2nid(pkcs7->type); switch(i){ - case NID_pkcs7_signed: + case NID_pkcs7_signed: certs = pkcs7->d.sign->cert; break; - case NID_pkcs7_signedAndEnveloped: + case NID_pkcs7_signedAndEnveloped: certs = pkcs7->d.signed_and_enveloped->cert; break; - default: + default: certs = NULL; } @@ -654,13 +685,13 @@ pkcs7_get_crls(VALUE self) GetPKCS7(self, pkcs7); i = OBJ_obj2nid(pkcs7->type); switch(i){ - case NID_pkcs7_signed: + case NID_pkcs7_signed: crls = pkcs7->d.sign->crl; break; - case NID_pkcs7_signedAndEnveloped: + case NID_pkcs7_signedAndEnveloped: crls = pkcs7->d.signed_and_enveloped->crl; break; - default: + default: crls = NULL; } @@ -680,7 +711,10 @@ ossl_pkcs7_set_certificates(VALUE self, VALUE ary) X509 *cert; certs = pkcs7_get_certs(self); - while((cert = sk_X509_pop(certs))) X509_free(cert); + if (certs) { + while ((cert = sk_X509_pop(certs))) + X509_free(cert); + } rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_certs_i, self); return ary; @@ -689,7 +723,10 @@ ossl_pkcs7_set_certificates(VALUE self, VALUE ary) static VALUE ossl_pkcs7_get_certificates(VALUE self) { - return ossl_x509_sk2ary(pkcs7_get_certs(self)); + STACK_OF(X509) *certs = pkcs7_get_certs(self); + if (!certs) + return Qnil; + return ossl_x509_sk2ary(certs); } static VALUE @@ -701,7 +738,7 @@ ossl_pkcs7_add_crl(VALUE self, VALUE crl) GetPKCS7(self, pkcs7); /* NO DUP needed! */ x509crl = GetX509CRLPtr(crl); if (!PKCS7_add_crl(pkcs7, x509crl)) { - ossl_raise(ePKCS7Error, NULL); + ossl_raise(ePKCS7Error, NULL); } return self; @@ -720,7 +757,10 @@ ossl_pkcs7_set_crls(VALUE self, VALUE ary) X509_CRL *crl; crls = pkcs7_get_crls(self); - while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl); + if (crls) { + while ((crl = sk_X509_CRL_pop(crls))) + X509_CRL_free(crl); + } rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_crls_i, self); return ary; @@ -729,7 +769,10 @@ ossl_pkcs7_set_crls(VALUE self, VALUE ary) static VALUE ossl_pkcs7_get_crls(VALUE self) { - return ossl_x509crl_sk2ary(pkcs7_get_crls(self)); + STACK_OF(X509_CRL) *crls = pkcs7_get_crls(self); + if (!crls) + return Qnil; + return ossl_x509crl_sk2ary(crls); } static VALUE @@ -742,38 +785,39 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self) BIO *in, *out; PKCS7 *p7; VALUE data; - const char *msg; + GetPKCS7(self, p7); rb_scan_args(argc, argv, "22", &certs, &store, &indata, &flags); + x509st = GetX509StorePtr(store); flg = NIL_P(flags) ? 0 : NUM2INT(flags); if(NIL_P(indata)) indata = ossl_pkcs7_get_data(self); - in = NIL_P(indata) ? NULL : ossl_obj2bio(indata); + in = NIL_P(indata) ? NULL : ossl_obj2bio(&indata); if(NIL_P(certs)) x509s = NULL; else{ - x509s = ossl_protect_x509_ary2sk(certs, &status); - if(status){ - BIO_free(in); - rb_jump_tag(status); - } + x509s = ossl_protect_x509_ary2sk(certs, &status); + if(status){ + BIO_free(in); + rb_jump_tag(status); + } } - x509st = GetX509StorePtr(store); - GetPKCS7(self, p7); if(!(out = BIO_new(BIO_s_mem()))){ - BIO_free(in); - sk_X509_pop_free(x509s, X509_free); - ossl_raise(ePKCS7Error, NULL); + BIO_free(in); + sk_X509_pop_free(x509s, X509_free); + ossl_raise(ePKCS7Error, NULL); } ok = PKCS7_verify(p7, x509s, x509st, in, out, flg); BIO_free(in); - if (ok < 0) ossl_raise(ePKCS7Error, NULL); - msg = ERR_reason_error_string(ERR_get_error()); - ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil); - ERR_clear_error(); + sk_X509_pop_free(x509s, X509_free); data = ossl_membio2str(out); ossl_pkcs7_set_data(self, data); - sk_X509_pop_free(x509s, X509_free); - - return (ok == 1) ? Qtrue : Qfalse; + if (ok != 1) { + const char *msg = ERR_reason_error_string(ERR_peek_error()); + ossl_pkcs7_set_err_string(self, msg ? rb_str_new_cstr(msg) : Qnil); + ossl_clear_error(); + return Qfalse; + } + ossl_pkcs7_set_err_string(self, Qnil); + return Qtrue; } static VALUE @@ -787,16 +831,16 @@ ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self) BIO *out; VALUE str; - rb_scan_args(argc, argv, "21", &pkey, &cert, &flags); + rb_scan_args(argc, argv, "12", &pkey, &cert, &flags); key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */ - x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ + x509 = NIL_P(cert) ? NULL : GetX509CertPtr(cert); /* NO NEED TO DUP */ flg = NIL_P(flags) ? 0 : NUM2INT(flags); GetPKCS7(self, p7); if(!(out = BIO_new(BIO_s_mem()))) - ossl_raise(ePKCS7Error, NULL); + ossl_raise(ePKCS7Error, NULL); if(!PKCS7_decrypt(p7, key, x509, out, flg)){ - BIO_free(out); - ossl_raise(ePKCS7Error, NULL); + BIO_free(out); + ossl_raise(ePKCS7Error, NULL); } str = ossl_membio2str(out); /* out will be free */ @@ -809,30 +853,38 @@ ossl_pkcs7_add_data(VALUE self, VALUE data) PKCS7 *pkcs7; BIO *out, *in; char buf[4096]; - int len; + int len, ret; - in = ossl_obj2bio(data); GetPKCS7(self, pkcs7); - if(PKCS7_type_is_signed(pkcs7)){ - if(!PKCS7_content_new(pkcs7, NID_pkcs7_data)) - ossl_raise(ePKCS7Error, NULL); + if (PKCS7_type_is_signed(pkcs7)) { + if (!PKCS7_content_new(pkcs7, NID_pkcs7_data)) + ossl_raise(ePKCS7Error, "PKCS7_content_new"); + } + in = ossl_obj2bio(&data); + if (!(out = PKCS7_dataInit(pkcs7, NULL))) { + BIO_free(in); + ossl_raise(ePKCS7Error, "PKCS7_dataInit"); } - if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err; - for(;;){ - if((len = BIO_read(in, buf, sizeof(buf))) <= 0) - break; - if(BIO_write(out, buf, len) != len) - goto err; + for (;;) { + if ((len = BIO_read(in, buf, sizeof(buf))) <= 0) + break; + if (BIO_write(out, buf, len) != len) { + BIO_free_all(out); + BIO_free(in); + ossl_raise(ePKCS7Error, "BIO_write"); + } } - if(!PKCS7_dataFinal(pkcs7, out)) goto err; - ossl_pkcs7_set_data(self, Qnil); - - err: - BIO_free(out); - BIO_free(in); - if(ERR_peek_error()){ - ossl_raise(ePKCS7Error, NULL); + if (BIO_flush(out) <= 0) { + BIO_free_all(out); + BIO_free(in); + ossl_raise(ePKCS7Error, "BIO_flush"); } + ret = PKCS7_dataFinal(pkcs7, out); + BIO_free_all(out); + BIO_free(in); + if (!ret) + ossl_raise(ePKCS7Error, "PKCS7_dataFinal"); + ossl_pkcs7_set_data(self, Qnil); return data; } @@ -847,17 +899,36 @@ ossl_pkcs7_to_der(VALUE self) GetPKCS7(self, pkcs7); if((len = i2d_PKCS7(pkcs7, NULL)) <= 0) - ossl_raise(ePKCS7Error, NULL); + ossl_raise(ePKCS7Error, NULL); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); if(i2d_PKCS7(pkcs7, &p) <= 0) - ossl_raise(ePKCS7Error, NULL); + ossl_raise(ePKCS7Error, NULL); ossl_str_adjust(str, p); return str; } static VALUE +ossl_pkcs7_to_text(VALUE self) +{ + PKCS7 *pkcs7; + BIO *out; + VALUE str; + + GetPKCS7(self, pkcs7); + if(!(out = BIO_new(BIO_s_mem()))) + ossl_raise(ePKCS7Error, NULL); + if(!PKCS7_print_ctx(out, pkcs7, 0, NULL)) { + BIO_free(out); + ossl_raise(ePKCS7Error, NULL); + } + str = ossl_membio2str(out); + + return str; +} + +static VALUE ossl_pkcs7_to_pem(VALUE self) { PKCS7 *pkcs7; @@ -866,11 +937,11 @@ ossl_pkcs7_to_pem(VALUE self) GetPKCS7(self, pkcs7); if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(ePKCS7Error, NULL); + ossl_raise(ePKCS7Error, NULL); } if (!PEM_write_bio_PKCS7(out, pkcs7)) { - BIO_free(out); - ossl_raise(ePKCS7Error, NULL); + BIO_free(out); + ossl_raise(ePKCS7Error, NULL); } str = ossl_membio2str(out); @@ -886,10 +957,11 @@ ossl_pkcs7si_alloc(VALUE klass) PKCS7_SIGNER_INFO *p7si; VALUE obj; + obj = NewPKCS7si(klass); if (!(p7si = PKCS7_SIGNER_INFO_new())) { - ossl_raise(ePKCS7Error, NULL); + ossl_raise(ePKCS7Error, NULL); } - WrapPKCS7si(klass, obj, p7si); + SetPKCS7si(obj, p7si); return obj; } @@ -901,14 +973,15 @@ ossl_pkcs7si_initialize(VALUE self, VALUE cert, VALUE key, VALUE digest) EVP_PKEY *pkey; X509 *x509; const EVP_MD *md; + VALUE md_holder; pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ - md = GetDigestPtr(digest); + md = ossl_evp_md_fetch(digest, &md_holder); GetPKCS7si(self, p7si); - if (!(PKCS7_SIGNER_INFO_set(p7si, x509, pkey, (EVP_MD*)md))) { - ossl_raise(ePKCS7Error, NULL); - } + if (!(PKCS7_SIGNER_INFO_set(p7si, x509, pkey, md))) + ossl_raise(ePKCS7Error, "PKCS7_SIGNER_INFO_set"); + rb_ivar_set(self, id_md_holder, md_holder); return self; } @@ -942,10 +1015,10 @@ ossl_pkcs7si_get_signed_time(VALUE self) GetPKCS7si(self, p7si); if (!(asn1obj = PKCS7_get_signed_attribute(p7si, NID_pkcs9_signingTime))) { - ossl_raise(ePKCS7Error, NULL); + ossl_raise(ePKCS7Error, NULL); } if (asn1obj->type == V_ASN1_UTCTIME) { - return asn1time_to_time(asn1obj->value.utctime); + return asn1time_to_time(asn1obj->value.utctime); } /* * OR @@ -965,10 +1038,11 @@ ossl_pkcs7ri_alloc(VALUE klass) PKCS7_RECIP_INFO *p7ri; VALUE obj; + obj = NewPKCS7ri(klass); if (!(p7ri = PKCS7_RECIP_INFO_new())) { - ossl_raise(ePKCS7Error, NULL); + ossl_raise(ePKCS7Error, NULL); } - WrapPKCS7ri(klass, obj, p7ri); + SetPKCS7ri(obj, p7ri); return obj; } @@ -982,7 +1056,7 @@ ossl_pkcs7ri_initialize(VALUE self, VALUE cert) x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ GetPKCS7ri(self, p7ri); if (!PKCS7_RECIP_INFO_set(p7ri, x509)) { - ossl_raise(ePKCS7Error, NULL); + ossl_raise(ePKCS7Error, NULL); } return self; @@ -1024,6 +1098,7 @@ ossl_pkcs7ri_get_enc_key(VALUE self) void Init_ossl_pkcs7(void) { +#undef rb_intern cPKCS7 = rb_define_class_under(mOSSL, "PKCS7", rb_cObject); ePKCS7Error = rb_define_class_under(cPKCS7, "PKCS7Error", eOSSLError); rb_define_singleton_method(cPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1); @@ -1033,7 +1108,7 @@ Init_ossl_pkcs7(void) rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse); rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse); rb_define_alloc_func(cPKCS7, ossl_pkcs7_alloc); - rb_define_copy_func(cPKCS7, ossl_pkcs7_copy); + rb_define_method(cPKCS7, "initialize_copy", ossl_pkcs7_copy, 1); rb_define_method(cPKCS7, "initialize", ossl_pkcs7_initialize, -1); rb_define_method(cPKCS7, "type=", ossl_pkcs7_set_type, 1); rb_define_method(cPKCS7, "type", ossl_pkcs7_get_type, 0); @@ -1058,13 +1133,13 @@ Init_ossl_pkcs7(void) rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0); rb_define_alias(cPKCS7, "to_s", "to_pem"); rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0); + rb_define_method(cPKCS7, "to_text", ossl_pkcs7_to_text, 0); cPKCS7Signer = rb_define_class_under(cPKCS7, "SignerInfo", rb_cObject); rb_define_const(cPKCS7, "Signer", cPKCS7Signer); rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc); rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3); rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0); - rb_define_alias(cPKCS7Signer, "name", "issuer"); rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0); rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0); @@ -1087,4 +1162,7 @@ Init_ossl_pkcs7(void) DefPKCS7Const(BINARY); DefPKCS7Const(NOATTR); DefPKCS7Const(NOSMIMECAP); + + id_md_holder = rb_intern_const("EVP_MD_holder"); + id_cipher_holder = rb_intern_const("EVP_CIPHER_holder"); } diff --git a/ext/openssl/ossl_pkcs7.h b/ext/openssl/ossl_pkcs7.h index 371c421103..140fda1835 100644 --- a/ext/openssl/ossl_pkcs7.h +++ b/ext/openssl/ossl_pkcs7.h @@ -1,22 +1,16 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(_OSSL_PKCS7_H_) #define _OSSL_PKCS7_H_ -extern VALUE cPKCS7; -extern VALUE cPKCS7Signer; -extern VALUE cPKCS7Recipient; -extern VALUE ePKCS7Error; - +VALUE ossl_pkcs7_new(PKCS7 *p7); void Init_ossl_pkcs7(void); #endif /* _OSSL_PKCS7_H_ */ - diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index aa9b046d38..d2fd5b29c3 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -1,73 +1,25 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" +#ifdef OSSL_USE_ENGINE +# include <openssl/engine.h> +#endif + /* * Classes */ VALUE mPKey; VALUE cPKey; VALUE ePKeyError; -ID id_private_q; - -/* - * callback for generating keys - */ -void -ossl_generate_cb(int p, int n, void *arg) -{ - VALUE ary; - - ary = rb_ary_new2(2); - rb_ary_store(ary, 0, INT2NUM(p)); - rb_ary_store(ary, 1, INT2NUM(n)); - - rb_yield(ary); -} - -#if HAVE_BN_GENCB -/* OpenSSL 2nd version of GN generation callback */ -int -ossl_generate_cb_2(int p, int n, BN_GENCB *cb) -{ - VALUE ary; - struct ossl_generate_cb_arg *arg; - int state; - - arg = (struct ossl_generate_cb_arg *)cb->arg; - if (arg->yield) { - ary = rb_ary_new2(2); - rb_ary_store(ary, 0, INT2NUM(p)); - rb_ary_store(ary, 1, INT2NUM(n)); - - /* - * can be break by raising exception or 'break' - */ - rb_protect(rb_yield, ary, &state); - if (state) { - arg->stop = 1; - arg->state = state; - } - } - if (arg->stop) return 0; - return 1; -} - -void -ossl_generate_cb_stop(void *ptr) -{ - struct ossl_generate_cb_arg *arg = (struct ossl_generate_cb_arg *)ptr; - arg->stop = 1; -} -#endif +static ID id_private_q; static void ossl_evp_pkey_free(void *ptr) @@ -81,153 +33,559 @@ ossl_evp_pkey_free(void *ptr) const rb_data_type_t ossl_evp_pkey_type = { "OpenSSL/EVP_PKEY", { - 0, ossl_evp_pkey_free, + 0, ossl_evp_pkey_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; -VALUE -ossl_pkey_new(EVP_PKEY *pkey) +static VALUE +pkey_wrap0(VALUE arg) { - if (!pkey) { - ossl_raise(ePKeyError, "Cannot make new key from NULL."); - } - switch (EVP_PKEY_type(pkey->type)) { + EVP_PKEY *pkey = (EVP_PKEY *)arg; + VALUE klass, obj; + + switch (EVP_PKEY_base_id(pkey)) { #if !defined(OPENSSL_NO_RSA) - case EVP_PKEY_RSA: - return ossl_rsa_new(pkey); + case EVP_PKEY_RSA: klass = cRSA; break; #endif #if !defined(OPENSSL_NO_DSA) - case EVP_PKEY_DSA: - return ossl_dsa_new(pkey); + case EVP_PKEY_DSA: klass = cDSA; break; #endif #if !defined(OPENSSL_NO_DH) - case EVP_PKEY_DH: - return ossl_dh_new(pkey); + case EVP_PKEY_DH: klass = cDH; break; #endif -#if !defined(OPENSSL_NO_EC) && (OPENSSL_VERSION_NUMBER >= 0x0090802fL) - case EVP_PKEY_EC: - return ossl_ec_new(pkey); +#if !defined(OPENSSL_NO_EC) + case EVP_PKEY_EC: klass = cEC; break; #endif - default: - ossl_raise(ePKeyError, "unsupported key type"); + default: klass = cPKey; break; } - - UNREACHABLE; + obj = rb_obj_alloc(klass); + RTYPEDDATA_DATA(obj) = pkey; + return obj; } VALUE -ossl_pkey_new_from_file(VALUE filename) +ossl_pkey_wrap(EVP_PKEY *pkey) { - FILE *fp; - EVP_PKEY *pkey; + VALUE obj; + int status; - SafeStringValue(filename); - if (!(fp = fopen(RSTRING_PTR(filename), "r"))) { - ossl_raise(ePKeyError, "%s", strerror(errno)); + obj = rb_protect(pkey_wrap0, (VALUE)pkey, &status); + if (status) { + EVP_PKEY_free(pkey); + rb_jump_tag(status); } - rb_fd_fix_cloexec(fileno(fp)); - pkey = PEM_read_PrivateKey(fp, NULL, ossl_pem_passwd_cb, NULL); - fclose(fp); - if (!pkey) { - ossl_raise(ePKeyError, NULL); + return obj; +} + +#if OSSL_OPENSSL_PREREQ(3, 0, 0) +# include <openssl/decoder.h> + +static EVP_PKEY * +ossl_pkey_read(BIO *bio, const char *input_type, int selection, VALUE pass) +{ + void *ppass = (void *)pass; + OSSL_DECODER_CTX *dctx; + EVP_PKEY *pkey = NULL; + int pos = 0, pos2; + + dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, input_type, NULL, NULL, + selection, NULL, NULL); + if (!dctx) + goto out; + if (selection == EVP_PKEY_KEYPAIR && + OSSL_DECODER_CTX_set_pem_password_cb(dctx, ossl_pem_passwd_cb, + ppass) != 1) + goto out; + while (1) { + if (OSSL_DECODER_from_bio(dctx, bio) == 1) + goto out; + if (BIO_eof(bio)) + break; + pos2 = BIO_tell(bio); + if (pos2 < 0 || pos2 <= pos) + break; + ossl_clear_error(); + pos = pos2; } + out: + OSSL_BIO_reset(bio); + OSSL_DECODER_CTX_free(dctx); + return pkey; +} - return ossl_pkey_new(pkey); +EVP_PKEY * +ossl_pkey_read_generic(BIO *bio, VALUE pass) +{ + EVP_PKEY *pkey = NULL; + /* First check DER, then check PEM. */ + const char *input_types[] = {"DER", "PEM"}; + int input_type_num = (int)(sizeof(input_types) / sizeof(char *)); + /* + * Non-zero selections to try to decode. + * + * See EVP_PKEY_fromdata(3) - Selections to see all the selections. + * + * This is a workaround for the decoder failing to decode or returning + * bogus keys with selection 0, if a key management provider is different + * from a decoder provider. The workaround is to avoid using selection 0. + * + * Affected OpenSSL versions: >= 3.1.0, <= 3.1.2, or >= 3.0.0, <= 3.0.10 + * Fixed OpenSSL versions: 3.2, next release of the 3.1.z and 3.0.z + * + * See https://github.com/openssl/openssl/pull/21519 for details. + * + * First check for private key formats (EVP_PKEY_KEYPAIR). This is to keep + * compatibility with ruby/openssl < 3.0 which decoded the following as a + * private key. + * + * $ openssl ecparam -name prime256v1 -genkey -outform PEM + * -----BEGIN EC PARAMETERS----- + * BggqhkjOPQMBBw== + * -----END EC PARAMETERS----- + * -----BEGIN EC PRIVATE KEY----- + * MHcCAQEEIAG8ugBbA5MHkqnZ9ujQF93OyUfL9tk8sxqM5Wv5tKg5oAoGCCqGSM49 + * AwEHoUQDQgAEVcjhJfkwqh5C7kGuhAf8XaAjVuG5ADwb5ayg/cJijCgs+GcXeedj + * 86avKpGH84DXUlB23C/kPt+6fXYlitUmXQ== + * -----END EC PRIVATE KEY----- + * + * While the first PEM block is a proper encoding of ECParameters, thus + * OSSL_DECODER_from_bio() would pick it up, ruby/openssl used to return + * the latter instead. Existing applications expect this behavior. + * + * Note that normally, the input is supposed to contain a single decodable + * PEM block only, so this special handling should not create a new problem. + * + * Note that we need to create the OSSL_DECODER_CTX variable each time when + * we use the different selection as a workaround. + * See https://github.com/openssl/openssl/issues/20657 for details. + */ + int selections[] = { + EVP_PKEY_KEYPAIR, + EVP_PKEY_KEY_PARAMETERS, + EVP_PKEY_PUBLIC_KEY + }; + int selection_num = (int)(sizeof(selections) / sizeof(int)); + int i, j; + + for (i = 0; i < input_type_num; i++) { + for (j = 0; j < selection_num; j++) { + pkey = ossl_pkey_read(bio, input_types[i], selections[j], pass); + if (pkey) { + goto out; + } + } + } + out: + return pkey; +} +#else +EVP_PKEY * +ossl_pkey_read_generic(BIO *bio, VALUE pass) +{ + void *ppass = (void *)pass; + EVP_PKEY *pkey; + + if ((pkey = d2i_PrivateKey_bio(bio, NULL))) + goto out; + OSSL_BIO_reset(bio); + if ((pkey = d2i_PKCS8PrivateKey_bio(bio, NULL, ossl_pem_passwd_cb, ppass))) + goto out; + OSSL_BIO_reset(bio); + if ((pkey = d2i_PUBKEY_bio(bio, NULL))) + goto out; + OSSL_BIO_reset(bio); + /* PEM_read_bio_PrivateKey() also parses PKCS #8 formats */ + if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, ppass))) + goto out; + OSSL_BIO_reset(bio); + if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL))) + goto out; + OSSL_BIO_reset(bio); + if ((pkey = PEM_read_bio_Parameters(bio, NULL))) + goto out; + + out: + return pkey; } +#endif /* * call-seq: - * OpenSSL::PKey.read(string [, pwd ] ) -> PKey - * OpenSSL::PKey.read(file [, pwd ]) -> PKey + * OpenSSL::PKey.read(string [, pwd ]) -> PKey + * OpenSSL::PKey.read(io [, pwd ]) -> PKey + * + * Reads a DER or PEM encoded string from _string_ or _io_ and returns an + * instance of the appropriate PKey class. * * === Parameters - * * +string+ is a DER- or PEM-encoded string containing an arbitrary private - * or public key. - * * +file+ is an instance of +File+ containing a DER- or PEM-encoded - * arbitrary private or public key. - * * +pwd+ is an optional password in case +string+ or +file+ is an encrypted - * PEM resource. + * * _string_ is a DER- or PEM-encoded string containing an arbitrary private + * or public key. + * * _io_ is an instance of IO containing a DER- or PEM-encoded + * arbitrary private or public key. + * * _pwd_ is an optional password in case _string_ or _io_ is an encrypted + * PEM resource. */ static VALUE ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self) { - EVP_PKEY *pkey; - BIO *bio; - VALUE data, pass; - char *passwd = NULL; - - rb_scan_args(argc, argv, "11", &data, &pass); - - bio = ossl_obj2bio(data); - if (!(pkey = d2i_PrivateKey_bio(bio, NULL))) { - OSSL_BIO_reset(bio); - if (!NIL_P(pass)) { - passwd = StringValuePtr(pass); - } - if (!(pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, passwd))) { - OSSL_BIO_reset(bio); - if (!(pkey = d2i_PUBKEY_bio(bio, NULL))) { - OSSL_BIO_reset(bio); - if (!NIL_P(pass)) { - passwd = StringValuePtr(pass); - } - pkey = PEM_read_bio_PUBKEY(bio, NULL, ossl_pem_passwd_cb, passwd); - } - } - } + EVP_PKEY *pkey; + BIO *bio; + VALUE data, pass; + rb_scan_args(argc, argv, "11", &data, &pass); + bio = ossl_obj2bio(&data); + pkey = ossl_pkey_read_generic(bio, ossl_pem_passwd_value(pass)); BIO_free(bio); if (!pkey) - ossl_raise(rb_eArgError, "Could not parse PKey"); - return ossl_pkey_new(pkey); + ossl_raise(ePKeyError, "Could not parse PKey"); + return ossl_pkey_wrap(pkey); } -EVP_PKEY * -GetPKeyPtr(VALUE obj) +static VALUE +pkey_ctx_apply_options_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ctx_v)) { + VALUE key = rb_ary_entry(i, 0), value = rb_ary_entry(i, 1); + EVP_PKEY_CTX *ctx = (EVP_PKEY_CTX *)ctx_v; + + if (SYMBOL_P(key)) + key = rb_sym2str(key); + value = rb_String(value); + + if (EVP_PKEY_CTX_ctrl_str(ctx, StringValueCStr(key), StringValueCStr(value)) <= 0) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_ctrl_str(ctx, %+"PRIsVALUE", %+"PRIsVALUE")", + key, value); + return Qnil; +} + +static VALUE +pkey_ctx_apply_options0(VALUE args_v) +{ + VALUE *args = (VALUE *)args_v; + Check_Type(args[1], T_HASH); + + rb_block_call(args[1], rb_intern("each"), 0, NULL, + pkey_ctx_apply_options_i, args[0]); + return Qnil; +} + +static void +pkey_ctx_apply_options(EVP_PKEY_CTX *ctx, VALUE options, int *state) +{ + VALUE args[2]; + args[0] = (VALUE)ctx; + args[1] = options; + + rb_protect(pkey_ctx_apply_options0, (VALUE)args, state); +} + +struct pkey_blocking_generate_arg { + EVP_PKEY_CTX *ctx; EVP_PKEY *pkey; + int state; + unsigned int yield: 1; + unsigned int genparam: 1; + unsigned int interrupted: 1; +}; - SafeGetPKey(obj, pkey); +static VALUE +pkey_gen_cb_yield(VALUE ctx_v) +{ + EVP_PKEY_CTX *ctx = (void *)ctx_v; + int i, info_num; + VALUE *argv; - return pkey; + info_num = EVP_PKEY_CTX_get_keygen_info(ctx, -1); + argv = ALLOCA_N(VALUE, info_num); + for (i = 0; i < info_num; i++) + argv[i] = INT2NUM(EVP_PKEY_CTX_get_keygen_info(ctx, i)); + + return rb_yield_values2(info_num, argv); +} + +static VALUE +call_check_ints0(VALUE arg) +{ + rb_thread_check_ints(); + return Qnil; +} + +static void * +call_check_ints(void *arg) +{ + int state; + rb_protect(call_check_ints0, Qnil, &state); + return (void *)(VALUE)state; +} + +static int +pkey_gen_cb(EVP_PKEY_CTX *ctx) +{ + struct pkey_blocking_generate_arg *arg = EVP_PKEY_CTX_get_app_data(ctx); + int state; + + if (arg->yield) { + rb_protect(pkey_gen_cb_yield, (VALUE)ctx, &state); + if (state) { + arg->state = state; + return 0; + } + } + if (arg->interrupted) { + arg->interrupted = 0; + state = (int)(VALUE)rb_thread_call_with_gvl(call_check_ints, NULL); + if (state) { + arg->state = state; + return 0; + } + } + return 1; +} + +static void +pkey_blocking_gen_stop(void *ptr) +{ + struct pkey_blocking_generate_arg *arg = ptr; + arg->interrupted = 1; +} + +static void * +pkey_blocking_gen(void *ptr) +{ + struct pkey_blocking_generate_arg *arg = ptr; + + if (arg->genparam && EVP_PKEY_paramgen(arg->ctx, &arg->pkey) <= 0) + return NULL; + if (!arg->genparam && EVP_PKEY_keygen(arg->ctx, &arg->pkey) <= 0) + return NULL; + return arg->pkey; +} + +static VALUE +pkey_generate(int argc, VALUE *argv, VALUE self, int genparam) +{ + EVP_PKEY_CTX *ctx; + VALUE alg, options; + struct pkey_blocking_generate_arg gen_arg = { 0 }; + int state; + + rb_scan_args(argc, argv, "11", &alg, &options); + if (rb_obj_is_kind_of(alg, cPKey)) { + EVP_PKEY *base_pkey; + + GetPKey(alg, base_pkey); + ctx = EVP_PKEY_CTX_new(base_pkey, NULL/* engine */); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + } + else { +#if OSSL_OPENSSL_PREREQ(3, 0, 0) + ctx = EVP_PKEY_CTX_new_from_name(NULL, StringValueCStr(alg), NULL); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_from_name"); +#else + const EVP_PKEY_ASN1_METHOD *ameth; + ENGINE *tmpeng; + int pkey_id; + + StringValue(alg); + ameth = EVP_PKEY_asn1_find_str(&tmpeng, RSTRING_PTR(alg), + RSTRING_LENINT(alg)); + if (!ameth) + ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", alg); + EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth); +#if !defined(OPENSSL_NO_ENGINE) + if (tmpeng) + ENGINE_finish(tmpeng); +#endif + + ctx = EVP_PKEY_CTX_new_id(pkey_id, NULL/* engine */); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_id"); +#endif + } + + if (genparam && EVP_PKEY_paramgen_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_paramgen_init"); + } + if (!genparam && EVP_PKEY_keygen_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_keygen_init"); + } + + if (!NIL_P(options)) { + pkey_ctx_apply_options(ctx, options, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + } + + gen_arg.genparam = genparam; + gen_arg.ctx = ctx; + gen_arg.yield = rb_block_given_p(); + EVP_PKEY_CTX_set_app_data(ctx, &gen_arg); + EVP_PKEY_CTX_set_cb(ctx, pkey_gen_cb); + if (gen_arg.yield) + pkey_blocking_gen(&gen_arg); + else + rb_thread_call_without_gvl(pkey_blocking_gen, &gen_arg, + pkey_blocking_gen_stop, &gen_arg); + EVP_PKEY_CTX_free(ctx); + if (!gen_arg.pkey) { + if (gen_arg.state) { + ossl_clear_error(); + rb_jump_tag(gen_arg.state); + } + else { + ossl_raise(ePKeyError, genparam ? "EVP_PKEY_paramgen" : "EVP_PKEY_keygen"); + } + } + + return ossl_pkey_wrap(gen_arg.pkey); +} + +/* + * call-seq: + * OpenSSL::PKey.generate_parameters(algo_name [, options]) -> pkey + * + * Generates new parameters for the algorithm. _algo_name_ is a String that + * represents the algorithm. The optional argument _options_ is a Hash that + * specifies the options specific to the algorithm. The order of the options + * can be important. + * + * A block can be passed optionally. The meaning of the arguments passed to + * the block varies depending on the implementation of the algorithm. The block + * may be called once or multiple times, or may not even be called. + * + * For the supported options, see the documentation for the 'openssl genpkey' + * utility command. + * + * == Example + * pkey = OpenSSL::PKey.generate_parameters("DSA", "dsa_paramgen_bits" => 2048) + * p pkey.p.num_bits #=> 2048 + */ +static VALUE +ossl_pkey_s_generate_parameters(int argc, VALUE *argv, VALUE self) +{ + return pkey_generate(argc, argv, self, 1); +} + +/* + * call-seq: + * OpenSSL::PKey.generate_key(algo_name [, options]) -> pkey + * OpenSSL::PKey.generate_key(pkey [, options]) -> pkey + * + * Generates a new key (pair). + * + * If a String is given as the first argument, it generates a new random key + * for the algorithm specified by the name just as ::generate_parameters does. + * If an OpenSSL::PKey::PKey is given instead, it generates a new random key + * for the same algorithm as the key, using the parameters the key contains. + * + * See ::generate_parameters for the details of _options_ and the given block. + * + * == Example + * pkey_params = OpenSSL::PKey.generate_parameters("DSA", "dsa_paramgen_bits" => 2048) + * pkey_params.priv_key #=> nil + * pkey = OpenSSL::PKey.generate_key(pkey_params) + * pkey.priv_key #=> #<OpenSSL::BN 6277... + */ +static VALUE +ossl_pkey_s_generate_key(int argc, VALUE *argv, VALUE self) +{ + return pkey_generate(argc, argv, self, 0); +} + +/* + * TODO: There is no convenient way to check the presence of public key + * components on OpenSSL 3.0. But since keys are immutable on 3.0, pkeys without + * these should only be created by OpenSSL::PKey.generate_parameters or by + * parsing DER-/PEM-encoded string. We would need another flag for that. + */ +void +ossl_pkey_check_public_key(const EVP_PKEY *pkey) +{ +#ifdef OSSL_HAVE_IMMUTABLE_PKEY + if (EVP_PKEY_missing_parameters(pkey)) + ossl_raise(ePKeyError, "parameters missing"); +#else + void *ptr; + const BIGNUM *n, *e, *pubkey; + + if (EVP_PKEY_missing_parameters(pkey)) + ossl_raise(ePKeyError, "parameters missing"); + + ptr = EVP_PKEY_get0(pkey); + switch (EVP_PKEY_base_id(pkey)) { + case EVP_PKEY_RSA: + RSA_get0_key(ptr, &n, &e, NULL); + if (n && e) + return; + break; + case EVP_PKEY_DSA: + DSA_get0_key(ptr, &pubkey, NULL); + if (pubkey) + return; + break; + case EVP_PKEY_DH: + DH_get0_key(ptr, &pubkey, NULL); + if (pubkey) + return; + break; +#if !defined(OPENSSL_NO_EC) + case EVP_PKEY_EC: + if (EC_KEY_get0_public_key(ptr)) + return; + break; +#endif + default: + /* unsupported type; assuming ok */ + return; + } + ossl_raise(ePKeyError, "public key missing"); +#endif } EVP_PKEY * -GetPrivPKeyPtr(VALUE obj) +GetPKeyPtr(VALUE obj) { EVP_PKEY *pkey; - if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) { - ossl_raise(rb_eArgError, "Private key is needed."); - } - SafeGetPKey(obj, pkey); + GetPKey(obj, pkey); return pkey; } EVP_PKEY * -DupPKeyPtr(VALUE obj) +GetPrivPKeyPtr(VALUE obj) { EVP_PKEY *pkey; - SafeGetPKey(obj, pkey); - CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); + GetPKey(obj, pkey); + if (OSSL_PKEY_IS_PRIVATE(obj)) + return pkey; + /* + * The EVP API does not provide a way to check if the EVP_PKEY has private + * components. Assuming it does... + */ + if (!rb_respond_to(obj, id_private_q)) + return pkey; + if (RTEST(rb_funcallv(obj, id_private_q, 0, NULL))) + return pkey; - return pkey; + rb_raise(rb_eArgError, "private key is needed"); } EVP_PKEY * -DupPrivPKeyPtr(VALUE obj) +DupPKeyPtr(VALUE obj) { EVP_PKEY *pkey; - if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) { - ossl_raise(rb_eArgError, "Private key is needed."); - } - SafeGetPKey(obj, pkey); - CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); + GetPKey(obj, pkey); + EVP_PKEY_up_ref(pkey); return pkey; } @@ -238,15 +596,7 @@ DupPrivPKeyPtr(VALUE obj) static VALUE ossl_pkey_alloc(VALUE klass) { - EVP_PKEY *pkey; - VALUE obj; - - if (!(pkey = EVP_PKEY_new())) { - ossl_raise(ePKeyError, NULL); - } - WrapPKey(klass, obj, pkey); - - return obj; + return TypedData_Wrap_Struct(klass, &ossl_evp_pkey_type, NULL); } /* @@ -254,102 +604,1051 @@ ossl_pkey_alloc(VALUE klass) * PKeyClass.new -> self * * Because PKey is an abstract class, actually calling this method explicitly - * will raise a +NotImplementedError+. + * will raise a NotImplementedError. */ static VALUE ossl_pkey_initialize(VALUE self) { if (rb_obj_is_instance_of(self, cPKey)) { - ossl_raise(rb_eNotImpError, "OpenSSL::PKey::PKey is an abstract class."); + ossl_raise(rb_eTypeError, "OpenSSL::PKey::PKey can't be instantiated directly"); } return self; } +#ifdef HAVE_EVP_PKEY_DUP +/* :nodoc: */ +static VALUE +ossl_pkey_initialize_copy(VALUE self, VALUE other) +{ + EVP_PKEY *pkey, *pkey_other; + + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + TypedData_Get_Struct(other, EVP_PKEY, &ossl_evp_pkey_type, pkey_other); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); + if (pkey_other) { + pkey = EVP_PKEY_dup(pkey_other); + if (!pkey) + ossl_raise(ePKeyError, "EVP_PKEY_dup"); + RTYPEDDATA_DATA(self) = pkey; + } + return self; +} +#endif + +#ifndef OSSL_USE_PROVIDER +static int +lookup_pkey_type(VALUE type) +{ + const EVP_PKEY_ASN1_METHOD *ameth; + int pkey_id; + + StringValue(type); + /* + * XXX: EVP_PKEY_asn1_find_str() looks up a PEM type string. Should we use + * OBJ_txt2nid() instead (and then somehow check if the NID is an acceptable + * EVP_PKEY type)? + * It is probably fine, though, since it can handle all algorithms that + * support raw keys in 1.1.1: { X25519, X448, ED25519, ED448, HMAC }. + */ + ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type)); + if (!ameth) + ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type); + EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth); + return pkey_id; +} +#endif + +/* + * call-seq: + * OpenSSL::PKey.new_raw_private_key(algo, string) -> PKey + * + * See the OpenSSL documentation for EVP_PKEY_new_raw_private_key() + */ + +static VALUE +ossl_pkey_new_raw_private_key(VALUE self, VALUE type, VALUE key) +{ + EVP_PKEY *pkey; + size_t keylen; + + StringValue(key); + keylen = RSTRING_LEN(key); + +#ifdef OSSL_USE_PROVIDER + pkey = EVP_PKEY_new_raw_private_key_ex(NULL, StringValueCStr(type), NULL, + (unsigned char *)RSTRING_PTR(key), + keylen); + if (!pkey) + ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key_ex"); +#else + int pkey_id = lookup_pkey_type(type); + pkey = EVP_PKEY_new_raw_private_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen); + if (!pkey) + ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key"); +#endif + + return ossl_pkey_wrap(pkey); +} + /* * call-seq: - * pkey.sign(digest, data) -> String + * OpenSSL::PKey.new_raw_public_key(algo, string) -> PKey * - * To sign the +String+ +data+, +digest+, an instance of OpenSSL::Digest, must - * be provided. The return value is again a +String+ containing the signature. - * A PKeyError is raised should errors occur. - * Any previous state of the +Digest+ instance is irrelevant to the signature - * outcome, the digest instance is reset to its initial state during the - * operation. + * See the OpenSSL documentation for EVP_PKEY_new_raw_public_key() + */ + +static VALUE +ossl_pkey_new_raw_public_key(VALUE self, VALUE type, VALUE key) +{ + EVP_PKEY *pkey; + size_t keylen; + + StringValue(key); + keylen = RSTRING_LEN(key); + +#ifdef OSSL_USE_PROVIDER + pkey = EVP_PKEY_new_raw_public_key_ex(NULL, StringValueCStr(type), NULL, + (unsigned char *)RSTRING_PTR(key), + keylen); + if (!pkey) + ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key_ex"); +#else + int pkey_id = lookup_pkey_type(type); + pkey = EVP_PKEY_new_raw_public_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen); + if (!pkey) + ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key"); +#endif + + return ossl_pkey_wrap(pkey); +} + +/* + * call-seq: + * pkey.oid -> string * - * == Example - * data = 'Sign me!' - * digest = OpenSSL::Digest::SHA256.new - * pkey = OpenSSL::PKey::RSA.new(2048) - * signature = pkey.sign(digest, data) + * Returns the short name of the OID associated with _pkey_. + */ +static VALUE +ossl_pkey_oid(VALUE self) +{ + EVP_PKEY *pkey; + int nid; + + GetPKey(self, pkey); + nid = EVP_PKEY_id(pkey); +#ifdef OSSL_USE_PROVIDER + if (nid == EVP_PKEY_KEYMGMT) + ossl_raise(ePKeyError, "EVP_PKEY_id"); +#endif + return rb_str_new_cstr(OBJ_nid2sn(nid)); +} + +/* + * call-seq: + * pkey.inspect -> string + * + * Returns a string describing the PKey object. + */ +static VALUE +ossl_pkey_inspect(VALUE self) +{ + EVP_PKEY *pkey; + + GetPKey(self, pkey); + VALUE str = rb_sprintf("#<%"PRIsVALUE":%p", + rb_obj_class(self), (void *)self); + int nid = EVP_PKEY_id(pkey); +#ifdef OSSL_USE_PROVIDER + if (nid != EVP_PKEY_KEYMGMT) +#endif + rb_str_catf(str, " oid=%s", OBJ_nid2sn(nid)); +#ifdef OSSL_USE_PROVIDER + rb_str_catf(str, " type_name=%s", EVP_PKEY_get0_type_name(pkey)); + const OSSL_PROVIDER *prov = EVP_PKEY_get0_provider(pkey); + if (prov) + rb_str_catf(str, " provider=%s", OSSL_PROVIDER_get0_name(prov)); +#endif + rb_str_catf(str, ">"); + return str; +} + +/* + * call-seq: + * pkey.to_text -> string + * + * Dumps key parameters, public key, and private key components contained in + * the key into a human-readable text. + * + * This is intended for debugging purpose. + * + * See also the man page EVP_PKEY_print_private(3). + */ +static VALUE +ossl_pkey_to_text(VALUE self) +{ + EVP_PKEY *pkey; + BIO *bio; + + GetPKey(self, pkey); + if (!(bio = BIO_new(BIO_s_mem()))) + ossl_raise(ePKeyError, "BIO_new"); + + if (EVP_PKEY_print_private(bio, pkey, 0, NULL) == 1) + goto out; + OSSL_BIO_reset(bio); + if (EVP_PKEY_print_public(bio, pkey, 0, NULL) == 1) + goto out; + OSSL_BIO_reset(bio); + if (EVP_PKEY_print_params(bio, pkey, 0, NULL) == 1) + goto out; + + BIO_free(bio); + ossl_raise(ePKeyError, "EVP_PKEY_print_params"); + + out: + return ossl_membio2str(bio); +} + +VALUE +ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, int to_der) +{ + EVP_PKEY *pkey; + VALUE cipher, pass, cipher_holder; + const EVP_CIPHER *enc = NULL; + BIO *bio; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "02", &cipher, &pass); + if (!NIL_P(cipher)) { + enc = ossl_evp_cipher_fetch(cipher, &cipher_holder); + pass = ossl_pem_passwd_value(pass); + } + + bio = BIO_new(BIO_s_mem()); + if (!bio) + ossl_raise(ePKeyError, "BIO_new"); + if (to_der) { + if (!i2d_PrivateKey_bio(bio, pkey)) { + BIO_free(bio); + ossl_raise(ePKeyError, "i2d_PrivateKey_bio"); + } + } + else { + if (!PEM_write_bio_PrivateKey_traditional(bio, pkey, enc, NULL, 0, + ossl_pem_passwd_cb, + (void *)pass)) { + BIO_free(bio); + ossl_raise(ePKeyError, "PEM_write_bio_PrivateKey_traditional"); + } + } + return ossl_membio2str(bio); +} + +static VALUE +do_pkcs8_export(int argc, VALUE *argv, VALUE self, int to_der) +{ + EVP_PKEY *pkey; + VALUE cipher, pass, cipher_holder; + const EVP_CIPHER *enc = NULL; + BIO *bio; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "02", &cipher, &pass); + if (argc > 0) { + /* + * TODO: EncryptedPrivateKeyInfo actually has more options. + * Should they be exposed? + */ + enc = ossl_evp_cipher_fetch(cipher, &cipher_holder); + pass = ossl_pem_passwd_value(pass); + } + + bio = BIO_new(BIO_s_mem()); + if (!bio) + ossl_raise(ePKeyError, "BIO_new"); + if (to_der) { + if (!i2d_PKCS8PrivateKey_bio(bio, pkey, enc, NULL, 0, + ossl_pem_passwd_cb, (void *)pass)) { + BIO_free(bio); + ossl_raise(ePKeyError, "i2d_PKCS8PrivateKey_bio"); + } + } + else { + if (!PEM_write_bio_PKCS8PrivateKey(bio, pkey, enc, NULL, 0, + ossl_pem_passwd_cb, (void *)pass)) { + BIO_free(bio); + ossl_raise(ePKeyError, "PEM_write_bio_PKCS8PrivateKey"); + } + } + return ossl_membio2str(bio); +} + +/* + * call-seq: + * pkey.private_to_der -> string + * pkey.private_to_der(cipher, password) -> string + * + * Serializes the private key to DER-encoded PKCS #8 format. If called without + * arguments, unencrypted PKCS #8 PrivateKeyInfo format is used. If called with + * a cipher name and a password, PKCS #8 EncryptedPrivateKeyInfo format with + * PBES2 encryption scheme is used. + */ +static VALUE +ossl_pkey_private_to_der(int argc, VALUE *argv, VALUE self) +{ + return do_pkcs8_export(argc, argv, self, 1); +} + +/* + * call-seq: + * pkey.private_to_pem -> string + * pkey.private_to_pem(cipher, password) -> string + * + * Serializes the private key to PEM-encoded PKCS #8 format. See #private_to_der + * for more details. + * + * An unencrypted PEM-encoded key will look like: + * + * -----BEGIN PRIVATE KEY----- + * [...] + * -----END PRIVATE KEY----- + * + * An encrypted PEM-encoded key will look like: + * + * -----BEGIN ENCRYPTED PRIVATE KEY----- + * [...] + * -----END ENCRYPTED PRIVATE KEY----- */ static VALUE -ossl_pkey_sign(VALUE self, VALUE digest, VALUE data) +ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self) +{ + return do_pkcs8_export(argc, argv, self, 0); +} + +/* + * call-seq: + * pkey.raw_private_key => string + * + * See the OpenSSL documentation for EVP_PKEY_get_raw_private_key() + */ + +static VALUE +ossl_pkey_raw_private_key(VALUE self) { EVP_PKEY *pkey; - EVP_MD_CTX ctx; - unsigned int buf_len; VALUE str; + size_t len; - if (rb_funcall(self, id_private_q, 0, NULL) != Qtrue) { - ossl_raise(rb_eArgError, "Private key is needed."); + GetPKey(self, pkey); + if (EVP_PKEY_get_raw_private_key(pkey, NULL, &len) != 1) + ossl_raise(ePKeyError, "EVP_PKEY_get_raw_private_key"); + str = rb_str_new(NULL, len); + + if (EVP_PKEY_get_raw_private_key(pkey, (unsigned char *)RSTRING_PTR(str), &len) != 1) + ossl_raise(ePKeyError, "EVP_PKEY_get_raw_private_key"); + + rb_str_set_len(str, len); + + return str; +} + +VALUE +ossl_pkey_export_spki(VALUE self, int to_der) +{ + EVP_PKEY *pkey; + BIO *bio; + + GetPKey(self, pkey); + ossl_pkey_check_public_key(pkey); + bio = BIO_new(BIO_s_mem()); + if (!bio) + ossl_raise(ePKeyError, "BIO_new"); + if (to_der) { + if (!i2d_PUBKEY_bio(bio, pkey)) { + BIO_free(bio); + ossl_raise(ePKeyError, "i2d_PUBKEY_bio"); + } } + else { + if (!PEM_write_bio_PUBKEY(bio, pkey)) { + BIO_free(bio); + ossl_raise(ePKeyError, "PEM_write_bio_PUBKEY"); + } + } + return ossl_membio2str(bio); +} + +/* + * call-seq: + * pkey.public_to_der -> string + * + * Serializes the public key to DER-encoded X.509 SubjectPublicKeyInfo format. + */ +static VALUE +ossl_pkey_public_to_der(VALUE self) +{ + return ossl_pkey_export_spki(self, 1); +} + +/* + * call-seq: + * pkey.public_to_pem -> string + * + * Serializes the public key to PEM-encoded X.509 SubjectPublicKeyInfo format. + * + * A PEM-encoded key will look like: + * + * -----BEGIN PUBLIC KEY----- + * [...] + * -----END PUBLIC KEY----- + */ +static VALUE +ossl_pkey_public_to_pem(VALUE self) +{ + return ossl_pkey_export_spki(self, 0); +} + +/* + * call-seq: + * pkey.raw_public_key => string + * + * See the OpenSSL documentation for EVP_PKEY_get_raw_public_key() + */ + +static VALUE +ossl_pkey_raw_public_key(VALUE self) +{ + EVP_PKEY *pkey; + VALUE str; + size_t len; + GetPKey(self, pkey); - EVP_SignInit(&ctx, GetDigestPtr(digest)); - StringValue(data); - EVP_SignUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data)); - str = rb_str_new(0, EVP_PKEY_size(pkey)+16); - if (!EVP_SignFinal(&ctx, (unsigned char *)RSTRING_PTR(str), &buf_len, pkey)) - ossl_raise(ePKeyError, NULL); - assert((long)buf_len <= RSTRING_LEN(str)); - rb_str_set_len(str, buf_len); + if (EVP_PKEY_get_raw_public_key(pkey, NULL, &len) != 1) + ossl_raise(ePKeyError, "EVP_PKEY_get_raw_public_key"); + str = rb_str_new(NULL, len); + + if (EVP_PKEY_get_raw_public_key(pkey, (unsigned char *)RSTRING_PTR(str), &len) != 1) + ossl_raise(ePKeyError, "EVP_PKEY_get_raw_public_key"); + + rb_str_set_len(str, len); return str; } /* * call-seq: - * pkey.verify(digest, signature, data) -> String + * pkey.compare?(another_pkey) -> true | false * - * To verify the +String+ +signature+, +digest+, an instance of - * OpenSSL::Digest, must be provided to re-compute the message digest of the - * original +data+, also a +String+. The return value is +true+ if the - * signature is valid, +false+ otherwise. A PKeyError is raised should errors - * occur. - * Any previous state of the +Digest+ instance is irrelevant to the validation - * outcome, the digest instance is reset to its initial state during the - * operation. + * Used primarily to check if an OpenSSL::X509::Certificate#public_key compares to its private key. * * == Example - * data = 'Sign me!' - * digest = OpenSSL::Digest::SHA256.new - * pkey = OpenSSL::PKey::RSA.new(2048) - * signature = pkey.sign(digest, data) + * x509 = OpenSSL::X509::Certificate.new(pem_encoded_certificate) + * rsa_key = OpenSSL::PKey::RSA.new(pem_encoded_private_key) + * + * rsa_key.compare?(x509.public_key) => true | false + */ +static VALUE +ossl_pkey_compare(VALUE self, VALUE other) +{ + int ret; + EVP_PKEY *selfPKey; + EVP_PKEY *otherPKey; + + GetPKey(self, selfPKey); + GetPKey(other, otherPKey); + + /* Explicitly check the key type given EVP_PKEY_ASN1_METHOD(3) + * docs param_cmp could return any negative number. + */ + if (EVP_PKEY_id(selfPKey) != EVP_PKEY_id(otherPKey)) + ossl_raise(rb_eTypeError, "cannot match different PKey types"); + + ret = EVP_PKEY_eq(selfPKey, otherPKey); + + if (ret == 0) + return Qfalse; + else if (ret == 1) + return Qtrue; + else + ossl_raise(ePKeyError, "EVP_PKEY_eq"); +} + +/* + * call-seq: + * pkey.sign(digest, data [, options]) -> string + * + * Hashes and signs the +data+ using a message digest algorithm +digest+ and + * a private key +pkey+. + * + * See #verify for the verification operation. + * + * See also the man page EVP_DigestSign(3). + * + * +digest+:: + * A String that represents the message digest algorithm name, or +nil+ + * if the PKey type requires no digest algorithm. + * For backwards compatibility, this can be an instance of OpenSSL::Digest. + * Its state will not affect the signature. + * +data+:: + * A String. The data to be hashed and signed. + * +options+:: + * A Hash that contains algorithm specific control operations to \OpenSSL. + * See OpenSSL's man page EVP_PKEY_CTX_ctrl_str(3) for details. + * +options+ parameter was added in version 3.0. + * + * Example: + * data = "Sign me!" + * pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048) + * signopts = { rsa_padding_mode: "pss" } + * signature = pkey.sign("SHA256", data, signopts) + * + * # Creates a copy of the RSA key pkey, but without the private components + * pub_key = pkey.public_key + * puts pub_key.verify("SHA256", signature, data, signopts) # => true + */ +static VALUE +ossl_pkey_sign(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + VALUE digest, data, options, sig, md_holder; + const EVP_MD *md = NULL; + EVP_MD_CTX *ctx; + EVP_PKEY_CTX *pctx; + size_t siglen; + int state; + + pkey = GetPrivPKeyPtr(self); + rb_scan_args(argc, argv, "21", &digest, &data, &options); + if (!NIL_P(digest)) + md = ossl_evp_md_fetch(digest, &md_holder); + StringValue(data); + + ctx = EVP_MD_CTX_new(); + if (!ctx) + ossl_raise(ePKeyError, "EVP_MD_CTX_new"); + if (EVP_DigestSignInit(ctx, &pctx, md, /* engine */NULL, pkey) < 1) { + EVP_MD_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_DigestSignInit"); + } + if (!NIL_P(options)) { + pkey_ctx_apply_options(pctx, options, &state); + if (state) { + EVP_MD_CTX_free(ctx); + rb_jump_tag(state); + } + } + if (EVP_DigestSign(ctx, NULL, &siglen, (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) < 1) { + EVP_MD_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_DigestSign"); + } + if (siglen > LONG_MAX) { + EVP_MD_CTX_free(ctx); + rb_raise(ePKeyError, "signature would be too large"); + } + sig = ossl_str_new(NULL, (long)siglen, &state); + if (state) { + EVP_MD_CTX_free(ctx); + rb_jump_tag(state); + } + if (EVP_DigestSign(ctx, (unsigned char *)RSTRING_PTR(sig), &siglen, + (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) < 1) { + EVP_MD_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_DigestSign"); + } + EVP_MD_CTX_free(ctx); + rb_str_set_len(sig, siglen); + return sig; +} + +/* + * call-seq: + * pkey.verify(digest, signature, data [, options]) -> true or false + * + * Verifies the +signature+ for the +data+ using a message digest algorithm + * +digest+ and a public key +pkey+. + * + * Returns +true+ if the signature is successfully verified, +false+ otherwise. + * The caller must check the return value. + * + * See #sign for the signing operation and an example. + * + * See also the man page EVP_DigestVerify(3). + * + * +digest+:: + * See #sign. + * +signature+:: + * A String containing the signature to be verified. + * +data+:: + * See #sign. + * +options+:: + * See #sign. +options+ parameter was added in version 3.0. + */ +static VALUE +ossl_pkey_verify(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + VALUE digest, sig, data, options, md_holder; + const EVP_MD *md = NULL; + EVP_MD_CTX *ctx; + EVP_PKEY_CTX *pctx; + int state, ret; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "31", &digest, &sig, &data, &options); + ossl_pkey_check_public_key(pkey); + if (!NIL_P(digest)) + md = ossl_evp_md_fetch(digest, &md_holder); + StringValue(sig); + StringValue(data); + + ctx = EVP_MD_CTX_new(); + if (!ctx) + ossl_raise(ePKeyError, "EVP_MD_CTX_new"); + if (EVP_DigestVerifyInit(ctx, &pctx, md, /* engine */NULL, pkey) < 1) { + EVP_MD_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_DigestVerifyInit"); + } + if (!NIL_P(options)) { + pkey_ctx_apply_options(pctx, options, &state); + if (state) { + EVP_MD_CTX_free(ctx); + rb_jump_tag(state); + } + } + ret = EVP_DigestVerify(ctx, (unsigned char *)RSTRING_PTR(sig), + RSTRING_LEN(sig), (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)); + EVP_MD_CTX_free(ctx); + if (ret < 0) + ossl_raise(ePKeyError, "EVP_DigestVerify"); + if (ret) + return Qtrue; + else { + ossl_clear_error(); + return Qfalse; + } +} + +/* + * call-seq: + * pkey.sign_raw(digest, data [, options]) -> string + * + * Signs +data+ using a private key +pkey+. Unlike #sign, +data+ will not be + * hashed by +digest+ automatically. + * + * See #verify_raw for the verification operation. + * + * Added in version 3.0. See also the man page EVP_PKEY_sign(3). + * + * +digest+:: + * A String that represents the message digest algorithm name, or +nil+ + * if the PKey type requires no digest algorithm. + * Although this method will not hash +data+ with it, this parameter may still + * be required depending on the signature algorithm. + * +data+:: + * A String. The data to be signed. + * +options+:: + * A Hash that contains algorithm specific control operations to \OpenSSL. + * See OpenSSL's man page EVP_PKEY_CTX_ctrl_str(3) for details. + * + * Example: + * data = "Sign me!" + * hash = OpenSSL::Digest.digest("SHA256", data) + * pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048) + * signopts = { rsa_padding_mode: "pss" } + * signature = pkey.sign_raw("SHA256", hash, signopts) + * + * # Creates a copy of the RSA key pkey, but without the private components * pub_key = pkey.public_key - * puts pub_key.verify(digest, signature, data) # => true + * puts pub_key.verify_raw("SHA256", signature, hash, signopts) # => true */ static VALUE -ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data) +ossl_pkey_sign_raw(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; - EVP_MD_CTX ctx; - int result; + VALUE digest, data, options, sig, md_holder; + const EVP_MD *md = NULL; + EVP_PKEY_CTX *ctx; + size_t outlen; + int state; GetPKey(self, pkey); + rb_scan_args(argc, argv, "21", &digest, &data, &options); + if (!NIL_P(digest)) + md = ossl_evp_md_fetch(digest, &md_holder); + StringValue(data); + + ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + if (EVP_PKEY_sign_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_sign_init"); + } + if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md"); + } + if (!NIL_P(options)) { + pkey_ctx_apply_options(ctx, options, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + } + if (EVP_PKEY_sign(ctx, NULL, &outlen, (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_sign"); + } + if (outlen > LONG_MAX) { + EVP_PKEY_CTX_free(ctx); + rb_raise(ePKeyError, "signature would be too large"); + } + sig = ossl_str_new(NULL, (long)outlen, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + if (EVP_PKEY_sign(ctx, (unsigned char *)RSTRING_PTR(sig), &outlen, + (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_sign"); + } + EVP_PKEY_CTX_free(ctx); + rb_str_set_len(sig, outlen); + return sig; +} + +/* + * call-seq: + * pkey.verify_raw(digest, signature, data [, options]) -> true or false + * + * Verifies the +signature+ for the +data+ using a public key +pkey+. Unlike + * #verify, this method will not hash +data+ with +digest+ automatically. + * + * Returns +true+ if the signature is successfully verified, +false+ otherwise. + * The caller must check the return value. + * + * See #sign_raw for the signing operation and an example code. + * + * Added in version 3.0. See also the man page EVP_PKEY_verify(3). + * + * +signature+:: + * A String containing the signature to be verified. + */ +static VALUE +ossl_pkey_verify_raw(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + VALUE digest, sig, data, options, md_holder; + const EVP_MD *md = NULL; + EVP_PKEY_CTX *ctx; + int state, ret; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "31", &digest, &sig, &data, &options); + ossl_pkey_check_public_key(pkey); + if (!NIL_P(digest)) + md = ossl_evp_md_fetch(digest, &md_holder); StringValue(sig); StringValue(data); - EVP_VerifyInit(&ctx, GetDigestPtr(digest)); - EVP_VerifyUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data)); - result = EVP_VerifyFinal(&ctx, (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), pkey); - EVP_MD_CTX_cleanup(&ctx); - switch (result) { - case 0: - return Qfalse; - case 1: - return Qtrue; - default: - ossl_raise(ePKeyError, NULL); + + ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + if (EVP_PKEY_verify_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_verify_init"); + } + if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md"); + } + if (!NIL_P(options)) { + pkey_ctx_apply_options(ctx, options, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + } + ret = EVP_PKEY_verify(ctx, (unsigned char *)RSTRING_PTR(sig), + RSTRING_LEN(sig), + (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)); + EVP_PKEY_CTX_free(ctx); + if (ret < 0) + ossl_raise(ePKeyError, "EVP_PKEY_verify"); + + if (ret) + return Qtrue; + else { + ossl_clear_error(); + return Qfalse; + } +} + +/* + * call-seq: + * pkey.verify_recover(digest, signature [, options]) -> string + * + * Recovers the signed data from +signature+ using a public key +pkey+. Not all + * signature algorithms support this operation. + * + * Added in version 3.0. See also the man page EVP_PKEY_verify_recover(3). + * + * +signature+:: + * A String containing the signature to be verified. + */ +static VALUE +ossl_pkey_verify_recover(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + VALUE digest, sig, options, out, md_holder; + const EVP_MD *md = NULL; + EVP_PKEY_CTX *ctx; + int state; + size_t outlen; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "21", &digest, &sig, &options); + ossl_pkey_check_public_key(pkey); + if (!NIL_P(digest)) + md = ossl_evp_md_fetch(digest, &md_holder); + StringValue(sig); + + ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + if (EVP_PKEY_verify_recover_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_verify_recover_init"); + } + if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md"); + } + if (!NIL_P(options)) { + pkey_ctx_apply_options(ctx, options, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + } + if (EVP_PKEY_verify_recover(ctx, NULL, &outlen, + (unsigned char *)RSTRING_PTR(sig), + RSTRING_LEN(sig)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_verify_recover"); + } + out = ossl_str_new(NULL, (long)outlen, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + if (EVP_PKEY_verify_recover(ctx, (unsigned char *)RSTRING_PTR(out), &outlen, + (unsigned char *)RSTRING_PTR(sig), + RSTRING_LEN(sig)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_verify_recover"); + } + EVP_PKEY_CTX_free(ctx); + rb_str_set_len(out, outlen); + return out; +} + +/* + * call-seq: + * pkey.derive(peer_pkey) -> string + * + * Derives a shared secret from _pkey_ and _peer_pkey_. _pkey_ must contain + * the private components, _peer_pkey_ must contain the public components. + */ +static VALUE +ossl_pkey_derive(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey, *peer_pkey; + EVP_PKEY_CTX *ctx; + VALUE peer_pkey_obj, str; + size_t keylen; + int state; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "1", &peer_pkey_obj); + GetPKey(peer_pkey_obj, peer_pkey); + + ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + if (EVP_PKEY_derive_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_derive_init"); + } + if (EVP_PKEY_derive_set_peer(ctx, peer_pkey) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_derive_set_peer"); + } + if (EVP_PKEY_derive(ctx, NULL, &keylen) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_derive"); + } + if (keylen > LONG_MAX) + rb_raise(ePKeyError, "derived key would be too large"); + str = ossl_str_new(NULL, (long)keylen, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + if (EVP_PKEY_derive(ctx, (unsigned char *)RSTRING_PTR(str), &keylen) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_derive"); + } + EVP_PKEY_CTX_free(ctx); + rb_str_set_len(str, keylen); + return str; +} + +/* + * call-seq: + * pkey.encrypt(data [, options]) -> string + * + * Performs a public key encryption operation using +pkey+. + * + * See #decrypt for the reverse operation. + * + * Added in version 3.0. See also the man page EVP_PKEY_encrypt(3). + * + * +data+:: + * A String to be encrypted. + * +options+:: + * A Hash that contains algorithm specific control operations to \OpenSSL. + * See OpenSSL's man page EVP_PKEY_CTX_ctrl_str(3) for details. + * + * Example: + * pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048) + * data = "secret data" + * encrypted = pkey.encrypt(data, rsa_padding_mode: "oaep") + * decrypted = pkey.decrypt(data, rsa_padding_mode: "oaep") + * p decrypted #=> "secret data" + */ +static VALUE +ossl_pkey_encrypt(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + EVP_PKEY_CTX *ctx; + VALUE data, options, str; + size_t outlen; + int state; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "11", &data, &options); + StringValue(data); + + ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + if (EVP_PKEY_encrypt_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_encrypt_init"); + } + if (!NIL_P(options)) { + pkey_ctx_apply_options(ctx, options, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } } - return Qnil; /* dummy */ + if (EVP_PKEY_encrypt(ctx, NULL, &outlen, + (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_encrypt"); + } + if (outlen > LONG_MAX) { + EVP_PKEY_CTX_free(ctx); + rb_raise(ePKeyError, "encrypted data would be too large"); + } + str = ossl_str_new(NULL, (long)outlen, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + if (EVP_PKEY_encrypt(ctx, (unsigned char *)RSTRING_PTR(str), &outlen, + (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_encrypt"); + } + EVP_PKEY_CTX_free(ctx); + rb_str_set_len(str, outlen); + return str; +} + +/* + * call-seq: + * pkey.decrypt(data [, options]) -> string + * + * Performs a public key decryption operation using +pkey+. + * + * See #encrypt for a description of the parameters and an example. + * + * Added in version 3.0. See also the man page EVP_PKEY_decrypt(3). + */ +static VALUE +ossl_pkey_decrypt(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + EVP_PKEY_CTX *ctx; + VALUE data, options, str; + size_t outlen; + int state; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "11", &data, &options); + StringValue(data); + + ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + if (EVP_PKEY_decrypt_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_decrypt_init"); + } + if (!NIL_P(options)) { + pkey_ctx_apply_options(ctx, options, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + } + if (EVP_PKEY_decrypt(ctx, NULL, &outlen, + (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_decrypt"); + } + if (outlen > LONG_MAX) { + EVP_PKEY_CTX_free(ctx); + rb_raise(ePKeyError, "decrypted data would be too large"); + } + str = ossl_str_new(NULL, (long)outlen, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + if (EVP_PKEY_decrypt(ctx, (unsigned char *)RSTRING_PTR(str), &outlen, + (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_decrypt"); + } + EVP_PKEY_CTX_free(ctx); + rb_str_set_len(str, outlen); + return str; } /* @@ -358,10 +1657,7 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data) void Init_ossl_pkey(void) { -#if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ -#endif - +#undef rb_intern /* Document-module: OpenSSL::PKey * * == Asymmetric Public Key Algorithms @@ -371,7 +1667,7 @@ Init_ossl_pkey(void) * algorithm consists of two parts: a public key that may be distributed * to others and a private key that needs to remain secret. * - * Messages encrypted with a public key can only be encrypted by + * Messages encrypted with a public key can only be decrypted by * recipients that are in possession of the associated private key. * Since public key algorithms are considerably slower than symmetric * key algorithms (cf. OpenSSL::Cipher) they are often used to establish @@ -417,7 +1713,16 @@ Init_ossl_pkey(void) /* Document-class: OpenSSL::PKey::PKeyError * - *Raised when errors occur during PKey#sign or PKey#verify. + * Raised when errors occur during PKey#sign or PKey#verify. + * + * Before version 4.0.0, OpenSSL::PKey::PKeyError had the following + * subclasses. These subclasses have been removed and the constants are + * now defined as aliases of OpenSSL::PKey::PKeyError. + * + * * OpenSSL::PKey::DHError + * * OpenSSL::PKey::DSAError + * * OpenSSL::PKey::ECError + * * OpenSSL::PKey::RSAError */ ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError); @@ -433,12 +1738,37 @@ Init_ossl_pkey(void) cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject); rb_define_module_function(mPKey, "read", ossl_pkey_new_from_data, -1); + rb_define_module_function(mPKey, "generate_parameters", ossl_pkey_s_generate_parameters, -1); + rb_define_module_function(mPKey, "generate_key", ossl_pkey_s_generate_key, -1); + rb_define_module_function(mPKey, "new_raw_private_key", ossl_pkey_new_raw_private_key, 2); + rb_define_module_function(mPKey, "new_raw_public_key", ossl_pkey_new_raw_public_key, 2); rb_define_alloc_func(cPKey, ossl_pkey_alloc); rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0); +#ifdef HAVE_EVP_PKEY_DUP + rb_define_method(cPKey, "initialize_copy", ossl_pkey_initialize_copy, 1); +#else + rb_undef_method(cPKey, "initialize_copy"); +#endif + rb_define_method(cPKey, "oid", ossl_pkey_oid, 0); + rb_define_method(cPKey, "inspect", ossl_pkey_inspect, 0); + rb_define_method(cPKey, "to_text", ossl_pkey_to_text, 0); + rb_define_method(cPKey, "private_to_der", ossl_pkey_private_to_der, -1); + rb_define_method(cPKey, "private_to_pem", ossl_pkey_private_to_pem, -1); + rb_define_method(cPKey, "public_to_der", ossl_pkey_public_to_der, 0); + rb_define_method(cPKey, "public_to_pem", ossl_pkey_public_to_pem, 0); + rb_define_method(cPKey, "raw_private_key", ossl_pkey_raw_private_key, 0); + rb_define_method(cPKey, "raw_public_key", ossl_pkey_raw_public_key, 0); + rb_define_method(cPKey, "compare?", ossl_pkey_compare, 1); - rb_define_method(cPKey, "sign", ossl_pkey_sign, 2); - rb_define_method(cPKey, "verify", ossl_pkey_verify, 3); + rb_define_method(cPKey, "sign", ossl_pkey_sign, -1); + rb_define_method(cPKey, "verify", ossl_pkey_verify, -1); + rb_define_method(cPKey, "sign_raw", ossl_pkey_sign_raw, -1); + rb_define_method(cPKey, "verify_raw", ossl_pkey_verify_raw, -1); + rb_define_method(cPKey, "verify_recover", ossl_pkey_verify_recover, -1); + rb_define_method(cPKey, "derive", ossl_pkey_derive, -1); + rb_define_method(cPKey, "encrypt", ossl_pkey_encrypt, -1); + rb_define_method(cPKey, "decrypt", ossl_pkey_decrypt, -1); id_private_q = rb_intern("private?"); @@ -450,4 +1780,3 @@ Init_ossl_pkey(void) Init_ossl_dh(); Init_ossl_ec(); } - diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h index 6c0b7fd602..023361b90f 100644 --- a/ext/openssl/ossl_pkey.h +++ b/ext/openssl/ossl_pkey.h @@ -1,152 +1,193 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ -#if !defined(_OSSL_PKEY_H_) -#define _OSSL_PKEY_H_ +#if !defined(OSSL_PKEY_H) +#define OSSL_PKEY_H extern VALUE mPKey; extern VALUE cPKey; extern VALUE ePKeyError; -extern ID id_private_q; extern const rb_data_type_t ossl_evp_pkey_type; -#define OSSL_PKEY_SET_PRIVATE(obj) rb_iv_set((obj), "private", Qtrue) -#define OSSL_PKEY_SET_PUBLIC(obj) rb_iv_set((obj), "private", Qfalse) -#define OSSL_PKEY_IS_PRIVATE(obj) (rb_iv_get((obj), "private") == Qtrue) +/* For ENGINE */ +#define OSSL_PKEY_SET_PRIVATE(obj) rb_ivar_set((obj), rb_intern("private"), Qtrue) +#define OSSL_PKEY_IS_PRIVATE(obj) (rb_attr_get((obj), rb_intern("private")) == Qtrue) -#define WrapPKey(klass, obj, pkey) do { \ - if (!(pkey)) { \ - rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!"); \ - } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_evp_pkey_type, (pkey)); \ - OSSL_PKEY_SET_PUBLIC(obj); \ -} while (0) #define GetPKey(obj, pkey) do {\ TypedData_Get_Struct((obj), EVP_PKEY, &ossl_evp_pkey_type, (pkey)); \ if (!(pkey)) { \ - rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!");\ + rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!");\ } \ } while (0) -#define SafeGetPKey(obj, pkey) do { \ - OSSL_Check_Kind((obj), cPKey); \ - GetPKey((obj), (pkey)); \ -} while (0) -void ossl_generate_cb(int, int, void *); -#define HAVE_BN_GENCB defined(HAVE_RSA_GENERATE_KEY_EX) || defined(HAVE_DH_GENERATE_PARAMETERS_EX) || defined(HAVE_DSA_GENERATE_PARAMETERS_EX) -#if HAVE_BN_GENCB -struct ossl_generate_cb_arg { - int yield; - int stop; - int state; -}; -int ossl_generate_cb_2(int p, int n, BN_GENCB *cb); -void ossl_generate_cb_stop(void *ptr); -#endif - -VALUE ossl_pkey_new(EVP_PKEY *); -VALUE ossl_pkey_new_from_file(VALUE); +/* Takes ownership of the EVP_PKEY */ +VALUE ossl_pkey_wrap(EVP_PKEY *); +void ossl_pkey_check_public_key(const EVP_PKEY *); +EVP_PKEY *ossl_pkey_read_generic(BIO *, VALUE); EVP_PKEY *GetPKeyPtr(VALUE); EVP_PKEY *DupPKeyPtr(VALUE); EVP_PKEY *GetPrivPKeyPtr(VALUE); -EVP_PKEY *DupPrivPKeyPtr(VALUE); + +/* + * Serializes _self_ in X.509 SubjectPublicKeyInfo format and returns the + * resulting String. Sub-classes use this when overriding #to_der. + */ +VALUE ossl_pkey_export_spki(VALUE self, int to_der); +/* + * Serializes the private key _self_ in the traditional private key format + * and returns the resulting String. Sub-classes use this when overriding + * #to_der. + */ +VALUE ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, + int to_der); + void Init_ossl_pkey(void); /* * RSA */ extern VALUE cRSA; -extern VALUE eRSAError; - -VALUE ossl_rsa_new(EVP_PKEY *); void Init_ossl_rsa(void); /* * DSA */ extern VALUE cDSA; -extern VALUE eDSAError; - -VALUE ossl_dsa_new(EVP_PKEY *); void Init_ossl_dsa(void); /* * DH */ extern VALUE cDH; -extern VALUE eDHError; -extern DH *OSSL_DEFAULT_DH_512; -extern DH *OSSL_DEFAULT_DH_1024; - -VALUE ossl_dh_new(EVP_PKEY *); void Init_ossl_dh(void); /* * EC */ extern VALUE cEC; -extern VALUE eECError; -extern VALUE cEC_GROUP; -extern VALUE eEC_GROUP; -extern VALUE cEC_POINT; -extern VALUE eEC_POINT; VALUE ossl_ec_new(EVP_PKEY *); void Init_ossl_ec(void); +#define OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, _name, _get) \ +/* \ + * call-seq: \ + * _keytype##.##_name -> aBN \ + */ \ +static VALUE ossl_##_keytype##_get_##_name(VALUE self) \ +{ \ + const _type *obj; \ + const BIGNUM *bn; \ + \ + Get##_type(self, obj); \ + _get; \ + if (bn == NULL) \ + return Qnil; \ + return ossl_bn_new(bn); \ +} -#define OSSL_PKEY_BN(keytype, name) \ -/* \ - * call-seq: \ - * key.##name -> aBN \ - */ \ -static VALUE ossl_##keytype##_get_##name(VALUE self) \ -{ \ - EVP_PKEY *pkey; \ - BIGNUM *bn; \ - \ - GetPKey(self, pkey); \ - bn = pkey->pkey.keytype->name; \ - if (bn == NULL) \ - return Qnil; \ - return ossl_bn_new(bn); \ -} \ -/* \ - * call-seq: \ - * key.##name = bn -> bn \ - */ \ -static VALUE ossl_##keytype##_set_##name(VALUE self, VALUE bignum) \ -{ \ - EVP_PKEY *pkey; \ - BIGNUM *bn; \ - \ - GetPKey(self, pkey); \ - if (NIL_P(bignum)) { \ - BN_clear_free(pkey->pkey.keytype->name); \ - pkey->pkey.keytype->name = NULL; \ - return Qnil; \ - } \ - \ - bn = GetBNPtr(bignum); \ - if (pkey->pkey.keytype->name == NULL) \ - pkey->pkey.keytype->name = BN_new(); \ - if (pkey->pkey.keytype->name == NULL) \ - ossl_raise(eBNError, NULL); \ - if (BN_copy(pkey->pkey.keytype->name, bn) == NULL) \ - ossl_raise(eBNError, NULL); \ - return bignum; \ +#define OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \ + OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a1, \ + _type##_get0_##_group(obj, &bn, NULL, NULL)) \ + OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \ + _type##_get0_##_group(obj, NULL, &bn, NULL)) \ + OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a3, \ + _type##_get0_##_group(obj, NULL, NULL, &bn)) + +#define OSSL_PKEY_BN_DEF_GETTER2(_keytype, _type, _group, a1, a2) \ + OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a1, \ + _type##_get0_##_group(obj, &bn, NULL)) \ + OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \ + _type##_get0_##_group(obj, NULL, &bn)) + +#ifndef OSSL_HAVE_IMMUTABLE_PKEY +#define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \ +/* \ + * call-seq: \ + * _keytype##.set_##_group(a1, a2, a3) -> self \ + */ \ +static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2, VALUE v3) \ +{ \ + _type *obj; \ + BIGNUM *bn1 = NULL, *orig_bn1 = NIL_P(v1) ? NULL : GetBNPtr(v1);\ + BIGNUM *bn2 = NULL, *orig_bn2 = NIL_P(v2) ? NULL : GetBNPtr(v2);\ + BIGNUM *bn3 = NULL, *orig_bn3 = NIL_P(v3) ? NULL : GetBNPtr(v3);\ + \ + Get##_type(self, obj); \ + if ((orig_bn1 && !(bn1 = BN_dup(orig_bn1))) || \ + (orig_bn2 && !(bn2 = BN_dup(orig_bn2))) || \ + (orig_bn3 && !(bn3 = BN_dup(orig_bn3)))) { \ + BN_clear_free(bn1); \ + BN_clear_free(bn2); \ + BN_clear_free(bn3); \ + ossl_raise(ePKeyError, "BN_dup"); \ + } \ + \ + if (!_type##_set0_##_group(obj, bn1, bn2, bn3)) { \ + BN_clear_free(bn1); \ + BN_clear_free(bn2); \ + BN_clear_free(bn3); \ + ossl_raise(ePKeyError, #_type"_set0_"#_group); \ + } \ + return self; \ } -#define DEF_OSSL_PKEY_BN(class, keytype, name) \ -do { \ - rb_define_method((class), #name, ossl_##keytype##_get_##name, 0); \ - rb_define_method((class), #name "=", ossl_##keytype##_set_##name, 1);\ -} while (0) +#define OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) \ +/* \ + * call-seq: \ + * _keytype##.set_##_group(a1, a2) -> self \ + */ \ +static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \ +{ \ + _type *obj; \ + BIGNUM *bn1 = NULL, *orig_bn1 = NIL_P(v1) ? NULL : GetBNPtr(v1);\ + BIGNUM *bn2 = NULL, *orig_bn2 = NIL_P(v2) ? NULL : GetBNPtr(v2);\ + \ + Get##_type(self, obj); \ + if ((orig_bn1 && !(bn1 = BN_dup(orig_bn1))) || \ + (orig_bn2 && !(bn2 = BN_dup(orig_bn2)))) { \ + BN_clear_free(bn1); \ + BN_clear_free(bn2); \ + ossl_raise(ePKeyError, "BN_dup"); \ + } \ + \ + if (!_type##_set0_##_group(obj, bn1, bn2)) { \ + BN_clear_free(bn1); \ + BN_clear_free(bn2); \ + ossl_raise(ePKeyError, #_type"_set0_"#_group); \ + } \ + return self; \ +} +#else +#define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \ +static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2, VALUE v3) \ +{ \ + rb_raise(ePKeyError, \ + #_keytype"#set_"#_group"= is incompatible with OpenSSL 3.0"); \ +} + +#define OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) \ +static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \ +{ \ + rb_raise(ePKeyError, \ + #_keytype"#set_"#_group"= is incompatible with OpenSSL 3.0"); \ +} +#endif + +#define OSSL_PKEY_BN_DEF3(_keytype, _type, _group, a1, a2, a3) \ + OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \ + OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) + +#define OSSL_PKEY_BN_DEF2(_keytype, _type, _group, a1, a2) \ + OSSL_PKEY_BN_DEF_GETTER2(_keytype, _type, _group, a1, a2) \ + OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) + +#define DEF_OSSL_PKEY_BN(class, keytype, name) \ + rb_define_method((class), #name, ossl_##keytype##_get_##name, 0) -#endif /* _OSSL_PKEY_H_ */ +#endif /* OSSL_PKEY_H */ diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c index cf283263a6..3f2975c5a3 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -1,246 +1,181 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ -#if !defined(OPENSSL_NO_DH) - #include "ossl.h" +#if !defined(OPENSSL_NO_DH) + #define GetPKeyDH(obj, pkey) do { \ GetPKey((obj), (pkey)); \ - if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_DH) { /* PARANOIA? */ \ - ossl_raise(rb_eRuntimeError, "THIS IS NOT A DH!") ; \ + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) { /* PARANOIA? */ \ + ossl_raise(rb_eRuntimeError, "THIS IS NOT A DH!") ; \ } \ } while (0) - -#define DH_HAS_PRIVATE(dh) ((dh)->priv_key) - -#ifdef OSSL_ENGINE_ENABLED -# define DH_PRIVATE(dh) (DH_HAS_PRIVATE(dh) || (dh)->engine) -#else -# define DH_PRIVATE(dh) DH_HAS_PRIVATE(dh) -#endif - +#define GetDH(obj, dh) do { \ + EVP_PKEY *_pkey; \ + GetPKeyDH((obj), _pkey); \ + (dh) = EVP_PKEY_get0_DH(_pkey); \ + if ((dh) == NULL) \ + ossl_raise(ePKeyError, "failed to get DH from EVP_PKEY"); \ +} while (0) /* * Classes */ VALUE cDH; -VALUE eDHError; - -/* - * Public - */ -static VALUE -dh_instance(VALUE klass, DH *dh) -{ - EVP_PKEY *pkey; - VALUE obj; - - if (!dh) { - return Qfalse; - } - if (!(pkey = EVP_PKEY_new())) { - return Qfalse; - } - if (!EVP_PKEY_assign_DH(pkey, dh)) { - EVP_PKEY_free(pkey); - return Qfalse; - } - WrapPKey(klass, obj, pkey); - - return obj; -} - -VALUE -ossl_dh_new(EVP_PKEY *pkey) -{ - VALUE obj; - - if (!pkey) { - obj = dh_instance(cDH, DH_new()); - } else { - if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) { - ossl_raise(rb_eTypeError, "Not a DH key!"); - } - WrapPKey(cDH, obj, pkey); - } - if (obj == Qfalse) { - ossl_raise(eDHError, NULL); - } - - return obj; -} /* * Private */ -#if defined(HAVE_DH_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB -struct dh_blocking_gen_arg { - DH *dh; - int size; - int gen; - BN_GENCB *cb; - int result; -}; - -static void * -dh_blocking_gen(void *arg) -{ - struct dh_blocking_gen_arg *gen = (struct dh_blocking_gen_arg *)arg; - gen->result = DH_generate_parameters_ex(gen->dh, gen->size, gen->gen, gen->cb); - return 0; -} -#endif - -static DH * -dh_generate(int size, int gen) -{ -#if defined(HAVE_DH_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB - BN_GENCB cb; - struct ossl_generate_cb_arg cb_arg; - struct dh_blocking_gen_arg gen_arg; - DH *dh = DH_new(); - - if (!dh) return 0; - - memset(&cb_arg, 0, sizeof(struct ossl_generate_cb_arg)); - if (rb_block_given_p()) - cb_arg.yield = 1; - BN_GENCB_set(&cb, ossl_generate_cb_2, &cb_arg); - gen_arg.dh = dh; - gen_arg.size = size; - gen_arg.gen = gen; - gen_arg.cb = &cb; - if (cb_arg.yield == 1) { - /* we cannot release GVL when callback proc is supplied */ - dh_blocking_gen(&gen_arg); - } else { - /* there's a chance to unblock */ - rb_thread_call_without_gvl(dh_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg); - } - - if (!gen_arg.result) { - DH_free(dh); - if (cb_arg.state) rb_jump_tag(cb_arg.state); - return 0; - } -#else - DH *dh; - - dh = DH_generate_parameters(size, gen, rb_block_given_p() ? ossl_generate_cb : NULL, NULL); - if (!dh) return 0; -#endif - - if (!DH_generate_key(dh)) { - DH_free(dh); - return 0; - } - - return dh; -} - /* - * call-seq: - * DH.generate(size [, generator]) -> dh + * call-seq: + * DH.new -> dh + * DH.new(string) -> dh + * DH.new(size [, generator]) -> dh * - * Creates a new DH instance from scratch by generating the private and public - * components alike. + * Creates a new instance of OpenSSL::PKey::DH. * - * === Parameters - * * +size+ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure. - * * +generator+ is a small number > 1, typically 2 or 5. + * If called without arguments, an empty instance without any parameter or key + * components is created. Use #set_pqg to manually set the parameters afterwards + * (and optionally #set_key to set private and public key components). + * This form is not compatible with OpenSSL 3.0 or later. * - */ -static VALUE -ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass) -{ - DH *dh ; - int g = 2; - VALUE size, gen, obj; - - if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) { - g = NUM2INT(gen); - } - dh = dh_generate(NUM2INT(size), g); - obj = dh_instance(klass, dh); - if (obj == Qfalse) { - DH_free(dh); - ossl_raise(eDHError, NULL); - } - - return obj; -} - -/* - * call-seq: - * DH.new([size [, generator] | string]) -> dh + * If a String is given, tries to parse it as a DER- or PEM- encoded parameters. + * See also OpenSSL::PKey.read which can parse keys of any kinds. + * + * The DH.new(size [, generator]) form is an alias of DH.generate. * - * Either generates a DH instance from scratch or by reading already existing - * DH parameters from +string+. Note that when reading a DH instance from - * data that was encoded from a DH instance by using DH#to_pem or DH#to_der - * the result will *not* contain a public/private key pair yet. This needs to - * be generated using DH#generate_key! first. + * +string+:: + * A String that contains the DER or PEM encoded key. + * +size+:: + * See DH.generate. + * +generator+:: + * See DH.generate. * - * === Parameters - * * +size+ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure. - * * +generator+ is a small number > 1, typically 2 or 5. - * * +string+ contains the DER or PEM encoded key. + * Examples: + * # Creating an instance from scratch + * # Note that this is deprecated and will result in ArgumentError when + * # using OpenSSL 3.0 or later. + * dh = OpenSSL::PKey::DH.new + * dh.set_pqg(bn_p, nil, bn_g) * - * === Examples - * DH.new # -> dh - * DH.new(1024) # -> dh - * DH.new(1024, 5) # -> dh - * #Reading DH parameters - * dh = DH.new(File.read('parameters.pem')) # -> dh, but no public/private key yet - * dh.generate_key! # -> dh with public and private key + * # Generating a parameters and a key pair + * dh = OpenSSL::PKey::DH.new(2048) # An alias of OpenSSL::PKey::DH.generate(2048) + * + * # Reading DH parameters from a PEM-encoded string + * dh_params = OpenSSL::PKey::DH.new(File.read('parameters.pem')) # loads parameters only + * dh = OpenSSL::PKey.generate_key(dh_params) # generates a key pair */ static VALUE ossl_dh_initialize(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; + int type; DH *dh; - int g = 2; - BIO *in; - VALUE arg, gen; + BIO *in = NULL; + VALUE arg; + + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); + + /* The DH.new(size, generator) form is handled by lib/openssl/pkey.rb */ + if (rb_scan_args(argc, argv, "01", &arg) == 0) { +#ifdef OSSL_HAVE_IMMUTABLE_PKEY + rb_raise(rb_eArgError, "OpenSSL::PKey::DH.new cannot be called " \ + "without arguments; pkeys are immutable with OpenSSL 3.0"); +#else + dh = DH_new(); + if (!dh) + ossl_raise(ePKeyError, "DH_new"); + goto legacy; +#endif + } - GetPKey(self, pkey); - if(rb_scan_args(argc, argv, "02", &arg, &gen) == 0) { - dh = DH_new(); + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(&arg); + + /* + * On OpenSSL <= 1.1.1 and current versions of LibreSSL, the generic + * routine does not support DER-encoded parameters + */ + dh = d2i_DHparams_bio(in, NULL); + if (dh) + goto legacy; + OSSL_BIO_reset(in); + + pkey = ossl_pkey_read_generic(in, Qnil); + BIO_free(in); + if (!pkey) + ossl_raise(ePKeyError, "could not parse pkey"); + + type = EVP_PKEY_base_id(pkey); + if (type != EVP_PKEY_DH) { + EVP_PKEY_free(pkey); + rb_raise(ePKeyError, "incorrect pkey type: %s", OBJ_nid2sn(type)); } - else if (FIXNUM_P(arg)) { - if (!NIL_P(gen)) { - g = NUM2INT(gen); - } - if (!(dh = dh_generate(FIX2INT(arg), g))) { - ossl_raise(eDHError, NULL); - } + RTYPEDDATA_DATA(self) = pkey; + return self; + + legacy: + BIO_free(in); + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) { + EVP_PKEY_free(pkey); + DH_free(dh); + ossl_raise(ePKeyError, "EVP_PKEY_assign_DH"); } - else { - arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(arg); - dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); - if (!dh){ - OSSL_BIO_reset(in); - dh = d2i_DHparams_bio(in, NULL); - } - BIO_free(in); - if (!dh) { - ossl_raise(eDHError, NULL); - } + RTYPEDDATA_DATA(self) = pkey; + return self; +} + +#ifndef HAVE_EVP_PKEY_DUP +/* :nodoc: */ +static VALUE +ossl_dh_initialize_copy(VALUE self, VALUE other) +{ + EVP_PKEY *pkey; + DH *dh, *dh_other; + const BIGNUM *pub, *priv; + + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); + GetDH(other, dh_other); + + dh = DHparams_dup(dh_other); + if (!dh) + ossl_raise(ePKeyError, "DHparams_dup"); + + DH_get0_key(dh_other, &pub, &priv); + if (pub) { + BIGNUM *pub2 = BN_dup(pub); + BIGNUM *priv2 = BN_dup(priv); + + if (!pub2 || (priv && !priv2)) { + BN_clear_free(pub2); + BN_clear_free(priv2); + ossl_raise(ePKeyError, "BN_dup"); + } + DH_set0_key(dh, pub2, priv2); } - if (!EVP_PKEY_assign_DH(pkey, dh)) { - DH_free(dh); - ossl_raise(eDHError, NULL); + + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) { + EVP_PKEY_free(pkey); + DH_free(dh); + ossl_raise(ePKeyError, "EVP_PKEY_assign_DH"); } + RTYPEDDATA_DATA(self) = pkey; return self; } +#endif /* * call-seq: @@ -252,11 +187,13 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self) static VALUE ossl_dh_is_public(VALUE self) { - EVP_PKEY *pkey; + OSSL_3_const DH *dh; + const BIGNUM *bn; - GetPKeyDH(self, pkey); + GetDH(self, dh); + DH_get0_key(dh, &bn, NULL); - return (pkey->pkey.dh->pub_key) ? Qtrue : Qfalse; + return bn ? Qtrue : Qfalse; } /* @@ -269,11 +206,17 @@ ossl_dh_is_public(VALUE self) static VALUE ossl_dh_is_private(VALUE self) { - EVP_PKEY *pkey; + OSSL_3_const DH *dh; + const BIGNUM *bn; - GetPKeyDH(self, pkey); + GetDH(self, dh); + DH_get0_key(dh, NULL, &bn); - return (DH_PRIVATE(pkey->pkey.dh)) ? Qtrue : Qfalse; +#if !defined(OPENSSL_NO_ENGINE) + return (bn || DH_get0_engine((DH *)dh)) ? Qtrue : Qfalse; +#else + return bn ? Qtrue : Qfalse; +#endif } /* @@ -282,24 +225,35 @@ ossl_dh_is_private(VALUE self) * dh.to_pem -> aString * dh.to_s -> aString * - * Encodes this DH to its PEM encoding. Note that any existing per-session - * public/private keys will *not* get encoded, just the Diffie-Hellman - * parameters will be encoded. + * Serializes the DH parameters to a PEM-encoding. + * + * Note that any existing per-session public/private keys will *not* get + * encoded, just the Diffie-Hellman parameters will be encoded. + * + * PEM-encoded parameters will look like: + * + * -----BEGIN DH PARAMETERS----- + * [...] + * -----END DH PARAMETERS----- + * + * See also #public_to_pem (X.509 SubjectPublicKeyInfo) and + * #private_to_pem (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) for + * serialization with the private or public key components. */ static VALUE ossl_dh_export(VALUE self) { - EVP_PKEY *pkey; + OSSL_3_const DH *dh; BIO *out; VALUE str; - GetPKeyDH(self, pkey); + GetDH(self, dh); if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eDHError, NULL); + ossl_raise(ePKeyError, NULL); } - if (!PEM_write_bio_DHparams(out, pkey->pkey.dh)) { - BIO_free(out); - ossl_raise(eDHError, NULL); + if (!PEM_write_bio_DHparams(out, dh)) { + BIO_free(out); + ossl_raise(ePKeyError, NULL); } str = ossl_membio2str(out); @@ -310,26 +264,30 @@ ossl_dh_export(VALUE self) * call-seq: * dh.to_der -> aString * - * Encodes this DH to its DER encoding. Note that any existing per-session - * public/private keys will *not* get encoded, just the Diffie-Hellman - * parameters will be encoded. - + * Serializes the DH parameters to a DER-encoding + * + * Note that any existing per-session public/private keys will *not* get + * encoded, just the Diffie-Hellman parameters will be encoded. + * + * See also #public_to_der (X.509 SubjectPublicKeyInfo) and + * #private_to_der (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) for + * serialization with the private or public key components. */ static VALUE ossl_dh_to_der(VALUE self) { - EVP_PKEY *pkey; + OSSL_3_const DH *dh; unsigned char *p; long len; VALUE str; - GetPKeyDH(self, pkey); - if((len = i2d_DHparams(pkey->pkey.dh, NULL)) <= 0) - ossl_raise(eDHError, NULL); + GetDH(self, dh); + if((len = i2d_DHparams(dh, NULL)) <= 0) + ossl_raise(ePKeyError, NULL); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); - if(i2d_DHparams(pkey->pkey.dh, &p) < 0) - ossl_raise(eDHError, NULL); + if(i2d_DHparams(dh, &p) < 0) + ossl_raise(ePKeyError, NULL); ossl_str_adjust(str, p); return str; @@ -337,252 +295,61 @@ ossl_dh_to_der(VALUE self) /* * call-seq: - * dh.params -> hash - * - * Stores all parameters of key to the hash - * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! - * Don't use :-)) (I's up to you) - */ -static VALUE -ossl_dh_get_params(VALUE self) -{ - EVP_PKEY *pkey; - VALUE hash; - - GetPKeyDH(self, pkey); - - hash = rb_hash_new(); - - rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dh->p)); - rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dh->g)); - rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dh->pub_key)); - rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dh->priv_key)); - - return hash; -} - -/* - * call-seq: - * dh.to_text -> aString - * - * Prints all parameters of key to buffer - * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! - * Don't use :-)) (I's up to you) - */ -static VALUE -ossl_dh_to_text(VALUE self) -{ - EVP_PKEY *pkey; - BIO *out; - VALUE str; - - GetPKeyDH(self, pkey); - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eDHError, NULL); - } - if (!DHparams_print(out, pkey->pkey.dh)) { - BIO_free(out); - ossl_raise(eDHError, NULL); - } - str = ossl_membio2str(out); - - return str; -} - -/* - * call-seq: - * dh.public_key -> aDH - * - * Returns a new DH instance that carries just the public information, i.e. - * the prime +p+ and the generator +g+, but no public/private key yet. Such - * a pair may be generated using DH#generate_key!. The "public key" needed - * for a key exchange with DH#compute_key is considered as per-session - * information and may be retrieved with DH#pub_key once a key pair has - * been generated. - * If the current instance already contains private information (and thus a - * valid public/private key pair), this information will no longer be present - * in the new instance generated by DH#public_key. This feature is helpful for - * publishing the Diffie-Hellman parameters without leaking any of the private - * per-session information. - * - * === Example - * dh = OpenSSL::PKey::DH.new(2048) # has public and private key set - * public_key = dh.public_key # contains only prime and generator - * parameters = public_key.to_der # it's safe to publish this - */ -static VALUE -ossl_dh_to_public_key(VALUE self) -{ - EVP_PKEY *pkey; - DH *dh; - VALUE obj; - - GetPKeyDH(self, pkey); - dh = DHparams_dup(pkey->pkey.dh); /* err check perfomed by dh_instance */ - obj = dh_instance(CLASS_OF(self), dh); - if (obj == Qfalse) { - DH_free(dh); - ossl_raise(eDHError, NULL); - } - - return obj; -} - -/* - * call-seq: * dh.params_ok? -> true | false * * Validates the Diffie-Hellman parameters associated with this instance. * It checks whether a safe prime and a suitable generator are used. If this * is not the case, +false+ is returned. + * + * See also the man page EVP_PKEY_param_check(3). */ static VALUE ossl_dh_check_params(VALUE self) { - DH *dh; + int ret; +#ifdef HAVE_EVP_PKEY_CHECK EVP_PKEY *pkey; + EVP_PKEY_CTX *pctx; + + GetPKey(self, pkey); + pctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!pctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + ret = EVP_PKEY_param_check(pctx); + EVP_PKEY_CTX_free(pctx); +#else + DH *dh; int codes; - GetPKeyDH(self, pkey); - dh = pkey->pkey.dh; + GetDH(self, dh); + ret = DH_check(dh, &codes) == 1 && codes == 0; +#endif - if (!DH_check(dh, &codes)) { - return Qfalse; + if (ret == 1) + return Qtrue; + else { + /* DH_check_ex() will put error entry on failure */ + ossl_clear_error(); + return Qfalse; } - - return codes == 0 ? Qtrue : Qfalse; } /* - * call-seq: - * dh.generate_key! -> self - * - * Generates a private and public key unless a private key already exists. - * If this DH instance was generated from public DH parameters (e.g. by - * encoding the result of DH#public_key), then this method needs to be - * called first in order to generate the per-session keys before performing - * the actual key exchange. + * Document-method: OpenSSL::PKey::DH#set_pqg + * call-seq: + * dh.set_pqg(p, q, g) -> self * - * === Example - * dh = OpenSSL::PKey::DH.new(2048) - * public_key = dh.public_key #contains no private/public key yet - * public_key.generate_key! - * puts public_key.private? # => true + * Sets _p_, _q_, _g_ to the DH instance. */ -static VALUE -ossl_dh_generate_key(VALUE self) -{ - DH *dh; - EVP_PKEY *pkey; - - GetPKeyDH(self, pkey); - dh = pkey->pkey.dh; - - if (!DH_generate_key(dh)) - ossl_raise(eDHError, "Failed to generate key"); - return self; -} - +OSSL_PKEY_BN_DEF3(dh, DH, pqg, p, q, g) /* - * call-seq: - * dh.compute_key(pub_bn) -> aString + * Document-method: OpenSSL::PKey::DH#set_key + * call-seq: + * dh.set_key(pub_key, priv_key) -> self * - * Returns a String containing a shared secret computed from the other party's public value. - * See DH_compute_key() for further information. - * - * === Parameters - * * +pub_bn+ is a OpenSSL::BN, *not* the DH instance returned by - * DH#public_key as that contains the DH parameters only. + * Sets _pub_key_ and _priv_key_ for the DH instance. _priv_key_ may be +nil+. */ -static VALUE -ossl_dh_compute_key(VALUE self, VALUE pub) -{ - DH *dh; - EVP_PKEY *pkey; - BIGNUM *pub_key; - VALUE str; - int len; - - GetPKeyDH(self, pkey); - dh = pkey->pkey.dh; - pub_key = GetBNPtr(pub); - len = DH_size(dh); - str = rb_str_new(0, len); - if ((len = DH_compute_key((unsigned char *)RSTRING_PTR(str), pub_key, dh)) < 0) { - ossl_raise(eDHError, NULL); - } - rb_str_set_len(str, len); - - return str; -} - -OSSL_PKEY_BN(dh, p) -OSSL_PKEY_BN(dh, g) -OSSL_PKEY_BN(dh, pub_key) -OSSL_PKEY_BN(dh, priv_key) - -/* - * -----BEGIN DH PARAMETERS----- - * MEYCQQD0zXHljRg/mJ9PYLACLv58Cd8VxBxxY7oEuCeURMiTqEhMym16rhhKgZG2 - * zk2O9uUIBIxSj+NKMURHGaFKyIvLAgEC - * -----END DH PARAMETERS----- - */ -static unsigned char DEFAULT_DH_512_PRIM[] = { - 0xf4, 0xcd, 0x71, 0xe5, 0x8d, 0x18, 0x3f, 0x98, - 0x9f, 0x4f, 0x60, 0xb0, 0x02, 0x2e, 0xfe, 0x7c, - 0x09, 0xdf, 0x15, 0xc4, 0x1c, 0x71, 0x63, 0xba, - 0x04, 0xb8, 0x27, 0x94, 0x44, 0xc8, 0x93, 0xa8, - 0x48, 0x4c, 0xca, 0x6d, 0x7a, 0xae, 0x18, 0x4a, - 0x81, 0x91, 0xb6, 0xce, 0x4d, 0x8e, 0xf6, 0xe5, - 0x08, 0x04, 0x8c, 0x52, 0x8f, 0xe3, 0x4a, 0x31, - 0x44, 0x47, 0x19, 0xa1, 0x4a, 0xc8, 0x8b, 0xcb, -}; -static unsigned char DEFAULT_DH_512_GEN[] = { 0x02 }; -DH *OSSL_DEFAULT_DH_512 = NULL; - -/* - * -----BEGIN DH PARAMETERS----- - * MIGHAoGBAJ0lOVy0VIr/JebWn0zDwY2h+rqITFOpdNr6ugsgvkDXuucdcChhYExJ - * AV/ZD2AWPbrTqV76mGRgJg4EddgT1zG0jq3rnFdMj2XzkBYx3BVvfR0Arnby0RHR - * T4h7KZ/2zmjvV+eF8kBUHBJAojUlzxKj4QeO2x20FP9X5xmNUXeDAgEC - * -----END DH PARAMETERS----- - */ -static unsigned char DEFAULT_DH_1024_PRIM[] = { - 0x9d, 0x25, 0x39, 0x5c, 0xb4, 0x54, 0x8a, 0xff, - 0x25, 0xe6, 0xd6, 0x9f, 0x4c, 0xc3, 0xc1, 0x8d, - 0xa1, 0xfa, 0xba, 0x88, 0x4c, 0x53, 0xa9, 0x74, - 0xda, 0xfa, 0xba, 0x0b, 0x20, 0xbe, 0x40, 0xd7, - 0xba, 0xe7, 0x1d, 0x70, 0x28, 0x61, 0x60, 0x4c, - 0x49, 0x01, 0x5f, 0xd9, 0x0f, 0x60, 0x16, 0x3d, - 0xba, 0xd3, 0xa9, 0x5e, 0xfa, 0x98, 0x64, 0x60, - 0x26, 0x0e, 0x04, 0x75, 0xd8, 0x13, 0xd7, 0x31, - 0xb4, 0x8e, 0xad, 0xeb, 0x9c, 0x57, 0x4c, 0x8f, - 0x65, 0xf3, 0x90, 0x16, 0x31, 0xdc, 0x15, 0x6f, - 0x7d, 0x1d, 0x00, 0xae, 0x76, 0xf2, 0xd1, 0x11, - 0xd1, 0x4f, 0x88, 0x7b, 0x29, 0x9f, 0xf6, 0xce, - 0x68, 0xef, 0x57, 0xe7, 0x85, 0xf2, 0x40, 0x54, - 0x1c, 0x12, 0x40, 0xa2, 0x35, 0x25, 0xcf, 0x12, - 0xa3, 0xe1, 0x07, 0x8e, 0xdb, 0x1d, 0xb4, 0x14, - 0xff, 0x57, 0xe7, 0x19, 0x8d, 0x51, 0x77, 0x83 -}; -static unsigned char DEFAULT_DH_1024_GEN[] = { 0x02 }; -DH *OSSL_DEFAULT_DH_1024 = NULL; - -static DH* -ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen) -{ - DH *dh; - - if ((dh = DH_new()) == NULL) ossl_raise(eDHError, NULL); - dh->p = BN_bin2bn(p, rb_long2int(plen), NULL); - dh->g = BN_bin2bn(g, rb_long2int(glen), NULL); - if (dh->p == NULL || dh->g == NULL){ - DH_free(dh); - ossl_raise(eDHError, NULL); - } - - return dh; -} +OSSL_PKEY_BN_DEF2(dh, DH, key, pub_key, priv_key) /* * INIT @@ -590,18 +357,6 @@ ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen) void Init_ossl_dh(void) { -#if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */ - mPKey = rb_define_module_under(mOSSL, "PKey"); -#endif - - /* Document-class: OpenSSL::PKey::DHError - * - * Generic exception that is raised if an operation on a DH PKey - * fails unexpectedly or in case an instantiation of an instance of DH - * fails due to non-conformant input data. - */ - eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError); /* Document-class: OpenSSL::PKey::DH * * An implementation of the Diffie-Hellman key exchange protocol based on @@ -609,53 +364,52 @@ Init_ossl_dh(void) * on. * * === Accessor methods for the Diffie-Hellman parameters - * * DH#p - * The prime (an OpenSSL::BN) of the Diffie-Hellman parameters. - * * DH#g - * The generator (an OpenSSL::BN) g of the Diffie-Hellman parameters. - * * DH#pub_key - * The per-session public key (an OpenSSL::BN) matching the private key. - * This needs to be passed to DH#compute_key. - * * DH#priv_key - * The per-session private key, an OpenSSL::BN. + * DH#p:: + * The prime (an OpenSSL::BN) of the Diffie-Hellman parameters. + * DH#g:: + * The generator (an OpenSSL::BN) g of the Diffie-Hellman parameters. + * DH#pub_key:: + * The per-session public key (an OpenSSL::BN) matching the private key. + * This needs to be passed to DH#compute_key. + * DH#priv_key:: + * The per-session private key, an OpenSSL::BN. * * === Example of a key exchange - * dh1 = OpenSSL::PKey::DH.new(2048) - * der = dh1.public_key.to_der #you may send this publicly to the participating party - * dh2 = OpenSSL::PKey::DH.new(der) - * dh2.generate_key! #generate the per-session key pair - * symm_key1 = dh1.compute_key(dh2.pub_key) - * symm_key2 = dh2.compute_key(dh1.pub_key) + * # you may send the parameters (der) and own public key (pub1) publicly + * # to the participating party + * dh1 = OpenSSL::PKey::DH.new(2048) + * der = dh1.to_der + * pub1 = dh1.pub_key * - * puts symm_key1 == symm_key2 # => true + * # the other party generates its per-session key pair + * dhparams = OpenSSL::PKey::DH.new(der) + * dh2 = OpenSSL::PKey.generate_key(dhparams) + * pub2 = dh2.pub_key + * + * symm_key1 = dh1.compute_key(pub2) + * symm_key2 = dh2.compute_key(pub1) + * puts symm_key1 == symm_key2 # => true */ cDH = rb_define_class_under(mPKey, "DH", cPKey); - rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1); rb_define_method(cDH, "initialize", ossl_dh_initialize, -1); +#ifndef HAVE_EVP_PKEY_DUP + rb_define_method(cDH, "initialize_copy", ossl_dh_initialize_copy, 1); +#endif rb_define_method(cDH, "public?", ossl_dh_is_public, 0); rb_define_method(cDH, "private?", ossl_dh_is_private, 0); - rb_define_method(cDH, "to_text", ossl_dh_to_text, 0); rb_define_method(cDH, "export", ossl_dh_export, 0); rb_define_alias(cDH, "to_pem", "export"); rb_define_alias(cDH, "to_s", "export"); rb_define_method(cDH, "to_der", ossl_dh_to_der, 0); - rb_define_method(cDH, "public_key", ossl_dh_to_public_key, 0); rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0); - rb_define_method(cDH, "generate_key!", ossl_dh_generate_key, 0); - rb_define_method(cDH, "compute_key", ossl_dh_compute_key, 1); DEF_OSSL_PKEY_BN(cDH, dh, p); + DEF_OSSL_PKEY_BN(cDH, dh, q); DEF_OSSL_PKEY_BN(cDH, dh, g); DEF_OSSL_PKEY_BN(cDH, dh, pub_key); DEF_OSSL_PKEY_BN(cDH, dh, priv_key); - rb_define_method(cDH, "params", ossl_dh_get_params, 0); - - OSSL_DEFAULT_DH_512 = ossl_create_dh( - DEFAULT_DH_512_PRIM, sizeof(DEFAULT_DH_512_PRIM), - DEFAULT_DH_512_GEN, sizeof(DEFAULT_DH_512_GEN)); - OSSL_DEFAULT_DH_1024 = ossl_create_dh( - DEFAULT_DH_1024_PRIM, sizeof(DEFAULT_DH_1024_PRIM), - DEFAULT_DH_1024_GEN, sizeof(DEFAULT_DH_1024_GEN)); + rb_define_method(cDH, "set_pqg", ossl_dh_set_pqg, 3); + rb_define_method(cDH, "set_key", ossl_dh_set_key, 2); } #else /* defined NO_DH */ diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index 979ae154e9..041646a058 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -1,259 +1,181 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ -#if !defined(OPENSSL_NO_DSA) - #include "ossl.h" +#if !defined(OPENSSL_NO_DSA) + #define GetPKeyDSA(obj, pkey) do { \ GetPKey((obj), (pkey)); \ - if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_DSA) { /* PARANOIA? */ \ - ossl_raise(rb_eRuntimeError, "THIS IS NOT A DSA!"); \ + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DSA) { /* PARANOIA? */ \ + ossl_raise(rb_eRuntimeError, "THIS IS NOT A DSA!"); \ } \ } while (0) +#define GetDSA(obj, dsa) do { \ + EVP_PKEY *_pkey; \ + GetPKeyDSA((obj), _pkey); \ + (dsa) = EVP_PKEY_get0_DSA(_pkey); \ + if ((dsa) == NULL) \ + ossl_raise(ePKeyError, "failed to get DSA from EVP_PKEY"); \ +} while (0) -#define DSA_HAS_PRIVATE(dsa) ((dsa)->priv_key) -#define DSA_PRIVATE(obj,dsa) (DSA_HAS_PRIVATE(dsa)||OSSL_PKEY_IS_PRIVATE(obj)) - -/* - * Classes - */ -VALUE cDSA; -VALUE eDSAError; - -/* - * Public - */ -static VALUE -dsa_instance(VALUE klass, DSA *dsa) +static inline int +DSA_HAS_PRIVATE(OSSL_3_const DSA *dsa) { - EVP_PKEY *pkey; - VALUE obj; - - if (!dsa) { - return Qfalse; - } - if (!(pkey = EVP_PKEY_new())) { - return Qfalse; - } - if (!EVP_PKEY_assign_DSA(pkey, dsa)) { - EVP_PKEY_free(pkey); - return Qfalse; - } - WrapPKey(klass, obj, pkey); - - return obj; + const BIGNUM *bn; + DSA_get0_key(dsa, NULL, &bn); + return !!bn; } -VALUE -ossl_dsa_new(EVP_PKEY *pkey) +static inline int +DSA_PRIVATE(VALUE obj, OSSL_3_const DSA *dsa) { - VALUE obj; - - if (!pkey) { - obj = dsa_instance(cDSA, DSA_new()); - } else { - if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DSA) { - ossl_raise(rb_eTypeError, "Not a DSA key!"); - } - WrapPKey(cDSA, obj, pkey); - } - if (obj == Qfalse) { - ossl_raise(eDSAError, NULL); - } - - return obj; + return DSA_HAS_PRIVATE(dsa) || OSSL_PKEY_IS_PRIVATE(obj); } /* - * Private + * Classes */ -#if defined(HAVE_DSA_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB -struct dsa_blocking_gen_arg { - DSA *dsa; - int size; - unsigned char* seed; - int seed_len; - int *counter; - unsigned long *h; - BN_GENCB *cb; - int result; -}; - -static void * -dsa_blocking_gen(void *arg) -{ - struct dsa_blocking_gen_arg *gen = (struct dsa_blocking_gen_arg *)arg; - gen->result = DSA_generate_parameters_ex(gen->dsa, gen->size, gen->seed, gen->seed_len, gen->counter, gen->h, gen->cb); - return 0; -} -#endif - -static DSA * -dsa_generate(int size) -{ -#if defined(HAVE_DSA_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB - BN_GENCB cb; - struct ossl_generate_cb_arg cb_arg; - struct dsa_blocking_gen_arg gen_arg; - DSA *dsa = DSA_new(); - unsigned char seed[20]; - int seed_len = 20, counter; - unsigned long h; - - if (!dsa) return 0; - if (!RAND_bytes(seed, seed_len)) { - DSA_free(dsa); - return 0; - } - - memset(&cb_arg, 0, sizeof(struct ossl_generate_cb_arg)); - if (rb_block_given_p()) - cb_arg.yield = 1; - BN_GENCB_set(&cb, ossl_generate_cb_2, &cb_arg); - gen_arg.dsa = dsa; - gen_arg.size = size; - gen_arg.seed = seed; - gen_arg.seed_len = seed_len; - gen_arg.counter = &counter; - gen_arg.h = &h; - gen_arg.cb = &cb; - if (cb_arg.yield == 1) { - /* we cannot release GVL when callback proc is supplied */ - dsa_blocking_gen(&gen_arg); - } else { - /* there's a chance to unblock */ - rb_thread_call_without_gvl(dsa_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg); - } - if (!gen_arg.result) { - DSA_free(dsa); - if (cb_arg.state) rb_jump_tag(cb_arg.state); - return 0; - } -#else - DSA *dsa; - unsigned char seed[20]; - int seed_len = 20, counter; - unsigned long h; - - if (!RAND_bytes(seed, seed_len)) { - return 0; - } - dsa = DSA_generate_parameters(size, seed, seed_len, &counter, &h, - rb_block_given_p() ? ossl_generate_cb : NULL, NULL); - if(!dsa) return 0; -#endif - - if (!DSA_generate_key(dsa)) { - DSA_free(dsa); - return 0; - } - - return dsa; -} +VALUE cDSA; /* + * Private + */ +/* * call-seq: - * DSA.generate(size) -> dsa + * DSA.new -> dsa + * DSA.new(string [, pass]) -> dsa + * DSA.new(size) -> dsa * - * Creates a new DSA instance by generating a private/public key pair - * from scratch. + * Creates a new DSA instance by reading an existing key from _string_. * - * === Parameters - * * +size+ is an integer representing the desired key size. + * If called without arguments, creates a new instance with no key components + * set. They can be set individually by #set_pqg and #set_key. + * This form is not compatible with OpenSSL 3.0 or later. * - */ -static VALUE -ossl_dsa_s_generate(VALUE klass, VALUE size) -{ - DSA *dsa = dsa_generate(NUM2INT(size)); /* err handled by dsa_instance */ - VALUE obj = dsa_instance(klass, dsa); - - if (obj == Qfalse) { - DSA_free(dsa); - ossl_raise(eDSAError, NULL); - } - - return obj; -} - -/* - * call-seq: - * DSA.new([size | string [, pass]) -> dsa + * If called with a String, tries to parse as DER or PEM encoding of a \DSA key. + * See also OpenSSL::PKey.read which can parse keys of any kinds. * - * Creates a new DSA instance by reading an existing key from +string+. + * If called with a number, generates random parameters and a key pair. This + * form works as an alias of DSA.generate. * - * === Parameters - * * +size+ is an integer representing the desired key size. - * * +string+ contains a DER or PEM encoded key. - * * +pass+ is a string that contains an optional password. + * +string+:: + * A String that contains a DER or PEM encoded key. + * +pass+:: + * A String that contains an optional password. + * +size+:: + * See DSA.generate. * - * === Examples - * DSA.new -> dsa - * DSA.new(1024) -> dsa - * DSA.new(File.read('dsa.pem')) -> dsa - * DSA.new(File.read('dsa.pem'), 'mypassword') -> dsa + * Examples: + * p OpenSSL::PKey::DSA.new(1024) + * #=> #<OpenSSL::PKey::DSA:0x000055a8d6025bf0 oid=DSA> * + * p OpenSSL::PKey::DSA.new(File.read('dsa.pem')) + * #=> #<OpenSSL::PKey::DSA:0x000055555d6b8110 oid=DSA> + * + * p OpenSSL::PKey::DSA.new(File.read('dsa.pem'), 'mypassword') + * #=> #<OpenSSL::PKey::DSA:0x0000556f973c40b8 oid=DSA> */ static VALUE ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; DSA *dsa; - BIO *in; - char *passwd = NULL; + BIO *in = NULL; VALUE arg, pass; - - GetPKey(self, pkey); - if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) { + int type; + + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); + + /* The DSA.new(size, generator) form is handled by lib/openssl/pkey.rb */ + rb_scan_args(argc, argv, "02", &arg, &pass); + if (argc == 0) { +#ifdef OSSL_HAVE_IMMUTABLE_PKEY + rb_raise(rb_eArgError, "OpenSSL::PKey::DSA.new cannot be called " \ + "without arguments; pkeys are immutable with OpenSSL 3.0"); +#else dsa = DSA_new(); + if (!dsa) + ossl_raise(ePKeyError, "DSA_new"); + goto legacy; +#endif } - else if (FIXNUM_P(arg)) { - if (!(dsa = dsa_generate(FIX2INT(arg)))) { - ossl_raise(eDSAError, NULL); - } + + pass = ossl_pem_passwd_value(pass); + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(&arg); + + /* DER-encoded DSAPublicKey format isn't supported by the generic routine */ + dsa = (DSA *)PEM_ASN1_read_bio((d2i_of_void *)d2i_DSAPublicKey, + PEM_STRING_DSA_PUBLIC, + in, NULL, NULL, NULL); + if (dsa) + goto legacy; + OSSL_BIO_reset(in); + + pkey = ossl_pkey_read_generic(in, pass); + BIO_free(in); + if (!pkey) + ossl_raise(ePKeyError, "Neither PUB key nor PRIV key"); + + type = EVP_PKEY_base_id(pkey); + if (type != EVP_PKEY_DSA) { + EVP_PKEY_free(pkey); + rb_raise(ePKeyError, "incorrect pkey type: %s", OBJ_nid2sn(type)); } - else { - if (!NIL_P(pass)) passwd = StringValuePtr(pass); - arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(arg); - dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd); - if (!dsa) { - OSSL_BIO_reset(in); - dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL); - } - if (!dsa) { - OSSL_BIO_reset(in); - dsa = d2i_DSAPrivateKey_bio(in, NULL); - } - if (!dsa) { - OSSL_BIO_reset(in); - dsa = d2i_DSA_PUBKEY_bio(in, NULL); - } - if (!dsa) { - OSSL_BIO_reset(in); - dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL); - } - BIO_free(in); - if (!dsa) { - ERR_clear_error(); - ossl_raise(eDSAError, "Neither PUB key nor PRIV key"); - } + RTYPEDDATA_DATA(self) = pkey; + return self; + + legacy: + BIO_free(in); + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_DSA(pkey, dsa) != 1) { + EVP_PKEY_free(pkey); + DSA_free(dsa); + ossl_raise(ePKeyError, "EVP_PKEY_assign_DSA"); } - if (!EVP_PKEY_assign_DSA(pkey, dsa)) { - DSA_free(dsa); - ossl_raise(eDSAError, NULL); + RTYPEDDATA_DATA(self) = pkey; + return self; +} + +#ifndef HAVE_EVP_PKEY_DUP +/* :nodoc: */ +static VALUE +ossl_dsa_initialize_copy(VALUE self, VALUE other) +{ + EVP_PKEY *pkey; + DSA *dsa, *dsa_new; + + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); + GetDSA(other, dsa); + + dsa_new = (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey, + (d2i_of_void *)d2i_DSAPrivateKey, + (char *)dsa); + if (!dsa_new) + ossl_raise(ePKeyError, "ASN1_dup"); + + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_DSA(pkey, dsa_new) != 1) { + EVP_PKEY_free(pkey); + DSA_free(dsa_new); + ossl_raise(ePKeyError, "EVP_PKEY_assign_DSA"); } + RTYPEDDATA_DATA(self) = pkey; return self; } +#endif /* * call-seq: @@ -265,11 +187,13 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) static VALUE ossl_dsa_is_public(VALUE self) { - EVP_PKEY *pkey; + const DSA *dsa; + const BIGNUM *bn; - GetPKeyDSA(self, pkey); + GetDSA(self, dsa); + DSA_get0_key(dsa, &bn, NULL); - return (pkey->pkey.dsa->pub_key) ? Qtrue : Qfalse; + return bn ? Qtrue : Qfalse; } /* @@ -282,11 +206,11 @@ ossl_dsa_is_public(VALUE self) static VALUE ossl_dsa_is_private(VALUE self) { - EVP_PKEY *pkey; + OSSL_3_const DSA *dsa; - GetPKeyDSA(self, pkey); + GetDSA(self, dsa); - return (DSA_PRIVATE(self, pkey->pkey.dsa)) ? Qtrue : Qfalse; + return DSA_PRIVATE(self, dsa) ? Qtrue : Qfalse; } /* @@ -295,269 +219,114 @@ ossl_dsa_is_private(VALUE self) * dsa.to_pem([cipher, password]) -> aString * dsa.to_s([cipher, password]) -> aString * - * Encodes this DSA to its PEM encoding. + * Serializes a private or public key to a PEM-encoding. * - * === Parameters - * * +cipher+ is an OpenSSL::Cipher. - * * +password+ is a string containing your password. + * [When the key contains public components only] * - * === Examples - * DSA.to_pem -> aString - * DSA.to_pem(cipher, 'mypassword') -> aString + * Serializes it into an X.509 SubjectPublicKeyInfo. + * The parameters _cipher_ and _password_ are ignored. * - */ -static VALUE -ossl_dsa_export(int argc, VALUE *argv, VALUE self) -{ - EVP_PKEY *pkey; - BIO *out; - const EVP_CIPHER *ciph = NULL; - char *passwd = NULL; - VALUE cipher, pass, str; - - GetPKeyDSA(self, pkey); - rb_scan_args(argc, argv, "02", &cipher, &pass); - if (!NIL_P(cipher)) { - ciph = GetCipherPtr(cipher); - if (!NIL_P(pass)) { - StringValue(pass); - if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN) - ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long"); - passwd = RSTRING_PTR(pass); - } - } - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eDSAError, NULL); - } - if (DSA_HAS_PRIVATE(pkey->pkey.dsa)) { - if (!PEM_write_bio_DSAPrivateKey(out, pkey->pkey.dsa, ciph, - NULL, 0, ossl_pem_passwd_cb, passwd)){ - BIO_free(out); - ossl_raise(eDSAError, NULL); - } - } else { - if (!PEM_write_bio_DSA_PUBKEY(out, pkey->pkey.dsa)) { - BIO_free(out); - ossl_raise(eDSAError, NULL); - } - } - str = ossl_membio2str(out); - - return str; -} - -/* - * call-seq: - * dsa.to_der -> aString + * A PEM-encoded key will look like: * - * Encodes this DSA to its DER encoding. + * -----BEGIN PUBLIC KEY----- + * [...] + * -----END PUBLIC KEY----- * - */ -static VALUE -ossl_dsa_to_der(VALUE self) -{ - EVP_PKEY *pkey; - int (*i2d_func)_((DSA*, unsigned char**)); - unsigned char *p; - long len; - VALUE str; - - GetPKeyDSA(self, pkey); - if(DSA_HAS_PRIVATE(pkey->pkey.dsa)) - i2d_func = (int(*)_((DSA*,unsigned char**)))i2d_DSAPrivateKey; - else - i2d_func = i2d_DSA_PUBKEY; - if((len = i2d_func(pkey->pkey.dsa, NULL)) <= 0) - ossl_raise(eDSAError, NULL); - str = rb_str_new(0, len); - p = (unsigned char *)RSTRING_PTR(str); - if(i2d_func(pkey->pkey.dsa, &p) < 0) - ossl_raise(eDSAError, NULL); - ossl_str_adjust(str, p); - - return str; -} - -/* - * call-seq: - * dsa.params -> hash + * Consider using #public_to_pem instead. This serializes the key into an + * X.509 SubjectPublicKeyInfo regardless of whether it is a public key + * or a private key. * - * Stores all parameters of key to the hash - * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! - * Don't use :-)) (I's up to you) - */ -static VALUE -ossl_dsa_get_params(VALUE self) -{ - EVP_PKEY *pkey; - VALUE hash; - - GetPKeyDSA(self, pkey); - - hash = rb_hash_new(); - - rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dsa->p)); - rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(pkey->pkey.dsa->q)); - rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dsa->g)); - rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dsa->pub_key)); - rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dsa->priv_key)); - - return hash; -} - -/* - * call-seq: - * dsa.to_text -> aString + * [When the key contains private components, and no parameters are given] * - * Prints all parameters of key to buffer - * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! - * Don't use :-)) (I's up to you) - */ -static VALUE -ossl_dsa_to_text(VALUE self) -{ - EVP_PKEY *pkey; - BIO *out; - VALUE str; - - GetPKeyDSA(self, pkey); - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eDSAError, NULL); - } - if (!DSA_print(out, pkey->pkey.dsa, 0)) { /* offset = 0 */ - BIO_free(out); - ossl_raise(eDSAError, NULL); - } - str = ossl_membio2str(out); - - return str; -} - -/* - * call-seq: - * dsa.public_key -> aDSA + * Serializes it into a traditional \OpenSSL DSAPrivateKey. * - * Returns a new DSA instance that carries just the public key information. - * If the current instance has also private key information, this will no - * longer be present in the new instance. This feature is helpful for - * publishing the public key information without leaking any of the private - * information. + * A PEM-encoded key will look like: * - * === Example - * dsa = OpenSSL::PKey::DSA.new(2048) # has public and private information - * pub_key = dsa.public_key # has only the public part available - * pub_key_der = pub_key.to_der # it's safe to publish this + * -----BEGIN DSA PRIVATE KEY----- + * [...] + * -----END DSA PRIVATE KEY----- * + * [When the key contains private components, and _cipher_ and _password_ are given] * - */ -static VALUE -ossl_dsa_to_public_key(VALUE self) -{ - EVP_PKEY *pkey; - DSA *dsa; - VALUE obj; - - GetPKeyDSA(self, pkey); - /* err check performed by dsa_instance */ - dsa = DSAPublicKey_dup(pkey->pkey.dsa); - obj = dsa_instance(CLASS_OF(self), dsa); - if (obj == Qfalse) { - DSA_free(dsa); - ossl_raise(eDSAError, NULL); - } - return obj; -} - -#define ossl_dsa_buf_size(pkey) (DSA_size((pkey)->pkey.dsa)+16) - -/* - * call-seq: - * dsa.syssign(string) -> aString + * Serializes it into a traditional \OpenSSL DSAPrivateKey and encrypts it in + * OpenSSL's traditional PEM encryption format. + * _cipher_ must be a cipher name understood by OpenSSL::Cipher.new or an + * instance of OpenSSL::Cipher. * - * Computes and returns the DSA signature of +string+, where +string+ is - * expected to be an already-computed message digest of the original input - * data. The signature is issued using the private key of this DSA instance. + * An encrypted PEM-encoded key will look like: * - * === Parameters - * * +string+ is a message digest of the original input data to be signed + * -----BEGIN DSA PRIVATE KEY----- + * Proc-Type: 4,ENCRYPTED + * DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 * - * === Example - * dsa = OpenSSL::PKey::DSA.new(2048) - * doc = "Sign me" - * digest = OpenSSL::Digest::SHA1.digest(doc) - * sig = dsa.syssign(digest) + * [...] + * -----END DSA PRIVATE KEY----- * + * Note that this format uses MD5 to derive the encryption key, and hence + * will not be available on FIPS-compliant systems. * + * <b>This method is kept for compatibility.</b> + * This should only be used when the traditional, non-standard \OpenSSL format + * is required. + * + * Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem + * (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead. */ static VALUE -ossl_dsa_sign(VALUE self, VALUE data) +ossl_dsa_export(int argc, VALUE *argv, VALUE self) { - EVP_PKEY *pkey; - unsigned int buf_len; - VALUE str; + OSSL_3_const DSA *dsa; - GetPKeyDSA(self, pkey); - StringValue(data); - if (!DSA_PRIVATE(self, pkey->pkey.dsa)) { - ossl_raise(eDSAError, "Private DSA key needed!"); - } - str = rb_str_new(0, ossl_dsa_buf_size(pkey)); - if (!DSA_sign(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data), - (unsigned char *)RSTRING_PTR(str), - &buf_len, pkey->pkey.dsa)) { /* type is ignored (0) */ - ossl_raise(eDSAError, NULL); - } - rb_str_set_len(str, buf_len); - - return str; + GetDSA(self, dsa); + if (DSA_HAS_PRIVATE(dsa)) + return ossl_pkey_export_traditional(argc, argv, self, 0); + else + return ossl_pkey_export_spki(self, 0); } /* * call-seq: - * dsa.sysverify(digest, sig) -> true | false + * dsa.to_der -> aString * - * Verifies whether the signature is valid given the message digest input. It - * does so by validating +sig+ using the public key of this DSA instance. + * Serializes a private or public key to a DER-encoding. * - * === Parameters - * * +digest+ is a message digest of the original input data to be signed - * * +sig+ is a DSA signature value + * See #to_pem for details. * - * === Example - * dsa = OpenSSL::PKey::DSA.new(2048) - * doc = "Sign me" - * digest = OpenSSL::Digest::SHA1.digest(doc) - * sig = dsa.syssign(digest) - * puts dsa.sysverify(digest, sig) # => true + * <b>This method is kept for compatibility.</b> + * This should only be used when the traditional, non-standard \OpenSSL format + * is required. * + * Consider using #public_to_der or #private_to_der instead. */ static VALUE -ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig) +ossl_dsa_to_der(VALUE self) { - EVP_PKEY *pkey; - int ret; - - GetPKeyDSA(self, pkey); - StringValue(digest); - StringValue(sig); - /* type is ignored (0) */ - ret = DSA_verify(0, (unsigned char *)RSTRING_PTR(digest), RSTRING_LENINT(digest), - (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), pkey->pkey.dsa); - if (ret < 0) { - ossl_raise(eDSAError, NULL); - } - else if (ret == 1) { - return Qtrue; - } + OSSL_3_const DSA *dsa; - return Qfalse; + GetDSA(self, dsa); + if (DSA_HAS_PRIVATE(dsa)) + return ossl_pkey_export_traditional(0, NULL, self, 1); + else + return ossl_pkey_export_spki(self, 1); } -OSSL_PKEY_BN(dsa, p) -OSSL_PKEY_BN(dsa, q) -OSSL_PKEY_BN(dsa, g) -OSSL_PKEY_BN(dsa, pub_key) -OSSL_PKEY_BN(dsa, priv_key) + +/* + * Document-method: OpenSSL::PKey::DSA#set_pqg + * call-seq: + * dsa.set_pqg(p, q, g) -> self + * + * Sets _p_, _q_, _g_ to the DSA instance. + */ +OSSL_PKEY_BN_DEF3(dsa, DSA, pqg, p, q, g) +/* + * Document-method: OpenSSL::PKey::DSA#set_key + * call-seq: + * dsa.set_key(pub_key, priv_key) -> self + * + * Sets _pub_key_ and _priv_key_ for the DSA instance. _priv_key_ may be +nil+. + */ +OSSL_PKEY_BN_DEF2(dsa, DSA, key, pub_key, priv_key) /* * INIT @@ -565,54 +334,33 @@ OSSL_PKEY_BN(dsa, priv_key) void Init_ossl_dsa(void) { -#if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */ - mPKey = rb_define_module_under(mOSSL, "PKey"); -#endif - - /* Document-class: OpenSSL::PKey::DSAError - * - * Generic exception that is raised if an operation on a DSA PKey - * fails unexpectedly or in case an instantiation of an instance of DSA - * fails due to non-conformant input data. - */ - eDSAError = rb_define_class_under(mPKey, "DSAError", ePKeyError); - /* Document-class: OpenSSL::PKey::DSA * * DSA, the Digital Signature Algorithm, is specified in NIST's * FIPS 186-3. It is an asymmetric public key algorithm that may be used * similar to e.g. RSA. - * Please note that for OpenSSL versions prior to 1.0.0 the digest - * algorithms OpenSSL::Digest::DSS (equivalent to SHA) or - * OpenSSL::Digest::DSS1 (equivalent to SHA-1) must be used for issuing - * signatures with a DSA key using OpenSSL::PKey#sign. - * Starting with OpenSSL 1.0.0, digest algorithms are no longer restricted, - * any Digest may be used for signing. */ cDSA = rb_define_class_under(mPKey, "DSA", cPKey); - rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1); rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1); +#ifndef HAVE_EVP_PKEY_DUP + rb_define_method(cDSA, "initialize_copy", ossl_dsa_initialize_copy, 1); +#endif rb_define_method(cDSA, "public?", ossl_dsa_is_public, 0); rb_define_method(cDSA, "private?", ossl_dsa_is_private, 0); - rb_define_method(cDSA, "to_text", ossl_dsa_to_text, 0); rb_define_method(cDSA, "export", ossl_dsa_export, -1); rb_define_alias(cDSA, "to_pem", "export"); rb_define_alias(cDSA, "to_s", "export"); rb_define_method(cDSA, "to_der", ossl_dsa_to_der, 0); - rb_define_method(cDSA, "public_key", ossl_dsa_to_public_key, 0); - rb_define_method(cDSA, "syssign", ossl_dsa_sign, 1); - rb_define_method(cDSA, "sysverify", ossl_dsa_verify, 2); DEF_OSSL_PKEY_BN(cDSA, dsa, p); DEF_OSSL_PKEY_BN(cDSA, dsa, q); DEF_OSSL_PKEY_BN(cDSA, dsa, g); DEF_OSSL_PKEY_BN(cDSA, dsa, pub_key); DEF_OSSL_PKEY_BN(cDSA, dsa, priv_key); - - rb_define_method(cDSA, "params", ossl_dsa_get_params, 0); + rb_define_method(cDSA, "set_pqg", ossl_dsa_set_pqg, 3); + rb_define_method(cDSA, "set_key", ossl_dsa_set_key, 2); } #else /* defined NO_DSA */ diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index d63f757394..35f031819d 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -4,18 +4,7 @@ #include "ossl.h" -#if !defined(OPENSSL_NO_EC) && (OPENSSL_VERSION_NUMBER >= 0x0090802fL) - -typedef struct { - EC_GROUP *group; - int dont_free; -} ossl_ec_group; - -typedef struct { - EC_POINT *point; - int dont_free; -} ossl_ec_point; - +#if !defined(OPENSSL_NO_EC) #define EXPORT_PEM 0 #define EXPORT_DER 1 @@ -25,295 +14,258 @@ static const rb_data_type_t ossl_ec_point_type; #define GetPKeyEC(obj, pkey) do { \ GetPKey((obj), (pkey)); \ - if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_EC) { \ - ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \ + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) { \ + ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \ } \ } while (0) - -#define SafeGet_ec_group(obj, group) do { \ - OSSL_Check_Kind((obj), cEC_GROUP); \ - TypedData_Get_Struct((obj), ossl_ec_group, &ossl_ec_group_type, (group)); \ -} while(0) - -#define Get_EC_KEY(obj, key) do { \ - EVP_PKEY *pkey; \ - GetPKeyEC((obj), pkey); \ - (key) = pkey->pkey.ec; \ -} while(0) - -#define Require_EC_KEY(obj, key) do { \ - Get_EC_KEY((obj), (key)); \ +#define GetEC(obj, key) do { \ + EVP_PKEY *_pkey; \ + GetPKeyEC(obj, _pkey); \ + (key) = EVP_PKEY_get0_EC_KEY(_pkey); \ if ((key) == NULL) \ - ossl_raise(eECError, "EC_KEY is not initialized"); \ -} while(0) - -#define SafeRequire_EC_KEY(obj, key) do { \ - OSSL_Check_Kind((obj), cEC); \ - Require_EC_KEY((obj), (key)); \ + ossl_raise(ePKeyError, "failed to get EC_KEY from EVP_PKEY"); \ } while (0) -#define Get_EC_GROUP(obj, g) do { \ - ossl_ec_group *ec_group; \ - TypedData_Get_Struct((obj), ossl_ec_group, &ossl_ec_group_type, ec_group); \ - if (ec_group == NULL) \ - ossl_raise(eEC_GROUP, "missing ossl_ec_group structure"); \ - (g) = ec_group->group; \ -} while(0) - -#define Require_EC_GROUP(obj, group) do { \ - Get_EC_GROUP((obj), (group)); \ +#define GetECGroup(obj, group) do { \ + TypedData_Get_Struct(obj, EC_GROUP, &ossl_ec_group_type, group); \ if ((group) == NULL) \ ossl_raise(eEC_GROUP, "EC_GROUP is not initialized"); \ -} while(0) - -#define SafeRequire_EC_GROUP(obj, group) do { \ - OSSL_Check_Kind((obj), cEC_GROUP); \ - Require_EC_GROUP((obj), (group)); \ -} while(0) - -#define Get_EC_POINT(obj, p) do { \ - ossl_ec_point *ec_point; \ - TypedData_Get_Struct((obj), ossl_ec_point, &ossl_ec_point_type, ec_point); \ - if (ec_point == NULL) \ - ossl_raise(eEC_POINT, "missing ossl_ec_point structure"); \ - (p) = ec_point->point; \ -} while(0) - -#define Require_EC_POINT(obj, point) do { \ - Get_EC_POINT((obj), (point)); \ +} while (0) + +#define GetECPoint(obj, point) do { \ + TypedData_Get_Struct(obj, EC_POINT, &ossl_ec_point_type, point); \ if ((point) == NULL) \ ossl_raise(eEC_POINT, "EC_POINT is not initialized"); \ -} while(0) - -#define SafeRequire_EC_POINT(obj, point) do { \ - OSSL_Check_Kind((obj), cEC_POINT); \ - Require_EC_POINT((obj), (point)); \ -} while(0) +} while (0) +#define GetECPointGroup(obj, group) do { \ + VALUE _group = rb_attr_get(obj, id_i_group); \ + GetECGroup(_group, group); \ +} while (0) VALUE cEC; -VALUE eECError; -VALUE cEC_GROUP; -VALUE eEC_GROUP; -VALUE cEC_POINT; -VALUE eEC_POINT; - -static ID s_GFp; -static ID s_GFp_simple; -static ID s_GFp_mont; -static ID s_GFp_nist; -static ID s_GF2m; -static ID s_GF2m_simple; - -static ID ID_uncompressed; -static ID ID_compressed; -static ID ID_hybrid; - -static VALUE ec_instance(VALUE klass, EC_KEY *ec) +static VALUE cEC_GROUP; +static VALUE eEC_GROUP; +static VALUE cEC_POINT; +static VALUE eEC_POINT; + +static VALUE sym_GFp, sym_GF2m; +static VALUE sym_uncompressed, sym_compressed, sym_hybrid; + +static ID id_i_group; + +static VALUE ec_group_new(const EC_GROUP *group); +static VALUE ec_point_new(const EC_POINT *point, const EC_GROUP *group); + +/* + * Creates a new EC_KEY on the EC group obj. arg can be an EC::Group or a String + * representing an OID. + */ +static EC_KEY * +ec_key_new_from_group(VALUE arg) { - EVP_PKEY *pkey; - VALUE obj; + EC_KEY *ec; - if (!ec) { - return Qfalse; - } - if (!(pkey = EVP_PKEY_new())) { - return Qfalse; - } - if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) { - EVP_PKEY_free(pkey); - return Qfalse; + if (rb_obj_is_kind_of(arg, cEC_GROUP)) { + EC_GROUP *group; + + GetECGroup(arg, group); + if (!(ec = EC_KEY_new())) + ossl_raise(ePKeyError, NULL); + + if (!EC_KEY_set_group(ec, group)) { + EC_KEY_free(ec); + ossl_raise(ePKeyError, NULL); + } + } else { + int nid = OBJ_sn2nid(StringValueCStr(arg)); + + if (nid == NID_undef) + ossl_raise(ePKeyError, "invalid curve name"); + + if (!(ec = EC_KEY_new_by_curve_name(nid))) + ossl_raise(ePKeyError, NULL); + + EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); + EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED); } - WrapPKey(klass, obj, pkey); - return obj; + return ec; } -VALUE ossl_ec_new(EVP_PKEY *pkey) +/* + * call-seq: + * EC.generate(ec_group) -> ec + * EC.generate(string) -> ec + * + * Creates a new EC instance with a new random private and public key. + */ +static VALUE +ossl_ec_key_s_generate(VALUE klass, VALUE arg) { + EVP_PKEY *pkey; + EC_KEY *ec; VALUE obj; - if (!pkey) { - obj = ec_instance(cEC, EC_KEY_new()); - } else { - if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) { - ossl_raise(rb_eTypeError, "Not a EC key!"); - } - WrapPKey(cEC, obj, pkey); - } - if (obj == Qfalse) { - ossl_raise(eECError, NULL); + obj = rb_obj_alloc(klass); + + ec = ec_key_new_from_group(arg); + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) { + EVP_PKEY_free(pkey); + EC_KEY_free(ec); + ossl_raise(ePKeyError, "EVP_PKEY_assign_EC_KEY"); } + RTYPEDDATA_DATA(obj) = pkey; + + if (!EC_KEY_generate_key(ec)) + ossl_raise(ePKeyError, "EC_KEY_generate_key"); return obj; } - -/* call-seq: - * OpenSSL::PKey::EC.new() - * OpenSSL::PKey::EC.new(ec_key) - * OpenSSL::PKey::EC.new(ec_group) - * OpenSSL::PKey::EC.new("secp112r1") - * OpenSSL::PKey::EC.new(pem_string) - * OpenSSL::PKey::EC.new(pem_string [, pwd]) - * OpenSSL::PKey::EC.new(der_string) +/* + * call-seq: + * OpenSSL::PKey::EC.new + * OpenSSL::PKey::EC.new(ec_key) + * OpenSSL::PKey::EC.new(ec_group) + * OpenSSL::PKey::EC.new("secp112r1") + * OpenSSL::PKey::EC.new(pem_string [, pwd]) + * OpenSSL::PKey::EC.new(der_string) * - * See the OpenSSL documentation for: - * EC_KEY_* + * Creates a new EC object from given arguments. */ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; - EC_KEY *ec = NULL; + EC_KEY *ec; + BIO *in; VALUE arg, pass; - VALUE group = Qnil; - char *passwd = NULL; + int type; - GetPKey(self, pkey); - if (pkey->pkey.ec) - ossl_raise(eECError, "EC_KEY already initialized"); + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); rb_scan_args(argc, argv, "02", &arg, &pass); - if (NIL_P(arg)) { - ec = EC_KEY_new(); - } else { - if (rb_obj_is_kind_of(arg, cEC)) { - EC_KEY *other_ec = NULL; - - SafeRequire_EC_KEY(arg, other_ec); - ec = EC_KEY_dup(other_ec); - } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) { - ec = EC_KEY_new(); - group = arg; - } else { - BIO *in = ossl_obj2bio(arg); - - if (!NIL_P(pass)) { - passwd = StringValuePtr(pass); - } - ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd); - if (!ec) { - OSSL_BIO_reset(in); - ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, passwd); - } - if (!ec) { - OSSL_BIO_reset(in); - ec = d2i_ECPrivateKey_bio(in, NULL); - } - if (!ec) { - OSSL_BIO_reset(in); - ec = d2i_EC_PUBKEY_bio(in, NULL); - } - - BIO_free(in); +#ifdef OSSL_HAVE_IMMUTABLE_PKEY + rb_raise(rb_eArgError, "OpenSSL::PKey::EC.new cannot be called " \ + "without arguments; pkeys are immutable with OpenSSL 3.0"); +#else + if (!(ec = EC_KEY_new())) + ossl_raise(ePKeyError, "EC_KEY_new"); + goto legacy; +#endif + } + else if (rb_obj_is_kind_of(arg, cEC_GROUP)) { + ec = ec_key_new_from_group(arg); + goto legacy; + } - if (ec == NULL) { - const char *name = StringValueCStr(arg); - int nid = OBJ_sn2nid(name); + pass = ossl_pem_passwd_value(pass); + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(&arg); - (void)ERR_get_error(); - if (nid == NID_undef) - ossl_raise(eECError, "unknown curve name (%s)\n", name); + pkey = ossl_pkey_read_generic(in, pass); + BIO_free(in); + if (!pkey) { + ossl_clear_error(); + ec = ec_key_new_from_group(arg); + goto legacy; + } - if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL) - ossl_raise(eECError, "unable to create curve (%s)\n", name); + type = EVP_PKEY_base_id(pkey); + if (type != EVP_PKEY_EC) { + EVP_PKEY_free(pkey); + rb_raise(ePKeyError, "incorrect pkey type: %s", OBJ_nid2sn(type)); + } + RTYPEDDATA_DATA(self) = pkey; + return self; - EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); - EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED); - } - } + legacy: + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) { + EVP_PKEY_free(pkey); + EC_KEY_free(ec); + ossl_raise(ePKeyError, "EVP_PKEY_assign_EC_KEY"); } + RTYPEDDATA_DATA(self) = pkey; + return self; +} - if (ec == NULL) - ossl_raise(eECError, NULL); +#ifndef HAVE_EVP_PKEY_DUP +/* :nodoc: */ +static VALUE +ossl_ec_key_initialize_copy(VALUE self, VALUE other) +{ + EVP_PKEY *pkey; + EC_KEY *ec, *ec_new; - if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) { - EC_KEY_free(ec); - ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY"); - } + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); + GetEC(other, ec); - rb_iv_set(self, "@group", Qnil); + ec_new = EC_KEY_dup(ec); + if (!ec_new) + ossl_raise(ePKeyError, "EC_KEY_dup"); - if (!NIL_P(group)) - rb_funcall(self, rb_intern("group="), 1, arg); + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec_new) != 1) { + EC_KEY_free(ec_new); + ossl_raise(ePKeyError, "EVP_PKEY_assign_EC_KEY"); + } + RTYPEDDATA_DATA(self) = pkey; return self; } +#endif /* - * call-seq: - * key.group => group + * call-seq: + * key.group => group * - * Returns a constant <code>OpenSSL::EC::Group</code> that is tied to the key. - * Modifying the returned group can make the key invalid. + * Returns the EC::Group that the key is associated with. Modifying the returned + * group does not affect _key_. */ -static VALUE ossl_ec_key_get_group(VALUE self) +static VALUE +ossl_ec_key_get_group(VALUE self) { - VALUE group_v; - EC_KEY *ec; - ossl_ec_group *ec_group; - EC_GROUP *group; - - Require_EC_KEY(self, ec); - - group_v = rb_iv_get(self, "@group"); - if (!NIL_P(group_v)) - return group_v; + OSSL_3_const EC_KEY *ec; + const EC_GROUP *group; - if ((group = (EC_GROUP *)EC_KEY_get0_group(ec)) != NULL) { - group_v = rb_obj_alloc(cEC_GROUP); - SafeGet_ec_group(group_v, ec_group); - ec_group->group = group; - ec_group->dont_free = 1; - rb_iv_set(group_v, "@key", self); - rb_iv_set(self, "@group", group_v); - return group_v; - } + GetEC(self, ec); + group = EC_KEY_get0_group(ec); + if (!group) + return Qnil; - return Qnil; + return ec_group_new(group); } /* - * call-seq: - * key.group = group => group - * - * Returns the same object passed, not the group object associated with the key. - * If you wish to access the group object tied to the key call key.group after setting - * the group. + * call-seq: + * key.group = group * - * Setting the group will immediately destroy any previously assigned group object. - * The group is internally copied by OpenSSL. Modifying the original group after - * assignment will not effect the internal key structure. - * (your changes may be lost). BE CAREFUL. - * - * EC_KEY_set_group calls EC_GROUP_free(key->group) then EC_GROUP_dup(), not EC_GROUP_copy. - * This documentation is accurate for OpenSSL 0.9.8b. + * Sets the EC::Group for the key. The group structure is internally copied so + * modification to _group_ after assigning to a key has no effect on the key. */ -static VALUE ossl_ec_key_set_group(VALUE self, VALUE group_v) +static VALUE +ossl_ec_key_set_group(VALUE self, VALUE group_v) { - VALUE old_group_v; +#ifdef OSSL_HAVE_IMMUTABLE_PKEY + rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0"); +#else EC_KEY *ec; EC_GROUP *group; - Require_EC_KEY(self, ec); - SafeRequire_EC_GROUP(group_v, group); - - old_group_v = rb_iv_get(self, "@group"); - if (!NIL_P(old_group_v)) { - ossl_ec_group *old_ec_group; - SafeGet_ec_group(old_group_v, old_ec_group); - - old_ec_group->group = NULL; - old_ec_group->dont_free = 0; - rb_iv_set(old_group_v, "@key", Qnil); - } - - rb_iv_set(self, "@group", Qnil); + GetEC(self, ec); + GetECGroup(group_v, group); if (EC_KEY_set_group(ec, group) != 1) - ossl_raise(eECError, "EC_KEY_set_group"); + ossl_raise(ePKeyError, "EC_KEY_set_group"); return group_v; +#endif } /* @@ -324,11 +276,10 @@ static VALUE ossl_ec_key_set_group(VALUE self, VALUE group_v) */ static VALUE ossl_ec_key_get_private_key(VALUE self) { - EC_KEY *ec; + OSSL_3_const EC_KEY *ec; const BIGNUM *bn; - Require_EC_KEY(self, ec); - + GetEC(self, ec); if ((bn = EC_KEY_get0_private_key(ec)) == NULL) return Qnil; @@ -343,44 +294,29 @@ static VALUE ossl_ec_key_get_private_key(VALUE self) */ static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key) { +#ifdef OSSL_HAVE_IMMUTABLE_PKEY + rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0"); +#else EC_KEY *ec; BIGNUM *bn = NULL; - Require_EC_KEY(self, ec); + GetEC(self, ec); if (!NIL_P(private_key)) bn = GetBNPtr(private_key); switch (EC_KEY_set_private_key(ec, bn)) { - case 1: + case 1: break; - case 0: + case 0: if (bn == NULL) break; - default: - ossl_raise(eECError, "EC_KEY_set_private_key"); + /* fallthrough */ + default: + ossl_raise(ePKeyError, "EC_KEY_set_private_key"); } return private_key; -} - - -static VALUE ossl_ec_point_dup(const EC_POINT *point, VALUE group_v) -{ - VALUE obj; - const EC_GROUP *group; - ossl_ec_point *new_point; - - obj = rb_obj_alloc(cEC_POINT); - TypedData_Get_Struct(obj, ossl_ec_point, &ossl_ec_point_type, new_point); - - SafeRequire_EC_GROUP(group_v, group); - - new_point->point = EC_POINT_dup(point, group); - if (new_point->point == NULL) - ossl_raise(eEC_POINT, "EC_POINT_dup"); - rb_iv_set(obj, "@group", group_v); - - return obj; +#endif } /* @@ -391,20 +327,14 @@ static VALUE ossl_ec_point_dup(const EC_POINT *point, VALUE group_v) */ static VALUE ossl_ec_key_get_public_key(VALUE self) { - EC_KEY *ec; + OSSL_3_const EC_KEY *ec; const EC_POINT *point; - VALUE group; - - Require_EC_KEY(self, ec); + GetEC(self, ec); if ((point = EC_KEY_get0_public_key(ec)) == NULL) return Qnil; - group = rb_funcall(self, rb_intern("group"), 0); - if (NIL_P(group)) - ossl_raise(eECError, "EC_KEY_get0_get0_group (has public_key but no group???"); - - return ossl_ec_point_dup(point, group); + return ec_point_new(point, EC_KEY_get0_group(ec)); } /* @@ -415,388 +345,310 @@ static VALUE ossl_ec_key_get_public_key(VALUE self) */ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key) { +#ifdef OSSL_HAVE_IMMUTABLE_PKEY + rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0"); +#else EC_KEY *ec; EC_POINT *point = NULL; - Require_EC_KEY(self, ec); + GetEC(self, ec); if (!NIL_P(public_key)) - SafeRequire_EC_POINT(public_key, point); + GetECPoint(public_key, point); switch (EC_KEY_set_public_key(ec, point)) { - case 1: + case 1: break; - case 0: + case 0: if (point == NULL) break; - default: - ossl_raise(eECError, "EC_KEY_set_public_key"); + /* fallthrough */ + default: + ossl_raise(ePKeyError, "EC_KEY_set_public_key"); } return public_key; +#endif } /* * call-seq: - * key.public_key? => true or false + * key.public? => true or false * - * Both public_key? and private_key? may return false at the same time unlike other PKey classes. + * Returns whether this EC instance has a public key. The public key + * (EC::Point) can be retrieved with EC#public_key. */ -static VALUE ossl_ec_key_is_public_key(VALUE self) +static VALUE ossl_ec_key_is_public(VALUE self) { - EC_KEY *ec; + OSSL_3_const EC_KEY *ec; - Require_EC_KEY(self, ec); + GetEC(self, ec); - return (EC_KEY_get0_public_key(ec) ? Qtrue : Qfalse); + return EC_KEY_get0_public_key(ec) ? Qtrue : Qfalse; } /* * call-seq: - * key.private_key? => true or false + * key.private? => true or false * - * Both public_key? and private_key? may return false at the same time unlike other PKey classes. + * Returns whether this EC instance has a private key. The private key (BN) can + * be retrieved with EC#private_key. */ -static VALUE ossl_ec_key_is_private_key(VALUE self) +static VALUE ossl_ec_key_is_private(VALUE self) { - EC_KEY *ec; + OSSL_3_const EC_KEY *ec; - Require_EC_KEY(self, ec); + GetEC(self, ec); - return (EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse); -} - -static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int format) -{ - EC_KEY *ec; - BIO *out; - int i = -1; - int private = 0; - char *password = NULL; - VALUE str; - - Require_EC_KEY(self, ec); - - if (EC_KEY_get0_public_key(ec) == NULL) - ossl_raise(eECError, "can't export - no public key set"); - - if (EC_KEY_check_key(ec) != 1) - ossl_raise(eECError, "can't export - EC_KEY_check_key failed"); - - if (EC_KEY_get0_private_key(ec)) - private = 1; - - if (!(out = BIO_new(BIO_s_mem()))) - ossl_raise(eECError, "BIO_new(BIO_s_mem())"); - - switch(format) { - case EXPORT_PEM: - if (private) { - const EVP_CIPHER *cipher; - if (!NIL_P(ciph)) { - cipher = GetCipherPtr(ciph); - if (!NIL_P(pass)) { - StringValue(pass); - if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN) - ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long"); - password = RSTRING_PTR(pass); - } - } - else { - cipher = NULL; - } - i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, NULL, password); - } else { - i = PEM_write_bio_EC_PUBKEY(out, ec); - } - - break; - case EXPORT_DER: - if (private) { - i = i2d_ECPrivateKey_bio(out, ec); - } else { - i = i2d_EC_PUBKEY_bio(out, ec); - } - - break; - default: - BIO_free(out); - ossl_raise(rb_eRuntimeError, "unknown format (internal error)"); - } - - if (i != 1) { - BIO_free(out); - ossl_raise(eECError, "outlen=%d", i); - } - - str = ossl_membio2str(out); - - return str; + return EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse; } /* * call-seq: - * key.export([cipher, pass_phrase]) => String - * key.to_pem([cipher, pass_phrase]) => String + * key.export([cipher, password]) => String + * key.to_pem([cipher, password]) => String + * + * Serializes a private or public key to a PEM-encoding. + * + * [When the key contains public components only] + * + * Serializes it into an X.509 SubjectPublicKeyInfo. + * The parameters _cipher_ and _password_ are ignored. + * + * A PEM-encoded key will look like: + * + * -----BEGIN PUBLIC KEY----- + * [...] + * -----END PUBLIC KEY----- + * + * Consider using #public_to_pem instead. This serializes the key into an + * X.509 SubjectPublicKeyInfo regardless of whether it is a public key + * or a private key. + * + * [When the key contains private components, and no parameters are given] * - * Outputs the EC key in PEM encoding. If +cipher+ and +pass_phrase+ are - * given they will be used to encrypt the key. +cipher+ must be an - * OpenSSL::Cipher::Cipher instance. Note that encryption will only be - * effective for a private key, public keys will always be encoded in plain - * text. + * Serializes it into a SEC 1/RFC 5915 ECPrivateKey. * + * A PEM-encoded key will look like: + * + * -----BEGIN EC PRIVATE KEY----- + * [...] + * -----END EC PRIVATE KEY----- + * + * [When the key contains private components, and _cipher_ and _password_ are given] + * + * Serializes it into a SEC 1/RFC 5915 ECPrivateKey + * and encrypts it in OpenSSL's traditional PEM encryption format. + * _cipher_ must be a cipher name understood by OpenSSL::Cipher.new or an + * instance of OpenSSL::Cipher. + * + * An encrypted PEM-encoded key will look like: + * + * -----BEGIN EC PRIVATE KEY----- + * Proc-Type: 4,ENCRYPTED + * DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 + * + * [...] + * -----END EC PRIVATE KEY----- + * + * Note that this format uses MD5 to derive the encryption key, and hence + * will not be available on FIPS-compliant systems. + * + * <b>This method is kept for compatibility.</b> + * This should only be used when the SEC 1/RFC 5915 ECPrivateKey format is + * required. + * + * Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem + * (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead. */ -static VALUE ossl_ec_key_export(int argc, VALUE *argv, VALUE self) +static VALUE +ossl_ec_key_export(int argc, VALUE *argv, VALUE self) { - VALUE cipher, passwd; - rb_scan_args(argc, argv, "02", &cipher, &passwd); - return ossl_ec_key_to_string(self, cipher, passwd, EXPORT_PEM); + OSSL_3_const EC_KEY *ec; + + GetEC(self, ec); + if (EC_KEY_get0_public_key(ec) == NULL) + ossl_raise(ePKeyError, "can't export - no public key set"); + if (EC_KEY_get0_private_key(ec)) + return ossl_pkey_export_traditional(argc, argv, self, 0); + else + return ossl_pkey_export_spki(self, 0); } /* * call-seq: * key.to_der => String * - * See the OpenSSL documentation for i2d_ECPrivateKey_bio() - */ -static VALUE ossl_ec_key_to_der(VALUE self) -{ - return ossl_ec_key_to_string(self, Qnil, Qnil, EXPORT_DER); -} - -/* - * call-seq: - * key.to_text => String + * Serializes a private or public key to a DER-encoding. + * + * See #to_pem for details. + * + * <b>This method is kept for compatibility.</b> + * This should only be used when the SEC 1/RFC 5915 ECPrivateKey format is + * required. * - * See the OpenSSL documentation for EC_KEY_print() + * Consider using #public_to_der or #private_to_der instead. */ -static VALUE ossl_ec_key_to_text(VALUE self) +static VALUE +ossl_ec_key_to_der(VALUE self) { - EC_KEY *ec; - BIO *out; - VALUE str; + OSSL_3_const EC_KEY *ec; - Require_EC_KEY(self, ec); - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eECError, "BIO_new(BIO_s_mem())"); - } - if (!EC_KEY_print(out, ec, 0)) { - BIO_free(out); - ossl_raise(eECError, "EC_KEY_print"); - } - str = ossl_membio2str(out); - - return str; + GetEC(self, ec); + if (EC_KEY_get0_public_key(ec) == NULL) + ossl_raise(ePKeyError, "can't export - no public key set"); + if (EC_KEY_get0_private_key(ec)) + return ossl_pkey_export_traditional(0, NULL, self, 1); + else + return ossl_pkey_export_spki(self, 1); } - /* * call-seq: - * key.generate_key => self + * key.generate_key! => self + * + * Generates a new random private and public key. + * + * See also the OpenSSL documentation for EC_KEY_generate_key() * - * See the OpenSSL documentation for EC_KEY_generate_key() + * === Example + * ec = OpenSSL::PKey::EC.new("prime256v1") + * p ec.private_key # => nil + * ec.generate_key! + * p ec.private_key # => #<OpenSSL::BN XXXXXX> */ static VALUE ossl_ec_key_generate_key(VALUE self) { +#ifdef OSSL_HAVE_IMMUTABLE_PKEY + rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0"); +#else EC_KEY *ec; - Require_EC_KEY(self, ec); - + GetEC(self, ec); if (EC_KEY_generate_key(ec) != 1) - ossl_raise(eECError, "EC_KEY_generate_key"); + ossl_raise(ePKeyError, "EC_KEY_generate_key"); return self; +#endif } /* - * call-seq: - * key.check_key => true + * call-seq: + * key.check_key => true * - * Raises an exception if the key is invalid. + * Raises an exception if the key is invalid. * - * See the OpenSSL documentation for EC_KEY_check_key() + * See also the man page EVP_PKEY_public_check(3). */ static VALUE ossl_ec_key_check_key(VALUE self) { - EC_KEY *ec; - - Require_EC_KEY(self, ec); - - if (EC_KEY_check_key(ec) != 1) - ossl_raise(eECError, "EC_KEY_check_key"); - - return Qtrue; -} - -/* - * call-seq: - * key.dh_compute_key(pubkey) => String - * - * See the OpenSSL documentation for ECDH_compute_key() - */ -static VALUE ossl_ec_key_dh_compute_key(VALUE self, VALUE pubkey) -{ - EC_KEY *ec; - EC_POINT *point; - int buf_len; - VALUE str; - - Require_EC_KEY(self, ec); - SafeRequire_EC_POINT(pubkey, point); - -/* BUG: need a way to figure out the maximum string size */ - buf_len = 1024; - str = rb_str_new(0, buf_len); -/* BUG: take KDF as a block */ - buf_len = ECDH_compute_key(RSTRING_PTR(str), buf_len, point, ec, NULL); - if (buf_len < 0) - ossl_raise(eECError, "ECDH_compute_key"); - - rb_str_resize(str, buf_len); - - return str; -} +#ifdef HAVE_EVP_PKEY_CHECK + EVP_PKEY *pkey; + EVP_PKEY_CTX *pctx; + const EC_KEY *ec; -/* sign_setup */ + GetPKey(self, pkey); + GetEC(self, ec); + pctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!pctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + + if (EC_KEY_get0_private_key(ec) != NULL) { + if (EVP_PKEY_check(pctx) != 1) { + EVP_PKEY_CTX_free(pctx); + ossl_raise(ePKeyError, "EVP_PKEY_check"); + } + } + else { + if (EVP_PKEY_public_check(pctx) != 1) { + EVP_PKEY_CTX_free(pctx); + ossl_raise(ePKeyError, "EVP_PKEY_public_check"); + } + } -/* - * call-seq: - * key.dsa_sign_asn1(data) => String - * - * See the OpenSSL documentation for ECDSA_sign() - */ -static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data) -{ + EVP_PKEY_CTX_free(pctx); +#else EC_KEY *ec; - unsigned int buf_len; - VALUE str; - - Require_EC_KEY(self, ec); - StringValue(data); - - if (EC_KEY_get0_private_key(ec) == NULL) - ossl_raise(eECError, "Private EC key needed!"); - - str = rb_str_new(0, ECDSA_size(ec) + 16); - if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1) - ossl_raise(eECError, "ECDSA_sign"); - rb_str_resize(str, buf_len); + GetEC(self, ec); + if (EC_KEY_check_key(ec) != 1) + ossl_raise(ePKeyError, "EC_KEY_check_key"); +#endif - return str; + return Qtrue; } /* - * call-seq: - * key.dsa_verify_asn1(data, sig) => true or false - * - * See the OpenSSL documentation for ECDSA_verify() + * OpenSSL::PKey::EC::Group */ -static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig) -{ - EC_KEY *ec; - - Require_EC_KEY(self, ec); - StringValue(data); - StringValue(sig); - - switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(sig), (int)RSTRING_LEN(sig), ec)) { - case 1: return Qtrue; - case 0: return Qfalse; - default: break; - } - - ossl_raise(eECError, "ECDSA_verify"); - - UNREACHABLE; -} - -static void ossl_ec_group_free(void *ptr) +static void +ossl_ec_group_free(void *ptr) { - ossl_ec_group *ec_group = ptr; - if (!ec_group->dont_free && ec_group->group) - EC_GROUP_clear_free(ec_group->group); - ruby_xfree(ec_group); + EC_GROUP_free(ptr); } static const rb_data_type_t ossl_ec_group_type = { "OpenSSL/ec_group", { - 0, ossl_ec_group_free, + 0, ossl_ec_group_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; -static VALUE ossl_ec_group_alloc(VALUE klass) +static VALUE +ossl_ec_group_alloc(VALUE klass) +{ + return TypedData_Wrap_Struct(klass, &ossl_ec_group_type, NULL); +} + +static VALUE +ec_group_new(const EC_GROUP *group) { - ossl_ec_group *ec_group; VALUE obj; + EC_GROUP *group_new; - obj = TypedData_Make_Struct(klass, ossl_ec_group, &ossl_ec_group_type, ec_group); + obj = ossl_ec_group_alloc(cEC_GROUP); + group_new = EC_GROUP_dup(group); + if (!group_new) + ossl_raise(eEC_GROUP, "EC_GROUP_dup"); + RTYPEDDATA_DATA(obj) = group_new; return obj; } -/* call-seq: - * OpenSSL::PKey::EC::Group.new("secp112r1") - * OpenSSL::PKey::EC::Group.new(ec_group) - * OpenSSL::PKey::EC::Group.new(pem_string) - * OpenSSL::PKey::EC::Group.new(der_string) - * OpenSSL::PKey::EC::Group.new(pem_file) - * OpenSSL::PKey::EC::Group.new(der_file) - * OpenSSL::PKey::EC::Group.new(:GFp_simple) - * OpenSSL::PKey::EC::Group.new(:GFp_mult) - * OpenSSL::PKey::EC::Group.new(:GFp_nist) - * OpenSSL::PKey::EC::Group.new(:GF2m_simple) - * OpenSSL::PKey::EC::Group.new(:GFp, bignum_p, bignum_a, bignum_b) - * OpenSSL::PKey::EC::Group.new(:GF2m, bignum_p, bignum_a, bignum_b) - * - * See the OpenSSL documentation for EC_GROUP_* +/* + * call-seq: + * OpenSSL::PKey::EC::Group.new(ec_group) + * OpenSSL::PKey::EC::Group.new(pem_or_der_encoded) + * OpenSSL::PKey::EC::Group.new(:GFp, bignum_p, bignum_a, bignum_b) + * OpenSSL::PKey::EC::Group.new(:GF2m, bignum_p, bignum_a, bignum_b) + * + * Creates a new EC::Group object. + * + * If the first argument is :GFp or :GF2m, creates a new curve with given + * parameters. */ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self) { VALUE arg1, arg2, arg3, arg4; - ossl_ec_group *ec_group; - EC_GROUP *group = NULL; + EC_GROUP *group; - TypedData_Get_Struct(self, ossl_ec_group, &ossl_ec_group_type, ec_group); - if (ec_group->group != NULL) + TypedData_Get_Struct(self, EC_GROUP, &ossl_ec_group_type, group); + if (group) ossl_raise(rb_eRuntimeError, "EC_GROUP is already initialized"); switch (rb_scan_args(argc, argv, "13", &arg1, &arg2, &arg3, &arg4)) { - case 1: - if (SYMBOL_P(arg1)) { - const EC_METHOD *method = NULL; - ID id = SYM2ID(arg1); - - if (id == s_GFp_simple) { - method = EC_GFp_simple_method(); - } else if (id == s_GFp_mont) { - method = EC_GFp_mont_method(); - } else if (id == s_GFp_nist) { - method = EC_GFp_nist_method(); -#if !defined(OPENSSL_NO_EC2M) - } else if (id == s_GF2m_simple) { - method = EC_GF2m_simple_method(); -#endif - } - - if (method) { - if ((group = EC_GROUP_new(method)) == NULL) - ossl_raise(eEC_GROUP, "EC_GROUP_new"); - } else { - ossl_raise(rb_eArgError, "unknown symbol, must be :GFp_simple, :GFp_mont, :GFp_nist or :GF2m_simple"); - } - } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) { + case 1: + if (rb_obj_is_kind_of(arg1, cEC_GROUP)) { const EC_GROUP *arg1_group; - SafeRequire_EC_GROUP(arg1, arg1_group); + GetECGroup(arg1, arg1_group); if ((group = EC_GROUP_dup(arg1_group)) == NULL) ossl_raise(eEC_GROUP, "EC_GROUP_dup"); } else { - BIO *in = ossl_obj2bio(arg1); + BIO *in = ossl_obj2bio(&arg1); group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); if (!group) { - OSSL_BIO_reset(in); + OSSL_BIO_reset(in); group = d2i_ECPKParameters_bio(in, NULL); } @@ -806,13 +658,16 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self) const char *name = StringValueCStr(arg1); int nid = OBJ_sn2nid(name); - (void)ERR_get_error(); + ossl_clear_error(); /* ignore errors in d2i_ECPKParameters_bio() */ if (nid == NID_undef) - ossl_raise(eEC_GROUP, "unknown curve name (%s)", name); - + ossl_raise(eEC_GROUP, "unknown curve name (%"PRIsVALUE")", arg1); +#if !defined(OPENSSL_IS_AWSLC) group = EC_GROUP_new_by_curve_name(nid); +#else /* EC_GROUPs are static and immutable by default in AWS-LC. */ + group = EC_GROUP_new_by_curve_name_mutable(nid); +#endif if (group == NULL) - ossl_raise(eEC_GROUP, "unable to create curve (%s)", name); + ossl_raise(eEC_GROUP, "unable to create curve (%"PRIsVALUE")", arg1); EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED); @@ -820,82 +675,112 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self) } break; - case 4: + case 4: if (SYMBOL_P(arg1)) { - ID id = SYM2ID(arg1); EC_GROUP *(*new_curve)(const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *) = NULL; const BIGNUM *p = GetBNPtr(arg2); const BIGNUM *a = GetBNPtr(arg3); const BIGNUM *b = GetBNPtr(arg4); - if (id == s_GFp) { + if (arg1 == sym_GFp) { new_curve = EC_GROUP_new_curve_GFp; + } #if !defined(OPENSSL_NO_EC2M) - } else if (id == s_GF2m) { + else if (arg1 == sym_GF2m) { new_curve = EC_GROUP_new_curve_GF2m; + } #endif - } else { + else { ossl_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m"); } if ((group = new_curve(p, a, b, ossl_bn_ctx)) == NULL) ossl_raise(eEC_GROUP, "EC_GROUP_new_by_GF*"); } else { - ossl_raise(rb_eArgError, "unknown argument, must be :GFp or :GF2m"); + ossl_raise(rb_eArgError, "unknown argument, must be :GFp or :GF2m"); } break; - default: - ossl_raise(rb_eArgError, "wrong number of arguments"); + default: + ossl_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1 or 4)", argc); } - if (group == NULL) - ossl_raise(eEC_GROUP, ""); + ASSUME(group); + RTYPEDDATA_DATA(self) = group; - ec_group->group = group; + return self; +} + +/* :nodoc: */ +static VALUE +ossl_ec_group_initialize_copy(VALUE self, VALUE other) +{ + EC_GROUP *group, *group_new; + + TypedData_Get_Struct(self, EC_GROUP, &ossl_ec_group_type, group_new); + if (group_new) + ossl_raise(eEC_GROUP, "EC::Group already initialized"); + GetECGroup(other, group); + + group_new = EC_GROUP_dup(group); + if (!group_new) + ossl_raise(eEC_GROUP, "EC_GROUP_dup"); + RTYPEDDATA_DATA(self) = group_new; return self; } -/* call-seq: - * group1.eql?(group2) => true | false - * group1 == group2 => true | false +/* + * call-seq: + * group1.eql?(group2) => true | false + * group1 == group2 => true | false * + * Returns +true+ if the two groups use the same curve and have the same + * parameters, +false+ otherwise. */ static VALUE ossl_ec_group_eql(VALUE a, VALUE b) { EC_GROUP *group1 = NULL, *group2 = NULL; - Require_EC_GROUP(a, group1); - SafeRequire_EC_GROUP(b, group2); - - if (EC_GROUP_cmp(group1, group2, ossl_bn_ctx) == 1) - return Qfalse; + GetECGroup(a, group1); + GetECGroup(b, group2); - return Qtrue; + switch (EC_GROUP_cmp(group1, group2, ossl_bn_ctx)) { + case 0: return Qtrue; + case 1: return Qfalse; + default: ossl_raise(eEC_GROUP, "EC_GROUP_cmp"); + } } -/* call-seq: - * group.generator => ec_point +/* + * call-seq: + * group.generator => ec_point * - * See the OpenSSL documentation for EC_GROUP_get0_generator() + * Returns the generator of the group. + * + * See the OpenSSL documentation for EC_GROUP_get0_generator() */ static VALUE ossl_ec_group_get_generator(VALUE self) { - VALUE point_obj; - EC_GROUP *group = NULL; - - Require_EC_GROUP(self, group); + EC_GROUP *group; + const EC_POINT *generator; - point_obj = ossl_ec_point_dup(EC_GROUP_get0_generator(group), self); + GetECGroup(self, group); + generator = EC_GROUP_get0_generator(group); + if (!generator) + return Qnil; - return point_obj; + return ec_point_new(generator, group); } -/* call-seq: - * group.set_generator(generator, order, cofactor) => self +/* + * call-seq: + * group.set_generator(generator, order, cofactor) => self + * + * Sets the curve parameters. _generator_ must be an instance of EC::Point that + * is on the curve. _order_ and _cofactor_ are integers. * - * See the OpenSSL documentation for EC_GROUP_set_generator() + * See the OpenSSL documentation for EC_GROUP_set_generator() */ static VALUE ossl_ec_group_set_generator(VALUE self, VALUE generator, VALUE order, VALUE cofactor) { @@ -903,8 +788,8 @@ static VALUE ossl_ec_group_set_generator(VALUE self, VALUE generator, VALUE orde const EC_POINT *point; const BIGNUM *o, *co; - Require_EC_GROUP(self, group); - SafeRequire_EC_POINT(generator, point); + GetECGroup(self, group); + GetECPoint(generator, point); o = GetBNPtr(order); co = GetBNPtr(cofactor); @@ -914,20 +799,22 @@ static VALUE ossl_ec_group_set_generator(VALUE self, VALUE generator, VALUE orde return self; } -/* call-seq: - * group.get_order => order_bn +/* + * call-seq: + * group.get_order => order_bn + * + * Returns the order of the group. * - * See the OpenSSL documentation for EC_GROUP_get_order() + * See the OpenSSL documentation for EC_GROUP_get_order() */ static VALUE ossl_ec_group_get_order(VALUE self) { VALUE bn_obj; BIGNUM *bn; - EC_GROUP *group = NULL; - - Require_EC_GROUP(self, group); + EC_GROUP *group; - bn_obj = ossl_bn_new(NULL); + GetECGroup(self, group); + bn_obj = ossl_bn_new(BN_value_one()); bn = GetBNPtr(bn_obj); if (EC_GROUP_get_order(group, bn, ossl_bn_ctx) != 1) @@ -936,20 +823,22 @@ static VALUE ossl_ec_group_get_order(VALUE self) return bn_obj; } -/* call-seq: - * group.get_cofactor => cofactor_bn +/* + * call-seq: + * group.get_cofactor => cofactor_bn + * + * Returns the cofactor of the group. * - * See the OpenSSL documentation for EC_GROUP_get_cofactor() + * See the OpenSSL documentation for EC_GROUP_get_cofactor() */ static VALUE ossl_ec_group_get_cofactor(VALUE self) { VALUE bn_obj; BIGNUM *bn; - EC_GROUP *group = NULL; - - Require_EC_GROUP(self, group); + EC_GROUP *group; - bn_obj = ossl_bn_new(NULL); + GetECGroup(self, group); + bn_obj = ossl_bn_new(BN_value_one()); bn = GetBNPtr(bn_obj); if (EC_GROUP_get_cofactor(group, bn, ossl_bn_ctx) != 1) @@ -958,30 +847,35 @@ static VALUE ossl_ec_group_get_cofactor(VALUE self) return bn_obj; } -/* call-seq: - * group.curve_name => String +/* + * call-seq: + * group.curve_name -> string or nil + * + * Returns the curve name (short name) corresponding to this group, or +nil+ + * if \OpenSSL does not have an OID associated with the group. * - * See the OpenSSL documentation for EC_GROUP_get_curve_name() + * See the OpenSSL documentation for EC_GROUP_get_curve_name() */ static VALUE ossl_ec_group_get_curve_name(VALUE self) { - EC_GROUP *group = NULL; + EC_GROUP *group; int nid; - Get_EC_GROUP(self, group); - if (group == NULL) - return Qnil; - + GetECGroup(self, group); nid = EC_GROUP_get_curve_name(group); - -/* BUG: an nid or asn1 object should be returned, maybe. */ - return rb_str_new2(OBJ_nid2sn(nid)); + if (nid == NID_undef) + return Qnil; + return rb_str_new_cstr(OBJ_nid2sn(nid)); } -/* call-seq: - * EC.builtin_curves => [[name, comment], ...] +/* + * call-seq: + * EC.builtin_curves => [[sn, comment], ...] + * + * Obtains a list of all predefined curves by the OpenSSL. Curve names are + * returned as sn. * - * See the OpenSSL documentation for EC_builtin_curves() + * See the OpenSSL documentation for EC_get_builtin_curves(). */ static VALUE ossl_s_builtin_curves(VALUE self) { @@ -1011,104 +905,136 @@ static VALUE ossl_s_builtin_curves(VALUE self) return ret; } -/* call-seq: - * group.asn1_flag => Fixnum +/* + * call-seq: + * group.asn1_flag -> Integer + * + * Returns the flags set on the group. * - * See the OpenSSL documentation for EC_GROUP_get_asn1_flag() + * See also #asn1_flag=. */ static VALUE ossl_ec_group_get_asn1_flag(VALUE self) { EC_GROUP *group = NULL; int flag; - Require_EC_GROUP(self, group); - + GetECGroup(self, group); flag = EC_GROUP_get_asn1_flag(group); - return INT2FIX(flag); + return INT2NUM(flag); } -/* call-seq: - * group.asn1_flag = Fixnum => Fixnum +/* + * call-seq: + * group.asn1_flag = flags + * + * Sets flags on the group. The flag value is used to determine how to encode + * the group: encode explicit parameters or named curve using an OID. + * + * The flag value can be either of: + * + * * EC::NAMED_CURVE + * * EC::EXPLICIT_CURVE * - * See the OpenSSL documentation for EC_GROUP_set_asn1_flag() + * See the OpenSSL documentation for EC_GROUP_set_asn1_flag(). */ static VALUE ossl_ec_group_set_asn1_flag(VALUE self, VALUE flag_v) { EC_GROUP *group = NULL; - Require_EC_GROUP(self, group); - + GetECGroup(self, group); EC_GROUP_set_asn1_flag(group, NUM2INT(flag_v)); return flag_v; } -/* call-seq: - * group.point_conversion_form => :uncompressed | :compressed | :hybrid +/* + * call-seq: + * group.point_conversion_form -> Symbol + * + * Returns the form how EC::Point data is encoded as ASN.1. * - * See the OpenSSL documentation for EC_GROUP_get_point_conversion_form() + * See also #point_conversion_form=. */ static VALUE ossl_ec_group_get_point_conversion_form(VALUE self) { - EC_GROUP *group = NULL; + EC_GROUP *group; point_conversion_form_t form; - VALUE ret; - - Require_EC_GROUP(self, group); + GetECGroup(self, group); form = EC_GROUP_get_point_conversion_form(group); switch (form) { - case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed; break; - case POINT_CONVERSION_COMPRESSED: ret = ID_compressed; break; - case POINT_CONVERSION_HYBRID: ret = ID_hybrid; break; - default: ossl_raise(eEC_GROUP, "unsupported point conversion form: %d, this module should be updated", form); + case POINT_CONVERSION_UNCOMPRESSED: + return sym_uncompressed; + case POINT_CONVERSION_COMPRESSED: + return sym_compressed; + case POINT_CONVERSION_HYBRID: + return sym_hybrid; + default: + ossl_raise(eEC_GROUP, "unsupported point conversion form: %d, " \ + "this module should be updated", form); } +} - return ID2SYM(ret); +static point_conversion_form_t +parse_point_conversion_form_symbol(VALUE sym) +{ + if (sym == sym_uncompressed) + return POINT_CONVERSION_UNCOMPRESSED; + if (sym == sym_compressed) + return POINT_CONVERSION_COMPRESSED; + if (sym == sym_hybrid) + return POINT_CONVERSION_HYBRID; + ossl_raise(rb_eArgError, "unsupported point conversion form %+"PRIsVALUE + " (expected :compressed, :uncompressed, or :hybrid)", sym); } -/* call-seq: - * group.point_conversion_form = form => form +/* + * call-seq: + * group.point_conversion_form = form + * + * Sets the form how EC::Point data is encoded as ASN.1 as defined in X9.62. * - * See the OpenSSL documentation for EC_GROUP_set_point_conversion_form() + * _format_ can be one of these: + * + * +:compressed+:: + * Encoded as z||x, where z is an octet indicating which solution of the + * equation y is. z will be 0x02 or 0x03. + * +:uncompressed+:: + * Encoded as z||x||y, where z is an octet 0x04. + * +:hybrid+:: + * Encodes as z||x||y, where z is an octet indicating which solution of the + * equation y is. z will be 0x06 or 0x07. + * + * See the OpenSSL documentation for EC_GROUP_set_point_conversion_form() */ -static VALUE ossl_ec_group_set_point_conversion_form(VALUE self, VALUE form_v) +static VALUE +ossl_ec_group_set_point_conversion_form(VALUE self, VALUE form_v) { - EC_GROUP *group = NULL; + EC_GROUP *group; point_conversion_form_t form; - ID form_id = SYM2ID(form_v); - Require_EC_GROUP(self, group); - - if (form_id == ID_uncompressed) { - form = POINT_CONVERSION_UNCOMPRESSED; - } else if (form_id == ID_compressed) { - form = POINT_CONVERSION_COMPRESSED; - } else if (form_id == ID_hybrid) { - form = POINT_CONVERSION_HYBRID; - } else { - ossl_raise(rb_eArgError, "form must be :compressed, :uncompressed, or :hybrid"); - } + GetECGroup(self, group); + form = parse_point_conversion_form_symbol(form_v); EC_GROUP_set_point_conversion_form(group, form); return form_v; } -/* call-seq: - * group.seed => String or nil +/* + * call-seq: + * group.seed => String or nil * - * See the OpenSSL documentation for EC_GROUP_get0_seed() + * See the OpenSSL documentation for EC_GROUP_get0_seed() */ static VALUE ossl_ec_group_get_seed(VALUE self) { EC_GROUP *group = NULL; size_t seed_len; - Require_EC_GROUP(self, group); - + GetECGroup(self, group); seed_len = EC_GROUP_get_seed_len(group); if (seed_len == 0) @@ -1117,16 +1043,17 @@ static VALUE ossl_ec_group_get_seed(VALUE self) return rb_str_new((const char *)EC_GROUP_get0_seed(group), seed_len); } -/* call-seq: - * group.seed = seed => seed +/* + * call-seq: + * group.seed = seed => seed * - * See the OpenSSL documentation for EC_GROUP_set_seed() + * See the OpenSSL documentation for EC_GROUP_set_seed() */ static VALUE ossl_ec_group_set_seed(VALUE self, VALUE seed) { EC_GROUP *group = NULL; - Require_EC_GROUP(self, group); + GetECGroup(self, group); StringValue(seed); if (EC_GROUP_set_seed(group, (unsigned char *)RSTRING_PTR(seed), RSTRING_LEN(seed)) != (size_t)RSTRING_LEN(seed)) @@ -1137,16 +1064,17 @@ static VALUE ossl_ec_group_set_seed(VALUE self, VALUE seed) /* get/set curve GFp, GF2m */ -/* call-seq: - * group.degree => Fixnum +/* + * call-seq: + * group.degree => integer * - * See the OpenSSL documentation for EC_GROUP_get_degree() + * See the OpenSSL documentation for EC_GROUP_get_degree() */ static VALUE ossl_ec_group_get_degree(VALUE self) { EC_GROUP *group = NULL; - Require_EC_GROUP(self, group); + GetECGroup(self, group); return INT2NUM(EC_GROUP_get_degree(group)); } @@ -1158,26 +1086,26 @@ static VALUE ossl_ec_group_to_string(VALUE self, int format) int i = -1; VALUE str; - Get_EC_GROUP(self, group); + GetECGroup(self, group); if (!(out = BIO_new(BIO_s_mem()))) ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())"); switch(format) { - case EXPORT_PEM: + case EXPORT_PEM: i = PEM_write_bio_ECPKParameters(out, group); - break; - case EXPORT_DER: + break; + case EXPORT_DER: i = i2d_ECPKParameters_bio(out, group); - break; - default: + break; + default: BIO_free(out); - ossl_raise(rb_eRuntimeError, "unknown format (internal error)"); + ossl_raise(rb_eRuntimeError, "unknown format (internal error)"); } if (i != 1) { BIO_free(out); - ossl_raise(eECError, NULL); + ossl_raise(ePKeyError, NULL); } str = ossl_membio2str(out); @@ -1185,8 +1113,9 @@ static VALUE ossl_ec_group_to_string(VALUE self, int format) return str; } -/* call-seq: - * group.to_pem => String +/* + * call-seq: + * group.to_pem => String * * See the OpenSSL documentation for PEM_write_bio_ECPKParameters() */ @@ -1195,20 +1124,22 @@ static VALUE ossl_ec_group_to_pem(VALUE self) return ossl_ec_group_to_string(self, EXPORT_PEM); } -/* call-seq: - * group.to_der => String +/* + * call-seq: + * group.to_der => String * - * See the OpenSSL documentation for i2d_ECPKParameters_bio() + * See the OpenSSL documentation for i2d_ECPKParameters_bio() */ static VALUE ossl_ec_group_to_der(VALUE self) { return ossl_ec_group_to_string(self, EXPORT_DER); } -/* call-seq: - * group.to_text => String +/* + * call-seq: + * group.to_text => String * - * See the OpenSSL documentation for ECPKParameters_print() + * See the OpenSSL documentation for ECPKParameters_print() */ static VALUE ossl_ec_group_to_text(VALUE self) { @@ -1216,13 +1147,13 @@ static VALUE ossl_ec_group_to_text(VALUE self) BIO *out; VALUE str; - Require_EC_GROUP(self, group); + GetECGroup(self, group); if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())"); + ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())"); } if (!ECPKParameters_print(out, group, 0)) { - BIO_free(out); - ossl_raise(eEC_GROUP, NULL); + BIO_free(out); + ossl_raise(eEC_GROUP, NULL); } str = ossl_membio2str(out); @@ -1230,386 +1161,409 @@ static VALUE ossl_ec_group_to_text(VALUE self) } -static void ossl_ec_point_free(void *ptr) +/* + * OpenSSL::PKey::EC::Point + */ +static void +ossl_ec_point_free(void *ptr) { - ossl_ec_point *ec_point = ptr; - if (!ec_point->dont_free && ec_point->point) - EC_POINT_clear_free(ec_point->point); - ruby_xfree(ec_point); + EC_POINT_clear_free(ptr); } static const rb_data_type_t ossl_ec_point_type = { - "OpenSSL/ec_point", + "OpenSSL/EC_POINT", { - 0, ossl_ec_point_free, + 0, ossl_ec_point_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; -static VALUE ossl_ec_point_alloc(VALUE klass) +static VALUE +ossl_ec_point_alloc(VALUE klass) { - ossl_ec_point *ec_point; + return TypedData_Wrap_Struct(klass, &ossl_ec_point_type, NULL); +} + +static VALUE +ec_point_new(const EC_POINT *point, const EC_GROUP *group) +{ + EC_POINT *point_new; VALUE obj; - obj = TypedData_Make_Struct(klass, ossl_ec_point, &ossl_ec_point_type, ec_point); + obj = ossl_ec_point_alloc(cEC_POINT); + point_new = EC_POINT_dup(point, group); + if (!point_new) + ossl_raise(eEC_POINT, "EC_POINT_dup"); + RTYPEDDATA_DATA(obj) = point_new; + rb_ivar_set(obj, id_i_group, ec_group_new(group)); return obj; } +static VALUE ossl_ec_point_initialize_copy(VALUE, VALUE); /* - * call-seq: - * OpenSSL::PKey::EC::Point.new(point) - * OpenSSL::PKey::EC::Point.new(group) - * OpenSSL::PKey::EC::Point.new(group, bn) + * call-seq: + * OpenSSL::PKey::EC::Point.new(point) + * OpenSSL::PKey::EC::Point.new(group [, encoded_point]) + * + * Creates a new instance of OpenSSL::PKey::EC::Point. If the only argument is + * an instance of EC::Point, a copy is returned. Otherwise, creates a point + * that belongs to _group_. * - * See the OpenSSL documentation for EC_POINT_* + * _encoded_point_ is the octet string representation of the point. This + * must be either a String or an OpenSSL::BN. */ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self) { - ossl_ec_point *ec_point; - EC_POINT *point = NULL; - VALUE arg1, arg2; - VALUE group_v = Qnil; - const EC_GROUP *group = NULL; - - TypedData_Get_Struct(self, ossl_ec_point, &ossl_ec_point_type, ec_point); - if (ec_point->point) - ossl_raise(eEC_POINT, "EC_POINT already initialized"); - - switch (rb_scan_args(argc, argv, "11", &arg1, &arg2)) { - case 1: - if (rb_obj_is_kind_of(arg1, cEC_POINT)) { - const EC_POINT *arg_point; - - group_v = rb_iv_get(arg1, "@group"); - SafeRequire_EC_GROUP(group_v, group); - SafeRequire_EC_POINT(arg1, arg_point); - - point = EC_POINT_dup(arg_point, group); - } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) { - group_v = arg1; - SafeRequire_EC_GROUP(group_v, group); + EC_POINT *point; + VALUE group_v, arg2; + const EC_GROUP *group; - point = EC_POINT_new(group); - } else { - ossl_raise(eEC_POINT, "wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group"); - } + TypedData_Get_Struct(self, EC_POINT, &ossl_ec_point_type, point); + if (point) + rb_raise(eEC_POINT, "EC_POINT already initialized"); - break; - case 2: - if (!rb_obj_is_kind_of(arg1, cEC_GROUP)) - ossl_raise(rb_eArgError, "1st argument must be OpenSSL::PKey::EC::Group"); - group_v = arg1; - SafeRequire_EC_GROUP(group_v, group); + rb_scan_args(argc, argv, "11", &group_v, &arg2); + if (rb_obj_is_kind_of(group_v, cEC_POINT)) { + if (argc != 1) + rb_raise(rb_eArgError, "invalid second argument"); + return ossl_ec_point_initialize_copy(self, group_v); + } + GetECGroup(group_v, group); + if (argc == 1) { + point = EC_POINT_new(group); + if (!point) + ossl_raise(eEC_POINT, "EC_POINT_new"); + } + else { if (rb_obj_is_kind_of(arg2, cBN)) { - const BIGNUM *bn = GetBNPtr(arg2); - - point = EC_POINT_bn2point(group, bn, NULL, ossl_bn_ctx); - } else { - BIO *in = ossl_obj2bio(arg1); - -/* BUG: finish me */ - - BIO_free(in); - - if (point == NULL) { - ossl_raise(eEC_POINT, "unknown type for 2nd arg"); + point = EC_POINT_bn2point(group, GetBNPtr(arg2), NULL, ossl_bn_ctx); + if (!point) + ossl_raise(eEC_POINT, "EC_POINT_bn2point"); + } + else { + StringValue(arg2); + point = EC_POINT_new(group); + if (!point) + ossl_raise(eEC_POINT, "EC_POINT_new"); + if (!EC_POINT_oct2point(group, point, + (unsigned char *)RSTRING_PTR(arg2), + RSTRING_LEN(arg2), ossl_bn_ctx)) { + EC_POINT_free(point); + ossl_raise(eEC_POINT, "EC_POINT_oct2point"); } } - break; - default: - ossl_raise(rb_eArgError, "wrong number of arguments"); } - if (point == NULL) - ossl_raise(eEC_POINT, NULL); + RTYPEDDATA_DATA(self) = point; + rb_ivar_set(self, id_i_group, group_v); + + return self; +} - if (NIL_P(group_v)) - ossl_raise(rb_eRuntimeError, "missing group (internal error)"); +/* :nodoc: */ +static VALUE +ossl_ec_point_initialize_copy(VALUE self, VALUE other) +{ + EC_POINT *point, *point_new; + EC_GROUP *group; + VALUE group_v; - ec_point->point = point; + TypedData_Get_Struct(self, EC_POINT, &ossl_ec_point_type, point_new); + if (point_new) + ossl_raise(eEC_POINT, "EC::Point already initialized"); + GetECPoint(other, point); - rb_iv_set(self, "@group", group_v); + group_v = rb_obj_dup(rb_attr_get(other, id_i_group)); + GetECGroup(group_v, group); + + point_new = EC_POINT_dup(point, group); + if (!point_new) + ossl_raise(eEC_POINT, "EC_POINT_dup"); + RTYPEDDATA_DATA(self) = point_new; + rb_ivar_set(self, id_i_group, group_v); return self; } /* - * call-seq: - * point1.eql?(point2) => true | false - * point1 == point2 => true | false - * + * call-seq: + * point1.eql?(point2) => true | false + * point1 == point2 => true | false */ static VALUE ossl_ec_point_eql(VALUE a, VALUE b) { EC_POINT *point1, *point2; - VALUE group_v1 = rb_iv_get(a, "@group"); - VALUE group_v2 = rb_iv_get(b, "@group"); + VALUE group_v1 = rb_attr_get(a, id_i_group); + VALUE group_v2 = rb_attr_get(b, id_i_group); const EC_GROUP *group; if (ossl_ec_group_eql(group_v1, group_v2) == Qfalse) return Qfalse; - Require_EC_POINT(a, point1); - SafeRequire_EC_POINT(b, point2); - SafeRequire_EC_GROUP(group_v1, group); + GetECPoint(a, point1); + GetECPoint(b, point2); + GetECGroup(group_v1, group); - if (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx) == 1) - return Qfalse; + switch (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx)) { + case 0: return Qtrue; + case 1: return Qfalse; + default: ossl_raise(eEC_POINT, "EC_POINT_cmp"); + } - return Qtrue; + UNREACHABLE; } /* - * call-seq: - * point.infinity? => true | false - * + * call-seq: + * point.infinity? => true | false */ static VALUE ossl_ec_point_is_at_infinity(VALUE self) { EC_POINT *point; - VALUE group_v = rb_iv_get(self, "@group"); const EC_GROUP *group; - Require_EC_POINT(self, point); - SafeRequire_EC_GROUP(group_v, group); + GetECPoint(self, point); + GetECPointGroup(self, group); switch (EC_POINT_is_at_infinity(group, point)) { - case 1: return Qtrue; - case 0: return Qfalse; - default: ossl_raise(cEC_POINT, "EC_POINT_is_at_infinity"); + case 1: return Qtrue; + case 0: return Qfalse; + default: ossl_raise(eEC_POINT, "EC_POINT_is_at_infinity"); } UNREACHABLE; } /* - * call-seq: - * point.on_curve? => true | false - * + * call-seq: + * point.on_curve? => true | false */ static VALUE ossl_ec_point_is_on_curve(VALUE self) { EC_POINT *point; - VALUE group_v = rb_iv_get(self, "@group"); const EC_GROUP *group; - Require_EC_POINT(self, point); - SafeRequire_EC_GROUP(group_v, group); + GetECPoint(self, point); + GetECPointGroup(self, group); switch (EC_POINT_is_on_curve(group, point, ossl_bn_ctx)) { - case 1: return Qtrue; - case 0: return Qfalse; - default: ossl_raise(cEC_POINT, "EC_POINT_is_on_curve"); + case 1: return Qtrue; + case 0: return Qfalse; + default: ossl_raise(eEC_POINT, "EC_POINT_is_on_curve"); } UNREACHABLE; } /* - * call-seq: - * point.make_affine! => self + * call-seq: + * point.make_affine! => self * + * This method is deprecated and should not be used. This is a no-op. */ static VALUE ossl_ec_point_make_affine(VALUE self) { EC_POINT *point; - VALUE group_v = rb_iv_get(self, "@group"); const EC_GROUP *group; - Require_EC_POINT(self, point); - SafeRequire_EC_GROUP(group_v, group); + GetECPoint(self, point); + GetECPointGroup(self, group); + rb_warn("OpenSSL::PKey::EC::Point#make_affine! is deprecated"); +#if !defined(OSSL_HAVE_IMMUTABLE_PKEY) && !defined(OPENSSL_IS_AWSLC) if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1) - ossl_raise(cEC_POINT, "EC_POINT_make_affine"); + ossl_raise(eEC_POINT, "EC_POINT_make_affine"); +#endif return self; } /* - * call-seq: - * point.invert! => self - * + * call-seq: + * point.invert! => self */ static VALUE ossl_ec_point_invert(VALUE self) { EC_POINT *point; - VALUE group_v = rb_iv_get(self, "@group"); const EC_GROUP *group; - Require_EC_POINT(self, point); - SafeRequire_EC_GROUP(group_v, group); + GetECPoint(self, point); + GetECPointGroup(self, group); if (EC_POINT_invert(group, point, ossl_bn_ctx) != 1) - ossl_raise(cEC_POINT, "EC_POINT_invert"); + ossl_raise(eEC_POINT, "EC_POINT_invert"); return self; } /* - * call-seq: - * point.set_to_infinity! => self - * + * call-seq: + * point.set_to_infinity! => self */ static VALUE ossl_ec_point_set_to_infinity(VALUE self) { EC_POINT *point; - VALUE group_v = rb_iv_get(self, "@group"); const EC_GROUP *group; - Require_EC_POINT(self, point); - SafeRequire_EC_GROUP(group_v, group); + GetECPoint(self, point); + GetECPointGroup(self, group); if (EC_POINT_set_to_infinity(group, point) != 1) - ossl_raise(cEC_POINT, "EC_POINT_set_to_infinity"); + ossl_raise(eEC_POINT, "EC_POINT_set_to_infinity"); return self; } /* - * call-seq: - * point.to_bn => OpenSSL::BN + * call-seq: + * point.to_octet_string(conversion_form) -> String + * + * Returns the octet string representation of the elliptic curve point. * - * See the OpenSSL documentation for EC_POINT_point2bn() + * _conversion_form_ specifies how the point is converted. Possible values are: + * + * - +:compressed+ + * - +:uncompressed+ + * - +:hybrid+ */ -static VALUE ossl_ec_point_to_bn(VALUE self) +static VALUE +ossl_ec_point_to_octet_string(VALUE self, VALUE conversion_form) { EC_POINT *point; - VALUE bn_obj; - VALUE group_v = rb_iv_get(self, "@group"); const EC_GROUP *group; point_conversion_form_t form; - BIGNUM *bn; - - Require_EC_POINT(self, point); - SafeRequire_EC_GROUP(group_v, group); - - form = EC_GROUP_get_point_conversion_form(group); - - bn_obj = rb_obj_alloc(cBN); - bn = GetBNPtr(bn_obj); - - if (EC_POINT_point2bn(group, point, form, bn, ossl_bn_ctx) == NULL) - ossl_raise(eEC_POINT, "EC_POINT_point2bn"); - - return bn_obj; + VALUE str; + size_t len; + + GetECPoint(self, point); + GetECPointGroup(self, group); + form = parse_point_conversion_form_symbol(conversion_form); + + len = EC_POINT_point2oct(group, point, form, NULL, 0, ossl_bn_ctx); + if (!len) + ossl_raise(eEC_POINT, "EC_POINT_point2oct"); + str = rb_str_new(NULL, (long)len); + if (!EC_POINT_point2oct(group, point, form, + (unsigned char *)RSTRING_PTR(str), len, + ossl_bn_ctx)) + ossl_raise(eEC_POINT, "EC_POINT_point2oct"); + return str; } /* - * call-seq: - * point.mul(bn) => point - * point.mul(bn, bn) => point - * point.mul([bn], [point]) => point - * point.mul([bn], [point], bn) => point + * call-seq: + * point.add(point) => point + * + * Performs elliptic curve point addition. */ -static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self) +static VALUE ossl_ec_point_add(VALUE self, VALUE other) { - EC_POINT *point1, *point2; + EC_POINT *point_self, *point_other, *point_result; const EC_GROUP *group; - VALUE group_v = rb_iv_get(self, "@group"); - VALUE bn_v1, bn_v2, r, points_v; - BIGNUM *bn1 = NULL, *bn2 = NULL; - - Require_EC_POINT(self, point1); - SafeRequire_EC_GROUP(group_v, group); - - r = rb_obj_alloc(cEC_POINT); - ossl_ec_point_initialize(1, &group_v, r); - Require_EC_POINT(r, point2); - - argc = rb_scan_args(argc, argv, "12", &bn_v1, &points_v, &bn_v2); + VALUE group_v = rb_attr_get(self, id_i_group); + VALUE result; - if (rb_obj_is_kind_of(bn_v1, cBN)) { - bn1 = GetBNPtr(bn_v1); - if (argc >= 2) { - bn2 = GetBNPtr(points_v); - } - if (EC_POINT_mul(group, point2, bn2, point1, bn1, ossl_bn_ctx) != 1) - ossl_raise(eEC_POINT, "Multiplication failed"); - } else { - size_t i, points_len, bignums_len; - const EC_POINT **points; - const BIGNUM **bignums; - - Check_Type(bn_v1, T_ARRAY); - bignums_len = RARRAY_LEN(bn_v1); - bignums = (const BIGNUM **)OPENSSL_malloc(bignums_len * (int)sizeof(BIGNUM *)); - - for (i = 0; i < bignums_len; ++i) { - bignums[i] = GetBNPtr(rb_ary_entry(bn_v1, i)); - } - - if (!rb_obj_is_kind_of(points_v, rb_cArray)) { - OPENSSL_free((void *)bignums); - rb_raise(rb_eTypeError, "Argument2 must be an array"); - } + GetECPoint(self, point_self); + GetECPoint(other, point_other); + GetECGroup(group_v, group); - rb_ary_unshift(points_v, self); - points_len = RARRAY_LEN(points_v); - points = (const EC_POINT **)OPENSSL_malloc(points_len * (int)sizeof(EC_POINT *)); + result = rb_obj_alloc(cEC_POINT); + ossl_ec_point_initialize(1, &group_v, result); + GetECPoint(result, point_result); - for (i = 0; i < points_len; ++i) { - Get_EC_POINT(rb_ary_entry(points_v, i), points[i]); - } - - if (argc >= 3) { - bn2 = GetBNPtr(bn_v2); - } - if (EC_POINTs_mul(group, point2, bn2, points_len, points, bignums, ossl_bn_ctx) != 1) { - OPENSSL_free((void *)bignums); - OPENSSL_free((void *)points); - ossl_raise(eEC_POINT, "Multiplication failed"); - } - OPENSSL_free((void *)bignums); - OPENSSL_free((void *)points); + if (EC_POINT_add(group, point_result, point_self, point_other, ossl_bn_ctx) != 1) { + ossl_raise(eEC_POINT, "EC_POINT_add"); } - return r; + return result; } -static void no_copy(VALUE klass) +/* + * call-seq: + * point.mul(bn1 [, bn2]) => point + * + * Performs elliptic curve point multiplication. + * + * The first form calculates <tt>bn1 * point + bn2 * G</tt>, where +G+ is the + * generator of the group of _point_. _bn2_ may be omitted, and in that case, + * the result is just <tt>bn1 * point</tt>. + * + * Before version 4.0.0, and when compiled with OpenSSL 1.1.1 or older, this + * method allowed another form: + * point.mul(bns, points [, bn2]) => point + */ +static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self) { - rb_undef_method(klass, "copy"); - rb_undef_method(klass, "clone"); - rb_undef_method(klass, "dup"); - rb_undef_method(klass, "initialize_copy"); + EC_POINT *point_self, *point_result; + const EC_GROUP *group; + VALUE group_v = rb_attr_get(self, id_i_group); + VALUE arg1, arg2, arg3, result; + const BIGNUM *bn_g = NULL; + + GetECPoint(self, point_self); + GetECGroup(group_v, group); + + result = rb_obj_alloc(cEC_POINT); + ossl_ec_point_initialize(1, &group_v, result); + GetECPoint(result, point_result); + + rb_scan_args(argc, argv, "12", &arg1, &arg2, &arg3); + if (RB_TYPE_P(arg1, T_ARRAY) || argc > 2) + rb_raise(rb_eNotImpError, "OpenSSL::PKey::EC::Point#mul with arrays " \ + "is no longer supported"); + + BIGNUM *bn = GetBNPtr(arg1); + if (!NIL_P(arg2)) + bn_g = GetBNPtr(arg2); + if (EC_POINT_mul(group, point_result, bn_g, point_self, bn, ossl_bn_ctx) != 1) + ossl_raise(eEC_POINT, NULL); + + return result; } void Init_ossl_ec(void) { -#ifdef DONT_NEED_RDOC_WORKAROUND - mOSSL = rb_define_module("OpenSSL"); - mPKey = rb_define_module_under(mOSSL, "PKey"); -#endif - - eECError = rb_define_class_under(mPKey, "ECError", ePKeyError); - +#undef rb_intern + /* + * Document-class: OpenSSL::PKey::EC + * + * OpenSSL::PKey::EC provides access to Elliptic Curve Digital Signature + * Algorithm (ECDSA) and Elliptic Curve Diffie-Hellman (ECDH). + * + * === Key exchange + * ec1 = OpenSSL::PKey::EC.generate("prime256v1") + * ec2 = OpenSSL::PKey::EC.generate("prime256v1") + * # ec1 and ec2 have own private key respectively + * shared_key1 = ec1.dh_compute_key(ec2.public_key) + * shared_key2 = ec2.dh_compute_key(ec1.public_key) + * + * p shared_key1 == shared_key2 #=> true + */ cEC = rb_define_class_under(mPKey, "EC", cPKey); cEC_GROUP = rb_define_class_under(cEC, "Group", rb_cObject); cEC_POINT = rb_define_class_under(cEC, "Point", rb_cObject); eEC_GROUP = rb_define_class_under(cEC_GROUP, "Error", eOSSLError); eEC_POINT = rb_define_class_under(cEC_POINT, "Error", eOSSLError); - s_GFp = rb_intern("GFp"); - s_GF2m = rb_intern("GF2m"); - s_GFp_simple = rb_intern("GFp_simple"); - s_GFp_mont = rb_intern("GFp_mont"); - s_GFp_nist = rb_intern("GFp_nist"); - s_GF2m_simple = rb_intern("GF2m_simple"); + sym_GFp = ID2SYM(rb_intern_const("GFp")); + sym_GF2m = ID2SYM(rb_intern_const("GF2m")); - ID_uncompressed = rb_intern("uncompressed"); - ID_compressed = rb_intern("compressed"); - ID_hybrid = rb_intern("hybrid"); + sym_uncompressed = ID2SYM(rb_intern_const("uncompressed")); + sym_compressed = ID2SYM(rb_intern_const("compressed")); + sym_hybrid = ID2SYM(rb_intern_const("hybrid")); -#ifdef OPENSSL_EC_NAMED_CURVE - rb_define_const(cEC, "NAMED_CURVE", ULONG2NUM(OPENSSL_EC_NAMED_CURVE)); -#endif + rb_define_const(cEC, "NAMED_CURVE", INT2NUM(OPENSSL_EC_NAMED_CURVE)); + rb_define_const(cEC, "EXPLICIT_CURVE", INT2NUM(OPENSSL_EC_EXPLICIT_CURVE)); rb_define_singleton_method(cEC, "builtin_curves", ossl_s_builtin_curves, 0); + rb_define_singleton_method(cEC, "generate", ossl_ec_key_s_generate, 1); rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1); -/* copy/dup/cmp */ +#ifndef HAVE_EVP_PKEY_DUP + rb_define_method(cEC, "initialize_copy", ossl_ec_key_initialize_copy, 1); +#endif rb_define_method(cEC, "group", ossl_ec_key_get_group, 0); rb_define_method(cEC, "group=", ossl_ec_key_set_group, 1); @@ -1617,8 +1571,10 @@ void Init_ossl_ec(void) rb_define_method(cEC, "private_key=", ossl_ec_key_set_private_key, 1); rb_define_method(cEC, "public_key", ossl_ec_key_get_public_key, 0); rb_define_method(cEC, "public_key=", ossl_ec_key_set_public_key, 1); - rb_define_method(cEC, "private_key?", ossl_ec_key_is_private_key, 0); - rb_define_method(cEC, "public_key?", ossl_ec_key_is_public_key, 0); + rb_define_method(cEC, "private?", ossl_ec_key_is_private, 0); + rb_define_method(cEC, "public?", ossl_ec_key_is_public, 0); + rb_define_alias(cEC, "private_key?", "private?"); + rb_define_alias(cEC, "public_key?", "public?"); /* rb_define_method(cEC, "", ossl_ec_key_get_, 0); rb_define_method(cEC, "=", ossl_ec_key_set_ 1); set/get enc_flags @@ -1626,22 +1582,18 @@ void Init_ossl_ec(void) set/get asn1_flag (can use ruby to call self.group.asn1_flag) set/get precompute_mult */ - rb_define_method(cEC, "generate_key", ossl_ec_key_generate_key, 0); + rb_define_method(cEC, "generate_key!", ossl_ec_key_generate_key, 0); + rb_define_alias(cEC, "generate_key", "generate_key!"); rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0); - rb_define_method(cEC, "dh_compute_key", ossl_ec_key_dh_compute_key, 1); - rb_define_method(cEC, "dsa_sign_asn1", ossl_ec_key_dsa_sign_asn1, 1); - rb_define_method(cEC, "dsa_verify_asn1", ossl_ec_key_dsa_verify_asn1, 2); -/* do_sign/do_verify */ - rb_define_method(cEC, "export", ossl_ec_key_export, -1); rb_define_alias(cEC, "to_pem", "export"); rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0); - rb_define_method(cEC, "to_text", ossl_ec_key_to_text, 0); rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc); rb_define_method(cEC_GROUP, "initialize", ossl_ec_group_initialize, -1); + rb_define_method(cEC_GROUP, "initialize_copy", ossl_ec_group_initialize_copy, 1); rb_define_method(cEC_GROUP, "eql?", ossl_ec_group_eql, 1); rb_define_alias(cEC_GROUP, "==", "eql?"); /* copy/dup/cmp */ @@ -1677,6 +1629,7 @@ void Init_ossl_ec(void) rb_define_alloc_func(cEC_POINT, ossl_ec_point_alloc); rb_define_method(cEC_POINT, "initialize", ossl_ec_point_initialize, -1); + rb_define_method(cEC_POINT, "initialize_copy", ossl_ec_point_initialize_copy, 1); rb_attr(cEC_POINT, rb_intern("group"), 1, 0, 0); rb_define_method(cEC_POINT, "eql?", ossl_ec_point_eql, 1); rb_define_alias(cEC_POINT, "==", "eql?"); @@ -1688,12 +1641,11 @@ void Init_ossl_ec(void) rb_define_method(cEC_POINT, "set_to_infinity!", ossl_ec_point_set_to_infinity, 0); /* all the other methods */ - rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, 0); + rb_define_method(cEC_POINT, "to_octet_string", ossl_ec_point_to_octet_string, 1); + rb_define_method(cEC_POINT, "add", ossl_ec_point_add, 1); rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1); - no_copy(cEC); - no_copy(cEC_GROUP); - no_copy(cEC_POINT); + id_i_group = rb_intern("@group"); } #else /* defined NO_EC */ diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index 0fef10a042..039b2c6a34 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -1,275 +1,194 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ -#if !defined(OPENSSL_NO_RSA) - #include "ossl.h" +#if !defined(OPENSSL_NO_RSA) + #define GetPKeyRSA(obj, pkey) do { \ GetPKey((obj), (pkey)); \ - if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_RSA) { /* PARANOIA? */ \ - ossl_raise(rb_eRuntimeError, "THIS IS NOT A RSA!") ; \ + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) { /* PARANOIA? */ \ + ossl_raise(rb_eRuntimeError, "THIS IS NOT A RSA!") ; \ } \ } while (0) +#define GetRSA(obj, rsa) do { \ + EVP_PKEY *_pkey; \ + GetPKeyRSA((obj), _pkey); \ + (rsa) = EVP_PKEY_get0_RSA(_pkey); \ + if ((rsa) == NULL) \ + ossl_raise(ePKeyError, "failed to get RSA from EVP_PKEY"); \ +} while (0) -#define RSA_HAS_PRIVATE(rsa) ((rsa)->p && (rsa)->q) -#define RSA_PRIVATE(obj,rsa) (RSA_HAS_PRIVATE(rsa)||OSSL_PKEY_IS_PRIVATE(obj)) - -/* - * Classes - */ -VALUE cRSA; -VALUE eRSAError; - -/* - * Public - */ -static VALUE -rsa_instance(VALUE klass, RSA *rsa) +static inline int +RSA_HAS_PRIVATE(OSSL_3_const RSA *rsa) { - EVP_PKEY *pkey; - VALUE obj; - - if (!rsa) { - return Qfalse; - } - if (!(pkey = EVP_PKEY_new())) { - return Qfalse; - } - if (!EVP_PKEY_assign_RSA(pkey, rsa)) { - EVP_PKEY_free(pkey); - return Qfalse; - } - WrapPKey(klass, obj, pkey); + const BIGNUM *e, *d; - return obj; + RSA_get0_key(rsa, NULL, &e, &d); + return e && d; } -VALUE -ossl_rsa_new(EVP_PKEY *pkey) +static inline int +RSA_PRIVATE(VALUE obj, OSSL_3_const RSA *rsa) { - VALUE obj; - - if (!pkey) { - obj = rsa_instance(cRSA, RSA_new()); - } - else { - if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) { - ossl_raise(rb_eTypeError, "Not a RSA key!"); - } - WrapPKey(cRSA, obj, pkey); - } - if (obj == Qfalse) { - ossl_raise(eRSAError, NULL); - } - - return obj; + return RSA_HAS_PRIVATE(rsa) || OSSL_PKEY_IS_PRIVATE(obj); } /* - * Private + * Classes */ -#if defined(HAVE_RSA_GENERATE_KEY_EX) && HAVE_BN_GENCB -struct rsa_blocking_gen_arg { - RSA *rsa; - BIGNUM *e; - int size; - BN_GENCB *cb; - int result; -}; - -static void * -rsa_blocking_gen(void *arg) -{ - struct rsa_blocking_gen_arg *gen = (struct rsa_blocking_gen_arg *)arg; - gen->result = RSA_generate_key_ex(gen->rsa, gen->size, gen->e, gen->cb); - return 0; -} -#endif - -static RSA * -rsa_generate(int size, unsigned long exp) -{ -#if defined(HAVE_RSA_GENERATE_KEY_EX) && HAVE_BN_GENCB - int i; - BN_GENCB cb; - struct ossl_generate_cb_arg cb_arg; - struct rsa_blocking_gen_arg gen_arg; - RSA *rsa = RSA_new(); - BIGNUM *e = BN_new(); - - if (!rsa || !e) { - if (e) BN_free(e); - if (rsa) RSA_free(rsa); - return 0; - } - for (i = 0; i < (int)sizeof(exp) * 8; ++i) { - if (exp & (1UL << i)) { - if (BN_set_bit(e, i) == 0) { - BN_free(e); - RSA_free(rsa); - return 0; - } - } - } - - memset(&cb_arg, 0, sizeof(struct ossl_generate_cb_arg)); - if (rb_block_given_p()) - cb_arg.yield = 1; - BN_GENCB_set(&cb, ossl_generate_cb_2, &cb_arg); - gen_arg.rsa = rsa; - gen_arg.e = e; - gen_arg.size = size; - gen_arg.cb = &cb; - if (cb_arg.yield == 1) { - /* we cannot release GVL when callback proc is supplied */ - rsa_blocking_gen(&gen_arg); - } else { - /* there's a chance to unblock */ - rb_thread_call_without_gvl(rsa_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg); - } - if (!gen_arg.result) { - BN_free(e); - RSA_free(rsa); - if (cb_arg.state) rb_jump_tag(cb_arg.state); - return 0; - } - - BN_free(e); - return rsa; -#else - return RSA_generate_key(size, exp, rb_block_given_p() ? ossl_generate_cb : NULL, NULL); -#endif -} +VALUE cRSA; /* - * call-seq: - * RSA.generate(size) => RSA instance - * RSA.generate(size, exponent) => RSA instance - * - * Generates an RSA keypair. +size+ is an integer representing the desired key - * size. Keys smaller than 1024 should be considered insecure. +exponent+ is - * an odd number normally 3, 17, or 65537. + * Private */ -static VALUE -ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass) -{ -/* why does this method exist? why can't initialize take an optional exponent? */ - RSA *rsa; - VALUE size, exp; - VALUE obj; - - rb_scan_args(argc, argv, "11", &size, &exp); - - rsa = rsa_generate(NUM2INT(size), NIL_P(exp) ? RSA_F4 : NUM2ULONG(exp)); /* err handled by rsa_instance */ - obj = rsa_instance(klass, rsa); - - if (obj == Qfalse) { - RSA_free(rsa); - ossl_raise(eRSAError, NULL); - } - - return obj; -} - /* * call-seq: - * RSA.new(key_size) => RSA instance - * RSA.new(encoded_key) => RSA instance - * RSA.new(encoded_key, pass_phrase) => RSA instance + * RSA.new -> rsa + * RSA.new(encoded_key [, password ]) -> rsa + * RSA.new(encoded_key) { password } -> rsa + * RSA.new(size [, exponent]) -> rsa * - * Generates or loads an RSA keypair. If an integer +key_size+ is given it - * represents the desired key size. Keys less than 1024 bits should be - * considered insecure. + * Generates or loads an \RSA keypair. * - * A key can instead be loaded from an +encoded_key+ which must be PEM or DER - * encoded. A +pass_phrase+ can be used to decrypt the key. If none is given - * OpenSSL will prompt for the pass phrase. + * If called without arguments, creates a new instance with no key components + * set. They can be set individually by #set_key, #set_factors, and + * #set_crt_params. + * This form is not compatible with OpenSSL 3.0 or later. * - * = Examples + * If called with a String, tries to parse as DER or PEM encoding of an \RSA key. + * Note that if _password_ is not specified, but the key is encrypted with a + * password, \OpenSSL will prompt for it. + * See also OpenSSL::PKey.read which can parse keys of any kind. * + * If called with a number, generates a new key pair. This form works as an + * alias of RSA.generate. + * + * Examples: * OpenSSL::PKey::RSA.new 2048 * OpenSSL::PKey::RSA.new File.read 'rsa.pem' - * OpenSSL::PKey::RSA.new File.read('rsa.pem'), 'my pass phrase' + * OpenSSL::PKey::RSA.new File.read('rsa.pem'), 'my password' */ static VALUE ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; RSA *rsa; - BIO *in; - char *passwd = NULL; + BIO *in = NULL; VALUE arg, pass; - - GetPKey(self, pkey); - if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) { - rsa = RSA_new(); + int type; + + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); + + /* The RSA.new(size, generator) form is handled by lib/openssl/pkey.rb */ + rb_scan_args(argc, argv, "02", &arg, &pass); + if (argc == 0) { +#ifdef OSSL_HAVE_IMMUTABLE_PKEY + rb_raise(rb_eArgError, "OpenSSL::PKey::RSA.new cannot be called " \ + "without arguments; pkeys are immutable with OpenSSL 3.0"); +#else + rsa = RSA_new(); + if (!rsa) + ossl_raise(ePKeyError, "RSA_new"); + goto legacy; +#endif } - else if (FIXNUM_P(arg)) { - rsa = rsa_generate(FIX2INT(arg), NIL_P(pass) ? RSA_F4 : NUM2ULONG(pass)); - if (!rsa) ossl_raise(eRSAError, NULL); + + pass = ossl_pem_passwd_value(pass); + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(&arg); + + /* First try RSAPublicKey format */ + rsa = d2i_RSAPublicKey_bio(in, NULL); + if (rsa) + goto legacy; + OSSL_BIO_reset(in); + rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL); + if (rsa) + goto legacy; + OSSL_BIO_reset(in); + + /* Use the generic routine */ + pkey = ossl_pkey_read_generic(in, pass); + BIO_free(in); + if (!pkey) + ossl_raise(ePKeyError, "Neither PUB key nor PRIV key"); + + type = EVP_PKEY_base_id(pkey); + if (type != EVP_PKEY_RSA) { + EVP_PKEY_free(pkey); + rb_raise(ePKeyError, "incorrect pkey type: %s", OBJ_nid2sn(type)); } - else { - if (!NIL_P(pass)) passwd = StringValuePtr(pass); - arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(arg); - rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd); - if (!rsa) { - OSSL_BIO_reset(in); - rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL); - } - if (!rsa) { - OSSL_BIO_reset(in); - rsa = d2i_RSAPrivateKey_bio(in, NULL); - } - if (!rsa) { - OSSL_BIO_reset(in); - rsa = d2i_RSA_PUBKEY_bio(in, NULL); - } - if (!rsa) { - OSSL_BIO_reset(in); - rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL); - } - if (!rsa) { - OSSL_BIO_reset(in); - rsa = d2i_RSAPublicKey_bio(in, NULL); - } - BIO_free(in); - if (!rsa) { - ossl_raise(eRSAError, "Neither PUB key nor PRIV key"); - } + RTYPEDDATA_DATA(self) = pkey; + return self; + + legacy: + BIO_free(in); + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_RSA(pkey, rsa) != 1) { + EVP_PKEY_free(pkey); + RSA_free(rsa); + ossl_raise(ePKeyError, "EVP_PKEY_assign_RSA"); } - if (!EVP_PKEY_assign_RSA(pkey, rsa)) { - RSA_free(rsa); - ossl_raise(eRSAError, NULL); + RTYPEDDATA_DATA(self) = pkey; + return self; +} + +#ifndef HAVE_EVP_PKEY_DUP +/* :nodoc: */ +static VALUE +ossl_rsa_initialize_copy(VALUE self, VALUE other) +{ + EVP_PKEY *pkey; + RSA *rsa, *rsa_new; + + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); + GetRSA(other, rsa); + + rsa_new = (RSA *)ASN1_dup((i2d_of_void *)i2d_RSAPrivateKey, + (d2i_of_void *)d2i_RSAPrivateKey, + (char *)rsa); + if (!rsa_new) + ossl_raise(ePKeyError, "ASN1_dup"); + + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_RSA(pkey, rsa_new) != 1) { + RSA_free(rsa_new); + ossl_raise(ePKeyError, "EVP_PKEY_assign_RSA"); } + RTYPEDDATA_DATA(self) = pkey; return self; } +#endif /* * call-seq: * rsa.public? => true * - * The return value is always true since every private key is also a public + * The return value is always +true+ since every private key is also a public * key. */ static VALUE ossl_rsa_is_public(VALUE self) { - EVP_PKEY *pkey; + OSSL_3_const RSA *rsa; - GetPKeyRSA(self, pkey); + GetRSA(self, rsa); /* * This method should check for n and e. BUG. */ + (void)rsa; return Qtrue; } @@ -282,369 +201,345 @@ ossl_rsa_is_public(VALUE self) static VALUE ossl_rsa_is_private(VALUE self) { - EVP_PKEY *pkey; + OSSL_3_const RSA *rsa; - GetPKeyRSA(self, pkey); + GetRSA(self, rsa); - return (RSA_PRIVATE(self, pkey->pkey.rsa)) ? Qtrue : Qfalse; + return RSA_PRIVATE(self, rsa) ? Qtrue : Qfalse; } -/* - * call-seq: - * rsa.export([cipher, pass_phrase]) => PEM-format String - * rsa.to_pem([cipher, pass_phrase]) => PEM-format String - * rsa.to_s([cipher, pass_phrase]) => PEM-format String - * - * Outputs this keypair in PEM encoding. If +cipher+ and +pass_phrase+ are - * given they will be used to encrypt the key. +cipher+ must be an - * OpenSSL::Cipher::Cipher instance. - */ -static VALUE -ossl_rsa_export(int argc, VALUE *argv, VALUE self) +static int +can_export_rsaprivatekey(VALUE self) { - EVP_PKEY *pkey; - BIO *out; - const EVP_CIPHER *ciph = NULL; - char *passwd = NULL; - VALUE cipher, pass, str; - - GetPKeyRSA(self, pkey); - - rb_scan_args(argc, argv, "02", &cipher, &pass); - - if (!NIL_P(cipher)) { - ciph = GetCipherPtr(cipher); - if (!NIL_P(pass)) { - StringValue(pass); - if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN) - ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long"); - passwd = RSTRING_PTR(pass); - } - } - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eRSAError, NULL); - } - if (RSA_HAS_PRIVATE(pkey->pkey.rsa)) { - if (!PEM_write_bio_RSAPrivateKey(out, pkey->pkey.rsa, ciph, - NULL, 0, ossl_pem_passwd_cb, passwd)) { - BIO_free(out); - ossl_raise(eRSAError, NULL); - } - } else { - if (!PEM_write_bio_RSA_PUBKEY(out, pkey->pkey.rsa)) { - BIO_free(out); - ossl_raise(eRSAError, NULL); - } - } - str = ossl_membio2str(out); + OSSL_3_const RSA *rsa; + const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp; - return str; + GetRSA(self, rsa); + + RSA_get0_key(rsa, &n, &e, &d); + RSA_get0_factors(rsa, &p, &q); + RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); + + return n && e && d && p && q && dmp1 && dmq1 && iqmp; } /* * call-seq: - * rsa.to_der => DER-format String + * rsa.export([cipher, password]) => PEM-format String + * rsa.to_pem([cipher, password]) => PEM-format String + * rsa.to_s([cipher, password]) => PEM-format String + * + * Serializes a private or public key to a PEM-encoding. + * + * [When the key contains public components only] + * + * Serializes it into an X.509 SubjectPublicKeyInfo. + * The parameters _cipher_ and _password_ are ignored. + * + * A PEM-encoded key will look like: + * + * -----BEGIN PUBLIC KEY----- + * [...] + * -----END PUBLIC KEY----- + * + * Consider using #public_to_pem instead. This serializes the key into an + * X.509 SubjectPublicKeyInfo regardless of whether the key is a public key + * or a private key. + * + * [When the key contains private components, and no parameters are given] + * + * Serializes it into a PKCS #1 RSAPrivateKey. + * + * A PEM-encoded key will look like: + * + * -----BEGIN RSA PRIVATE KEY----- + * [...] + * -----END RSA PRIVATE KEY----- + * + * [When the key contains private components, and _cipher_ and _password_ are given] + * + * Serializes it into a PKCS #1 RSAPrivateKey + * and encrypts it in OpenSSL's traditional PEM encryption format. + * _cipher_ must be a cipher name understood by OpenSSL::Cipher.new or an + * instance of OpenSSL::Cipher. * - * Outputs this keypair in DER encoding. + * An encrypted PEM-encoded key will look like: + * + * -----BEGIN RSA PRIVATE KEY----- + * Proc-Type: 4,ENCRYPTED + * DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 + * + * [...] + * -----END RSA PRIVATE KEY----- + * + * Note that this format uses MD5 to derive the encryption key, and hence + * will not be available on FIPS-compliant systems. + * + * <b>This method is kept for compatibility.</b> + * This should only be used when the PKCS #1 RSAPrivateKey format is required. + * + * Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem + * (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead. */ static VALUE -ossl_rsa_to_der(VALUE self) +ossl_rsa_export(int argc, VALUE *argv, VALUE self) { - EVP_PKEY *pkey; - int (*i2d_func)_((const RSA*, unsigned char**)); - unsigned char *p; - long len; - VALUE str; - - GetPKeyRSA(self, pkey); - if(RSA_HAS_PRIVATE(pkey->pkey.rsa)) - i2d_func = i2d_RSAPrivateKey; + if (can_export_rsaprivatekey(self)) + return ossl_pkey_export_traditional(argc, argv, self, 0); else - i2d_func = (int (*)(const RSA*, unsigned char**))i2d_RSA_PUBKEY; - if((len = i2d_func(pkey->pkey.rsa, NULL)) <= 0) - ossl_raise(eRSAError, NULL); - str = rb_str_new(0, len); - p = (unsigned char *)RSTRING_PTR(str); - if(i2d_func(pkey->pkey.rsa, &p) < 0) - ossl_raise(eRSAError, NULL); - ossl_str_adjust(str, p); - - return str; + return ossl_pkey_export_spki(self, 0); } -#define ossl_rsa_buf_size(pkey) (RSA_size((pkey)->pkey.rsa)+16) - /* * call-seq: - * rsa.public_encrypt(string) => String - * rsa.public_encrypt(string, padding) => String + * rsa.to_der => DER-format String * - * Encrypt +string+ with the public key. +padding+ defaults to PKCS1_PADDING. - * The encrypted string output can be decrypted using #private_decrypt. - */ -static VALUE -ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self) -{ - EVP_PKEY *pkey; - int buf_len, pad; - VALUE str, buffer, padding; - - GetPKeyRSA(self, pkey); - rb_scan_args(argc, argv, "11", &buffer, &padding); - pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); - StringValue(buffer); - str = rb_str_new(0, ossl_rsa_buf_size(pkey)); - buf_len = RSA_public_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), - (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa, - pad); - if (buf_len < 0) ossl_raise(eRSAError, NULL); - rb_str_set_len(str, buf_len); - - return str; -} - -/* - * call-seq: - * rsa.public_decrypt(string) => String - * rsa.public_decrypt(string, padding) => String + * Serializes a private or public key to a DER-encoding. * - * Decrypt +string+, which has been encrypted with the private key, with the - * public key. +padding+ defaults to PKCS1_PADDING. - */ -static VALUE -ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self) -{ - EVP_PKEY *pkey; - int buf_len, pad; - VALUE str, buffer, padding; - - GetPKeyRSA(self, pkey); - rb_scan_args(argc, argv, "11", &buffer, &padding); - pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); - StringValue(buffer); - str = rb_str_new(0, ossl_rsa_buf_size(pkey)); - buf_len = RSA_public_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), - (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa, - pad); - if (buf_len < 0) ossl_raise(eRSAError, NULL); - rb_str_set_len(str, buf_len); - - return str; -} - -/* - * call-seq: - * rsa.private_encrypt(string) => String - * rsa.private_encrypt(string, padding) => String + * See #to_pem for details. * - * Encrypt +string+ with the private key. +padding+ defaults to PKCS1_PADDING. - * The encrypted string output can be decrypted using #public_decrypt. - */ -static VALUE -ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self) -{ - EVP_PKEY *pkey; - int buf_len, pad; - VALUE str, buffer, padding; - - GetPKeyRSA(self, pkey); - if (!RSA_PRIVATE(self, pkey->pkey.rsa)) { - ossl_raise(eRSAError, "private key needed."); - } - rb_scan_args(argc, argv, "11", &buffer, &padding); - pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); - StringValue(buffer); - str = rb_str_new(0, ossl_rsa_buf_size(pkey)); - buf_len = RSA_private_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), - (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa, - pad); - if (buf_len < 0) ossl_raise(eRSAError, NULL); - rb_str_set_len(str, buf_len); - - return str; -} - -/* - * call-seq: - * rsa.private_decrypt(string) => String - * rsa.private_decrypt(string, padding) => String + * <b>This method is kept for compatibility.</b> + * This should only be used when the PKCS #1 RSAPrivateKey format is required. * - * Decrypt +string+, which has been encrypted with the public key, with the - * private key. +padding+ defaults to PKCS1_PADDING. + * Consider using #public_to_der or #private_to_der instead. */ static VALUE -ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self) +ossl_rsa_to_der(VALUE self) { - EVP_PKEY *pkey; - int buf_len, pad; - VALUE str, buffer, padding; - - GetPKeyRSA(self, pkey); - if (!RSA_PRIVATE(self, pkey->pkey.rsa)) { - ossl_raise(eRSAError, "private key needed."); - } - rb_scan_args(argc, argv, "11", &buffer, &padding); - pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); - StringValue(buffer); - str = rb_str_new(0, ossl_rsa_buf_size(pkey)); - buf_len = RSA_private_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), - (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa, - pad); - if (buf_len < 0) ossl_raise(eRSAError, NULL); - rb_str_set_len(str, buf_len); - - return str; + if (can_export_rsaprivatekey(self)) + return ossl_pkey_export_traditional(0, NULL, self, 1); + else + return ossl_pkey_export_spki(self, 1); } /* * call-seq: - * rsa.params => hash + * rsa.sign_pss(digest, data, salt_length:, mgf1_hash:) -> String + * + * Signs _data_ using the Probabilistic Signature Scheme (RSA-PSS) and returns + * the calculated signature. + * + * PKeyError will be raised if an error occurs. * - * THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!! + * See #verify_pss for the verification operation. * - * Stores all parameters of key to the hash. The hash has keys 'n', 'e', 'd', - * 'p', 'q', 'dmp1', 'dmq1', 'iqmp'. + * === Parameters + * _digest_:: + * A String containing the message digest algorithm name. + * _data_:: + * A String. The data to be signed. + * _salt_length_:: + * The length in octets of the salt. Two special values are reserved: + * +:digest+ means the digest length, and +:max+ means the maximum possible + * length for the combination of the private key and the selected message + * digest algorithm. + * _mgf1_hash_:: + * The hash algorithm used in MGF1 (the currently supported mask generation + * function (MGF)). * - * Don't use :-)) (It's up to you) + * === Example + * data = "Sign me!" + * pkey = OpenSSL::PKey::RSA.new(2048) + * signature = pkey.sign_pss("SHA256", data, salt_length: :max, mgf1_hash: "SHA256") + * pub_key = OpenSSL::PKey.read(pkey.public_to_der) + * puts pub_key.verify_pss("SHA256", signature, data, + * salt_length: :auto, mgf1_hash: "SHA256") # => true */ static VALUE -ossl_rsa_get_params(VALUE self) +ossl_rsa_sign_pss(int argc, VALUE *argv, VALUE self) { + VALUE digest, data, options, kwargs[2], signature, mgf1md_holder, md_holder; + static ID kwargs_ids[2]; EVP_PKEY *pkey; - VALUE hash; + EVP_PKEY_CTX *pkey_ctx; + const EVP_MD *md, *mgf1md; + EVP_MD_CTX *md_ctx; + size_t buf_len; + int salt_len; + + if (!kwargs_ids[0]) { + kwargs_ids[0] = rb_intern_const("salt_length"); + kwargs_ids[1] = rb_intern_const("mgf1_hash"); + } + rb_scan_args(argc, argv, "2:", &digest, &data, &options); + rb_get_kwargs(options, kwargs_ids, 2, 0, kwargs); + if (kwargs[0] == ID2SYM(rb_intern("max"))) + salt_len = -2; /* RSA_PSS_SALTLEN_MAX_SIGN */ + else if (kwargs[0] == ID2SYM(rb_intern("digest"))) + salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */ + else + salt_len = NUM2INT(kwargs[0]); + mgf1md = ossl_evp_md_fetch(kwargs[1], &mgf1md_holder); + + pkey = GetPrivPKeyPtr(self); + buf_len = EVP_PKEY_size(pkey); + md = ossl_evp_md_fetch(digest, &md_holder); + StringValue(data); + signature = rb_str_new(NULL, (long)buf_len); + + md_ctx = EVP_MD_CTX_new(); + if (!md_ctx) + goto err; + + if (EVP_DigestSignInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1) + goto err; + + if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1) + goto err; - GetPKeyRSA(self, pkey); + if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) != 1) + goto err; - hash = rb_hash_new(); + if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1md) != 1) + goto err; - rb_hash_aset(hash, rb_str_new2("n"), ossl_bn_new(pkey->pkey.rsa->n)); - rb_hash_aset(hash, rb_str_new2("e"), ossl_bn_new(pkey->pkey.rsa->e)); - rb_hash_aset(hash, rb_str_new2("d"), ossl_bn_new(pkey->pkey.rsa->d)); - rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.rsa->p)); - rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(pkey->pkey.rsa->q)); - rb_hash_aset(hash, rb_str_new2("dmp1"), ossl_bn_new(pkey->pkey.rsa->dmp1)); - rb_hash_aset(hash, rb_str_new2("dmq1"), ossl_bn_new(pkey->pkey.rsa->dmq1)); - rb_hash_aset(hash, rb_str_new2("iqmp"), ossl_bn_new(pkey->pkey.rsa->iqmp)); + if (EVP_DigestSignUpdate(md_ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1) + goto err; - return hash; + if (EVP_DigestSignFinal(md_ctx, (unsigned char *)RSTRING_PTR(signature), &buf_len) != 1) + goto err; + + rb_str_set_len(signature, (long)buf_len); + + EVP_MD_CTX_free(md_ctx); + return signature; + + err: + EVP_MD_CTX_free(md_ctx); + ossl_raise(ePKeyError, NULL); } /* * call-seq: - * rsa.to_text => String + * rsa.verify_pss(digest, signature, data, salt_length:, mgf1_hash:) -> true | false * - * THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!! + * Verifies _data_ using the Probabilistic Signature Scheme (RSA-PSS). * - * Dumps all parameters of a keypair to a String + * The return value is +true+ if the signature is valid, +false+ otherwise. + * PKeyError will be raised if an error occurs. * - * Don't use :-)) (It's up to you) + * See #sign_pss for the signing operation and an example code. + * + * === Parameters + * _digest_:: + * A String containing the message digest algorithm name. + * _data_:: + * A String. The data to be signed. + * _salt_length_:: + * The length in octets of the salt. Two special values are reserved: + * +:digest+ means the digest length, and +:auto+ means automatically + * determining the length based on the signature. + * _mgf1_hash_:: + * The hash algorithm used in MGF1. */ static VALUE -ossl_rsa_to_text(VALUE self) +ossl_rsa_verify_pss(int argc, VALUE *argv, VALUE self) { + VALUE digest, signature, data, options, kwargs[2], mgf1md_holder, md_holder; + static ID kwargs_ids[2]; EVP_PKEY *pkey; - BIO *out; - VALUE str; - - GetPKeyRSA(self, pkey); - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eRSAError, NULL); + EVP_PKEY_CTX *pkey_ctx; + const EVP_MD *md, *mgf1md; + EVP_MD_CTX *md_ctx; + int result, salt_len; + + if (!kwargs_ids[0]) { + kwargs_ids[0] = rb_intern_const("salt_length"); + kwargs_ids[1] = rb_intern_const("mgf1_hash"); } - if (!RSA_print(out, pkey->pkey.rsa, 0)) { /* offset = 0 */ - BIO_free(out); - ossl_raise(eRSAError, NULL); + rb_scan_args(argc, argv, "3:", &digest, &signature, &data, &options); + rb_get_kwargs(options, kwargs_ids, 2, 0, kwargs); + if (kwargs[0] == ID2SYM(rb_intern("auto"))) + salt_len = -2; /* RSA_PSS_SALTLEN_AUTO */ + else if (kwargs[0] == ID2SYM(rb_intern("digest"))) + salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */ + else + salt_len = NUM2INT(kwargs[0]); + mgf1md = ossl_evp_md_fetch(kwargs[1], &mgf1md_holder); + + GetPKey(self, pkey); + md = ossl_evp_md_fetch(digest, &md_holder); + StringValue(signature); + StringValue(data); + + md_ctx = EVP_MD_CTX_new(); + if (!md_ctx) + goto err; + + if (EVP_DigestVerifyInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1) + goto err; + + if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1) + goto err; + + if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) != 1) + goto err; + + if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1md) != 1) + goto err; + + if (EVP_DigestVerifyUpdate(md_ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1) + goto err; + + result = EVP_DigestVerifyFinal(md_ctx, + (unsigned char *)RSTRING_PTR(signature), + RSTRING_LEN(signature)); + EVP_MD_CTX_free(md_ctx); + + switch (result) { + case 0: + ossl_clear_error(); + return Qfalse; + case 1: + return Qtrue; + default: + ossl_raise(ePKeyError, "EVP_DigestVerifyFinal"); } - str = ossl_membio2str(out); - return str; + err: + EVP_MD_CTX_free(md_ctx); + ossl_raise(ePKeyError, NULL); } /* + * Document-method: OpenSSL::PKey::RSA#set_key * call-seq: - * rsa.public_key -> RSA + * rsa.set_key(n, e, d) -> self * - * Makes new RSA instance containing the public key from the private key. + * Sets _n_, _e_, _d_ for the RSA instance. */ -static VALUE -ossl_rsa_to_public_key(VALUE self) -{ - EVP_PKEY *pkey; - RSA *rsa; - VALUE obj; - - GetPKeyRSA(self, pkey); - /* err check performed by rsa_instance */ - rsa = RSAPublicKey_dup(pkey->pkey.rsa); - obj = rsa_instance(CLASS_OF(self), rsa); - if (obj == Qfalse) { - RSA_free(rsa); - ossl_raise(eRSAError, NULL); - } - return obj; -} - +OSSL_PKEY_BN_DEF3(rsa, RSA, key, n, e, d) /* - * TODO: Test me - -static VALUE -ossl_rsa_blinding_on(VALUE self) -{ - EVP_PKEY *pkey; - - GetPKeyRSA(self, pkey); - - if (RSA_blinding_on(pkey->pkey.rsa, ossl_bn_ctx) != 1) { - ossl_raise(eRSAError, NULL); - } - return self; -} - -static VALUE -ossl_rsa_blinding_off(VALUE self) -{ - EVP_PKEY *pkey; - - GetPKeyRSA(self, pkey); - RSA_blinding_off(pkey->pkey.rsa); - - return self; -} + * Document-method: OpenSSL::PKey::RSA#set_factors + * call-seq: + * rsa.set_factors(p, q) -> self + * + * Sets _p_, _q_ for the RSA instance. */ - -OSSL_PKEY_BN(rsa, n) -OSSL_PKEY_BN(rsa, e) -OSSL_PKEY_BN(rsa, d) -OSSL_PKEY_BN(rsa, p) -OSSL_PKEY_BN(rsa, q) -OSSL_PKEY_BN(rsa, dmp1) -OSSL_PKEY_BN(rsa, dmq1) -OSSL_PKEY_BN(rsa, iqmp) +OSSL_PKEY_BN_DEF2(rsa, RSA, factors, p, q) +/* + * Document-method: OpenSSL::PKey::RSA#set_crt_params + * call-seq: + * rsa.set_crt_params(dmp1, dmq1, iqmp) -> self + * + * Sets _dmp1_, _dmq1_, _iqmp_ for the RSA instance. They are calculated by + * <tt>d mod (p - 1)</tt>, <tt>d mod (q - 1)</tt> and <tt>q^(-1) mod p</tt> + * respectively. + */ +OSSL_PKEY_BN_DEF3(rsa, RSA, crt_params, dmp1, dmq1, iqmp) /* * INIT */ -#define DefRSAConst(x) rb_define_const(cRSA, #x,INT2FIX(RSA_##x)) +#define DefRSAConst(x) rb_define_const(cRSA, #x, INT2NUM(RSA_##x)) void Init_ossl_rsa(void) { -#if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */ - mPKey = rb_define_module_under(mOSSL, "PKey"); -#endif - - /* Document-class: OpenSSL::PKey::RSAError - * - * Generic exception that is raised if an operation on an RSA PKey - * fails unexpectedly or in case an instantiation of an instance of RSA - * fails due to non-conformant input data. - */ - eRSAError = rb_define_class_under(mPKey, "RSAError", ePKeyError); - /* Document-class: OpenSSL::PKey::RSA * * RSA is an asymmetric public key algorithm that has been formalized in - * RFC 3447. It is in widespread use in public key infrastuctures (PKI) + * RFC 3447. It is in widespread use in public key infrastructures (PKI) * where certificates (cf. OpenSSL::X509::Certificate) often are issued * on the basis of a public/private RSA key pair. RSA is used in a wide * field of applications such as secure (symmetric) key exchange, e.g. @@ -653,21 +548,19 @@ Init_ossl_rsa(void) */ cRSA = rb_define_class_under(mPKey, "RSA", cPKey); - rb_define_singleton_method(cRSA, "generate", ossl_rsa_s_generate, -1); rb_define_method(cRSA, "initialize", ossl_rsa_initialize, -1); +#ifndef HAVE_EVP_PKEY_DUP + rb_define_method(cRSA, "initialize_copy", ossl_rsa_initialize_copy, 1); +#endif rb_define_method(cRSA, "public?", ossl_rsa_is_public, 0); rb_define_method(cRSA, "private?", ossl_rsa_is_private, 0); - rb_define_method(cRSA, "to_text", ossl_rsa_to_text, 0); rb_define_method(cRSA, "export", ossl_rsa_export, -1); rb_define_alias(cRSA, "to_pem", "export"); rb_define_alias(cRSA, "to_s", "export"); rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0); - rb_define_method(cRSA, "public_key", ossl_rsa_to_public_key, 0); - rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, -1); - rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1); - rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1); - rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, -1); + rb_define_method(cRSA, "sign_pss", ossl_rsa_sign_pss, -1); + rb_define_method(cRSA, "verify_pss", ossl_rsa_verify_pss, -1); DEF_OSSL_PKEY_BN(cRSA, rsa, n); DEF_OSSL_PKEY_BN(cRSA, rsa, e); @@ -677,13 +570,9 @@ Init_ossl_rsa(void) DEF_OSSL_PKEY_BN(cRSA, rsa, dmp1); DEF_OSSL_PKEY_BN(cRSA, rsa, dmq1); DEF_OSSL_PKEY_BN(cRSA, rsa, iqmp); - - rb_define_method(cRSA, "params", ossl_rsa_get_params, 0); - - DefRSAConst(PKCS1_PADDING); - DefRSAConst(SSLV23_PADDING); - DefRSAConst(NO_PADDING); - DefRSAConst(PKCS1_OAEP_PADDING); + rb_define_method(cRSA, "set_key", ossl_rsa_set_key, 3); + rb_define_method(cRSA, "set_factors", ossl_rsa_set_factors, 2); + rb_define_method(cRSA, "set_crt_params", ossl_rsa_set_crt_params, 3); /* * TODO: Test it @@ -698,4 +587,3 @@ Init_ossl_rsa(void) { } #endif /* NO_RSA */ - diff --git a/ext/openssl/ossl_provider.c b/ext/openssl/ossl_provider.c new file mode 100644 index 0000000000..ea5abb8e48 --- /dev/null +++ b/ext/openssl/ossl_provider.c @@ -0,0 +1,204 @@ +/* + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) + */ +#include "ossl.h" + +#ifdef OSSL_USE_PROVIDER +#define NewProvider(klass) \ + TypedData_Wrap_Struct((klass), &ossl_provider_type, 0) +#define SetProvider(obj, provider) do { \ + if (!(provider)) { \ + ossl_raise(rb_eRuntimeError, "Provider wasn't initialized."); \ + } \ + RTYPEDDATA_DATA(obj) = (provider); \ +} while(0) +#define GetProvider(obj, provider) do { \ + TypedData_Get_Struct((obj), OSSL_PROVIDER, &ossl_provider_type, (provider)); \ + if (!(provider)) { \ + ossl_raise(rb_eRuntimeError, "PROVIDER wasn't initialized."); \ + } \ +} while (0) + +static const rb_data_type_t ossl_provider_type = { + "OpenSSL/Provider", + { + 0, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, +}; + +/* + * Classes + */ +/* Document-class: OpenSSL::Provider + * + * This class is the access to openssl's Provider + * See also, https://www.openssl.org/docs/manmaster/man7/provider.html + */ +static VALUE cProvider; +/* Document-class: OpenSSL::Provider::ProviderError + * + * This is the generic exception for OpenSSL::Provider related errors + */ +static VALUE eProviderError; + +/* + * call-seq: + * OpenSSL::Provider.load(name) -> provider + * + * This method loads and initializes a provider + */ +static VALUE +ossl_provider_s_load(VALUE klass, VALUE name) +{ + OSSL_PROVIDER *provider = NULL; + VALUE obj; + + const char *provider_name_ptr = StringValueCStr(name); + + provider = OSSL_PROVIDER_load(NULL, provider_name_ptr); + if (provider == NULL) { + ossl_raise(eProviderError, "Failed to load %s provider", provider_name_ptr); + } + obj = NewProvider(klass); + SetProvider(obj, provider); + + return obj; +} + +struct ary_with_state { VALUE ary; int state; }; +struct rb_push_provider_name_args { OSSL_PROVIDER *prov; VALUE ary; }; + +static VALUE +rb_push_provider_name(VALUE rb_push_provider_name_args) +{ + struct rb_push_provider_name_args *args = (struct rb_push_provider_name_args *)rb_push_provider_name_args; + + VALUE name = rb_str_new2(OSSL_PROVIDER_get0_name(args->prov)); + return rb_ary_push(args->ary, name); +} + +static int +push_provider(OSSL_PROVIDER *prov, void *cbdata) +{ + struct ary_with_state *ary_with_state = (struct ary_with_state *)cbdata; + struct rb_push_provider_name_args args = { prov, ary_with_state->ary }; + + rb_protect(rb_push_provider_name, (VALUE)&args, &ary_with_state->state); + if (ary_with_state->state) { + return 0; + } else { + return 1; + } +} + +/* + * call-seq: + * OpenSSL::Provider.provider_names -> [provider_name, ...] + * + * Returns an array of currently loaded provider names. + */ +static VALUE +ossl_provider_s_provider_names(VALUE klass) +{ + VALUE ary = rb_ary_new(); + struct ary_with_state cbdata = { ary, 0 }; + + int result = OSSL_PROVIDER_do_all(NULL, &push_provider, (void*)&cbdata); + if (result != 1 ) { + if (cbdata.state) { + rb_jump_tag(cbdata.state); + } else { + ossl_raise(eProviderError, "Failed to load provider names"); + } + } + + return ary; +} + +/* + * call-seq: + * provider.unload -> true + * + * This method unloads this provider. + * + * if provider unload fails or already unloaded, it raises OpenSSL::Provider::ProviderError + */ +static VALUE +ossl_provider_unload(VALUE self) +{ + OSSL_PROVIDER *prov; + if (RTYPEDDATA_DATA(self) == NULL) { + ossl_raise(eProviderError, "Provider already unloaded."); + } + GetProvider(self, prov); + + int result = OSSL_PROVIDER_unload(prov); + + if (result != 1) { + ossl_raise(eProviderError, "Failed to unload provider"); + } + RTYPEDDATA_DATA(self) = NULL; + return Qtrue; +} + +/* + * call-seq: + * provider.name -> string + * + * Get the name of this provider. + * + * if this provider is already unloaded, it raises OpenSSL::Provider::ProviderError + */ +static VALUE +ossl_provider_get_name(VALUE self) +{ + OSSL_PROVIDER *prov; + if (RTYPEDDATA_DATA(self) == NULL) { + ossl_raise(eProviderError, "Provider already unloaded."); + } + GetProvider(self, prov); + + return rb_str_new2(OSSL_PROVIDER_get0_name(prov)); +} + +/* + * call-seq: + * provider.inspect -> string + * + * Pretty prints this provider. + */ +static VALUE +ossl_provider_inspect(VALUE self) +{ + OSSL_PROVIDER *prov; + if (RTYPEDDATA_DATA(self) == NULL ) { + return rb_sprintf("#<%"PRIsVALUE" unloaded provider>", rb_obj_class(self)); + } + GetProvider(self, prov); + + return rb_sprintf("#<%"PRIsVALUE" name=\"%s\">", + rb_obj_class(self), OSSL_PROVIDER_get0_name(prov)); +} + +void +Init_ossl_provider(void) +{ + cProvider = rb_define_class_under(mOSSL, "Provider", rb_cObject); + eProviderError = rb_define_class_under(cProvider, "ProviderError", eOSSLError); + + rb_undef_alloc_func(cProvider); + rb_define_singleton_method(cProvider, "load", ossl_provider_s_load, 1); + rb_define_singleton_method(cProvider, "provider_names", ossl_provider_s_provider_names, 0); + + rb_define_method(cProvider, "unload", ossl_provider_unload, 0); + rb_define_method(cProvider, "name", ossl_provider_get_name, 0); + rb_define_method(cProvider, "inspect", ossl_provider_inspect, 0); +} +#else +void +Init_ossl_provider(void) +{ +} +#endif diff --git a/ext/openssl/ossl_provider.h b/ext/openssl/ossl_provider.h new file mode 100644 index 0000000000..1d69cb1e44 --- /dev/null +++ b/ext/openssl/ossl_provider.h @@ -0,0 +1,5 @@ +#if !defined(OSSL_PROVIDER_H) +#define OSSL_PROVIDER_H + +void Init_ossl_provider(void); +#endif diff --git a/ext/openssl/ossl_rand.c b/ext/openssl/ossl_rand.c index 29cbf8c3f5..753f8b25f7 100644 --- a/ext/openssl/ossl_rand.c +++ b/ext/openssl/ossl_rand.c @@ -1,23 +1,22 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * * All rights reserved. * - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -VALUE mRandom; -VALUE eRandomError; +static VALUE mRandom; +static VALUE eRandomError; /* * call-seq: * seed(str) -> str * - * ::seed is equivalent to ::add where +entropy+ is length of +str+. + * ::seed is equivalent to ::add where _entropy_ is length of _str_. */ static VALUE ossl_rand_seed(VALUE self, VALUE str) @@ -32,23 +31,23 @@ ossl_rand_seed(VALUE self, VALUE str) * call-seq: * add(str, entropy) -> self * - * Mixes the bytes from +str+ into the Pseudo Random Number Generator(PRNG) + * Mixes the bytes from _str_ into the Pseudo Random Number Generator(PRNG) * state. * - * Thus, if the data from +str+ are unpredictable to an adversary, this + * Thus, if the data from _str_ are unpredictable to an adversary, this * increases the uncertainty about the state and makes the PRNG output less * predictable. * - * The +entropy+ argument is (the lower bound of) an estimate of how much - * randomness is contained in +str+, measured in bytes. + * The _entropy_ argument is (the lower bound of) an estimate of how much + * randomness is contained in _str_, measured in bytes. * - * Example: + * === Example * * pid = $$ * now = Time.now * ary = [now.to_i, now.nsec, 1000, pid] - * OpenSSL::Random.add(ary.join("").to_s, 0.0) - * OpenSSL::Random.seed(ary.join("").to_s) + * OpenSSL::Random.add(ary.join, 0.0) + * OpenSSL::Random.seed(ary.join) */ static VALUE ossl_rand_add(VALUE self, VALUE str, VALUE entropy) @@ -63,15 +62,13 @@ ossl_rand_add(VALUE self, VALUE str, VALUE entropy) * call-seq: * load_random_file(filename) -> true * - * Reads bytes from +filename+ and adds them to the PRNG. + * Reads bytes from _filename_ and adds them to the PRNG. */ static VALUE ossl_rand_load_file(VALUE self, VALUE filename) { - SafeStringValue(filename); - - if(!RAND_load_file(RSTRING_PTR(filename), -1)) { - ossl_raise(eRandomError, NULL); + if(!RAND_load_file(StringValueCStr(filename), -1)) { + ossl_raise(eRandomError, NULL); } return Qtrue; } @@ -80,74 +77,50 @@ ossl_rand_load_file(VALUE self, VALUE filename) * call-seq: * write_random_file(filename) -> true * - * Writes a number of random generated bytes (currently 1024) to +filename+ + * Writes a number of random generated bytes (currently 1024) to _filename_ * which can be used to initialize the PRNG by calling ::load_random_file in a * later session. */ static VALUE ossl_rand_write_file(VALUE self, VALUE filename) { - SafeStringValue(filename); - if (RAND_write_file(RSTRING_PTR(filename)) == -1) { - ossl_raise(eRandomError, NULL); + if (RAND_write_file(StringValueCStr(filename)) == -1) { + ossl_raise(eRandomError, NULL); } return Qtrue; } /* * call-seq: - * random_bytes(length) -> string + * random_bytes(length) -> string * - * Generates +string+ with +length+ number of cryptographically strong + * Generates a String with _length_ number of cryptographically strong * pseudo-random bytes. * - * Example: + * === Example * * OpenSSL::Random.random_bytes(12) - * => "..." + * #=> "..." */ static VALUE ossl_rand_bytes(VALUE self, VALUE len) { VALUE str; int n = NUM2INT(len); + int ret; str = rb_str_new(0, n); - if (!RAND_bytes((unsigned char *)RSTRING_PTR(str), n)) { - ossl_raise(eRandomError, NULL); - } - - return str; -} - -/* - * call-seq: - * pseudo_bytes(length) -> string - * - * Generates +string+ with +length+ number of pseudo-random bytes. - * - * Pseudo-random byte sequences generated by ::pseudo_bytes will be unique if - * they are of sufficient length, but are not necessarily unpredictable. - * - * Example: - * - * OpenSSL::Random.pseudo_bytes(12) - * => "..." - */ -static VALUE -ossl_rand_pseudo_bytes(VALUE self, VALUE len) -{ - VALUE str; - int n = NUM2INT(len); - - str = rb_str_new(0, n); - if (!RAND_pseudo_bytes((unsigned char *)RSTRING_PTR(str), n)) { - ossl_raise(eRandomError, NULL); + ret = RAND_bytes((unsigned char *)RSTRING_PTR(str), n); + if (ret == 0) { + ossl_raise(eRandomError, "RAND_bytes"); + } else if (ret == -1) { + ossl_raise(eRandomError, "RAND_bytes is not supported"); } return str; } +#ifdef HAVE_RAND_EGD /* * call-seq: * egd(filename) -> true @@ -157,10 +130,8 @@ ossl_rand_pseudo_bytes(VALUE self, VALUE len) static VALUE ossl_rand_egd(VALUE self, VALUE filename) { - SafeStringValue(filename); - - if(!RAND_egd(RSTRING_PTR(filename))) { - ossl_raise(eRandomError, NULL); + if (RAND_egd(StringValueCStr(filename)) == -1) { + ossl_raise(eRandomError, NULL); } return Qtrue; } @@ -169,9 +140,9 @@ ossl_rand_egd(VALUE self, VALUE filename) * call-seq: * egd_bytes(filename, length) -> true * - * Queries the entropy gathering daemon EGD on socket path given by +filename+. + * Queries the entropy gathering daemon EGD on socket path given by _filename_. * - * Fetches +length+ number of bytes and uses ::add to seed the OpenSSL built-in + * Fetches _length_ number of bytes and uses ::add to seed the OpenSSL built-in * PRNG. */ static VALUE @@ -179,19 +150,18 @@ ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len) { int n = NUM2INT(len); - SafeStringValue(filename); - - if (!RAND_egd_bytes(RSTRING_PTR(filename), n)) { - ossl_raise(eRandomError, NULL); + if (RAND_egd_bytes(StringValueCStr(filename), n) == -1) { + ossl_raise(eRandomError, NULL); } return Qtrue; } +#endif /* HAVE_RAND_EGD */ /* * call-seq: * status? => true | false * - * Return true if the PRNG has been seeded with enough data, false otherwise. + * Return +true+ if the PRNG has been seeded with enough data, +false+ otherwise. */ static VALUE ossl_rand_status(VALUE self) @@ -205,10 +175,6 @@ ossl_rand_status(VALUE self) void Init_ossl_rand(void) { -#if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ -#endif - mRandom = rb_define_module_under(mOSSL, "Random"); eRandomError = rb_define_class_under(mRandom, "RandomError", eOSSLError); @@ -218,9 +184,10 @@ Init_ossl_rand(void) rb_define_module_function(mRandom, "load_random_file", ossl_rand_load_file, 1); rb_define_module_function(mRandom, "write_random_file", ossl_rand_write_file, 1); rb_define_module_function(mRandom, "random_bytes", ossl_rand_bytes, 1); - rb_define_module_function(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1); + rb_define_alias(rb_singleton_class(mRandom), "pseudo_bytes", "random_bytes"); +#ifdef HAVE_RAND_EGD rb_define_module_function(mRandom, "egd", ossl_rand_egd, 1); rb_define_module_function(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2); +#endif /* HAVE_RAND_EGD */ rb_define_module_function(mRandom, "status?", ossl_rand_status, 0); } - diff --git a/ext/openssl/ossl_rand.h b/ext/openssl/ossl_rand.h index ce2ae0d129..294986d017 100644 --- a/ext/openssl/ossl_rand.h +++ b/ext/openssl/ossl_rand.h @@ -1,20 +1,15 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(_OSSL_RAND_H_) #define _OSSL_RAND_H_ -extern VALUE mRandom; -extern VALUE eRandomError; - void Init_ossl_rand(void); #endif /* _OSSL_RAND_H_ */ - diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index af93252e96..630d46e43f 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1,5 +1,4 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2000-2002 GOTOU Yuuzou <gotoyuzo@notwork.org> * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> @@ -7,17 +6,18 @@ * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#if defined(HAVE_UNISTD_H) -# include <unistd.h> /* for read(), and write() */ -#endif - +#ifndef OPENSSL_NO_SOCK #define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0])) +#if !defined(OPENSSL_NO_NEXTPROTONEG) && !OSSL_IS_LIBRESSL +# define OSSL_USE_NEXTPROTONEG +#endif + #ifdef _WIN32 # define TO_SOCKET(s) _get_osfhandle(s) #else @@ -25,361 +25,233 @@ #endif #define GetSSLCTX(obj, ctx) do { \ - TypedData_Get_Struct((obj), SSL_CTX, &ossl_sslctx_type, (ctx)); \ + TypedData_Get_Struct((obj), SSL_CTX, &ossl_sslctx_type, (ctx)); \ } while (0) VALUE mSSL; -VALUE eSSLError; -VALUE cSSLContext; +static VALUE eSSLError; +static VALUE cSSLContext; VALUE cSSLSocket; static VALUE eSSLErrorWaitReadable; static VALUE eSSLErrorWaitWritable; -#define ossl_sslctx_set_cert(o,v) rb_iv_set((o),"@cert",(v)) -#define ossl_sslctx_set_key(o,v) rb_iv_set((o),"@key",(v)) -#define ossl_sslctx_set_client_ca(o,v) rb_iv_set((o),"@client_ca",(v)) -#define ossl_sslctx_set_ca_file(o,v) rb_iv_set((o),"@ca_file",(v)) -#define ossl_sslctx_set_ca_path(o,v) rb_iv_set((o),"@ca_path",(v)) -#define ossl_sslctx_set_timeout(o,v) rb_iv_set((o),"@timeout",(v)) -#define ossl_sslctx_set_verify_mode(o,v) rb_iv_set((o),"@verify_mode",(v)) -#define ossl_sslctx_set_verify_dep(o,v) rb_iv_set((o),"@verify_depth",(v)) -#define ossl_sslctx_set_verify_cb(o,v) rb_iv_set((o),"@verify_callback",(v)) -#define ossl_sslctx_set_options(o,v) rb_iv_set((o),"@options",(v)) -#define ossl_sslctx_set_cert_store(o,v) rb_iv_set((o),"@cert_store",(v)) -#define ossl_sslctx_set_extra_cert(o,v) rb_iv_set((o),"@extra_chain_cert",(v)) -#define ossl_sslctx_set_client_cert_cb(o,v) rb_iv_set((o),"@client_cert_cb",(v)) -#define ossl_sslctx_set_tmp_dh_cb(o,v) rb_iv_set((o),"@tmp_dh_callback",(v)) -#define ossl_sslctx_set_sess_id_ctx(o, v) rb_iv_set((o),"@session_id_context",(v)) - -#define ossl_sslctx_get_cert(o) rb_iv_get((o),"@cert") -#define ossl_sslctx_get_key(o) rb_iv_get((o),"@key") -#define ossl_sslctx_get_client_ca(o) rb_iv_get((o),"@client_ca") -#define ossl_sslctx_get_ca_file(o) rb_iv_get((o),"@ca_file") -#define ossl_sslctx_get_ca_path(o) rb_iv_get((o),"@ca_path") -#define ossl_sslctx_get_timeout(o) rb_iv_get((o),"@timeout") -#define ossl_sslctx_get_verify_mode(o) rb_iv_get((o),"@verify_mode") -#define ossl_sslctx_get_verify_dep(o) rb_iv_get((o),"@verify_depth") -#define ossl_sslctx_get_verify_cb(o) rb_iv_get((o),"@verify_callback") -#define ossl_sslctx_get_options(o) rb_iv_get((o),"@options") -#define ossl_sslctx_get_cert_store(o) rb_iv_get((o),"@cert_store") -#define ossl_sslctx_get_extra_cert(o) rb_iv_get((o),"@extra_chain_cert") -#define ossl_sslctx_get_client_cert_cb(o) rb_iv_get((o),"@client_cert_cb") -#define ossl_sslctx_get_tmp_dh_cb(o) rb_iv_get((o),"@tmp_dh_callback") -#define ossl_sslctx_get_sess_id_ctx(o) rb_iv_get((o),"@session_id_context") - -static const char *ossl_sslctx_attrs[] = { - "cert", "key", "client_ca", "ca_file", "ca_path", - "timeout", "verify_mode", "verify_depth", "renegotiation_cb", - "verify_callback", "options", "cert_store", "extra_chain_cert", - "client_cert_cb", "tmp_dh_callback", "session_id_context", - "session_get_cb", "session_new_cb", "session_remove_cb", -#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME - "servername_cb", -#endif -#ifdef HAVE_OPENSSL_NPN_NEGOTIATED - "npn_protocols", - "npn_select_cb", -#endif -}; - -#define ossl_ssl_get_io(o) rb_iv_get((o),"@io") -#define ossl_ssl_get_ctx(o) rb_iv_get((o),"@context") -#define ossl_ssl_get_sync_close(o) rb_iv_get((o),"@sync_close") -#define ossl_ssl_get_x509(o) rb_iv_get((o),"@x509") -#define ossl_ssl_get_key(o) rb_iv_get((o),"@key") -#define ossl_ssl_get_tmp_dh(o) rb_iv_get((o),"@tmp_dh") - -#define ossl_ssl_set_io(o,v) rb_iv_set((o),"@io",(v)) -#define ossl_ssl_set_ctx(o,v) rb_iv_set((o),"@context",(v)) -#define ossl_ssl_set_sync_close(o,v) rb_iv_set((o),"@sync_close",(v)) -#define ossl_ssl_set_x509(o,v) rb_iv_set((o),"@x509",(v)) -#define ossl_ssl_set_key(o,v) rb_iv_set((o),"@key",(v)) -#define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v)) - -static const char *ossl_ssl_attr_readers[] = { "io", "context", }; -static const char *ossl_ssl_attrs[] = { -#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME - "hostname", -#endif - "sync_close", -}; +static ID id_call, ID_callback_state, id_npn_protocols_encoded, id_each; +static VALUE sym_exception, sym_wait_readable, sym_wait_writable; -ID ID_callback_state; +static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode, + id_i_verify_depth, id_i_verify_callback, id_i_client_ca, + id_i_renegotiation_cb, id_i_cert, id_i_key, id_i_extra_chain_cert, + id_i_client_cert_cb, id_i_timeout, + id_i_session_id_context, id_i_session_get_cb, id_i_session_new_cb, + id_i_session_remove_cb, id_i_npn_select_cb, id_i_npn_protocols, + id_i_alpn_select_cb, id_i_alpn_protocols, id_i_servername_cb, + id_i_verify_hostname, id_i_keylog_cb, id_i_tmp_dh_callback; +static ID id_i_io, id_i_context, id_i_hostname; -static VALUE sym_exception; +static int ossl_ssl_ex_ptr_idx; +static int ossl_sslctx_ex_ptr_idx; -/* - * SSLContext class - */ -static const struct { - const char *name; - SSL_METHOD *(*func)(void); -} ossl_ssl_method_tab[] = { -#define OSSL_SSL_METHOD_ENTRY(name) { #name, (SSL_METHOD *(*)(void))name##_method } - OSSL_SSL_METHOD_ENTRY(TLSv1), - OSSL_SSL_METHOD_ENTRY(TLSv1_server), - OSSL_SSL_METHOD_ENTRY(TLSv1_client), -#if defined(HAVE_TLSV1_2_METHOD) && defined(HAVE_TLSV1_2_SERVER_METHOD) && \ - defined(HAVE_TLSV1_2_CLIENT_METHOD) - OSSL_SSL_METHOD_ENTRY(TLSv1_2), - OSSL_SSL_METHOD_ENTRY(TLSv1_2_server), - OSSL_SSL_METHOD_ENTRY(TLSv1_2_client), -#endif -#if defined(HAVE_TLSV1_1_METHOD) && defined(HAVE_TLSV1_1_SERVER_METHOD) && \ - defined(HAVE_TLSV1_1_CLIENT_METHOD) - OSSL_SSL_METHOD_ENTRY(TLSv1_1), - OSSL_SSL_METHOD_ENTRY(TLSv1_1_server), - OSSL_SSL_METHOD_ENTRY(TLSv1_1_client), -#endif -#if defined(HAVE_SSLV2_METHOD) && defined(HAVE_SSLV2_SERVER_METHOD) && \ - defined(HAVE_SSLV2_CLIENT_METHOD) - OSSL_SSL_METHOD_ENTRY(SSLv2), - OSSL_SSL_METHOD_ENTRY(SSLv2_server), - OSSL_SSL_METHOD_ENTRY(SSLv2_client), -#endif - OSSL_SSL_METHOD_ENTRY(SSLv3), - OSSL_SSL_METHOD_ENTRY(SSLv3_server), - OSSL_SSL_METHOD_ENTRY(SSLv3_client), - OSSL_SSL_METHOD_ENTRY(SSLv23), - OSSL_SSL_METHOD_ENTRY(SSLv23_server), - OSSL_SSL_METHOD_ENTRY(SSLv23_client), -#undef OSSL_SSL_METHOD_ENTRY -}; - -int ossl_ssl_ex_vcb_idx; -int ossl_ssl_ex_store_p; -int ossl_ssl_ex_ptr_idx; -int ossl_ssl_ex_client_cert_cb_idx; -int ossl_ssl_ex_tmp_dh_callback_idx; +static void +ossl_sslctx_mark(void *ptr) +{ + SSL_CTX *ctx = ptr; + rb_gc_mark((VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx)); +} static void ossl_sslctx_free(void *ptr) { - SSL_CTX *ctx = ptr; - if(ctx && SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_store_p)== (void*)1) - ctx->cert_store = NULL; - SSL_CTX_free(ctx); + SSL_CTX_free(ptr); } static const rb_data_type_t ossl_sslctx_type = { "OpenSSL/SSL/CTX", { - 0, ossl_sslctx_free, + ossl_sslctx_mark, ossl_sslctx_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; static VALUE ossl_sslctx_s_alloc(VALUE klass) { SSL_CTX *ctx; - long mode = SSL_MODE_ENABLE_PARTIAL_WRITE; - -#ifdef SSL_MODE_RELEASE_BUFFERS - mode |= SSL_MODE_RELEASE_BUFFERS; -#endif + long mode = 0 | + SSL_MODE_ENABLE_PARTIAL_WRITE | + SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | + SSL_MODE_RELEASE_BUFFERS; + VALUE obj; - ctx = SSL_CTX_new(SSLv23_method()); + obj = TypedData_Wrap_Struct(klass, &ossl_sslctx_type, 0); + ctx = SSL_CTX_new(TLS_method()); if (!ctx) { ossl_raise(eSSLError, "SSL_CTX_new"); } SSL_CTX_set_mode(ctx, mode); - return TypedData_Wrap_Struct(klass, &ossl_sslctx_type, ctx); -} - -/* - * call-seq: - * ctx.ssl_version = :TLSv1 - * ctx.ssl_version = "SSLv23_client" - * - * You can get a list of valid versions with OpenSSL::SSL::SSLContext::METHODS - */ -static VALUE -ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method) -{ - SSL_METHOD *method = NULL; - const char *s; - int i; + SSL_CTX_set_dh_auto(ctx, 1); + RTYPEDDATA_DATA(obj) = ctx; + SSL_CTX_set_ex_data(ctx, ossl_sslctx_ex_ptr_idx, (void *)obj); - SSL_CTX *ctx; - if (RB_TYPE_P(ssl_method, T_SYMBOL)) - s = rb_id2name(SYM2ID(ssl_method)); - else - s = StringValuePtr(ssl_method); - for (i = 0; i < numberof(ossl_ssl_method_tab); i++) { - if (strcmp(ossl_ssl_method_tab[i].name, s) == 0) { - method = ossl_ssl_method_tab[i].func(); - break; - } - } - if (!method) { - ossl_raise(rb_eArgError, "unknown SSL method `%s'.", s); - } - GetSSLCTX(self, ctx); - if (SSL_CTX_set_ssl_version(ctx, method) != 1) { - ossl_raise(eSSLError, "SSL_CTX_set_ssl_version"); - } - - return ssl_method; -} - -/* - * call-seq: - * SSLContext.new => ctx - * SSLContext.new(:TLSv1) => ctx - * SSLContext.new("SSLv23_client") => ctx - * - * You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS - */ -static VALUE -ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self) -{ - VALUE ssl_method; - int i; - - for(i = 0; i < numberof(ossl_sslctx_attrs); i++){ - char buf[32]; - snprintf(buf, sizeof(buf), "@%s", ossl_sslctx_attrs[i]); - rb_iv_set(self, buf, Qnil); - } - if (rb_scan_args(argc, argv, "01", &ssl_method) == 0){ - return self; - } - ossl_sslctx_set_ssl_version(self, ssl_method); - - return self; + return obj; } static VALUE ossl_call_client_cert_cb(VALUE obj) { - VALUE cb, ary, cert, key; - SSL *ssl; + VALUE ctx_obj, cb, ary, cert, key; - GetSSL(obj, ssl); - cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx); - if (NIL_P(cb)) return Qfalse; - ary = rb_funcall(cb, rb_intern("call"), 1, obj); + ctx_obj = rb_attr_get(obj, id_i_context); + cb = rb_attr_get(ctx_obj, id_i_client_cert_cb); + if (NIL_P(cb)) + return Qnil; + + ary = rb_funcallv(cb, id_call, 1, &obj); Check_Type(ary, T_ARRAY); GetX509CertPtr(cert = rb_ary_entry(ary, 0)); - GetPKeyPtr(key = rb_ary_entry(ary, 1)); - ossl_ssl_set_x509(obj, cert); - ossl_ssl_set_key(obj, key); + GetPrivPKeyPtr(key = rb_ary_entry(ary, 1)); - return Qtrue; + return rb_ary_new3(2, cert, key); } static int ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) { - VALUE obj, success; + VALUE obj, ret; obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); - success = rb_protect((VALUE(*)_((VALUE)))ossl_call_client_cert_cb, - obj, NULL); - if (!RTEST(success)) return 0; - *x509 = DupX509CertPtr(ossl_ssl_get_x509(obj)); - *pkey = DupPKeyPtr(ossl_ssl_get_key(obj)); + ret = rb_protect(ossl_call_client_cert_cb, obj, NULL); + if (NIL_P(ret)) + return 0; + + *x509 = DupX509CertPtr(RARRAY_AREF(ret, 0)); + *pkey = DupPKeyPtr(RARRAY_AREF(ret, 1)); return 1; } #if !defined(OPENSSL_NO_DH) +struct tmp_dh_callback_args { + VALUE ssl_obj; + int is_export; + int keylength; +}; + static VALUE -ossl_call_tmp_dh_callback(VALUE *args) +ossl_call_tmp_dh_callback(VALUE arg) { - SSL *ssl; - VALUE cb, dh; - EVP_PKEY *pkey; + struct tmp_dh_callback_args *args = (struct tmp_dh_callback_args *)arg; + VALUE ctx_obj, cb, obj; + const DH *dh; - GetSSL(args[0], ssl); - cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx); - if (NIL_P(cb)) return Qfalse; - dh = rb_funcall(cb, rb_intern("call"), 3, args[0], args[1], args[2]); - pkey = GetPKeyPtr(dh); - if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) return Qfalse; - ossl_ssl_set_tmp_dh(args[0], dh); + ctx_obj = rb_attr_get(args->ssl_obj, id_i_context); + cb = rb_attr_get(ctx_obj, id_i_tmp_dh_callback); + if (NIL_P(cb)) + return (VALUE)NULL; - return Qtrue; + obj = rb_funcall(cb, id_call, 3, args->ssl_obj, INT2NUM(args->is_export), + INT2NUM(args->keylength)); + // TODO: We should riase if obj is not DH + dh = EVP_PKEY_get0_DH(GetPKeyPtr(obj)); + if (!dh) + ossl_clear_error(); + + return (VALUE)dh; } -static DH* +static DH * ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength) { - VALUE args[3], success; - - args[0] = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); - args[1] = INT2FIX(is_export); - args[2] = INT2FIX(keylength); - success = rb_protect((VALUE(*)_((VALUE)))ossl_call_tmp_dh_callback, - (VALUE)args, NULL); - if (!RTEST(success)) return NULL; - - return GetPKeyPtr(ossl_ssl_get_tmp_dh(args[0]))->pkey.dh; + int state; + VALUE rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); + struct tmp_dh_callback_args args = {rb_ssl, is_export, keylength}; + VALUE ret = rb_protect(ossl_call_tmp_dh_callback, (VALUE)&args, &state); + if (state) { + rb_ivar_set(rb_ssl, ID_callback_state, INT2NUM(state)); + return NULL; + } + return (DH *)ret; } +#endif /* OPENSSL_NO_DH */ -static DH* -ossl_default_tmp_dh_callback(SSL *ssl, int is_export, int keylength) +static VALUE +call_verify_certificate_identity(VALUE ctx_v) { - rb_warning("using default DH parameters."); + X509_STORE_CTX *ctx = (X509_STORE_CTX *)ctx_v; + SSL *ssl; + VALUE ssl_obj, hostname, cert_obj; + + ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); + ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); + hostname = rb_attr_get(ssl_obj, id_i_hostname); - switch(keylength){ - case 512: - return OSSL_DEFAULT_DH_512; - case 1024: - return OSSL_DEFAULT_DH_1024; + if (!RTEST(hostname)) { + rb_warning("verify_hostname requires hostname to be set"); + return Qtrue; } - return NULL; + + cert_obj = ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx)); + return rb_funcall(mSSL, rb_intern("verify_certificate_identity"), 2, + cert_obj, hostname); } -#endif /* OPENSSL_NO_DH */ static int ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) { - VALUE cb; + VALUE cb, ssl_obj, sslctx_obj, verify_hostname, ret; SSL *ssl; + int status; ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); - cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx); - X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx, (void*)cb); - return ossl_verify_cb(preverify_ok, ctx); + ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); + sslctx_obj = rb_attr_get(ssl_obj, id_i_context); + cb = rb_attr_get(sslctx_obj, id_i_verify_callback); + verify_hostname = rb_attr_get(sslctx_obj, id_i_verify_hostname); + + if (preverify_ok && RTEST(verify_hostname) && !SSL_is_server(ssl) && + !X509_STORE_CTX_get_error_depth(ctx)) { + ret = rb_protect(call_verify_certificate_identity, (VALUE)ctx, &status); + if (status) { + rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status)); + return 0; + } + if (ret != Qtrue) { + preverify_ok = 0; + X509_STORE_CTX_set_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH); + } + } + + return ossl_verify_cb_call(cb, preverify_ok, ctx); } static VALUE ossl_call_session_get_cb(VALUE ary) { - VALUE ssl_obj, sslctx_obj, cb; + VALUE ssl_obj, cb; Check_Type(ary, T_ARRAY); ssl_obj = rb_ary_entry(ary, 0); - sslctx_obj = rb_iv_get(ssl_obj, "@context"); - if (NIL_P(sslctx_obj)) return Qnil; - cb = rb_iv_get(sslctx_obj, "@session_get_cb"); + cb = rb_funcall(ssl_obj, rb_intern("session_get_cb"), 0); if (NIL_P(cb)) return Qnil; - return rb_funcall(cb, rb_intern("call"), 1, ary); + return rb_funcallv(cb, id_call, 1, &ary); } -/* this method is currently only called for servers (in OpenSSL <= 0.9.8e) */ static SSL_SESSION * -ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy) +ossl_sslctx_session_get_cb(SSL *ssl, const unsigned char *buf, int len, int *copy) { VALUE ary, ssl_obj, ret_obj; SSL_SESSION *sess; - void *ptr; int state = 0; OSSL_Debug("SSL SESSION get callback entered"); - if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL) - return NULL; - ssl_obj = (VALUE)ptr; + ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); ary = rb_ary_new2(2); rb_ary_push(ary, ssl_obj); rb_ary_push(ary, rb_str_new((const char *)buf, len)); - ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_get_cb, ary, &state); + ret_obj = rb_protect(ossl_call_session_get_cb, ary, &state); if (state) { rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state)); return NULL; @@ -387,7 +259,7 @@ ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy) if (!rb_obj_is_instance_of(ret_obj, cSSLSession)) return NULL; - SafeGetSSLSession(ret_obj, sess); + GetSSLSession(ret_obj, sess); *copy = 1; return sess; @@ -396,17 +268,15 @@ ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy) static VALUE ossl_call_session_new_cb(VALUE ary) { - VALUE ssl_obj, sslctx_obj, cb; + VALUE ssl_obj, cb; Check_Type(ary, T_ARRAY); ssl_obj = rb_ary_entry(ary, 0); - sslctx_obj = rb_iv_get(ssl_obj, "@context"); - if (NIL_P(sslctx_obj)) return Qnil; - cb = rb_iv_get(sslctx_obj, "@session_new_cb"); + cb = rb_funcall(ssl_obj, rb_intern("session_new_cb"), 0); if (NIL_P(cb)) return Qnil; - return rb_funcall(cb, rb_intern("call"), 1, ary); + return rb_funcallv(cb, id_call, 1, &ary); } /* return 1 normal. return 0 removes the session */ @@ -414,23 +284,20 @@ static int ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess) { VALUE ary, ssl_obj, sess_obj; - void *ptr; int state = 0; OSSL_Debug("SSL SESSION new callback entered"); - if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL) - return 1; - ssl_obj = (VALUE)ptr; + ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); sess_obj = rb_obj_alloc(cSSLSession); - CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION); + SSL_SESSION_up_ref(sess); DATA_PTR(sess_obj) = sess; ary = rb_ary_new2(2); rb_ary_push(ary, ssl_obj); rb_ary_push(ary, sess_obj); - rb_protect((VALUE(*)_((VALUE)))ossl_call_session_new_cb, ary, &state); + rb_protect(ossl_call_session_new_cb, ary, &state); if (state) { rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state)); } @@ -445,6 +312,54 @@ ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess) return 0; } +#if !OSSL_IS_LIBRESSL +/* + * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements + * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see + * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6). + */ + +struct ossl_call_keylog_cb_args { + VALUE ssl_obj; + const char * line; +}; + +static VALUE +ossl_call_keylog_cb(VALUE args_v) +{ + VALUE sslctx_obj, cb, line_v; + struct ossl_call_keylog_cb_args *args = (struct ossl_call_keylog_cb_args *) args_v; + + sslctx_obj = rb_attr_get(args->ssl_obj, id_i_context); + + cb = rb_attr_get(sslctx_obj, id_i_keylog_cb); + if (NIL_P(cb)) return Qnil; + + line_v = rb_str_new_cstr(args->line); + + return rb_funcall(cb, id_call, 2, args->ssl_obj, line_v); +} + +static void +ossl_sslctx_keylog_cb(const SSL *ssl, const char *line) +{ + VALUE ssl_obj; + struct ossl_call_keylog_cb_args args; + int state = 0; + + OSSL_Debug("SSL keylog callback entered"); + + ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); + args.ssl_obj = ssl_obj; + args.line = line; + + rb_protect(ossl_call_keylog_cb, (VALUE)&args, &state); + if (state) { + rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state)); + } +} +#endif + static VALUE ossl_call_session_remove_cb(VALUE ary) { @@ -453,33 +368,37 @@ ossl_call_session_remove_cb(VALUE ary) Check_Type(ary, T_ARRAY); sslctx_obj = rb_ary_entry(ary, 0); - cb = rb_iv_get(sslctx_obj, "@session_remove_cb"); + cb = rb_attr_get(sslctx_obj, id_i_session_remove_cb); if (NIL_P(cb)) return Qnil; - return rb_funcall(cb, rb_intern("call"), 1, ary); + return rb_funcallv(cb, id_call, 1, &ary); } static void ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess) { VALUE ary, sslctx_obj, sess_obj; - void *ptr; int state = 0; + /* + * This callback is also called for all sessions in the internal store + * when SSL_CTX_free() is called. + */ + if (rb_during_gc()) + return; + OSSL_Debug("SSL SESSION remove callback entered"); - if ((ptr = SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_ptr_idx)) == NULL) - return; - sslctx_obj = (VALUE)ptr; + sslctx_obj = (VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx); sess_obj = rb_obj_alloc(cSSLSession); - CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION); + SSL_SESSION_up_ref(sess); DATA_PTR(sess_obj) = sess; ary = rb_ary_new2(2); rb_ary_push(ary, sslctx_obj); rb_ary_push(ary, sess_obj); - rb_protect((VALUE(*)_((VALUE)))ossl_call_session_remove_cb, ary, &state); + rb_protect(ossl_call_session_remove_cb, ary, &state); if (state) { /* the SSL_CTX is frozen, nowhere to save state. @@ -497,8 +416,9 @@ ossl_sslctx_add_extra_chain_cert_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg)) GetSSLCTX(arg, ctx); x509 = DupX509CertPtr(i); - if(!SSL_CTX_add_extra_chain_cert(ctx, x509)){ - ossl_raise(eSSLError, NULL); + if (!SSL_CTX_add_extra_chain_cert(ctx, x509)) { + X509_free(x509); + ossl_raise(eSSLError, "SSL_CTX_add_extra_chain_cert"); } return i; @@ -506,90 +426,70 @@ ossl_sslctx_add_extra_chain_cert_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg)) static VALUE ossl_sslctx_setup(VALUE self); -#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME static VALUE -ossl_call_servername_cb(VALUE ary) +ossl_call_servername_cb(VALUE arg) { - VALUE ssl_obj, sslctx_obj, cb, ret_obj; - - Check_Type(ary, T_ARRAY); - ssl_obj = rb_ary_entry(ary, 0); + SSL *ssl = (void *)arg; + const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + if (!servername) + return Qnil; - sslctx_obj = rb_iv_get(ssl_obj, "@context"); - if (NIL_P(sslctx_obj)) return Qnil; - cb = rb_iv_get(sslctx_obj, "@servername_cb"); - if (NIL_P(cb)) return Qnil; + VALUE ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); + VALUE sslctx_obj = rb_attr_get(ssl_obj, id_i_context); + VALUE cb = rb_attr_get(sslctx_obj, id_i_servername_cb); + VALUE ary = rb_assoc_new(ssl_obj, rb_str_new_cstr(servername)); - ret_obj = rb_funcall(cb, rb_intern("call"), 1, ary); + VALUE ret_obj = rb_funcallv(cb, id_call, 1, &ary); if (rb_obj_is_kind_of(ret_obj, cSSLContext)) { - SSL *ssl; SSL_CTX *ctx2; - ossl_sslctx_setup(ret_obj); - GetSSL(ssl_obj, ssl); GetSSLCTX(ret_obj, ctx2); - SSL_set_SSL_CTX(ssl, ctx2); + if (!SSL_set_SSL_CTX(ssl, ctx2)) + ossl_raise(eSSLError, "SSL_set_SSL_CTX"); + rb_ivar_set(ssl_obj, id_i_context, ret_obj); } else if (!NIL_P(ret_obj)) { - ossl_raise(rb_eArgError, "servername_cb must return an OpenSSL::SSL::SSLContext object or nil"); + ossl_raise(rb_eArgError, "servername_cb must return an " + "OpenSSL::SSL::SSLContext object or nil"); } - return ret_obj; + return Qnil; } static int ssl_servername_cb(SSL *ssl, int *ad, void *arg) { - VALUE ary, ssl_obj; - void *ptr; - int state = 0; - const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); - - if (!servername) - return SSL_TLSEXT_ERR_OK; - - if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL) - return SSL_TLSEXT_ERR_ALERT_FATAL; - ssl_obj = (VALUE)ptr; - ary = rb_ary_new2(2); - rb_ary_push(ary, ssl_obj); - rb_ary_push(ary, rb_str_new2(servername)); + int state; - rb_protect((VALUE(*)_((VALUE)))ossl_call_servername_cb, ary, &state); + rb_protect(ossl_call_servername_cb, (VALUE)ssl, &state); if (state) { + VALUE ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state)); return SSL_TLSEXT_ERR_ALERT_FATAL; } return SSL_TLSEXT_ERR_OK; } -#endif static void ssl_renegotiation_cb(const SSL *ssl) { VALUE ssl_obj, sslctx_obj, cb; - void *ptr; - if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL) - ossl_raise(eSSLError, "SSL object could not be retrieved"); - ssl_obj = (VALUE)ptr; - - sslctx_obj = rb_iv_get(ssl_obj, "@context"); - if (NIL_P(sslctx_obj)) return; - cb = rb_iv_get(sslctx_obj, "@renegotiation_cb"); + ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); + sslctx_obj = rb_attr_get(ssl_obj, id_i_context); + cb = rb_attr_get(sslctx_obj, id_i_renegotiation_cb); if (NIL_P(cb)) return; - (void) rb_funcall(cb, rb_intern("call"), 1, ssl_obj); + rb_funcallv(cb, id_call, 1, &ssl_obj); } -#ifdef HAVE_OPENSSL_NPN_NEGOTIATED static VALUE -ssl_npn_encode_protocol_i(VALUE cur, VALUE encoded) +ssl_npn_encode_protocol_i(RB_BLOCK_CALL_FUNC_ARGLIST(cur, encoded)) { int len = RSTRING_LENINT(cur); char len_byte; if (len < 1 || len > 255) - ossl_raise(eSSLError, "Advertised protocol must have length 1..255"); + ossl_raise(eSSLError, "Advertised protocol must have length 1..255"); /* Encode the length byte */ len_byte = len; rb_str_buf_cat(encoded, &len_byte, 1); @@ -597,20 +497,80 @@ ssl_npn_encode_protocol_i(VALUE cur, VALUE encoded) return Qnil; } -static void -ssl_npn_encode_protocols(VALUE sslctx, VALUE protocols) +static VALUE +ssl_encode_npn_protocols(VALUE protocols) { - VALUE encoded = rb_str_new2(""); - rb_iterate(rb_each, protocols, ssl_npn_encode_protocol_i, encoded); - StringValueCStr(encoded); - rb_iv_set(sslctx, "@_protocols", encoded); + VALUE encoded = rb_str_new(NULL, 0); + rb_block_call(protocols, id_each, 0, 0, ssl_npn_encode_protocol_i, encoded); + return encoded; +} + +struct npn_select_cb_common_args { + VALUE cb; + const unsigned char *in; + unsigned inlen; +}; + +static VALUE +npn_select_cb_common_i(VALUE tmp) +{ + struct npn_select_cb_common_args *args = (void *)tmp; + const unsigned char *in = args->in, *in_end = in + args->inlen; + unsigned char l; + long len; + VALUE selected, protocols = rb_ary_new(); + + /* assume OpenSSL verifies this format */ + /* The format is len_1|proto_1|...|len_n|proto_n */ + while (in < in_end) { + l = *in++; + rb_ary_push(protocols, rb_str_new((const char *)in, l)); + in += l; + } + + selected = rb_funcallv(args->cb, id_call, 1, &protocols); + StringValue(selected); + len = RSTRING_LEN(selected); + if (len < 1 || len >= 256) { + ossl_raise(eSSLError, "Selected protocol name must have length 1..255"); + } + + return selected; } static int -ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg) +ssl_npn_select_cb_common(SSL *ssl, VALUE cb, const unsigned char **out, + unsigned char *outlen, const unsigned char *in, + unsigned int inlen) { - VALUE sslctx_obj = (VALUE) arg; - VALUE protocols = rb_iv_get(sslctx_obj, "@_protocols"); + VALUE selected; + int status; + struct npn_select_cb_common_args args; + + args.cb = cb; + args.in = in; + args.inlen = inlen; + + selected = rb_protect(npn_select_cb_common_i, (VALUE)&args, &status); + if (status) { + VALUE ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); + + rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status)); + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + *out = (unsigned char *)RSTRING_PTR(selected); + *outlen = (unsigned char)RSTRING_LEN(selected); + + return SSL_TLSEXT_ERR_OK; +} + +#ifdef OSSL_USE_NEXTPROTONEG +static int +ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, + void *arg) +{ + VALUE protocols = rb_attr_get((VALUE)arg, id_npn_protocols_encoded); *out = (const unsigned char *) RSTRING_PTR(protocols); *outlen = RSTRING_LENINT(protocols); @@ -619,100 +579,143 @@ ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, } static int -ssl_npn_select_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) +ssl_npn_select_cb(SSL *ssl, unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg) { - int i = 0; - VALUE sslctx_obj, cb, protocols, selected; + VALUE sslctx_obj, cb; sslctx_obj = (VALUE) arg; - cb = rb_iv_get(sslctx_obj, "@npn_select_cb"); - protocols = rb_ary_new(); - - /* The format is len_1|proto_1|...|len_n|proto_n\0 */ - while (in[i]) { - VALUE protocol = rb_str_new((const char *) &in[i + 1], in[i]); - rb_ary_push(protocols, protocol); - i += in[i] + 1; - } + cb = rb_attr_get(sslctx_obj, id_i_npn_select_cb); - selected = rb_funcall(cb, rb_intern("call"), 1, protocols); - StringValue(selected); - *out = (unsigned char *) StringValuePtr(selected); - *outlen = RSTRING_LENINT(selected); - - return SSL_TLSEXT_ERR_OK; + return ssl_npn_select_cb_common(ssl, cb, (const unsigned char **)out, + outlen, in, inlen); } #endif -/* This function may serve as the entry point to support further - * callbacks. */ +static int +ssl_alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg) +{ + VALUE sslctx_obj, cb; + + sslctx_obj = (VALUE) arg; + cb = rb_attr_get(sslctx_obj, id_i_alpn_select_cb); + + return ssl_npn_select_cb_common(ssl, cb, out, outlen, in, inlen); +} + +/* This function may serve as the entry point to support further callbacks. */ static void ssl_info_cb(const SSL *ssl, int where, int val) { - int state = SSL_state(ssl); + int is_server = SSL_is_server((SSL *)ssl); - if ((where & SSL_CB_HANDSHAKE_START) && - (state & SSL_ST_ACCEPT)) { - ssl_renegotiation_cb(ssl); + if (is_server && where & SSL_CB_HANDSHAKE_START) { + ssl_renegotiation_cb(ssl); } } /* * call-seq: + * ctx.options -> integer + * + * Gets various \OpenSSL options. + */ +static VALUE +ossl_sslctx_get_options(VALUE self) +{ + SSL_CTX *ctx; + GetSSLCTX(self, ctx); + /* + * Do explicit cast because SSL_CTX_get_options() returned (signed) long in + * OpenSSL before 1.1.0. + */ + return ULONG2NUM((unsigned long)SSL_CTX_get_options(ctx)); +} + +/* + * call-seq: + * ctx.options = integer + * + * Sets various \OpenSSL options. The options are a bit field and can be + * combined with the bitwise OR operator (<tt>|</tt>). Available options are + * defined as constants in OpenSSL::SSL that begin with +OP_+. + * + * For backwards compatibility, passing +nil+ has the same effect as passing + * OpenSSL::SSL::OP_ALL. + * + * See also man page SSL_CTX_set_options(3). + */ +static VALUE +ossl_sslctx_set_options(VALUE self, VALUE options) +{ + SSL_CTX *ctx; + + rb_check_frozen(self); + GetSSLCTX(self, ctx); + + SSL_CTX_clear_options(ctx, SSL_CTX_get_options(ctx)); + + if (NIL_P(options)) { + SSL_CTX_set_options(ctx, SSL_OP_ALL); + } else { + SSL_CTX_set_options(ctx, NUM2ULONG(options)); + } + + return self; +} + +/* + * call-seq: * ctx.setup => Qtrue # first time * ctx.setup => nil # thereafter * * This method is called automatically when a new SSLSocket is created. - * Normally you do not need to call this method (unless you are writing an - * extension in C). + * However, it is not thread-safe and must be called before creating + * SSLSocket objects in a multi-threaded program. */ static VALUE ossl_sslctx_setup(VALUE self) { SSL_CTX *ctx; X509 *cert = NULL, *client_ca = NULL; - X509_STORE *store; EVP_PKEY *key = NULL; char *ca_path = NULL, *ca_file = NULL; - int i, verify_mode; + int verify_mode; + long i; VALUE val; if(OBJ_FROZEN(self)) return Qnil; GetSSLCTX(self, ctx); #if !defined(OPENSSL_NO_DH) - if (RTEST(ossl_sslctx_get_tmp_dh_cb(self))){ - SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback); - } - else{ - SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback); + if (!NIL_P(rb_attr_get(self, id_i_tmp_dh_callback))) { + SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback); + SSL_CTX_set_dh_auto(ctx, 0); } #endif - SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)self); - val = ossl_sslctx_get_cert_store(self); - if(!NIL_P(val)){ - /* - * WORKAROUND: - * X509_STORE can count references, but - * X509_STORE_free() doesn't care it. - * So we won't increment it but mark it by ex_data. - */ - store = GetX509StorePtr(val); /* NO NEED TO DUP */ +#if !defined(OPENSSL_IS_AWSLC) /* AWS-LC has no support for TLS 1.3 PHA. */ + SSL_CTX_set_post_handshake_auth(ctx, 1); +#endif + + val = rb_attr_get(self, id_i_cert_store); + if (!NIL_P(val)) { + X509_STORE *store = GetX509StorePtr(val); /* NO NEED TO DUP */ SSL_CTX_set_cert_store(ctx, store); - SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void*)1); + X509_STORE_up_ref(store); } - val = ossl_sslctx_get_extra_cert(self); + val = rb_attr_get(self, id_i_extra_chain_cert); if(!NIL_P(val)){ - rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self); + rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self); } /* private key may be bundled in certificate file. */ - val = ossl_sslctx_get_cert(self); + val = rb_attr_get(self, id_i_cert); cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */ - val = ossl_sslctx_get_key(self); - key = NIL_P(val) ? NULL : GetPKeyPtr(val); /* NO DUP NEEDED */ + val = rb_attr_get(self, id_i_key); + key = NIL_P(val) ? NULL : GetPrivPKeyPtr(val); /* NO DUP NEEDED */ if (cert && key) { if (!SSL_CTX_use_certificate(ctx, cert)) { /* Adds a ref => Safe to FREE */ @@ -727,104 +730,217 @@ ossl_sslctx_setup(VALUE self) } } - val = ossl_sslctx_get_client_ca(self); + val = rb_attr_get(self, id_i_client_ca); if(!NIL_P(val)){ - if (RB_TYPE_P(val, T_ARRAY)) { - for(i = 0; i < RARRAY_LEN(val); i++){ - client_ca = GetX509CertPtr(RARRAY_PTR(val)[i]); - if (!SSL_CTX_add_client_CA(ctx, client_ca)){ - /* Copies X509_NAME => FREE it. */ - ossl_raise(eSSLError, "SSL_CTX_add_client_CA"); - } - } + if (RB_TYPE_P(val, T_ARRAY)) { + for(i = 0; i < RARRAY_LEN(val); i++){ + client_ca = GetX509CertPtr(RARRAY_AREF(val, i)); + if (!SSL_CTX_add_client_CA(ctx, client_ca)){ + /* Copies X509_NAME => FREE it. */ + ossl_raise(eSSLError, "SSL_CTX_add_client_CA"); + } + } } - else{ - client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */ + else{ + client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */ if (!SSL_CTX_add_client_CA(ctx, client_ca)){ - /* Copies X509_NAME => FREE it. */ - ossl_raise(eSSLError, "SSL_CTX_add_client_CA"); + /* Copies X509_NAME => FREE it. */ + ossl_raise(eSSLError, "SSL_CTX_add_client_CA"); } - } + } } - val = ossl_sslctx_get_ca_file(self); - ca_file = NIL_P(val) ? NULL : StringValuePtr(val); - val = ossl_sslctx_get_ca_path(self); - ca_path = NIL_P(val) ? NULL : StringValuePtr(val); - if(ca_file || ca_path){ - if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path)) - rb_warning("can't set verify locations"); + val = rb_attr_get(self, id_i_ca_file); + ca_file = NIL_P(val) ? NULL : StringValueCStr(val); + val = rb_attr_get(self, id_i_ca_path); + ca_path = NIL_P(val) ? NULL : StringValueCStr(val); +#ifdef HAVE_SSL_CTX_LOAD_VERIFY_FILE + if (ca_file && !SSL_CTX_load_verify_file(ctx, ca_file)) + ossl_raise(eSSLError, "SSL_CTX_load_verify_file"); + if (ca_path && !SSL_CTX_load_verify_dir(ctx, ca_path)) + ossl_raise(eSSLError, "SSL_CTX_load_verify_dir"); +#else + if (ca_file || ca_path) { + if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path)) + ossl_raise(eSSLError, "SSL_CTX_load_verify_locations"); } +#endif - val = ossl_sslctx_get_verify_mode(self); + val = rb_attr_get(self, id_i_verify_mode); verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val); SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback); - if (RTEST(ossl_sslctx_get_client_cert_cb(self))) - SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb); + if (RTEST(rb_attr_get(self, id_i_client_cert_cb))) + SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb); - val = ossl_sslctx_get_timeout(self); + val = rb_attr_get(self, id_i_timeout); if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val)); - val = ossl_sslctx_get_verify_dep(self); + val = rb_attr_get(self, id_i_verify_depth); if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2INT(val)); - val = ossl_sslctx_get_options(self); - if(!NIL_P(val)) { - SSL_CTX_set_options(ctx, NUM2LONG(val)); - } else { - SSL_CTX_set_options(ctx, SSL_OP_ALL); +#ifdef OSSL_USE_NEXTPROTONEG + val = rb_attr_get(self, id_i_npn_protocols); + if (!NIL_P(val)) { + VALUE encoded = ssl_encode_npn_protocols(val); + rb_ivar_set(self, id_npn_protocols_encoded, encoded); + SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)self); + OSSL_Debug("SSL NPN advertise callback added"); } + if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) { + SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, (void *) self); + OSSL_Debug("SSL NPN select callback added"); + } +#endif -#ifdef HAVE_OPENSSL_NPN_NEGOTIATED - val = rb_iv_get(self, "@npn_protocols"); + val = rb_attr_get(self, id_i_alpn_protocols); if (!NIL_P(val)) { - ssl_npn_encode_protocols(self, val); - SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *) self); - OSSL_Debug("SSL NPN advertise callback added"); + VALUE rprotos = ssl_encode_npn_protocols(val); + + /* returns 0 on success */ + if (SSL_CTX_set_alpn_protos(ctx, (unsigned char *)RSTRING_PTR(rprotos), + RSTRING_LENINT(rprotos))) + ossl_raise(eSSLError, "SSL_CTX_set_alpn_protos"); + OSSL_Debug("SSL ALPN values added"); } - if (RTEST(rb_iv_get(self, "@npn_select_cb"))) { - SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, (void *) self); - OSSL_Debug("SSL NPN select callback added"); + if (RTEST(rb_attr_get(self, id_i_alpn_select_cb))) { + SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, (void *) self); + OSSL_Debug("SSL ALPN select callback added"); } -#endif rb_obj_freeze(self); - val = ossl_sslctx_get_sess_id_ctx(self); + val = rb_attr_get(self, id_i_session_id_context); if (!NIL_P(val)){ - StringValue(val); - if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val), - RSTRING_LENINT(val))){ - ossl_raise(eSSLError, "SSL_CTX_set_session_id_context"); - } + StringValue(val); + if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val), + RSTRING_LENINT(val))){ + ossl_raise(eSSLError, "SSL_CTX_set_session_id_context"); + } } - if (RTEST(rb_iv_get(self, "@session_get_cb"))) { - SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb); - OSSL_Debug("SSL SESSION get callback added"); + if (RTEST(rb_attr_get(self, id_i_session_get_cb))) { + SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb); + OSSL_Debug("SSL SESSION get callback added"); } - if (RTEST(rb_iv_get(self, "@session_new_cb"))) { - SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb); - OSSL_Debug("SSL SESSION new callback added"); + if (RTEST(rb_attr_get(self, id_i_session_new_cb))) { + SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb); + OSSL_Debug("SSL SESSION new callback added"); } - if (RTEST(rb_iv_get(self, "@session_remove_cb"))) { - SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb); - OSSL_Debug("SSL SESSION remove callback added"); + if (RTEST(rb_attr_get(self, id_i_session_remove_cb))) { + SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb); + OSSL_Debug("SSL SESSION remove callback added"); } -#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME - val = rb_iv_get(self, "@servername_cb"); + val = rb_attr_get(self, id_i_servername_cb); if (!NIL_P(val)) { SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); - OSSL_Debug("SSL TLSEXT servername callback added"); + OSSL_Debug("SSL TLSEXT servername callback added"); + } + +#if !OSSL_IS_LIBRESSL + /* + * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements + * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see + * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6). + */ + if (RTEST(rb_attr_get(self, id_i_keylog_cb))) { + SSL_CTX_set_keylog_callback(ctx, ossl_sslctx_keylog_cb); + OSSL_Debug("SSL keylog callback added"); } #endif return Qtrue; } +static int +parse_proto_version(VALUE str) +{ + int i; + static const struct { + const char *name; + int version; + } map[] = { + { "SSL2", SSL2_VERSION }, + { "SSL3", SSL3_VERSION }, + { "TLS1", TLS1_VERSION }, + { "TLS1_1", TLS1_1_VERSION }, + { "TLS1_2", TLS1_2_VERSION }, + { "TLS1_3", TLS1_3_VERSION }, + }; + + if (NIL_P(str)) + return 0; + if (RB_INTEGER_TYPE_P(str)) + return NUM2INT(str); + + if (SYMBOL_P(str)) + str = rb_sym2str(str); + StringValue(str); + for (i = 0; i < numberof(map); i++) + if (!strncmp(map[i].name, RSTRING_PTR(str), RSTRING_LEN(str))) + return map[i].version; + rb_raise(rb_eArgError, "unrecognized version %+"PRIsVALUE, str); +} + +/* + * call-seq: + * ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION + * ctx.min_version = :TLS1_2 + * ctx.min_version = nil + * + * Sets the lower bound on the supported SSL/TLS protocol version. The + * version may be specified by an integer constant named + * OpenSSL::SSL::*_VERSION, a Symbol, or +nil+ which means "any version". + * + * === Example + * ctx = OpenSSL::SSL::SSLContext.new + * ctx.min_version = OpenSSL::SSL::TLS1_1_VERSION + * ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION + * + * sock = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx) + * sock.connect # Initiates a connection using either TLS 1.1 or TLS 1.2 + */ +static VALUE +ossl_sslctx_set_min_version(VALUE self, VALUE v) +{ + SSL_CTX *ctx; + int version; + + rb_check_frozen(self); + GetSSLCTX(self, ctx); + version = parse_proto_version(v); + + if (!SSL_CTX_set_min_proto_version(ctx, version)) + ossl_raise(eSSLError, "SSL_CTX_set_min_proto_version"); + return v; +} + +/* + * call-seq: + * ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION + * ctx.max_version = :TLS1_2 + * ctx.max_version = nil + * + * Sets the upper bound of the supported SSL/TLS protocol version. See + * #min_version= for the possible values. + */ static VALUE -ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher) +ossl_sslctx_set_max_version(VALUE self, VALUE v) +{ + SSL_CTX *ctx; + int version; + + rb_check_frozen(self); + GetSSLCTX(self, ctx); + version = parse_proto_version(v); + + if (!SSL_CTX_set_max_proto_version(ctx, version)) + ossl_raise(eSSLError, "SSL_CTX_set_max_proto_version"); + return v; +} + +static VALUE +ossl_ssl_cipher_to_ary(const SSL_CIPHER *cipher) { VALUE ary; int bits, alg_bits; @@ -833,8 +949,8 @@ ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher) rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_name(cipher))); rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_version(cipher))); bits = SSL_CIPHER_get_bits(cipher, &alg_bits); - rb_ary_push(ary, INT2FIX(bits)); - rb_ary_push(ary, INT2FIX(alg_bits)); + rb_ary_push(ary, INT2NUM(bits)); + rb_ary_push(ary, INT2NUM(alg_bits)); return ary; } @@ -843,24 +959,19 @@ ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher) * call-seq: * ctx.ciphers => [[name, version, bits, alg_bits], ...] * - * The list of ciphers configured for this context. + * The list of cipher suites configured for this context. */ static VALUE ossl_sslctx_get_ciphers(VALUE self) { SSL_CTX *ctx; STACK_OF(SSL_CIPHER) *ciphers; - SSL_CIPHER *cipher; + const SSL_CIPHER *cipher; VALUE ary; int i, num; GetSSLCTX(self, ctx); - if(!ctx){ - rb_warning("SSL_CTX is not initialized."); - return Qnil; - } - ciphers = ctx->cipher_list; - + ciphers = SSL_CTX_get_ciphers(ctx); if (!ciphers) return rb_ary_new(); @@ -873,31 +984,14 @@ ossl_sslctx_get_ciphers(VALUE self) return ary; } -/* - * call-seq: - * ctx.ciphers = "cipher1:cipher2:..." - * ctx.ciphers = [name, ...] - * ctx.ciphers = [[name, version, bits, alg_bits], ...] - * - * Sets the list of available ciphers for this context. Note in a server - * context some ciphers require the appropriate certificates. For example, an - * RSA cipher can only be chosen when an RSA certificate is available. - * - * See also OpenSSL::Cipher and OpenSSL::Cipher::ciphers - */ static VALUE -ossl_sslctx_set_ciphers(VALUE self, VALUE v) +build_cipher_string(VALUE v) { - SSL_CTX *ctx; VALUE str, elem; - int i; - rb_check_frozen(self); - if (NIL_P(v)) - return v; - else if (RB_TYPE_P(v, T_ARRAY)) { + if (RB_TYPE_P(v, T_ARRAY)) { str = rb_str_new(0, 0); - for (i = 0; i < RARRAY_LEN(v); i++) { + for (long i = 0; i < RARRAY_LEN(v); i++) { elem = rb_ary_entry(v, i); if (RB_TYPE_P(elem, T_ARRAY)) elem = rb_ary_entry(elem, 0); elem = rb_String(elem); @@ -909,23 +1003,374 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v) StringValue(str); } + return str; +} + +/* + * call-seq: + * ctx.ciphers = "cipher1:cipher2:..." + * ctx.ciphers = [name, ...] + * ctx.ciphers = [[name, version, bits, alg_bits], ...] + * + * Sets the list of available cipher suites for TLS 1.2 and below for this + * context. + * + * Note in a server context some ciphers require the appropriate certificates. + * For example, an RSA cipher suite can only be chosen when an RSA certificate + * is available. + * + * This method does not affect TLS 1.3 connections. See also #ciphersuites=. + */ +static VALUE +ossl_sslctx_set_ciphers(VALUE self, VALUE v) +{ + SSL_CTX *ctx; + VALUE str; + + rb_check_frozen(self); + // Assigning nil is a no-op for compatibility + if (NIL_P(v)) + return v; + + str = build_cipher_string(v); + GetSSLCTX(self, ctx); - if(!ctx){ - ossl_raise(eSSLError, "SSL_CTX is not initialized."); - return Qnil; - } - if (!SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(str))) { + if (!SSL_CTX_set_cipher_list(ctx, StringValueCStr(str))) ossl_raise(eSSLError, "SSL_CTX_set_cipher_list"); - } return v; } /* + * call-seq: + * ctx.ciphersuites = "cipher1:cipher2:..." + * ctx.ciphersuites = [name, ...] + * + * Sets the list of available TLS 1.3 cipher suites for this context. + */ +static VALUE +ossl_sslctx_set_ciphersuites(VALUE self, VALUE v) +{ + SSL_CTX *ctx; + VALUE str; + + rb_check_frozen(self); + // Assigning nil is a no-op for compatibility + if (NIL_P(v)) + return v; + + str = build_cipher_string(v); + + GetSSLCTX(self, ctx); + if (!SSL_CTX_set_ciphersuites(ctx, StringValueCStr(str))) + ossl_raise(eSSLError, "SSL_CTX_set_ciphersuites"); + + return v; +} + +#ifdef HAVE_SSL_CTX_SET1_SIGALGS_LIST +/* + * call-seq: + * ctx.sigalgs = "sigalg1:sigalg2:..." + * + * Sets the list of "supported signature algorithms" for this context. + * + * For a TLS client, the list is used in the "signature_algorithms" extension + * in the ClientHello message. For a server, the list is used by OpenSSL to + * determine the set of shared signature algorithms. OpenSSL will pick the most + * appropriate one from it. + * + * See also #client_sigalgs= for the client authentication equivalent. + */ +static VALUE +ossl_sslctx_set_sigalgs(VALUE self, VALUE v) +{ + SSL_CTX *ctx; + + rb_check_frozen(self); + GetSSLCTX(self, ctx); + + if (!SSL_CTX_set1_sigalgs_list(ctx, StringValueCStr(v))) + ossl_raise(eSSLError, "SSL_CTX_set1_sigalgs_list"); + + return v; +} +#endif + +#ifdef HAVE_SSL_CTX_SET1_CLIENT_SIGALGS_LIST +/* + * call-seq: + * ctx.client_sigalgs = "sigalg1:sigalg2:..." + * + * Sets the list of "supported signature algorithms" for client authentication + * for this context. + * + * For a TLS server, the list is sent to the client as part of the + * CertificateRequest message. + * + * See also #sigalgs= for the server authentication equivalent. + */ +static VALUE +ossl_sslctx_set_client_sigalgs(VALUE self, VALUE v) +{ + SSL_CTX *ctx; + + rb_check_frozen(self); + GetSSLCTX(self, ctx); + + if (!SSL_CTX_set1_client_sigalgs_list(ctx, StringValueCStr(v))) + ossl_raise(eSSLError, "SSL_CTX_set1_client_sigalgs_list"); + + return v; +} +#endif + +#ifndef OPENSSL_NO_DH +/* + * call-seq: + * ctx.tmp_dh = pkey + * + * Sets DH parameters used for ephemeral DH key exchange. This is relevant for + * servers only. + * + * +pkey+ is an instance of OpenSSL::PKey::DH. Note that key components + * contained in the key object, if any, are ignored. The server will always + * generate a new key pair for each handshake. + * + * Added in version 3.0. See also the man page SSL_CTX_set0_tmp_dh_pkey(3). + * + * Example: + * ctx = OpenSSL::SSL::SSLContext.new + * ctx.tmp_dh = OpenSSL::DH.generate(2048) + * svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx) + * Thread.new { svr.accept } + */ +static VALUE +ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg) +{ + SSL_CTX *ctx; + EVP_PKEY *pkey; + + rb_check_frozen(self); + GetSSLCTX(self, ctx); + pkey = GetPKeyPtr(arg); + + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) + rb_raise(eSSLError, "invalid pkey type %s (expected DH)", + OBJ_nid2sn(EVP_PKEY_base_id(pkey))); +#ifdef HAVE_SSL_CTX_SET0_TMP_DH_PKEY + if (!SSL_CTX_set0_tmp_dh_pkey(ctx, pkey)) + ossl_raise(eSSLError, "SSL_CTX_set0_tmp_dh_pkey"); + EVP_PKEY_up_ref(pkey); +#else + if (!SSL_CTX_set_tmp_dh(ctx, EVP_PKEY_get0_DH(pkey))) + ossl_raise(eSSLError, "SSL_CTX_set_tmp_dh"); +#endif + + // Turn off the "auto" DH parameters set by ossl_sslctx_s_alloc() + SSL_CTX_set_dh_auto(ctx, 0); + + return arg; +} +#endif + +/* + * call-seq: + * ctx.groups = groups_list + * ctx.ecdh_curves = groups_list + * + * Sets the list of supported groups for key agreement for this context. + * + * For a TLS client, the list is directly used in the "supported_groups" + * extension. For a server, the list is used by OpenSSL to determine the set of + * shared supported groups. OpenSSL will pick the most appropriate one from it. + * + * #ecdh_curves= is a deprecated alias for #groups=. + * + * See also the man page SSL_CTX_set1_groups_list(3). + * + * === Example + * ctx1 = OpenSSL::SSL::SSLContext.new + * ctx1.groups = "X25519:P-256:P-224" + * svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx1) + * Thread.new { svr.accept } + * + * ctx2 = OpenSSL::SSL::SSLContext.new + * ctx2.groups = "P-256" + * cli = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx2) + * cli.connect + * + * p cli.tmp_key.group.curve_name + * # => "prime256v1" (is an alias for NIST P-256) + */ +static VALUE +ossl_sslctx_set_groups(VALUE self, VALUE arg) +{ + SSL_CTX *ctx; + + rb_check_frozen(self); + GetSSLCTX(self, ctx); + StringValueCStr(arg); + + if (!SSL_CTX_set1_groups_list(ctx, RSTRING_PTR(arg))) + ossl_raise(eSSLError, "SSL_CTX_set1_groups_list"); + return arg; +} + +/* + * call-seq: + * ctx.security_level -> Integer + * + * Returns the security level for the context. + * + * See also OpenSSL::SSL::SSLContext#security_level=. + */ +static VALUE +ossl_sslctx_get_security_level(VALUE self) +{ + SSL_CTX *ctx; + + GetSSLCTX(self, ctx); + + return INT2NUM(SSL_CTX_get_security_level(ctx)); +} + +/* + * call-seq: + * ctx.security_level = integer + * + * Sets the security level for the context. OpenSSL limits parameters according + * to the level. The "parameters" include: ciphersuites, curves, key sizes, + * certificate signature algorithms, protocol version and so on. For example, + * level 1 rejects parameters offering below 80 bits of security, such as + * ciphersuites using MD5 for the MAC or RSA keys shorter than 1024 bits. + * + * Note that attempts to set such parameters with insufficient security are + * also blocked. You need to lower the level first. + * + * This feature is not supported in OpenSSL < 1.1.0, and setting the level to + * other than 0 will raise NotImplementedError. Level 0 means everything is + * permitted, the same behavior as previous versions of OpenSSL. + * + * See the manpage of SSL_CTX_set_security_level(3) for details. + */ +static VALUE +ossl_sslctx_set_security_level(VALUE self, VALUE value) +{ + SSL_CTX *ctx; + + rb_check_frozen(self); + GetSSLCTX(self, ctx); + + SSL_CTX_set_security_level(ctx, NUM2INT(value)); + + return value; +} + +#ifdef SSL_MODE_SEND_FALLBACK_SCSV +/* + * call-seq: + * ctx.enable_fallback_scsv() => nil + * + * Activate TLS_FALLBACK_SCSV for this context. + * See RFC 7507. + */ +static VALUE +ossl_sslctx_enable_fallback_scsv(VALUE self) +{ + SSL_CTX *ctx; + + GetSSLCTX(self, ctx); + SSL_CTX_set_mode(ctx, SSL_MODE_SEND_FALLBACK_SCSV); + + return Qnil; +} +#endif + +/* + * call-seq: + * ctx.add_certificate(certificate, pkey [, extra_certs]) -> self + * + * Adds a certificate to the context. _pkey_ must be a corresponding private + * key with _certificate_. + * + * Multiple certificates with different public key type can be added by + * repeated calls of this method, and OpenSSL will choose the most appropriate + * certificate during the handshake. + * + * #cert=, #key=, and #extra_chain_cert= are old accessor methods for setting + * certificate and internally call this method. + * + * === Parameters + * _certificate_:: + * A certificate. An instance of OpenSSL::X509::Certificate. + * _pkey_:: + * The private key for _certificate_. An instance of OpenSSL::PKey::PKey. + * _extra_certs_:: + * Optional. An array of OpenSSL::X509::Certificate. When sending a + * certificate chain, the certificates specified by this are sent following + * _certificate_, in the order in the array. + * + * === Example + * rsa_cert = OpenSSL::X509::Certificate.new(...) + * rsa_pkey = OpenSSL::PKey.read(...) + * ca_intermediate_cert = OpenSSL::X509::Certificate.new(...) + * ctx.add_certificate(rsa_cert, rsa_pkey, [ca_intermediate_cert]) + * + * ecdsa_cert = ... + * ecdsa_pkey = ... + * another_ca_cert = ... + * ctx.add_certificate(ecdsa_cert, ecdsa_pkey, [another_ca_cert]) + */ +static VALUE +ossl_sslctx_add_certificate(int argc, VALUE *argv, VALUE self) +{ + VALUE cert, key, extra_chain_ary; + SSL_CTX *ctx; + X509 *x509; + STACK_OF(X509) *extra_chain = NULL; + EVP_PKEY *pkey, *pub_pkey; + + GetSSLCTX(self, ctx); + rb_scan_args(argc, argv, "21", &cert, &key, &extra_chain_ary); + rb_check_frozen(self); + x509 = GetX509CertPtr(cert); + pkey = GetPrivPKeyPtr(key); + + /* + * The reference counter is bumped, and decremented immediately. + * X509_get0_pubkey() is only available in OpenSSL >= 1.1.0. + */ + pub_pkey = X509_get_pubkey(x509); + EVP_PKEY_free(pub_pkey); + if (!pub_pkey) + rb_raise(rb_eArgError, "certificate does not contain public key"); + if (EVP_PKEY_eq(pub_pkey, pkey) != 1) + rb_raise(rb_eArgError, "public key mismatch"); + + if (argc >= 3) + extra_chain = ossl_x509_ary2sk(extra_chain_ary); + + if (!SSL_CTX_use_certificate(ctx, x509)) { + sk_X509_pop_free(extra_chain, X509_free); + ossl_raise(eSSLError, "SSL_CTX_use_certificate"); + } + if (!SSL_CTX_use_PrivateKey(ctx, pkey)) { + sk_X509_pop_free(extra_chain, X509_free); + ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey"); + } + if (extra_chain && !SSL_CTX_set0_chain(ctx, extra_chain)) { + sk_X509_pop_free(extra_chain, X509_free); + ossl_raise(eSSLError, "SSL_CTX_set0_chain"); + } + return self; +} + +/* * call-seq: * ctx.session_add(session) -> true | false * - * Adds +session+ to the session cache + * Adds _session_ to the session cache. */ static VALUE ossl_sslctx_session_add(VALUE self, VALUE arg) @@ -934,7 +1379,7 @@ ossl_sslctx_session_add(VALUE self, VALUE arg) SSL_SESSION *sess; GetSSLCTX(self, ctx); - SafeGetSSLSession(arg, sess); + GetSSLSession(arg, sess); return SSL_CTX_add_session(ctx, sess) == 1 ? Qtrue : Qfalse; } @@ -943,7 +1388,7 @@ ossl_sslctx_session_add(VALUE self, VALUE arg) * call-seq: * ctx.session_remove(session) -> true | false * - * Removes +session+ from the session cache + * Removes _session_ from the session cache. */ static VALUE ossl_sslctx_session_remove(VALUE self, VALUE arg) @@ -952,7 +1397,7 @@ ossl_sslctx_session_remove(VALUE self, VALUE arg) SSL_SESSION *sess; GetSSLCTX(self, ctx); - SafeGetSSLSession(arg, sess); + GetSSLSession(arg, sess); return SSL_CTX_remove_session(ctx, sess) == 1 ? Qtrue : Qfalse; } @@ -1079,9 +1524,9 @@ ossl_sslctx_get_session_cache_stats(VALUE self) /* * call-seq: - * ctx.flush_sessions(time | nil) -> self + * ctx.flush_sessions(time) -> self * - * Removes sessions in the internal cache that have expired at +time+. + * Removes sessions in the internal cache that have expired at _time_. */ static VALUE ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self) @@ -1110,26 +1555,18 @@ ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self) /* * SSLSocket class */ -#ifndef OPENSSL_NO_SOCK +static inline int +ssl_started(SSL *ssl) +{ + /* BIO is created through ossl_ssl_setup(), called by #connect or #accept */ + return SSL_get_rbio(ssl) != NULL; +} + static void -ossl_ssl_shutdown(SSL *ssl) -{ - int i, rc; - - if (ssl) { - /* 4 is from SSL_smart_shutdown() of mod_ssl.c (v2.2.19) */ - /* It says max 2x pending + 2x data = 4 */ - for (i = 0; i < 4; ++i) { - /* - * Ignore the case SSL_shutdown returns -1. Empty handshake_func - * must not happen. - */ - if (rc = SSL_shutdown(ssl)) - break; - } - SSL_clear(ssl); - ERR_clear_error(); - } +ossl_ssl_mark(void *ptr) +{ + SSL *ssl = ptr; + rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)); } static void @@ -1141,9 +1578,9 @@ ossl_ssl_free(void *ssl) const rb_data_type_t ossl_ssl_type = { "OpenSSL/SSL", { - 0, ossl_ssl_free, + ossl_ssl_mark, ossl_ssl_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; static VALUE @@ -1152,15 +1589,38 @@ ossl_ssl_s_alloc(VALUE klass) return TypedData_Wrap_Struct(klass, &ossl_ssl_type, NULL); } +static VALUE +peer_ip_address(VALUE self) +{ + VALUE remote_address = rb_funcall(rb_attr_get(self, id_i_io), rb_intern("remote_address"), 0); + + return rb_funcall(remote_address, rb_intern("inspect_sockaddr"), 0); +} + +static VALUE +fallback_peer_ip_address(VALUE self, VALUE args) +{ + return rb_str_new_cstr("(null)"); +} + +static VALUE +peeraddr_ip_str(VALUE self) +{ + VALUE rb_mErrno = rb_const_get(rb_cObject, rb_intern("Errno")); + VALUE rb_eSystemCallError = rb_const_get(rb_mErrno, rb_intern("SystemCallError")); + + return rb_rescue2(peer_ip_address, self, fallback_peer_ip_address, (VALUE)0, rb_eSystemCallError, NULL); +} + /* * call-seq: * SSLSocket.new(io) => aSSLSocket * SSLSocket.new(io, ctx) => aSSLSocket * - * Creates a new SSL socket from +io+ which must be a real ruby object (not an + * Creates a new SSL socket from _io_ which must be a real IO object (not an * IO-like object that responds to read/write). * - * If +ctx+ is provided the SSL Sockets initial params will be taken from + * If _ctx_ is provided the SSL Sockets initial params will be taken from * the context. * * The OpenSSL::Buffering module provides additional IO methods. @@ -1171,68 +1631,67 @@ ossl_ssl_s_alloc(VALUE klass) static VALUE ossl_ssl_initialize(int argc, VALUE *argv, VALUE self) { - VALUE io, ctx; + VALUE io, v_ctx; + SSL *ssl; + SSL_CTX *ctx; - if (rb_scan_args(argc, argv, "11", &io, &ctx) == 1) { - ctx = rb_funcall(cSSLContext, rb_intern("new"), 0); - } - OSSL_Check_Kind(ctx, cSSLContext); + TypedData_Get_Struct(self, SSL, &ossl_ssl_type, ssl); + if (ssl) + ossl_raise(eSSLError, "SSL already initialized"); + + if (rb_scan_args(argc, argv, "11", &io, &v_ctx) == 1) + v_ctx = rb_funcall(cSSLContext, rb_intern("new"), 0); + + GetSSLCTX(v_ctx, ctx); + rb_ivar_set(self, id_i_context, v_ctx); + ossl_sslctx_setup(v_ctx); + + if (rb_respond_to(io, rb_intern("nonblock="))) + rb_funcall(io, rb_intern("nonblock="), 1, Qtrue); Check_Type(io, T_FILE); - ossl_ssl_set_io(self, io); - ossl_ssl_set_ctx(self, ctx); - ossl_ssl_set_sync_close(self, Qfalse); - ossl_sslctx_setup(ctx); + rb_ivar_set(self, id_i_io, io); + + ssl = SSL_new(ctx); + if (!ssl) + ossl_raise(eSSLError, NULL); + RTYPEDDATA_DATA(self) = ssl; - rb_iv_set(self, "@hostname", Qnil); + SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void *)self); + SSL_set_info_callback(ssl, ssl_info_cb); - rb_call_super(0, 0); + rb_call_super(0, NULL); return self; } +#ifndef HAVE_RB_IO_DESCRIPTOR +static int +io_descriptor_fallback(VALUE io) +{ + rb_io_t *fptr; + GetOpenFile(io, fptr); + return fptr->fd; +} +#define rb_io_descriptor io_descriptor_fallback +#endif + static VALUE ossl_ssl_setup(VALUE self) { - VALUE io, v_ctx, cb; - SSL_CTX *ctx; + VALUE io; SSL *ssl; rb_io_t *fptr; GetSSL(self, ssl); - if(!ssl){ -#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME - VALUE hostname = rb_iv_get(self, "@hostname"); -#endif - - v_ctx = ossl_ssl_get_ctx(self); - GetSSLCTX(v_ctx, ctx); + if (ssl_started(ssl)) + return Qtrue; - ssl = SSL_new(ctx); - if (!ssl) { - ossl_raise(eSSLError, "SSL_new"); - } - DATA_PTR(self) = ssl; - -#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME - if (!NIL_P(hostname)) { - if (SSL_set_tlsext_host_name(ssl, StringValuePtr(hostname)) != 1) - ossl_raise(eSSLError, "SSL_set_tlsext_host_name"); - } -#endif - io = ossl_ssl_get_io(self); - GetOpenFile(io, fptr); - rb_io_check_readable(fptr); - rb_io_check_writable(fptr); - SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr))); - SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self); - cb = ossl_sslctx_get_verify_cb(v_ctx); - SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb); - cb = ossl_sslctx_get_client_cert_cb(v_ctx); - SSL_set_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx, (void*)cb); - cb = ossl_sslctx_get_tmp_dh_cb(v_ctx); - SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx, (void*)cb); - SSL_set_info_callback(ssl, ssl_info_cb); - } + io = rb_attr_get(self, id_i_io); + GetOpenFile(io, fptr); + rb_io_check_readable(fptr); + rb_io_check_writable(fptr); + if (!SSL_set_fd(ssl, TO_SOCKET(rb_io_descriptor(io)))) + ossl_raise(eSSLError, "SSL_set_fd"); return Qtrue; } @@ -1243,71 +1702,141 @@ ossl_ssl_setup(VALUE self) #define ssl_get_error(ssl, ret) SSL_get_error((ssl), (ret)) #endif -#define ossl_ssl_data_get_struct(v, ssl) \ -do { \ - GetSSL((v), (ssl)); \ - if (!(ssl)) { \ - rb_warning("SSL session is not started yet."); \ - return Qnil; \ - } \ -} while (0) - static void write_would_block(int nonblock) { - if (nonblock) { - VALUE exc = ossl_exc_new(eSSLErrorWaitWritable, "write would block"); - rb_exc_raise(exc); - } + if (nonblock) + ossl_raise(eSSLErrorWaitWritable, "write would block"); } static void read_would_block(int nonblock) { - if (nonblock) { - VALUE exc = ossl_exc_new(eSSLErrorWaitReadable, "read would block"); - rb_exc_raise(exc); + if (nonblock) + ossl_raise(eSSLErrorWaitReadable, "read would block"); +} + +static int +no_exception_p(VALUE opts) +{ + if (RB_TYPE_P(opts, T_HASH) && + rb_hash_lookup2(opts, sym_exception, Qundef) == Qfalse) + return 1; + return 0; +} + +// Provided by Ruby 3.2.0 and later in order to support the default IO#timeout. +#ifndef RUBY_IO_TIMEOUT_DEFAULT +#define RUBY_IO_TIMEOUT_DEFAULT Qnil +#endif + +#ifdef HAVE_RB_IO_TIMEOUT +#define IO_TIMEOUT_ERROR rb_eIOTimeoutError +#else +#define IO_TIMEOUT_ERROR rb_eIOError +#endif + + +static void +io_wait_writable(VALUE io) +{ +#ifdef HAVE_RB_IO_MAYBE_WAIT + if (!rb_io_maybe_wait_writable(errno, io, RUBY_IO_TIMEOUT_DEFAULT)) { + rb_raise(IO_TIMEOUT_ERROR, "Timed out while waiting to become writable!"); + } +#else + rb_io_t *fptr; + GetOpenFile(io, fptr); + rb_io_wait_writable(fptr->fd); +#endif +} + +static void +io_wait_readable(VALUE io) +{ +#ifdef HAVE_RB_IO_MAYBE_WAIT + if (!rb_io_maybe_wait_readable(errno, io, RUBY_IO_TIMEOUT_DEFAULT)) { + rb_raise(IO_TIMEOUT_ERROR, "Timed out while waiting to become readable!"); } +#else + rb_io_t *fptr; + GetOpenFile(io, fptr); + rb_io_wait_readable(fptr->fd); +#endif } static VALUE -ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, int nonblock) +ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts) { SSL *ssl; - rb_io_t *fptr; int ret, ret2; VALUE cb_state; + int nonblock = opts != Qfalse; rb_ivar_set(self, ID_callback_state, Qnil); - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); - GetOpenFile(ossl_ssl_get_io(self), fptr); - for(;;){ - ret = func(ssl); + VALUE io = rb_attr_get(self, id_i_io); + for (;;) { + ret = func(ssl); - cb_state = rb_ivar_get(self, ID_callback_state); - if (!NIL_P(cb_state)) + cb_state = rb_attr_get(self, ID_callback_state); + if (!NIL_P(cb_state)) { + /* must cleanup OpenSSL error stack before re-raising */ + ossl_clear_error(); rb_jump_tag(NUM2INT(cb_state)); + } - if (ret > 0) - break; + if (ret > 0) + break; - switch((ret2 = ssl_get_error(ssl, ret))){ - case SSL_ERROR_WANT_WRITE: + switch ((ret2 = ssl_get_error(ssl, ret))) { + case SSL_ERROR_WANT_WRITE: + if (no_exception_p(opts)) { return sym_wait_writable; } write_would_block(nonblock); - rb_io_wait_writable(FPTR_TO_FD(fptr)); + io_wait_writable(io); continue; - case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_READ: + if (no_exception_p(opts)) { return sym_wait_readable; } read_would_block(nonblock); - rb_io_wait_readable(FPTR_TO_FD(fptr)); + io_wait_readable(io); continue; - case SSL_ERROR_SYSCALL: - if (errno) rb_sys_fail(funcname); - ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl)); - default: - ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl)); - } + case SSL_ERROR_SYSCALL: +#ifdef __APPLE__ + /* See ossl_ssl_write_internal() */ + if (errno == EPROTOTYPE) + continue; +#endif + if (errno) rb_sys_fail(funcname); + /* fallthrough */ + default: { + VALUE error_append = Qnil; +#if defined(SSL_R_CERTIFICATE_VERIFY_FAILED) + unsigned long err = ERR_peek_last_error(); + if (ERR_GET_LIB(err) == ERR_LIB_SSL && + ERR_GET_REASON(err) == SSL_R_CERTIFICATE_VERIFY_FAILED) { + const char *err_msg = ERR_reason_error_string(err), + *verify_msg = X509_verify_cert_error_string(SSL_get_verify_result(ssl)); + if (!err_msg) + err_msg = "(null)"; + if (!verify_msg) + verify_msg = "(null)"; + ossl_clear_error(); /* let ossl_raise() not append message */ + error_append = rb_sprintf(": %s (%s)", err_msg, verify_msg); + } +#endif + ossl_raise(eSSLError, + "%s%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s%"PRIsVALUE, + funcname, + ret2 == SSL_ERROR_SYSCALL ? " SYSCALL" : "", + ret2, + errno, + peeraddr_ip_str(self), + SSL_state_string_long(ssl), + error_append); + } + } } return self; @@ -1317,19 +1846,19 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, int nonblock) * call-seq: * ssl.connect => self * - * Initiates an SSL/TLS handshake with a server. The handshake may be started - * after unencrypted data has been sent over the socket. + * Initiates an SSL/TLS handshake with a server. */ static VALUE ossl_ssl_connect(VALUE self) { ossl_ssl_setup(self); - return ossl_start_ssl(self, SSL_connect, "SSL_connect", 0); + + return ossl_start_ssl(self, SSL_connect, "SSL_connect", Qfalse); } /* * call-seq: - * ssl.connect_nonblock => self + * ssl.connect_nonblock([options]) => self * * Initiates the SSL/TLS handshake as a client in non-blocking manner. * @@ -1344,31 +1873,39 @@ ossl_ssl_connect(VALUE self) * retry * end * + * By specifying a keyword argument _exception_ to +false+, you can indicate + * that connect_nonblock should not raise an IO::WaitReadable or + * IO::WaitWritable exception, but return the symbol +:wait_readable+ or + * +:wait_writable+ instead. */ static VALUE -ossl_ssl_connect_nonblock(VALUE self) +ossl_ssl_connect_nonblock(int argc, VALUE *argv, VALUE self) { + VALUE opts; + rb_scan_args(argc, argv, "0:", &opts); + ossl_ssl_setup(self); - return ossl_start_ssl(self, SSL_connect, "SSL_connect", 1); + + return ossl_start_ssl(self, SSL_connect, "SSL_connect", opts); } /* * call-seq: * ssl.accept => self * - * Waits for a SSL/TLS client to initiate a handshake. The handshake may be - * started after unencrypted data has been sent over the socket. + * Waits for a SSL/TLS client to initiate a handshake. */ static VALUE ossl_ssl_accept(VALUE self) { ossl_ssl_setup(self); - return ossl_start_ssl(self, SSL_accept, "SSL_accept", 0); + + return ossl_start_ssl(self, SSL_accept, "SSL_accept", Qfalse); } /* * call-seq: - * ssl.accept_nonblock => self + * ssl.accept_nonblock([options]) => self * * Initiates the SSL/TLS handshake as a server in non-blocking manner. * @@ -1383,87 +1920,116 @@ ossl_ssl_accept(VALUE self) * retry * end * + * By specifying a keyword argument _exception_ to +false+, you can indicate + * that accept_nonblock should not raise an IO::WaitReadable or + * IO::WaitWritable exception, but return the symbol +:wait_readable+ or + * +:wait_writable+ instead. */ static VALUE -ossl_ssl_accept_nonblock(VALUE self) +ossl_ssl_accept_nonblock(int argc, VALUE *argv, VALUE self) { + VALUE opts; + + rb_scan_args(argc, argv, "0:", &opts); ossl_ssl_setup(self); - return ossl_start_ssl(self, SSL_accept, "SSL_accept", 1); + + return ossl_start_ssl(self, SSL_accept, "SSL_accept", opts); } static VALUE ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) { SSL *ssl; - int ilen, nread = 0; - int no_exception = 0; - VALUE len, str; - rb_io_t *fptr; + int ilen; + VALUE len, str, cb_state; VALUE opts = Qnil; - rb_scan_args(argc, argv, "11:", &len, &str, &opts); - - if (!NIL_P(opts) && Qfalse == rb_hash_aref(opts, sym_exception)) - no_exception = 1; + if (nonblock) { + rb_scan_args(argc, argv, "11:", &len, &str, &opts); + } else { + rb_scan_args(argc, argv, "11", &len, &str); + } + GetSSL(self, ssl); + if (!ssl_started(ssl)) + rb_raise(eSSLError, "SSL session is not started yet"); ilen = NUM2INT(len); - if(NIL_P(str)) str = rb_str_new(0, ilen); - else{ + if (NIL_P(str)) + str = rb_str_new(0, ilen); + else { StringValue(str); - rb_str_modify(str); - rb_str_resize(str, ilen); + if (RSTRING_LEN(str) >= ilen) + rb_str_modify(str); + else + rb_str_modify_expand(str, ilen - RSTRING_LEN(str)); } - if(ilen == 0) return str; - GetSSL(self, ssl); - GetOpenFile(ossl_ssl_get_io(self), fptr); - if (ssl) { - if(!nonblock && SSL_pending(ssl) <= 0) - rb_thread_wait_fd(FPTR_TO_FD(fptr)); - for (;;){ - nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LENINT(str)); - switch(ssl_get_error(ssl, nread)){ - case SSL_ERROR_NONE: - goto end; - case SSL_ERROR_ZERO_RETURN: - if (no_exception) { return Qnil; } - rb_eof_error(); - case SSL_ERROR_WANT_WRITE: - if (no_exception) { return ID2SYM(rb_intern("wait_writable")); } - write_would_block(nonblock); - rb_io_wait_writable(FPTR_TO_FD(fptr)); - continue; - case SSL_ERROR_WANT_READ: - if (no_exception) { return ID2SYM(rb_intern("wait_readable")); } - read_would_block(nonblock); - rb_io_wait_readable(FPTR_TO_FD(fptr)); - continue; - case SSL_ERROR_SYSCALL: - if(ERR_peek_error() == 0 && nread == 0) { - if (no_exception) { return Qnil; } - rb_eof_error(); - } - rb_sys_fail(0); - default: - ossl_raise(eSSLError, "SSL_read"); - } - } + if (ilen == 0) { + rb_str_set_len(str, 0); + return str; } - else { - ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread"); - rb_warning("SSL session is not started yet."); - if (nonblock) { - return rb_funcall(ossl_ssl_get_io(self), meth, 3, len, str, opts); - } else { - return rb_funcall(ossl_ssl_get_io(self), meth, 2, len, str); + + VALUE io = rb_attr_get(self, id_i_io); + + for (;;) { + rb_str_locktmp(str); + int nread = SSL_read(ssl, RSTRING_PTR(str), ilen); + rb_str_unlocktmp(str); + + cb_state = rb_attr_get(self, ID_callback_state); + if (!NIL_P(cb_state)) { + rb_ivar_set(self, ID_callback_state, Qnil); + ossl_clear_error(); + rb_jump_tag(NUM2INT(cb_state)); } - } - end: - rb_str_set_len(str, nread); - OBJ_TAINT(str); + switch (ssl_get_error(ssl, nread)) { + case SSL_ERROR_NONE: + rb_str_set_len(str, nread); + return str; + case SSL_ERROR_ZERO_RETURN: + if (no_exception_p(opts)) { return Qnil; } + rb_eof_error(); + case SSL_ERROR_WANT_WRITE: + if (nonblock) { + if (no_exception_p(opts)) { return sym_wait_writable; } + write_would_block(nonblock); + } + io_wait_writable(io); + break; + case SSL_ERROR_WANT_READ: + if (nonblock) { + if (no_exception_p(opts)) { return sym_wait_readable; } + read_would_block(nonblock); + } + io_wait_readable(io); + break; + case SSL_ERROR_SYSCALL: + if (!ERR_peek_error()) { + if (errno) + rb_sys_fail(0); + else { + /* + * The underlying BIO returned 0. This is actually a + * protocol error. But unfortunately, not all + * implementations cleanly shutdown the TLS connection + * but just shutdown/close the TCP connection. So report + * EOF for now... + */ + if (no_exception_p(opts)) { return Qnil; } + rb_eof_error(); + } + } + /* fall through */ + default: + ossl_raise(eSSLError, "SSL_read"); + } - return str; + // Ensure the buffer is not modified during io_wait_*able() + rb_str_modify(str); + if (rb_str_capacity(str) < (size_t)ilen) + rb_raise(eSSLError, "read buffer was modified"); + } } /* @@ -1471,7 +2037,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) * ssl.sysread(length) => string * ssl.sysread(length, buffer) => buffer * - * Reads +length+ bytes from the SSL connection. If a pre-allocated +buffer+ + * Reads _length_ bytes from the SSL connection. If a pre-allocated _buffer_ * is provided the data will be written into it. */ static VALUE @@ -1490,7 +2056,7 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self) * block. If "exception: false" is passed, this method returns a symbol of * :wait_readable, :wait_writable, or nil, rather than raising an exception. * - * Reads +length+ bytes from the SSL connection. If a pre-allocated +buffer+ + * Reads _length_ bytes from the SSL connection. If a pre-allocated _buffer_ * is provided the data will be written into it. */ static VALUE @@ -1500,111 +2066,152 @@ ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self) } static VALUE -ossl_ssl_write_internal(VALUE self, VALUE str, int nonblock, int no_exception) +ossl_ssl_write_internal_safe(VALUE _args) { + VALUE *args = (VALUE*)_args; + VALUE self = args[0]; + VALUE str = args[1]; + VALUE opts = args[2]; + SSL *ssl; - int nwrite = 0; rb_io_t *fptr; + int num, nonblock = opts != Qfalse; + VALUE cb_state; - StringValue(str); GetSSL(self, ssl); - GetOpenFile(ossl_ssl_get_io(self), fptr); - - if (ssl) { - for (;;){ - nwrite = SSL_write(ssl, RSTRING_PTR(str), RSTRING_LENINT(str)); - switch(ssl_get_error(ssl, nwrite)){ - case SSL_ERROR_NONE: - goto end; - case SSL_ERROR_WANT_WRITE: - if (no_exception) { return ID2SYM(rb_intern("wait_writable")); } - write_would_block(nonblock); - rb_io_wait_writable(FPTR_TO_FD(fptr)); - continue; - case SSL_ERROR_WANT_READ: - if (no_exception) { return ID2SYM(rb_intern("wait_readable")); } - read_would_block(nonblock); - rb_io_wait_readable(FPTR_TO_FD(fptr)); + if (!ssl_started(ssl)) + rb_raise(eSSLError, "SSL session is not started yet"); + + VALUE io = rb_attr_get(self, id_i_io); + GetOpenFile(io, fptr); + + /* SSL_write(3ssl) manpage states num == 0 is undefined */ + num = RSTRING_LENINT(str); + if (num == 0) + return INT2FIX(0); + + for (;;) { + int nwritten = SSL_write(ssl, RSTRING_PTR(str), num); + + cb_state = rb_attr_get(self, ID_callback_state); + if (!NIL_P(cb_state)) { + rb_ivar_set(self, ID_callback_state, Qnil); + ossl_clear_error(); + rb_jump_tag(NUM2INT(cb_state)); + } + + switch (ssl_get_error(ssl, nwritten)) { + case SSL_ERROR_NONE: + return INT2NUM(nwritten); + case SSL_ERROR_WANT_WRITE: + if (no_exception_p(opts)) { return sym_wait_writable; } + write_would_block(nonblock); + io_wait_writable(io); + continue; + case SSL_ERROR_WANT_READ: + if (no_exception_p(opts)) { return sym_wait_readable; } + read_would_block(nonblock); + io_wait_readable(io); + continue; + case SSL_ERROR_SYSCALL: +#ifdef __APPLE__ + /* + * It appears that send syscall can return EPROTOTYPE if the + * socket is being torn down. Retry to get a proper errno to + * make the error handling in line with the socket library. + * [Bug #14713] https://bugs.ruby-lang.org/issues/14713 + */ + if (errno == EPROTOTYPE) continue; - case SSL_ERROR_SYSCALL: - if (errno) rb_sys_fail(0); - default: - ossl_raise(eSSLError, "SSL_write"); - } +#endif + if (errno) rb_sys_fail(0); + /* fallthrough */ + default: + ossl_raise(eSSLError, "SSL_write"); } } - else { - ID id_syswrite = rb_intern("syswrite"); - rb_warning("SSL session is not started yet."); - return rb_funcall(ossl_ssl_get_io(self), id_syswrite, 1, str); +} + + +static VALUE +ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts) +{ + StringValue(str); + int frozen = RB_OBJ_FROZEN(str); + if (!frozen) { + rb_str_locktmp(str); + } + int state; + VALUE args[3] = {self, str, opts}; + VALUE result = rb_protect(ossl_ssl_write_internal_safe, (VALUE)args, &state); + if (!frozen) { + rb_str_unlocktmp(str); } - end: - return INT2NUM(nwrite); + if (state) { + rb_jump_tag(state); + } + return result; } /* * call-seq: * ssl.syswrite(string) => Integer * - * Writes +string+ to the SSL connection. + * Writes _string_ to the SSL connection. */ static VALUE ossl_ssl_write(VALUE self, VALUE str) { - return ossl_ssl_write_internal(self, str, 0, 0); + return ossl_ssl_write_internal(self, str, Qfalse); } /* * call-seq: * ssl.syswrite_nonblock(string) => Integer * - * Writes +string+ to the SSL connection in a non-blocking manner. Raises an + * Writes _string_ to the SSL connection in a non-blocking manner. Raises an * SSLError if writing would block. */ static VALUE ossl_ssl_write_nonblock(int argc, VALUE *argv, VALUE self) { - VALUE str; - VALUE opts = Qnil; - int no_exception = 0; + VALUE str, opts; rb_scan_args(argc, argv, "1:", &str, &opts); - if (!NIL_P(opts) && Qfalse == rb_hash_aref(opts, sym_exception)) - no_exception = 1; - - return ossl_ssl_write_internal(self, str, 1, no_exception); + return ossl_ssl_write_internal(self, str, opts); } /* * call-seq: - * ssl.sysclose => nil + * ssl.stop => nil * - * Shuts down the SSL connection and prepares it for another connection. + * Sends "close notify" to the peer and tries to shut down the SSL connection + * gracefully. */ static VALUE -ossl_ssl_close(VALUE self) +ossl_ssl_stop(VALUE self) { SSL *ssl; - VALUE io; - - /* ossl_ssl_data_get_struct() is not usable here because it may return - * from this function; */ + int ret; GetSSL(self, ssl); + if (!ssl_started(ssl)) + return Qnil; + ret = SSL_shutdown(ssl); + if (ret == 1) /* Have already received close_notify */ + return Qnil; + if (ret == 0) /* Sent close_notify, but we don't wait for reply */ + return Qnil; - io = ossl_ssl_get_io(self); - if (!RTEST(rb_funcall(io, rb_intern("closed?"), 0))) { - if (ssl) { - ossl_ssl_shutdown(ssl); - SSL_free(ssl); - } - DATA_PTR(self) = NULL; - if (RTEST(ossl_ssl_get_sync_close(self))) - rb_funcall(io, rb_intern("close"), 0); - } - + /* + * XXX: Something happened. Possibly it failed because the underlying socket + * is not writable/readable, since it is in non-blocking mode. We should do + * some proper error handling using SSL_get_error() and maybe retry, but we + * can't block here. Give up for now. + */ + ossl_clear_error(); return Qnil; } @@ -1620,7 +2227,7 @@ ossl_ssl_get_cert(VALUE self) SSL *ssl; X509 *cert = NULL; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); /* * Is this OpenSSL bug? Should add a ref? @@ -1647,7 +2254,7 @@ ossl_ssl_get_peer_cert(VALUE self) X509 *cert = NULL; VALUE obj; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); cert = SSL_get_peer_certificate(ssl); /* Adds a ref => Safe to FREE. */ @@ -1675,61 +2282,61 @@ ossl_ssl_get_peer_cert_chain(VALUE self) VALUE ary; int i, num; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); chain = SSL_get_peer_cert_chain(ssl); if(!chain) return Qnil; num = sk_X509_num(chain); ary = rb_ary_new2(num); for (i = 0; i < num; i++){ - cert = sk_X509_value(chain, i); - rb_ary_push(ary, ossl_x509_new(cert)); + cert = sk_X509_value(chain, i); + rb_ary_push(ary, ossl_x509_new(cert)); } return ary; } /* -* call-seq: -* ssl.ssl_version => String -* -* Returns a String representing the SSL/TLS version that was negotiated -* for the connection, for example "TLSv1.2". -*/ + * call-seq: + * ssl.ssl_version => String + * + * Returns a String representing the SSL/TLS version that was negotiated + * for the connection, for example "TLSv1.2". + */ static VALUE ossl_ssl_get_version(VALUE self) { SSL *ssl; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); return rb_str_new2(SSL_get_version(ssl)); } /* -* call-seq: -* ssl.cipher => [name, version, bits, alg_bits] -* -* The cipher being used for the current connection -*/ + * call-seq: + * ssl.cipher -> nil or [name, version, bits, alg_bits] + * + * Returns the cipher suite actually used in the current session, or nil if + * no session has been established. + */ static VALUE ossl_ssl_get_cipher(VALUE self) { SSL *ssl; - SSL_CIPHER *cipher; + const SSL_CIPHER *cipher; - ossl_ssl_data_get_struct(self, ssl); - - cipher = (SSL_CIPHER *)SSL_get_current_cipher(ssl); - - return ossl_ssl_cipher_to_ary(cipher); + GetSSL(self, ssl); + cipher = SSL_get_current_cipher(ssl); + return cipher ? ossl_ssl_cipher_to_ary(cipher) : Qnil; } /* * call-seq: * ssl.state => string * - * A description of the current connection state. + * A description of the current connection state. This is for diagnostic + * purposes only. */ static VALUE ossl_ssl_get_state(VALUE self) @@ -1737,7 +2344,7 @@ ossl_ssl_get_state(VALUE self) SSL *ssl; VALUE ret; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); ret = rb_str_new2(SSL_state_string(ssl)); if (ruby_verbose) { @@ -1751,14 +2358,14 @@ ossl_ssl_get_state(VALUE self) * call-seq: * ssl.pending => Integer * - * The number of bytes that are immediately available for reading + * The number of bytes that are immediately available for reading. */ static VALUE ossl_ssl_pending(VALUE self) { SSL *ssl; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); return INT2NUM(SSL_pending(ssl)); } @@ -1767,22 +2374,16 @@ ossl_ssl_pending(VALUE self) * call-seq: * ssl.session_reused? -> true | false * - * Returns true if a reused session was negotiated during the handshake. + * Returns +true+ if a reused session was negotiated during the handshake. */ static VALUE ossl_ssl_session_reused(VALUE self) { SSL *ssl; - ossl_ssl_data_get_struct(self, ssl); - - switch(SSL_session_reused(ssl)) { - case 1: return Qtrue; - case 0: return Qfalse; - default: ossl_raise(eSSLError, "SSL_session_reused"); - } + GetSSL(self, ssl); - UNREACHABLE; + return SSL_session_reused(ssl) ? Qtrue : Qfalse; } /* @@ -1797,12 +2398,8 @@ ossl_ssl_set_session(VALUE self, VALUE arg1) SSL *ssl; SSL_SESSION *sess; -/* why is ossl_ssl_setup delayed? */ - ossl_ssl_setup(self); - - ossl_ssl_data_get_struct(self, ssl); - - SafeGetSSLSession(arg1, sess); + GetSSL(self, ssl); + GetSSLSession(arg1, sess); if (SSL_set_session(ssl, sess) != 1) ossl_raise(eSSLError, "SSL_set_session"); @@ -1812,6 +2409,33 @@ ossl_ssl_set_session(VALUE self, VALUE arg1) /* * call-seq: + * ssl.hostname = hostname -> hostname + * + * Sets the server hostname used for SNI. This needs to be set before + * SSLSocket#connect. + */ +static VALUE +ossl_ssl_set_hostname(VALUE self, VALUE arg) +{ + SSL *ssl; + char *hostname = NULL; + + GetSSL(self, ssl); + + if (!NIL_P(arg)) + hostname = StringValueCStr(arg); + + if (!SSL_set_tlsext_host_name(ssl, hostname)) + ossl_raise(eSSLError, NULL); + + /* for SSLSocket#hostname */ + rb_ivar_set(self, id_i_hostname, arg); + + return arg; +} + +/* + * call-seq: * ssl.verify_result => Integer * * Returns the result of the peer certificates verification. See verify(1) @@ -1824,14 +2448,64 @@ ossl_ssl_get_verify_result(VALUE self) { SSL *ssl; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); + + return LONG2NUM(SSL_get_verify_result(ssl)); +} + +/* + * call-seq: + * ssl.finished_message => "finished message" + * + * Returns the last *Finished* message sent + * + */ +static VALUE +ossl_ssl_get_finished(VALUE self) +{ + SSL *ssl; + char sizer[1], *buf; + size_t len; + + GetSSL(self, ssl); + + len = SSL_get_finished(ssl, sizer, 0); + if (len == 0) + return Qnil; - return INT2FIX(SSL_get_verify_result(ssl)); + buf = ALLOCA_N(char, len); + SSL_get_finished(ssl, buf, len); + return rb_str_new(buf, len); } /* * call-seq: - * ssl.client_ca => [x509name, ...] + * ssl.peer_finished_message => "peer finished message" + * + * Returns the last *Finished* message received + * + */ +static VALUE +ossl_ssl_get_peer_finished(VALUE self) +{ + SSL *ssl; + char sizer[1], *buf; + size_t len; + + GetSSL(self, ssl); + + len = SSL_get_peer_finished(ssl, sizer, 0); + if (len == 0) + return Qnil; + + buf = ALLOCA_N(char, len); + SSL_get_peer_finished(ssl, buf, len); + return rb_str_new(buf, len); +} + +/* + * call-seq: + * ssl.client_ca => [x509name, ...] or nil * * Returns the list of client CAs. Please note that in contrast to * SSLContext#client_ca= no array of X509::Certificate is returned but @@ -1846,16 +2520,18 @@ ossl_ssl_get_client_ca_list(VALUE self) SSL *ssl; STACK_OF(X509_NAME) *ca; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); ca = SSL_get_client_CA_list(ssl); + if (!ca) + return Qnil; return ossl_x509name_sk2ary(ca); } -# ifdef HAVE_OPENSSL_NPN_NEGOTIATED +# ifdef OSSL_USE_NEXTPROTONEG /* * call-seq: - * ssl.npn_protocol => String + * ssl.npn_protocol => String | nil * * Returns the protocol string that was finally selected by the client * during the handshake. @@ -1867,36 +2543,181 @@ ossl_ssl_npn_protocol(VALUE self) const unsigned char *out; unsigned int outlen; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); SSL_get0_next_proto_negotiated(ssl, &out, &outlen); if (!outlen) - return Qnil; + return Qnil; else - return rb_str_new((const char *) out, outlen); + return rb_str_new((const char *) out, outlen); } # endif + +/* + * call-seq: + * ssl.alpn_protocol => String | nil + * + * Returns the ALPN protocol string that was finally selected by the server + * during the handshake. + */ +static VALUE +ossl_ssl_alpn_protocol(VALUE self) +{ + SSL *ssl; + const unsigned char *out; + unsigned int outlen; + + GetSSL(self, ssl); + + SSL_get0_alpn_selected(ssl, &out, &outlen); + if (!outlen) + return Qnil; + else + return rb_str_new((const char *) out, outlen); +} + +/* + * call-seq: + * session.export_keying_material(label, length) -> String + * + * Enables use of shared session key material in accordance with RFC 5705. + */ +static VALUE +ossl_ssl_export_keying_material(int argc, VALUE *argv, VALUE self) +{ + SSL *ssl; + VALUE str; + VALUE label; + VALUE length; + VALUE context; + unsigned char *p; + size_t len; + int use_ctx = 0; + unsigned char *ctx = NULL; + size_t ctx_len = 0; + int ret; + + rb_scan_args(argc, argv, "21", &label, &length, &context); + StringValue(label); + + GetSSL(self, ssl); + + len = (size_t)NUM2LONG(length); + str = rb_str_new(0, len); + p = (unsigned char *)RSTRING_PTR(str); + if (!NIL_P(context)) { + use_ctx = 1; + StringValue(context); + ctx = (unsigned char *)RSTRING_PTR(context); + ctx_len = RSTRING_LEN(context); + } + ret = SSL_export_keying_material(ssl, p, len, (char *)RSTRING_PTR(label), + RSTRING_LENINT(label), ctx, ctx_len, use_ctx); + if (ret == 0 || ret == -1) { + ossl_raise(eSSLError, "SSL_export_keying_material"); + } + return str; +} + +/* + * call-seq: + * ssl.tmp_key => PKey or nil + * + * Returns the ephemeral key used in case of forward secrecy cipher. + */ +static VALUE +ossl_ssl_tmp_key(VALUE self) +{ + SSL *ssl; + EVP_PKEY *key; + + GetSSL(self, ssl); + if (!SSL_get_server_tmp_key(ssl, &key)) + return Qnil; + return ossl_pkey_wrap(key); +} + +#ifdef HAVE_SSL_GET0_PEER_SIGNATURE_NAME +/* + * call-seq: + * ssl.sigalg => String or nil + * + * Returns the signature algorithm name, the IANA name of the signature scheme + * used by the local to sign the TLS handshake. + */ +static VALUE +ossl_ssl_get_sigalg(VALUE self) +{ + SSL *ssl; + const char *name; + + GetSSL(self, ssl); + if (!SSL_get0_signature_name(ssl, &name)) + return Qnil; + return rb_str_new_cstr(name); +} + +/* + * call-seq: + * ssl.peer_sigalg => String or nil + * + * Returns the signature algorithm name, the IANA name of the signature scheme + * used by the peer to sign the TLS handshake. + */ +static VALUE +ossl_ssl_get_peer_sigalg(VALUE self) +{ + SSL *ssl; + const char *name; + + GetSSL(self, ssl); + if (!SSL_get0_peer_signature_name(ssl, &name)) + return Qnil; + return rb_str_new_cstr(name); +} +#endif + +#ifdef HAVE_SSL_GET0_GROUP_NAME +/* + * call-seq: + * ssl.group => String or nil + * + * Returns the name of the group that was used for the key agreement of the + * current TLS session establishment. + */ +static VALUE +ossl_ssl_get_group(VALUE self) +{ + SSL *ssl; + const char *name; + + GetSSL(self, ssl); + if (!(name = SSL_get0_group_name(ssl))) + return Qnil; + return rb_str_new_cstr(name); +} +#endif + #endif /* !defined(OPENSSL_NO_SOCK) */ void Init_ossl_ssl(void) { - int i; - VALUE ary; - #if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ + rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable"); + rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable"); #endif - ID_callback_state = rb_intern("@callback_state"); +#ifndef OPENSSL_NO_SOCK + id_call = rb_intern_const("call"); + ID_callback_state = rb_intern_const("callback_state"); - ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_vcb_idx",0,0,0); - ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_store_p",0,0,0); - ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_ptr_idx",0,0,0); - ossl_ssl_ex_client_cert_cb_idx = - SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_client_cert_cb_idx",0,0,0); - ossl_ssl_ex_tmp_dh_callback_idx = - SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_tmp_dh_callback_idx",0,0,0); + ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0, (void *)"ossl_ssl_ex_ptr_idx", 0, 0, 0); + if (ossl_ssl_ex_ptr_idx < 0) + ossl_raise(rb_eRuntimeError, "SSL_get_ex_new_index"); + ossl_sslctx_ex_ptr_idx = SSL_CTX_get_ex_new_index(0, (void *)"ossl_sslctx_ex_ptr_idx", 0, 0, 0); + if (ossl_sslctx_ex_ptr_idx < 0) + ossl_raise(rb_eRuntimeError, "SSL_CTX_get_ex_new_index"); /* Document-module: OpenSSL::SSL * @@ -1906,6 +2727,7 @@ Init_ossl_ssl(void) * of SSLContext to set up connections. */ mSSL = rb_define_module_under(mOSSL, "SSL"); + /* Document-class: OpenSSL::SSL::SSLError * * Generic error class raised by SSLSocket and SSLContext. @@ -1926,88 +2748,102 @@ Init_ossl_ssl(void) * * All attributes must be set before creating an SSLSocket as the * SSLContext will be frozen afterward. - * - * The following attributes are available but don't show up in rdoc: - * * ssl_version, cert, key, client_ca, ca_file, ca_path, timeout, - * * verify_mode, verify_depth client_cert_cb, tmp_dh_callback, - * * session_id_context, session_add_cb, session_new_cb, session_remove_cb */ cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject); rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc); + rb_undef_method(cSSLContext, "initialize_copy"); /* * Context certificate + * + * The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated. + * It is recommended to use #add_certificate instead. */ - rb_attr(cSSLContext, rb_intern("cert"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("cert"), 1, 1, Qfalse); /* * Context private key + * + * The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated. + * It is recommended to use #add_certificate instead. */ - rb_attr(cSSLContext, rb_intern("key"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("key"), 1, 1, Qfalse); /* * A certificate or Array of certificates that will be sent to the client. */ - rb_attr(cSSLContext, rb_intern("client_ca"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("client_ca"), 1, 1, Qfalse); /* * The path to a file containing a PEM-format CA certificate */ - rb_attr(cSSLContext, rb_intern("ca_file"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("ca_file"), 1, 1, Qfalse); /* * The path to a directory containing CA certificates in PEM format. * * Files are looked up by subject's X509 name's hash value. */ - rb_attr(cSSLContext, rb_intern("ca_path"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("ca_path"), 1, 1, Qfalse); /* - * Maximum session lifetime. + * Maximum session lifetime in seconds. */ - rb_attr(cSSLContext, rb_intern("timeout"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("timeout"), 1, 1, Qfalse); /* * Session verification mode. * * Valid modes are VERIFY_NONE, VERIFY_PEER, VERIFY_CLIENT_ONCE, * VERIFY_FAIL_IF_NO_PEER_CERT and defined on OpenSSL::SSL + * + * The default mode is VERIFY_NONE, which does not perform any verification + * at all. + * + * See SSL_CTX_set_verify(3) for details. */ - rb_attr(cSSLContext, rb_intern("verify_mode"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("verify_mode"), 1, 1, Qfalse); /* * Number of CA certificates to walk when verifying a certificate chain. */ - rb_attr(cSSLContext, rb_intern("verify_depth"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("verify_depth"), 1, 1, Qfalse); /* * A callback for additional certificate verification. The callback is * invoked for each certificate in the chain. * - * The callback is invoked with two values. +preverify_ok+ indicates - * indicates if the verification was passed (true) or not (false). - * +store_context+ is an OpenSSL::X509::StoreContext containing the + * The callback is invoked with two values. _preverify_ok_ indicates + * indicates if the verification was passed (+true+) or not (+false+). + * _store_context_ is an OpenSSL::X509::StoreContext containing the * context used for certificate verification. * - * If the callback returns false verification is stopped. + * If the callback returns +false+, the chain verification is immediately + * stopped and a bad_certificate alert is then sent. */ - rb_attr(cSSLContext, rb_intern("verify_callback"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("verify_callback"), 1, 1, Qfalse); /* - * Sets various OpenSSL options. + * Whether to check the server certificate is valid for the hostname. + * + * In order to make this work, verify_mode must be set to VERIFY_PEER and + * the server hostname must be given by OpenSSL::SSL::SSLSocket#hostname=. */ - rb_attr(cSSLContext, rb_intern("options"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("verify_hostname"), 1, 1, Qfalse); /* - * An OpenSSL::X509::Store used for certificate verification + * An OpenSSL::X509::Store used for certificate verification. */ - rb_attr(cSSLContext, rb_intern("cert_store"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("cert_store"), 1, 1, Qfalse); /* * An Array of extra X509 certificates to be added to the certificate * chain. + * + * The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated. + * It is recommended to use #add_certificate instead. */ - rb_attr(cSSLContext, rb_intern("extra_chain_cert"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("extra_chain_cert"), 1, 1, Qfalse); /* * A callback invoked when a client certificate is requested by a server @@ -2017,26 +2853,31 @@ Init_ossl_ssl(void) * containing an OpenSSL::X509::Certificate and an OpenSSL::PKey. If any * other value is returned the handshake is suspended. */ - rb_attr(cSSLContext, rb_intern("client_cert_cb"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("client_cert_cb"), 1, 1, Qfalse); +#ifndef OPENSSL_NO_DH /* - * A callback invoked when DH parameters are required. + * A callback invoked when DH parameters are required for ephemeral DH key + * exchange. * - * The callback is invoked with the Session for the key exchange, an + * The callback is invoked with the SSLSocket, a * flag indicating the use of an export cipher and the keylength * required. * * The callback must return an OpenSSL::PKey::DH instance of the correct * key length. + * + * <b>Deprecated in version 3.0.</b> Use #tmp_dh= instead. */ - rb_attr(cSSLContext, rb_intern("tmp_dh_callback"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("tmp_dh_callback"), 1, 1, Qfalse); +#endif /* * Sets the context in which a session can be reused. This allows * sessions for multiple applications to be distinguished, for example, by * name. */ - rb_attr(cSSLContext, rb_intern("session_id_context"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("session_id_context"), 1, 1, Qfalse); /* * A callback invoked on a server when a session is proposed by the client @@ -2045,41 +2886,35 @@ Init_ossl_ssl(void) * The callback is invoked with the SSLSocket and session id. The * callback may return a Session from an external cache. */ - rb_attr(cSSLContext, rb_intern("session_get_cb"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("session_get_cb"), 1, 1, Qfalse); /* * A callback invoked when a new session was negotiated. * - * The callback is invoked with an SSLSocket. If false is returned the + * The callback is invoked with an SSLSocket. If +false+ is returned the * session will be removed from the internal cache. */ - rb_attr(cSSLContext, rb_intern("session_new_cb"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("session_new_cb"), 1, 1, Qfalse); /* * A callback invoked when a session is removed from the internal cache. * * The callback is invoked with an SSLContext and a Session. - */ - rb_attr(cSSLContext, rb_intern("session_remove_cb"), 1, 1, Qfalse); - -#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME - /* - * A callback invoked at connect time to distinguish between multiple - * server names. * - * The callback is invoked with an SSLSocket and a server name. The - * callback must return an SSLContext for the server name or nil. + * IMPORTANT NOTE: It is currently not possible to use this safely in a + * multi-threaded application. The callback is called inside a global lock + * and it can randomly cause deadlock on Ruby thread switching. */ - rb_attr(cSSLContext, rb_intern("servername_cb"), 1, 1, Qfalse); -#endif + rb_attr(cSSLContext, rb_intern_const("session_remove_cb"), 1, 1, Qfalse); + /* - * A callback invoked whenever a new handshake is initiated. May be used - * to disable renegotiation entirely. + * A callback invoked whenever a new handshake is initiated on an + * established connection. May be used to disable renegotiation entirely. * * The callback is invoked with the active SSLSocket. The callback's - * return value is irrelevant, normal return indicates "approval" of the + * return value is ignored. A normal return indicates "approval" of the * renegotiation and will continue the process. To forbid renegotiation - * and to cancel the process, an Error may be raised within the callback. + * and to cancel the process, raise an exception within the callback. * * === Disable client renegotiation * @@ -2087,14 +2922,12 @@ Init_ossl_ssl(void) * renegotiation entirely. You may use a callback as follows to implement * this feature: * - * num_handshakes = 0 * ctx.renegotiation_cb = lambda do |ssl| - * num_handshakes += 1 - * raise RuntimeError.new("Client renegotiation disabled") if num_handshakes > 1 + * raise RuntimeError, "Client renegotiation disabled" * end */ - rb_attr(cSSLContext, rb_intern("renegotiation_cb"), 1, 1, Qfalse); -#ifdef HAVE_OPENSSL_NPN_NEGOTIATED + rb_attr(cSSLContext, rb_intern_const("renegotiation_cb"), 1, 1, Qfalse); +#ifdef OSSL_USE_NEXTPROTONEG /* * An Enumerable of Strings. Each String represents a protocol to be * advertised as the list of supported protocols for Next Protocol @@ -2106,7 +2939,7 @@ Init_ossl_ssl(void) * * ctx.npn_protocols = ["http/1.1", "spdy/2"] */ - rb_attr(cSSLContext, rb_intern("npn_protocols"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("npn_protocols"), 1, 1, Qfalse); /* * A callback invoked on the client side when the client needs to select * a protocol from the list sent by the server. Supported in OpenSSL 1.0.1 @@ -2119,41 +2952,113 @@ Init_ossl_ssl(void) * === Example * * ctx.npn_select_cb = lambda do |protocols| - * #inspect the protocols and select one + * # inspect the protocols and select one * protocols.first * end */ - rb_attr(cSSLContext, rb_intern("npn_select_cb"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("npn_select_cb"), 1, 1, Qfalse); #endif + /* + * An Enumerable of Strings. Each String represents a protocol to be + * advertised as the list of supported protocols for Application-Layer + * Protocol Negotiation. Supported in OpenSSL 1.0.2 and higher. Has no + * effect on the server side. If not set explicitly, the ALPN extension will + * not be included in the handshake. + * + * === Example + * + * ctx.alpn_protocols = ["http/1.1", "spdy/2", "h2"] + */ + rb_attr(cSSLContext, rb_intern_const("alpn_protocols"), 1, 1, Qfalse); + /* + * A callback invoked on the server side when the server needs to select + * a protocol from the list sent by the client. Supported in OpenSSL 1.0.2 + * and higher. The callback must return a protocol of those advertised by + * the client. If none is acceptable, raising an error in the callback + * will cause the handshake to fail. Not setting this callback explicitly + * means not supporting the ALPN extension on the server - any protocols + * advertised by the client will be ignored. + * + * === Example + * + * ctx.alpn_select_cb = lambda do |protocols| + * # inspect the protocols and select one + * protocols.first + * end + */ + rb_attr(cSSLContext, rb_intern_const("alpn_select_cb"), 1, 1, Qfalse); + + /* + * A callback invoked when TLS key material is generated or received, in + * order to allow applications to store this keying material for debugging + * purposes. + * + * The callback is invoked with an SSLSocket and a string containing the + * key material in the format used by NSS for its SSLKEYLOGFILE debugging + * output. + * + * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements + * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see + * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6). + * + * === Example + * + * context.keylog_cb = proc do |_sock, line| + * File.open('ssl_keylog_file', "a") do |f| + * f.write("#{line}\n") + * end + * end + */ + rb_attr(cSSLContext, rb_intern_const("keylog_cb"), 1, 1, Qfalse); + rb_define_alias(cSSLContext, "ssl_timeout", "timeout"); rb_define_alias(cSSLContext, "ssl_timeout=", "timeout="); - rb_define_method(cSSLContext, "initialize", ossl_sslctx_initialize, -1); - rb_define_method(cSSLContext, "ssl_version=", ossl_sslctx_set_ssl_version, 1); + rb_define_method(cSSLContext, "min_version=", ossl_sslctx_set_min_version, 1); + rb_define_method(cSSLContext, "max_version=", ossl_sslctx_set_max_version, 1); rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0); rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1); + rb_define_method(cSSLContext, "ciphersuites=", ossl_sslctx_set_ciphersuites, 1); +#ifdef HAVE_SSL_CTX_SET1_SIGALGS_LIST // Not in LibreSSL yet + rb_define_method(cSSLContext, "sigalgs=", ossl_sslctx_set_sigalgs, 1); +#endif +#ifdef HAVE_SSL_CTX_SET1_CLIENT_SIGALGS_LIST // Not in LibreSSL or AWS-LC yet + rb_define_method(cSSLContext, "client_sigalgs=", ossl_sslctx_set_client_sigalgs, 1); +#endif +#ifndef OPENSSL_NO_DH + rb_define_method(cSSLContext, "tmp_dh=", ossl_sslctx_set_tmp_dh, 1); +#endif + rb_define_method(cSSLContext, "groups=", ossl_sslctx_set_groups, 1); + rb_define_alias(cSSLContext, "ecdh_curves=", "groups="); + rb_define_method(cSSLContext, "security_level", ossl_sslctx_get_security_level, 0); + rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1); +#ifdef SSL_MODE_SEND_FALLBACK_SCSV + rb_define_method(cSSLContext, "enable_fallback_scsv", ossl_sslctx_enable_fallback_scsv, 0); +#endif + rb_define_method(cSSLContext, "add_certificate", ossl_sslctx_add_certificate, -1); rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0); + rb_define_alias(cSSLContext, "freeze", "setup"); /* * No session caching for client or server */ - rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2FIX(SSL_SESS_CACHE_OFF)); + rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2NUM(SSL_SESS_CACHE_OFF)); /* * Client sessions are added to the session cache */ - rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2FIX(SSL_SESS_CACHE_CLIENT)); /* doesn't actually do anything in 0.9.8e */ + rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2NUM(SSL_SESS_CACHE_CLIENT)); /* doesn't actually do anything in 0.9.8e */ /* * Server sessions are added to the session cache */ - rb_define_const(cSSLContext, "SESSION_CACHE_SERVER", LONG2FIX(SSL_SESS_CACHE_SERVER)); + rb_define_const(cSSLContext, "SESSION_CACHE_SERVER", LONG2NUM(SSL_SESS_CACHE_SERVER)); /* * Both client and server sessions are added to the session cache */ - rb_define_const(cSSLContext, "SESSION_CACHE_BOTH", LONG2FIX(SSL_SESS_CACHE_BOTH)); /* no different than CACHE_SERVER in 0.9.8e */ + rb_define_const(cSSLContext, "SESSION_CACHE_BOTH", LONG2NUM(SSL_SESS_CACHE_BOTH)); /* no different than CACHE_SERVER in 0.9.8e */ /* * Normally the session cache is checked for expired sessions every 255 @@ -2161,7 +3066,7 @@ Init_ossl_ssl(void) * the automatic flushing may be disabled and #flush_sessions can be * called explicitly. */ - rb_define_const(cSSLContext, "SESSION_CACHE_NO_AUTO_CLEAR", LONG2FIX(SSL_SESS_CACHE_NO_AUTO_CLEAR)); + rb_define_const(cSSLContext, "SESSION_CACHE_NO_AUTO_CLEAR", LONG2NUM(SSL_SESS_CACHE_NO_AUTO_CLEAR)); /* * Always perform external lookups of sessions even if they are in the @@ -2169,18 +3074,18 @@ Init_ossl_ssl(void) * * This flag has no effect on clients */ - rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_LOOKUP", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)); + rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_LOOKUP", LONG2NUM(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)); /* * Never automatically store sessions in the internal store. */ - rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_STORE", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_STORE)); + rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_STORE", LONG2NUM(SSL_SESS_CACHE_NO_INTERNAL_STORE)); /* * Enables both SESSION_CACHE_NO_INTERNAL_LOOKUP and * SESSION_CACHE_NO_INTERNAL_STORE. */ - rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL)); + rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL", LONG2NUM(SSL_SESS_CACHE_NO_INTERNAL)); rb_define_method(cSSLContext, "session_add", ossl_sslctx_session_add, 1); rb_define_method(cSSLContext, "session_remove", ossl_sslctx_session_remove, 1); @@ -2190,42 +3095,25 @@ Init_ossl_ssl(void) rb_define_method(cSSLContext, "session_cache_size=", ossl_sslctx_set_session_cache_size, 1); rb_define_method(cSSLContext, "session_cache_stats", ossl_sslctx_get_session_cache_stats, 0); rb_define_method(cSSLContext, "flush_sessions", ossl_sslctx_flush_sessions, -1); - - ary = rb_ary_new2(numberof(ossl_ssl_method_tab)); - for (i = 0; i < numberof(ossl_ssl_method_tab); i++) { - rb_ary_push(ary, ID2SYM(rb_intern(ossl_ssl_method_tab[i].name))); - } - rb_obj_freeze(ary); - /* The list of available SSL/TLS methods */ - rb_define_const(cSSLContext, "METHODS", ary); + rb_define_method(cSSLContext, "options", ossl_sslctx_get_options, 0); + rb_define_method(cSSLContext, "options=", ossl_sslctx_set_options, 1); /* * Document-class: OpenSSL::SSL::SSLSocket - * - * The following attributes are available but don't show up in rdoc. - * * io, context, sync_close - * */ cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject); -#ifdef OPENSSL_NO_SOCK - rb_define_method(cSSLSocket, "initialize", rb_notimplement, -1); -#else rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc); - for(i = 0; i < numberof(ossl_ssl_attr_readers); i++) - rb_attr(cSSLSocket, rb_intern(ossl_ssl_attr_readers[i]), 1, 0, Qfalse); - for(i = 0; i < numberof(ossl_ssl_attrs); i++) - rb_attr(cSSLSocket, rb_intern(ossl_ssl_attrs[i]), 1, 1, Qfalse); - rb_define_alias(cSSLSocket, "to_io", "io"); rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1); + rb_undef_method(cSSLSocket, "initialize_copy"); rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0); - rb_define_method(cSSLSocket, "connect_nonblock", ossl_ssl_connect_nonblock, 0); + rb_define_method(cSSLSocket, "connect_nonblock", ossl_ssl_connect_nonblock, -1); rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0); - rb_define_method(cSSLSocket, "accept_nonblock", ossl_ssl_accept_nonblock, 0); + rb_define_method(cSSLSocket, "accept_nonblock", ossl_ssl_accept_nonblock, -1); rb_define_method(cSSLSocket, "sysread", ossl_ssl_read, -1); rb_define_private_method(cSSLSocket, "sysread_nonblock", ossl_ssl_read_nonblock, -1); rb_define_method(cSSLSocket, "syswrite", ossl_ssl_write, 1); rb_define_private_method(cSSLSocket, "syswrite_nonblock", ossl_ssl_write_nonblock, -1); - rb_define_method(cSSLSocket, "sysclose", ossl_ssl_close, 0); + rb_define_private_method(cSSLSocket, "stop", ossl_ssl_stop, 0); rb_define_method(cSSLSocket, "cert", ossl_ssl_get_cert, 0); rb_define_method(cSSLSocket, "peer_cert", ossl_ssl_get_peer_cert, 0); rb_define_method(cSSLSocket, "peer_cert_chain", ossl_ssl_get_peer_cert_chain, 0); @@ -2238,65 +3126,179 @@ Init_ossl_ssl(void) rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1); rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0); rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0); -# ifdef HAVE_OPENSSL_NPN_NEGOTIATED + /* #hostname is defined in lib/openssl/ssl.rb */ + rb_define_method(cSSLSocket, "hostname=", ossl_ssl_set_hostname, 1); + rb_define_method(cSSLSocket, "finished_message", ossl_ssl_get_finished, 0); + rb_define_method(cSSLSocket, "peer_finished_message", ossl_ssl_get_peer_finished, 0); + rb_define_method(cSSLSocket, "tmp_key", ossl_ssl_tmp_key, 0); + rb_define_method(cSSLSocket, "alpn_protocol", ossl_ssl_alpn_protocol, 0); + rb_define_method(cSSLSocket, "export_keying_material", ossl_ssl_export_keying_material, -1); +# ifdef OSSL_USE_NEXTPROTONEG rb_define_method(cSSLSocket, "npn_protocol", ossl_ssl_npn_protocol, 0); # endif +#ifdef HAVE_SSL_GET0_PEER_SIGNATURE_NAME + rb_define_method(cSSLSocket, "sigalg", ossl_ssl_get_sigalg, 0); + rb_define_method(cSSLSocket, "peer_sigalg", ossl_ssl_get_peer_sigalg, 0); +#endif +#ifdef HAVE_SSL_GET0_GROUP_NAME + rb_define_method(cSSLSocket, "group", ossl_ssl_get_group, 0); #endif -#define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, INT2NUM(SSL_##x)) + rb_define_const(mSSL, "VERIFY_NONE", INT2NUM(SSL_VERIFY_NONE)); + rb_define_const(mSSL, "VERIFY_PEER", INT2NUM(SSL_VERIFY_PEER)); + rb_define_const(mSSL, "VERIFY_FAIL_IF_NO_PEER_CERT", INT2NUM(SSL_VERIFY_FAIL_IF_NO_PEER_CERT)); + rb_define_const(mSSL, "VERIFY_CLIENT_ONCE", INT2NUM(SSL_VERIFY_CLIENT_ONCE)); - ossl_ssl_def_const(VERIFY_NONE); - ossl_ssl_def_const(VERIFY_PEER); - ossl_ssl_def_const(VERIFY_FAIL_IF_NO_PEER_CERT); - ossl_ssl_def_const(VERIFY_CLIENT_ONCE); - /* Introduce constants included in OP_ALL. These constants are mostly for - * unset some bits in OP_ALL such as; - * ctx.options = OP_ALL & ~OP_DONT_INSERT_EMPTY_FRAGMENTS - */ - ossl_ssl_def_const(OP_MICROSOFT_SESS_ID_BUG); - ossl_ssl_def_const(OP_NETSCAPE_CHALLENGE_BUG); - ossl_ssl_def_const(OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG); - ossl_ssl_def_const(OP_SSLREF2_REUSE_CERT_TYPE_BUG); - ossl_ssl_def_const(OP_MICROSOFT_BIG_SSLV3_BUFFER); -#if defined(SSL_OP_MSIE_SSLV2_RSA_PADDING) - ossl_ssl_def_const(OP_MSIE_SSLV2_RSA_PADDING); + rb_define_const(mSSL, "OP_ALL", ULONG2NUM(SSL_OP_ALL)); +#ifdef SSL_OP_CLEANSE_PLAINTEXT /* OpenSSL 3.0 */ + rb_define_const(mSSL, "OP_CLEANSE_PLAINTEXT", ULONG2NUM(SSL_OP_CLEANSE_PLAINTEXT)); +#endif + rb_define_const(mSSL, "OP_LEGACY_SERVER_CONNECT", ULONG2NUM(SSL_OP_LEGACY_SERVER_CONNECT)); +#ifdef SSL_OP_ENABLE_KTLS /* OpenSSL 3.0 */ + rb_define_const(mSSL, "OP_ENABLE_KTLS", ULONG2NUM(SSL_OP_ENABLE_KTLS)); +#endif + rb_define_const(mSSL, "OP_TLSEXT_PADDING", ULONG2NUM(SSL_OP_TLSEXT_PADDING)); + rb_define_const(mSSL, "OP_SAFARI_ECDHE_ECDSA_BUG", ULONG2NUM(SSL_OP_SAFARI_ECDHE_ECDSA_BUG)); +#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF /* OpenSSL 3.0 */ + rb_define_const(mSSL, "OP_IGNORE_UNEXPECTED_EOF", ULONG2NUM(SSL_OP_IGNORE_UNEXPECTED_EOF)); #endif - ossl_ssl_def_const(OP_SSLEAY_080_CLIENT_DH_BUG); - ossl_ssl_def_const(OP_TLS_D5_BUG); - ossl_ssl_def_const(OP_TLS_BLOCK_PADDING_BUG); - ossl_ssl_def_const(OP_DONT_INSERT_EMPTY_FRAGMENTS); - ossl_ssl_def_const(OP_ALL); -#if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION) - ossl_ssl_def_const(OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); +#ifdef SSL_OP_ALLOW_CLIENT_RENEGOTIATION /* OpenSSL 3.0 */ + rb_define_const(mSSL, "OP_ALLOW_CLIENT_RENEGOTIATION", ULONG2NUM(SSL_OP_ALLOW_CLIENT_RENEGOTIATION)); #endif -#if defined(SSL_OP_SINGLE_ECDH_USE) - ossl_ssl_def_const(OP_SINGLE_ECDH_USE); +#ifdef SSL_OP_DISABLE_TLSEXT_CA_NAMES /* OpenSSL 3.0 */ + rb_define_const(mSSL, "OP_DISABLE_TLSEXT_CA_NAMES", ULONG2NUM(SSL_OP_DISABLE_TLSEXT_CA_NAMES)); #endif - ossl_ssl_def_const(OP_SINGLE_DH_USE); - ossl_ssl_def_const(OP_EPHEMERAL_RSA); -#if defined(SSL_OP_CIPHER_SERVER_PREFERENCE) - ossl_ssl_def_const(OP_CIPHER_SERVER_PREFERENCE); +#ifdef SSL_OP_ALLOW_NO_DHE_KEX /* OpenSSL 1.1.1, missing in LibreSSL */ + rb_define_const(mSSL, "OP_ALLOW_NO_DHE_KEX", ULONG2NUM(SSL_OP_ALLOW_NO_DHE_KEX)); #endif - ossl_ssl_def_const(OP_TLS_ROLLBACK_BUG); - ossl_ssl_def_const(OP_NO_SSLv2); - ossl_ssl_def_const(OP_NO_SSLv3); - ossl_ssl_def_const(OP_NO_TLSv1); -#if defined(SSL_OP_NO_TLSv1_1) - ossl_ssl_def_const(OP_NO_TLSv1_1); + rb_define_const(mSSL, "OP_DONT_INSERT_EMPTY_FRAGMENTS", ULONG2NUM(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)); + rb_define_const(mSSL, "OP_NO_TICKET", ULONG2NUM(SSL_OP_NO_TICKET)); + rb_define_const(mSSL, "OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)); + rb_define_const(mSSL, "OP_NO_COMPRESSION", ULONG2NUM(SSL_OP_NO_COMPRESSION)); + rb_define_const(mSSL, "OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION", ULONG2NUM(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)); +#ifdef SSL_OP_NO_ENCRYPT_THEN_MAC /* OpenSSL 1.1.1, missing in LibreSSL */ + rb_define_const(mSSL, "OP_NO_ENCRYPT_THEN_MAC", ULONG2NUM(SSL_OP_NO_ENCRYPT_THEN_MAC)); #endif -#if defined(SSL_OP_NO_TLSv1_2) - ossl_ssl_def_const(OP_NO_TLSv1_2); +#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT /* OpenSSL 1.1.1, missing in LibreSSL */ + rb_define_const(mSSL, "OP_ENABLE_MIDDLEBOX_COMPAT", ULONG2NUM(SSL_OP_ENABLE_MIDDLEBOX_COMPAT)); #endif -#if defined(SSL_OP_NO_TICKET) - ossl_ssl_def_const(OP_NO_TICKET); +#ifdef SSL_OP_PRIORITIZE_CHACHA /* OpenSSL 1.1.1, missing in LibreSSL */ + rb_define_const(mSSL, "OP_PRIORITIZE_CHACHA", ULONG2NUM(SSL_OP_PRIORITIZE_CHACHA)); #endif -#if defined(SSL_OP_NO_COMPRESSION) - ossl_ssl_def_const(OP_NO_COMPRESSION); +#ifdef SSL_OP_NO_ANTI_REPLAY /* OpenSSL 1.1.1, missing in LibreSSL */ + rb_define_const(mSSL, "OP_NO_ANTI_REPLAY", ULONG2NUM(SSL_OP_NO_ANTI_REPLAY)); #endif - ossl_ssl_def_const(OP_PKCS1_CHECK_1); - ossl_ssl_def_const(OP_PKCS1_CHECK_2); - ossl_ssl_def_const(OP_NETSCAPE_CA_DN_BUG); - ossl_ssl_def_const(OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG); + rb_define_const(mSSL, "OP_NO_SSLv3", ULONG2NUM(SSL_OP_NO_SSLv3)); + rb_define_const(mSSL, "OP_NO_TLSv1", ULONG2NUM(SSL_OP_NO_TLSv1)); + rb_define_const(mSSL, "OP_NO_TLSv1_1", ULONG2NUM(SSL_OP_NO_TLSv1_1)); + rb_define_const(mSSL, "OP_NO_TLSv1_2", ULONG2NUM(SSL_OP_NO_TLSv1_2)); + rb_define_const(mSSL, "OP_NO_TLSv1_3", ULONG2NUM(SSL_OP_NO_TLSv1_3)); + rb_define_const(mSSL, "OP_CIPHER_SERVER_PREFERENCE", ULONG2NUM(SSL_OP_CIPHER_SERVER_PREFERENCE)); + rb_define_const(mSSL, "OP_TLS_ROLLBACK_BUG", ULONG2NUM(SSL_OP_TLS_ROLLBACK_BUG)); +#ifdef SSL_OP_NO_RENEGOTIATION /* OpenSSL 1.1.1, missing in LibreSSL */ + rb_define_const(mSSL, "OP_NO_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_RENEGOTIATION)); +#endif + rb_define_const(mSSL, "OP_CRYPTOPRO_TLSEXT_BUG", ULONG2NUM(SSL_OP_CRYPTOPRO_TLSEXT_BUG)); - sym_exception = ID2SYM(rb_intern("exception")); + /* SSL_OP_* flags for DTLS */ +#if 0 + rb_define_const(mSSL, "OP_NO_QUERY_MTU", ULONG2NUM(SSL_OP_NO_QUERY_MTU)); + rb_define_const(mSSL, "OP_COOKIE_EXCHANGE", ULONG2NUM(SSL_OP_COOKIE_EXCHANGE)); + rb_define_const(mSSL, "OP_CISCO_ANYCONNECT", ULONG2NUM(SSL_OP_CISCO_ANYCONNECT)); +#endif + + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_MICROSOFT_SESS_ID_BUG", ULONG2NUM(SSL_OP_MICROSOFT_SESS_ID_BUG)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_NETSCAPE_CHALLENGE_BUG", ULONG2NUM(SSL_OP_NETSCAPE_CHALLENGE_BUG)); + /* Deprecated in OpenSSL 0.9.8q and 1.0.0c. */ + rb_define_const(mSSL, "OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG", ULONG2NUM(SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG)); + /* Deprecated in OpenSSL 1.0.1h and 1.0.2. */ + rb_define_const(mSSL, "OP_SSLREF2_REUSE_CERT_TYPE_BUG", ULONG2NUM(SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_MICROSOFT_BIG_SSLV3_BUFFER", ULONG2NUM(SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)); + /* Deprecated in OpenSSL 0.9.7h and 0.9.8b. */ + rb_define_const(mSSL, "OP_MSIE_SSLV2_RSA_PADDING", ULONG2NUM(SSL_OP_MSIE_SSLV2_RSA_PADDING)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_SSLEAY_080_CLIENT_DH_BUG", ULONG2NUM(SSL_OP_SSLEAY_080_CLIENT_DH_BUG)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_TLS_D5_BUG", ULONG2NUM(SSL_OP_TLS_D5_BUG)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_TLS_BLOCK_PADDING_BUG", ULONG2NUM(SSL_OP_TLS_BLOCK_PADDING_BUG)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_SINGLE_ECDH_USE", ULONG2NUM(SSL_OP_SINGLE_ECDH_USE)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_SINGLE_DH_USE", ULONG2NUM(SSL_OP_SINGLE_DH_USE)); + /* Deprecated in OpenSSL 1.0.1k and 1.0.2. */ + rb_define_const(mSSL, "OP_EPHEMERAL_RSA", ULONG2NUM(SSL_OP_EPHEMERAL_RSA)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_NO_SSLv2", ULONG2NUM(SSL_OP_NO_SSLv2)); + /* Deprecated in OpenSSL 1.0.1. */ + rb_define_const(mSSL, "OP_PKCS1_CHECK_1", ULONG2NUM(SSL_OP_PKCS1_CHECK_1)); + /* Deprecated in OpenSSL 1.0.1. */ + rb_define_const(mSSL, "OP_PKCS1_CHECK_2", ULONG2NUM(SSL_OP_PKCS1_CHECK_2)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_NETSCAPE_CA_DN_BUG", ULONG2NUM(SSL_OP_NETSCAPE_CA_DN_BUG)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG", ULONG2NUM(SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG)); + + + /* + * SSL/TLS version constants. Used by SSLContext#min_version= and + * #max_version= + */ + /* SSL 2.0 */ + rb_define_const(mSSL, "SSL2_VERSION", INT2NUM(SSL2_VERSION)); + /* SSL 3.0 */ + rb_define_const(mSSL, "SSL3_VERSION", INT2NUM(SSL3_VERSION)); + /* TLS 1.0 */ + rb_define_const(mSSL, "TLS1_VERSION", INT2NUM(TLS1_VERSION)); + /* TLS 1.1 */ + rb_define_const(mSSL, "TLS1_1_VERSION", INT2NUM(TLS1_1_VERSION)); + /* TLS 1.2 */ + rb_define_const(mSSL, "TLS1_2_VERSION", INT2NUM(TLS1_2_VERSION)); + /* TLS 1.3 */ + rb_define_const(mSSL, "TLS1_3_VERSION", INT2NUM(TLS1_3_VERSION)); + + + sym_exception = ID2SYM(rb_intern_const("exception")); + sym_wait_readable = ID2SYM(rb_intern_const("wait_readable")); + sym_wait_writable = ID2SYM(rb_intern_const("wait_writable")); + + id_npn_protocols_encoded = rb_intern_const("npn_protocols_encoded"); + id_each = rb_intern_const("each"); + +#define DefIVarID(name) do \ + id_i_##name = rb_intern_const("@"#name); while (0) + + DefIVarID(cert_store); + DefIVarID(ca_file); + DefIVarID(ca_path); + DefIVarID(verify_mode); + DefIVarID(verify_depth); + DefIVarID(verify_callback); + DefIVarID(client_ca); + DefIVarID(renegotiation_cb); + DefIVarID(cert); + DefIVarID(key); + DefIVarID(extra_chain_cert); + DefIVarID(client_cert_cb); + DefIVarID(timeout); + DefIVarID(session_id_context); + DefIVarID(session_get_cb); + DefIVarID(session_new_cb); + DefIVarID(session_remove_cb); + DefIVarID(npn_select_cb); + DefIVarID(npn_protocols); + DefIVarID(alpn_protocols); + DefIVarID(alpn_select_cb); + DefIVarID(servername_cb); + DefIVarID(verify_hostname); + DefIVarID(keylog_cb); + DefIVarID(tmp_dh_callback); + + DefIVarID(io); + DefIVarID(context); + DefIVarID(hostname); +#endif /* !defined(OPENSSL_NO_SOCK) */ } diff --git a/ext/openssl/ossl_ssl.h b/ext/openssl/ossl_ssl.h index 0c20b10721..a87e62d450 100644 --- a/ext/openssl/ossl_ssl.h +++ b/ext/openssl/ossl_ssl.h @@ -1,42 +1,36 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(_OSSL_SSL_H_) #define _OSSL_SSL_H_ #define GetSSL(obj, ssl) do { \ - TypedData_Get_Struct((obj), SSL, &ossl_ssl_type, (ssl)); \ + TypedData_Get_Struct((obj), SSL, &ossl_ssl_type, (ssl)); \ + if (!(ssl)) { \ + ossl_raise(rb_eRuntimeError, "SSL is not initialized"); \ + } \ } while (0) #define GetSSLSession(obj, sess) do { \ - TypedData_Get_Struct((obj), SSL_SESSION, &ossl_ssl_session_type, (sess)); \ - if (!(sess)) { \ - ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \ - } \ -} while (0) - -#define SafeGetSSLSession(obj, sess) do { \ - OSSL_Check_Kind((obj), cSSLSession); \ - GetSSLSession((obj), (sess)); \ + TypedData_Get_Struct((obj), SSL_SESSION, &ossl_ssl_session_type, (sess)); \ + if (!(sess)) { \ + ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \ + } \ } while (0) extern const rb_data_type_t ossl_ssl_type; extern const rb_data_type_t ossl_ssl_session_type; extern VALUE mSSL; -extern VALUE eSSLError; extern VALUE cSSLSocket; -extern VALUE cSSLContext; extern VALUE cSSLSession; void Init_ossl_ssl(void); void Init_ossl_ssl_session(void); #endif /* _OSSL_SSL_H_ */ - diff --git a/ext/openssl/ossl_ssl_session.c b/ext/openssl/ossl_ssl_session.c index 5318f1a525..8a2fbf4100 100644 --- a/ext/openssl/ossl_ssl_session.c +++ b/ext/openssl/ossl_ssl_session.c @@ -4,6 +4,7 @@ #include "ossl.h" +#ifndef OPENSSL_NO_SOCK VALUE cSSLSession; static VALUE eSSLSession; @@ -16,217 +17,236 @@ ossl_ssl_session_free(void *ptr) const rb_data_type_t ossl_ssl_session_type = { "OpenSSL/SSL/Session", { - 0, ossl_ssl_session_free, + 0, ossl_ssl_session_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; static VALUE ossl_ssl_session_alloc(VALUE klass) { - return TypedData_Wrap_Struct(klass, &ossl_ssl_session_type, NULL); + return TypedData_Wrap_Struct(klass, &ossl_ssl_session_type, NULL); } /* * call-seq: - * Session.new(SSLSocket | string) => session + * Session.new(ssl_socket) -> Session + * Session.new(string) -> Session * - * === Parameters - * +SSLSocket+ is an OpenSSL::SSL::SSLSocket - * +string+ must be a DER or PEM encoded Session. -*/ -static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1) + * Creates a new Session object from an instance of SSLSocket or DER/PEM encoded + * String. + */ +static VALUE +ossl_ssl_session_initialize(VALUE self, VALUE arg1) { - SSL_SESSION *ctx = NULL; + SSL_SESSION *ctx; + + if (RTYPEDDATA_DATA(self)) + ossl_raise(eSSLSession, "SSL Session already initialized"); - if (RDATA(self)->data) - ossl_raise(eSSLSession, "SSL Session already initialized"); + if (rb_obj_is_instance_of(arg1, cSSLSocket)) { + SSL *ssl; - if (rb_obj_is_instance_of(arg1, cSSLSocket)) { - SSL *ssl; + GetSSL(arg1, ssl); - GetSSL(arg1, ssl); + if ((ctx = SSL_get1_session(ssl)) == NULL) + ossl_raise(eSSLSession, "no session available"); + } + else { + BIO *in = ossl_obj2bio(&arg1); - if (!ssl || (ctx = SSL_get1_session(ssl)) == NULL) - ossl_raise(eSSLSession, "no session available"); - } else { - BIO *in = ossl_obj2bio(arg1); + ctx = d2i_SSL_SESSION_bio(in, NULL); + if (!ctx) { + OSSL_BIO_reset(in); + ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL); + } + BIO_free(in); + if (!ctx) + ossl_raise(rb_eArgError, "unknown type"); + } - ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL); + RTYPEDDATA_DATA(self) = ctx; - if (!ctx) { - OSSL_BIO_reset(in); - ctx = d2i_SSL_SESSION_bio(in, NULL); - } + return self; +} - BIO_free(in); +/* :nodoc: */ +static VALUE +ossl_ssl_session_initialize_copy(VALUE self, VALUE other) +{ + SSL_SESSION *sess, *sess_other, *sess_new; - if (!ctx) - ossl_raise(rb_eArgError, "unknown type"); - } + rb_check_frozen(self); + sess = RTYPEDDATA_DATA(self); /* XXX */ + GetSSLSession(other, sess_other); - /* should not happen */ - if (ctx == NULL) - ossl_raise(eSSLSession, "ctx not set - internal error"); + sess_new = ASN1_dup((i2d_of_void *)i2d_SSL_SESSION, (d2i_of_void *)d2i_SSL_SESSION, + (char *)sess_other); + if (!sess_new) + ossl_raise(eSSLSession, "ASN1_dup"); - RDATA(self)->data = ctx; + RTYPEDDATA_DATA(self) = sess_new; + SSL_SESSION_free(sess); - return self; + return self; } -#if HAVE_SSL_SESSION_CMP == 0 -int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b) +static int +ossl_SSL_SESSION_cmp(const SSL_SESSION *a, const SSL_SESSION *b) { - if (a->ssl_version != b->ssl_version || - a->session_id_length != b->session_id_length) - return 1; - return memcmp(a->session_id,b-> session_id, a->session_id_length); + unsigned int a_len; + const unsigned char *a_sid = SSL_SESSION_get_id(a, &a_len); + unsigned int b_len; + const unsigned char *b_sid = SSL_SESSION_get_id(b, &b_len); + + if (SSL_SESSION_get_protocol_version(a) != SSL_SESSION_get_protocol_version(b)) + return 1; + if (a_len != b_len) + return 1; + + return CRYPTO_memcmp(a_sid, b_sid, a_len); } -#endif /* * call-seq: - * session1 == session2 -> boolean + * session1 == session2 -> boolean * -*/ + * Returns +true+ if the two Session is the same, +false+ if not. + */ static VALUE ossl_ssl_session_eq(VALUE val1, VALUE val2) { - SSL_SESSION *ctx1, *ctx2; + SSL_SESSION *ctx1, *ctx2; - GetSSLSession(val1, ctx1); - SafeGetSSLSession(val2, ctx2); + GetSSLSession(val1, ctx1); + GetSSLSession(val2, ctx2); - switch (SSL_SESSION_cmp(ctx1, ctx2)) { - case 0: return Qtrue; - default: return Qfalse; - } + switch (ossl_SSL_SESSION_cmp(ctx1, ctx2)) { + case 0: return Qtrue; + default: return Qfalse; + } } /* * call-seq: * session.time -> Time * - * Gets start time of the session. - * -*/ -static VALUE ossl_ssl_session_get_time(VALUE self) + * Returns the time at which the session was established. + */ +static VALUE +ossl_ssl_session_get_time(VALUE self) { - SSL_SESSION *ctx; - time_t t; - - GetSSLSession(self, ctx); - - t = SSL_SESSION_get_time(ctx); + SSL_SESSION *ctx; + long t; - if (t == 0) - return Qnil; + GetSSLSession(self, ctx); + t = SSL_SESSION_get_time(ctx); + if (t == 0) + return Qnil; - return rb_funcall(rb_cTime, rb_intern("at"), 1, TIMET2NUM(t)); + return rb_funcall(rb_cTime, rb_intern("at"), 1, LONG2NUM(t)); } /* * call-seq: - * session.timeout -> integer + * session.timeout -> Integer * - * Gets how long until the session expires in seconds. + * Returns the timeout value set for the session, in seconds from the + * established time. * -*/ -static VALUE ossl_ssl_session_get_timeout(VALUE self) + */ +static VALUE +ossl_ssl_session_get_timeout(VALUE self) { - SSL_SESSION *ctx; - time_t t; - - GetSSLSession(self, ctx); + SSL_SESSION *ctx; + long t; - t = SSL_SESSION_get_timeout(ctx); + GetSSLSession(self, ctx); + t = SSL_SESSION_get_timeout(ctx); - return TIMET2NUM(t); + return LONG2NUM(t); } /* * call-seq: - * session.time=(Time) -> Time - * session.time=(integer) -> Time + * session.time = time + * session.time = integer * * Sets start time of the session. Time resolution is in seconds. * -*/ + */ static VALUE ossl_ssl_session_set_time(VALUE self, VALUE time_v) { - SSL_SESSION *ctx; - long t; - - GetSSLSession(self, ctx); - if (rb_obj_is_instance_of(time_v, rb_cTime)) { - time_v = rb_funcall(time_v, rb_intern("to_i"), 0); - } - t = NUM2LONG(time_v); - SSL_SESSION_set_time(ctx, t); - return ossl_ssl_session_get_time(self); + SSL_SESSION *ctx; + long t; + + GetSSLSession(self, ctx); + if (rb_obj_is_instance_of(time_v, rb_cTime)) { + time_v = rb_funcall(time_v, rb_intern("to_i"), 0); + } + t = NUM2LONG(time_v); + SSL_SESSION_set_time(ctx, t); + return ossl_ssl_session_get_time(self); } /* * call-seq: - * session.timeout=(integer) -> integer + * session.timeout = integer * * Sets how long until the session expires in seconds. - * -*/ + */ static VALUE ossl_ssl_session_set_timeout(VALUE self, VALUE time_v) { - SSL_SESSION *ctx; - long t; + SSL_SESSION *ctx; + long t; - GetSSLSession(self, ctx); - t = NUM2LONG(time_v); - SSL_SESSION_set_timeout(ctx, t); - return ossl_ssl_session_get_timeout(self); + GetSSLSession(self, ctx); + t = NUM2LONG(time_v); + SSL_SESSION_set_timeout(ctx, t); + return ossl_ssl_session_get_timeout(self); } -#ifdef HAVE_SSL_SESSION_GET_ID /* * call-seq: - * session.id -> aString + * session.id -> String * * Returns the Session ID. -*/ + */ static VALUE ossl_ssl_session_get_id(VALUE self) { - SSL_SESSION *ctx; - const unsigned char *p = NULL; - unsigned int i = 0; + SSL_SESSION *ctx; + const unsigned char *p = NULL; + unsigned int i = 0; - GetSSLSession(self, ctx); + GetSSLSession(self, ctx); - p = SSL_SESSION_get_id(ctx, &i); + p = SSL_SESSION_get_id(ctx, &i); - return rb_str_new((const char *) p, i); + return rb_str_new((const char *) p, i); } -#endif /* * call-seq: - * session.to_der -> aString + * session.to_der -> String * * Returns an ASN1 encoded String that contains the Session object. -*/ + */ static VALUE ossl_ssl_session_to_der(VALUE self) { - SSL_SESSION *ctx; - unsigned char *p; - int len; - VALUE str; - - GetSSLSession(self, ctx); - len = i2d_SSL_SESSION(ctx, NULL); - if (len <= 0) { - ossl_raise(eSSLSession, "i2d_SSL_SESSION"); - } - - str = rb_str_new(0, len); - p = (unsigned char *)RSTRING_PTR(str); - i2d_SSL_SESSION(ctx, &p); - ossl_str_adjust(str, p); - return str; + SSL_SESSION *ctx; + unsigned char *p; + int len; + VALUE str; + + GetSSLSession(self, ctx); + len = i2d_SSL_SESSION(ctx, NULL); + if (len <= 0) { + ossl_raise(eSSLSession, "i2d_SSL_SESSION"); + } + + str = rb_str_new(0, len); + p = (unsigned char *)RSTRING_PTR(str); + i2d_SSL_SESSION(ctx, &p); + ossl_str_adjust(str, p); + return str; } /* @@ -234,31 +254,25 @@ static VALUE ossl_ssl_session_to_der(VALUE self) * session.to_pem -> String * * Returns a PEM encoded String that contains the Session object. -*/ + */ static VALUE ossl_ssl_session_to_pem(VALUE self) { - SSL_SESSION *ctx; - BIO *out; - BUF_MEM *buf; - VALUE str; - int i; + SSL_SESSION *ctx; + BIO *out; - GetSSLSession(self, ctx); + GetSSLSession(self, ctx); - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eSSLSession, "BIO_s_mem()"); - } + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eSSLSession, "BIO_s_mem()"); + } - if (!(i=PEM_write_bio_SSL_SESSION(out, ctx))) { - BIO_free(out); - ossl_raise(eSSLSession, "SSL_SESSION_print()"); - } + if (!PEM_write_bio_SSL_SESSION(out, ctx)) { + BIO_free(out); + ossl_raise(eSSLSession, "SSL_SESSION_print()"); + } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); - return str; + return ossl_membio2str(out); } @@ -266,59 +280,48 @@ static VALUE ossl_ssl_session_to_pem(VALUE self) * call-seq: * session.to_text -> String * - * Shows everything in the Session object. -*/ + * Shows everything in the Session object. This is for diagnostic purposes. + */ static VALUE ossl_ssl_session_to_text(VALUE self) { - SSL_SESSION *ctx; - BIO *out; - BUF_MEM *buf; - VALUE str; - - GetSSLSession(self, ctx); + SSL_SESSION *ctx; + BIO *out; - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eSSLSession, "BIO_s_mem()"); - } + GetSSLSession(self, ctx); - if (!SSL_SESSION_print(out, ctx)) { - BIO_free(out); - ossl_raise(eSSLSession, "SSL_SESSION_print()"); - } + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eSSLSession, "BIO_s_mem()"); + } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); + if (!SSL_SESSION_print(out, ctx)) { + BIO_free(out); + ossl_raise(eSSLSession, "SSL_SESSION_print()"); + } - return str; + return ossl_membio2str(out); } +#endif /* !defined(OPENSSL_NO_SOCK) */ void Init_ossl_ssl_session(void) { -#if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ - mSSL = rb_define_module_under(mOSSL, "SSL"); -#endif - cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject); - eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError); - - rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc); - rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1); - - rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1); - - rb_define_method(cSSLSession, "time", ossl_ssl_session_get_time, 0); - rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1); - rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0); - rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1); - -#ifdef HAVE_SSL_SESSION_GET_ID - rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0); -#else - rb_undef_method(cSSLSession, "id"); -#endif - rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0); - rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0); - rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0); +#ifndef OPENSSL_NO_SOCK + cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject); + eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError); + + rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc); + rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1); + rb_define_method(cSSLSession, "initialize_copy", ossl_ssl_session_initialize_copy, 1); + + rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1); + + rb_define_method(cSSLSession, "time", ossl_ssl_session_get_time, 0); + rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1); + rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0); + rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1); + rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0); + rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0); + rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0); + rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0); +#endif /* !defined(OPENSSL_NO_SOCK) */ } diff --git a/ext/openssl/ossl_ts.c b/ext/openssl/ossl_ts.c new file mode 100644 index 0000000000..b31a854a63 --- /dev/null +++ b/ext/openssl/ossl_ts.c @@ -0,0 +1,1551 @@ +/* + * + * Copyright (C) 2010 Martin Bosslet <Martin.Bosslet@googlemail.com> + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'COPYING'.) + */ +#include "ossl.h" + +#ifndef OPENSSL_NO_TS + +#define NewTSRequest(klass) \ + TypedData_Wrap_Struct((klass), &ossl_ts_req_type, 0) +#define SetTSRequest(obj, req) do { \ + if (!(req)) { \ + ossl_raise(rb_eRuntimeError, "TS_REQ wasn't initialized."); \ + } \ + RTYPEDDATA_DATA(obj) = (req); \ +} while (0) +#define GetTSRequest(obj, req) do { \ + TypedData_Get_Struct((obj), TS_REQ, &ossl_ts_req_type, (req)); \ + if (!(req)) { \ + ossl_raise(rb_eRuntimeError, "TS_REQ wasn't initialized."); \ + } \ +} while (0) + +#define NewTSResponse(klass) \ + TypedData_Wrap_Struct((klass), &ossl_ts_resp_type, 0) +#define SetTSResponse(obj, resp) do { \ + if (!(resp)) { \ + ossl_raise(rb_eRuntimeError, "TS_RESP wasn't initialized."); \ + } \ + RTYPEDDATA_DATA(obj) = (resp); \ +} while (0) +#define GetTSResponse(obj, resp) do { \ + TypedData_Get_Struct((obj), TS_RESP, &ossl_ts_resp_type, (resp)); \ + if (!(resp)) { \ + ossl_raise(rb_eRuntimeError, "TS_RESP wasn't initialized."); \ + } \ +} while (0) + +#define NewTSTokenInfo(klass) \ + TypedData_Wrap_Struct((klass), &ossl_ts_token_info_type, 0) +#define SetTSTokenInfo(obj, info) do { \ + if (!(info)) { \ + ossl_raise(rb_eRuntimeError, "TS_TST_INFO wasn't initialized."); \ + } \ + RTYPEDDATA_DATA(obj) = (info); \ +} while (0) +#define GetTSTokenInfo(obj, info) do { \ + TypedData_Get_Struct((obj), TS_TST_INFO, &ossl_ts_token_info_type, (info)); \ + if (!(info)) { \ + ossl_raise(rb_eRuntimeError, "TS_TST_INFO wasn't initialized."); \ + } \ +} while (0) + +#define ossl_tsfac_get_default_policy_id(o) rb_attr_get((o),rb_intern("@default_policy_id")) +#define ossl_tsfac_get_serial_number(o) rb_attr_get((o),rb_intern("@serial_number")) +#define ossl_tsfac_get_gen_time(o) rb_attr_get((o),rb_intern("@gen_time")) +#define ossl_tsfac_get_additional_certs(o) rb_attr_get((o),rb_intern("@additional_certs")) +#define ossl_tsfac_get_allowed_digests(o) rb_attr_get((o),rb_intern("@allowed_digests")) + +static VALUE mTimestamp; +static VALUE eTimestampError; +static VALUE cTimestampRequest; +static VALUE cTimestampResponse; +static VALUE cTimestampTokenInfo; +static VALUE cTimestampFactory; +static VALUE sBAD_ALG, sBAD_REQUEST, sBAD_DATA_FORMAT, sTIME_NOT_AVAILABLE; +static VALUE sUNACCEPTED_POLICY, sUNACCEPTED_EXTENSION, sADD_INFO_NOT_AVAILABLE; +static VALUE sSYSTEM_FAILURE; + +static void +ossl_ts_req_free(void *ptr) +{ + TS_REQ_free(ptr); +} + +static const rb_data_type_t ossl_ts_req_type = { + "OpenSSL/Timestamp/Request", + { + 0, ossl_ts_req_free, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, +}; + +static void +ossl_ts_resp_free(void *ptr) +{ + TS_RESP_free(ptr); +} + +static const rb_data_type_t ossl_ts_resp_type = { + "OpenSSL/Timestamp/Response", + { + 0, ossl_ts_resp_free, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, +}; + +static void +ossl_ts_token_info_free(void *ptr) +{ + TS_TST_INFO_free(ptr); +} + +static const rb_data_type_t ossl_ts_token_info_type = { + "OpenSSL/Timestamp/TokenInfo", + { + 0, ossl_ts_token_info_free, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, +}; + +static VALUE +asn1_to_der(void *template, int (*i2d)(void *template, unsigned char **pp)) +{ + VALUE str; + int len; + unsigned char *p; + + if((len = i2d(template, NULL)) <= 0) + ossl_raise(eTimestampError, "Error when encoding to DER"); + str = rb_str_new(0, len); + p = (unsigned char *)RSTRING_PTR(str); + if(i2d(template, &p) <= 0) + ossl_raise(eTimestampError, "Error when encoding to DER"); + rb_str_set_len(str, p - (unsigned char*)RSTRING_PTR(str)); + + return str; +} + +static VALUE +obj_to_asn1obj_i(VALUE obj) +{ + return (VALUE)ossl_to_asn1obj(obj); +} + +static VALUE +ossl_ts_req_alloc(VALUE klass) +{ + TS_REQ *req; + VALUE obj; + + obj = NewTSRequest(klass); + if (!(req = TS_REQ_new())) + ossl_raise(eTimestampError, NULL); + SetTSRequest(obj, req); + + /* Defaults */ + TS_REQ_set_version(req, 1); + TS_REQ_set_cert_req(req, 1); + + return obj; +} + +/* + * When creating a Request with the +File+ or +string+ parameter, the + * corresponding +File+ or +string+ must be DER-encoded. + * + * call-seq: + * OpenSSL::Timestamp::Request.new(file) -> request + * OpenSSL::Timestamp::Request.new(string) -> request + * OpenSSL::Timestamp::Request.new -> empty request + */ +static VALUE +ossl_ts_req_initialize(int argc, VALUE *argv, VALUE self) +{ + TS_REQ *ts_req = DATA_PTR(self); + BIO *in; + VALUE arg; + + if(rb_scan_args(argc, argv, "01", &arg) == 0) { + return self; + } + + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(&arg); + ts_req = d2i_TS_REQ_bio(in, &ts_req); + BIO_free(in); + if (!ts_req) { + DATA_PTR(self) = NULL; + ossl_raise(eTimestampError, "Error when decoding the timestamp request"); + } + DATA_PTR(self) = ts_req; + + return self; +} + +/* + * Returns the 'short name' of the object identifier that represents the + * algorithm that was used to create the message imprint digest. + * + * call-seq: + * request.algorithm -> string + */ +static VALUE +ossl_ts_req_get_algorithm(VALUE self) +{ + TS_REQ *req; + TS_MSG_IMPRINT *mi; + X509_ALGOR *algor; + const ASN1_OBJECT *obj; + + GetTSRequest(self, req); + mi = TS_REQ_get_msg_imprint(req); + algor = TS_MSG_IMPRINT_get_algo(mi); + X509_ALGOR_get0(&obj, NULL, NULL, algor); + return ossl_asn1obj_to_string(obj); +} + +/* + * Allows to set the object identifier or the 'short name' of the + * algorithm that was used to create the message imprint digest. + * + * ===Example: + * request.algorithm = "SHA1" + * + * call-seq: + * request.algorithm = "string" -> string + */ +static VALUE +ossl_ts_req_set_algorithm(VALUE self, VALUE algo) +{ + TS_REQ *req; + TS_MSG_IMPRINT *mi; + ASN1_OBJECT *obj; + X509_ALGOR *algor; + + GetTSRequest(self, req); + obj = ossl_to_asn1obj(algo); + mi = TS_REQ_get_msg_imprint(req); + algor = TS_MSG_IMPRINT_get_algo(mi); + if (!X509_ALGOR_set0(algor, obj, V_ASN1_NULL, NULL)) { + ASN1_OBJECT_free(obj); + ossl_raise(eTimestampError, "X509_ALGOR_set0"); + } + + return algo; +} + +/* + * Returns the message imprint (digest) of the data to be timestamped. + * + * call-seq: + * request.message_imprint -> string or nil + */ +static VALUE +ossl_ts_req_get_msg_imprint(VALUE self) +{ + TS_REQ *req; + TS_MSG_IMPRINT *mi; + ASN1_OCTET_STRING *hashed_msg; + VALUE ret; + + GetTSRequest(self, req); + mi = TS_REQ_get_msg_imprint(req); + hashed_msg = TS_MSG_IMPRINT_get_msg(mi); + + ret = asn1str_to_str(hashed_msg); + + return ret; +} + +/* + * Set the message imprint digest. + * + * call-seq: + * request.message_imprint = "string" -> string + */ +static VALUE +ossl_ts_req_set_msg_imprint(VALUE self, VALUE hash) +{ + TS_REQ *req; + TS_MSG_IMPRINT *mi; + StringValue(hash); + + GetTSRequest(self, req); + mi = TS_REQ_get_msg_imprint(req); + if (!TS_MSG_IMPRINT_set_msg(mi, (unsigned char *)RSTRING_PTR(hash), RSTRING_LENINT(hash))) + ossl_raise(eTimestampError, "TS_MSG_IMPRINT_set_msg"); + + return hash; +} + +/* + * Returns the version of this request. +1+ is the default value. + * + * call-seq: + * request.version -> Integer + */ +static VALUE +ossl_ts_req_get_version(VALUE self) +{ + TS_REQ *req; + + GetTSRequest(self, req); + return LONG2NUM(TS_REQ_get_version(req)); +} + +/* + * Sets the version number for this Request. This should be +1+ for compliant + * servers. + * + * call-seq: + * request.version = number -> Integer + */ +static VALUE +ossl_ts_req_set_version(VALUE self, VALUE version) +{ + TS_REQ *req; + long ver; + + if ((ver = NUM2LONG(version)) < 0) + ossl_raise(eTimestampError, "version must be >= 0!"); + GetTSRequest(self, req); + if (!TS_REQ_set_version(req, ver)) + ossl_raise(eTimestampError, "TS_REQ_set_version"); + + return version; +} + +/* + * Returns the 'short name' of the object identifier that represents the + * timestamp policy under which the server shall create the timestamp. + * + * call-seq: + * request.policy_id -> string or nil + */ +static VALUE +ossl_ts_req_get_policy_id(VALUE self) +{ + TS_REQ *req; + + GetTSRequest(self, req); + if (!TS_REQ_get_policy_id(req)) + return Qnil; + return ossl_asn1obj_to_string(TS_REQ_get_policy_id(req)); +} + +/* + * Allows to set the object identifier that represents the + * timestamp policy under which the server shall create the timestamp. This + * may be left +nil+, implying that the timestamp server will issue the + * timestamp using some default policy. + * + * ===Example: + * request.policy_id = "1.2.3.4.5" + * + * call-seq: + * request.policy_id = "string" -> string + */ +static VALUE +ossl_ts_req_set_policy_id(VALUE self, VALUE oid) +{ + TS_REQ *req; + ASN1_OBJECT *obj; + int ok; + + GetTSRequest(self, req); + obj = ossl_to_asn1obj(oid); + ok = TS_REQ_set_policy_id(req, obj); + ASN1_OBJECT_free(obj); + if (!ok) + ossl_raise(eTimestampError, "TS_REQ_set_policy_id"); + + return oid; +} + +/* + * Returns the nonce (number used once) that the server shall include in its + * response. + * + * call-seq: + * request.nonce -> BN or nil + */ +static VALUE +ossl_ts_req_get_nonce(VALUE self) +{ + TS_REQ *req; + const ASN1_INTEGER * nonce; + + GetTSRequest(self, req); + if (!(nonce = TS_REQ_get_nonce(req))) + return Qnil; + return asn1integer_to_num(nonce); +} + +/* + * Sets the nonce (number used once) that the server shall include in its + * response. If the nonce is set, the server must return the same nonce value in + * a valid Response. + * + * call-seq: + * request.nonce = number -> BN + */ +static VALUE +ossl_ts_req_set_nonce(VALUE self, VALUE num) +{ + TS_REQ *req; + ASN1_INTEGER *nonce; + int ok; + + GetTSRequest(self, req); + nonce = num_to_asn1integer(num, NULL); + ok = TS_REQ_set_nonce(req, nonce); + ASN1_INTEGER_free(nonce); + if (!ok) + ossl_raise(eTimestampError, NULL); + return num; +} + +/* + * Indicates whether the response shall contain the timestamp authority's + * certificate or not. + * + * call-seq: + * request.cert_requested? -> true or false + */ +static VALUE +ossl_ts_req_get_cert_requested(VALUE self) +{ + TS_REQ *req; + + GetTSRequest(self, req); + return TS_REQ_get_cert_req(req) ? Qtrue: Qfalse; +} + +/* + * Specify whether the response shall contain the timestamp authority's + * certificate or not. The default value is +true+. + * + * call-seq: + * request.cert_requested = boolean -> true or false + */ +static VALUE +ossl_ts_req_set_cert_requested(VALUE self, VALUE requested) +{ + TS_REQ *req; + + GetTSRequest(self, req); + TS_REQ_set_cert_req(req, RTEST(requested)); + + return requested; +} + +/* + * DER-encodes this Request. + * + * call-seq: + * request.to_der -> DER-encoded string + */ +static VALUE +ossl_ts_req_to_der(VALUE self) +{ + TS_REQ *req; + TS_MSG_IMPRINT *mi; + X509_ALGOR *algo; + const ASN1_OBJECT *obj; + ASN1_OCTET_STRING *hashed_msg; + + GetTSRequest(self, req); + mi = TS_REQ_get_msg_imprint(req); + + algo = TS_MSG_IMPRINT_get_algo(mi); + X509_ALGOR_get0(&obj, NULL, NULL, algo); + if (OBJ_obj2nid(obj) == NID_undef) + ossl_raise(eTimestampError, "Message imprint missing algorithm"); + + hashed_msg = TS_MSG_IMPRINT_get_msg(mi); + if (!ASN1_STRING_length(hashed_msg)) + ossl_raise(eTimestampError, "Message imprint missing hashed message"); + + return asn1_to_der((void *)req, (int (*)(void *, unsigned char **))i2d_TS_REQ); +} + +static VALUE +ossl_ts_req_to_text(VALUE self) +{ + TS_REQ *req; + BIO *out; + + GetTSRequest(self, req); + + out = BIO_new(BIO_s_mem()); + if (!out) ossl_raise(eTimestampError, NULL); + + if (!TS_REQ_print_bio(out, req)) { + BIO_free(out); + ossl_raise(eTimestampError, NULL); + } + + return ossl_membio2str(out); +} + +static VALUE +ossl_ts_resp_alloc(VALUE klass) +{ + TS_RESP *resp; + VALUE obj; + + obj = NewTSResponse(klass); + if (!(resp = TS_RESP_new())) + ossl_raise(eTimestampError, NULL); + SetTSResponse(obj, resp); + + return obj; +} + +/* + * Creates a Response from a +File+ or +string+ parameter, the + * corresponding +File+ or +string+ must be DER-encoded. Please note + * that Response is an immutable read-only class. If you'd like to create + * timestamps please refer to Factory instead. + * + * call-seq: + * OpenSSL::Timestamp::Response.new(file) -> response + * OpenSSL::Timestamp::Response.new(string) -> response + */ +static VALUE +ossl_ts_resp_initialize(VALUE self, VALUE der) +{ + TS_RESP *ts_resp = DATA_PTR(self); + BIO *in; + + der = ossl_to_der_if_possible(der); + in = ossl_obj2bio(&der); + ts_resp = d2i_TS_RESP_bio(in, &ts_resp); + BIO_free(in); + if (!ts_resp) { + DATA_PTR(self) = NULL; + ossl_raise(eTimestampError, "Error when decoding the timestamp response"); + } + DATA_PTR(self) = ts_resp; + + return self; +} + +/* + * Returns one of GRANTED, GRANTED_WITH_MODS, REJECTION, WAITING, + * REVOCATION_WARNING or REVOCATION_NOTIFICATION. A timestamp token has + * been created only in case +status+ is equal to GRANTED or GRANTED_WITH_MODS. + * + * call-seq: + * response.status -> BN (never nil) + */ +static VALUE +ossl_ts_resp_get_status(VALUE self) +{ + TS_RESP *resp; + TS_STATUS_INFO *si; + const ASN1_INTEGER *st; + + GetTSResponse(self, resp); + si = TS_RESP_get_status_info(resp); + st = TS_STATUS_INFO_get0_status(si); + + return asn1integer_to_num(st); +} + +/* + * In cases no timestamp token has been created, this field contains further + * info about the reason why response creation failed. The method returns either + * nil (the request was successful and a timestamp token was created) or one of + * the following: + * * :BAD_ALG - Indicates that the timestamp server rejects the message + * imprint algorithm used in the Request + * * :BAD_REQUEST - Indicates that the timestamp server was not able to process + * the Request properly + * * :BAD_DATA_FORMAT - Indicates that the timestamp server was not able to + * parse certain data in the Request + * * :TIME_NOT_AVAILABLE - Indicates that the server could not access its time + * source + * * :UNACCEPTED_POLICY - Indicates that the requested policy identifier is not + * recognized or supported by the timestamp server + * * :UNACCEPTED_EXTENSIION - Indicates that an extension in the Request is + * not supported by the timestamp server + * * :ADD_INFO_NOT_AVAILABLE -Indicates that additional information requested + * is either not understood or currently not available + * * :SYSTEM_FAILURE - Timestamp creation failed due to an internal error that + * occurred on the timestamp server + * + * call-seq: + * response.failure_info -> nil or symbol + */ +static VALUE +ossl_ts_resp_get_failure_info(VALUE self) +{ + TS_RESP *resp; + TS_STATUS_INFO *si; + const ASN1_BIT_STRING *fi; + + GetTSResponse(self, resp); + si = TS_RESP_get_status_info(resp); + fi = TS_STATUS_INFO_get0_failure_info(si); + if (!fi) + return Qnil; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_ALG)) + return sBAD_ALG; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_REQUEST)) + return sBAD_REQUEST; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_DATA_FORMAT)) + return sBAD_DATA_FORMAT; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_TIME_NOT_AVAILABLE)) + return sTIME_NOT_AVAILABLE; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_POLICY)) + return sUNACCEPTED_POLICY; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_EXTENSION)) + return sUNACCEPTED_EXTENSION; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_ADD_INFO_NOT_AVAILABLE)) + return sADD_INFO_NOT_AVAILABLE; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_SYSTEM_FAILURE)) + return sSYSTEM_FAILURE; + + ossl_raise(eTimestampError, "Unrecognized failure info."); +} + +/* + * In cases of failure this field may contain an array of strings further + * describing the origin of the failure. + * + * call-seq: + * response.status_text -> Array of strings or nil + */ +static VALUE +ossl_ts_resp_get_status_text(VALUE self) +{ + TS_RESP *resp; + TS_STATUS_INFO *si; + const STACK_OF(ASN1_UTF8STRING) *text; + ASN1_UTF8STRING *current; + int i; + VALUE ret = rb_ary_new(); + + GetTSResponse(self, resp); + si = TS_RESP_get_status_info(resp); + if ((text = TS_STATUS_INFO_get0_text(si))) { + for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) { + current = sk_ASN1_UTF8STRING_value(text, i); + rb_ary_push(ret, asn1str_to_str(current)); + } + } + + return ret; +} + +/* + * If a timestamp token is present, this returns it in the form of a + * OpenSSL::PKCS7. + * + * call-seq: + * response.token -> nil or OpenSSL::PKCS7 + */ +static VALUE +ossl_ts_resp_get_token(VALUE self) +{ + TS_RESP *resp; + PKCS7 *p7; + + GetTSResponse(self, resp); + if (!(p7 = TS_RESP_get_token(resp))) + return Qnil; + return ossl_pkcs7_new(p7); +} + +/* + * Get the response's token info if present. + * + * call-seq: + * response.token_info -> nil or OpenSSL::Timestamp::TokenInfo + */ +static VALUE +ossl_ts_resp_get_token_info(VALUE self) +{ + TS_RESP *resp; + TS_TST_INFO *info, *copy; + VALUE obj; + + GetTSResponse(self, resp); + if (!(info = TS_RESP_get_tst_info(resp))) + return Qnil; + + obj = NewTSTokenInfo(cTimestampTokenInfo); + + if (!(copy = TS_TST_INFO_dup(info))) + ossl_raise(eTimestampError, NULL); + + SetTSTokenInfo(obj, copy); + + return obj; +} + +/* + * If the Request specified to request the TSA certificate + * (Request#cert_requested = true), then this field contains the + * certificate of the timestamp authority. + * + * call-seq: + * response.tsa_certificate -> OpenSSL::X509::Certificate or nil + */ +static VALUE +ossl_ts_resp_get_tsa_certificate(VALUE self) +{ + TS_RESP *resp; + PKCS7 *p7; + PKCS7_SIGNER_INFO *ts_info; + X509 *cert; + + GetTSResponse(self, resp); + if (!(p7 = TS_RESP_get_token(resp))) + return Qnil; + ts_info = sk_PKCS7_SIGNER_INFO_value(p7->d.sign->signer_info, 0); + cert = PKCS7_cert_from_signer_info(p7, ts_info); + if (!cert) + return Qnil; + return ossl_x509_new(cert); +} + +/* + * Returns the Response in DER-encoded form. + * + * call-seq: + * response.to_der -> string + */ +static VALUE +ossl_ts_resp_to_der(VALUE self) +{ + TS_RESP *resp; + + GetTSResponse(self, resp); + return asn1_to_der((void *)resp, (int (*)(void *, unsigned char **))i2d_TS_RESP); +} + +static VALUE +ossl_ts_resp_to_text(VALUE self) +{ + TS_RESP *resp; + BIO *out; + + GetTSResponse(self, resp); + + out = BIO_new(BIO_s_mem()); + if (!out) ossl_raise(eTimestampError, NULL); + + if (!TS_RESP_print_bio(out, resp)) { + BIO_free(out); + ossl_raise(eTimestampError, NULL); + } + + return ossl_membio2str(out); +} + +/* + * Verifies a timestamp token by checking the signature, validating the + * certificate chain implied by tsa_certificate and by checking conformance to + * a given Request. Mandatory parameters are the Request associated to this + * Response, and an OpenSSL::X509::Store of trusted roots. + * + * Intermediate certificates can optionally be supplied for creating the + * certificate chain. These intermediate certificates must all be + * instances of OpenSSL::X509::Certificate. + * + * If validation fails, several kinds of exceptions can be raised: + * * TypeError if types don't fit + * * TimestampError if something is wrong with the timestamp token itself, if + * it is not conformant to the Request, or if validation of the timestamp + * certificate chain fails. + * + * call-seq: + * response.verify(Request, root_store) -> Response + * response.verify(Request, root_store, [intermediate_cert]) -> Response + */ +static VALUE +ossl_ts_resp_verify(int argc, VALUE *argv, VALUE self) +{ + VALUE ts_req, store, intermediates; + TS_RESP *resp; + TS_REQ *req; + X509_STORE *x509st; + TS_VERIFY_CTX *ctx; + STACK_OF(X509) *x509inter = NULL; + PKCS7* p7; + X509 *cert; + int status, i, ok; + + rb_scan_args(argc, argv, "21", &ts_req, &store, &intermediates); + + GetTSResponse(self, resp); + GetTSRequest(ts_req, req); + x509st = GetX509StorePtr(store); + + if (!(ctx = TS_REQ_to_TS_VERIFY_CTX(req, NULL))) { + ossl_raise(eTimestampError, "Error when creating the verification context."); + } + + if (!NIL_P(intermediates)) { + x509inter = ossl_protect_x509_ary2sk(intermediates, &status); + if (status) { + TS_VERIFY_CTX_free(ctx); + rb_jump_tag(status); + } + } else if (!(x509inter = sk_X509_new_null())) { + TS_VERIFY_CTX_free(ctx); + ossl_raise(eTimestampError, "sk_X509_new_null"); + } + + if (!(p7 = TS_RESP_get_token(resp))) { + TS_VERIFY_CTX_free(ctx); + sk_X509_pop_free(x509inter, X509_free); + ossl_raise(eTimestampError, "TS_RESP_get_token"); + } + for (i=0; i < sk_X509_num(p7->d.sign->cert); i++) { + cert = sk_X509_value(p7->d.sign->cert, i); + if (!sk_X509_push(x509inter, cert)) { + sk_X509_pop_free(x509inter, X509_free); + TS_VERIFY_CTX_free(ctx); + ossl_raise(eTimestampError, "sk_X509_push"); + } + X509_up_ref(cert); + } + + if (!X509_STORE_up_ref(x509st)) { + sk_X509_pop_free(x509inter, X509_free); + TS_VERIFY_CTX_free(ctx); + ossl_raise(eTimestampError, "X509_STORE_up_ref"); + } + +#ifdef HAVE_TS_VERIFY_CTX_SET0_CERTS + TS_VERIFY_CTX_set0_certs(ctx, x509inter); + TS_VERIFY_CTX_set0_store(ctx, x509st); +#else +# if OSSL_OPENSSL_PREREQ(3, 0, 0) || OSSL_IS_LIBRESSL + TS_VERIFY_CTX_set_certs(ctx, x509inter); +# else + TS_VERIFY_CTS_set_certs(ctx, x509inter); +# endif + TS_VERIFY_CTX_set_store(ctx, x509st); +#endif + TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE); + + ok = TS_RESP_verify_response(ctx, resp); + TS_VERIFY_CTX_free(ctx); + + if (!ok) + ossl_raise(eTimestampError, "TS_RESP_verify_response"); + + return self; +} + +static VALUE +ossl_ts_token_info_alloc(VALUE klass) +{ + TS_TST_INFO *info; + VALUE obj; + + obj = NewTSTokenInfo(klass); + if (!(info = TS_TST_INFO_new())) + ossl_raise(eTimestampError, NULL); + SetTSTokenInfo(obj, info); + + return obj; +} + +/* + * Creates a TokenInfo from a +File+ or +string+ parameter, the + * corresponding +File+ or +string+ must be DER-encoded. Please note + * that TokenInfo is an immutable read-only class. If you'd like to create + * timestamps please refer to Factory instead. + * + * call-seq: + * OpenSSL::Timestamp::TokenInfo.new(file) -> token-info + * OpenSSL::Timestamp::TokenInfo.new(string) -> token-info + */ +static VALUE +ossl_ts_token_info_initialize(VALUE self, VALUE der) +{ + TS_TST_INFO *info = DATA_PTR(self); + BIO *in; + + der = ossl_to_der_if_possible(der); + in = ossl_obj2bio(&der); + info = d2i_TS_TST_INFO_bio(in, &info); + BIO_free(in); + if (!info) { + DATA_PTR(self) = NULL; + ossl_raise(eTimestampError, "Error when decoding the timestamp token info"); + } + DATA_PTR(self) = info; + + return self; +} + +/* + * Returns the version number of the token info. With compliant servers, + * this value should be +1+ if present. If status is GRANTED or + * GRANTED_WITH_MODS. + * + * call-seq: + * token_info.version -> Integer or nil + */ +static VALUE +ossl_ts_token_info_get_version(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return LONG2NUM(TS_TST_INFO_get_version(info)); +} + +/* + * Returns the timestamp policy object identifier of the policy this timestamp + * was created under. If status is GRANTED or GRANTED_WITH_MODS, this is never + * +nil+. + * + * ===Example: + * id = token_info.policy_id + * puts id -> "1.2.3.4.5" + * + * call-seq: + * token_info.policy_id -> string or nil + */ +static VALUE +ossl_ts_token_info_get_policy_id(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return ossl_asn1obj_to_string(TS_TST_INFO_get_policy_id(info)); +} + +/* + * Returns the 'short name' of the object identifier representing the algorithm + * that was used to derive the message imprint digest. For valid timestamps, + * this is the same value that was already given in the Request. If status is + * GRANTED or GRANTED_WITH_MODS, this is never +nil+. + * + * ===Example: + * algo = token_info.algorithm + * puts algo -> "SHA1" + * + * call-seq: + * token_info.algorithm -> string or nil + */ +static VALUE +ossl_ts_token_info_get_algorithm(VALUE self) +{ + TS_TST_INFO *info; + TS_MSG_IMPRINT *mi; + X509_ALGOR *algo; + const ASN1_OBJECT *obj; + + GetTSTokenInfo(self, info); + mi = TS_TST_INFO_get_msg_imprint(info); + algo = TS_MSG_IMPRINT_get_algo(mi); + X509_ALGOR_get0(&obj, NULL, NULL, algo); + return ossl_asn1obj_to_string(obj); +} + +/* + * Returns the message imprint digest. For valid timestamps, + * this is the same value that was already given in the Request. + * If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+. + * + * ===Example: + * mi = token_info.msg_imprint + * puts mi -> "DEADBEEF" + * + * call-seq: + * token_info.msg_imprint -> string. + */ +static VALUE +ossl_ts_token_info_get_msg_imprint(VALUE self) +{ + TS_TST_INFO *info; + TS_MSG_IMPRINT *mi; + ASN1_OCTET_STRING *hashed_msg; + VALUE ret; + + GetTSTokenInfo(self, info); + mi = TS_TST_INFO_get_msg_imprint(info); + hashed_msg = TS_MSG_IMPRINT_get_msg(mi); + ret = asn1str_to_str(hashed_msg); + + return ret; +} + +/* + * Returns serial number of the timestamp token. This value shall never be the + * same for two timestamp tokens issued by a dedicated timestamp authority. + * If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+. + * + * call-seq: + * token_info.serial_number -> BN or nil + */ +static VALUE +ossl_ts_token_info_get_serial_number(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return asn1integer_to_num(TS_TST_INFO_get_serial(info)); +} + +/* + * Returns time when this timestamp token was created. If status is GRANTED or + * GRANTED_WITH_MODS, this is never +nil+. + * + * call-seq: + * token_info.gen_time -> Time + */ +static VALUE +ossl_ts_token_info_get_gen_time(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return asn1time_to_time(TS_TST_INFO_get_time(info)); +} + +/* + * If the ordering field is missing, or if the ordering field is present + * and set to false, then the genTime field only indicates the time at + * which the time-stamp token has been created by the TSA. In such a + * case, the ordering of time-stamp tokens issued by the same TSA or + * different TSAs is only possible when the difference between the + * genTime of the first time-stamp token and the genTime of the second + * time-stamp token is greater than the sum of the accuracies of the + * genTime for each time-stamp token. + * + * If the ordering field is present and set to true, every time-stamp + * token from the same TSA can always be ordered based on the genTime + * field, regardless of the genTime accuracy. + * + * call-seq: + * token_info.ordering -> true, falses or nil + */ +static VALUE +ossl_ts_token_info_get_ordering(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return TS_TST_INFO_get_ordering(info) ? Qtrue : Qfalse; +} + +/* + * If the timestamp token is valid then this field contains the same nonce that + * was passed to the timestamp server in the initial Request. + * + * call-seq: + * token_info.nonce -> BN or nil + */ +static VALUE +ossl_ts_token_info_get_nonce(VALUE self) +{ + TS_TST_INFO *info; + const ASN1_INTEGER *nonce; + + GetTSTokenInfo(self, info); + if (!(nonce = TS_TST_INFO_get_nonce(info))) + return Qnil; + + return asn1integer_to_num(nonce); +} + +/* + * Returns the TokenInfo in DER-encoded form. + * + * call-seq: + * token_info.to_der -> string + */ +static VALUE +ossl_ts_token_info_to_der(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return asn1_to_der((void *)info, (int (*)(void *, unsigned char **))i2d_TS_TST_INFO); +} + +static VALUE +ossl_ts_token_info_to_text(VALUE self) +{ + TS_TST_INFO *info; + BIO *out; + + GetTSTokenInfo(self, info); + + out = BIO_new(BIO_s_mem()); + if (!out) ossl_raise(eTimestampError, NULL); + + if (!TS_TST_INFO_print_bio(out, info)) { + BIO_free(out); + ossl_raise(eTimestampError, NULL); + } + + return ossl_membio2str(out); +} + +static ASN1_INTEGER * +ossl_tsfac_serial_cb(struct TS_resp_ctx *ctx, void *data) +{ + ASN1_INTEGER **snptr = (ASN1_INTEGER **)data; + ASN1_INTEGER *sn = *snptr; + *snptr = NULL; + return sn; +} + +static int +#if !defined(LIBRESSL_VERSION_NUMBER) +ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, long *sec, long *usec) +#else +ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, time_t *sec, long *usec) +#endif +{ + *sec = *((long *)data); + *usec = 0; + return 1; +} + +static VALUE +ossl_evp_md_fetch_i(VALUE args_) +{ + VALUE *args = (VALUE *)args_, md_holder; + const EVP_MD *md; + + md = ossl_evp_md_fetch(args[1], &md_holder); + rb_ary_push(args[0], md_holder); + return (VALUE)md; +} + +static VALUE +ossl_obj2bio_i(VALUE arg) +{ + return (VALUE)ossl_obj2bio((VALUE *)arg); +} + +/* + * Creates a Response with the help of an OpenSSL::PKey, an + * OpenSSL::X509::Certificate and a Request. + * + * Mandatory parameters for timestamp creation that need to be set in the + * Request: + * + * * Request#algorithm + * * Request#message_imprint + * + * Mandatory parameters that need to be set in the Factory: + * * Factory#serial_number + * * Factory#gen_time + * * Factory#allowed_digests + * + * In addition one of either Request#policy_id or Factory#default_policy_id + * must be set. + * + * Raises a TimestampError if creation fails, though successfully created error + * responses may be returned. + * + * call-seq: + * factory.create_timestamp(key, certificate, request) -> Response + */ +static VALUE +ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request) +{ + VALUE serial_number, def_policy_id, gen_time, additional_certs, + allowed_digests, allowed_digests_tmp = Qnil; + VALUE str; + STACK_OF(X509) *inter_certs; + VALUE tsresp, ret = Qnil; + EVP_PKEY *sign_key; + X509 *tsa_cert; + TS_REQ *req; + TS_RESP *response = NULL; + TS_RESP_CTX *ctx = NULL; + BIO *req_bio; + ASN1_INTEGER *asn1_serial = NULL; + ASN1_OBJECT *def_policy_id_obj = NULL; + long lgen_time; + const char * err_msg = NULL; + int status = 0; + + tsresp = NewTSResponse(cTimestampResponse); + tsa_cert = GetX509CertPtr(certificate); + sign_key = GetPrivPKeyPtr(key); + GetTSRequest(request, req); + + gen_time = ossl_tsfac_get_gen_time(self); + if (!rb_obj_is_instance_of(gen_time, rb_cTime)) { + err_msg = "@gen_time must be a Time."; + goto end; + } + lgen_time = NUM2LONG(rb_funcall(gen_time, rb_intern("to_i"), 0)); + + serial_number = ossl_tsfac_get_serial_number(self); + if (NIL_P(serial_number)) { + err_msg = "@serial_number must be set."; + goto end; + } + asn1_serial = num_to_asn1integer(serial_number, NULL); + + def_policy_id = ossl_tsfac_get_default_policy_id(self); + if (NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) { + err_msg = "No policy id in the request and no default policy set"; + goto end; + } + if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) { + def_policy_id_obj = (ASN1_OBJECT*)rb_protect(obj_to_asn1obj_i, (VALUE)def_policy_id, &status); + if (status) + goto end; + } + + if (!(ctx = TS_RESP_CTX_new())) { + err_msg = "Memory allocation failed."; + goto end; + } + + TS_RESP_CTX_set_serial_cb(ctx, ossl_tsfac_serial_cb, &asn1_serial); + if (!TS_RESP_CTX_set_signer_cert(ctx, tsa_cert)) { + err_msg = "Certificate does not contain the timestamping extension"; + goto end; + } + + additional_certs = ossl_tsfac_get_additional_certs(self); + if (rb_obj_is_kind_of(additional_certs, rb_cArray)) { + inter_certs = ossl_protect_x509_ary2sk(additional_certs, &status); + if (status) + goto end; + + /* this dups the sk_X509 and ups each cert's ref count */ + TS_RESP_CTX_set_certs(ctx, inter_certs); + sk_X509_pop_free(inter_certs, X509_free); + } + + TS_RESP_CTX_set_signer_key(ctx, sign_key); + if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) + TS_RESP_CTX_set_def_policy(ctx, def_policy_id_obj); + if (TS_REQ_get_policy_id(req)) + TS_RESP_CTX_set_def_policy(ctx, TS_REQ_get_policy_id(req)); + TS_RESP_CTX_set_time_cb(ctx, ossl_tsfac_time_cb, &lgen_time); + + allowed_digests = ossl_tsfac_get_allowed_digests(self); + if (rb_obj_is_kind_of(allowed_digests, rb_cArray)) { + allowed_digests_tmp = rb_ary_new_capa(RARRAY_LEN(allowed_digests)); + for (long i = 0; i < RARRAY_LEN(allowed_digests); i++) { + VALUE args[] = { + allowed_digests_tmp, + rb_ary_entry(allowed_digests, i), + }; + const EVP_MD *md = (const EVP_MD *)rb_protect(ossl_evp_md_fetch_i, + (VALUE)args, &status); + if (status) + goto end; + if (!TS_RESP_CTX_add_md(ctx, md)) + goto end; + } + } + + str = rb_protect(ossl_to_der, request, &status); + if (status) + goto end; + + req_bio = (BIO*)rb_protect(ossl_obj2bio_i, (VALUE)&str, &status); + if (status) + goto end; + + response = TS_RESP_create_response(ctx, req_bio); + BIO_free(req_bio); + RB_GC_GUARD(allowed_digests_tmp); + + if (!response) { + err_msg = "Error during response generation"; + goto end; + } + + /* bad responses aren't exceptional, but openssl still sets error + * information. */ + ossl_clear_error(); + + SetTSResponse(tsresp, response); + ret = tsresp; + + end: + ASN1_INTEGER_free(asn1_serial); + ASN1_OBJECT_free(def_policy_id_obj); + TS_RESP_CTX_free(ctx); + if (err_msg) + rb_exc_raise(ossl_make_error(eTimestampError, rb_str_new_cstr(err_msg))); + if (status) + rb_jump_tag(status); + return ret; +} + +/* + * INIT + */ +void +Init_ossl_ts(void) +{ + /* + * Possible return value for +Response#failure_info+. Indicates that the + * timestamp server rejects the message imprint algorithm used in the + * +Request+ + */ + sBAD_ALG = ID2SYM(rb_intern_const("BAD_ALG")); + + /* + * Possible return value for +Response#failure_info+. Indicates that the + * timestamp server was not able to process the +Request+ properly. + */ + sBAD_REQUEST = ID2SYM(rb_intern_const("BAD_REQUEST")); + /* + * Possible return value for +Response#failure_info+. Indicates that the + * timestamp server was not able to parse certain data in the +Request+. + */ + sBAD_DATA_FORMAT = ID2SYM(rb_intern_const("BAD_DATA_FORMAT")); + + sTIME_NOT_AVAILABLE = ID2SYM(rb_intern_const("TIME_NOT_AVAILABLE")); + sUNACCEPTED_POLICY = ID2SYM(rb_intern_const("UNACCEPTED_POLICY")); + sUNACCEPTED_EXTENSION = ID2SYM(rb_intern_const("UNACCEPTED_EXTENSION")); + sADD_INFO_NOT_AVAILABLE = ID2SYM(rb_intern_const("ADD_INFO_NOT_AVAILABLE")); + sSYSTEM_FAILURE = ID2SYM(rb_intern_const("SYSTEM_FAILURE")); + + /* Document-class: OpenSSL::Timestamp + * Provides classes and methods to request, create and validate + * {RFC3161-compliant}[http://www.ietf.org/rfc/rfc3161.txt] timestamps. + * Request may be used to either create requests from scratch or to parse + * existing requests that again can be used to request timestamps from a + * timestamp server, e.g. via the net/http. The resulting timestamp + * response may be parsed using Response. + * + * Please note that Response is read-only and immutable. To create a + * Response, an instance of Factory as well as a valid Request are needed. + * + * ===Create a Response: + * #Assumes ts.p12 is a PKCS#12-compatible file with a private key + * #and a certificate that has an extended key usage of 'timeStamping' + * p12 = OpenSSL::PKCS12.new(File.binread('ts.p12'), 'pwd') + * md = OpenSSL::Digest.new('SHA1') + * hash = md.digest(data) #some binary data to be timestamped + * req = OpenSSL::Timestamp::Request.new + * req.algorithm = 'SHA1' + * req.message_imprint = hash + * req.policy_id = "1.2.3.4.5" + * req.nonce = 42 + * fac = OpenSSL::Timestamp::Factory.new + * fac.gen_time = Time.now + * fac.serial_number = 1 + * timestamp = fac.create_timestamp(p12.key, p12.certificate, req) + * + * ===Verify a timestamp response: + * #Assume we have a timestamp token in a file called ts.der + * ts = OpenSSL::Timestamp::Response.new(File.binread('ts.der')) + * #Assume we have the Request for this token in a file called req.der + * req = OpenSSL::Timestamp::Request.new(File.binread('req.der')) + * # Assume the associated root CA certificate is contained in a + * # DER-encoded file named root.cer + * root = OpenSSL::X509::Certificate.new(File.binread('root.cer')) + * # get the necessary intermediate certificates, available in + * # DER-encoded form in inter1.cer and inter2.cer + * inter1 = OpenSSL::X509::Certificate.new(File.binread('inter1.cer')) + * inter2 = OpenSSL::X509::Certificate.new(File.binread('inter2.cer')) + * ts.verify(req, root, inter1, inter2) -> ts or raises an exception if validation fails + * + */ + mTimestamp = rb_define_module_under(mOSSL, "Timestamp"); + + /* Document-class: OpenSSL::Timestamp::TimestampError + * Generic exception class of the Timestamp module. + */ + eTimestampError = rb_define_class_under(mTimestamp, "TimestampError", eOSSLError); + + /* Document-class: OpenSSL::Timestamp::Response + * Immutable and read-only representation of a timestamp response returned + * from a timestamp server after receiving an associated Request. Allows + * access to specific information about the response but also allows to + * verify the Response. + */ + cTimestampResponse = rb_define_class_under(mTimestamp, "Response", rb_cObject); + rb_define_alloc_func(cTimestampResponse, ossl_ts_resp_alloc); + rb_define_method(cTimestampResponse, "initialize", ossl_ts_resp_initialize, 1); + rb_define_method(cTimestampResponse, "status", ossl_ts_resp_get_status, 0); + rb_define_method(cTimestampResponse, "failure_info", ossl_ts_resp_get_failure_info, 0); + rb_define_method(cTimestampResponse, "status_text", ossl_ts_resp_get_status_text, 0); + rb_define_method(cTimestampResponse, "token", ossl_ts_resp_get_token, 0); + rb_define_method(cTimestampResponse, "token_info", ossl_ts_resp_get_token_info, 0); + rb_define_method(cTimestampResponse, "tsa_certificate", ossl_ts_resp_get_tsa_certificate, 0); + rb_define_method(cTimestampResponse, "to_der", ossl_ts_resp_to_der, 0); + rb_define_method(cTimestampResponse, "to_text", ossl_ts_resp_to_text, 0); + rb_define_method(cTimestampResponse, "verify", ossl_ts_resp_verify, -1); + + /* Document-class: OpenSSL::Timestamp::TokenInfo + * Immutable and read-only representation of a timestamp token info from a + * Response. + */ + cTimestampTokenInfo = rb_define_class_under(mTimestamp, "TokenInfo", rb_cObject); + rb_define_alloc_func(cTimestampTokenInfo, ossl_ts_token_info_alloc); + rb_define_method(cTimestampTokenInfo, "initialize", ossl_ts_token_info_initialize, 1); + rb_define_method(cTimestampTokenInfo, "version", ossl_ts_token_info_get_version, 0); + rb_define_method(cTimestampTokenInfo, "policy_id", ossl_ts_token_info_get_policy_id, 0); + rb_define_method(cTimestampTokenInfo, "algorithm", ossl_ts_token_info_get_algorithm, 0); + rb_define_method(cTimestampTokenInfo, "message_imprint", ossl_ts_token_info_get_msg_imprint, 0); + rb_define_method(cTimestampTokenInfo, "serial_number", ossl_ts_token_info_get_serial_number, 0); + rb_define_method(cTimestampTokenInfo, "gen_time", ossl_ts_token_info_get_gen_time, 0); + rb_define_method(cTimestampTokenInfo, "ordering", ossl_ts_token_info_get_ordering, 0); + rb_define_method(cTimestampTokenInfo, "nonce", ossl_ts_token_info_get_nonce, 0); + rb_define_method(cTimestampTokenInfo, "to_der", ossl_ts_token_info_to_der, 0); + rb_define_method(cTimestampTokenInfo, "to_text", ossl_ts_token_info_to_text, 0); + + /* Document-class: OpenSSL::Timestamp::Request + * Allows to create timestamp requests or parse existing ones. A Request is + * also needed for creating timestamps from scratch with Factory. When + * created from scratch, some default values are set: + * * version is set to +1+ + * * cert_requested is set to +true+ + * * algorithm, message_imprint, policy_id, and nonce are set to +false+ + */ + cTimestampRequest = rb_define_class_under(mTimestamp, "Request", rb_cObject); + rb_define_alloc_func(cTimestampRequest, ossl_ts_req_alloc); + rb_define_method(cTimestampRequest, "initialize", ossl_ts_req_initialize, -1); + rb_define_method(cTimestampRequest, "version=", ossl_ts_req_set_version, 1); + rb_define_method(cTimestampRequest, "version", ossl_ts_req_get_version, 0); + rb_define_method(cTimestampRequest, "algorithm=", ossl_ts_req_set_algorithm, 1); + rb_define_method(cTimestampRequest, "algorithm", ossl_ts_req_get_algorithm, 0); + rb_define_method(cTimestampRequest, "message_imprint=", ossl_ts_req_set_msg_imprint, 1); + rb_define_method(cTimestampRequest, "message_imprint", ossl_ts_req_get_msg_imprint, 0); + rb_define_method(cTimestampRequest, "policy_id=", ossl_ts_req_set_policy_id, 1); + rb_define_method(cTimestampRequest, "policy_id", ossl_ts_req_get_policy_id, 0); + rb_define_method(cTimestampRequest, "nonce=", ossl_ts_req_set_nonce, 1); + rb_define_method(cTimestampRequest, "nonce", ossl_ts_req_get_nonce, 0); + rb_define_method(cTimestampRequest, "cert_requested=", ossl_ts_req_set_cert_requested, 1); + rb_define_method(cTimestampRequest, "cert_requested?", ossl_ts_req_get_cert_requested, 0); + rb_define_method(cTimestampRequest, "to_der", ossl_ts_req_to_der, 0); + rb_define_method(cTimestampRequest, "to_text", ossl_ts_req_to_text, 0); + + /* + * Indicates a successful response. Equal to +0+. + */ + rb_define_const(cTimestampResponse, "GRANTED", INT2NUM(TS_STATUS_GRANTED)); + /* + * Indicates a successful response that probably contains modifications + * from the initial request. Equal to +1+. + */ + rb_define_const(cTimestampResponse, "GRANTED_WITH_MODS", INT2NUM(TS_STATUS_GRANTED_WITH_MODS)); + /* + * Indicates a failure. No timestamp token was created. Equal to +2+. + */ + rb_define_const(cTimestampResponse, "REJECTION", INT2NUM(TS_STATUS_REJECTION)); + /* + * Indicates a failure. No timestamp token was created. Equal to +3+. + */ + rb_define_const(cTimestampResponse, "WAITING", INT2NUM(TS_STATUS_WAITING)); + /* + * Indicates a failure. No timestamp token was created. Revocation of a + * certificate is imminent. Equal to +4+. + */ + rb_define_const(cTimestampResponse, "REVOCATION_WARNING", INT2NUM(TS_STATUS_REVOCATION_WARNING)); + /* + * Indicates a failure. No timestamp token was created. A certificate + * has been revoked. Equal to +5+. + */ + rb_define_const(cTimestampResponse, "REVOCATION_NOTIFICATION", INT2NUM(TS_STATUS_REVOCATION_NOTIFICATION)); + + /* Document-class: OpenSSL::Timestamp::Factory + * + * Used to generate a Response from scratch. + * + * Please bear in mind that the implementation will always apply and prefer + * the policy object identifier given in the request over the default policy + * id specified in the Factory. As a consequence, +default_policy_id+ will + * only be applied if no Request#policy_id was given. But this also means + * that one needs to check the policy identifier in the request manually + * before creating the Response, e.g. to check whether it complies to a + * specific set of acceptable policies. + * + * There exists also the possibility to add certificates (instances of + * OpenSSL::X509::Certificate) besides the timestamping certificate + * that will be included in the resulting timestamp token if + * Request#cert_requested? is +true+. Ideally, one would also include any + * intermediate certificates (the root certificate can be left out - in + * order to trust it any verifying party will have to be in its possession + * anyway). This simplifies validation of the timestamp since these + * intermediate certificates are "already there" and need not be passed as + * external parameters to Response#verify anymore, thus minimizing external + * resources needed for verification. + * + * ===Example: Inclusion of (untrusted) intermediate certificates + * + * Assume we received a timestamp request that has set Request#policy_id to + * +nil+ and Request#cert_requested? to true. The raw request bytes are + * stored in a variable called +req_raw+. We'd still like to integrate + * the necessary intermediate certificates (in +inter1.cer+ and + * +inter2.cer+) to simplify validation of the resulting Response. +ts.p12+ + * is a PKCS#12-compatible file including the private key and the + * timestamping certificate. + * + * req = OpenSSL::Timestamp::Request.new(raw_bytes) + * p12 = OpenSSL::PKCS12.new(File.binread('ts.p12'), 'pwd') + * inter1 = OpenSSL::X509::Certificate.new(File.binread('inter1.cer')) + * inter2 = OpenSSL::X509::Certificate.new(File.binread('inter2.cer')) + * fac = OpenSSL::Timestamp::Factory.new + * fac.gen_time = Time.now + * fac.serial_number = 1 + * fac.allowed_digests = ["sha256", "sha384", "sha512"] + * #needed because the Request contained no policy identifier + * fac.default_policy_id = '1.2.3.4.5' + * fac.additional_certificates = [ inter1, inter2 ] + * timestamp = fac.create_timestamp(p12.key, p12.certificate, req) + */ + cTimestampFactory = rb_define_class_under(mTimestamp, "Factory", rb_cObject); + /* + * The list of digest algorithms that the factory is allowed + * create timestamps for. Known vulnerable or weak algorithms should not be + * allowed where possible. Must be an Array of String or OpenSSL::Digest + * subclass instances. + */ + rb_attr(cTimestampFactory, rb_intern_const("allowed_digests"), 1, 1, 0); + /* + * A String representing the default policy object identifier, or +nil+. + * + * Request#policy_id will always be preferred over this if present in the + * Request, only if Request#policy_id is +nil+ default_policy will be used. + * If none of both is present, a TimestampError will be raised when trying + * to create a Response. + */ + rb_attr(cTimestampFactory, rb_intern_const("default_policy_id"), 1, 1, 0); + /* + * The serial number to be used for timestamp creation. Must be present for + * timestamp creation. Must be an instance of OpenSSL::BN or Integer. + */ + rb_attr(cTimestampFactory, rb_intern_const("serial_number"), 1, 1, 0); + /* + * The Time value to be used in the Response. Must be present for timestamp + * creation. + */ + rb_attr(cTimestampFactory, rb_intern_const("gen_time"), 1, 1, 0); + /* + * Additional certificates apart from the timestamp certificate (e.g. + * intermediate certificates) to be added to the Response. + * Must be an Array of OpenSSL::X509::Certificate, or +nil+. + */ + rb_attr(cTimestampFactory, rb_intern_const("additional_certs"), 1, 1, 0); + rb_define_method(cTimestampFactory, "create_timestamp", ossl_tsfac_create_ts, 3); +} +#else /* OPENSSL_NO_TS */ +void +Init_ossl_ts(void) +{ +} +#endif diff --git a/ext/openssl/ossl_ts.h b/ext/openssl/ossl_ts.h new file mode 100644 index 0000000000..eeca3046eb --- /dev/null +++ b/ext/openssl/ossl_ts.h @@ -0,0 +1,16 @@ +/* + * + * Copyright (C) 2010 Martin Bosslet <Martin.Bosslet@googlemail.com> + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'COPYING'.) + */ + +#if !defined(_OSSL_TS_H_) +#define _OSSL_TS_H_ + +void Init_ossl_ts(void); + +#endif diff --git a/ext/openssl/ossl_version.h b/ext/openssl/ossl_version.h deleted file mode 100644 index 193ceab089..0000000000 --- a/ext/openssl/ossl_version.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * $Id$ - * 'OpenSSL for Ruby' project - * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> - * All rights reserved. - */ -/* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) - */ -#if !defined(_OSSL_VERSION_H_) -#define _OSSL_VERSION_H_ - -#define OSSL_VERSION "1.1.0" - -#endif /* _OSSL_VERSION_H_ */ diff --git a/ext/openssl/ossl_x509.c b/ext/openssl/ossl_x509.c index 4de45455d4..bc3914fda2 100644 --- a/ext/openssl/ossl_x509.c +++ b/ext/openssl/ossl_x509.c @@ -1,20 +1,31 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" VALUE mX509; -#define DefX509Const(x) rb_define_const(mX509, #x,INT2FIX(X509_##x)) +#define DefX509Const(x) rb_define_const(mX509, #x, INT2NUM(X509_##x)) #define DefX509Default(x,i) \ - rb_define_const(mX509, "DEFAULT_" #x, rb_str_new2(X509_get_default_##i())) + rb_define_const(mX509, "DEFAULT_" #x, \ + rb_obj_freeze(rb_str_new_cstr(X509_get_default_##i()))) + +ASN1_TIME * +ossl_x509_time_adjust(ASN1_TIME *s, VALUE time) +{ + time_t sec; + + int off_days; + + ossl_time_split(time, &sec, &off_days); + return X509_time_adj_ex(s, off_days, 0, &sec); +} void Init_ossl_x509(void) @@ -30,7 +41,11 @@ Init_ossl_x509(void) Init_ossl_x509revoked(); Init_ossl_x509store(); + /* Constants are up-to-date with 1.1.1. */ + + /* Certificate verification error code */ DefX509Const(V_OK); + DefX509Const(V_ERR_UNSPECIFIED); DefX509Const(V_ERR_UNABLE_TO_GET_ISSUER_CERT); DefX509Const(V_ERR_UNABLE_TO_GET_CRL); DefX509Const(V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE); @@ -62,37 +77,156 @@ Init_ossl_x509(void) DefX509Const(V_ERR_AKID_SKID_MISMATCH); DefX509Const(V_ERR_AKID_ISSUER_SERIAL_MISMATCH); DefX509Const(V_ERR_KEYUSAGE_NO_CERTSIGN); + DefX509Const(V_ERR_UNABLE_TO_GET_CRL_ISSUER); + DefX509Const(V_ERR_UNHANDLED_CRITICAL_EXTENSION); + DefX509Const(V_ERR_KEYUSAGE_NO_CRL_SIGN); + DefX509Const(V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION); + DefX509Const(V_ERR_INVALID_NON_CA); + DefX509Const(V_ERR_PROXY_PATH_LENGTH_EXCEEDED); + DefX509Const(V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE); + DefX509Const(V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED); + DefX509Const(V_ERR_INVALID_EXTENSION); + DefX509Const(V_ERR_INVALID_POLICY_EXTENSION); + DefX509Const(V_ERR_NO_EXPLICIT_POLICY); + DefX509Const(V_ERR_DIFFERENT_CRL_SCOPE); + DefX509Const(V_ERR_UNSUPPORTED_EXTENSION_FEATURE); + DefX509Const(V_ERR_UNNESTED_RESOURCE); + DefX509Const(V_ERR_PERMITTED_VIOLATION); + DefX509Const(V_ERR_EXCLUDED_VIOLATION); + DefX509Const(V_ERR_SUBTREE_MINMAX); DefX509Const(V_ERR_APPLICATION_VERIFICATION); + DefX509Const(V_ERR_UNSUPPORTED_CONSTRAINT_TYPE); + DefX509Const(V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX); + DefX509Const(V_ERR_UNSUPPORTED_NAME_SYNTAX); + DefX509Const(V_ERR_CRL_PATH_VALIDATION_ERROR); +#if defined(X509_V_ERR_PATH_LOOP) /* OpenSSL 1.1.0, missing in LibreSSL */ + DefX509Const(V_ERR_PATH_LOOP); +#endif +#if defined(X509_V_ERR_SUITE_B_INVALID_VERSION) /* OpenSSL 1.1.0, missing in LibreSSL */ + DefX509Const(V_ERR_SUITE_B_INVALID_VERSION); + DefX509Const(V_ERR_SUITE_B_INVALID_ALGORITHM); + DefX509Const(V_ERR_SUITE_B_INVALID_CURVE); + DefX509Const(V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM); + DefX509Const(V_ERR_SUITE_B_LOS_NOT_ALLOWED); + DefX509Const(V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256); +#endif + DefX509Const(V_ERR_HOSTNAME_MISMATCH); + DefX509Const(V_ERR_EMAIL_MISMATCH); + DefX509Const(V_ERR_IP_ADDRESS_MISMATCH); +#if defined(X509_V_ERR_DANE_NO_MATCH) /* OpenSSL 1.1.0, missing in LibreSSL */ + DefX509Const(V_ERR_DANE_NO_MATCH); +#endif + DefX509Const(V_ERR_EE_KEY_TOO_SMALL); + DefX509Const(V_ERR_CA_KEY_TOO_SMALL); + DefX509Const(V_ERR_CA_MD_TOO_WEAK); + DefX509Const(V_ERR_INVALID_CALL); + DefX509Const(V_ERR_STORE_LOOKUP); +#if defined(X509_V_ERR_NO_VALID_SCTS) /* OpenSSL 1.1.0, missing in LibreSSL */ + DefX509Const(V_ERR_NO_VALID_SCTS); +#endif +#if defined(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION) /* OpenSSL 1.1.0, missing in LibreSSL */ + DefX509Const(V_ERR_PROXY_SUBJECT_NAME_VIOLATION); +#endif +#if defined(X509_V_ERR_OCSP_VERIFY_NEEDED) /* OpenSSL 1.1.1, missing in LibreSSL */ + DefX509Const(V_ERR_OCSP_VERIFY_NEEDED); + DefX509Const(V_ERR_OCSP_VERIFY_FAILED); + DefX509Const(V_ERR_OCSP_CERT_UNKNOWN); +#endif -#if defined(X509_V_FLAG_CRL_CHECK) + /* Certificate verify flags */ + /* Set by Store#flags= and StoreContext#flags=. */ + DefX509Const(V_FLAG_USE_CHECK_TIME); + /* Set by Store#flags= and StoreContext#flags=. Enables CRL checking for the + * certificate chain leaf. */ DefX509Const(V_FLAG_CRL_CHECK); -#endif -#if defined(X509_V_FLAG_CRL_CHECK_ALL) + /* Set by Store#flags= and StoreContext#flags=. Enables CRL checking for all + * certificates in the certificate chain */ DefX509Const(V_FLAG_CRL_CHECK_ALL); + /* Set by Store#flags= and StoreContext#flags=. Disables critical extension + * checking. */ + DefX509Const(V_FLAG_IGNORE_CRITICAL); + /* Set by Store#flags= and StoreContext#flags=. Disables workarounds for + * broken certificates. */ + DefX509Const(V_FLAG_X509_STRICT); + /* Set by Store#flags= and StoreContext#flags=. Enables proxy certificate + * verification. */ + DefX509Const(V_FLAG_ALLOW_PROXY_CERTS); + /* Set by Store#flags= and StoreContext#flags=. Enables certificate policy + * constraints checking. */ + DefX509Const(V_FLAG_POLICY_CHECK); + /* Set by Store#flags= and StoreContext#flags=. + * Implies V_FLAG_POLICY_CHECK */ + DefX509Const(V_FLAG_EXPLICIT_POLICY); + /* Set by Store#flags= and StoreContext#flags=. + * Implies V_FLAG_POLICY_CHECK */ + DefX509Const(V_FLAG_INHIBIT_ANY); + /* Set by Store#flags= and StoreContext#flags=. + * Implies V_FLAG_POLICY_CHECK */ + DefX509Const(V_FLAG_INHIBIT_MAP); + /* Set by Store#flags= and StoreContext#flags=. */ + DefX509Const(V_FLAG_NOTIFY_POLICY); + /* Set by Store#flags= and StoreContext#flags=. Enables some additional + * features including support for indirect signed CRLs. */ + DefX509Const(V_FLAG_EXTENDED_CRL_SUPPORT); + /* Set by Store#flags= and StoreContext#flags=. Uses delta CRLs. If not + * specified, deltas are ignored. */ + DefX509Const(V_FLAG_USE_DELTAS); + /* Set by Store#flags= and StoreContext#flags=. Enables checking of the + * signature of the root self-signed CA. */ + DefX509Const(V_FLAG_CHECK_SS_SIGNATURE); + /* Set by Store#flags= and StoreContext#flags=. When constructing a + * certificate chain, search the Store first for the issuer certificate. + * Enabled by default in OpenSSL >= 1.1.0. */ + DefX509Const(V_FLAG_TRUSTED_FIRST); +#if defined(X509_V_FLAG_SUITEB_128_LOS_ONLY) /* OpenSSL 1.1.0, missing in LibreSSL */ + /* Set by Store#flags= and StoreContext#flags=. + * Enables Suite B 128 bit only mode. */ + DefX509Const(V_FLAG_SUITEB_128_LOS_ONLY); + /* Set by Store#flags= and StoreContext#flags=. + * Enables Suite B 192 bit only mode. */ + DefX509Const(V_FLAG_SUITEB_192_LOS); + /* Set by Store#flags= and StoreContext#flags=. + * Enables Suite B 128 bit mode allowing 192 bit algorithms. */ + DefX509Const(V_FLAG_SUITEB_128_LOS); #endif + /* Set by Store#flags= and StoreContext#flags=. + * Allows partial chains if at least one certificate is in trusted store. */ + DefX509Const(V_FLAG_PARTIAL_CHAIN); + /* Set by Store#flags= and StoreContext#flags=. Suppresses searching for + * a alternative chain. No effect in OpenSSL >= 1.1.0. */ + DefX509Const(V_FLAG_NO_ALT_CHAINS); + /* Set by Store#flags= and StoreContext#flags=. Suppresses checking the + * validity period of certificates and CRLs. No effect when the current + * time is explicitly set by Store#time= or StoreContext#time=. */ + DefX509Const(V_FLAG_NO_CHECK_TIME); + /* Set by Store#purpose=. SSL/TLS client. */ DefX509Const(PURPOSE_SSL_CLIENT); + /* Set by Store#purpose=. SSL/TLS server. */ DefX509Const(PURPOSE_SSL_SERVER); + /* Set by Store#purpose=. Netscape SSL server. */ DefX509Const(PURPOSE_NS_SSL_SERVER); + /* Set by Store#purpose=. S/MIME signing. */ DefX509Const(PURPOSE_SMIME_SIGN); + /* Set by Store#purpose=. S/MIME encryption. */ DefX509Const(PURPOSE_SMIME_ENCRYPT); + /* Set by Store#purpose=. CRL signing */ DefX509Const(PURPOSE_CRL_SIGN); + /* Set by Store#purpose=. No checks. */ DefX509Const(PURPOSE_ANY); -#if defined(X509_PURPOSE_OCSP_HELPER) + /* Set by Store#purpose=. OCSP helper. */ DefX509Const(PURPOSE_OCSP_HELPER); -#endif + /* Set by Store#purpose=. Time stamps signer. */ + DefX509Const(PURPOSE_TIMESTAMP_SIGN); DefX509Const(TRUST_COMPAT); DefX509Const(TRUST_SSL_CLIENT); DefX509Const(TRUST_SSL_SERVER); DefX509Const(TRUST_EMAIL); DefX509Const(TRUST_OBJECT_SIGN); -#if defined(X509_TRUST_OCSP_SIGN) DefX509Const(TRUST_OCSP_SIGN); -#endif -#if defined(X509_TRUST_OCSP_REQUEST) DefX509Const(TRUST_OCSP_REQUEST); -#endif + DefX509Const(TRUST_TSA); DefX509Default(CERT_AREA, cert_area); DefX509Default(CERT_DIR, cert_dir); @@ -101,4 +235,3 @@ Init_ossl_x509(void) DefX509Default(CERT_FILE_ENV, cert_file_env); DefX509Default(PRIVATE_DIR, private_dir); } - diff --git a/ext/openssl/ossl_x509.h b/ext/openssl/ossl_x509.h index 1a43569073..d25167ee7b 100644 --- a/ext/openssl/ossl_x509.h +++ b/ext/openssl/ossl_x509.h @@ -1,12 +1,11 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #if !defined(_OSSL_X509_H_) #define _OSSL_X509_H_ @@ -16,26 +15,30 @@ */ extern VALUE mX509; +/* + * Converts the VALUE into Integer and set it to the ASN1_TIME. This is a + * wrapper for X509_time_adj_ex() so passing NULL creates a new ASN1_TIME. + * Note that the caller must check the NULL return. + */ +ASN1_TIME *ossl_x509_time_adjust(ASN1_TIME *, VALUE); + void Init_ossl_x509(void); /* * X509Attr */ extern VALUE cX509Attr; -extern VALUE eX509AttrError; VALUE ossl_x509attr_new(X509_ATTRIBUTE *); -X509_ATTRIBUTE *DupX509AttrPtr(VALUE); +X509_ATTRIBUTE *GetX509AttrPtr(VALUE); void Init_ossl_x509attr(void); /* * X509Cert */ extern VALUE cX509Cert; -extern VALUE eX509CertError; VALUE ossl_x509_new(X509 *); -VALUE ossl_x509_new_from_file(VALUE); X509 *GetX509CertPtr(VALUE); X509 *DupX509CertPtr(VALUE); void Init_ossl_x509cert(void); @@ -43,32 +46,22 @@ void Init_ossl_x509cert(void); /* * X509CRL */ -extern VALUE cX509CRL; -extern VALUE eX509CRLError; - VALUE ossl_x509crl_new(X509_CRL *); X509_CRL *GetX509CRLPtr(VALUE); -X509_CRL *DupX509CRLPtr(VALUE); void Init_ossl_x509crl(void); /* * X509Extension */ extern VALUE cX509Ext; -extern VALUE cX509ExtFactory; -extern VALUE eX509ExtError; VALUE ossl_x509ext_new(X509_EXTENSION *); X509_EXTENSION *GetX509ExtPtr(VALUE); -X509_EXTENSION *DupX509ExtPtr(VALUE); void Init_ossl_x509ext(void); /* * X509Name */ -extern VALUE cX509Name; -extern VALUE eX509NameError; - VALUE ossl_x509name_new(X509_NAME *); X509_NAME *GetX509NamePtr(VALUE); void Init_ossl_x509name(void); @@ -76,19 +69,13 @@ void Init_ossl_x509name(void); /* * X509Request */ -extern VALUE cX509Req; -extern VALUE eX509ReqError; - -VALUE ossl_x509req_new(X509_REQ *); X509_REQ *GetX509ReqPtr(VALUE); -X509_REQ *DupX509ReqPtr(VALUE); void Init_ossl_x509req(void); /* * X509Revoked */ extern VALUE cX509Rev; -extern VALUE eX509RevError; VALUE ossl_x509revoked_new(X509_REVOKED *); X509_REVOKED *DupX509RevokedPtr(VALUE); @@ -97,18 +84,13 @@ void Init_ossl_x509revoked(void); /* * X509Store and X509StoreContext */ -extern VALUE cX509Store; -extern VALUE cX509StoreContext; -extern VALUE eX509StoreError; - -VALUE ossl_x509store_new(X509_STORE *); X509_STORE *GetX509StorePtr(VALUE); -X509_STORE *DupX509StorePtr(VALUE); - -VALUE ossl_x509stctx_new(X509_STORE_CTX *); -VALUE ossl_x509stctx_clear_ptr(VALUE); -X509_STORE_CTX *GetX509StCtxtPtr(VALUE); - void Init_ossl_x509store(void); +/* + * Calls the verify callback Proc (the first parameter) with given pre-verify + * result and the X509_STORE_CTX. + */ +int ossl_verify_cb_call(VALUE, int, X509_STORE_CTX *); + #endif /* _OSSL_X509_H_ */ diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c index c9036cad90..4769e56e1e 100644 --- a/ext/openssl/ossl_x509attr.c +++ b/ext/openssl/ossl_x509attr.c @@ -1,37 +1,34 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#define WrapX509Attr(klass, obj, attr) do { \ +#define NewX509Attr(klass) \ + TypedData_Wrap_Struct((klass), &ossl_x509attr_type, 0) +#define SetX509Attr(obj, attr) do { \ if (!(attr)) { \ - ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \ } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_x509attr_type, (attr)); \ + RTYPEDDATA_DATA(obj) = (attr); \ } while (0) #define GetX509Attr(obj, attr) do { \ TypedData_Get_Struct((obj), X509_ATTRIBUTE, &ossl_x509attr_type, (attr)); \ if (!(attr)) { \ - ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \ } \ } while (0) -#define SafeGetX509Attr(obj, attr) do { \ - OSSL_Check_Kind((obj), cX509Attr); \ - GetX509Attr((obj), (attr)); \ -} while (0) /* * Classes */ VALUE cX509Attr; -VALUE eX509AttrError; +static VALUE eX509AttrError; static void ossl_x509attr_free(void *ptr) @@ -42,9 +39,9 @@ ossl_x509attr_free(void *ptr) static const rb_data_type_t ossl_x509attr_type = { "OpenSSL/X509/ATTRIBUTE", { - 0, ossl_x509attr_free, + 0, ossl_x509attr_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; /* @@ -56,30 +53,23 @@ ossl_x509attr_new(X509_ATTRIBUTE *attr) X509_ATTRIBUTE *new; VALUE obj; - if (!attr) { - new = X509_ATTRIBUTE_new(); - } else { - new = X509_ATTRIBUTE_dup(attr); - } - if (!new) { - ossl_raise(eX509AttrError, NULL); - } - WrapX509Attr(cX509Attr, obj, new); + obj = NewX509Attr(cX509Attr); + new = X509_ATTRIBUTE_dup(attr); + if (!new) + ossl_raise(eX509AttrError, "X509_ATTRIBUTE_dup"); + SetX509Attr(obj, new); return obj; } X509_ATTRIBUTE * -DupX509AttrPtr(VALUE obj) +GetX509AttrPtr(VALUE obj) { - X509_ATTRIBUTE *attr, *new; + X509_ATTRIBUTE *attr; - SafeGetX509Attr(obj, attr); - if (!(new = X509_ATTRIBUTE_dup(attr))) { - ossl_raise(eX509AttrError, NULL); - } + GetX509Attr(obj, attr); - return new; + return attr; } /* @@ -91,9 +81,10 @@ ossl_x509attr_alloc(VALUE klass) X509_ATTRIBUTE *attr; VALUE obj; + obj = NewX509Attr(klass); if (!(attr = X509_ATTRIBUTE_new())) - ossl_raise(eX509AttrError, NULL); - WrapX509Attr(klass, obj, attr); + ossl_raise(eX509AttrError, NULL); + SetX509Attr(obj, attr); return obj; } @@ -111,15 +102,15 @@ ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self) GetX509Attr(self, attr); if(rb_scan_args(argc, argv, "11", &oid, &value) == 1){ - oid = ossl_to_der_if_possible(oid); - StringValue(oid); - p = (unsigned char *)RSTRING_PTR(oid); - x = d2i_X509_ATTRIBUTE(&attr, &p, RSTRING_LEN(oid)); - DATA_PTR(self) = attr; - if(!x){ - ossl_raise(eX509AttrError, NULL); - } - return self; + oid = ossl_to_der_if_possible(oid); + StringValue(oid); + p = (unsigned char *)RSTRING_PTR(oid); + x = d2i_X509_ATTRIBUTE(&attr, &p, RSTRING_LEN(oid)); + DATA_PTR(self) = attr; + if(!x){ + ossl_raise(eX509AttrError, NULL); + } + return self; } rb_funcall(self, rb_intern("oid="), 1, oid); rb_funcall(self, rb_intern("value="), 1, value); @@ -127,6 +118,26 @@ ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self) return self; } +/* :nodoc: */ +static VALUE +ossl_x509attr_initialize_copy(VALUE self, VALUE other) +{ + X509_ATTRIBUTE *attr, *attr_other, *attr_new; + + rb_check_frozen(self); + GetX509Attr(self, attr); + GetX509Attr(other, attr_other); + + attr_new = X509_ATTRIBUTE_dup(attr_other); + if (!attr_new) + ossl_raise(eX509AttrError, "X509_ATTRIBUTE_dup"); + + SetX509Attr(self, attr_new); + X509_ATTRIBUTE_free(attr); + + return self; +} + /* * call-seq: * attr.oid = string => string @@ -138,51 +149,35 @@ ossl_x509attr_set_oid(VALUE self, VALUE oid) ASN1_OBJECT *obj; char *s; - s = StringValuePtr(oid); + GetX509Attr(self, attr); + s = StringValueCStr(oid); obj = OBJ_txt2obj(s, 0); - if(!obj) obj = OBJ_txt2obj(s, 1); if(!obj) ossl_raise(eX509AttrError, NULL); - GetX509Attr(self, attr); - X509_ATTRIBUTE_set1_object(attr, obj); + if (!X509_ATTRIBUTE_set1_object(attr, obj)) { + ASN1_OBJECT_free(obj); + ossl_raise(eX509AttrError, "X509_ATTRIBUTE_set1_object"); + } + ASN1_OBJECT_free(obj); return oid; } /* * call-seq: - * attr.oid => string + * attr.oid -> string + * + * Returns the OID of the attribute. Returns the short name or the dotted + * decimal notation. */ static VALUE ossl_x509attr_get_oid(VALUE self) { X509_ATTRIBUTE *attr; - ASN1_OBJECT *oid; - BIO *out; - VALUE ret; - int nid; GetX509Attr(self, attr); - oid = X509_ATTRIBUTE_get0_object(attr); - if ((nid = OBJ_obj2nid(oid)) != NID_undef) - ret = rb_str_new2(OBJ_nid2sn(nid)); - else{ - if (!(out = BIO_new(BIO_s_mem()))) - ossl_raise(eX509AttrError, NULL); - i2a_ASN1_OBJECT(out, oid); - ret = ossl_membio2str(out); - } - - return ret; + return ossl_asn1obj_to_string(X509_ATTRIBUTE_get0_object(attr)); } -#if defined(HAVE_ST_X509_ATTRIBUTE_SINGLE) || defined(HAVE_ST_SINGLE) -# define OSSL_X509ATTR_IS_SINGLE(attr) ((attr)->single) -# define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->single = 1) -#else -# define OSSL_X509ATTR_IS_SINGLE(attr) (!(attr)->value.set) -# define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->value.set = 0) -#endif - /* * call-seq: * attr.value = asn1 => asn1 @@ -191,21 +186,36 @@ static VALUE ossl_x509attr_set_value(VALUE self, VALUE value) { X509_ATTRIBUTE *attr; - ASN1_TYPE *a1type; + GetX509Attr(self, attr); - if(!(a1type = ossl_asn1_get_asn1type(value))) - ossl_raise(eASN1Error, "could not get ASN1_TYPE"); - if(ASN1_TYPE_get(a1type) == V_ASN1_SEQUENCE){ - ASN1_TYPE_free(a1type); - ossl_raise(eASN1Error, "couldn't set SEQUENCE for attribute value."); + OSSL_Check_Kind(value, cASN1Data); + VALUE der = ossl_to_der(value); + const unsigned char *p = (const unsigned char *)RSTRING_PTR(der); + STACK_OF(ASN1_TYPE) *sk = d2i_ASN1_SET_ANY(NULL, &p, RSTRING_LEN(der)); + if (!sk) + ossl_raise(eX509AttrError, "attribute value must be ASN1::Set"); + + if (X509_ATTRIBUTE_count(attr)) { /* populated, reset first */ + ASN1_OBJECT *obj = X509_ATTRIBUTE_get0_object(attr); + X509_ATTRIBUTE *new_attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, 0, NULL, -1); + if (!new_attr) { + sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free); + ossl_raise(eX509AttrError, "X509_ATTRIBUTE_create_by_OBJ"); + } + SetX509Attr(self, new_attr); + X509_ATTRIBUTE_free(attr); + attr = new_attr; } - GetX509Attr(self, attr); - if(attr->value.set){ - if(OSSL_X509ATTR_IS_SINGLE(attr)) ASN1_TYPE_free(attr->value.single); - else sk_ASN1_TYPE_free(attr->value.set); + + for (int i = 0; i < sk_ASN1_TYPE_num(sk); i++) { + ASN1_TYPE *a1type = sk_ASN1_TYPE_value(sk, i); + if (!X509_ATTRIBUTE_set1_data(attr, ASN1_TYPE_get(a1type), + a1type->value.ptr, -1)) { + sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free); + ossl_raise(eX509AttrError, "X509_ATTRIBUTE_set1_data"); + } } - OSSL_X509ATTR_SET_SINGLE(attr); - attr->value.single = a1type; + sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free); return value; } @@ -218,32 +228,34 @@ static VALUE ossl_x509attr_get_value(VALUE self) { X509_ATTRIBUTE *attr; - VALUE str, asn1; - long length; + STACK_OF(ASN1_TYPE) *sk; + VALUE str; + int i, count, len; unsigned char *p; GetX509Attr(self, attr); - if(attr->value.ptr == NULL) return Qnil; - if(OSSL_X509ATTR_IS_SINGLE(attr)){ - length = i2d_ASN1_TYPE(attr->value.single, NULL); - str = rb_str_new(0, length); - p = (unsigned char *)RSTRING_PTR(str); - i2d_ASN1_TYPE(attr->value.single, &p); - ossl_str_adjust(str, p); + /* there is no X509_ATTRIBUTE_get0_set() :( */ + if (!(sk = sk_ASN1_TYPE_new_null())) + ossl_raise(eX509AttrError, "sk_new"); + + count = X509_ATTRIBUTE_count(attr); + for (i = 0; i < count; i++) + sk_ASN1_TYPE_push(sk, X509_ATTRIBUTE_get0_type(attr, i)); + + if ((len = i2d_ASN1_SET_ANY(sk, NULL)) <= 0) { + sk_ASN1_TYPE_free(sk); + ossl_raise(eX509AttrError, NULL); } - else{ - length = i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set, - (unsigned char **) NULL, i2d_ASN1_TYPE, - V_ASN1_SET, V_ASN1_UNIVERSAL, 0); - str = rb_str_new(0, length); - p = (unsigned char *)RSTRING_PTR(str); - i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set, &p, - i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0); - ossl_str_adjust(str, p); + str = rb_str_new(0, len); + p = (unsigned char *)RSTRING_PTR(str); + if (i2d_ASN1_SET_ANY(sk, &p) <= 0) { + sk_ASN1_TYPE_free(sk); + ossl_raise(eX509AttrError, NULL); } - asn1 = rb_funcall(mASN1, rb_intern("decode"), 1, str); + ossl_str_adjust(str, p); + sk_ASN1_TYPE_free(sk); - return asn1; + return rb_funcall(mASN1, rb_intern("decode"), 1, str); } /* @@ -260,12 +272,12 @@ ossl_x509attr_to_der(VALUE self) GetX509Attr(self, attr); if((len = i2d_X509_ATTRIBUTE(attr, NULL)) <= 0) - ossl_raise(eX509AttrError, NULL); + ossl_raise(eX509AttrError, NULL); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); if(i2d_X509_ATTRIBUTE(attr, &p) <= 0) - ossl_raise(eX509AttrError, NULL); - rb_str_set_len(str, p - (unsigned char*)RSTRING_PTR(str)); + ossl_raise(eX509AttrError, NULL); + ossl_str_adjust(str, p); return str; } @@ -281,6 +293,7 @@ Init_ossl_x509attr(void) cX509Attr = rb_define_class_under(mX509, "Attribute", rb_cObject); rb_define_alloc_func(cX509Attr, ossl_x509attr_alloc); rb_define_method(cX509Attr, "initialize", ossl_x509attr_initialize, -1); + rb_define_method(cX509Attr, "initialize_copy", ossl_x509attr_initialize_copy, 1); rb_define_method(cX509Attr, "oid=", ossl_x509attr_set_oid, 1); rb_define_method(cX509Attr, "oid", ossl_x509attr_get_oid, 0); rb_define_method(cX509Attr, "value=", ossl_x509attr_set_value, 1); diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c index b76ea793aa..95679c7d24 100644 --- a/ext/openssl/ossl_x509cert.c +++ b/ext/openssl/ossl_x509cert.c @@ -1,37 +1,34 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#define WrapX509(klass, obj, x509) do { \ +#define NewX509(klass) \ + TypedData_Wrap_Struct((klass), &ossl_x509_type, 0) +#define SetX509(obj, x509) do { \ if (!(x509)) { \ - ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \ } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_x509_type, (x509)); \ + RTYPEDDATA_DATA(obj) = (x509); \ } while (0) #define GetX509(obj, x509) do { \ TypedData_Get_Struct((obj), X509, &ossl_x509_type, (x509)); \ if (!(x509)) { \ - ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \ } \ } while (0) -#define SafeGetX509(obj, x509) do { \ - OSSL_Check_Kind((obj), cX509Cert); \ - GetX509((obj), (x509)); \ -} while (0) /* * Classes */ VALUE cX509Cert; -VALUE eX509CertError; +static VALUE eX509CertError; static void ossl_x509_free(void *ptr) @@ -42,9 +39,9 @@ ossl_x509_free(void *ptr) static const rb_data_type_t ossl_x509_type = { "OpenSSL/X509", { - 0, ossl_x509_free, + 0, ossl_x509_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; /* @@ -56,48 +53,11 @@ ossl_x509_new(X509 *x509) X509 *new; VALUE obj; - if (!x509) { - new = X509_new(); - } else { - new = X509_dup(x509); - } - if (!new) { - ossl_raise(eX509CertError, NULL); - } - WrapX509(cX509Cert, obj, new); - - return obj; -} - -VALUE -ossl_x509_new_from_file(VALUE filename) -{ - X509 *x509; - FILE *fp; - VALUE obj; - - SafeStringValue(filename); - if (!(fp = fopen(RSTRING_PTR(filename), "r"))) { - ossl_raise(eX509CertError, "%s", strerror(errno)); - } - rb_fd_fix_cloexec(fileno(fp)); - x509 = PEM_read_X509(fp, NULL, NULL, NULL); - /* - * prepare for DER... -#if !defined(OPENSSL_NO_FP_API) - if (!x509) { - (void)ERR_get_error(); - rewind(fp); - - x509 = d2i_X509_fp(fp, NULL); - } -#endif - */ - fclose(fp); - if (!x509) { - ossl_raise(eX509CertError, NULL); - } - WrapX509(cX509Cert, obj, x509); + obj = NewX509(cX509Cert); + new = X509_dup(x509); + if (!new) + ossl_raise(eX509CertError, "X509_dup"); + SetX509(obj, new); return obj; } @@ -107,7 +67,7 @@ GetX509CertPtr(VALUE obj) { X509 *x509; - SafeGetX509(obj, x509); + GetX509(obj, x509); return x509; } @@ -117,9 +77,9 @@ DupX509CertPtr(VALUE obj) { X509 *x509; - SafeGetX509(obj, x509); + GetX509(obj, x509); - CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(x509); return x509; } @@ -133,10 +93,10 @@ ossl_x509_alloc(VALUE klass) X509 *x509; VALUE obj; + obj = NewX509(klass); x509 = X509_new(); if (!x509) ossl_raise(eX509CertError, NULL); - - WrapX509(klass, obj, x509); + SetX509(obj, x509); return obj; } @@ -150,28 +110,32 @@ static VALUE ossl_x509_initialize(int argc, VALUE *argv, VALUE self) { BIO *in; - X509 *x509, *x = DATA_PTR(self); + X509 *x509, *x509_orig = RTYPEDDATA_DATA(self); VALUE arg; + rb_check_frozen(self); if (rb_scan_args(argc, argv, "01", &arg) == 0) { - /* create just empty X509Cert */ - return self; + /* create just empty X509Cert */ + return self; } arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(arg); - x509 = PEM_read_bio_X509(in, &x, NULL, NULL); - DATA_PTR(self) = x; + in = ossl_obj2bio(&arg); + x509 = d2i_X509_bio(in, NULL); if (!x509) { - OSSL_BIO_reset(in); - x509 = d2i_X509_bio(in, &x); - DATA_PTR(self) = x; + OSSL_BIO_reset(in); + x509 = PEM_read_bio_X509(in, NULL, NULL, NULL); } BIO_free(in); - if (!x509) ossl_raise(eX509CertError, NULL); + if (!x509) + ossl_raise(eX509CertError, "PEM_read_bio_X509"); + + RTYPEDDATA_DATA(self) = x509; + X509_free(x509_orig); return self; } +/* :nodoc: */ static VALUE ossl_x509_copy(VALUE self, VALUE other) { @@ -181,7 +145,7 @@ ossl_x509_copy(VALUE self, VALUE other) if (self == other) return self; GetX509(self, a); - SafeGetX509(other, b); + GetX509(other, b); x509 = X509_dup(b); if (!x509) ossl_raise(eX509CertError, NULL); @@ -206,11 +170,11 @@ ossl_x509_to_der(VALUE self) GetX509(self, x509); if ((len = i2d_X509(x509, NULL)) <= 0) - ossl_raise(eX509CertError, NULL); + ossl_raise(eX509CertError, NULL); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); if (i2d_X509(x509, &p) <= 0) - ossl_raise(eX509CertError, NULL); + ossl_raise(eX509CertError, NULL); ossl_str_adjust(str, p); return str; @@ -232,8 +196,8 @@ ossl_x509_to_pem(VALUE self) if (!out) ossl_raise(eX509CertError, NULL); if (!PEM_write_bio_X509(out, x509)) { - BIO_free(out); - ossl_raise(eX509CertError, NULL); + BIO_free(out); + ossl_raise(eX509CertError, NULL); } str = ossl_membio2str(out); @@ -257,8 +221,8 @@ ossl_x509_to_text(VALUE self) if (!out) ossl_raise(eX509CertError, NULL); if (!X509_print(out, x509)) { - BIO_free(out); - ossl_raise(eX509CertError, NULL); + BIO_free(out); + ossl_raise(eX509CertError, NULL); } str = ossl_membio2str(out); @@ -278,7 +242,7 @@ ossl_x509_to_req(VALUE self) GetX509(self, x509); if (!(req = X509_to_X509_REQ(x509, NULL, EVP_md5()))) { - ossl_raise(eX509CertError, NULL); + ossl_raise(eX509CertError, NULL); } obj = ossl_x509req_new(req); X509_REQ_free(req); @@ -312,11 +276,11 @@ ossl_x509_set_version(VALUE self, VALUE version) long ver; if ((ver = NUM2LONG(version)) < 0) { - ossl_raise(eX509CertError, "version must be >= 0!"); + ossl_raise(eX509CertError, "version must be >= 0!"); } GetX509(self, x509); if (!X509_set_version(x509, ver)) { - ossl_raise(eX509CertError, NULL); + ossl_raise(eX509CertError, NULL); } return version; @@ -346,9 +310,7 @@ ossl_x509_set_serial(VALUE self, VALUE num) X509 *x509; GetX509(self, x509); - - x509->cert_info->serialNumber = - num_to_asn1integer(num, X509_get_serialNumber(x509)); + X509_set_serialNumber(x509, num_to_asn1integer(num, X509_get_serialNumber(x509))); return num; } @@ -356,25 +318,23 @@ ossl_x509_set_serial(VALUE self, VALUE num) /* * call-seq: * cert.signature_algorithm => string + * + * Returns the signature algorithm used to sign this certificate. This returns + * the algorithm name found in the TBSCertificate structure, not the outer + * \Certificate structure. + * + * Returns the long name of the signature algorithm, or the dotted decimal + * notation if \OpenSSL does not define a long name for it. */ static VALUE ossl_x509_get_signature_algorithm(VALUE self) { X509 *x509; - BIO *out; - VALUE str; + const ASN1_OBJECT *obj; GetX509(self, x509); - out = BIO_new(BIO_s_mem()); - if (!out) ossl_raise(eX509CertError, NULL); - - if (!i2a_ASN1_OBJECT(out, x509->cert_info->signature->algorithm)) { - BIO_free(out); - ossl_raise(eX509CertError, NULL); - } - str = ossl_membio2str(out); - - return str; + X509_ALGOR_get0(&obj, NULL, NULL, X509_get0_tbs_sigalg(x509)); + return ossl_asn1obj_to_string_long_name(obj); } /* @@ -389,7 +349,7 @@ ossl_x509_get_subject(VALUE self) GetX509(self, x509); if (!(name = X509_get_subject_name(x509))) { /* NO DUP - don't free! */ - ossl_raise(eX509CertError, NULL); + ossl_raise(eX509CertError, NULL); } return ossl_x509name_new(name); @@ -406,7 +366,7 @@ ossl_x509_set_subject(VALUE self, VALUE subject) GetX509(self, x509); if (!X509_set_subject_name(x509, GetX509NamePtr(subject))) { /* DUPs name */ - ossl_raise(eX509CertError, NULL); + ossl_raise(eX509CertError, NULL); } return subject; @@ -424,7 +384,7 @@ ossl_x509_get_issuer(VALUE self) GetX509(self, x509); if(!(name = X509_get_issuer_name(x509))) { /* NO DUP - don't free! */ - ossl_raise(eX509CertError, NULL); + ossl_raise(eX509CertError, NULL); } return ossl_x509name_new(name); @@ -441,7 +401,7 @@ ossl_x509_set_issuer(VALUE self, VALUE issuer) GetX509(self, x509); if (!X509_set_issuer_name(x509, GetX509NamePtr(issuer))) { /* DUPs name */ - ossl_raise(eX509CertError, NULL); + ossl_raise(eX509CertError, NULL); } return issuer; @@ -455,11 +415,11 @@ static VALUE ossl_x509_get_not_before(VALUE self) { X509 *x509; - ASN1_UTCTIME *asn1time; + const ASN1_TIME *asn1time; GetX509(self, x509); - if (!(asn1time = X509_get_notBefore(x509))) { /* NO DUP - don't free! */ - ossl_raise(eX509CertError, NULL); + if (!(asn1time = X509_get0_notBefore(x509))) { + ossl_raise(eX509CertError, NULL); } return asn1time_to_time(asn1time); @@ -473,13 +433,15 @@ static VALUE ossl_x509_set_not_before(VALUE self, VALUE time) { X509 *x509; - time_t sec; + ASN1_TIME *asn1time; - sec = time_to_time_t(time); GetX509(self, x509); - if (!X509_time_adj(X509_get_notBefore(x509), 0, &sec)) { - ossl_raise(eX509CertError, NULL); + asn1time = ossl_x509_time_adjust(NULL, time); + if (!X509_set1_notBefore(x509, asn1time)) { + ASN1_TIME_free(asn1time); + ossl_raise(eX509CertError, "X509_set_notBefore"); } + ASN1_TIME_free(asn1time); return time; } @@ -492,11 +454,11 @@ static VALUE ossl_x509_get_not_after(VALUE self) { X509 *x509; - ASN1_TIME *asn1time; + const ASN1_TIME *asn1time; GetX509(self, x509); - if (!(asn1time = X509_get_notAfter(x509))) { /* NO DUP - don't free! */ - ossl_raise(eX509CertError, NULL); + if (!(asn1time = X509_get0_notAfter(x509))) { + ossl_raise(eX509CertError, NULL); } return asn1time_to_time(asn1time); @@ -510,13 +472,15 @@ static VALUE ossl_x509_set_not_after(VALUE self, VALUE time) { X509 *x509; - time_t sec; + ASN1_TIME *asn1time; - sec = time_to_time_t(time); GetX509(self, x509); - if (!X509_time_adj(X509_get_notAfter(x509), 0, &sec)) { - ossl_raise(eX509CertError, NULL); + asn1time = ossl_x509_time_adjust(NULL, time); + if (!X509_set1_notAfter(x509, asn1time)) { + ASN1_TIME_free(asn1time); + ossl_raise(eX509CertError, "X509_set_notAfter"); } + ASN1_TIME_free(asn1time); return time; } @@ -533,26 +497,27 @@ ossl_x509_get_public_key(VALUE self) GetX509(self, x509); if (!(pkey = X509_get_pubkey(x509))) { /* adds an reference */ - ossl_raise(eX509CertError, NULL); + ossl_raise(eX509CertError, NULL); } - return ossl_pkey_new(pkey); /* NO DUP - OK */ + return ossl_pkey_wrap(pkey); } /* * call-seq: - * cert.public_key = key => key + * cert.public_key = key */ static VALUE ossl_x509_set_public_key(VALUE self, VALUE key) { X509 *x509; + EVP_PKEY *pkey; GetX509(self, x509); - if (!X509_set_pubkey(x509, GetPKeyPtr(key))) { /* DUPs pkey */ - ossl_raise(eX509CertError, NULL); - } - + pkey = GetPKeyPtr(key); + ossl_pkey_check_public_key(pkey); + if (!X509_set_pubkey(x509, pkey)) + ossl_raise(eX509CertError, "X509_set_pubkey"); return key; } @@ -566,13 +531,14 @@ ossl_x509_sign(VALUE self, VALUE key, VALUE digest) X509 *x509; EVP_PKEY *pkey; const EVP_MD *md; + VALUE md_holder; pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ - md = GetDigestPtr(digest); + /* NULL needed for some key types, e.g. Ed25519 */ + md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder); GetX509(self, x509); - if (!X509_sign(x509, pkey, md)) { - ossl_raise(eX509CertError, NULL); - } + if (!X509_sign(x509, pkey, md)) + ossl_raise(eX509CertError, "X509_sign"); return self; } @@ -581,32 +547,35 @@ ossl_x509_sign(VALUE self, VALUE key, VALUE digest) * call-seq: * cert.verify(key) => true | false * - * Checks that cert signature is made with PRIVversion of this PUBLIC 'key' + * Verifies the signature of the certificate, with the public key _key_. _key_ + * must be an instance of OpenSSL::PKey. */ static VALUE ossl_x509_verify(VALUE self, VALUE key) { X509 *x509; EVP_PKEY *pkey; - int i; - pkey = GetPKeyPtr(key); /* NO NEED TO DUP */ GetX509(self, x509); - if ((i = X509_verify(x509, pkey)) < 0) { - ossl_raise(eX509CertError, NULL); + pkey = GetPKeyPtr(key); + ossl_pkey_check_public_key(pkey); + switch (X509_verify(x509, pkey)) { + case 1: + return Qtrue; + case 0: + ossl_clear_error(); + return Qfalse; + default: + ossl_raise(eX509CertError, NULL); } - if (i > 0) { - return Qtrue; - } - - return Qfalse; } /* * call-seq: - * cert.check_private_key(key) + * cert.check_private_key(key) -> true | false * - * Checks if 'key' is PRIV key for this cert + * Returns +true+ if _key_ is the corresponding private key to the Subject + * Public Key Information, +false+ otherwise. */ static VALUE ossl_x509_check_private_key(VALUE self, VALUE key) @@ -618,8 +587,8 @@ ossl_x509_check_private_key(VALUE self, VALUE key) pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ GetX509(self, x509); if (!X509_check_private_key(x509, pkey)) { - OSSL_Warning("Check private key:%s", OSSL_ErrMsg()); - return Qfalse; + ossl_clear_error(); + return Qfalse; } return Qtrue; @@ -639,13 +608,10 @@ ossl_x509_get_extensions(VALUE self) GetX509(self, x509); count = X509_get_ext_count(x509); - if (count < 0) { - return rb_ary_new(); - } - ary = rb_ary_new2(count); + ary = rb_ary_new_capa(count); for (i=0; i<count; i++) { - ext = X509_get_ext(x509, i); /* NO DUP - don't free! */ - rb_ary_push(ary, ossl_x509ext_new(ext)); + ext = X509_get_ext(x509, i); /* NO DUP - don't free! */ + rb_ary_push(ary, ossl_x509ext_new(ext)); } return ary; @@ -660,24 +626,21 @@ ossl_x509_set_extensions(VALUE self, VALUE ary) { X509 *x509; X509_EXTENSION *ext; - int i; + long i; Check_Type(ary, T_ARRAY); /* All ary's members should be X509Extension */ for (i=0; i<RARRAY_LEN(ary); i++) { - OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext); + OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext); } GetX509(self, x509); - sk_X509_EXTENSION_pop_free(x509->cert_info->extensions, X509_EXTENSION_free); - x509->cert_info->extensions = NULL; + for (i = X509_get_ext_count(x509); i > 0; i--) + X509_EXTENSION_free(X509_delete_ext(x509, 0)); for (i=0; i<RARRAY_LEN(ary); i++) { - ext = DupX509ExtPtr(RARRAY_PTR(ary)[i]); - - if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */ - X509_EXTENSION_free(ext); - ossl_raise(eX509CertError, NULL); - } - X509_EXTENSION_free(ext); + ext = GetX509ExtPtr(RARRAY_AREF(ary, i)); + if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext */ + ossl_raise(eX509CertError, "X509_add_ext"); + } } return ary; @@ -694,28 +657,219 @@ ossl_x509_add_extension(VALUE self, VALUE extension) X509_EXTENSION *ext; GetX509(self, x509); - ext = DupX509ExtPtr(extension); + ext = GetX509ExtPtr(extension); if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */ - X509_EXTENSION_free(ext); - ossl_raise(eX509CertError, NULL); + ossl_raise(eX509CertError, NULL); } - X509_EXTENSION_free(ext); return extension; } +/* + * call-seq: + * cert1 == cert2 -> true | false + * + * Compares the two certificates. Note that this takes into account all fields, + * not just the issuer name and the serial number. + * + * This method uses X509_cmp() from OpenSSL, which compares certificates based + * on their cached DER encodings. The comparison can be unreliable if a + * certificate is incomplete. + * + * See also the man page X509_cmp(3). + */ +static VALUE +ossl_x509_eq(VALUE self, VALUE other) +{ + X509 *a, *b; + + GetX509(self, a); + if (!rb_obj_is_kind_of(other, cX509Cert)) + return Qfalse; + GetX509(other, b); + + return !X509_cmp(a, b) ? Qtrue : Qfalse; +} + +/* + * call-seq: + * cert.tbs_bytes => string + * + * Returns the DER-encoded bytes of the certificate's to be signed certificate. + * This is mainly useful for validating embedded certificate transparency signatures. + */ +static VALUE +ossl_x509_tbs_bytes(VALUE self) +{ + X509 *x509; + int len; + unsigned char *p0; + VALUE str; + + GetX509(self, x509); + len = i2d_re_X509_tbs(x509, NULL); + if (len <= 0) { + ossl_raise(eX509CertError, "i2d_re_X509_tbs"); + } + str = rb_str_new(NULL, len); + p0 = (unsigned char *)RSTRING_PTR(str); + if (i2d_re_X509_tbs(x509, &p0) <= 0) { + ossl_raise(eX509CertError, "i2d_re_X509_tbs"); + } + ossl_str_adjust(str, p0); + + return str; +} + +struct load_chained_certificates_arguments { + VALUE certificates; + X509 *certificate; +}; + +static VALUE +load_chained_certificates_append_push(VALUE _arguments) { + struct load_chained_certificates_arguments *arguments = (struct load_chained_certificates_arguments*)_arguments; + + if (arguments->certificates == Qnil) { + arguments->certificates = rb_ary_new(); + } + + rb_ary_push(arguments->certificates, ossl_x509_new(arguments->certificate)); + + return Qnil; +} + +static VALUE +load_chained_certificate_append_ensure(VALUE _arguments) { + struct load_chained_certificates_arguments *arguments = (struct load_chained_certificates_arguments*)_arguments; + + X509_free(arguments->certificate); + + return Qnil; +} + +inline static VALUE +load_chained_certificates_append(VALUE certificates, X509 *certificate) { + struct load_chained_certificates_arguments arguments; + arguments.certificates = certificates; + arguments.certificate = certificate; + + rb_ensure(load_chained_certificates_append_push, (VALUE)&arguments, load_chained_certificate_append_ensure, (VALUE)&arguments); + + return arguments.certificates; +} + static VALUE -ossl_x509_inspect(VALUE self) +load_chained_certificates_PEM(BIO *in) { + VALUE certificates = Qnil; + X509 *certificate = PEM_read_bio_X509(in, NULL, NULL, NULL); + + /* If we cannot read even one certificate: */ + if (certificate == NULL) { + /* If we cannot read one certificate because we could not read the PEM encoding: */ + if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) { + ossl_clear_error(); + } + + if (ERR_peek_last_error()) + ossl_raise(eX509CertError, NULL); + else + return Qnil; + } + + certificates = load_chained_certificates_append(Qnil, certificate); + + while ((certificate = PEM_read_bio_X509(in, NULL, NULL, NULL))) { + load_chained_certificates_append(certificates, certificate); + } + + /* We tried to read one more certificate but could not read start line: */ + if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) { + /* This is not an error, it means we are finished: */ + ossl_clear_error(); + + return certificates; + } + + /* Alternatively, if we reached the end of the file and there was no error: */ + if (BIO_eof(in) && !ERR_peek_last_error()) { + return certificates; + } else { + /* Otherwise, we tried to read a certificate but failed somewhere: */ + ossl_raise(eX509CertError, NULL); + } +} + +static VALUE +load_chained_certificates_DER(BIO *in) { + X509 *certificate = d2i_X509_bio(in, NULL); + + /* If we cannot read one certificate: */ + if (certificate == NULL) { + /* Ignore error. We could not load. */ + ossl_clear_error(); + + return Qnil; + } + + return load_chained_certificates_append(Qnil, certificate); +} + +static VALUE +load_chained_certificates(VALUE _io) { + BIO *in = (BIO*)_io; + VALUE certificates = Qnil; + + /* + DER is a binary format and it may contain octets within it that look like + PEM encoded certificates. So we need to check DER first. + */ + certificates = load_chained_certificates_DER(in); + + if (certificates != Qnil) + return certificates; + + OSSL_BIO_reset(in); + + certificates = load_chained_certificates_PEM(in); + + if (certificates != Qnil) + return certificates; + + /* Otherwise we couldn't read the output correctly so fail: */ + ossl_raise(eX509CertError, "Could not detect format of certificate data!"); +} + +static VALUE +load_chained_certificates_ensure(VALUE _io) { + BIO *in = (BIO*)_io; + + BIO_free(in); + + return Qnil; +} + +/* + * call-seq: + * OpenSSL::X509::Certificate.load(string) -> [certs...] + * OpenSSL::X509::Certificate.load(file) -> [certs...] + * + * Read the chained certificates from the given input. Supports both PEM + * and DER encoded certificates. + * + * PEM is a text format and supports more than one certificate. + * + * DER is a binary format and only supports one certificate. + * + * If the file is empty, or contains only unrelated data, an + * +OpenSSL::X509::CertificateError+ exception will be raised. + */ +static VALUE +ossl_x509_load(VALUE klass, VALUE buffer) { - return rb_sprintf("#<%"PRIsVALUE": subject=%+"PRIsVALUE", " - "issuer=%+"PRIsVALUE", serial=%+"PRIsVALUE", " - "not_before=%+"PRIsVALUE", not_after=%+"PRIsVALUE">", - rb_obj_class(self), - ossl_x509_get_subject(self), - ossl_x509_get_issuer(self), - ossl_x509_get_serial(self), - ossl_x509_get_not_before(self), - ossl_x509_get_not_after(self)); + BIO *in = ossl_obj2bio(&buffer); + + return rb_ensure(load_chained_certificates, (VALUE)in, load_chained_certificates_ensure, (VALUE)in); } /* @@ -724,12 +878,6 @@ ossl_x509_inspect(VALUE self) void Init_ossl_x509cert(void) { - -#if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ - mX509 = rb_define_module_under(mOSSL, "X509"); -#endif - eX509CertError = rb_define_class_under(mX509, "CertificateError", eOSSLError); /* Document-class: OpenSSL::X509::Certificate @@ -744,7 +892,7 @@ Init_ossl_x509cert(void) * Certificate is capable of handling DER-encoded certificates and * certificates encoded in OpenSSL's PEM format. * - * raw = File.read "cert.cer" # DER- or PEM-encoded + * raw = File.binread "cert.cer" # DER- or PEM-encoded * certificate = OpenSSL::X509::Certificate.new raw * * === Saving a certificate to a file @@ -802,7 +950,7 @@ Init_ossl_x509cert(void) * root_ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true)) * root_ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false)) * root_ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false)) - * root_ca.sign(root_key, OpenSSL::Digest::SHA256.new) + * root_ca.sign(root_key, OpenSSL::Digest.new('SHA256')) * * The next step is to create the end-entity certificate using the root CA * certificate. @@ -821,14 +969,16 @@ Init_ossl_x509cert(void) * ef.issuer_certificate = root_ca * cert.add_extension(ef.create_extension("keyUsage","digitalSignature", true)) * cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false)) - * cert.sign(root_key, OpenSSL::Digest::SHA256.new) + * cert.sign(root_key, OpenSSL::Digest.new('SHA256')) * */ cX509Cert = rb_define_class_under(mX509, "Certificate", rb_cObject); + rb_define_singleton_method(cX509Cert, "load", ossl_x509_load, 1); + rb_define_alloc_func(cX509Cert, ossl_x509_alloc); rb_define_method(cX509Cert, "initialize", ossl_x509_initialize, -1); - rb_define_copy_func(cX509Cert, ossl_x509_copy); + rb_define_method(cX509Cert, "initialize_copy", ossl_x509_copy, 1); rb_define_method(cX509Cert, "to_der", ossl_x509_to_der, 0); rb_define_method(cX509Cert, "to_pem", ossl_x509_to_pem, 0); @@ -855,6 +1005,6 @@ Init_ossl_x509cert(void) rb_define_method(cX509Cert, "extensions", ossl_x509_get_extensions, 0); rb_define_method(cX509Cert, "extensions=", ossl_x509_set_extensions, 1); rb_define_method(cX509Cert, "add_extension", ossl_x509_add_extension, 1); - rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0); + rb_define_method(cX509Cert, "==", ossl_x509_eq, 1); + rb_define_method(cX509Cert, "tbs_bytes", ossl_x509_tbs_bytes, 0); } - diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c index 461c226f4c..a221429c34 100644 --- a/ext/openssl/ossl_x509crl.c +++ b/ext/openssl/ossl_x509crl.c @@ -1,37 +1,34 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#define WrapX509CRL(klass, obj, crl) do { \ +#define NewX509CRL(klass) \ + TypedData_Wrap_Struct((klass), &ossl_x509crl_type, 0) +#define SetX509CRL(obj, crl) do { \ if (!(crl)) { \ - ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \ } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_x509crl_type, (crl)); \ + RTYPEDDATA_DATA(obj) = (crl); \ } while (0) #define GetX509CRL(obj, crl) do { \ TypedData_Get_Struct((obj), X509_CRL, &ossl_x509crl_type, (crl)); \ if (!(crl)) { \ - ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \ } \ } while (0) -#define SafeGetX509CRL(obj, crl) do { \ - OSSL_Check_Kind((obj), cX509CRL); \ - GetX509CRL((obj), (crl)); \ -} while (0) /* * Classes */ -VALUE cX509CRL; -VALUE eX509CRLError; +static VALUE cX509CRL; +static VALUE eX509CRLError; static void ossl_x509crl_free(void *ptr) @@ -42,9 +39,9 @@ ossl_x509crl_free(void *ptr) static const rb_data_type_t ossl_x509crl_type = { "OpenSSL/X509/CRL", { - 0, ossl_x509crl_free, + 0, ossl_x509crl_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; /* @@ -55,18 +52,7 @@ GetX509CRLPtr(VALUE obj) { X509_CRL *crl; - SafeGetX509CRL(obj, crl); - - return crl; -} - -X509_CRL * -DupX509CRLPtr(VALUE obj) -{ - X509_CRL *crl; - - SafeGetX509CRL(obj, crl); - CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL); + GetX509CRL(obj, crl); return crl; } @@ -77,9 +63,11 @@ ossl_x509crl_new(X509_CRL *crl) X509_CRL *tmp; VALUE obj; - tmp = crl ? X509_CRL_dup(crl) : X509_CRL_new(); - if(!tmp) ossl_raise(eX509CRLError, NULL); - WrapX509CRL(cX509CRL, obj, tmp); + obj = NewX509CRL(cX509CRL); + tmp = X509_CRL_dup(crl); + if (!tmp) + ossl_raise(eX509CRLError, "X509_CRL_dup"); + SetX509CRL(obj, tmp); return obj; } @@ -93,10 +81,11 @@ ossl_x509crl_alloc(VALUE klass) X509_CRL *crl; VALUE obj; + obj = NewX509CRL(klass); if (!(crl = X509_CRL_new())) { - ossl_raise(eX509CRLError, NULL); + ossl_raise(eX509CRLError, NULL); } - WrapX509CRL(klass, obj, crl); + SetX509CRL(obj, crl); return obj; } @@ -105,27 +94,31 @@ static VALUE ossl_x509crl_initialize(int argc, VALUE *argv, VALUE self) { BIO *in; - X509_CRL *crl, *x = DATA_PTR(self); + X509_CRL *crl, *crl_orig = RTYPEDDATA_DATA(self); VALUE arg; + rb_check_frozen(self); if (rb_scan_args(argc, argv, "01", &arg) == 0) { - return self; + return self; } arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(arg); - crl = PEM_read_bio_X509_CRL(in, &x, NULL, NULL); - DATA_PTR(self) = x; + in = ossl_obj2bio(&arg); + crl = d2i_X509_CRL_bio(in, NULL); if (!crl) { - OSSL_BIO_reset(in); - crl = d2i_X509_CRL_bio(in, &x); - DATA_PTR(self) = x; + OSSL_BIO_reset(in); + crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); } BIO_free(in); - if (!crl) ossl_raise(eX509CRLError, NULL); + if (!crl) + ossl_raise(eX509CRLError, "PEM_read_bio_X509_CRL"); + + RTYPEDDATA_DATA(self) = crl; + X509_CRL_free(crl_orig); return self; } +/* :nodoc: */ static VALUE ossl_x509crl_copy(VALUE self, VALUE other) { @@ -134,9 +127,9 @@ ossl_x509crl_copy(VALUE self, VALUE other) rb_check_frozen(self); if (self == other) return self; GetX509CRL(self, a); - SafeGetX509CRL(other, b); + GetX509CRL(other, b); if (!(crl = X509_CRL_dup(b))) { - ossl_raise(eX509CRLError, NULL); + ossl_raise(eX509CRLError, NULL); } X509_CRL_free(a); DATA_PTR(self) = crl; @@ -163,36 +156,36 @@ ossl_x509crl_set_version(VALUE self, VALUE version) long ver; if ((ver = NUM2LONG(version)) < 0) { - ossl_raise(eX509CRLError, "version must be >= 0!"); + ossl_raise(eX509CRLError, "version must be >= 0!"); } GetX509CRL(self, crl); if (!X509_CRL_set_version(crl, ver)) { - ossl_raise(eX509CRLError, NULL); + ossl_raise(eX509CRLError, NULL); } return version; } +/* + * call-seq: + * crl.signature_algorithm -> string + * + * Returns the signature algorithm used to sign this CRL. + * + * Returns the long name of the signature algorithm, or the dotted decimal + * notation if \OpenSSL does not define a long name for it. + */ static VALUE ossl_x509crl_get_signature_algorithm(VALUE self) { X509_CRL *crl; - BIO *out; - BUF_MEM *buf; - VALUE str; + const X509_ALGOR *alg; + const ASN1_OBJECT *obj; GetX509CRL(self, crl); - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eX509CRLError, NULL); - } - if (!i2a_ASN1_OBJECT(out, crl->sig_alg->algorithm)) { - BIO_free(out); - ossl_raise(eX509CRLError, NULL); - } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); - return str; + X509_CRL_get0_signature(crl, NULL, &alg); + X509_ALGOR_get0(&obj, NULL, NULL, alg); + return ossl_asn1obj_to_string_long_name(obj); } static VALUE @@ -213,7 +206,7 @@ ossl_x509crl_set_issuer(VALUE self, VALUE issuer) GetX509CRL(self, crl); if (!X509_CRL_set_issuer_name(crl, GetX509NamePtr(issuer))) { /* DUPs name */ - ossl_raise(eX509CRLError, NULL); + ossl_raise(eX509CRLError, NULL); } return issuer; } @@ -222,23 +215,29 @@ static VALUE ossl_x509crl_get_last_update(VALUE self) { X509_CRL *crl; + const ASN1_TIME *time; GetX509CRL(self, crl); + time = X509_CRL_get0_lastUpdate(crl); + if (!time) + return Qnil; - return asn1time_to_time(X509_CRL_get_lastUpdate(crl)); + return asn1time_to_time(time); } static VALUE ossl_x509crl_set_last_update(VALUE self, VALUE time) { X509_CRL *crl; - time_t sec; + ASN1_TIME *asn1time; - sec = time_to_time_t(time); GetX509CRL(self, crl); - if (!X509_time_adj(crl->crl->lastUpdate, 0, &sec)) { - ossl_raise(eX509CRLError, NULL); + asn1time = ossl_x509_time_adjust(NULL, time); + if (!X509_CRL_set1_lastUpdate(crl, asn1time)) { + ASN1_TIME_free(asn1time); + ossl_raise(eX509CRLError, "X509_CRL_set_lastUpdate"); } + ASN1_TIME_free(asn1time); return time; } @@ -247,24 +246,29 @@ static VALUE ossl_x509crl_get_next_update(VALUE self) { X509_CRL *crl; + const ASN1_TIME *time; GetX509CRL(self, crl); + time = X509_CRL_get0_nextUpdate(crl); + if (!time) + return Qnil; - return asn1time_to_time(X509_CRL_get_nextUpdate(crl)); + return asn1time_to_time(time); } static VALUE ossl_x509crl_set_next_update(VALUE self, VALUE time) { X509_CRL *crl; - time_t sec; + ASN1_TIME *asn1time; - sec = time_to_time_t(time); GetX509CRL(self, crl); - /* This must be some thinko in OpenSSL */ - if (!(crl->crl->nextUpdate = X509_time_adj(crl->crl->nextUpdate, 0, &sec))){ - ossl_raise(eX509CRLError, NULL); + asn1time = ossl_x509_time_adjust(NULL, time); + if (!X509_CRL_set1_nextUpdate(crl, asn1time)) { + ASN1_TIME_free(asn1time); + ossl_raise(eX509CRLError, "X509_CRL_set_nextUpdate"); } + ASN1_TIME_free(asn1time); return time; } @@ -274,21 +278,19 @@ ossl_x509crl_get_revoked(VALUE self) { X509_CRL *crl; int i, num; - X509_REVOKED *rev; - VALUE ary, revoked; + STACK_OF(X509_REVOKED) *sk; + VALUE ary; GetX509CRL(self, crl); - num = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl)); - if (num < 0) { - OSSL_Debug("num < 0???"); - return rb_ary_new(); - } - ary = rb_ary_new2(num); + sk = X509_CRL_get_REVOKED(crl); + if (!sk) + return rb_ary_new(); + + num = sk_X509_REVOKED_num(sk); + ary = rb_ary_new_capa(num); for(i=0; i<num; i++) { - /* NO DUP - don't free! */ - rev = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i); - revoked = ossl_x509revoked_new(rev); - rb_ary_push(ary, revoked); + X509_REVOKED *rev = sk_X509_REVOKED_value(sk, i); + rb_ary_push(ary, ossl_x509revoked_new(rev)); } return ary; @@ -299,21 +301,25 @@ ossl_x509crl_set_revoked(VALUE self, VALUE ary) { X509_CRL *crl; X509_REVOKED *rev; - int i; + STACK_OF(X509_REVOKED) *sk; + long i; Check_Type(ary, T_ARRAY); /* All ary members should be X509 Revoked */ for (i=0; i<RARRAY_LEN(ary); i++) { - OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Rev); + OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Rev); } GetX509CRL(self, crl); - sk_X509_REVOKED_pop_free(crl->crl->revoked, X509_REVOKED_free); - crl->crl->revoked = NULL; + if ((sk = X509_CRL_get_REVOKED(crl))) { + while ((rev = sk_X509_REVOKED_pop(sk))) + X509_REVOKED_free(rev); + } for (i=0; i<RARRAY_LEN(ary); i++) { - rev = DupX509RevokedPtr(RARRAY_PTR(ary)[i]); - if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */ - ossl_raise(eX509CRLError, NULL); - } + rev = DupX509RevokedPtr(RARRAY_AREF(ary, i)); + if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */ + X509_REVOKED_free(rev); + ossl_raise(eX509CRLError, "X509_CRL_add0_revoked"); + } } X509_CRL_sort(crl); @@ -329,7 +335,8 @@ ossl_x509crl_add_revoked(VALUE self, VALUE revoked) GetX509CRL(self, crl); rev = DupX509RevokedPtr(revoked); if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */ - ossl_raise(eX509CRLError, NULL); + X509_REVOKED_free(rev); + ossl_raise(eX509CRLError, "X509_CRL_add0_revoked"); } X509_CRL_sort(crl); @@ -342,13 +349,14 @@ ossl_x509crl_sign(VALUE self, VALUE key, VALUE digest) X509_CRL *crl; EVP_PKEY *pkey; const EVP_MD *md; + VALUE md_holder; GetX509CRL(self, crl); pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ - md = GetDigestPtr(digest); - if (!X509_CRL_sign(crl, pkey, md)) { - ossl_raise(eX509CRLError, NULL); - } + /* NULL needed for some key types, e.g. Ed25519 */ + md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder); + if (!X509_CRL_sign(crl, pkey, md)) + ossl_raise(eX509CRLError, "X509_CRL_sign"); return self; } @@ -357,17 +365,20 @@ static VALUE ossl_x509crl_verify(VALUE self, VALUE key) { X509_CRL *crl; - int ret; + EVP_PKEY *pkey; GetX509CRL(self, crl); - if ((ret = X509_CRL_verify(crl, GetPKeyPtr(key))) < 0) { - ossl_raise(eX509CRLError, NULL); - } - if (ret == 1) { - return Qtrue; + pkey = GetPKeyPtr(key); + ossl_pkey_check_public_key(pkey); + switch (X509_CRL_verify(crl, pkey)) { + case 1: + return Qtrue; + case 0: + ossl_clear_error(); + return Qfalse; + default: + ossl_raise(eX509CRLError, NULL); } - - return Qfalse; } static VALUE @@ -375,22 +386,17 @@ ossl_x509crl_to_der(VALUE self) { X509_CRL *crl; BIO *out; - BUF_MEM *buf; - VALUE str; GetX509CRL(self, crl); if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eX509CRLError, NULL); + ossl_raise(eX509CRLError, NULL); } if (!i2d_X509_CRL_bio(out, crl)) { - BIO_free(out); - ossl_raise(eX509CRLError, NULL); + BIO_free(out); + ossl_raise(eX509CRLError, NULL); } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); - return str; + return ossl_membio2str(out); } static VALUE @@ -398,22 +404,17 @@ ossl_x509crl_to_pem(VALUE self) { X509_CRL *crl; BIO *out; - BUF_MEM *buf; - VALUE str; GetX509CRL(self, crl); if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eX509CRLError, NULL); + ossl_raise(eX509CRLError, NULL); } if (!PEM_write_bio_X509_CRL(out, crl)) { - BIO_free(out); - ossl_raise(eX509CRLError, NULL); + BIO_free(out); + ossl_raise(eX509CRLError, NULL); } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); - return str; + return ossl_membio2str(out); } static VALUE @@ -421,22 +422,17 @@ ossl_x509crl_to_text(VALUE self) { X509_CRL *crl; BIO *out; - BUF_MEM *buf; - VALUE str; GetX509CRL(self, crl); if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eX509CRLError, NULL); + ossl_raise(eX509CRLError, NULL); } if (!X509_CRL_print(out, crl)) { - BIO_free(out); - ossl_raise(eX509CRLError, NULL); + BIO_free(out); + ossl_raise(eX509CRLError, NULL); } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); - return str; + return ossl_membio2str(out); } /* @@ -452,14 +448,10 @@ ossl_x509crl_get_extensions(VALUE self) GetX509CRL(self, crl); count = X509_CRL_get_ext_count(crl); - if (count < 0) { - OSSL_Debug("count < 0???"); - return rb_ary_new(); - } - ary = rb_ary_new2(count); + ary = rb_ary_new_capa(count); for (i=0; i<count; i++) { - ext = X509_CRL_get_ext(crl, i); /* NO DUP - don't free! */ - rb_ary_push(ary, ossl_x509ext_new(ext)); + ext = X509_CRL_get_ext(crl, i); /* NO DUP - don't free! */ + rb_ary_push(ary, ossl_x509ext_new(ext)); } return ary; @@ -473,23 +465,21 @@ ossl_x509crl_set_extensions(VALUE self, VALUE ary) { X509_CRL *crl; X509_EXTENSION *ext; - int i; + long i; Check_Type(ary, T_ARRAY); /* All ary members should be X509 Extensions */ for (i=0; i<RARRAY_LEN(ary); i++) { - OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext); + OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext); } GetX509CRL(self, crl); - sk_X509_EXTENSION_pop_free(crl->crl->extensions, X509_EXTENSION_free); - crl->crl->extensions = NULL; + for (i = X509_CRL_get_ext_count(crl); i > 0; i--) + X509_EXTENSION_free(X509_CRL_delete_ext(crl, 0)); for (i=0; i<RARRAY_LEN(ary); i++) { - ext = DupX509ExtPtr(RARRAY_PTR(ary)[i]); - if(!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */ - X509_EXTENSION_free(ext); - ossl_raise(eX509CRLError, NULL); - } - X509_EXTENSION_free(ext); + ext = GetX509ExtPtr(RARRAY_AREF(ary, i)); /* NO NEED TO DUP */ + if (!X509_CRL_add_ext(crl, ext, -1)) { + ossl_raise(eX509CRLError, "X509_CRL_add_ext"); + } } return ary; @@ -502,12 +492,10 @@ ossl_x509crl_add_extension(VALUE self, VALUE extension) X509_EXTENSION *ext; GetX509CRL(self, crl); - ext = DupX509ExtPtr(extension); - if (!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */ - X509_EXTENSION_free(ext); - ossl_raise(eX509CRLError, NULL); + ext = GetX509ExtPtr(extension); + if (!X509_CRL_add_ext(crl, ext, -1)) { + ossl_raise(eX509CRLError, NULL); } - X509_EXTENSION_free(ext); return extension; } @@ -524,7 +512,7 @@ Init_ossl_x509crl(void) rb_define_alloc_func(cX509CRL, ossl_x509crl_alloc); rb_define_method(cX509CRL, "initialize", ossl_x509crl_initialize, -1); - rb_define_copy_func(cX509CRL, ossl_x509crl_copy); + rb_define_method(cX509CRL, "initialize_copy", ossl_x509crl_copy, 1); rb_define_method(cX509CRL, "version", ossl_x509crl_get_version, 0); rb_define_method(cX509CRL, "version=", ossl_x509crl_set_version, 1); @@ -548,4 +536,3 @@ Init_ossl_x509crl(void) rb_define_method(cX509CRL, "extensions=", ossl_x509crl_set_extensions, 1); rb_define_method(cX509CRL, "add_extension", ossl_x509crl_add_extension, 1); } - diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c index faffe06a66..ef66ecc3fe 100644 --- a/ext/openssl/ossl_x509ext.c +++ b/ext/openssl/ossl_x509ext.c @@ -1,41 +1,39 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#define WrapX509Ext(klass, obj, ext) do { \ +#define NewX509Ext(klass) \ + TypedData_Wrap_Struct((klass), &ossl_x509ext_type, 0) +#define SetX509Ext(obj, ext) do { \ if (!(ext)) { \ - ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \ } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_x509ext_type, (ext)); \ + RTYPEDDATA_DATA(obj) = (ext); \ } while (0) #define GetX509Ext(obj, ext) do { \ TypedData_Get_Struct((obj), X509_EXTENSION, &ossl_x509ext_type, (ext)); \ if (!(ext)) { \ - ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \ } \ } while (0) -#define SafeGetX509Ext(obj, ext) do { \ - OSSL_Check_Kind((obj), cX509Ext); \ - GetX509Ext((obj), (ext)); \ -} while (0) #define MakeX509ExtFactory(klass, obj, ctx) do { \ + (obj) = TypedData_Wrap_Struct((klass), &ossl_x509extfactory_type, 0); \ if (!((ctx) = OPENSSL_malloc(sizeof(X509V3_CTX)))) \ ossl_raise(rb_eRuntimeError, "CTX wasn't allocated!"); \ X509V3_set_ctx((ctx), NULL, NULL, NULL, NULL, 0); \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_x509extfactory_type, (ctx)); \ + RTYPEDDATA_DATA(obj) = (ctx); \ } while (0) #define GetX509ExtFactory(obj, ctx) do { \ TypedData_Get_Struct((obj), X509V3_CTX, &ossl_x509extfactory_type, (ctx)); \ if (!(ctx)) { \ - ossl_raise(rb_eRuntimeError, "CTX wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "CTX wasn't initialized!"); \ } \ } while (0) @@ -43,8 +41,8 @@ * Classes */ VALUE cX509Ext; -VALUE cX509ExtFactory; -VALUE eX509ExtError; +static VALUE cX509ExtFactory; +static VALUE eX509ExtError; static void ossl_x509ext_free(void *ptr) @@ -55,9 +53,9 @@ ossl_x509ext_free(void *ptr) static const rb_data_type_t ossl_x509ext_type = { "OpenSSL/X509/EXTENSION", { - 0, ossl_x509ext_free, + 0, ossl_x509ext_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; /* @@ -69,15 +67,11 @@ ossl_x509ext_new(X509_EXTENSION *ext) X509_EXTENSION *new; VALUE obj; - if (!ext) { - new = X509_EXTENSION_new(); - } else { - new = X509_EXTENSION_dup(ext); - } - if (!new) { - ossl_raise(eX509ExtError, NULL); - } - WrapX509Ext(cX509Ext, obj, new); + obj = NewX509Ext(cX509Ext); + new = X509_EXTENSION_dup(ext); + if (!new) + ossl_raise(eX509ExtError, "X509_EXTENSION_dup"); + SetX509Ext(obj, new); return obj; } @@ -87,24 +81,11 @@ GetX509ExtPtr(VALUE obj) { X509_EXTENSION *ext; - SafeGetX509Ext(obj, ext); + GetX509Ext(obj, ext); return ext; } -X509_EXTENSION * -DupX509ExtPtr(VALUE obj) -{ - X509_EXTENSION *ext, *new; - - SafeGetX509Ext(obj, ext); - if (!(new = X509_EXTENSION_dup(ext))) { - ossl_raise(eX509ExtError, NULL); - } - - return new; -} - /* * Private */ @@ -120,9 +101,9 @@ ossl_x509extfactory_free(void *ctx) static const rb_data_type_t ossl_x509extfactory_type = { "OpenSSL/X509/EXTENSION/Factory", { - 0, ossl_x509extfactory_free, + 0, ossl_x509extfactory_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; static VALUE @@ -185,24 +166,6 @@ ossl_x509extfactory_set_crl(VALUE self, VALUE crl) return crl; } -#ifdef HAVE_X509V3_SET_NCONF -static VALUE -ossl_x509extfactory_set_config(VALUE self, VALUE config) -{ - X509V3_CTX *ctx; - CONF *conf; - - GetX509ExtFactory(self, ctx); - rb_iv_set(self, "@config", config); - conf = GetConfigPtr(config); /* NO DUP NEEDED */ - X509V3_set_nconf(ctx, conf); - - return config; -} -#else -#define ossl_x509extfactory_set_config rb_f_notimplement -#endif - static VALUE ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self) { @@ -212,26 +175,25 @@ ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self) /*GetX509ExtFactory(self, ctx);*/ rb_scan_args(argc, argv, "04", - &issuer_cert, &subject_cert, &subject_req, &crl); + &issuer_cert, &subject_cert, &subject_req, &crl); if (!NIL_P(issuer_cert)) - ossl_x509extfactory_set_issuer_cert(self, issuer_cert); + ossl_x509extfactory_set_issuer_cert(self, issuer_cert); if (!NIL_P(subject_cert)) - ossl_x509extfactory_set_subject_cert(self, subject_cert); + ossl_x509extfactory_set_subject_cert(self, subject_cert); if (!NIL_P(subject_req)) - ossl_x509extfactory_set_subject_req(self, subject_req); + ossl_x509extfactory_set_subject_req(self, subject_req); if (!NIL_P(crl)) - ossl_x509extfactory_set_crl(self, crl); + ossl_x509extfactory_set_crl(self, crl); return self; } /* - * Array to X509_EXTENSION - * Structure: - * ["ln", "value", bool_critical] or - * ["sn", "value", bool_critical] or - * ["ln", "critical,value"] or the same for sn - * ["ln", "value"] => not critical + * call-seq: + * ef.create_ext(ln_or_sn, "value", critical = false) -> X509::Extension + * ef.create_ext(ln_or_sn, "critical,value") -> X509::Extension + * + * Creates a new X509::Extension with passed values. See also x509v3_config(5). */ static VALUE ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self) @@ -240,37 +202,35 @@ ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self) X509_EXTENSION *ext; VALUE oid, value, critical, valstr, obj; int nid; -#ifdef HAVE_X509V3_EXT_NCONF_NID VALUE rconf; CONF *conf; -#else - static LHASH *empty_lhash; -#endif + const char *oid_cstr = NULL; rb_scan_args(argc, argv, "21", &oid, &value, &critical); - StringValue(oid); StringValue(value); if(NIL_P(critical)) critical = Qfalse; - nid = OBJ_ln2nid(RSTRING_PTR(oid)); - if(!nid) nid = OBJ_sn2nid(RSTRING_PTR(oid)); - if(!nid) ossl_raise(eX509ExtError, "unknown OID `%s'", RSTRING_PTR(oid)); + oid_cstr = StringValueCStr(oid); + nid = OBJ_ln2nid(oid_cstr); + if (nid != NID_undef) + oid_cstr = OBJ_nid2sn(nid); + valstr = rb_str_new2(RTEST(critical) ? "critical," : ""); rb_str_append(valstr, value); + StringValueCStr(valstr); + GetX509ExtFactory(self, ctx); -#ifdef HAVE_X509V3_EXT_NCONF_NID + obj = NewX509Ext(cX509Ext); rconf = rb_iv_get(self, "@config"); - conf = NIL_P(rconf) ? NULL : GetConfigPtr(rconf); - ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING_PTR(valstr)); -#else - if (!empty_lhash) empty_lhash = lh_new(NULL, NULL); - ext = X509V3_EXT_conf_nid(empty_lhash, ctx, nid, RSTRING_PTR(valstr)); -#endif + conf = NIL_P(rconf) ? NULL : GetConfig(rconf); + X509V3_set_nconf(ctx, conf); + + ext = X509V3_EXT_nconf(conf, ctx, oid_cstr, RSTRING_PTR(valstr)); + X509V3_set_ctx_nodb(ctx); if (!ext){ - ossl_raise(eX509ExtError, "%s = %s", - RSTRING_PTR(oid), RSTRING_PTR(value)); + ossl_raise(eX509ExtError, "%"PRIsVALUE" = %"PRIsVALUE, oid, valstr); } - WrapX509Ext(cX509Ext, obj, ext); + SetX509Ext(obj, ext); return obj; } @@ -284,25 +244,26 @@ ossl_x509ext_alloc(VALUE klass) X509_EXTENSION *ext; VALUE obj; + obj = NewX509Ext(klass); if(!(ext = X509_EXTENSION_new())){ - ossl_raise(eX509ExtError, NULL); + ossl_raise(eX509ExtError, NULL); } - WrapX509Ext(klass, obj, ext); + SetX509Ext(obj, ext); return obj; } /* * call-seq: - * OpenSSL::X509::Extension.new asn1 - * OpenSSL::X509::Extension.new name, value - * OpenSSL::X509::Extension.new name, value, critical + * OpenSSL::X509::Extension.new(der) + * OpenSSL::X509::Extension.new(oid, value) + * OpenSSL::X509::Extension.new(oid, value, critical) * * Creates an X509 extension. * - * The extension may be created from +asn1+ data or from an extension +name+ - * and +value+. The +name+ may be either an OID or an extension name. If - * +critical+ is true the extension is marked critical. + * The extension may be created from _der_ data or from an extension _oid_ + * and _value_. The _oid_ may be either an OID or an extension name. If + * _critical_ is +true+ the extension is marked critical. */ static VALUE ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self) @@ -313,14 +274,14 @@ ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self) GetX509Ext(self, ext); if(rb_scan_args(argc, argv, "12", &oid, &value, &critical) == 1){ - oid = ossl_to_der_if_possible(oid); - StringValue(oid); - p = (unsigned char *)RSTRING_PTR(oid); - x = d2i_X509_EXTENSION(&ext, &p, RSTRING_LEN(oid)); - DATA_PTR(self) = ext; - if(!x) - ossl_raise(eX509ExtError, NULL); - return self; + oid = ossl_to_der_if_possible(oid); + StringValue(oid); + p = (unsigned char *)RSTRING_PTR(oid); + x = d2i_X509_EXTENSION(&ext, &p, RSTRING_LEN(oid)); + DATA_PTR(self) = ext; + if(!x) + ossl_raise(eX509ExtError, NULL); + return self; } rb_funcall(self, rb_intern("oid="), 1, oid); rb_funcall(self, rb_intern("value="), 1, value); @@ -329,19 +290,41 @@ ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self) return self; } +/* :nodoc: */ +static VALUE +ossl_x509ext_initialize_copy(VALUE self, VALUE other) +{ + X509_EXTENSION *ext, *ext_other, *ext_new; + + rb_check_frozen(self); + GetX509Ext(self, ext); + GetX509Ext(other, ext_other); + + ext_new = X509_EXTENSION_dup(ext_other); + if (!ext_new) + ossl_raise(eX509ExtError, "X509_EXTENSION_dup"); + + SetX509Ext(self, ext_new); + X509_EXTENSION_free(ext); + + return self; +} + static VALUE ossl_x509ext_set_oid(VALUE self, VALUE oid) { X509_EXTENSION *ext; ASN1_OBJECT *obj; - char *s; - s = StringValuePtr(oid); - obj = OBJ_txt2obj(s, 0); - if(!obj) obj = OBJ_txt2obj(s, 1); - if(!obj) ossl_raise(eX509ExtError, NULL); GetX509Ext(self, ext); - X509_EXTENSION_set_object(ext, obj); + obj = OBJ_txt2obj(StringValueCStr(oid), 0); + if (!obj) + ossl_raise(eX509ExtError, "OBJ_txt2obj"); + if (!X509_EXTENSION_set_object(ext, obj)) { + ASN1_OBJECT_free(obj); + ossl_raise(eX509ExtError, "X509_EXTENSION_set_object"); + } + ASN1_OBJECT_free(obj); return oid; } @@ -351,25 +334,16 @@ ossl_x509ext_set_value(VALUE self, VALUE data) { X509_EXTENSION *ext; ASN1_OCTET_STRING *asn1s; - char *s; + GetX509Ext(self, ext); data = ossl_to_der_if_possible(data); StringValue(data); - if(!(s = OPENSSL_malloc(RSTRING_LEN(data)))) - ossl_raise(eX509ExtError, "malloc error"); - memcpy(s, RSTRING_PTR(data), RSTRING_LEN(data)); - if(!(asn1s = ASN1_OCTET_STRING_new())){ - OPENSSL_free(s); - ossl_raise(eX509ExtError, NULL); - } - if(!M_ASN1_OCTET_STRING_set(asn1s, s, RSTRING_LENINT(data))){ - OPENSSL_free(s); - ASN1_OCTET_STRING_free(asn1s); - ossl_raise(eX509ExtError, NULL); + asn1s = X509_EXTENSION_get_data(ext); + + if (!ASN1_OCTET_STRING_set(asn1s, (unsigned char *)RSTRING_PTR(data), + RSTRING_LENINT(data))) { + ossl_raise(eX509ExtError, "ASN1_OCTET_STRING_set"); } - OPENSSL_free(s); - GetX509Ext(self, ext); - X509_EXTENSION_set_data(ext, asn1s); return data; } @@ -385,27 +359,20 @@ ossl_x509ext_set_critical(VALUE self, VALUE flag) return flag; } +/* + * call-seq: + * ext.oid -> string + * + * Returns the OID of the extension. Returns the short name or the dotted + * decimal notation. + */ static VALUE ossl_x509ext_get_oid(VALUE obj) { X509_EXTENSION *ext; - ASN1_OBJECT *extobj; - BIO *out; - VALUE ret; - int nid; GetX509Ext(obj, ext); - extobj = X509_EXTENSION_get_object(ext); - if ((nid = OBJ_obj2nid(extobj)) != NID_undef) - ret = rb_str_new2(OBJ_nid2sn(nid)); - else{ - if (!(out = BIO_new(BIO_s_mem()))) - ossl_raise(eX509ExtError, NULL); - i2a_ASN1_OBJECT(out, extobj); - ret = ossl_membio2str(out); - } - - return ret; + return ossl_asn1obj_to_string(X509_EXTENSION_get_object(ext)); } static VALUE @@ -417,15 +384,28 @@ ossl_x509ext_get_value(VALUE obj) GetX509Ext(obj, ext); if (!(out = BIO_new(BIO_s_mem()))) - ossl_raise(eX509ExtError, NULL); + ossl_raise(eX509ExtError, NULL); if (!X509V3_EXT_print(out, ext, 0, 0)) - M_ASN1_OCTET_STRING_print(out, ext->value); + ASN1_STRING_print(out, (ASN1_STRING *)X509_EXTENSION_get_data(ext)); ret = ossl_membio2str(out); return ret; } static VALUE +ossl_x509ext_get_value_der(VALUE obj) +{ + X509_EXTENSION *ext; + ASN1_OCTET_STRING *value; + + GetX509Ext(obj, ext); + if ((value = X509_EXTENSION_get_data(ext)) == NULL) + ossl_raise(eX509ExtError, NULL); + + return asn1str_to_str(value); +} + +static VALUE ossl_x509ext_get_critical(VALUE obj) { X509_EXTENSION *ext; @@ -444,11 +424,11 @@ ossl_x509ext_to_der(VALUE obj) GetX509Ext(obj, ext); if((len = i2d_X509_EXTENSION(ext, NULL)) <= 0) - ossl_raise(eX509ExtError, NULL); + ossl_raise(eX509ExtError, NULL); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); if(i2d_X509_EXTENSION(ext, &p) < 0) - ossl_raise(eX509ExtError, NULL); + ossl_raise(eX509ExtError, NULL); ossl_str_adjust(str, p); return str; @@ -460,6 +440,7 @@ ossl_x509ext_to_der(VALUE obj) void Init_ossl_x509ext(void) { +#undef rb_intern eX509ExtError = rb_define_class_under(mX509, "ExtensionError", eOSSLError); cX509ExtFactory = rb_define_class_under(mX509, "ExtensionFactory", rb_cObject); @@ -471,23 +452,24 @@ Init_ossl_x509ext(void) rb_attr(cX509ExtFactory, rb_intern("subject_certificate"), 1, 0, Qfalse); rb_attr(cX509ExtFactory, rb_intern("subject_request"), 1, 0, Qfalse); rb_attr(cX509ExtFactory, rb_intern("crl"), 1, 0, Qfalse); - rb_attr(cX509ExtFactory, rb_intern("config"), 1, 0, Qfalse); + rb_attr(cX509ExtFactory, rb_intern("config"), 1, 1, Qfalse); rb_define_method(cX509ExtFactory, "issuer_certificate=", ossl_x509extfactory_set_issuer_cert, 1); rb_define_method(cX509ExtFactory, "subject_certificate=", ossl_x509extfactory_set_subject_cert, 1); rb_define_method(cX509ExtFactory, "subject_request=", ossl_x509extfactory_set_subject_req, 1); rb_define_method(cX509ExtFactory, "crl=", ossl_x509extfactory_set_crl, 1); - rb_define_method(cX509ExtFactory, "config=", ossl_x509extfactory_set_config, 1); rb_define_method(cX509ExtFactory, "create_ext", ossl_x509extfactory_create_ext, -1); cX509Ext = rb_define_class_under(mX509, "Extension", rb_cObject); rb_define_alloc_func(cX509Ext, ossl_x509ext_alloc); rb_define_method(cX509Ext, "initialize", ossl_x509ext_initialize, -1); + rb_define_method(cX509Ext, "initialize_copy", ossl_x509ext_initialize_copy, 1); rb_define_method(cX509Ext, "oid=", ossl_x509ext_set_oid, 1); rb_define_method(cX509Ext, "value=", ossl_x509ext_set_value, 1); rb_define_method(cX509Ext, "critical=", ossl_x509ext_set_critical, 1); rb_define_method(cX509Ext, "oid", ossl_x509ext_get_oid, 0); rb_define_method(cX509Ext, "value", ossl_x509ext_get_value, 0); + rb_define_method(cX509Ext, "value_der", ossl_x509ext_get_value_der, 0); rb_define_method(cX509Ext, "critical?", ossl_x509ext_get_critical, 0); rb_define_method(cX509Ext, "to_der", ossl_x509ext_to_der, 0); } diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c index 546cf3bf2c..5b3c3f7261 100644 --- a/ext/openssl/ossl_x509name.c +++ b/ext/openssl/ossl_x509name.c @@ -1,42 +1,39 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#define WrapX509Name(klass, obj, name) do { \ +#define NewX509Name(klass) \ + TypedData_Wrap_Struct((klass), &ossl_x509name_type, 0) +#define SetX509Name(obj, name) do { \ if (!(name)) { \ - ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \ + ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \ } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_x509name_type, (name)); \ + RTYPEDDATA_DATA(obj) = (name); \ } while (0) #define GetX509Name(obj, name) do { \ TypedData_Get_Struct((obj), X509_NAME, &ossl_x509name_type, (name)); \ if (!(name)) { \ - ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \ + ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \ } \ } while (0) -#define SafeGetX509Name(obj, name) do { \ - OSSL_Check_Kind((obj), cX509Name); \ - GetX509Name((obj), (name)); \ -} while (0) #define OBJECT_TYPE_TEMPLATE \ - rb_const_get(cX509Name, rb_intern("OBJECT_TYPE_TEMPLATE")) + rb_const_get(cX509Name, rb_intern("OBJECT_TYPE_TEMPLATE")) #define DEFAULT_OBJECT_TYPE \ - rb_const_get(cX509Name, rb_intern("DEFAULT_OBJECT_TYPE")) + rb_const_get(cX509Name, rb_intern("DEFAULT_OBJECT_TYPE")) /* * Classes */ -VALUE cX509Name; -VALUE eX509NameError; +static VALUE cX509Name; +static VALUE eX509NameError; static void ossl_x509name_free(void *ptr) @@ -47,9 +44,9 @@ ossl_x509name_free(void *ptr) static const rb_data_type_t ossl_x509name_type = { "OpenSSL/X509/NAME", { - 0, ossl_x509name_free, + 0, ossl_x509name_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; /* @@ -61,15 +58,11 @@ ossl_x509name_new(X509_NAME *name) X509_NAME *new; VALUE obj; - if (!name) { - new = X509_NAME_new(); - } else { - new = X509_NAME_dup(name); - } - if (!new) { - ossl_raise(eX509NameError, NULL); - } - WrapX509Name(cX509Name, obj, new); + obj = NewX509Name(cX509Name); + new = X509_NAME_dup(name); + if (!new) + ossl_raise(eX509NameError, "X509_NAME_dup"); + SetX509Name(obj, new); return obj; } @@ -79,7 +72,7 @@ GetX509NamePtr(VALUE obj) { X509_NAME *name; - SafeGetX509Name(obj, name); + GetX509Name(obj, name); return name; } @@ -93,10 +86,11 @@ ossl_x509name_alloc(VALUE klass) X509_NAME *name; VALUE obj; + obj = NewX509Name(klass); if (!(name = X509_NAME_new())) { - ossl_raise(eX509NameError, NULL); + ossl_raise(eX509NameError, NULL); } - WrapX509Name(klass, obj, name); + SetX509Name(obj, name); return obj; } @@ -132,15 +126,15 @@ ossl_x509name_init_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) * * Creates a new Name. * - * A name may be created from a DER encoded string +der+, an Array - * representing a +distinguished_name+ or a +distinguished_name+ along with a - * +template+. + * A name may be created from a DER encoded string _der_, an Array + * representing a _distinguished_name_ or a _distinguished_name_ along with a + * _template_. * * name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']] * * name = OpenSSL::X509::Name.new name.to_der * - * See add_entry for a description of the +distinguished_name+ Array's + * See add_entry for a description of the _distinguished_name_ Array's * contents */ static VALUE @@ -151,38 +145,58 @@ ossl_x509name_initialize(int argc, VALUE *argv, VALUE self) GetX509Name(self, name); if (rb_scan_args(argc, argv, "02", &arg, &template) == 0) { - return self; + return self; } else { - VALUE tmp = rb_check_array_type(arg); - if (!NIL_P(tmp)) { - VALUE args; - if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE; - args = rb_ary_new3(2, self, template); - rb_block_call(tmp, rb_intern("each"), 0, 0, ossl_x509name_init_i, args); - } - else{ - const unsigned char *p; - VALUE str = ossl_to_der_if_possible(arg); - X509_NAME *x; - StringValue(str); - p = (unsigned char *)RSTRING_PTR(str); - x = d2i_X509_NAME(&name, &p, RSTRING_LEN(str)); - DATA_PTR(self) = name; - if(!x){ - ossl_raise(eX509NameError, NULL); - } - } + VALUE tmp = rb_check_array_type(arg); + if (!NIL_P(tmp)) { + VALUE args; + if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE; + args = rb_ary_new3(2, self, template); + rb_block_call(tmp, rb_intern("each"), 0, 0, ossl_x509name_init_i, args); + } + else{ + const unsigned char *p; + VALUE str = ossl_to_der_if_possible(arg); + X509_NAME *x; + StringValue(str); + p = (unsigned char *)RSTRING_PTR(str); + x = d2i_X509_NAME(&name, &p, RSTRING_LEN(str)); + DATA_PTR(self) = name; + if(!x){ + ossl_raise(eX509NameError, NULL); + } + } } return self; } +/* :nodoc: */ +static VALUE +ossl_x509name_initialize_copy(VALUE self, VALUE other) +{ + X509_NAME *name, *name_other, *name_new; + + rb_check_frozen(self); + GetX509Name(self, name); + GetX509Name(other, name_other); + + name_new = X509_NAME_dup(name_other); + if (!name_new) + ossl_raise(eX509NameError, "X509_NAME_dup"); + + SetX509Name(self, name_new); + X509_NAME_free(name); + + return self; +} + /* * call-seq: - * name.add_entry(oid, value [, type]) => self + * name.add_entry(oid, value [, type], loc: -1, set: 0) => self * - * Adds a new entry with the given +oid+ and +value+ to this name. The +oid+ + * Adds a new entry with the given _oid_ and _value_ to this name. The _oid_ * is an object identifier defined in ASN.1. Some common OIDs are: * * C:: Country Name @@ -191,24 +205,39 @@ ossl_x509name_initialize(int argc, VALUE *argv, VALUE self) * O:: Organization Name * OU:: Organizational Unit Name * ST:: State or Province Name + * + * The optional keyword parameters _loc_ and _set_ specify where to insert the + * new attribute. Refer to the manpage of X509_NAME_add_entry(3) for details. + * _loc_ defaults to -1 and _set_ defaults to 0. This appends a single-valued + * RDN to the end. */ static VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self) { X509_NAME *name; - VALUE oid, value, type; + VALUE oid, value, type, opts, kwargs[2]; + static ID kwargs_ids[2]; const char *oid_name; + int loc = -1, set = 0; - rb_scan_args(argc, argv, "21", &oid, &value, &type); + if (!kwargs_ids[0]) { + kwargs_ids[0] = rb_intern_const("loc"); + kwargs_ids[1] = rb_intern_const("set"); + } + rb_scan_args(argc, argv, "21:", &oid, &value, &type, &opts); + rb_get_kwargs(opts, kwargs_ids, 0, 2, kwargs); oid_name = StringValueCStr(oid); StringValue(value); if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid); + if (kwargs[0] != Qundef) + loc = NUM2INT(kwargs[0]); + if (kwargs[1] != Qundef) + set = NUM2INT(kwargs[1]); GetX509Name(self, name); if (!X509_NAME_add_entry_by_txt(name, oid_name, NUM2INT(type), - (const unsigned char *)RSTRING_PTR(value), RSTRING_LENINT(value), -1, 0)) { - ossl_raise(eX509NameError, NULL); - } - + (unsigned char *)RSTRING_PTR(value), + RSTRING_LENINT(value), loc, set)) + ossl_raise(eX509NameError, "X509_NAME_add_entry_by_txt"); return self; } @@ -217,52 +246,90 @@ ossl_x509name_to_s_old(VALUE self) { X509_NAME *name; char *buf; - VALUE str; GetX509Name(self, name); buf = X509_NAME_oneline(name, NULL, 0); - str = rb_str_new2(buf); - OPENSSL_free(buf); + if (!buf) + ossl_raise(eX509NameError, "X509_NAME_oneline"); + return ossl_buf2str(buf, rb_long2int(strlen(buf))); +} - return str; +static VALUE +x509name_print(VALUE self, unsigned long iflag) +{ + X509_NAME *name; + BIO *out; + int ret; + + GetX509Name(self, name); + out = BIO_new(BIO_s_mem()); + if (!out) + ossl_raise(eX509NameError, NULL); + ret = X509_NAME_print_ex(out, name, 0, iflag); + if (ret < 0 || (iflag == XN_FLAG_COMPAT && ret == 0)) { + BIO_free(out); + ossl_raise(eX509NameError, "X509_NAME_print_ex"); + } + return ossl_membio2str(out); } /* * call-seq: - * name.to_s => string - * name.to_s(flags) => string + * name.to_s -> string + * name.to_s(format) -> string * - * Returns this name as a Distinguished Name string. +flags+ may be one of: + * Returns a String representation of the Distinguished Name. _format_ is + * one of: * * * OpenSSL::X509::Name::COMPAT * * OpenSSL::X509::Name::RFC2253 * * OpenSSL::X509::Name::ONELINE * * OpenSSL::X509::Name::MULTILINE + * + * If _format_ is omitted, the largely broken and traditional OpenSSL format + * (<tt>X509_NAME_oneline()</tt> format) is chosen. + * + * <b>Use of this method is discouraged.</b> None of the formats other than + * OpenSSL::X509::Name::RFC2253 is standardized and may show an inconsistent + * behavior through \OpenSSL versions. + * + * It is recommended to use #to_utf8 instead, which is equivalent to calling + * <tt>name.to_s(OpenSSL::X509::Name::RFC2253).force_encoding("UTF-8")</tt>. */ static VALUE ossl_x509name_to_s(int argc, VALUE *argv, VALUE self) { - X509_NAME *name; - VALUE flag, str; - BIO *out; - unsigned long iflag; - - rb_scan_args(argc, argv, "01", &flag); - if (NIL_P(flag)) - return ossl_x509name_to_s_old(self); - else iflag = NUM2ULONG(flag); - if (!(out = BIO_new(BIO_s_mem()))) - ossl_raise(eX509NameError, NULL); - GetX509Name(self, name); - if (!X509_NAME_print_ex(out, name, 0, iflag)){ - BIO_free(out); - ossl_raise(eX509NameError, NULL); - } - str = ossl_membio2str(out); + rb_check_arity(argc, 0, 1); + /* name.to_s(nil) was allowed */ + if (!argc || NIL_P(argv[0])) + return ossl_x509name_to_s_old(self); + else + return x509name_print(self, NUM2ULONG(argv[0])); +} +/* + * call-seq: + * name.to_utf8 -> string + * + * Returns an UTF-8 representation of the distinguished name, as specified + * in {RFC 2253}[https://www.ietf.org/rfc/rfc2253.txt]. + */ +static VALUE +ossl_x509name_to_utf8(VALUE self) +{ + VALUE str = x509name_print(self, XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB); + rb_enc_associate_index(str, rb_utf8_encindex()); return str; } +/* :nodoc: */ +static VALUE +ossl_x509name_inspect(VALUE self) +{ + return rb_enc_sprintf(rb_utf8_encoding(), "#<%"PRIsVALUE" %"PRIsVALUE">", + rb_obj_class(self), ossl_x509name_to_utf8(self)); +} + /* * call-seq: * name.to_a => [[name, data, type], ...] @@ -274,38 +341,22 @@ static VALUE ossl_x509name_to_a(VALUE self) { X509_NAME *name; - X509_NAME_ENTRY *entry; - int i,entries,nid; - char long_name[512]; - const char *short_name; - VALUE ary, vname, ret; + int entries; + VALUE ret; GetX509Name(self, name); entries = X509_NAME_entry_count(name); - if (entries < 0) { - OSSL_Debug("name entries < 0!"); - return rb_ary_new(); - } - ret = rb_ary_new2(entries); - for (i=0; i<entries; i++) { - if (!(entry = X509_NAME_get_entry(name, i))) { - ossl_raise(eX509NameError, NULL); - } - if (!i2t_ASN1_OBJECT(long_name, sizeof(long_name), entry->object)) { - ossl_raise(eX509NameError, NULL); - } - nid = OBJ_ln2nid(long_name); - if (nid == NID_undef) { - vname = rb_str_new2((const char *) &long_name); - } else { - short_name = OBJ_nid2sn(nid); - vname = rb_str_new2(short_name); /*do not free*/ - } - ary = rb_ary_new3(3, - vname, - rb_str_new((const char *)entry->value->data, entry->value->length), - INT2FIX(entry->value->type)); - rb_ary_push(ret, ary); + ret = rb_ary_new_capa(entries); + for (int i = 0; i < entries; i++) { + const X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); + if (!entry) + ossl_raise(eX509NameError, "X509_NAME_get_entry"); + const ASN1_OBJECT *obj = X509_NAME_ENTRY_get_object(entry); + VALUE vname = ossl_asn1obj_to_string(obj); + const ASN1_STRING *data = X509_NAME_ENTRY_get_data(entry); + VALUE vdata = asn1str_to_str(data); + VALUE type = INT2NUM(ASN1_STRING_type(data)); + rb_ary_push(ret, rb_ary_new_from_args(3, vname, vdata, type)); } return ret; } @@ -316,46 +367,48 @@ ossl_x509name_cmp0(VALUE self, VALUE other) X509_NAME *name1, *name2; GetX509Name(self, name1); - SafeGetX509Name(other, name2); + GetX509Name(other, name2); return X509_NAME_cmp(name1, name2); } /* * call-seq: - * name.cmp other => integer - * name.<=> other => integer + * name.cmp(other) -> -1 | 0 | 1 | nil + * name <=> other -> -1 | 0 | 1 | nil * - * Compares this Name with +other+ and returns 0 if they are the same and -1 or - * +1 if they are greater or less than each other respectively. + * Compares this Name with _other_ and returns +0+ if they are the same and +-1+ + * or ++1+ if they are greater or less than each other respectively. + * Returns +nil+ if they are not comparable (i.e. different types). */ static VALUE ossl_x509name_cmp(VALUE self, VALUE other) { int result; + if (!rb_obj_is_kind_of(other, cX509Name)) + return Qnil; + result = ossl_x509name_cmp0(self, other); if (result < 0) return INT2FIX(-1); - if (result > 1) return INT2FIX(1); + if (result > 0) return INT2FIX(1); return INT2FIX(0); } /* * call-seq: - * name.eql? other => boolean + * name.eql?(other) -> true | false * - * Returns true if +name+ and +other+ refer to the same hash key. + * Returns true if _name_ and _other_ refer to the same hash key. */ static VALUE ossl_x509name_eql(VALUE self, VALUE other) { - int result; - - if(CLASS_OF(other) != cX509Name) return Qfalse; - result = ossl_x509name_cmp0(self, other); + if (!rb_obj_is_kind_of(other, cX509Name)) + return Qfalse; - return (result == 0) ? Qtrue : Qfalse; + return ossl_x509name_cmp0(self, other) == 0 ? Qtrue : Qfalse; } /* @@ -378,7 +431,6 @@ ossl_x509name_hash(VALUE self) return ULONG2NUM(hash); } -#ifdef HAVE_X509_NAME_HASH_OLD /* * call-seq: * name.hash_old => integer @@ -397,7 +449,6 @@ ossl_x509name_hash_old(VALUE self) return ULONG2NUM(hash); } -#endif /* * call-seq: @@ -415,11 +466,11 @@ ossl_x509name_to_der(VALUE self) GetX509Name(self, name); if((len = i2d_X509_NAME(name, NULL)) <= 0) - ossl_raise(eX509NameError, NULL); + ossl_raise(eX509NameError, NULL); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); if(i2d_X509_NAME(name, &p) <= 0) - ossl_raise(eX509NameError, NULL); + ossl_raise(eX509NameError, NULL); ossl_str_adjust(str, p); return str; @@ -434,7 +485,7 @@ ossl_x509name_to_der(VALUE self) * You can create a Name by parsing a distinguished name String or by * supplying the distinguished name as an Array. * - * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example' + * name = OpenSSL::X509::Name.parse_rfc2253 'DC=example,CN=nobody' * * name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']] */ @@ -442,6 +493,7 @@ ossl_x509name_to_der(VALUE self) void Init_ossl_x509name(void) { +#undef rb_intern VALUE utf8str, ptrstr, ia5str, hash; id_aref = rb_intern("[]"); @@ -452,24 +504,24 @@ Init_ossl_x509name(void) rb_define_alloc_func(cX509Name, ossl_x509name_alloc); rb_define_method(cX509Name, "initialize", ossl_x509name_initialize, -1); + rb_define_method(cX509Name, "initialize_copy", ossl_x509name_initialize_copy, 1); rb_define_method(cX509Name, "add_entry", ossl_x509name_add_entry, -1); rb_define_method(cX509Name, "to_s", ossl_x509name_to_s, -1); + rb_define_method(cX509Name, "to_utf8", ossl_x509name_to_utf8, 0); + rb_define_method(cX509Name, "inspect", ossl_x509name_inspect, 0); rb_define_method(cX509Name, "to_a", ossl_x509name_to_a, 0); rb_define_method(cX509Name, "cmp", ossl_x509name_cmp, 1); rb_define_alias(cX509Name, "<=>", "cmp"); rb_define_method(cX509Name, "eql?", ossl_x509name_eql, 1); rb_define_method(cX509Name, "hash", ossl_x509name_hash, 0); -#ifdef HAVE_X509_NAME_HASH_OLD rb_define_method(cX509Name, "hash_old", ossl_x509name_hash_old, 0); -#endif rb_define_method(cX509Name, "to_der", ossl_x509name_to_der, 0); utf8str = INT2NUM(V_ASN1_UTF8STRING); ptrstr = INT2NUM(V_ASN1_PRINTABLESTRING); ia5str = INT2NUM(V_ASN1_IA5STRING); - /* Document-const: DEFAULT_OBJECT_TYPE - * + /* * The default object type for name entries. */ rb_define_const(cX509Name, "DEFAULT_OBJECT_TYPE", utf8str); @@ -482,15 +534,14 @@ Init_ossl_x509name(void) rb_hash_aset(hash, rb_str_new2("DC"), ia5str); rb_hash_aset(hash, rb_str_new2("domainComponent"), ia5str); rb_hash_aset(hash, rb_str_new2("emailAddress"), ia5str); + rb_obj_freeze(hash); - /* Document-const: OBJECT_TYPE_TEMPLATE - * + /* * The default object type template for name entries. */ rb_define_const(cX509Name, "OBJECT_TYPE_TEMPLATE", hash); - /* Document-const: COMPAT - * + /* * A flag for #to_s. * * Breaks the name returned into multiple lines if longer than 80 @@ -498,24 +549,21 @@ Init_ossl_x509name(void) */ rb_define_const(cX509Name, "COMPAT", ULONG2NUM(XN_FLAG_COMPAT)); - /* Document-const: RFC2253 - * + /* * A flag for #to_s. * * Returns an RFC2253 format name. */ rb_define_const(cX509Name, "RFC2253", ULONG2NUM(XN_FLAG_RFC2253)); - /* Document-const: ONELINE - * + /* * A flag for #to_s. * * Returns a more readable format than RFC2253. */ rb_define_const(cX509Name, "ONELINE", ULONG2NUM(XN_FLAG_ONELINE)); - /* Document-const: MULTILINE - * + /* * A flag for #to_s. * * Returns a multiline format. diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c index 529b68500c..433cc461a9 100644 --- a/ext/openssl/ossl_x509req.c +++ b/ext/openssl/ossl_x509req.c @@ -1,37 +1,34 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#define WrapX509Req(klass, obj, req) do { \ +#define NewX509Req(klass) \ + TypedData_Wrap_Struct((klass), &ossl_x509req_type, 0) +#define SetX509Req(obj, req) do { \ if (!(req)) { \ - ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \ } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_x509req_type, (req)); \ + RTYPEDDATA_DATA(obj) = (req); \ } while (0) #define GetX509Req(obj, req) do { \ TypedData_Get_Struct((obj), X509_REQ, &ossl_x509req_type, (req)); \ if (!(req)) { \ - ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \ } \ } while (0) -#define SafeGetX509Req(obj, req) do { \ - OSSL_Check_Kind((obj), cX509Req); \ - GetX509Req((obj), (req)); \ -} while (0) /* * Classes */ -VALUE cX509Req; -VALUE eX509ReqError; +static VALUE cX509Req; +static VALUE eX509ReqError; static void ossl_x509req_free(void *ptr) @@ -42,56 +39,24 @@ ossl_x509req_free(void *ptr) static const rb_data_type_t ossl_x509req_type = { "OpenSSL/X509/REQ", { - 0, ossl_x509req_free, + 0, ossl_x509req_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; /* * Public functions */ -VALUE -ossl_x509req_new(X509_REQ *req) -{ - X509_REQ *new; - VALUE obj; - - if (!req) { - new = X509_REQ_new(); - } else { - new = X509_REQ_dup(req); - } - if (!new) { - ossl_raise(eX509ReqError, NULL); - } - WrapX509Req(cX509Req, obj, new); - - return obj; -} - X509_REQ * GetX509ReqPtr(VALUE obj) { X509_REQ *req; - SafeGetX509Req(obj, req); + GetX509Req(obj, req); return req; } -X509_REQ * -DupX509ReqPtr(VALUE obj) -{ - X509_REQ *req, *new; - - SafeGetX509Req(obj, req); - if (!(new = X509_REQ_dup(req))) { - ossl_raise(eX509ReqError, NULL); - } - - return new; -} - /* * Private functions */ @@ -101,10 +66,11 @@ ossl_x509req_alloc(VALUE klass) X509_REQ *req; VALUE obj; + obj = NewX509Req(klass); if (!(req = X509_REQ_new())) { - ossl_raise(eX509ReqError, NULL); + ossl_raise(eX509ReqError, NULL); } - WrapX509Req(klass, obj, req); + SetX509Req(obj, req); return obj; } @@ -113,27 +79,31 @@ static VALUE ossl_x509req_initialize(int argc, VALUE *argv, VALUE self) { BIO *in; - X509_REQ *req, *x = DATA_PTR(self); + X509_REQ *req, *req_orig = RTYPEDDATA_DATA(self); VALUE arg; + rb_check_frozen(self); if (rb_scan_args(argc, argv, "01", &arg) == 0) { - return self; + return self; } arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(arg); - req = PEM_read_bio_X509_REQ(in, &x, NULL, NULL); - DATA_PTR(self) = x; + in = ossl_obj2bio(&arg); + req = d2i_X509_REQ_bio(in, NULL); if (!req) { - OSSL_BIO_reset(in); - req = d2i_X509_REQ_bio(in, &x); - DATA_PTR(self) = x; + OSSL_BIO_reset(in); + req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); } BIO_free(in); - if (!req) ossl_raise(eX509ReqError, NULL); + if (!req) + ossl_raise(eX509ReqError, "PEM_read_bio_X509_REQ"); + + RTYPEDDATA_DATA(self) = req; + X509_REQ_free(req_orig); return self; } +/* :nodoc: */ static VALUE ossl_x509req_copy(VALUE self, VALUE other) { @@ -142,9 +112,9 @@ ossl_x509req_copy(VALUE self, VALUE other) rb_check_frozen(self); if (self == other) return self; GetX509Req(self, a); - SafeGetX509Req(other, b); + GetX509Req(other, b); if (!(req = X509_REQ_dup(b))) { - ossl_raise(eX509ReqError, NULL); + ossl_raise(eX509ReqError, NULL); } X509_REQ_free(a); DATA_PTR(self) = req; @@ -157,22 +127,17 @@ ossl_x509req_to_pem(VALUE self) { X509_REQ *req; BIO *out; - BUF_MEM *buf; - VALUE str; GetX509Req(self, req); if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eX509ReqError, NULL); + ossl_raise(eX509ReqError, NULL); } if (!PEM_write_bio_X509_REQ(out, req)) { - BIO_free(out); - ossl_raise(eX509ReqError, NULL); + BIO_free(out); + ossl_raise(eX509ReqError, NULL); } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); - return str; + return ossl_membio2str(out); } static VALUE @@ -185,11 +150,11 @@ ossl_x509req_to_der(VALUE self) GetX509Req(self, req); if ((len = i2d_X509_REQ(req, NULL)) <= 0) - ossl_raise(eX509ReqError, NULL); + ossl_raise(eX509ReqError, NULL); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); if (i2d_X509_REQ(req, &p) <= 0) - ossl_raise(eX509ReqError, NULL); + ossl_raise(eX509ReqError, NULL); ossl_str_adjust(str, p); return str; @@ -200,22 +165,17 @@ ossl_x509req_to_text(VALUE self) { X509_REQ *req; BIO *out; - BUF_MEM *buf; - VALUE str; GetX509Req(self, req); if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eX509ReqError, NULL); + ossl_raise(eX509ReqError, NULL); } if (!X509_REQ_print(out, req)) { - BIO_free(out); - ossl_raise(eX509ReqError, NULL); + BIO_free(out); + ossl_raise(eX509ReqError, NULL); } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); - return str; + return ossl_membio2str(out); } #if 0 @@ -231,7 +191,7 @@ ossl_x509req_to_x509(VALUE self, VALUE days, VALUE key) GetX509Req(self, req); ... if (!(x509 = X509_REQ_to_X509(req, d, pkey))) { - ossl_raise(eX509ReqError, NULL); + ossl_raise(eX509ReqError, NULL); } return ossl_x509_new(x509); @@ -247,7 +207,7 @@ ossl_x509req_get_version(VALUE self) GetX509Req(self, req); version = X509_REQ_get_version(req); - return LONG2FIX(version); + return LONG2NUM(version); } static VALUE @@ -256,12 +216,12 @@ ossl_x509req_set_version(VALUE self, VALUE version) X509_REQ *req; long ver; - if ((ver = FIX2LONG(version)) < 0) { - ossl_raise(eX509ReqError, "version must be >= 0!"); + if ((ver = NUM2LONG(version)) < 0) { + ossl_raise(eX509ReqError, "version must be >= 0!"); } GetX509Req(self, req); if (!X509_REQ_set_version(req, ver)) { - ossl_raise(eX509ReqError, NULL); + ossl_raise(eX509ReqError, "X509_REQ_set_version"); } return version; @@ -275,7 +235,7 @@ ossl_x509req_get_subject(VALUE self) GetX509Req(self, req); if (!(name = X509_REQ_get_subject_name(req))) { /* NO DUP - don't free */ - ossl_raise(eX509ReqError, NULL); + ossl_raise(eX509ReqError, NULL); } return ossl_x509name_new(name); @@ -289,33 +249,32 @@ ossl_x509req_set_subject(VALUE self, VALUE subject) GetX509Req(self, req); /* DUPs name */ if (!X509_REQ_set_subject_name(req, GetX509NamePtr(subject))) { - ossl_raise(eX509ReqError, NULL); + ossl_raise(eX509ReqError, NULL); } return subject; } +/* + * call-seq: + * req.signature_algorithm -> string + * + * Returns the signature algorithm used to sign this request. + * + * Returns the long name of the signature algorithm, or the dotted decimal + * notation if \OpenSSL does not define a long name for it. + */ static VALUE ossl_x509req_get_signature_algorithm(VALUE self) { X509_REQ *req; - BIO *out; - BUF_MEM *buf; - VALUE str; + const X509_ALGOR *alg; + const ASN1_OBJECT *obj; GetX509Req(self, req); - - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eX509ReqError, NULL); - } - if (!i2a_ASN1_OBJECT(out, req->sig_alg->algorithm)) { - BIO_free(out); - ossl_raise(eX509ReqError, NULL); - } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); - return str; + X509_REQ_get0_signature(req, NULL, &alg); + X509_ALGOR_get0(&obj, NULL, NULL, alg); + return ossl_asn1obj_to_string_long_name(obj); } static VALUE @@ -326,10 +285,10 @@ ossl_x509req_get_public_key(VALUE self) GetX509Req(self, req); if (!(pkey = X509_REQ_get_pubkey(req))) { /* adds reference */ - ossl_raise(eX509ReqError, NULL); + ossl_raise(eX509ReqError, NULL); } - return ossl_pkey_new(pkey); /* NO DUP - OK */ + return ossl_pkey_wrap(pkey); } static VALUE @@ -339,11 +298,10 @@ ossl_x509req_set_public_key(VALUE self, VALUE key) EVP_PKEY *pkey; GetX509Req(self, req); - pkey = GetPKeyPtr(key); /* NO NEED TO DUP */ - if (!X509_REQ_set_pubkey(req, pkey)) { - ossl_raise(eX509ReqError, NULL); - } - + pkey = GetPKeyPtr(key); + ossl_pkey_check_public_key(pkey); + if (!X509_REQ_set_pubkey(req, pkey)) + ossl_raise(eX509ReqError, "X509_REQ_set_pubkey"); return key; } @@ -353,13 +311,14 @@ ossl_x509req_sign(VALUE self, VALUE key, VALUE digest) X509_REQ *req; EVP_PKEY *pkey; const EVP_MD *md; + VALUE md_holder; GetX509Req(self, req); pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ - md = GetDigestPtr(digest); - if (!X509_REQ_sign(req, pkey, md)) { - ossl_raise(eX509ReqError, NULL); - } + /* NULL needed for some key types, e.g. Ed25519 */ + md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder); + if (!X509_REQ_sign(req, pkey, md)) + ossl_raise(eX509ReqError, "X509_REQ_sign"); return self; } @@ -372,18 +331,19 @@ ossl_x509req_verify(VALUE self, VALUE key) { X509_REQ *req; EVP_PKEY *pkey; - int i; GetX509Req(self, req); - pkey = GetPKeyPtr(key); /* NO NEED TO DUP */ - if ((i = X509_REQ_verify(req, pkey)) < 0) { - ossl_raise(eX509ReqError, NULL); - } - if (i > 0) { - return Qtrue; + pkey = GetPKeyPtr(key); + ossl_pkey_check_public_key(pkey); + switch (X509_REQ_verify(req, pkey)) { + case 1: + return Qtrue; + case 0: + ossl_clear_error(); + return Qfalse; + default: + ossl_raise(eX509ReqError, NULL); } - - return Qfalse; } static VALUE @@ -398,13 +358,13 @@ ossl_x509req_get_attributes(VALUE self) count = X509_REQ_get_attr_count(req); if (count < 0) { - OSSL_Debug("count < 0???"); - return rb_ary_new(); + OSSL_Debug("count < 0???"); + return rb_ary_new(); } ary = rb_ary_new2(count); for (i=0; i<count; i++) { - attr = X509_REQ_get_attr(req, i); - rb_ary_push(ary, ossl_x509attr_new(attr)); + attr = X509_REQ_get_attr(req, i); + rb_ary_push(ary, ossl_x509attr_new(attr)); } return ary; @@ -415,22 +375,22 @@ ossl_x509req_set_attributes(VALUE self, VALUE ary) { X509_REQ *req; X509_ATTRIBUTE *attr; - int i; + long i; VALUE item; Check_Type(ary, T_ARRAY); for (i=0;i<RARRAY_LEN(ary); i++) { - OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Attr); + OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Attr); } GetX509Req(self, req); - sk_X509_ATTRIBUTE_pop_free(req->req_info->attributes, X509_ATTRIBUTE_free); - req->req_info->attributes = NULL; + for (i = X509_REQ_get_attr_count(req); i > 0; i--) + X509_ATTRIBUTE_free(X509_REQ_delete_attr(req, 0)); for (i=0;i<RARRAY_LEN(ary); i++) { - item = RARRAY_PTR(ary)[i]; - attr = DupX509AttrPtr(item); - if (!X509_REQ_add1_attr(req, attr)) { - ossl_raise(eX509ReqError, NULL); - } + item = RARRAY_AREF(ary, i); + attr = GetX509AttrPtr(item); + if (!X509_REQ_add1_attr(req, attr)) { + ossl_raise(eX509ReqError, "X509_REQ_add1_attr"); + } } return ary; } @@ -441,8 +401,8 @@ ossl_x509req_add_attribute(VALUE self, VALUE attr) X509_REQ *req; GetX509Req(self, req); - if (!X509_REQ_add1_attr(req, DupX509AttrPtr(attr))) { - ossl_raise(eX509ReqError, NULL); + if (!X509_REQ_add1_attr(req, GetX509AttrPtr(attr))) { + ossl_raise(eX509ReqError, NULL); } return attr; @@ -460,7 +420,7 @@ Init_ossl_x509req(void) rb_define_alloc_func(cX509Req, ossl_x509req_alloc); rb_define_method(cX509Req, "initialize", ossl_x509req_initialize, -1); - rb_define_copy_func(cX509Req, ossl_x509req_copy); + rb_define_method(cX509Req, "initialize_copy", ossl_x509req_copy, 1); rb_define_method(cX509Req, "to_pem", ossl_x509req_to_pem, 0); rb_define_method(cX509Req, "to_der", ossl_x509req_to_der, 0); @@ -479,4 +439,3 @@ Init_ossl_x509req(void) rb_define_method(cX509Req, "attributes=", ossl_x509req_set_attributes, 1); rb_define_method(cX509Req, "add_attribute", ossl_x509req_add_attribute, 1); } - diff --git a/ext/openssl/ossl_x509revoked.c b/ext/openssl/ossl_x509revoked.c index 30c362c3cd..b88c390c72 100644 --- a/ext/openssl/ossl_x509revoked.c +++ b/ext/openssl/ossl_x509revoked.c @@ -1,37 +1,34 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#define WrapX509Rev(klass, obj, rev) do { \ +#define NewX509Rev(klass) \ + TypedData_Wrap_Struct((klass), &ossl_x509rev_type, 0) +#define SetX509Rev(obj, rev) do { \ if (!(rev)) { \ - ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \ } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_x509rev_type, (rev)); \ + RTYPEDDATA_DATA(obj) = (rev); \ } while (0) #define GetX509Rev(obj, rev) do { \ TypedData_Get_Struct((obj), X509_REVOKED, &ossl_x509rev_type, (rev)); \ if (!(rev)) { \ - ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \ } \ } while (0) -#define SafeGetX509Rev(obj, rev) do { \ - OSSL_Check_Kind((obj), cX509Rev); \ - GetX509Rev((obj), (rev)); \ -} while (0) /* * Classes */ VALUE cX509Rev; -VALUE eX509RevError; +static VALUE eX509RevError; static void ossl_x509rev_free(void *ptr) @@ -42,9 +39,9 @@ ossl_x509rev_free(void *ptr) static const rb_data_type_t ossl_x509rev_type = { "OpenSSL/X509/REV", { - 0, ossl_x509rev_free, + 0, ossl_x509rev_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; /* @@ -56,15 +53,11 @@ ossl_x509revoked_new(X509_REVOKED *rev) X509_REVOKED *new; VALUE obj; - if (!rev) { - new = X509_REVOKED_new(); - } else { - new = X509_REVOKED_dup(rev); - } - if (!new) { - ossl_raise(eX509RevError, NULL); - } - WrapX509Rev(cX509Rev, obj, new); + obj = NewX509Rev(cX509Rev); + new = X509_REVOKED_dup(rev); + if (!new) + ossl_raise(eX509RevError, "X509_REVOKED_dup"); + SetX509Rev(obj, new); return obj; } @@ -74,9 +67,9 @@ DupX509RevokedPtr(VALUE obj) { X509_REVOKED *rev, *new; - SafeGetX509Rev(obj, rev); + GetX509Rev(obj, rev); if (!(new = X509_REVOKED_dup(rev))) { - ossl_raise(eX509RevError, NULL); + ossl_raise(eX509RevError, NULL); } return new; @@ -91,10 +84,11 @@ ossl_x509revoked_alloc(VALUE klass) X509_REVOKED *rev; VALUE obj; + obj = NewX509Rev(klass); if (!(rev = X509_REVOKED_new())) { - ossl_raise(eX509RevError, NULL); + ossl_raise(eX509RevError, NULL); } - WrapX509Rev(klass, obj, rev); + SetX509Rev(obj, rev); return obj; } @@ -106,6 +100,26 @@ ossl_x509revoked_initialize(int argc, VALUE *argv, VALUE self) return self; } +/* :nodoc: */ +static VALUE +ossl_x509revoked_initialize_copy(VALUE self, VALUE other) +{ + X509_REVOKED *rev, *rev_other, *rev_new; + + rb_check_frozen(self); + GetX509Rev(self, rev); + GetX509Rev(other, rev_other); + + rev_new = X509_REVOKED_dup(rev_other); + if (!rev_new) + ossl_raise(eX509RevError, "X509_REVOKED_dup"); + + SetX509Rev(self, rev_new); + X509_REVOKED_free(rev); + + return self; +} + static VALUE ossl_x509revoked_get_serial(VALUE self) { @@ -113,16 +127,22 @@ ossl_x509revoked_get_serial(VALUE self) GetX509Rev(self, rev); - return asn1integer_to_num(rev->serialNumber); + return asn1integer_to_num(X509_REVOKED_get0_serialNumber(rev)); } static VALUE ossl_x509revoked_set_serial(VALUE self, VALUE num) { X509_REVOKED *rev; + ASN1_INTEGER *asn1int; GetX509Rev(self, rev); - rev->serialNumber = num_to_asn1integer(num, rev->serialNumber); + asn1int = num_to_asn1integer(num, NULL); + if (!X509_REVOKED_set_serialNumber(rev, asn1int)) { + ASN1_INTEGER_free(asn1int); + ossl_raise(eX509RevError, "X509_REVOKED_set_serialNumber"); + } + ASN1_INTEGER_free(asn1int); return num; } @@ -131,23 +151,29 @@ static VALUE ossl_x509revoked_get_time(VALUE self) { X509_REVOKED *rev; + const ASN1_TIME *time; GetX509Rev(self, rev); + time = X509_REVOKED_get0_revocationDate(rev); + if (!time) + return Qnil; - return asn1time_to_time(rev->revocationDate); + return asn1time_to_time(time); } static VALUE ossl_x509revoked_set_time(VALUE self, VALUE time) { X509_REVOKED *rev; - time_t sec; + ASN1_TIME *asn1time; - sec = time_to_time_t(time); GetX509Rev(self, rev); - if (!X509_time_adj(rev->revocationDate, 0, &sec)) { - ossl_raise(eX509RevError, NULL); + asn1time = ossl_x509_time_adjust(NULL, time); + if (!X509_REVOKED_set_revocationDate(rev, asn1time)) { + ASN1_TIME_free(asn1time); + ossl_raise(eX509RevError, "X509_REVOKED_set_revocationDate"); } + ASN1_TIME_free(asn1time); return time; } @@ -164,14 +190,10 @@ ossl_x509revoked_get_extensions(VALUE self) GetX509Rev(self, rev); count = X509_REVOKED_get_ext_count(rev); - if (count < 0) { - OSSL_Debug("count < 0???"); - return rb_ary_new(); - } - ary = rb_ary_new2(count); + ary = rb_ary_new_capa(count); for (i=0; i<count; i++) { - ext = X509_REVOKED_get_ext(rev, i); - rb_ary_push(ary, ossl_x509ext_new(ext)); + ext = X509_REVOKED_get_ext(rev, i); + rb_ary_push(ary, ossl_x509ext_new(ext)); } return ary; @@ -185,22 +207,22 @@ ossl_x509revoked_set_extensions(VALUE self, VALUE ary) { X509_REVOKED *rev; X509_EXTENSION *ext; - int i; + long i; VALUE item; Check_Type(ary, T_ARRAY); for (i=0; i<RARRAY_LEN(ary); i++) { - OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext); + OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext); } GetX509Rev(self, rev); - sk_X509_EXTENSION_pop_free(rev->extensions, X509_EXTENSION_free); - rev->extensions = NULL; + for (i = X509_REVOKED_get_ext_count(rev); i > 0; i--) + X509_EXTENSION_free(X509_REVOKED_delete_ext(rev, 0)); for (i=0; i<RARRAY_LEN(ary); i++) { - item = RARRAY_PTR(ary)[i]; - ext = DupX509ExtPtr(item); - if(!X509_REVOKED_add_ext(rev, ext, -1)) { - ossl_raise(eX509RevError, NULL); - } + item = RARRAY_AREF(ary, i); + ext = GetX509ExtPtr(item); + if(!X509_REVOKED_add_ext(rev, ext, -1)) { + ossl_raise(eX509RevError, "X509_REVOKED_add_ext"); + } } return ary; @@ -212,13 +234,33 @@ ossl_x509revoked_add_extension(VALUE self, VALUE ext) X509_REVOKED *rev; GetX509Rev(self, rev); - if(!X509_REVOKED_add_ext(rev, DupX509ExtPtr(ext), -1)) { - ossl_raise(eX509RevError, NULL); + if (!X509_REVOKED_add_ext(rev, GetX509ExtPtr(ext), -1)) { + ossl_raise(eX509RevError, NULL); } return ext; } +static VALUE +ossl_x509revoked_to_der(VALUE self) +{ + X509_REVOKED *rev; + VALUE str; + int len; + unsigned char *p; + + GetX509Rev(self, rev); + len = i2d_X509_REVOKED(rev, NULL); + if (len <= 0) + ossl_raise(eX509RevError, "i2d_X509_REVOKED"); + str = rb_str_new(NULL, len); + p = (unsigned char *)RSTRING_PTR(str); + if (i2d_X509_REVOKED(rev, &p) <= 0) + ossl_raise(eX509RevError, "i2d_X509_REVOKED"); + ossl_str_adjust(str, p); + return str; +} + /* * INIT */ @@ -231,6 +273,7 @@ Init_ossl_x509revoked(void) rb_define_alloc_func(cX509Rev, ossl_x509revoked_alloc); rb_define_method(cX509Rev, "initialize", ossl_x509revoked_initialize, -1); + rb_define_method(cX509Rev, "initialize_copy", ossl_x509revoked_initialize_copy, 1); rb_define_method(cX509Rev, "serial", ossl_x509revoked_get_serial, 0); rb_define_method(cX509Rev, "serial=", ossl_x509revoked_set_serial, 1); @@ -239,5 +282,5 @@ Init_ossl_x509revoked(void) rb_define_method(cX509Rev, "extensions", ossl_x509revoked_get_extensions, 0); rb_define_method(cX509Rev, "extensions=", ossl_x509revoked_set_extensions, 1); rb_define_method(cX509Rev, "add_extension", ossl_x509revoked_add_extension, 1); + rb_define_method(cX509Rev, "to_der", ossl_x509revoked_to_der, 0); } - diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c index 3093e28af1..be1458cec5 100644 --- a/ext/openssl/ossl_x509store.c +++ b/ext/openssl/ossl_x509store.c @@ -1,55 +1,126 @@ /* - * $Id$ * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> * All rights reserved. */ /* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * This program is licensed under the same licence as Ruby. + * (See the file 'COPYING'.) */ #include "ossl.h" -#define WrapX509Store(klass, obj, st) do { \ +#define NewX509Store(klass) \ + TypedData_Wrap_Struct((klass), &ossl_x509store_type, 0) +#define SetX509Store(obj, st) do { \ if (!(st)) { \ - ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \ } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_x509store_type, (st)); \ + RTYPEDDATA_DATA(obj) = (st); \ } while (0) #define GetX509Store(obj, st) do { \ TypedData_Get_Struct((obj), X509_STORE, &ossl_x509store_type, (st)); \ if (!(st)) { \ - ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \ } \ } while (0) -#define SafeGetX509Store(obj, st) do { \ - OSSL_Check_Kind((obj), cX509Store); \ - GetX509Store((obj), (st)); \ -} while (0) -#define WrapX509StCtx(klass, obj, ctx) do { \ +#define NewX509StCtx(klass) \ + TypedData_Wrap_Struct((klass), &ossl_x509stctx_type, 0) +#define SetX509StCtx(obj, ctx) do { \ if (!(ctx)) { \ - ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \ + ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \ } \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_x509stctx_type, (ctx)); \ + RTYPEDDATA_DATA(obj) = (ctx); \ } while (0) #define GetX509StCtx(obj, ctx) do { \ TypedData_Get_Struct((obj), X509_STORE_CTX, &ossl_x509stctx_type, (ctx)); \ if (!(ctx)) { \ - ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \ + ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \ } \ } while (0) -#define SafeGetX509StCtx(obj, storep) do { \ - OSSL_Check_Kind((obj), cX509StoreContext); \ - GetX509Store((obj), (ctx)); \ -} while (0) + +/* + * Verify callback stuff + */ +static int stctx_ex_verify_cb_idx, store_ex_verify_cb_idx; +static VALUE ossl_x509stctx_new(X509_STORE_CTX *); + +struct ossl_verify_cb_args { + VALUE proc; + VALUE preverify_ok; + VALUE store_ctx; +}; + +static VALUE +ossl_x509stctx_new_i(VALUE arg) +{ + return ossl_x509stctx_new((X509_STORE_CTX *)arg); +} + +static VALUE +call_verify_cb_proc(VALUE arg) +{ + struct ossl_verify_cb_args *args = (struct ossl_verify_cb_args *)arg; + return rb_funcall(args->proc, rb_intern("call"), 2, + args->preverify_ok, args->store_ctx); +} + +int +ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx) +{ + VALUE rctx, ret; + struct ossl_verify_cb_args args; + int state; + + if (NIL_P(proc)) + return ok; + + ret = Qfalse; + rctx = rb_protect(ossl_x509stctx_new_i, (VALUE)ctx, &state); + if (state) { + rb_set_errinfo(Qnil); + rb_warn("StoreContext initialization failure"); + } + else { + args.proc = proc; + args.preverify_ok = ok ? Qtrue : Qfalse; + args.store_ctx = rctx; + ret = rb_protect(call_verify_cb_proc, (VALUE)&args, &state); + if (state) { + rb_set_errinfo(Qnil); + rb_warn("exception in verify_callback is ignored"); + } + RTYPEDDATA_DATA(rctx) = NULL; + } + if (ret == Qtrue) { + X509_STORE_CTX_set_error(ctx, X509_V_OK); + ok = 1; + } + else { + if (X509_STORE_CTX_get_error(ctx) == X509_V_OK) + X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED); + ok = 0; + } + + return ok; +} /* * Classes */ -VALUE cX509Store; -VALUE cX509StoreContext; -VALUE eX509StoreError; +static VALUE cX509Store; +static VALUE cX509StoreContext; +static VALUE eX509StoreError; + +static void +ossl_x509store_mark(void *ptr) +{ + X509_STORE *store = ptr; + // Note: this reference is stored as @verify_callback so we don't need to mark it. + // However we do need to ensure GC compaction won't move it, hence why + // we call rb_gc_mark here. + rb_gc_mark((VALUE)X509_STORE_get_ex_data(store, store_ex_verify_cb_idx)); +} static void ossl_x509store_free(void *ptr) @@ -60,58 +131,52 @@ ossl_x509store_free(void *ptr) static const rb_data_type_t ossl_x509store_type = { "OpenSSL/X509/STORE", { - 0, ossl_x509store_free, + ossl_x509store_mark, ossl_x509store_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; /* * Public functions */ -VALUE -ossl_x509store_new(X509_STORE *store) -{ - VALUE obj; - - WrapX509Store(cX509Store, obj, store); - - return obj; -} - X509_STORE * GetX509StorePtr(VALUE obj) { X509_STORE *store; - SafeGetX509Store(obj, store); + GetX509Store(obj, store); return store; } -X509_STORE * -DupX509StorePtr(VALUE obj) +/* + * Private functions + */ +static int +x509store_verify_cb(int ok, X509_STORE_CTX *ctx) { - X509_STORE *store; + VALUE proc; - SafeGetX509Store(obj, store); - CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE); + proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx); + if (!proc) + proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx), + store_ex_verify_cb_idx); + if (!proc) + return ok; - return store; + return ossl_verify_cb_call(proc, ok, ctx); } -/* - * Private functions - */ static VALUE ossl_x509store_alloc(VALUE klass) { X509_STORE *store; VALUE obj; - if((store = X509_STORE_new()) == NULL){ - ossl_raise(eX509StoreError, NULL); - } - WrapX509Store(klass, obj, store); + obj = NewX509Store(klass); + if ((store = X509_STORE_new()) == NULL) + ossl_raise(eX509StoreError, "X509_STORE_new"); + SetX509Store(obj, store); return obj; } @@ -125,8 +190,9 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb) X509_STORE *store; GetX509Store(self, store); - X509_STORE_set_ex_data(store, ossl_verify_cb_idx, (void*)cb); rb_iv_set(self, "@verify_callback", cb); + X509_STORE_set_ex_data(store, store_ex_verify_cb_idx, (void *)cb); + RB_OBJ_WRITTEN(self, Qundef, cb); return cb; } @@ -136,135 +202,187 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb) * call-seq: * X509::Store.new => store * + * Creates a new X509::Store. */ static VALUE ossl_x509store_initialize(int argc, VALUE *argv, VALUE self) { X509_STORE *store; -/* BUG: This method takes any number of arguments but appears to ignore them. */ GetX509Store(self, store); - store->ex_data.sk = NULL; - X509_STORE_set_verify_cb_func(store, ossl_verify_cb); + if (argc != 0) + rb_warn("OpenSSL::X509::Store.new does not take any arguments"); + X509_STORE_set_verify_cb(store, x509store_verify_cb); ossl_x509store_set_vfy_cb(self, Qnil); -#if (OPENSSL_VERSION_NUMBER < 0x00907000L) - rb_iv_set(self, "@flags", INT2FIX(0)); - rb_iv_set(self, "@purpose", INT2FIX(0)); - rb_iv_set(self, "@trust", INT2FIX(0)); -#endif - /* last verification status */ rb_iv_set(self, "@error", Qnil); rb_iv_set(self, "@error_string", Qnil); rb_iv_set(self, "@chain", Qnil); - rb_iv_set(self, "@time", Qnil); return self; } +/* + * call-seq: + * store.flags = flags + * + * Sets the default flags used by certificate chain verification performed with + * the Store. + * + * _flags_ consists of zero or more of the constants defined in OpenSSL::X509 + * with name V_FLAG_* or'ed together. + * + * OpenSSL::X509::StoreContext#flags= can be used to change the flags for a + * single verification operation. + * + * See also the man page X509_VERIFY_PARAM_set_flags(3). + */ static VALUE ossl_x509store_set_flags(VALUE self, VALUE flags) { -#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) X509_STORE *store; long f = NUM2LONG(flags); GetX509Store(self, store); X509_STORE_set_flags(store, f); -#else - rb_iv_set(self, "@flags", flags); -#endif return flags; } +/* + * call-seq: + * store.purpose = purpose + * + * Sets the store's default verification purpose. If specified, + * the verifications on the store will check every certificate's extensions are + * consistent with the purpose. The purpose is specified by constants: + * + * * X509::PURPOSE_SSL_CLIENT + * * X509::PURPOSE_SSL_SERVER + * * X509::PURPOSE_NS_SSL_SERVER + * * X509::PURPOSE_SMIME_SIGN + * * X509::PURPOSE_SMIME_ENCRYPT + * * X509::PURPOSE_CRL_SIGN + * * X509::PURPOSE_ANY + * * X509::PURPOSE_OCSP_HELPER + * * X509::PURPOSE_TIMESTAMP_SIGN + * + * OpenSSL::X509::StoreContext#purpose= can be used to change the value for a + * single verification operation. + * + * See also the man page X509_VERIFY_PARAM_set_purpose(3). + */ static VALUE ossl_x509store_set_purpose(VALUE self, VALUE purpose) { -#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) X509_STORE *store; int p = NUM2INT(purpose); GetX509Store(self, store); X509_STORE_set_purpose(store, p); -#else - rb_iv_set(self, "@purpose", purpose); -#endif return purpose; } +/* + * call-seq: + * store.trust = trust + * + * Sets the default trust settings used by the certificate verification with + * the store. + * + * OpenSSL::X509::StoreContext#trust= can be used to change the value for a + * single verification operation. + * + * See also the man page X509_VERIFY_PARAM_set_trust(3). + */ static VALUE ossl_x509store_set_trust(VALUE self, VALUE trust) { -#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) X509_STORE *store; int t = NUM2INT(trust); GetX509Store(self, store); X509_STORE_set_trust(store, t); -#else - rb_iv_set(self, "@trust", trust); -#endif return trust; } +/* + * call-seq: + * store.time = time + * + * Sets the time to be used in the certificate verifications with the store. + * By default, if not specified, the current system time is used. + * + * OpenSSL::X509::StoreContext#time= can be used to change the value for a + * single verification operation. + * + * See also the man page X509_VERIFY_PARAM_set_time(3). + */ static VALUE ossl_x509store_set_time(VALUE self, VALUE time) { - rb_iv_set(self, "@time", time); + X509_STORE *store; + X509_VERIFY_PARAM *param; + + GetX509Store(self, store); + param = X509_STORE_get0_param(store); + X509_VERIFY_PARAM_set_time(param, NUM2LONG(rb_Integer(time))); return time; } /* * call-seq: - * store.add_file(file) -> store + * store.add_file(file) -> self * + * Adds the certificates in _file_ to the certificate store. _file_ is the path + * to the file, and the file contains one or more certificates in PEM format + * concatenated together. * - * Adds the certificates in +file+ to the certificate store. The +file+ can - * contain multiple PEM-encoded certificates. + * See also the man page X509_LOOKUP_file(3). */ - static VALUE ossl_x509store_add_file(VALUE self, VALUE file) { X509_STORE *store; X509_LOOKUP *lookup; - char *path = NULL; + const char *path; - if(file != Qnil){ - SafeStringValue(file); - path = RSTRING_PTR(file); - } GetX509Store(self, store); + path = StringValueCStr(file); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); - if(lookup == NULL) ossl_raise(eX509StoreError, NULL); - if(X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1){ - ossl_raise(eX509StoreError, NULL); - } + if (!lookup) + ossl_raise(eX509StoreError, "X509_STORE_add_lookup"); + if (X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1) + ossl_raise(eX509StoreError, "X509_LOOKUP_load_file"); return self; } +/* + * call-seq: + * store.add_path(path) -> self + * + * Adds _path_ as the hash dir to be looked up by the store. + * + * See also the man page X509_LOOKUP_hash_dir(3). + */ static VALUE ossl_x509store_add_path(VALUE self, VALUE dir) { X509_STORE *store; X509_LOOKUP *lookup; - char *path = NULL; + const char *path; - if(dir != Qnil){ - SafeStringValue(dir); - path = RSTRING_PTR(dir); - } GetX509Store(self, store); + path = StringValueCStr(dir); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); - if(lookup == NULL) ossl_raise(eX509StoreError, NULL); - if(X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1){ - ossl_raise(eX509StoreError, NULL); - } + if (!lookup) + ossl_raise(eX509StoreError, "X509_STORE_add_lookup"); + if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1) + ossl_raise(eX509StoreError, "X509_LOOKUP_add_dir"); return self; } @@ -273,11 +391,14 @@ ossl_x509store_add_path(VALUE self, VALUE dir) * call-seq: * store.set_default_paths * - * Adds the default certificates to the certificate store. These certificates - * are loaded from the default configuration directory which can usually be + * Configures _store_ to look up CA certificates from the system default + * certificate store as needed basis. The location of the store can usually be * determined by: * - * File.dirname OpenSSL::Config::DEFAULT_CONFIG_FILE + * * OpenSSL::X509::DEFAULT_CERT_FILE + * * OpenSSL::X509::DEFAULT_CERT_DIR + * + * See also the man page X509_STORE_set_default_paths(3). */ static VALUE ossl_x509store_set_default_paths(VALUE self) @@ -285,20 +406,20 @@ ossl_x509store_set_default_paths(VALUE self) X509_STORE *store; GetX509Store(self, store); - if (X509_STORE_set_default_paths(store) != 1){ - ossl_raise(eX509StoreError, NULL); - } + if (X509_STORE_set_default_paths(store) != 1) + ossl_raise(eX509StoreError, "X509_STORE_set_default_paths"); return Qnil; } /* * call-seq: - * store.add_cert(cert) + * store.add_cert(cert) -> self + * + * Adds the OpenSSL::X509::Certificate _cert_ to the certificate store. * - * Adds the OpenSSL::X509::Certificate +cert+ to the certificate store. + * See also the man page X509_STORE_add_cert(3). */ - static VALUE ossl_x509store_add_cert(VALUE self, VALUE arg) { @@ -307,13 +428,20 @@ ossl_x509store_add_cert(VALUE self, VALUE arg) cert = GetX509CertPtr(arg); /* NO NEED TO DUP */ GetX509Store(self, store); - if (X509_STORE_add_cert(store, cert) != 1){ - ossl_raise(eX509StoreError, NULL); - } + if (X509_STORE_add_cert(store, cert) != 1) + ossl_raise(eX509StoreError, "X509_STORE_add_cert"); return self; } +/* + * call-seq: + * store.add_crl(crl) -> self + * + * Adds the OpenSSL::X509::CRL _crl_ to the store. + * + * See also the man page X509_STORE_add_crl(3). + */ static VALUE ossl_x509store_add_crl(VALUE self, VALUE arg) { @@ -322,9 +450,8 @@ ossl_x509store_add_crl(VALUE self, VALUE arg) crl = GetX509CRLPtr(arg); /* NO NEED TO DUP */ GetX509Store(self, store); - if (X509_STORE_add_crl(store, crl) != 1){ - ossl_raise(eX509StoreError, NULL); - } + if (X509_STORE_add_crl(store, crl) != 1) + ossl_raise(eX509StoreError, "X509_STORE_add_crl"); return self; } @@ -333,6 +460,21 @@ static VALUE ossl_x509stctx_get_err(VALUE); static VALUE ossl_x509stctx_get_err_string(VALUE); static VALUE ossl_x509stctx_get_chain(VALUE); +/* + * call-seq: + * store.verify(cert, chain = nil) -> true | false + * + * Performs a certificate verification on the OpenSSL::X509::Certificate _cert_. + * + * _chain_ can be an array of OpenSSL::X509::Certificate that is used to + * construct the certificate chain. + * + * If a block is given, it overrides the callback set by #verify_callback=. + * + * After finishing the verification, the error information can be retrieved by + * #error, #error_string, and the resulting complete certificate chain can be + * retrieved by #chain. + */ static VALUE ossl_x509store_verify(int argc, VALUE *argv, VALUE self) { @@ -342,7 +484,7 @@ ossl_x509store_verify(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "11", &cert, &chain); ctx = rb_funcall(cX509StoreContext, rb_intern("new"), 3, self, cert, chain); proc = rb_block_given_p() ? rb_block_proc() : - rb_iv_get(self, "@verify_callback"); + rb_iv_get(self, "@verify_callback"); rb_iv_set(ctx, "@verify_callback", proc); result = rb_funcall(ctx, rb_intern("verify"), 0); @@ -354,63 +496,58 @@ ossl_x509store_verify(int argc, VALUE *argv, VALUE self) } /* - * Public Functions + * Private functions */ -static void ossl_x509stctx_free(void*); +static void +ossl_x509stctx_mark(void *ptr) +{ + X509_STORE_CTX *ctx = ptr; + // Note: this reference is stored as @verify_callback so we don't need to mark it. + // However we do need to ensure GC compaction won't move it, hence why + // we call rb_gc_mark here. + rb_gc_mark((VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx)); +} +static void +ossl_x509stctx_free(void *ptr) +{ + X509_STORE_CTX *ctx = ptr; + if (X509_STORE_CTX_get0_untrusted(ctx)) + sk_X509_pop_free(X509_STORE_CTX_get0_untrusted(ctx), X509_free); + if (X509_STORE_CTX_get0_cert(ctx)) + X509_free(X509_STORE_CTX_get0_cert(ctx)); + X509_STORE_CTX_free(ctx); +} static const rb_data_type_t ossl_x509stctx_type = { "OpenSSL/X509/STORE_CTX", { - 0, ossl_x509stctx_free, + ossl_x509stctx_mark, ossl_x509stctx_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; - -VALUE -ossl_x509stctx_new(X509_STORE_CTX *ctx) +static VALUE +ossl_x509stctx_alloc(VALUE klass) { + X509_STORE_CTX *ctx; VALUE obj; - WrapX509StCtx(cX509StoreContext, obj, ctx); + obj = NewX509StCtx(klass); + if ((ctx = X509_STORE_CTX_new()) == NULL) + ossl_raise(eX509StoreError, "X509_STORE_CTX_new"); + SetX509StCtx(obj, ctx); return obj; } -VALUE -ossl_x509stctx_clear_ptr(VALUE obj) -{ - OSSL_Check_Kind(obj, cX509StoreContext); - RDATA(obj)->data = NULL; - - return obj; -} - -/* - * Private functions - */ -static void -ossl_x509stctx_free(void *ptr) -{ - X509_STORE_CTX *ctx = ptr; - if(ctx->untrusted) - sk_X509_pop_free(ctx->untrusted, X509_free); - if(ctx->cert) - X509_free(ctx->cert); - X509_STORE_CTX_free(ctx); -} - static VALUE -ossl_x509stctx_alloc(VALUE klass) +ossl_x509stctx_new(X509_STORE_CTX *ctx) { - X509_STORE_CTX *ctx; VALUE obj; - if((ctx = X509_STORE_CTX_new()) == NULL){ - ossl_raise(eX509StoreError, NULL); - } - WrapX509StCtx(klass, obj, ctx); + obj = NewX509StCtx(cX509StoreContext); + SetX509StCtx(obj, ctx); return obj; } @@ -418,81 +555,106 @@ ossl_x509stctx_alloc(VALUE klass) static VALUE ossl_x509stctx_set_flags(VALUE, VALUE); static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE); static VALUE ossl_x509stctx_set_trust(VALUE, VALUE); -static VALUE ossl_x509stctx_set_time(VALUE, VALUE); +/* + * call-seq: + * StoreContext.new(store, cert = nil, untrusted = nil) + * + * Sets up a StoreContext for a verification of the X.509 certificate _cert_. + */ static VALUE ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self) { - VALUE store, cert, chain, t; + VALUE store, cert, chain; X509_STORE_CTX *ctx; X509_STORE *x509st; X509 *x509 = NULL; STACK_OF(X509) *x509s = NULL; + int state; rb_scan_args(argc, argv, "12", &store, &cert, &chain); GetX509StCtx(self, ctx); - SafeGetX509Store(store, x509st); - if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */ - if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain); -#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) - if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){ + GetX509Store(store, x509st); + if (!NIL_P(cert)) + x509 = DupX509CertPtr(cert); /* NEED TO DUP */ + if (!NIL_P(chain)) { + x509s = ossl_protect_x509_ary2sk(chain, &state); + if (state) { + X509_free(x509); + rb_jump_tag(state); + } + } + if (X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){ + X509_free(x509); sk_X509_pop_free(x509s, X509_free); - ossl_raise(eX509StoreError, NULL); + ossl_raise(eX509StoreError, "X509_STORE_CTX_init"); } -#else - X509_STORE_CTX_init(ctx, x509st, x509, x509s); - ossl_x509stctx_set_flags(self, rb_iv_get(store, "@flags")); - ossl_x509stctx_set_purpose(self, rb_iv_get(store, "@purpose")); - ossl_x509stctx_set_trust(self, rb_iv_get(store, "@trust")); -#endif - if (!NIL_P(t = rb_iv_get(store, "@time"))) - ossl_x509stctx_set_time(self, t); rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback")); rb_iv_set(self, "@cert", cert); return self; } +/* + * call-seq: + * stctx.verify -> true | false + * + * Performs the certificate verification using the parameters set to _stctx_. + * + * See also the man page X509_verify_cert(3). + */ static VALUE ossl_x509stctx_verify(VALUE self) { X509_STORE_CTX *ctx; - int result; GetX509StCtx(self, ctx); - X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx, - (void*)rb_iv_get(self, "@verify_callback")); - result = X509_verify_cert(ctx); - - return result ? Qtrue : Qfalse; + VALUE cb = rb_iv_get(self, "@verify_callback"); + X509_STORE_CTX_set_ex_data(ctx, stctx_ex_verify_cb_idx, (void *)cb); + RB_OBJ_WRITTEN(self, Qundef, cb); + + switch (X509_verify_cert(ctx)) { + case 1: + return Qtrue; + case 0: + ossl_clear_error(); + return Qfalse; + default: + ossl_raise(eX509StoreError, "X509_verify_cert"); + } } +/* + * call-seq: + * stctx.chain -> nil | Array of X509::Certificate + * + * Returns the verified chain. + * + * See also the man page X509_STORE_CTX_set0_verified_chain(3). + */ static VALUE ossl_x509stctx_get_chain(VALUE self) { X509_STORE_CTX *ctx; - STACK_OF(X509) *chain; - X509 *x509; - int i, num; - VALUE ary; + const STACK_OF(X509) *chain; GetX509StCtx(self, ctx); - if((chain = X509_STORE_CTX_get_chain(ctx)) == NULL){ - return Qnil; - } - if((num = sk_X509_num(chain)) < 0){ - OSSL_Debug("certs in chain < 0???"); - return rb_ary_new(); - } - ary = rb_ary_new2(num); - for(i = 0; i < num; i++) { - x509 = sk_X509_value(chain, i); - rb_ary_push(ary, ossl_x509_new(x509)); - } - - return ary; + chain = X509_STORE_CTX_get0_chain(ctx); + if (!chain) + return Qnil; /* Could be an empty array instead? */ + return ossl_x509_sk2ary(chain); } +/* + * call-seq: + * stctx.error -> Integer + * + * Returns the error code of _stctx_. This is typically called after #verify + * is done, or from the verification callback set to + * OpenSSL::X509::Store#verify_callback=. + * + * See also the man page X509_STORE_CTX_get_error(3). + */ static VALUE ossl_x509stctx_get_err(VALUE self) { @@ -500,9 +662,18 @@ ossl_x509stctx_get_err(VALUE self) GetX509StCtx(self, ctx); - return INT2FIX(X509_STORE_CTX_get_error(ctx)); + return INT2NUM(X509_STORE_CTX_get_error(ctx)); } +/* + * call-seq: + * stctx.error = error_code + * + * Sets the error code of _stctx_. This is used by the verification callback + * set to OpenSSL::X509::Store#verify_callback=. + * + * See also the man page X509_STORE_CTX_set_error(3). + */ static VALUE ossl_x509stctx_set_error(VALUE self, VALUE err) { @@ -514,6 +685,15 @@ ossl_x509stctx_set_error(VALUE self, VALUE err) return err; } +/* + * call-seq: + * stctx.error_string -> String + * + * Returns the human readable error string corresponding to the error code + * retrieved by #error. + * + * See also the man page X509_verify_cert_error_string(3). + */ static VALUE ossl_x509stctx_get_err_string(VALUE self) { @@ -526,6 +706,14 @@ ossl_x509stctx_get_err_string(VALUE self) return rb_str_new2(X509_verify_cert_error_string(err)); } +/* + * call-seq: + * stctx.error_depth -> Integer + * + * Returns the depth of the chain. This is used in combination with #error. + * + * See also the man page X509_STORE_CTX_get_error_depth(3). + */ static VALUE ossl_x509stctx_get_err_depth(VALUE self) { @@ -533,34 +721,62 @@ ossl_x509stctx_get_err_depth(VALUE self) GetX509StCtx(self, ctx); - return INT2FIX(X509_STORE_CTX_get_error_depth(ctx)); + return INT2NUM(X509_STORE_CTX_get_error_depth(ctx)); } +/* + * call-seq: + * stctx.current_cert -> X509::Certificate + * + * Returns the certificate which caused the error. + * + * See also the man page X509_STORE_CTX_get_current_cert(3). + */ static VALUE ossl_x509stctx_get_curr_cert(VALUE self) { X509_STORE_CTX *ctx; + X509 *x509; GetX509StCtx(self, ctx); + x509 = X509_STORE_CTX_get_current_cert(ctx); + if (!x509) + return Qnil; - return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx)); + return ossl_x509_new(x509); } +/* + * call-seq: + * stctx.current_crl -> X509::CRL + * + * Returns the CRL which caused the error. + * + * See also the man page X509_STORE_CTX_get_current_crl(3). + */ static VALUE ossl_x509stctx_get_curr_crl(VALUE self) { -#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) X509_STORE_CTX *ctx; + X509_CRL *crl; GetX509StCtx(self, ctx); - if(!ctx->current_crl) return Qnil; + crl = X509_STORE_CTX_get0_current_crl(ctx); + if (!crl) + return Qnil; - return ossl_x509crl_new(ctx->current_crl); -#else - return Qnil; -#endif + return ossl_x509crl_new(crl); } +/* + * call-seq: + * stctx.flags = flags + * + * Sets the verification flags to the context. This overrides the default value + * set by Store#flags=. + * + * See also the man page X509_VERIFY_PARAM_set_flags(3). + */ static VALUE ossl_x509stctx_set_flags(VALUE self, VALUE flags) { @@ -573,6 +789,15 @@ ossl_x509stctx_set_flags(VALUE self, VALUE flags) return flags; } +/* + * call-seq: + * stctx.purpose = purpose + * + * Sets the purpose of the context. This overrides the default value set by + * Store#purpose=. + * + * See also the man page X509_VERIFY_PARAM_set_purpose(3). + */ static VALUE ossl_x509stctx_set_purpose(VALUE self, VALUE purpose) { @@ -585,6 +810,15 @@ ossl_x509stctx_set_purpose(VALUE self, VALUE purpose) return purpose; } +/* + * call-seq: + * stctx.trust = trust + * + * Sets the trust settings of the context. This overrides the default value set + * by Store#trust=. + * + * See also the man page X509_VERIFY_PARAM_set_trust(3). + */ static VALUE ossl_x509stctx_set_trust(VALUE self, VALUE trust) { @@ -599,7 +833,11 @@ ossl_x509stctx_set_trust(VALUE self, VALUE trust) /* * call-seq: - * storectx.time = time => time + * stctx.time = time + * + * Sets the time used in the verification. If not set, the current time is used. + * + * See also the man page X509_VERIFY_PARAM_set_time(3). */ static VALUE ossl_x509stctx_set_time(VALUE self, VALUE time) @@ -620,12 +858,14 @@ ossl_x509stctx_set_time(VALUE self, VALUE time) void Init_ossl_x509store(void) { - VALUE x509stctx; - -#if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ - mX509 = rb_define_module_under(mOSSL, "X509"); -#endif +#undef rb_intern + /* Register ext_data slot for verify callback Proc */ + stctx_ex_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"stctx_ex_verify_cb_idx", 0, 0, 0); + if (stctx_ex_verify_cb_idx < 0) + ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index"); + store_ex_verify_cb_idx = X509_STORE_get_ex_new_index(0, (void *)"store_ex_verify_cb_idx", 0, 0, 0); + if (store_ex_verify_cb_idx < 0) + ossl_raise(eOSSLError, "X509_STORE_get_ex_new_index"); eX509StoreError = rb_define_class_under(mX509, "StoreError", eOSSLError); @@ -641,11 +881,11 @@ Init_ossl_x509store(void) * * This will use your system's built-in certificates. * - * If your system does not have a default set of certificates you can - * obtain a set from Mozilla here: http://curl.haxx.se/docs/caextract.html - * (Note that this set does not have an HTTPS download option so you may - * wish to use the firefox-db2pem.sh script to extract the certificates - * from a local install to avoid man-in-the-middle attacks.) + * If your system does not have a default set of certificates you can obtain + * a set extracted from Mozilla CA certificate store by cURL maintainers + * here: https://curl.haxx.se/docs/caextract.html (You may wish to use the + * firefox-db2pem.sh script to extract the certificates from a local install + * to avoid man-in-the-middle attacks.) * * After downloading or generating a cacert.pem from the above link you * can create a certificate store from the pem file like this: @@ -656,6 +896,7 @@ Init_ossl_x509store(void) * The certificate store can be used with an SSLSocket like this: * * ssl_context = OpenSSL::SSL::SSLContext.new + * ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER * ssl_context.cert_store = cert_store * * tcp_socket = TCPSocket.open 'example.com', 443 @@ -664,12 +905,44 @@ Init_ossl_x509store(void) */ cX509Store = rb_define_class_under(mX509, "Store", rb_cObject); + /* + * The callback for additional certificate verification. It is invoked for + * each certificate in the chain and can be used to implement custom + * certificate verification conditions. + * + * The callback is invoked with two values, a boolean that indicates if the + * pre-verification by OpenSSL has succeeded or not, and the StoreContext in + * use. + * + * The callback can use StoreContext#error= to change the error code as + * needed. The callback must return either true or false. + * + * NOTE: any exception raised within the callback will be ignored. + * + * See also the man page X509_STORE_CTX_set_verify_cb(3). + */ rb_attr(cX509Store, rb_intern("verify_callback"), 1, 0, Qfalse); + /* + * The error code set by the last call of #verify. + * + * See also StoreContext#error. + */ rb_attr(cX509Store, rb_intern("error"), 1, 0, Qfalse); + /* + * The description for the error code set by the last call of #verify. + * + * See also StoreContext#error_string. + */ rb_attr(cX509Store, rb_intern("error_string"), 1, 0, Qfalse); + /* + * The certificate chain constructed by the last call of #verify. + * + * See also StoreContext#chain. + */ rb_attr(cX509Store, rb_intern("chain"), 1, 0, Qfalse); rb_define_alloc_func(cX509Store, ossl_x509store_alloc); rb_define_method(cX509Store, "initialize", ossl_x509store_initialize, -1); + rb_undef_method(cX509Store, "initialize_copy"); rb_define_method(cX509Store, "verify_callback=", ossl_x509store_set_vfy_cb, 1); rb_define_method(cX509Store, "flags=", ossl_x509store_set_flags, 1); rb_define_method(cX509Store, "purpose=", ossl_x509store_set_purpose, 1); @@ -682,21 +955,26 @@ Init_ossl_x509store(void) rb_define_method(cX509Store, "add_crl", ossl_x509store_add_crl, 1); rb_define_method(cX509Store, "verify", ossl_x509store_verify, -1); - cX509StoreContext = rb_define_class_under(mX509,"StoreContext",rb_cObject); - x509stctx = cX509StoreContext; + /* + * Document-class: OpenSSL::X509::StoreContext + * + * A StoreContext is used while validating a single certificate and holds + * the status involved. + */ + cX509StoreContext = rb_define_class_under(mX509,"StoreContext", rb_cObject); rb_define_alloc_func(cX509StoreContext, ossl_x509stctx_alloc); - rb_define_method(x509stctx,"initialize", ossl_x509stctx_initialize, -1); - rb_define_method(x509stctx,"verify", ossl_x509stctx_verify, 0); - rb_define_method(x509stctx,"chain", ossl_x509stctx_get_chain,0); - rb_define_method(x509stctx,"error", ossl_x509stctx_get_err, 0); - rb_define_method(x509stctx,"error=", ossl_x509stctx_set_error, 1); - rb_define_method(x509stctx,"error_string",ossl_x509stctx_get_err_string,0); - rb_define_method(x509stctx,"error_depth", ossl_x509stctx_get_err_depth, 0); - rb_define_method(x509stctx,"current_cert",ossl_x509stctx_get_curr_cert, 0); - rb_define_method(x509stctx,"current_crl", ossl_x509stctx_get_curr_crl, 0); - rb_define_method(x509stctx,"flags=", ossl_x509stctx_set_flags, 1); - rb_define_method(x509stctx,"purpose=", ossl_x509stctx_set_purpose, 1); - rb_define_method(x509stctx,"trust=", ossl_x509stctx_set_trust, 1); - rb_define_method(x509stctx,"time=", ossl_x509stctx_set_time, 1); - + rb_define_method(cX509StoreContext, "initialize", ossl_x509stctx_initialize, -1); + rb_undef_method(cX509StoreContext, "initialize_copy"); + rb_define_method(cX509StoreContext, "verify", ossl_x509stctx_verify, 0); + rb_define_method(cX509StoreContext, "chain", ossl_x509stctx_get_chain,0); + rb_define_method(cX509StoreContext, "error", ossl_x509stctx_get_err, 0); + rb_define_method(cX509StoreContext, "error=", ossl_x509stctx_set_error, 1); + rb_define_method(cX509StoreContext, "error_string", ossl_x509stctx_get_err_string,0); + rb_define_method(cX509StoreContext, "error_depth", ossl_x509stctx_get_err_depth, 0); + rb_define_method(cX509StoreContext, "current_cert", ossl_x509stctx_get_curr_cert, 0); + rb_define_method(cX509StoreContext, "current_crl", ossl_x509stctx_get_curr_crl, 0); + rb_define_method(cX509StoreContext, "flags=", ossl_x509stctx_set_flags, 1); + rb_define_method(cX509StoreContext, "purpose=", ossl_x509stctx_set_purpose, 1); + rb_define_method(cX509StoreContext, "trust=", ossl_x509stctx_set_trust, 1); + rb_define_method(cX509StoreContext, "time=", ossl_x509stctx_set_time, 1); } diff --git a/ext/openssl/ruby_missing.h b/ext/openssl/ruby_missing.h deleted file mode 100644 index 0f9de1c842..0000000000 --- a/ext/openssl/ruby_missing.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * $Id$ - * 'OpenSSL for Ruby' project - * Copyright (C) 2001-2003 Michal Rokos <m.rokos@sh.cvut.cz> - * All rights reserved. - */ -/* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) - */ -#if !defined(_OSSL_RUBY_MISSING_H_) -#define _OSSL_RUBY_MISSING_H_ - -#define rb_define_copy_func(klass, func) \ - rb_define_method((klass), "initialize_copy", (func), 1) - - -#ifndef GetReadFile -#define FPTR_TO_FD(fptr) ((fptr)->fd) -#else -#define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr))) -#endif - -#ifndef HAVE_RB_IO_T -#define rb_io_t OpenFile -#endif - -#endif /* _OSSL_RUBY_MISSING_H_ */ |
