RPM build fix (reverted CI changes which will need to be un-reverted or made conditional) and vendor Rust dependencies to make builds much faster in any CI system.
This commit is contained in:
1
zeroidc/vendor/openssl/.cargo-checksum.json
vendored
Normal file
1
zeroidc/vendor/openssl/.cargo-checksum.json
vendored
Normal file
File diff suppressed because one or more lines are too long
644
zeroidc/vendor/openssl/CHANGELOG.md
vendored
Normal file
644
zeroidc/vendor/openssl/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,644 @@
|
||||
# Change Log
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v0.10.40] - 2022-05-04
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed the openssl-sys dependency version.
|
||||
|
||||
## [v0.10.39] - 2022-05-02
|
||||
|
||||
### Deprecated
|
||||
|
||||
* Deprecated `SslContextBuilder::set_tmp_ecdh_callback` and `SslRef::set_tmp_ecdh_callback`.
|
||||
|
||||
### Added
|
||||
|
||||
* Added `SslRef::extms_support`.
|
||||
* Added `Nid::create`.
|
||||
* Added `CipherCtx`, which exposes a more direct interface to `EVP_CIPHER_CTX`.
|
||||
* Added `PkeyCtx`, which exposes a more direct interface to `EVP_PKEY_CTX`.
|
||||
* Added `MdCtx`, which exposes a more direct interface to `EVP_MD_CTX`.
|
||||
* Added `Pkcs12Builder::mac_md`.
|
||||
* Added `Provider`.
|
||||
* Added `X509Ref::issuer_name_hash`.
|
||||
* Added `Decrypter::set_rsa_oaep_label`.
|
||||
* Added `X509Ref::to_text`.
|
||||
|
||||
## [v0.10.38] - 2021-10-31
|
||||
|
||||
### Added
|
||||
|
||||
* Added `Pkey::ec_gen`.
|
||||
|
||||
## [v0.10.37] - 2021-10-27
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed linkage against OpenSSL distributions built with `no-chacha`.
|
||||
|
||||
### Added
|
||||
|
||||
* Added `BigNumRef::to_vec_padded`.
|
||||
* Added `X509Name::from_der` and `X509NameRef::to_der`.
|
||||
* Added `BigNum::new_secure`, `BigNumReef::set_const_time`, `BigNumref::is_const_time`, and `BigNumRef::is_secure`.
|
||||
|
||||
## [v0.10.36] - 2021-08-17
|
||||
|
||||
### Added
|
||||
|
||||
* Added `Asn1Object::as_slice`.
|
||||
* Added `PKeyRef::{raw_public_key, raw_private_key, private_key_to_pkcs8_passphrase}` and
|
||||
`PKey::{private_key_from_raw_bytes, public_key_from_raw_bytes}`.
|
||||
* Added `Cipher::{seed_cbc, seed_cfb128, seed_ecb, seed_ofb}`.
|
||||
|
||||
## [v0.10.35] - 2021-06-18
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed a memory leak in `Deriver`.
|
||||
|
||||
### Added
|
||||
|
||||
* Added support for OpenSSL 3.x.x.
|
||||
* Added `SslStream::peek`.
|
||||
|
||||
## [v0.10.34] - 2021-04-28
|
||||
|
||||
### Added
|
||||
|
||||
* Added `Dh::set_private_key` and `DhRef::private_key`.
|
||||
* Added `EcPointRef::affine_coordinates`.
|
||||
* Added `TryFrom` implementations to convert between `PKey` and specific key types.
|
||||
* Added `X509StoreBuilderRef::set_flags`.
|
||||
|
||||
## [v0.10.33] - 2021-03-13
|
||||
|
||||
### Fixed
|
||||
|
||||
* `Dh::generate_params` now uses `DH_generate_params_ex` rather than the deprecated `DH_generated_params` function.
|
||||
|
||||
### Added
|
||||
|
||||
* Added `Asn1Type`.
|
||||
* Added `CmsContentInfoRef::decrypt_without_cert_check`.
|
||||
* Added `EcPointRef::{is_infinity, is_on_curve}`.
|
||||
* Added `Encrypter::set_rsa_oaep_label`.
|
||||
* Added `MessageDigest::sm3`.
|
||||
* Added `Pkcs7Ref::signers`.
|
||||
* Added `Cipher::nid`.
|
||||
* Added `X509Ref::authority_info` and `AccessDescription::{method, location}`.
|
||||
* Added `X509NameBuilder::{append_entry_by_text_with_type, append_entry_by_nid_with_type}`.
|
||||
|
||||
## [v0.10.32] - 2020-12-24
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed `Ssl::new` to take a `&SslContextRef` rather than `&SslContext`.
|
||||
|
||||
### Added
|
||||
|
||||
* Added the `encrypt` module to support asymmetric encryption and decryption with `PKey`s.
|
||||
* Added `MessageDigest::from_name`.
|
||||
* Added `ConnectConfiguration::into_ssl`.
|
||||
* Added the ability to create unconnected `SslStream`s directly from an `Ssl` and transport stream
|
||||
without performing any part of the handshake with `SslStream::new`.
|
||||
* Added `SslStream::{read_early_data, write_early_data, connect, accept, do_handshake, stateless}`.
|
||||
* Implemented `ToOwned` for `SslContextRef`.
|
||||
* Added `SslRef::{set_connect_state, set_accept_state}`.
|
||||
|
||||
### Deprecated
|
||||
|
||||
* Deprecated `SslStream::from_raw_parts` in favor of `Ssl::from_ptr` and `SslStream::new`.
|
||||
* Deprecated `SslStreamBuilder` in favor of methods on `Ssl` and `SslStream`.
|
||||
|
||||
## [v0.10.31] - 2020-12-09
|
||||
|
||||
### Added
|
||||
|
||||
* Added `Asn1Object::from_str`.
|
||||
* Added `Dh::from_pgq`, `DhRef::prime_p`, `DhRef::prime_q`, `DhRef::generator`, `DhRef::generate_params`,
|
||||
`DhRef::generate_key`, `DhRef::public_key`, and `DhRef::compute_key`.
|
||||
* Added `Pkcs7::from_der` and `Pkcs7Ref::to_der`.
|
||||
* Added `Id::X25519`, `Id::X448`, `PKey::generate_x25519`, and `PKey::generate_x448`.
|
||||
* Added `SrtpProfileId::SRTP_AEAD_AES_128_GCM` and `SrtpProfileId::SRTP_AEAD_AES_256_GCM`.
|
||||
* Added `SslContextBuilder::verify_param` and `SslContextBuilder::verify_param_mut`.
|
||||
* Added `X509Ref::subject_name_hash` and `X509Ref::version`.
|
||||
* Added `X509StoreBuilderRef::add_lookup`, and the `X509Lookup` type.
|
||||
* Added `X509VerifyFlags`, `X509VerifyParamRef::set_flags`, `X509VerifyParamRef::clear_flags`
|
||||
`X509VerifyParamRef::get_flags`.
|
||||
|
||||
## [v0.10.30] - 2020-06-25
|
||||
|
||||
### Fixed
|
||||
|
||||
* `DsaRef::private_key_to_pem` can no longer be called without a private key.
|
||||
|
||||
### Changed
|
||||
|
||||
* Improved the `Debug` implementations of many types.
|
||||
|
||||
### Added
|
||||
|
||||
* Added `is_empty` implementations for `Asn1StringRef` and `Asn1BitStringRef`.
|
||||
* Added `EcPointRef::{to_pem, to_dir}` and `EcKeyRef::{public_key_from_pem, public_key_from_der}`.
|
||||
* Added `Default` implementations for many types.
|
||||
* Added `Debug` implementations for many types.
|
||||
* Added `SslStream::from_raw_parts`.
|
||||
* Added `SslRef::set_mtu`.
|
||||
* Added `Cipher::{aes_128_ocb, aes_192_ocb, aes_256_ocb}`.
|
||||
|
||||
### Deprecated
|
||||
|
||||
* Deprecated `SslStreamBuilder::set_dtls_mtu_size` in favor of `SslRef::set_mtu`.
|
||||
|
||||
## [v0.10.29] - 2020-04-07
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed a memory leak in `X509Builder::append_extension`.
|
||||
|
||||
### Added
|
||||
|
||||
* Added `SslConnector::into_context` and `SslConnector::context`.
|
||||
* Added `SslAcceptor::into_context` and `SslAcceptor::context`.
|
||||
* Added `SslMethod::tls_client` and `SslMethod::tls_server`.
|
||||
* Added `SslContextBuilder::set_cert_store`.
|
||||
* Added `SslContextRef::verify_mode` and `SslRef::verify_mode`.
|
||||
* Added `SslRef::is_init_finished`.
|
||||
* Added `X509Object`.
|
||||
* Added `X509StoreRef::objects`.
|
||||
|
||||
## [v0.10.28] - 2020-02-04
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed the mutability of `Signer::sign_oneshot` and `Verifier::verify_oneshot`. This is unfortunately a breaking
|
||||
change, but a necessary soundness fix.
|
||||
|
||||
## [v0.10.27] - 2020-01-29
|
||||
|
||||
### Added
|
||||
|
||||
* Added `MessageDigest::null`.
|
||||
* Added `PKey::private_key_from_pkcs8`.
|
||||
* Added `SslOptions::NO_RENEGOTIATION`.
|
||||
* Added `SslStreamBuilder::set_dtls_mtu_size`.
|
||||
|
||||
## [v0.10.26] - 2019-11-22
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed improper handling of the IV buffer in `envelope::{Seal, Unseal}`.
|
||||
|
||||
### Added
|
||||
|
||||
* Added `Asn1TimeRef::{diff, compare}`.
|
||||
* Added `Asn1Time::from_unix`.
|
||||
* Added `PartialEq` and `PartialOrd` implementations for `Asn1Time` and `Asn1TimeRef`.
|
||||
* Added `base64::{encode_block, decode_block}`.
|
||||
* Added `EcGroupRef::order_bits`.
|
||||
* Added `Clone` implementations for `Sha1`, `Sha224`, `Sha256`, `Sha384`, and `Sha512`.
|
||||
* Added `SslContextBuilder::{set_sigalgs_list, set_groups_list}`.
|
||||
|
||||
## [v0.10.25] - 2019-10-02
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed a memory leak in `EcdsaSig::from_private_components` when using OpenSSL 1.0.x.
|
||||
|
||||
### Added
|
||||
|
||||
* Added support for Ed25519 and Ed448 keys.
|
||||
* Implemented `ToOwned` for `PKeyRef` and `Clone` for `PKey`.
|
||||
|
||||
## [v0.10.24] - 2019-07-19
|
||||
|
||||
### Fixed
|
||||
|
||||
* Worked around an OpenSSL 1.0.x bug triggered by code calling `SSL_set_app_data`.
|
||||
|
||||
### Added
|
||||
|
||||
* Added `aes::{wrap_key, unwrap_key}`.
|
||||
* Added `CmsContentInfoRef::to_pem` and `CmsContentInfo::from_pem`.
|
||||
* Added `DsaRef::private_key_to_pem`.
|
||||
* Added `EcGroupRef::{cofactor, generator}`.
|
||||
* Added `EcPointRef::to_owned`.
|
||||
* Added a `Debug` implementation for `EcKey`.
|
||||
* Added `SslAcceptor::{mozilla_intermediate_v5, mozilla_modern_v5}`.
|
||||
* Added `Cipher::{aes_128_ofb, aes_192_ecb, aes_192_cbc, aes_192_ctr, aes_192_cfb1, aes_192_cfb128, aes_192_cfb8,
|
||||
aes_192_gcm, aes_192_ccm, aes_192_ofb, aes_256_ofb}`.
|
||||
|
||||
## [v0.10.23] - 2019-05-18
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed session callbacks when an `Ssl`'s context is replaced.
|
||||
|
||||
### Added
|
||||
|
||||
* Added `SslContextBuilder::add_client_ca`.
|
||||
|
||||
## [v0.10.22] - 2019-05-08
|
||||
|
||||
### Added
|
||||
|
||||
* Added support for the LibreSSL 2.9.x series.
|
||||
|
||||
## [v0.10.21] - 2019-04-30
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed overly conservatifve buffer size checks in `Crypter` when using stream ciphers.
|
||||
|
||||
### Added
|
||||
|
||||
* Added bindings to envelope encryption APIs.
|
||||
* Added `PkeyRef::size`.
|
||||
|
||||
## [v0.10.20] - 2019-03-20
|
||||
|
||||
### Added
|
||||
|
||||
* Added `CmsContentInfo::from_der` and `CmsContentInfo::encrypt`.
|
||||
* Added `X509Ref::verify` and `X509ReqRef::verify`.
|
||||
* Implemented `PartialEq` and `Eq` for `MessageDigest`.
|
||||
* Added `MessageDigest::type_` and `EcGroupRef::curve_name`.
|
||||
|
||||
## [v0.10.19] - 2019-03-01
|
||||
|
||||
### Added
|
||||
|
||||
* The openssl-sys build script now logs the values of environment variables.
|
||||
* Added `ERR_PACK` to openssl-sys.
|
||||
* The `ERR_*` functions in openssl-sys are const functions when building against newer Rust versions.
|
||||
* Implemented `Clone` for `Dsa`.
|
||||
* Added `SslContextRef::add_session` and `SslContextRef::remove_session`.
|
||||
* Added `SslSessionRef::time`, `SslSessionRef::timeout`, and `SslSessionRef::protocol_version`.
|
||||
* Added `SslContextBuilder::set_session_cache_size` and `SslContextRef::session_cache_size`.
|
||||
|
||||
## [v0.10.18] - 2019-02-22
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed the return type of `ssl::cipher_name`.
|
||||
|
||||
## [v0.10.17] - 2019-02-22
|
||||
|
||||
### Added
|
||||
|
||||
* Implemented `AsRef<str>` and `AsRef<[u8]>` for `OpenSslString`.
|
||||
* Added `Asn1Integer::from_bn`.
|
||||
* Added `RsaRef::check_key`.
|
||||
* Added `Asn1Time::from_str` and `Asn1Time::from_str_x509`.
|
||||
* Added `Rsa::generate_with_e`.
|
||||
* Added `Cipher::des_ede3_cfb64`.
|
||||
* Added `SslCipherRef::standard_name` and `ssl::cipher_name`.
|
||||
|
||||
## [v0.10.16] - 2018-12-16
|
||||
|
||||
### Added
|
||||
|
||||
* Added SHA3 and SHAKE to `MessageDigest`.
|
||||
* Added `rand::keep_random_devices_open`.
|
||||
* Added support for LibreSSL 2.9.0.
|
||||
|
||||
## [v0.10.15] - 2018-10-22
|
||||
|
||||
### Added
|
||||
|
||||
* Implemented `DoubleEndedIterator` for stack iterators.
|
||||
|
||||
## [v0.10.14] - 2018-10-18
|
||||
|
||||
### Fixed
|
||||
|
||||
* Made some accidentally exposed internal functions private.
|
||||
|
||||
### Added
|
||||
|
||||
* Added support for LibreSSL 2.8.
|
||||
|
||||
### Changed
|
||||
|
||||
* The OpenSSL version used with the `vendored` feature has been upgraded from 1.1.0 to 1.1.1.
|
||||
|
||||
## [v0.10.13] - 2018-10-14
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed a double-free in the `SslContextBuilder::set_get_session_callback` API.
|
||||
|
||||
### Added
|
||||
|
||||
* Added `SslContextBuilder::set_client_hello_callback`.
|
||||
* Added support for LibreSSL 2.8.1.
|
||||
* Added `EcdsaSig::from_der` and `EcdsaSig::to_der`.
|
||||
* Added PKCS#7 support.
|
||||
|
||||
## [v0.10.12] - 2018-09-13
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed handling of SNI callbacks during renegotiation.
|
||||
|
||||
### Added
|
||||
|
||||
* Added `SslRef::get_shutdown` and `SslRef::set_shutdown`.
|
||||
* Added support for SRTP in DTLS sessions.
|
||||
* Added support for LibreSSL 2.8.0.
|
||||
|
||||
## [v0.10.11] - 2018-08-04
|
||||
|
||||
### Added
|
||||
|
||||
* The new `vendored` cargo feature will cause openssl-sys to compile and statically link to a
|
||||
vendored copy of OpenSSL.
|
||||
* Added `SslContextBuilder::set_psk_server_callback`.
|
||||
* Added `DsaRef::pub_key` and `DsaRef::priv_key`.
|
||||
* Added `Dsa::from_private_components` and `Dsa::from_public_components`.
|
||||
* Added `X509NameRef::entries`.
|
||||
|
||||
### Deprecated
|
||||
|
||||
* `SslContextBuilder::set_psk_callback` has been renamed to
|
||||
`SslContextBuilder::set_psk_client_callback` and deprecated.
|
||||
|
||||
## [v0.10.10] - 2018-06-06
|
||||
|
||||
### Added
|
||||
|
||||
* Added `SslRef::set_alpn_protos`.
|
||||
* Added `SslContextBuilder::set_ciphersuites`.
|
||||
|
||||
## [v0.10.9] - 2018-06-01
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed a use-after-free in `CmsContentInfo::sign`.
|
||||
* `SslRef::servername` now returns `None` rather than panicking on a non-UTF8 name.
|
||||
|
||||
### Added
|
||||
|
||||
* Added `MessageDigest::from_nid`.
|
||||
* Added `Nid::signature_algorithms`, `Nid::long_name`, and `Nid::short_name`.
|
||||
* Added early data and early keying material export support for TLS 1.3.
|
||||
* Added `SslRef::verified_chain`.
|
||||
* Added `SslRef::servername_raw` which returns a `&[u8]` rather than `&str`.
|
||||
* Added `SslRef::finished` and `SslRef::peer_finished`.
|
||||
* Added `X509Ref::digest` to replace `X509Ref::fingerprint`.
|
||||
* `X509StoreBuilder` and `X509Store` now implement `Sync` and `Send`.
|
||||
|
||||
### Deprecated
|
||||
|
||||
* `X509Ref::fingerprint` has been deprecated in favor of `X509Ref::digest`.
|
||||
|
||||
## [v0.10.8] - 2018-05-20
|
||||
|
||||
### Fixed
|
||||
|
||||
* `openssl-sys` will now detect Homebrew-installed OpenSSL when installed to a non-default
|
||||
directory.
|
||||
* The `X509_V_ERR_INVALID_CALL`, `X509_V_ERR_STORE_LOOKUP`, and
|
||||
`X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION` constants in `openssl-sys` are now only present when
|
||||
building against 1.1.0g and up rather than 1.1.0.
|
||||
* `SslContextBuilder::max_proto_version` and `SslContextBuilder::min_proto_version` are only present
|
||||
when building against 1.1.0g and up rather than 1.1.0.
|
||||
|
||||
### Added
|
||||
|
||||
* Added `CmsContentInfo::sign`.
|
||||
* Added `Clone` and `ToOwned` implementations to `Rsa` and `RsaRef` respectively.
|
||||
* The `min_proto_version` and `max_proto_version` methods are available when linking against
|
||||
LibreSSL 2.6.1 and up in addition to OpenSSL.
|
||||
* `X509VerifyParam` is available when linking against LibreSSL 2.6.1 and up in addition to OpenSSL.
|
||||
* ALPN support is available when linking against LibreSSL 2.6.1 and up in addition to OpenSSL.
|
||||
* `Stack` and `StackRef` are now `Sync` and `Send`.
|
||||
|
||||
## [v0.10.7] - 2018-04-30
|
||||
|
||||
### Added
|
||||
|
||||
* Added `X509Req::public_key` and `X509Req::extensions`.
|
||||
* Added `RsaPrivateKeyBuilder` to allow control over initialization of optional components of an RSA
|
||||
private key.
|
||||
* Added DER encode/decode support to `SslSession`.
|
||||
* openssl-sys now provides the `DEP_OPENSSL_VERSION_NUMBER` and
|
||||
`DEP_OPENSSL_LIBRESSL_VERSION_NUMBER` environment variables to downstream build scripts which
|
||||
contains the hex-encoded version number of the OpenSSL or LibreSSL distribution being built
|
||||
against. The other variables are deprecated.
|
||||
|
||||
## [v0.10.6] - 2018-03-05
|
||||
|
||||
### Added
|
||||
|
||||
* Added `SslOptions::ENABLE_MIDDLEBOX_COMPAT`.
|
||||
* Added more `Sync` and `Send` implementations.
|
||||
* Added `PKeyRef::id`.
|
||||
* Added `Padding::PKCS1_PSS`.
|
||||
* Added `Signer::set_rsa_pss_saltlen`, `Signer::set_rsa_mgf1_md`, `Signer::set_rsa_pss_saltlen`, and
|
||||
`Signer::set_rsa_mgf1_md`
|
||||
* Added `X509StoreContextRef::verify` to directly verify certificates.
|
||||
* Added low level ECDSA support.
|
||||
* Added support for TLSv1.3 custom extensions. (OpenSSL 1.1.1 only)
|
||||
* Added AES-CCM support.
|
||||
* Added `EcKey::from_private_components`.
|
||||
* Added CMAC support.
|
||||
* Added support for LibreSSL 2.7.
|
||||
* Added `X509Ref::serial_number`.
|
||||
* Added `Asn1IntegerRef::to_bn`.
|
||||
* Added support for TLSv1.3 stateless handshakes. (OpenSSL 1.1.1 only)
|
||||
|
||||
### Changed
|
||||
|
||||
* The Cargo features previously used to gate access to version-specific OpenSSL APIs have been
|
||||
removed. Those APIs will be available automatically when building against an appropriate OpenSSL
|
||||
version.
|
||||
* Fixed `PKey::private_key_from_der` to return a `PKey<Private>` rather than a `PKey<Public>`. This
|
||||
is technically a breaking change but the function was pretty useless previously.
|
||||
|
||||
### Deprecated
|
||||
|
||||
* `X509CheckFlags::FLAG_NO_WILDCARDS` has been renamed to `X509CheckFlags::NO_WILDCARDS` and the old
|
||||
name deprecated.
|
||||
|
||||
## [v0.10.5] - 2018-02-28
|
||||
|
||||
### Fixed
|
||||
|
||||
* `ErrorStack`'s `Display` implementation no longer writes an empty string if it contains no errors.
|
||||
|
||||
### Added
|
||||
|
||||
* Added `SslRef::version2`.
|
||||
* Added `Cipher::des_ede3_cbc`.
|
||||
* Added `SslRef::export_keying_material`.
|
||||
* Added the ability to push an `Error` or `ErrorStack` back onto OpenSSL's error stack. Various
|
||||
callback bindings use this to propagate errors properly.
|
||||
* Added `SslContextBuilder::set_cookie_generate_cb` and `SslContextBuilder::set_cookie_verify_cb`.
|
||||
* Added `SslContextBuilder::set_max_proto_version`, `SslContextBuilder::set_min_proto_version`,
|
||||
`SslContextBuilder::max_proto_version`, and `SslContextBuilder::min_proto_version`.
|
||||
|
||||
### Changed
|
||||
|
||||
* Updated `SslConnector`'s default cipher list to match Python's.
|
||||
|
||||
### Deprecated
|
||||
|
||||
* `SslRef::version` has been deprecated. Use `SslRef::version_str` instead.
|
||||
|
||||
## [v0.10.4] - 2018-02-18
|
||||
|
||||
### Added
|
||||
|
||||
* Added OpenSSL 1.1.1 support.
|
||||
* Added `Rsa::public_key_from_pem_pkcs1`.
|
||||
* Added `SslOptions::NO_TLSV1_3`. (OpenSSL 1.1.1 only)
|
||||
* Added `SslVersion`.
|
||||
* Added `SslSessionCacheMode` and `SslContextBuilder::set_session_cache_mode`.
|
||||
* Added `SslContextBuilder::set_new_session_callback`,
|
||||
`SslContextBuilder::set_remove_session_callback`, and
|
||||
`SslContextBuilder::set_get_session_callback`.
|
||||
* Added `SslContextBuilder::set_keylog_callback`. (OpenSSL 1.1.1 only)
|
||||
* Added `SslRef::client_random` and `SslRef::server_random`. (OpenSSL 1.1.0+ only)
|
||||
|
||||
### Fixed
|
||||
|
||||
* The `SslAcceptorBuilder::mozilla_modern` constructor now disables TLSv1.0 and TLSv1.1 in
|
||||
accordance with Mozilla's recommendations.
|
||||
|
||||
## [v0.10.3] - 2018-02-12
|
||||
|
||||
### Added
|
||||
|
||||
* OpenSSL is now automatically detected on FreeBSD systems.
|
||||
* Added `GeneralName` accessors for `rfc822Name` and `uri` variants.
|
||||
* Added DES-EDE3 support.
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed a memory leak in `X509StoreBuilder::add_cert`.
|
||||
|
||||
## [v0.10.2] - 2018-01-11
|
||||
|
||||
### Added
|
||||
|
||||
* Added `ConnectConfiguration::set_use_server_name_indication` and
|
||||
`ConnectConfiguration::set_verify_hostname` for use in contexts where you don't have ownership
|
||||
of the `ConnectConfiguration`.
|
||||
|
||||
## [v0.10.1] - 2018-01-10
|
||||
|
||||
### Added
|
||||
|
||||
* Added a `From<ErrorStack> for ssl::Error` implementation.
|
||||
|
||||
## [v0.10.0] - 2018-01-10
|
||||
|
||||
### Compatibility
|
||||
|
||||
* openssl 0.10 still uses openssl-sys 0.9, so openssl 0.9 and 0.10 can coexist without issue.
|
||||
|
||||
### Added
|
||||
|
||||
* The `ssl::select_next_proto` function can be used to easily implement the ALPN selection callback
|
||||
in a "standard" way.
|
||||
* FIPS mode support is available in the `fips` module.
|
||||
* Accessors for the Issuer and Issuer Alternative Name fields of X509 certificates have been added.
|
||||
* The `X509VerifyResult` can now be set in the certificate verification callback via
|
||||
`X509StoreContextRef::set_error`.
|
||||
|
||||
### Changed
|
||||
|
||||
* All constants have been moved to associated constants of their type. For example, `bn::MSB_ONE`
|
||||
is now `bn::MsbOption::ONE`.
|
||||
* Asymmetric key types are now parameterized over what they contain. In OpenSSL, the same type is
|
||||
used for key parameters, public keys, and private keys. Unfortunately, some APIs simply assume
|
||||
that certain components are present and will segfault trying to use things that aren't there.
|
||||
|
||||
The `pkey` module contains new tag types named `Params`, `Public`, and `Private`, and the
|
||||
`Dh`, `Dsa`, `EcKey`, `Rsa`, and `PKey` have a type parameter set to one of those values. This
|
||||
allows the `Signer` constructor to indicate that it requires a private key at compile time for
|
||||
example. Previously, `Signer` would simply segfault if provided a key without private
|
||||
components.
|
||||
* ALPN support has been changed to more directly model OpenSSL's own APIs. Instead of a single
|
||||
method used for both the server and client sides which performed everything automatically, the
|
||||
`SslContextBuilder::set_alpn_protos` and `SslContextBuilder::set_alpn_select_callback` handle
|
||||
the client and server sides respectively.
|
||||
* `SslConnector::danger_connect_without_providing_domain_for_certificate_verification_and_server_name_indication`
|
||||
has been removed in favor of new methods which provide more control. The
|
||||
`ConnectConfiguration::use_server_name_indication` method controls the use of Server Name
|
||||
Indication (SNI), and the `ConnectConfiguration::verify_hostname` method controls the use of
|
||||
hostname verification. These can be controlled independently, and if both are disabled, the
|
||||
domain argument to `ConnectConfiguration::connect` is ignored.
|
||||
* Shared secret derivation is now handled by the new `derive::Deriver` type rather than
|
||||
`pkey::PKeyContext`, which has been removed.
|
||||
* `ssl::Error` is now no longer an enum, and provides more direct access to the relevant state.
|
||||
* `SslConnectorBuilder::new` has been moved and renamed to `SslConnector::builder`.
|
||||
* `SslAcceptorBuilder::mozilla_intermediate` and `SslAcceptorBuilder::mozilla_modern` have been
|
||||
moved to `SslAcceptor` and no longer take the private key and certificate chain. Install those
|
||||
manually after creating the builder.
|
||||
* `X509VerifyError` is now `X509VerifyResult` and can now have the "ok" value in addition to error
|
||||
values.
|
||||
* `x509::X509FileType` is now `ssl::SslFiletype`.
|
||||
* Asymmetric key serialization and deserialization methods now document the formats that they
|
||||
correspond to, and some have been renamed to better indicate that.
|
||||
|
||||
### Removed
|
||||
|
||||
* All deprecated APIs have been removed.
|
||||
* NPN support has been removed. It has been supersceded by ALPN, and is hopefully no longer being
|
||||
used in practice. If you still depend on it, please file an issue!
|
||||
* `SslRef::compression` has been removed.
|
||||
* Some `ssl::SslOptions` flags have been removed as they no longer do anything.
|
||||
|
||||
## Older
|
||||
|
||||
Look at the [release tags] for information about older releases.
|
||||
|
||||
[Unreleased]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.40...master
|
||||
[v0.10.40]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.39...openssl-v0.10.40
|
||||
[v0.10.39]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.38...openssl-v0.10.39
|
||||
[v0.10.38]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.37...openssl-v0.10.38
|
||||
[v0.10.37]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.36...openssl-v0.10.37
|
||||
[v0.10.36]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.35...openssl-v0.10.36
|
||||
[v0.10.35]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.34...openssl-v0.10.35
|
||||
[v0.10.34]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.33...openssl-v0.10.34
|
||||
[v0.10.33]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.32...openssl-v0.10.33
|
||||
[v0.10.32]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.31...openssl-v0.10.32
|
||||
[v0.10.31]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.30...openssl-v0.10.31
|
||||
[v0.10.30]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.29...openssl-v0.10.30
|
||||
[v0.10.29]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.28...openssl-v0.10.29
|
||||
[v0.10.28]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.27...openssl-v0.10.28
|
||||
[v0.10.27]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.26...openssl-v0.10.27
|
||||
[v0.10.26]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.25...openssl-v0.10.26
|
||||
[v0.10.25]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.24...openssl-v0.10.25
|
||||
[v0.10.24]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.23...openssl-v0.10.24
|
||||
[v0.10.23]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.22...openssl-v0.10.23
|
||||
[v0.10.22]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.21...openssl-v0.10.22
|
||||
[v0.10.21]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.20...openssl-v0.10.21
|
||||
[v0.10.20]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.19...openssl-v0.10.20
|
||||
[v0.10.19]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.18...openssl-v0.10.19
|
||||
[v0.10.18]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.17...openssl-v0.10.18
|
||||
[v0.10.17]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.16...openssl-v0.10.17
|
||||
[v0.10.16]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.15...openssl-v0.10.16
|
||||
[v0.10.15]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.14...openssl-v0.10.15
|
||||
[v0.10.14]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.13...openssl-v0.10.14
|
||||
[v0.10.13]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.12...openssl-v0.10.13
|
||||
[v0.10.12]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.11...openssl-v0.10.12
|
||||
[v0.10.11]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.10...openssl-v0.10.11
|
||||
[v0.10.10]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.9...openssl-v0.10.10
|
||||
[v0.10.9]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.8...openssl-v0.10.9
|
||||
[v0.10.8]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.7...openssl-v0.10.8
|
||||
[v0.10.7]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.6...openssl-v0.10.7
|
||||
[v0.10.6]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.5...openssl-v0.10.6
|
||||
[v0.10.5]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.4...openssl-v0.10.5
|
||||
[v0.10.4]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.3...openssl-v0.10.4
|
||||
[v0.10.3]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.2...openssl-v0.10.3
|
||||
[v0.10.2]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.1...openssl-v0.10.2
|
||||
[v0.10.1]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.0...openssl-v0.10.1
|
||||
[v0.10.0]: https://github.com/sfackler/rust-openssl/compare/v0.9.23...openssl-v0.10.0
|
||||
[release tags]: https://github.com/sfackler/rust-openssl/releases
|
||||
449
zeroidc/vendor/openssl/Cargo.lock
generated
vendored
Normal file
449
zeroidc/vendor/openssl/Cargo.lock
generated
vendored
Normal file
@@ -0,0 +1,449 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.59.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"clap",
|
||||
"env_logger",
|
||||
"lazy_static",
|
||||
"lazycell",
|
||||
"log",
|
||||
"peeking_take_while",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cc00842eed744b858222c4c9faf7243aafc6d33f92f96935263ef4d8a41ce21"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"atty",
|
||||
"bitflags",
|
||||
"strsim",
|
||||
"textwrap",
|
||||
"unicode-width",
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"humantime",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
dependencies = [
|
||||
"foreign-types-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "lazycell"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.40"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"hex",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"openssl-macros",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-src"
|
||||
version = "111.18.0+1.1.1n"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7897a926e1e8d00219127dc020130eca4292e5ca666dd592480d72c3eca2ff6c"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bindgen",
|
||||
"cc",
|
||||
"libc",
|
||||
"openssl-src",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peeking_take_while"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae"
|
||||
dependencies = [
|
||||
"either",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
63
zeroidc/vendor/openssl/Cargo.toml
vendored
Normal file
63
zeroidc/vendor/openssl/Cargo.toml
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "openssl"
|
||||
version = "0.10.40"
|
||||
authors = ["Steven Fackler <sfackler@gmail.com>"]
|
||||
description = "OpenSSL bindings"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"crypto",
|
||||
"tls",
|
||||
"ssl",
|
||||
"dtls",
|
||||
]
|
||||
categories = [
|
||||
"cryptography",
|
||||
"api-bindings",
|
||||
]
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/sfackler/rust-openssl"
|
||||
|
||||
[dependencies.bitflags]
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.cfg-if]
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.ffi]
|
||||
version = "0.9.73"
|
||||
package = "openssl-sys"
|
||||
|
||||
[dependencies.foreign-types]
|
||||
version = "0.3.1"
|
||||
|
||||
[dependencies.libc]
|
||||
version = "0.2"
|
||||
|
||||
[dependencies.once_cell]
|
||||
version = "1.5.2"
|
||||
|
||||
[dependencies.openssl-macros]
|
||||
version = "0.1.0"
|
||||
|
||||
[dev-dependencies.hex]
|
||||
version = "0.3"
|
||||
|
||||
[features]
|
||||
bindgen = ["ffi/bindgen"]
|
||||
v101 = []
|
||||
v102 = []
|
||||
v110 = []
|
||||
v111 = []
|
||||
vendored = ["ffi/vendored"]
|
||||
15
zeroidc/vendor/openssl/LICENSE
vendored
Normal file
15
zeroidc/vendor/openssl/LICENSE
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
Copyright 2011-2017 Google Inc.
|
||||
2013 Jack Lloyd
|
||||
2013-2014 Steven Fackler
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
22
zeroidc/vendor/openssl/README.md
vendored
Normal file
22
zeroidc/vendor/openssl/README.md
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# rust-openssl
|
||||
|
||||
[](https://crates.io/crates/openssl)
|
||||
|
||||
OpenSSL bindings for the Rust programming language.
|
||||
|
||||
[Documentation](https://docs.rs/openssl).
|
||||
|
||||
## Release Support
|
||||
|
||||
The current supported release of `openssl` is 0.10 and `openssl-sys` is 0.9.
|
||||
|
||||
New major versions will be published at most once per year. After a new
|
||||
release, the previous major version will be partially supported with bug
|
||||
fixes for 3 months, after which support will be dropped entirely.
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally
|
||||
submitted for inclusion in the work by you, as defined in the Apache-2.0
|
||||
license, shall be dual licensed under the terms of both the Apache License,
|
||||
Version 2.0 and the MIT license without any additional terms or conditions.
|
||||
89
zeroidc/vendor/openssl/build.rs
vendored
Normal file
89
zeroidc/vendor/openssl/build.rs
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
#![allow(clippy::inconsistent_digit_grouping, clippy::unusual_byte_groupings)]
|
||||
|
||||
use std::env;
|
||||
|
||||
fn main() {
|
||||
if env::var("DEP_OPENSSL_LIBRESSL").is_ok() {
|
||||
println!("cargo:rustc-cfg=libressl");
|
||||
}
|
||||
|
||||
if let Ok(v) = env::var("DEP_OPENSSL_LIBRESSL_VERSION") {
|
||||
println!("cargo:rustc-cfg=libressl{}", v);
|
||||
}
|
||||
|
||||
if let Ok(vars) = env::var("DEP_OPENSSL_CONF") {
|
||||
for var in vars.split(',') {
|
||||
println!("cargo:rustc-cfg=osslconf=\"{}\"", var);
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(version) = env::var("DEP_OPENSSL_VERSION_NUMBER") {
|
||||
let version = u64::from_str_radix(&version, 16).unwrap();
|
||||
|
||||
if version >= 0x1_00_01_00_0 {
|
||||
println!("cargo:rustc-cfg=ossl101");
|
||||
}
|
||||
if version >= 0x1_00_02_00_0 {
|
||||
println!("cargo:rustc-cfg=ossl102");
|
||||
}
|
||||
if version >= 0x1_01_00_00_0 {
|
||||
println!("cargo:rustc-cfg=ossl110");
|
||||
}
|
||||
if version >= 0x1_01_00_07_0 {
|
||||
println!("cargo:rustc-cfg=ossl110g");
|
||||
}
|
||||
if version >= 0x1_01_00_08_0 {
|
||||
println!("cargo:rustc-cfg=ossl110h");
|
||||
}
|
||||
if version >= 0x1_01_01_00_0 {
|
||||
println!("cargo:rustc-cfg=ossl111");
|
||||
}
|
||||
if version >= 0x3_00_00_00_0 {
|
||||
println!("cargo:rustc-cfg=ossl300");
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(version) = env::var("DEP_OPENSSL_LIBRESSL_VERSION_NUMBER") {
|
||||
let version = u64::from_str_radix(&version, 16).unwrap();
|
||||
|
||||
if version >= 0x2_06_01_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl261");
|
||||
}
|
||||
|
||||
if version >= 0x2_07_00_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl270");
|
||||
}
|
||||
|
||||
if version >= 0x2_07_01_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl271");
|
||||
}
|
||||
|
||||
if version >= 0x2_07_03_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl273");
|
||||
}
|
||||
|
||||
if version >= 0x2_08_00_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl280");
|
||||
}
|
||||
|
||||
if version >= 0x2_09_01_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl291");
|
||||
}
|
||||
|
||||
if version >= 0x3_02_01_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl321");
|
||||
}
|
||||
|
||||
if version >= 0x3_03_02_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl332");
|
||||
}
|
||||
|
||||
if version >= 0x3_04_00_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl340");
|
||||
}
|
||||
|
||||
if version >= 0x3_05_00_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl350");
|
||||
}
|
||||
}
|
||||
}
|
||||
158
zeroidc/vendor/openssl/examples/mk_certs.rs
vendored
Normal file
158
zeroidc/vendor/openssl/examples/mk_certs.rs
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
//! A program that generates ca certs, certs verified by the ca, and public
|
||||
//! and private keys.
|
||||
|
||||
use openssl::asn1::Asn1Time;
|
||||
use openssl::bn::{BigNum, MsbOption};
|
||||
use openssl::error::ErrorStack;
|
||||
use openssl::hash::MessageDigest;
|
||||
use openssl::pkey::{PKey, PKeyRef, Private};
|
||||
use openssl::rsa::Rsa;
|
||||
use openssl::x509::extension::{
|
||||
AuthorityKeyIdentifier, BasicConstraints, KeyUsage, SubjectAlternativeName,
|
||||
SubjectKeyIdentifier,
|
||||
};
|
||||
use openssl::x509::{X509NameBuilder, X509Ref, X509Req, X509ReqBuilder, X509VerifyResult, X509};
|
||||
|
||||
/// Make a CA certificate and private key
|
||||
fn mk_ca_cert() -> Result<(X509, PKey<Private>), ErrorStack> {
|
||||
let rsa = Rsa::generate(2048)?;
|
||||
let key_pair = PKey::from_rsa(rsa)?;
|
||||
|
||||
let mut x509_name = X509NameBuilder::new()?;
|
||||
x509_name.append_entry_by_text("C", "US")?;
|
||||
x509_name.append_entry_by_text("ST", "TX")?;
|
||||
x509_name.append_entry_by_text("O", "Some CA organization")?;
|
||||
x509_name.append_entry_by_text("CN", "ca test")?;
|
||||
let x509_name = x509_name.build();
|
||||
|
||||
let mut cert_builder = X509::builder()?;
|
||||
cert_builder.set_version(2)?;
|
||||
let serial_number = {
|
||||
let mut serial = BigNum::new()?;
|
||||
serial.rand(159, MsbOption::MAYBE_ZERO, false)?;
|
||||
serial.to_asn1_integer()?
|
||||
};
|
||||
cert_builder.set_serial_number(&serial_number)?;
|
||||
cert_builder.set_subject_name(&x509_name)?;
|
||||
cert_builder.set_issuer_name(&x509_name)?;
|
||||
cert_builder.set_pubkey(&key_pair)?;
|
||||
let not_before = Asn1Time::days_from_now(0)?;
|
||||
cert_builder.set_not_before(¬_before)?;
|
||||
let not_after = Asn1Time::days_from_now(365)?;
|
||||
cert_builder.set_not_after(¬_after)?;
|
||||
|
||||
cert_builder.append_extension(BasicConstraints::new().critical().ca().build()?)?;
|
||||
cert_builder.append_extension(
|
||||
KeyUsage::new()
|
||||
.critical()
|
||||
.key_cert_sign()
|
||||
.crl_sign()
|
||||
.build()?,
|
||||
)?;
|
||||
|
||||
let subject_key_identifier =
|
||||
SubjectKeyIdentifier::new().build(&cert_builder.x509v3_context(None, None))?;
|
||||
cert_builder.append_extension(subject_key_identifier)?;
|
||||
|
||||
cert_builder.sign(&key_pair, MessageDigest::sha256())?;
|
||||
let cert = cert_builder.build();
|
||||
|
||||
Ok((cert, key_pair))
|
||||
}
|
||||
|
||||
/// Make a X509 request with the given private key
|
||||
fn mk_request(key_pair: &PKey<Private>) -> Result<X509Req, ErrorStack> {
|
||||
let mut req_builder = X509ReqBuilder::new()?;
|
||||
req_builder.set_pubkey(key_pair)?;
|
||||
|
||||
let mut x509_name = X509NameBuilder::new()?;
|
||||
x509_name.append_entry_by_text("C", "US")?;
|
||||
x509_name.append_entry_by_text("ST", "TX")?;
|
||||
x509_name.append_entry_by_text("O", "Some organization")?;
|
||||
x509_name.append_entry_by_text("CN", "www.example.com")?;
|
||||
let x509_name = x509_name.build();
|
||||
req_builder.set_subject_name(&x509_name)?;
|
||||
|
||||
req_builder.sign(key_pair, MessageDigest::sha256())?;
|
||||
let req = req_builder.build();
|
||||
Ok(req)
|
||||
}
|
||||
|
||||
/// Make a certificate and private key signed by the given CA cert and private key
|
||||
fn mk_ca_signed_cert(
|
||||
ca_cert: &X509Ref,
|
||||
ca_key_pair: &PKeyRef<Private>,
|
||||
) -> Result<(X509, PKey<Private>), ErrorStack> {
|
||||
let rsa = Rsa::generate(2048)?;
|
||||
let key_pair = PKey::from_rsa(rsa)?;
|
||||
|
||||
let req = mk_request(&key_pair)?;
|
||||
|
||||
let mut cert_builder = X509::builder()?;
|
||||
cert_builder.set_version(2)?;
|
||||
let serial_number = {
|
||||
let mut serial = BigNum::new()?;
|
||||
serial.rand(159, MsbOption::MAYBE_ZERO, false)?;
|
||||
serial.to_asn1_integer()?
|
||||
};
|
||||
cert_builder.set_serial_number(&serial_number)?;
|
||||
cert_builder.set_subject_name(req.subject_name())?;
|
||||
cert_builder.set_issuer_name(ca_cert.subject_name())?;
|
||||
cert_builder.set_pubkey(&key_pair)?;
|
||||
let not_before = Asn1Time::days_from_now(0)?;
|
||||
cert_builder.set_not_before(¬_before)?;
|
||||
let not_after = Asn1Time::days_from_now(365)?;
|
||||
cert_builder.set_not_after(¬_after)?;
|
||||
|
||||
cert_builder.append_extension(BasicConstraints::new().build()?)?;
|
||||
|
||||
cert_builder.append_extension(
|
||||
KeyUsage::new()
|
||||
.critical()
|
||||
.non_repudiation()
|
||||
.digital_signature()
|
||||
.key_encipherment()
|
||||
.build()?,
|
||||
)?;
|
||||
|
||||
let subject_key_identifier =
|
||||
SubjectKeyIdentifier::new().build(&cert_builder.x509v3_context(Some(ca_cert), None))?;
|
||||
cert_builder.append_extension(subject_key_identifier)?;
|
||||
|
||||
let auth_key_identifier = AuthorityKeyIdentifier::new()
|
||||
.keyid(false)
|
||||
.issuer(false)
|
||||
.build(&cert_builder.x509v3_context(Some(ca_cert), None))?;
|
||||
cert_builder.append_extension(auth_key_identifier)?;
|
||||
|
||||
let subject_alt_name = SubjectAlternativeName::new()
|
||||
.dns("*.example.com")
|
||||
.dns("hello.com")
|
||||
.build(&cert_builder.x509v3_context(Some(ca_cert), None))?;
|
||||
cert_builder.append_extension(subject_alt_name)?;
|
||||
|
||||
cert_builder.sign(ca_key_pair, MessageDigest::sha256())?;
|
||||
let cert = cert_builder.build();
|
||||
|
||||
Ok((cert, key_pair))
|
||||
}
|
||||
|
||||
fn real_main() -> Result<(), ErrorStack> {
|
||||
let (ca_cert, ca_key_pair) = mk_ca_cert()?;
|
||||
let (cert, _key_pair) = mk_ca_signed_cert(&ca_cert, &ca_key_pair)?;
|
||||
|
||||
// Verify that this cert was issued by this ca
|
||||
match ca_cert.issued(&cert) {
|
||||
X509VerifyResult::OK => println!("Certificate verified!"),
|
||||
ver_err => println!("Failed to verify certificate: {}", ver_err),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match real_main() {
|
||||
Ok(()) => println!("Finished."),
|
||||
Err(e) => println!("Error: {}", e),
|
||||
};
|
||||
}
|
||||
297
zeroidc/vendor/openssl/src/aes.rs
vendored
Normal file
297
zeroidc/vendor/openssl/src/aes.rs
vendored
Normal file
@@ -0,0 +1,297 @@
|
||||
//! Low level AES IGE and key wrapping functionality
|
||||
//!
|
||||
//! AES ECB, CBC, XTS, CTR, CFB, GCM and other conventional symmetric encryption
|
||||
//! modes are found in [`symm`]. This is the implementation of AES IGE and key wrapping
|
||||
//!
|
||||
//! Advanced Encryption Standard (AES) provides symmetric key cipher that
|
||||
//! the same key is used to encrypt and decrypt data. This implementation
|
||||
//! uses 128, 192, or 256 bit keys. This module provides functions to
|
||||
//! create a new key with [`new_encrypt`] and perform an encryption/decryption
|
||||
//! using that key with [`aes_ige`].
|
||||
//!
|
||||
//! [`new_encrypt`]: struct.AesKey.html#method.new_encrypt
|
||||
//! [`aes_ige`]: fn.aes_ige.html
|
||||
//!
|
||||
//! The [`symm`] module should be used in preference to this module in most cases.
|
||||
//! The IGE block cipher is a non-traditional cipher mode. More traditional AES
|
||||
//! encryption methods are found in the [`Crypter`] and [`Cipher`] structs.
|
||||
//!
|
||||
//! [`symm`]: ../symm/index.html
|
||||
//! [`Crypter`]: ../symm/struct.Crypter.html
|
||||
//! [`Cipher`]: ../symm/struct.Cipher.html
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! ## AES IGE
|
||||
//! ```rust
|
||||
//! use openssl::aes::{AesKey, aes_ige};
|
||||
//! use openssl::symm::Mode;
|
||||
//!
|
||||
//! let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
|
||||
//! let plaintext = b"\x12\x34\x56\x78\x90\x12\x34\x56\x12\x34\x56\x78\x90\x12\x34\x56";
|
||||
//! let mut iv = *b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\
|
||||
//! \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
|
||||
//!
|
||||
//! let key = AesKey::new_encrypt(key).unwrap();
|
||||
//! let mut output = [0u8; 16];
|
||||
//! aes_ige(plaintext, &mut output, &key, &mut iv, Mode::Encrypt);
|
||||
//! assert_eq!(output, *b"\xa6\xad\x97\x4d\x5c\xea\x1d\x36\xd2\xf3\x67\x98\x09\x07\xed\x32");
|
||||
//! ```
|
||||
//!
|
||||
//! ## Key wrapping
|
||||
//! ```rust
|
||||
//! use openssl::aes::{AesKey, unwrap_key, wrap_key};
|
||||
//!
|
||||
//! let kek = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
|
||||
//! let key_to_wrap = b"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF";
|
||||
//!
|
||||
//! let enc_key = AesKey::new_encrypt(kek).unwrap();
|
||||
//! let mut ciphertext = [0u8; 24];
|
||||
//! wrap_key(&enc_key, None, &mut ciphertext, &key_to_wrap[..]).unwrap();
|
||||
//! let dec_key = AesKey::new_decrypt(kek).unwrap();
|
||||
//! let mut orig_key = [0u8; 16];
|
||||
//! unwrap_key(&dec_key, None, &mut orig_key, &ciphertext[..]).unwrap();
|
||||
//!
|
||||
//! assert_eq!(&orig_key[..], &key_to_wrap[..]);
|
||||
//! ```
|
||||
//!
|
||||
use libc::{c_int, c_uint};
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr;
|
||||
|
||||
use crate::symm::Mode;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
/// Provides Error handling for parsing keys.
|
||||
#[derive(Debug)]
|
||||
pub struct KeyError(());
|
||||
|
||||
/// The key used to encrypt or decrypt cipher blocks.
|
||||
pub struct AesKey(ffi::AES_KEY);
|
||||
|
||||
impl AesKey {
|
||||
/// Prepares a key for encryption.
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// Returns an error if the key is not 128, 192, or 256 bits.
|
||||
#[corresponds(AES_set_encrypt_key)]
|
||||
pub fn new_encrypt(key: &[u8]) -> Result<AesKey, KeyError> {
|
||||
unsafe {
|
||||
assert!(key.len() <= c_int::max_value() as usize / 8);
|
||||
|
||||
let mut aes_key = MaybeUninit::uninit();
|
||||
let r = ffi::AES_set_encrypt_key(
|
||||
key.as_ptr() as *const _,
|
||||
key.len() as c_int * 8,
|
||||
aes_key.as_mut_ptr(),
|
||||
);
|
||||
if r == 0 {
|
||||
Ok(AesKey(aes_key.assume_init()))
|
||||
} else {
|
||||
Err(KeyError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepares a key for decryption.
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// Returns an error if the key is not 128, 192, or 256 bits.
|
||||
#[corresponds(AES_set_decrypt_key)]
|
||||
pub fn new_decrypt(key: &[u8]) -> Result<AesKey, KeyError> {
|
||||
unsafe {
|
||||
assert!(key.len() <= c_int::max_value() as usize / 8);
|
||||
|
||||
let mut aes_key = MaybeUninit::uninit();
|
||||
let r = ffi::AES_set_decrypt_key(
|
||||
key.as_ptr() as *const _,
|
||||
key.len() as c_int * 8,
|
||||
aes_key.as_mut_ptr(),
|
||||
);
|
||||
|
||||
if r == 0 {
|
||||
Ok(AesKey(aes_key.assume_init()))
|
||||
} else {
|
||||
Err(KeyError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs AES IGE encryption or decryption
|
||||
///
|
||||
/// AES IGE (Infinite Garble Extension) is a form of AES block cipher utilized in
|
||||
/// OpenSSL. Infinite Garble refers to propagating forward errors. IGE, like other
|
||||
/// block ciphers implemented for AES requires an initialization vector. The IGE mode
|
||||
/// allows a stream of blocks to be encrypted or decrypted without having the entire
|
||||
/// plaintext available. For more information, visit [AES IGE Encryption].
|
||||
///
|
||||
/// This block cipher uses 16 byte blocks. The rust implementation will panic
|
||||
/// if the input or output does not meet this 16-byte boundary. Attention must
|
||||
/// be made in this low level implementation to pad the value to the 128-bit boundary.
|
||||
///
|
||||
/// [AES IGE Encryption]: http://www.links.org/files/openssl-ige.pdf
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `in_` is not the same length as `out`, if that length is not a multiple of 16, or if
|
||||
/// `iv` is not at least 32 bytes.
|
||||
#[corresponds(AES_ige_encrypt)]
|
||||
pub fn aes_ige(in_: &[u8], out: &mut [u8], key: &AesKey, iv: &mut [u8], mode: Mode) {
|
||||
unsafe {
|
||||
assert!(in_.len() == out.len());
|
||||
assert!(in_.len() % ffi::AES_BLOCK_SIZE as usize == 0);
|
||||
assert!(iv.len() >= ffi::AES_BLOCK_SIZE as usize * 2);
|
||||
|
||||
let mode = match mode {
|
||||
Mode::Encrypt => ffi::AES_ENCRYPT,
|
||||
Mode::Decrypt => ffi::AES_DECRYPT,
|
||||
};
|
||||
ffi::AES_ige_encrypt(
|
||||
in_.as_ptr() as *const _,
|
||||
out.as_mut_ptr() as *mut _,
|
||||
in_.len(),
|
||||
&key.0,
|
||||
iv.as_mut_ptr() as *mut _,
|
||||
mode,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrap a key, according to [RFC 3394](https://tools.ietf.org/html/rfc3394)
|
||||
///
|
||||
/// * `key`: The key-encrypting-key to use. Must be a encrypting key
|
||||
/// * `iv`: The IV to use. You must use the same IV for both wrapping and unwrapping
|
||||
/// * `out`: The output buffer to store the ciphertext
|
||||
/// * `in_`: The input buffer, storing the key to be wrapped
|
||||
///
|
||||
/// Returns the number of bytes written into `out`
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if either `out` or `in_` do not have sizes that are a multiple of 8, or if
|
||||
/// `out` is not 8 bytes longer than `in_`
|
||||
#[corresponds(AES_wrap_key)]
|
||||
pub fn wrap_key(
|
||||
key: &AesKey,
|
||||
iv: Option<[u8; 8]>,
|
||||
out: &mut [u8],
|
||||
in_: &[u8],
|
||||
) -> Result<usize, KeyError> {
|
||||
unsafe {
|
||||
assert!(out.len() >= in_.len() + 8); // Ciphertext is 64 bits longer (see 2.2.1)
|
||||
|
||||
let written = ffi::AES_wrap_key(
|
||||
&key.0 as *const _ as *mut _, // this is safe, the implementation only uses the key as a const pointer.
|
||||
iv.as_ref()
|
||||
.map_or(ptr::null(), |iv| iv.as_ptr() as *const _),
|
||||
out.as_ptr() as *mut _,
|
||||
in_.as_ptr() as *const _,
|
||||
in_.len() as c_uint,
|
||||
);
|
||||
if written <= 0 {
|
||||
Err(KeyError(()))
|
||||
} else {
|
||||
Ok(written as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Unwrap a key, according to [RFC 3394](https://tools.ietf.org/html/rfc3394)
|
||||
///
|
||||
/// * `key`: The key-encrypting-key to decrypt the wrapped key. Must be a decrypting key
|
||||
/// * `iv`: The same IV used for wrapping the key
|
||||
/// * `out`: The buffer to write the unwrapped key to
|
||||
/// * `in_`: The input ciphertext
|
||||
///
|
||||
/// Returns the number of bytes written into `out`
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if either `out` or `in_` do not have sizes that are a multiple of 8, or
|
||||
/// if `in_` is not 8 bytes longer than `out`
|
||||
#[corresponds(AES_unwrap_key)]
|
||||
pub fn unwrap_key(
|
||||
key: &AesKey,
|
||||
iv: Option<[u8; 8]>,
|
||||
out: &mut [u8],
|
||||
in_: &[u8],
|
||||
) -> Result<usize, KeyError> {
|
||||
unsafe {
|
||||
assert!(out.len() + 8 <= in_.len());
|
||||
|
||||
let written = ffi::AES_unwrap_key(
|
||||
&key.0 as *const _ as *mut _, // this is safe, the implementation only uses the key as a const pointer.
|
||||
iv.as_ref()
|
||||
.map_or(ptr::null(), |iv| iv.as_ptr() as *const _),
|
||||
out.as_ptr() as *mut _,
|
||||
in_.as_ptr() as *const _,
|
||||
in_.len() as c_uint,
|
||||
);
|
||||
|
||||
if written <= 0 {
|
||||
Err(KeyError(()))
|
||||
} else {
|
||||
Ok(written as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use hex::FromHex;
|
||||
|
||||
use super::*;
|
||||
use crate::symm::Mode;
|
||||
|
||||
// From https://www.mgp25.com/AESIGE/
|
||||
#[test]
|
||||
fn ige_vector_1() {
|
||||
let raw_key = "000102030405060708090A0B0C0D0E0F";
|
||||
let raw_iv = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F";
|
||||
let raw_pt = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||
let raw_ct = "1A8519A6557BE652E9DA8E43DA4EF4453CF456B4CA488AA383C79C98B34797CB";
|
||||
|
||||
let key = AesKey::new_encrypt(&Vec::from_hex(raw_key).unwrap()).unwrap();
|
||||
let mut iv = Vec::from_hex(raw_iv).unwrap();
|
||||
let pt = Vec::from_hex(raw_pt).unwrap();
|
||||
let ct = Vec::from_hex(raw_ct).unwrap();
|
||||
|
||||
let mut ct_actual = vec![0; ct.len()];
|
||||
aes_ige(&pt, &mut ct_actual, &key, &mut iv, Mode::Encrypt);
|
||||
assert_eq!(ct_actual, ct);
|
||||
|
||||
let key = AesKey::new_decrypt(&Vec::from_hex(raw_key).unwrap()).unwrap();
|
||||
let mut iv = Vec::from_hex(raw_iv).unwrap();
|
||||
let mut pt_actual = vec![0; pt.len()];
|
||||
aes_ige(&ct, &mut pt_actual, &key, &mut iv, Mode::Decrypt);
|
||||
assert_eq!(pt_actual, pt);
|
||||
}
|
||||
|
||||
// from the RFC https://tools.ietf.org/html/rfc3394#section-2.2.3
|
||||
#[test]
|
||||
fn test_wrap_unwrap() {
|
||||
let raw_key = Vec::from_hex("000102030405060708090A0B0C0D0E0F").unwrap();
|
||||
let key_data = Vec::from_hex("00112233445566778899AABBCCDDEEFF").unwrap();
|
||||
let expected_ciphertext =
|
||||
Vec::from_hex("1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5").unwrap();
|
||||
|
||||
let enc_key = AesKey::new_encrypt(&raw_key).unwrap();
|
||||
let mut wrapped = [0; 24];
|
||||
assert_eq!(
|
||||
wrap_key(&enc_key, None, &mut wrapped, &key_data).unwrap(),
|
||||
24
|
||||
);
|
||||
assert_eq!(&wrapped[..], &expected_ciphertext[..]);
|
||||
|
||||
let dec_key = AesKey::new_decrypt(&raw_key).unwrap();
|
||||
let mut unwrapped = [0; 16];
|
||||
assert_eq!(
|
||||
unwrap_key(&dec_key, None, &mut unwrapped, &wrapped).unwrap(),
|
||||
16
|
||||
);
|
||||
assert_eq!(&unwrapped[..], &key_data[..]);
|
||||
}
|
||||
}
|
||||
769
zeroidc/vendor/openssl/src/asn1.rs
vendored
Normal file
769
zeroidc/vendor/openssl/src/asn1.rs
vendored
Normal file
@@ -0,0 +1,769 @@
|
||||
#![deny(missing_docs)]
|
||||
|
||||
//! Defines the format of certificates
|
||||
//!
|
||||
//! This module is used by [`x509`] and other certificate building functions
|
||||
//! to describe time, strings, and objects.
|
||||
//!
|
||||
//! Abstract Syntax Notation One is an interface description language.
|
||||
//! The specification comes from [X.208] by OSI, and rewritten in X.680.
|
||||
//! ASN.1 describes properties of an object with a type set. Those types
|
||||
//! can be atomic, structured, choice, and other (CHOICE and ANY). These
|
||||
//! types are expressed as a number and the assignment operator ::= gives
|
||||
//! the type a name.
|
||||
//!
|
||||
//! The implementation here provides a subset of the ASN.1 types that OpenSSL
|
||||
//! uses, especially in the properties of a certificate used in HTTPS.
|
||||
//!
|
||||
//! [X.208]: https://www.itu.int/rec/T-REC-X.208-198811-W/en
|
||||
//! [`x509`]: ../x509/struct.X509Builder.html
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::asn1::Asn1Time;
|
||||
//! let tomorrow = Asn1Time::days_from_now(1);
|
||||
//! ```
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::{c_char, c_int, c_long, time_t};
|
||||
#[cfg(ossl102)]
|
||||
use std::cmp::Ordering;
|
||||
use std::ffi::CString;
|
||||
use std::fmt;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
use std::str;
|
||||
|
||||
use crate::bio::MemBio;
|
||||
use crate::bn::{BigNum, BigNumRef};
|
||||
use crate::error::ErrorStack;
|
||||
use crate::nid::Nid;
|
||||
use crate::string::OpensslString;
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_GENERALIZEDTIME;
|
||||
fn drop = ffi::ASN1_GENERALIZEDTIME_free;
|
||||
|
||||
/// Non-UTC representation of time
|
||||
///
|
||||
/// If a time can be represented by UTCTime, UTCTime is used
|
||||
/// otherwise, ASN1_GENERALIZEDTIME is used. This would be, for
|
||||
/// example outside the year range of 1950-2049.
|
||||
///
|
||||
/// [ASN1_GENERALIZEDTIME_set] documentation from OpenSSL provides
|
||||
/// further details of implementation. Note: these docs are from the master
|
||||
/// branch as documentation on the 1.1.0 branch did not include this page.
|
||||
///
|
||||
/// [ASN1_GENERALIZEDTIME_set]: https://www.openssl.org/docs/manmaster/man3/ASN1_GENERALIZEDTIME_set.html
|
||||
pub struct Asn1GeneralizedTime;
|
||||
/// Reference to a [`Asn1GeneralizedTime`]
|
||||
///
|
||||
/// [`Asn1GeneralizedTime`]: struct.Asn1GeneralizedTime.html
|
||||
pub struct Asn1GeneralizedTimeRef;
|
||||
}
|
||||
|
||||
impl fmt::Display for Asn1GeneralizedTimeRef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
unsafe {
|
||||
let mem_bio = match MemBio::new() {
|
||||
Err(_) => return f.write_str("error"),
|
||||
Ok(m) => m,
|
||||
};
|
||||
let print_result = cvt(ffi::ASN1_GENERALIZEDTIME_print(
|
||||
mem_bio.as_ptr(),
|
||||
self.as_ptr(),
|
||||
));
|
||||
match print_result {
|
||||
Err(_) => f.write_str("error"),
|
||||
Ok(_) => f.write_str(str::from_utf8_unchecked(mem_bio.get_buf())),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of an ASN.1 value.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct Asn1Type(c_int);
|
||||
|
||||
#[allow(missing_docs)] // no need to document the constants
|
||||
impl Asn1Type {
|
||||
pub const EOC: Asn1Type = Asn1Type(ffi::V_ASN1_EOC);
|
||||
|
||||
pub const BOOLEAN: Asn1Type = Asn1Type(ffi::V_ASN1_BOOLEAN);
|
||||
|
||||
pub const INTEGER: Asn1Type = Asn1Type(ffi::V_ASN1_INTEGER);
|
||||
|
||||
pub const BIT_STRING: Asn1Type = Asn1Type(ffi::V_ASN1_BIT_STRING);
|
||||
|
||||
pub const OCTET_STRING: Asn1Type = Asn1Type(ffi::V_ASN1_OCTET_STRING);
|
||||
|
||||
pub const NULL: Asn1Type = Asn1Type(ffi::V_ASN1_NULL);
|
||||
|
||||
pub const OBJECT: Asn1Type = Asn1Type(ffi::V_ASN1_OBJECT);
|
||||
|
||||
pub const OBJECT_DESCRIPTOR: Asn1Type = Asn1Type(ffi::V_ASN1_OBJECT_DESCRIPTOR);
|
||||
|
||||
pub const EXTERNAL: Asn1Type = Asn1Type(ffi::V_ASN1_EXTERNAL);
|
||||
|
||||
pub const REAL: Asn1Type = Asn1Type(ffi::V_ASN1_REAL);
|
||||
|
||||
pub const ENUMERATED: Asn1Type = Asn1Type(ffi::V_ASN1_ENUMERATED);
|
||||
|
||||
pub const UTF8STRING: Asn1Type = Asn1Type(ffi::V_ASN1_UTF8STRING);
|
||||
|
||||
pub const SEQUENCE: Asn1Type = Asn1Type(ffi::V_ASN1_SEQUENCE);
|
||||
|
||||
pub const SET: Asn1Type = Asn1Type(ffi::V_ASN1_SET);
|
||||
|
||||
pub const NUMERICSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_NUMERICSTRING);
|
||||
|
||||
pub const PRINTABLESTRING: Asn1Type = Asn1Type(ffi::V_ASN1_PRINTABLESTRING);
|
||||
|
||||
pub const T61STRING: Asn1Type = Asn1Type(ffi::V_ASN1_T61STRING);
|
||||
|
||||
pub const TELETEXSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_TELETEXSTRING);
|
||||
|
||||
pub const VIDEOTEXSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_VIDEOTEXSTRING);
|
||||
|
||||
pub const IA5STRING: Asn1Type = Asn1Type(ffi::V_ASN1_IA5STRING);
|
||||
|
||||
pub const UTCTIME: Asn1Type = Asn1Type(ffi::V_ASN1_UTCTIME);
|
||||
|
||||
pub const GENERALIZEDTIME: Asn1Type = Asn1Type(ffi::V_ASN1_GENERALIZEDTIME);
|
||||
|
||||
pub const GRAPHICSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_GRAPHICSTRING);
|
||||
|
||||
pub const ISO64STRING: Asn1Type = Asn1Type(ffi::V_ASN1_ISO64STRING);
|
||||
|
||||
pub const VISIBLESTRING: Asn1Type = Asn1Type(ffi::V_ASN1_VISIBLESTRING);
|
||||
|
||||
pub const GENERALSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_GENERALSTRING);
|
||||
|
||||
pub const UNIVERSALSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_UNIVERSALSTRING);
|
||||
|
||||
pub const BMPSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_BMPSTRING);
|
||||
|
||||
/// Constructs an `Asn1Type` from a raw OpenSSL value.
|
||||
pub fn from_raw(value: c_int) -> Self {
|
||||
Asn1Type(value)
|
||||
}
|
||||
|
||||
/// Returns the raw OpenSSL value represented by this type.
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Difference between two ASN1 times.
|
||||
///
|
||||
/// This `struct` is created by the [`diff`] method on [`Asn1TimeRef`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`diff`]: struct.Asn1TimeRef.html#method.diff
|
||||
/// [`Asn1TimeRef`]: struct.Asn1TimeRef.html
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg(ossl102)]
|
||||
pub struct TimeDiff {
|
||||
/// Difference in days
|
||||
pub days: c_int,
|
||||
/// Difference in seconds.
|
||||
///
|
||||
/// This is always less than the number of seconds in a day.
|
||||
pub secs: c_int,
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_TIME;
|
||||
fn drop = ffi::ASN1_TIME_free;
|
||||
/// Time storage and comparison
|
||||
///
|
||||
/// Asn1Time should be used to store and share time information
|
||||
/// using certificates. If Asn1Time is set using a string, it must
|
||||
/// be in either YYMMDDHHMMSSZ, YYYYMMDDHHMMSSZ, or another ASN.1 format.
|
||||
///
|
||||
/// [ASN_TIME_set] documentation at OpenSSL explains the ASN.1 implementation
|
||||
/// used by OpenSSL.
|
||||
///
|
||||
/// [ASN_TIME_set]: https://www.openssl.org/docs/man1.1.0/crypto/ASN1_TIME_set.html
|
||||
pub struct Asn1Time;
|
||||
/// Reference to an [`Asn1Time`]
|
||||
///
|
||||
/// [`Asn1Time`]: struct.Asn1Time.html
|
||||
pub struct Asn1TimeRef;
|
||||
}
|
||||
|
||||
impl Asn1TimeRef {
|
||||
/// Find difference between two times
|
||||
#[corresponds(ASN1_TIME_diff)]
|
||||
#[cfg(ossl102)]
|
||||
pub fn diff(&self, compare: &Self) -> Result<TimeDiff, ErrorStack> {
|
||||
let mut days = 0;
|
||||
let mut secs = 0;
|
||||
let other = compare.as_ptr();
|
||||
|
||||
let err = unsafe { ffi::ASN1_TIME_diff(&mut days, &mut secs, self.as_ptr(), other) };
|
||||
|
||||
match err {
|
||||
0 => Err(ErrorStack::get()),
|
||||
_ => Ok(TimeDiff { days, secs }),
|
||||
}
|
||||
}
|
||||
|
||||
/// Compare two times
|
||||
#[corresponds(ASN1_TIME_compare)]
|
||||
#[cfg(ossl102)]
|
||||
pub fn compare(&self, other: &Self) -> Result<Ordering, ErrorStack> {
|
||||
let d = self.diff(other)?;
|
||||
if d.days > 0 || d.secs > 0 {
|
||||
return Ok(Ordering::Less);
|
||||
}
|
||||
if d.days < 0 || d.secs < 0 {
|
||||
return Ok(Ordering::Greater);
|
||||
}
|
||||
|
||||
Ok(Ordering::Equal)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl102)]
|
||||
impl PartialEq for Asn1TimeRef {
|
||||
fn eq(&self, other: &Asn1TimeRef) -> bool {
|
||||
self.diff(other)
|
||||
.map(|t| t.days == 0 && t.secs == 0)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl102)]
|
||||
impl PartialEq<Asn1Time> for Asn1TimeRef {
|
||||
fn eq(&self, other: &Asn1Time) -> bool {
|
||||
self.diff(other)
|
||||
.map(|t| t.days == 0 && t.secs == 0)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl102)]
|
||||
impl<'a> PartialEq<Asn1Time> for &'a Asn1TimeRef {
|
||||
fn eq(&self, other: &Asn1Time) -> bool {
|
||||
self.diff(other)
|
||||
.map(|t| t.days == 0 && t.secs == 0)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl102)]
|
||||
impl PartialOrd for Asn1TimeRef {
|
||||
fn partial_cmp(&self, other: &Asn1TimeRef) -> Option<Ordering> {
|
||||
self.compare(other).ok()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl102)]
|
||||
impl PartialOrd<Asn1Time> for Asn1TimeRef {
|
||||
fn partial_cmp(&self, other: &Asn1Time) -> Option<Ordering> {
|
||||
self.compare(other).ok()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl102)]
|
||||
impl<'a> PartialOrd<Asn1Time> for &'a Asn1TimeRef {
|
||||
fn partial_cmp(&self, other: &Asn1Time) -> Option<Ordering> {
|
||||
self.compare(other).ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Asn1TimeRef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
unsafe {
|
||||
let mem_bio = match MemBio::new() {
|
||||
Err(_) => return f.write_str("error"),
|
||||
Ok(m) => m,
|
||||
};
|
||||
let print_result = cvt(ffi::ASN1_TIME_print(mem_bio.as_ptr(), self.as_ptr()));
|
||||
match print_result {
|
||||
Err(_) => f.write_str("error"),
|
||||
Ok(_) => f.write_str(str::from_utf8_unchecked(mem_bio.get_buf())),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Asn1TimeRef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl Asn1Time {
|
||||
#[corresponds(ASN1_TIME_new)]
|
||||
fn new() -> Result<Asn1Time, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
unsafe {
|
||||
let handle = cvt_p(ffi::ASN1_TIME_new())?;
|
||||
Ok(Asn1Time::from_ptr(handle))
|
||||
}
|
||||
}
|
||||
|
||||
#[corresponds(X509_gmtime_adj)]
|
||||
fn from_period(period: c_long) -> Result<Asn1Time, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
unsafe {
|
||||
let handle = cvt_p(ffi::X509_gmtime_adj(ptr::null_mut(), period))?;
|
||||
Ok(Asn1Time::from_ptr(handle))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new time on specified interval in days from now
|
||||
pub fn days_from_now(days: u32) -> Result<Asn1Time, ErrorStack> {
|
||||
Asn1Time::from_period(days as c_long * 60 * 60 * 24)
|
||||
}
|
||||
|
||||
/// Creates a new time from the specified `time_t` value
|
||||
#[corresponds(ASN1_TIME_set)]
|
||||
pub fn from_unix(time: time_t) -> Result<Asn1Time, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
unsafe {
|
||||
let handle = cvt_p(ffi::ASN1_TIME_set(ptr::null_mut(), time))?;
|
||||
Ok(Asn1Time::from_ptr(handle))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new time corresponding to the specified ASN1 time string.
|
||||
#[corresponds(ASN1_TIME_set_string)]
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn from_str(s: &str) -> Result<Asn1Time, ErrorStack> {
|
||||
unsafe {
|
||||
let s = CString::new(s).unwrap();
|
||||
|
||||
let time = Asn1Time::new()?;
|
||||
cvt(ffi::ASN1_TIME_set_string(time.as_ptr(), s.as_ptr()))?;
|
||||
|
||||
Ok(time)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new time corresponding to the specified X509 time string.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[corresponds(ASN1_TIME_set_string_X509)]
|
||||
#[cfg(ossl111)]
|
||||
pub fn from_str_x509(s: &str) -> Result<Asn1Time, ErrorStack> {
|
||||
unsafe {
|
||||
let s = CString::new(s).unwrap();
|
||||
|
||||
let time = Asn1Time::new()?;
|
||||
cvt(ffi::ASN1_TIME_set_string_X509(time.as_ptr(), s.as_ptr()))?;
|
||||
|
||||
Ok(time)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl102)]
|
||||
impl PartialEq for Asn1Time {
|
||||
fn eq(&self, other: &Asn1Time) -> bool {
|
||||
self.diff(other)
|
||||
.map(|t| t.days == 0 && t.secs == 0)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl102)]
|
||||
impl PartialEq<Asn1TimeRef> for Asn1Time {
|
||||
fn eq(&self, other: &Asn1TimeRef) -> bool {
|
||||
self.diff(other)
|
||||
.map(|t| t.days == 0 && t.secs == 0)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl102)]
|
||||
impl<'a> PartialEq<&'a Asn1TimeRef> for Asn1Time {
|
||||
fn eq(&self, other: &&'a Asn1TimeRef) -> bool {
|
||||
self.diff(other)
|
||||
.map(|t| t.days == 0 && t.secs == 0)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl102)]
|
||||
impl PartialOrd for Asn1Time {
|
||||
fn partial_cmp(&self, other: &Asn1Time) -> Option<Ordering> {
|
||||
self.compare(other).ok()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl102)]
|
||||
impl PartialOrd<Asn1TimeRef> for Asn1Time {
|
||||
fn partial_cmp(&self, other: &Asn1TimeRef) -> Option<Ordering> {
|
||||
self.compare(other).ok()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl102)]
|
||||
impl<'a> PartialOrd<&'a Asn1TimeRef> for Asn1Time {
|
||||
fn partial_cmp(&self, other: &&'a Asn1TimeRef) -> Option<Ordering> {
|
||||
self.compare(other).ok()
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_STRING;
|
||||
fn drop = ffi::ASN1_STRING_free;
|
||||
/// Primary ASN.1 type used by OpenSSL
|
||||
///
|
||||
/// Almost all ASN.1 types in OpenSSL are represented by ASN1_STRING
|
||||
/// structures. This implementation uses [ASN1_STRING-to_UTF8] to preserve
|
||||
/// compatibility with Rust's String.
|
||||
///
|
||||
/// [ASN1_STRING-to_UTF8]: https://www.openssl.org/docs/man1.1.0/crypto/ASN1_STRING_to_UTF8.html
|
||||
pub struct Asn1String;
|
||||
/// A reference to an [`Asn1String`].
|
||||
pub struct Asn1StringRef;
|
||||
}
|
||||
|
||||
impl Asn1StringRef {
|
||||
/// Converts the ASN.1 underlying format to UTF8
|
||||
///
|
||||
/// ASN.1 strings may utilize UTF-16, ASCII, BMP, or UTF8. This is important to
|
||||
/// consume the string in a meaningful way without knowing the underlying
|
||||
/// format.
|
||||
#[corresponds(ASN1_STRING_to_UTF8)]
|
||||
pub fn as_utf8(&self) -> Result<OpensslString, ErrorStack> {
|
||||
unsafe {
|
||||
let mut ptr = ptr::null_mut();
|
||||
let len = ffi::ASN1_STRING_to_UTF8(&mut ptr, self.as_ptr());
|
||||
if len < 0 {
|
||||
return Err(ErrorStack::get());
|
||||
}
|
||||
|
||||
Ok(OpensslString::from_ptr(ptr as *mut c_char))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the string as an array of bytes.
|
||||
///
|
||||
/// The bytes do not directly correspond to UTF-8 encoding. To interact with
|
||||
/// strings in rust, it is preferable to use [`as_utf8`]
|
||||
///
|
||||
/// [`as_utf8`]: struct.Asn1String.html#method.as_utf8
|
||||
#[corresponds(ASN1_STRING_get0_data)]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr()), self.len()) }
|
||||
}
|
||||
|
||||
/// Returns the number of bytes in the string.
|
||||
#[corresponds(ASN1_STRING_length)]
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { ffi::ASN1_STRING_length(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Determines if the string is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Asn1StringRef {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.as_utf8() {
|
||||
Ok(openssl_string) => openssl_string.fmt(fmt),
|
||||
Err(_) => fmt.write_str("error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_INTEGER;
|
||||
fn drop = ffi::ASN1_INTEGER_free;
|
||||
|
||||
/// Numeric representation
|
||||
///
|
||||
/// Integers in ASN.1 may include BigNum, int64 or uint64. BigNum implementation
|
||||
/// can be found within [`bn`] module.
|
||||
///
|
||||
/// OpenSSL documentation includes [`ASN1_INTEGER_set`].
|
||||
///
|
||||
/// [`bn`]: ../bn/index.html
|
||||
/// [`ASN1_INTEGER_set`]: https://www.openssl.org/docs/man1.1.0/crypto/ASN1_INTEGER_set.html
|
||||
pub struct Asn1Integer;
|
||||
/// A reference to an [`Asn1Integer`].
|
||||
pub struct Asn1IntegerRef;
|
||||
}
|
||||
|
||||
impl Asn1Integer {
|
||||
/// Converts a bignum to an `Asn1Integer`.
|
||||
///
|
||||
/// Corresponds to [`BN_to_ASN1_INTEGER`]. Also see
|
||||
/// [`BigNumRef::to_asn1_integer`].
|
||||
///
|
||||
/// [`BN_to_ASN1_INTEGER`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_to_ASN1_INTEGER.html
|
||||
/// [`BigNumRef::to_asn1_integer`]: ../bn/struct.BigNumRef.html#method.to_asn1_integer
|
||||
pub fn from_bn(bn: &BigNumRef) -> Result<Self, ErrorStack> {
|
||||
bn.to_asn1_integer()
|
||||
}
|
||||
}
|
||||
|
||||
impl Asn1IntegerRef {
|
||||
#[allow(missing_docs)]
|
||||
#[deprecated(since = "0.10.6", note = "use to_bn instead")]
|
||||
pub fn get(&self) -> i64 {
|
||||
unsafe { ffi::ASN1_INTEGER_get(self.as_ptr()) as i64 }
|
||||
}
|
||||
|
||||
/// Converts the integer to a `BigNum`.
|
||||
#[corresponds(ASN1_INTEGER_to_BN)]
|
||||
pub fn to_bn(&self) -> Result<BigNum, ErrorStack> {
|
||||
unsafe {
|
||||
cvt_p(ffi::ASN1_INTEGER_to_BN(self.as_ptr(), ptr::null_mut()))
|
||||
.map(|p| BigNum::from_ptr(p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the ASN.1 value to the value of a signed 32-bit integer, for larger numbers
|
||||
/// see [`bn`].
|
||||
///
|
||||
/// [`bn`]: ../bn/struct.BigNumRef.html#method.to_asn1_integer
|
||||
#[corresponds(ASN1_INTEGER_set)]
|
||||
pub fn set(&mut self, value: i32) -> Result<(), ErrorStack> {
|
||||
unsafe { cvt(ffi::ASN1_INTEGER_set(self.as_ptr(), value as c_long)).map(|_| ()) }
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_BIT_STRING;
|
||||
fn drop = ffi::ASN1_BIT_STRING_free;
|
||||
/// Sequence of bytes
|
||||
///
|
||||
/// Asn1BitString is used in [`x509`] certificates for the signature.
|
||||
/// The bit string acts as a collection of bytes.
|
||||
///
|
||||
/// [`x509`]: ../x509/struct.X509.html#method.signature
|
||||
pub struct Asn1BitString;
|
||||
/// A reference to an [`Asn1BitString`].
|
||||
pub struct Asn1BitStringRef;
|
||||
}
|
||||
|
||||
impl Asn1BitStringRef {
|
||||
/// Returns the Asn1BitString as a slice.
|
||||
#[corresponds(ASN1_STRING_get0_data)]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr() as *mut _), self.len()) }
|
||||
}
|
||||
|
||||
/// Returns the number of bytes in the string.
|
||||
#[corresponds(ASN1_STRING_length)]
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { ffi::ASN1_STRING_length(self.as_ptr() as *const _) as usize }
|
||||
}
|
||||
|
||||
/// Determines if the string is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_OBJECT;
|
||||
fn drop = ffi::ASN1_OBJECT_free;
|
||||
|
||||
/// Object Identifier
|
||||
///
|
||||
/// Represents an ASN.1 Object. Typically, NIDs, or numeric identifiers
|
||||
/// are stored as a table within the [`Nid`] module. These constants are
|
||||
/// used to determine attributes of a certificate, such as mapping the
|
||||
/// attribute "CommonName" to "CN" which is represented as the OID of 13.
|
||||
/// This attribute is a constant in the [`nid::COMMONNAME`].
|
||||
///
|
||||
/// OpenSSL documentation at [`OBJ_nid2obj`]
|
||||
///
|
||||
/// [`Nid`]: ../nid/index.html
|
||||
/// [`nid::COMMONNAME`]: ../nid/constant.COMMONNAME.html
|
||||
/// [`OBJ_nid2obj`]: https://www.openssl.org/docs/man1.1.0/crypto/OBJ_obj2nid.html
|
||||
pub struct Asn1Object;
|
||||
/// A reference to an [`Asn1Object`].
|
||||
pub struct Asn1ObjectRef;
|
||||
}
|
||||
|
||||
impl Asn1Object {
|
||||
/// Constructs an ASN.1 Object Identifier from a string representation of the OID.
|
||||
#[corresponds(OBJ_txt2obj)]
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn from_str(txt: &str) -> Result<Asn1Object, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
let txt = CString::new(txt).unwrap();
|
||||
let obj: *mut ffi::ASN1_OBJECT = cvt_p(ffi::OBJ_txt2obj(txt.as_ptr() as *const _, 0))?;
|
||||
Ok(Asn1Object::from_ptr(obj))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the OID as an DER encoded array of bytes. This is the ASN.1
|
||||
/// value, not including tag or length.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[corresponds(OBJ_get0_data)]
|
||||
#[cfg(ossl111)]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe {
|
||||
let len = ffi::OBJ_length(self.as_ptr());
|
||||
slice::from_raw_parts(ffi::OBJ_get0_data(self.as_ptr()), len)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Asn1ObjectRef {
|
||||
/// Returns the NID associated with this OID.
|
||||
pub fn nid(&self) -> Nid {
|
||||
unsafe { Nid::from_raw(ffi::OBJ_obj2nid(self.as_ptr())) }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Asn1ObjectRef {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
unsafe {
|
||||
let mut buf = [0; 80];
|
||||
let len = ffi::OBJ_obj2txt(
|
||||
buf.as_mut_ptr() as *mut _,
|
||||
buf.len() as c_int,
|
||||
self.as_ptr(),
|
||||
0,
|
||||
);
|
||||
match str::from_utf8(&buf[..len as usize]) {
|
||||
Err(_) => fmt.write_str("error"),
|
||||
Ok(s) => fmt.write_str(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Asn1ObjectRef {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.write_str(self.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273))] {
|
||||
use ffi::ASN1_STRING_get0_data;
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn ASN1_STRING_get0_data(s: *mut ffi::ASN1_STRING) -> *const ::libc::c_uchar {
|
||||
ffi::ASN1_STRING_data(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::bn::BigNum;
|
||||
use crate::nid::Nid;
|
||||
|
||||
/// Tests conversion between BigNum and Asn1Integer.
|
||||
#[test]
|
||||
fn bn_cvt() {
|
||||
fn roundtrip(bn: BigNum) {
|
||||
let large = Asn1Integer::from_bn(&bn).unwrap();
|
||||
assert_eq!(large.to_bn().unwrap(), bn);
|
||||
}
|
||||
|
||||
roundtrip(BigNum::from_dec_str("1000000000000000000000000000000000").unwrap());
|
||||
roundtrip(-BigNum::from_dec_str("1000000000000000000000000000000000").unwrap());
|
||||
roundtrip(BigNum::from_u32(1234).unwrap());
|
||||
roundtrip(-BigNum::from_u32(1234).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn time_from_str() {
|
||||
Asn1Time::from_str("99991231235959Z").unwrap();
|
||||
#[cfg(ossl111)]
|
||||
Asn1Time::from_str_x509("99991231235959Z").unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn time_from_unix() {
|
||||
let t = Asn1Time::from_unix(0).unwrap();
|
||||
assert_eq!("Jan 1 00:00:00 1970 GMT", t.to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn time_eq() {
|
||||
let a = Asn1Time::from_str("99991231235959Z").unwrap();
|
||||
let b = Asn1Time::from_str("99991231235959Z").unwrap();
|
||||
let c = Asn1Time::from_str("99991231235958Z").unwrap();
|
||||
let a_ref = a.as_ref();
|
||||
let b_ref = b.as_ref();
|
||||
let c_ref = c.as_ref();
|
||||
assert!(a == b);
|
||||
assert!(a != c);
|
||||
assert!(a == b_ref);
|
||||
assert!(a != c_ref);
|
||||
assert!(b_ref == a);
|
||||
assert!(c_ref != a);
|
||||
assert!(a_ref == b_ref);
|
||||
assert!(a_ref != c_ref);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn time_ord() {
|
||||
let a = Asn1Time::from_str("99991231235959Z").unwrap();
|
||||
let b = Asn1Time::from_str("99991231235959Z").unwrap();
|
||||
let c = Asn1Time::from_str("99991231235958Z").unwrap();
|
||||
let a_ref = a.as_ref();
|
||||
let b_ref = b.as_ref();
|
||||
let c_ref = c.as_ref();
|
||||
assert!(a >= b);
|
||||
assert!(a > c);
|
||||
assert!(b <= a);
|
||||
assert!(c < a);
|
||||
|
||||
assert!(a_ref >= b);
|
||||
assert!(a_ref > c);
|
||||
assert!(b_ref <= a);
|
||||
assert!(c_ref < a);
|
||||
|
||||
assert!(a >= b_ref);
|
||||
assert!(a > c_ref);
|
||||
assert!(b <= a_ref);
|
||||
assert!(c < a_ref);
|
||||
|
||||
assert!(a_ref >= b_ref);
|
||||
assert!(a_ref > c_ref);
|
||||
assert!(b_ref <= a_ref);
|
||||
assert!(c_ref < a_ref);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn object_from_str() {
|
||||
let object = Asn1Object::from_str("2.16.840.1.101.3.4.2.1").unwrap();
|
||||
assert_eq!(object.nid(), Nid::SHA256);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn object_from_str_with_invalid_input() {
|
||||
Asn1Object::from_str("NOT AN OID")
|
||||
.map(|object| object.to_string())
|
||||
.expect_err("parsing invalid OID should fail");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl111)]
|
||||
fn object_to_slice() {
|
||||
let object = Asn1Object::from_str("2.16.840.1.101.3.4.2.1").unwrap();
|
||||
assert_eq!(
|
||||
object.as_slice(),
|
||||
&[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01],
|
||||
);
|
||||
}
|
||||
}
|
||||
128
zeroidc/vendor/openssl/src/base64.rs
vendored
Normal file
128
zeroidc/vendor/openssl/src/base64.rs
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
//! Base64 encoding support.
|
||||
use crate::cvt_n;
|
||||
use crate::error::ErrorStack;
|
||||
use libc::c_int;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
/// Encodes a slice of bytes to a base64 string.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the input length or computed output length overflow a signed C integer.
|
||||
#[corresponds(EVP_EncodeBlock)]
|
||||
pub fn encode_block(src: &[u8]) -> String {
|
||||
assert!(src.len() <= c_int::max_value() as usize);
|
||||
let src_len = src.len() as c_int;
|
||||
|
||||
let len = encoded_len(src_len).unwrap();
|
||||
let mut out = Vec::with_capacity(len as usize);
|
||||
|
||||
// SAFETY: `encoded_len` ensures space for 4 output characters
|
||||
// for every 3 input bytes including padding and nul terminator.
|
||||
// `EVP_EncodeBlock` will write only single byte ASCII characters.
|
||||
// `EVP_EncodeBlock` will only write to not read from `out`.
|
||||
unsafe {
|
||||
let out_len = ffi::EVP_EncodeBlock(out.as_mut_ptr(), src.as_ptr(), src_len);
|
||||
out.set_len(out_len as usize);
|
||||
String::from_utf8_unchecked(out)
|
||||
}
|
||||
}
|
||||
|
||||
/// Decodes a base64-encoded string to bytes.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the input length or computed output length overflow a signed C integer.
|
||||
#[corresponds(EVP_DecodeBlock)]
|
||||
pub fn decode_block(src: &str) -> Result<Vec<u8>, ErrorStack> {
|
||||
let src = src.trim();
|
||||
|
||||
// https://github.com/openssl/openssl/issues/12143
|
||||
if src.is_empty() {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
|
||||
assert!(src.len() <= c_int::max_value() as usize);
|
||||
let src_len = src.len() as c_int;
|
||||
|
||||
let len = decoded_len(src_len).unwrap();
|
||||
let mut out = Vec::with_capacity(len as usize);
|
||||
|
||||
// SAFETY: `decoded_len` ensures space for 3 output bytes
|
||||
// for every 4 input characters including padding.
|
||||
// `EVP_DecodeBlock` can write fewer bytes after stripping
|
||||
// leading and trailing whitespace, but never more.
|
||||
// `EVP_DecodeBlock` will only write to not read from `out`.
|
||||
unsafe {
|
||||
let out_len = cvt_n(ffi::EVP_DecodeBlock(
|
||||
out.as_mut_ptr(),
|
||||
src.as_ptr(),
|
||||
src_len,
|
||||
))?;
|
||||
out.set_len(out_len as usize);
|
||||
}
|
||||
|
||||
if src.ends_with('=') {
|
||||
out.pop();
|
||||
if src.ends_with("==") {
|
||||
out.pop();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn encoded_len(src_len: c_int) -> Option<c_int> {
|
||||
let mut len = (src_len / 3).checked_mul(4)?;
|
||||
|
||||
if src_len % 3 != 0 {
|
||||
len = len.checked_add(4)?;
|
||||
}
|
||||
|
||||
len = len.checked_add(1)?;
|
||||
|
||||
Some(len)
|
||||
}
|
||||
|
||||
fn decoded_len(src_len: c_int) -> Option<c_int> {
|
||||
let mut len = (src_len / 4).checked_mul(3)?;
|
||||
|
||||
if src_len % 4 != 0 {
|
||||
len = len.checked_add(3)?;
|
||||
}
|
||||
|
||||
Some(len)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_encode_block() {
|
||||
assert_eq!("".to_string(), encode_block(b""));
|
||||
assert_eq!("Zg==".to_string(), encode_block(b"f"));
|
||||
assert_eq!("Zm8=".to_string(), encode_block(b"fo"));
|
||||
assert_eq!("Zm9v".to_string(), encode_block(b"foo"));
|
||||
assert_eq!("Zm9vYg==".to_string(), encode_block(b"foob"));
|
||||
assert_eq!("Zm9vYmE=".to_string(), encode_block(b"fooba"));
|
||||
assert_eq!("Zm9vYmFy".to_string(), encode_block(b"foobar"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_block() {
|
||||
assert_eq!(b"".to_vec(), decode_block("").unwrap());
|
||||
assert_eq!(b"f".to_vec(), decode_block("Zg==").unwrap());
|
||||
assert_eq!(b"fo".to_vec(), decode_block("Zm8=").unwrap());
|
||||
assert_eq!(b"foo".to_vec(), decode_block("Zm9v").unwrap());
|
||||
assert_eq!(b"foob".to_vec(), decode_block("Zm9vYg==").unwrap());
|
||||
assert_eq!(b"fooba".to_vec(), decode_block("Zm9vYmE=").unwrap());
|
||||
assert_eq!(b"foobar".to_vec(), decode_block("Zm9vYmFy").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strip_whitespace() {
|
||||
assert_eq!(b"foobar".to_vec(), decode_block(" Zm9vYmFy\n").unwrap());
|
||||
assert_eq!(b"foob".to_vec(), decode_block(" Zm9vYg==\n").unwrap());
|
||||
}
|
||||
}
|
||||
84
zeroidc/vendor/openssl/src/bio.rs
vendored
Normal file
84
zeroidc/vendor/openssl/src/bio.rs
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
use cfg_if::cfg_if;
|
||||
use libc::c_int;
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
use crate::cvt_p;
|
||||
use crate::error::ErrorStack;
|
||||
|
||||
pub struct MemBioSlice<'a>(*mut ffi::BIO, PhantomData<&'a [u8]>);
|
||||
|
||||
impl<'a> Drop for MemBioSlice<'a> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::BIO_free_all(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MemBioSlice<'a> {
|
||||
pub fn new(buf: &'a [u8]) -> Result<MemBioSlice<'a>, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
assert!(buf.len() <= c_int::max_value() as usize);
|
||||
let bio = unsafe {
|
||||
cvt_p(BIO_new_mem_buf(
|
||||
buf.as_ptr() as *const _,
|
||||
buf.len() as c_int,
|
||||
))?
|
||||
};
|
||||
|
||||
Ok(MemBioSlice(bio, PhantomData))
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *mut ffi::BIO {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MemBio(*mut ffi::BIO);
|
||||
|
||||
impl Drop for MemBio {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::BIO_free_all(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MemBio {
|
||||
pub fn new() -> Result<MemBio, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
let bio = unsafe { cvt_p(ffi::BIO_new(ffi::BIO_s_mem()))? };
|
||||
Ok(MemBio(bio))
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *mut ffi::BIO {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn get_buf(&self) -> &[u8] {
|
||||
unsafe {
|
||||
let mut ptr = ptr::null_mut();
|
||||
let len = ffi::BIO_get_mem_data(self.0, &mut ptr);
|
||||
slice::from_raw_parts(ptr as *const _ as *const _, len as usize)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn from_ptr(bio: *mut ffi::BIO) -> MemBio {
|
||||
MemBio(bio)
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl102)] {
|
||||
use ffi::BIO_new_mem_buf;
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn BIO_new_mem_buf(buf: *const ::libc::c_void, len: ::libc::c_int) -> *mut ffi::BIO {
|
||||
ffi::BIO_new_mem_buf(buf as *mut _, len)
|
||||
}
|
||||
}
|
||||
}
|
||||
1415
zeroidc/vendor/openssl/src/bn.rs
vendored
Normal file
1415
zeroidc/vendor/openssl/src/bn.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
388
zeroidc/vendor/openssl/src/cipher.rs
vendored
Normal file
388
zeroidc/vendor/openssl/src/cipher.rs
vendored
Normal file
@@ -0,0 +1,388 @@
|
||||
//! Symmetric ciphers.
|
||||
|
||||
#[cfg(ossl300)]
|
||||
use crate::cvt_p;
|
||||
#[cfg(ossl300)]
|
||||
use crate::error::ErrorStack;
|
||||
#[cfg(ossl300)]
|
||||
use crate::lib_ctx::LibCtxRef;
|
||||
use crate::nid::Nid;
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignTypeRef, Opaque};
|
||||
use openssl_macros::corresponds;
|
||||
#[cfg(ossl300)]
|
||||
use std::ffi::CString;
|
||||
#[cfg(ossl300)]
|
||||
use std::ptr;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273))] {
|
||||
use ffi::{EVP_CIPHER_block_size, EVP_CIPHER_iv_length, EVP_CIPHER_key_length};
|
||||
} else {
|
||||
use libc::c_int;
|
||||
|
||||
#[allow(bad_style)]
|
||||
pub unsafe fn EVP_CIPHER_iv_length(ptr: *const ffi::EVP_CIPHER) -> c_int {
|
||||
(*ptr).iv_len
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
pub unsafe fn EVP_CIPHER_block_size(ptr: *const ffi::EVP_CIPHER) -> c_int {
|
||||
(*ptr).block_size
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
pub unsafe fn EVP_CIPHER_key_length(ptr: *const ffi::EVP_CIPHER) -> c_int {
|
||||
(*ptr).key_len
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl300)] {
|
||||
use foreign_types::ForeignType;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
type Inner = *mut ffi::EVP_CIPHER;
|
||||
|
||||
impl Drop for Cipher {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::EVP_CIPHER_free(self.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ForeignType for Cipher {
|
||||
type CType = ffi::EVP_CIPHER;
|
||||
type Ref = CipherRef;
|
||||
|
||||
#[inline]
|
||||
unsafe fn from_ptr(ptr: *mut Self::CType) -> Self {
|
||||
Cipher(ptr)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut Self::CType {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Cipher {
|
||||
type Target = CipherRef;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe {
|
||||
CipherRef::from_ptr(self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Cipher {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe {
|
||||
CipherRef::from_ptr_mut(self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
enum Inner {}
|
||||
}
|
||||
}
|
||||
|
||||
/// A symmetric cipher.
|
||||
pub struct Cipher(Inner);
|
||||
|
||||
unsafe impl Sync for Cipher {}
|
||||
unsafe impl Send for Cipher {}
|
||||
|
||||
impl Cipher {
|
||||
/// Looks up the cipher for a certain nid.
|
||||
#[corresponds(EVP_get_cipherbynid)]
|
||||
pub fn from_nid(nid: Nid) -> Option<&'static CipherRef> {
|
||||
unsafe {
|
||||
let ptr = ffi::EVP_get_cipherbyname(ffi::OBJ_nid2sn(nid.as_raw()));
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(CipherRef::from_ptr(ptr as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetches a cipher object corresponding to the specified algorithm name and properties.
|
||||
///
|
||||
/// Requires OpenSSL 3.0.0 or newer.
|
||||
#[corresponds(EVP_CIPHER_fetch)]
|
||||
#[cfg(ossl300)]
|
||||
pub fn fetch(
|
||||
ctx: Option<&LibCtxRef>,
|
||||
algorithm: &str,
|
||||
properties: Option<&str>,
|
||||
) -> Result<Self, ErrorStack> {
|
||||
let algorithm = CString::new(algorithm).unwrap();
|
||||
let properties = properties.map(|s| CString::new(s).unwrap());
|
||||
|
||||
unsafe {
|
||||
let ptr = cvt_p(ffi::EVP_CIPHER_fetch(
|
||||
ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
|
||||
algorithm.as_ptr(),
|
||||
properties.map_or(ptr::null_mut(), |s| s.as_ptr()),
|
||||
))?;
|
||||
|
||||
Ok(Cipher::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn aes_128_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_128_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_128_xts() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_xts() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_128_ctr() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ctr() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_128_cfb1() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb1() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_128_cfb128() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb128() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_128_cfb8() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb8() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_128_gcm() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_gcm() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_128_ccm() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ccm() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_128_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ofb() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(ossl110)]
|
||||
pub fn aes_128_ocb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ocb() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_ctr() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ctr() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_cfb1() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb1() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_cfb128() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb128() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_cfb8() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb8() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_gcm() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_gcm() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_ccm() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ccm() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ofb() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(ossl110)]
|
||||
pub fn aes_192_ocb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ocb() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_ctr() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ctr() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_cfb1() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb1() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_cfb128() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb128() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_cfb8() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb8() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_gcm() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_gcm() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_ccm() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ccm() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ofb() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(ossl110)]
|
||||
pub fn aes_256_ocb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ocb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_BF"))]
|
||||
pub fn bf_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_bf_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_BF"))]
|
||||
pub fn bf_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_bf_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_BF"))]
|
||||
pub fn bf_cfb64() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_bf_cfb64() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_BF"))]
|
||||
pub fn bf_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_bf_ofb() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn des_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_des_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn des_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_des_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn des_ede3() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn des_ede3_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn des_ede3_cfb64() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cfb64() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn rc4() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_rc4() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_CHACHA")))]
|
||||
pub fn chacha20() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_chacha20() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_CHACHA")))]
|
||||
pub fn chacha20_poly1305() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_chacha20_poly1305() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
|
||||
pub fn seed_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_seed_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
|
||||
pub fn seed_cfb128() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_seed_cfb128() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
|
||||
pub fn seed_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_seed_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
|
||||
pub fn seed_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_seed_ofb() as *mut _) }
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to a [`Cipher`].
|
||||
pub struct CipherRef(Opaque);
|
||||
|
||||
impl ForeignTypeRef for CipherRef {
|
||||
type CType = ffi::EVP_CIPHER;
|
||||
}
|
||||
|
||||
unsafe impl Sync for CipherRef {}
|
||||
unsafe impl Send for CipherRef {}
|
||||
|
||||
impl CipherRef {
|
||||
/// Returns the cipher's Nid.
|
||||
#[corresponds(EVP_CIPHER_nid)]
|
||||
pub fn nid(&self) -> Nid {
|
||||
let nid = unsafe { ffi::EVP_CIPHER_nid(self.as_ptr()) };
|
||||
Nid::from_raw(nid)
|
||||
}
|
||||
|
||||
/// Returns the length of keys used with this cipher.
|
||||
#[corresponds(EVP_CIPHER_key_length)]
|
||||
pub fn key_length(&self) -> usize {
|
||||
unsafe { EVP_CIPHER_key_length(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Returns the length of the IV used with this cipher.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Ciphers that do not use an IV have an IV length of 0.
|
||||
#[corresponds(EVP_CIPHER_iv_length)]
|
||||
pub fn iv_length(&self) -> usize {
|
||||
unsafe { EVP_CIPHER_iv_length(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Returns the block size of the cipher.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Stream ciphers have a block size of 1.
|
||||
#[corresponds(EVP_CIPHER_block_size)]
|
||||
pub fn block_size(&self) -> usize {
|
||||
unsafe { EVP_CIPHER_block_size(self.as_ptr()) as usize }
|
||||
}
|
||||
}
|
||||
665
zeroidc/vendor/openssl/src/cipher_ctx.rs
vendored
Normal file
665
zeroidc/vendor/openssl/src/cipher_ctx.rs
vendored
Normal file
@@ -0,0 +1,665 @@
|
||||
//! The symmetric encryption context.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Encrypt data with AES128 CBC
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::cipher::Cipher;
|
||||
//! use openssl::cipher_ctx::CipherCtx;
|
||||
//!
|
||||
//! let cipher = Cipher::aes_128_cbc();
|
||||
//! let data = b"Some Crypto Text";
|
||||
//! let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
|
||||
//! let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07";
|
||||
//!
|
||||
//! let mut ctx = CipherCtx::new().unwrap();
|
||||
//! ctx.encrypt_init(Some(cipher), Some(key), Some(iv)).unwrap();
|
||||
//!
|
||||
//! let mut ciphertext = vec![];
|
||||
//! ctx.cipher_update_vec(data, &mut ciphertext).unwrap();
|
||||
//! ctx.cipher_final_vec(&mut ciphertext).unwrap();
|
||||
//!
|
||||
//! assert_eq!(
|
||||
//! b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\x87\x4D\
|
||||
//! \xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1",
|
||||
//! &ciphertext[..],
|
||||
//! );
|
||||
//! ```
|
||||
//!
|
||||
//! Decrypt data with AES128 CBC
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::cipher::Cipher;
|
||||
//! use openssl::cipher_ctx::CipherCtx;
|
||||
//!
|
||||
//! let cipher = Cipher::aes_128_cbc();
|
||||
//! let data = b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\
|
||||
//! \x87\x4D\xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1";
|
||||
//! let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
|
||||
//! let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07";
|
||||
//!
|
||||
//! let mut ctx = CipherCtx::new().unwrap();
|
||||
//! ctx.decrypt_init(Some(cipher), Some(key), Some(iv)).unwrap();
|
||||
//!
|
||||
//! let mut plaintext = vec![];
|
||||
//! ctx.cipher_update_vec(data, &mut plaintext).unwrap();
|
||||
//! ctx.cipher_final_vec(&mut plaintext).unwrap();
|
||||
//!
|
||||
//! assert_eq!(b"Some Crypto Text", &plaintext[..]);
|
||||
//! ```
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use crate::cipher::CipherRef;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef};
|
||||
use crate::{cvt, cvt_p};
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::{c_int, c_uchar};
|
||||
use openssl_macros::corresponds;
|
||||
use std::convert::TryFrom;
|
||||
use std::ptr;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl300)] {
|
||||
use ffi::EVP_CIPHER_CTX_get0_cipher;
|
||||
} else {
|
||||
use ffi::EVP_CIPHER_CTX_cipher as EVP_CIPHER_CTX_get0_cipher;
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::EVP_CIPHER_CTX;
|
||||
fn drop = ffi::EVP_CIPHER_CTX_free;
|
||||
|
||||
/// A context object used to perform symmetric encryption operations.
|
||||
pub struct CipherCtx;
|
||||
/// A reference to a [`CipherCtx`].
|
||||
pub struct CipherCtxRef;
|
||||
}
|
||||
|
||||
impl CipherCtx {
|
||||
/// Creates a new context.
|
||||
#[corresponds(EVP_CIPHER_CTX_new)]
|
||||
pub fn new() -> Result<Self, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
unsafe {
|
||||
let ptr = cvt_p(ffi::EVP_CIPHER_CTX_new())?;
|
||||
Ok(CipherCtx::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CipherCtxRef {
|
||||
/// Initializes the context for encryption.
|
||||
///
|
||||
/// Normally this is called once to set all of the cipher, key, and IV. However, this process can be split up
|
||||
/// by first setting the cipher with no key or IV and then setting the key and IV with no cipher. This can be used
|
||||
/// to, for example, use a nonstandard IV size.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the key buffer is smaller than the key size of the cipher, the IV buffer is smaller than the IV size
|
||||
/// of the cipher, or if a key or IV is provided before a cipher.
|
||||
#[corresponds(EVP_EncryptInit_ex)]
|
||||
pub fn encrypt_init(
|
||||
&mut self,
|
||||
type_: Option<&CipherRef>,
|
||||
key: Option<&[u8]>,
|
||||
iv: Option<&[u8]>,
|
||||
) -> Result<(), ErrorStack> {
|
||||
self.cipher_init(type_, key, iv, ffi::EVP_EncryptInit_ex)
|
||||
}
|
||||
|
||||
/// Initializes the context for decryption.
|
||||
///
|
||||
/// Normally this is called once to set all of the cipher, key, and IV. However, this process can be split up
|
||||
/// by first setting the cipher with no key or IV and then setting the key and IV with no cipher. This can be used
|
||||
/// to, for example, use a nonstandard IV size.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the key buffer is smaller than the key size of the cipher, the IV buffer is smaller than the IV size
|
||||
/// of the cipher, or if a key or IV is provided before a cipher.
|
||||
#[corresponds(EVP_DecryptInit_ex)]
|
||||
pub fn decrypt_init(
|
||||
&mut self,
|
||||
type_: Option<&CipherRef>,
|
||||
key: Option<&[u8]>,
|
||||
iv: Option<&[u8]>,
|
||||
) -> Result<(), ErrorStack> {
|
||||
self.cipher_init(type_, key, iv, ffi::EVP_DecryptInit_ex)
|
||||
}
|
||||
|
||||
fn cipher_init(
|
||||
&mut self,
|
||||
type_: Option<&CipherRef>,
|
||||
key: Option<&[u8]>,
|
||||
iv: Option<&[u8]>,
|
||||
f: unsafe extern "C" fn(
|
||||
*mut ffi::EVP_CIPHER_CTX,
|
||||
*const ffi::EVP_CIPHER,
|
||||
*mut ffi::ENGINE,
|
||||
*const c_uchar,
|
||||
*const c_uchar,
|
||||
) -> c_int,
|
||||
) -> Result<(), ErrorStack> {
|
||||
if let Some(key) = key {
|
||||
let key_len = type_.map_or_else(|| self.key_length(), |c| c.key_length());
|
||||
assert!(key_len <= key.len());
|
||||
}
|
||||
|
||||
if let Some(iv) = iv {
|
||||
let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
|
||||
assert!(iv_len <= iv.len());
|
||||
}
|
||||
|
||||
unsafe {
|
||||
cvt(f(
|
||||
self.as_ptr(),
|
||||
type_.map_or(ptr::null(), |p| p.as_ptr()),
|
||||
ptr::null_mut(),
|
||||
key.map_or(ptr::null(), |k| k.as_ptr()),
|
||||
iv.map_or(ptr::null(), |iv| iv.as_ptr()),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Initializes the context to perform envelope encryption.
|
||||
///
|
||||
/// Normally this is called once to set both the cipher and public keys. However, this process may be split up by
|
||||
/// first providing the cipher with no public keys and then setting the public keys with no cipher.
|
||||
///
|
||||
/// `encrypted_keys` will contain the generated symmetric key encrypted with each corresponding asymmetric private
|
||||
/// key. The generated IV will be written to `iv`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `pub_keys` is not the same size as `encrypted_keys`, the IV buffer is smaller than the cipher's IV
|
||||
/// size, or if an IV is provided before the cipher.
|
||||
#[corresponds(EVP_SealInit)]
|
||||
pub fn seal_init<T>(
|
||||
&mut self,
|
||||
type_: Option<&CipherRef>,
|
||||
pub_keys: &[PKey<T>],
|
||||
encrypted_keys: &mut [Vec<u8>],
|
||||
iv: Option<&mut [u8]>,
|
||||
) -> Result<(), ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
assert_eq!(pub_keys.len(), encrypted_keys.len());
|
||||
if !pub_keys.is_empty() {
|
||||
let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
|
||||
assert!(iv.as_ref().map_or(0, |b| b.len()) >= iv_len);
|
||||
}
|
||||
|
||||
for (pub_key, buf) in pub_keys.iter().zip(&mut *encrypted_keys) {
|
||||
buf.resize(pub_key.size(), 0);
|
||||
}
|
||||
|
||||
let mut keys = encrypted_keys
|
||||
.iter_mut()
|
||||
.map(|b| b.as_mut_ptr())
|
||||
.collect::<Vec<_>>();
|
||||
let mut key_lengths = vec![0; pub_keys.len()];
|
||||
let pub_keys_len = i32::try_from(pub_keys.len()).unwrap();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_SealInit(
|
||||
self.as_ptr(),
|
||||
type_.map_or(ptr::null(), |p| p.as_ptr()),
|
||||
keys.as_mut_ptr(),
|
||||
key_lengths.as_mut_ptr(),
|
||||
iv.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
|
||||
pub_keys.as_ptr() as *mut _,
|
||||
pub_keys_len,
|
||||
))?;
|
||||
}
|
||||
|
||||
for (buf, len) in encrypted_keys.iter_mut().zip(key_lengths) {
|
||||
buf.truncate(len as usize);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Initializes the context to perform envelope decryption.
|
||||
///
|
||||
/// Normally this is called once with all of the arguments present. However, this process may be split up by first
|
||||
/// providing the cipher alone and then after providing the rest of the arguments in a second call.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the IV buffer is smaller than the cipher's required IV size or if the IV is provided before the
|
||||
/// cipher.
|
||||
#[corresponds(EVP_OpenInit)]
|
||||
pub fn open_init<T>(
|
||||
&mut self,
|
||||
type_: Option<&CipherRef>,
|
||||
encrypted_key: &[u8],
|
||||
iv: Option<&[u8]>,
|
||||
priv_key: Option<&PKeyRef<T>>,
|
||||
) -> Result<(), ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
if priv_key.is_some() {
|
||||
let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
|
||||
assert!(iv.map_or(0, |b| b.len()) >= iv_len);
|
||||
}
|
||||
|
||||
let len = c_int::try_from(encrypted_key.len()).unwrap();
|
||||
unsafe {
|
||||
cvt(ffi::EVP_OpenInit(
|
||||
self.as_ptr(),
|
||||
type_.map_or(ptr::null(), |p| p.as_ptr()),
|
||||
encrypted_key.as_ptr(),
|
||||
len,
|
||||
iv.map_or(ptr::null(), |b| b.as_ptr()),
|
||||
priv_key.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn assert_cipher(&self) {
|
||||
unsafe {
|
||||
assert!(!EVP_CIPHER_CTX_get0_cipher(self.as_ptr()).is_null());
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the block size of the context's cipher.
|
||||
///
|
||||
/// Stream ciphers will report a block size of 1.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the context has not been initialized with a cipher.
|
||||
#[corresponds(EVP_CIPHER_CTX_block_size)]
|
||||
pub fn block_size(&self) -> usize {
|
||||
self.assert_cipher();
|
||||
|
||||
unsafe { ffi::EVP_CIPHER_CTX_block_size(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Returns the key length of the context's cipher.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the context has not been initialized with a cipher.
|
||||
#[corresponds(EVP_CIPHER_CTX_key_length)]
|
||||
pub fn key_length(&self) -> usize {
|
||||
self.assert_cipher();
|
||||
|
||||
unsafe { ffi::EVP_CIPHER_CTX_key_length(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Generates a random key based on the configured cipher.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the context has not been initialized with a cipher or if the buffer is smaller than the cipher's key
|
||||
/// length.
|
||||
///
|
||||
/// This corresponds to [`EVP_CIPHER_CTX_rand_key`].
|
||||
///
|
||||
/// [`EVP_CIPHER_CTX_rand_key`]: https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_CTX_rand_key.html
|
||||
#[corresponds(EVP_CIPHER_CTX_rand_key)]
|
||||
pub fn rand_key(&self, buf: &mut [u8]) -> Result<(), ErrorStack> {
|
||||
assert!(buf.len() >= self.key_length());
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_CIPHER_CTX_rand_key(
|
||||
self.as_ptr(),
|
||||
buf.as_mut_ptr(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the length of the key expected by the context.
|
||||
///
|
||||
/// Only some ciphers support configurable key lengths.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the context has not been initialized with a cipher.
|
||||
#[corresponds(EVP_CIPHER_CTX_set_key_length)]
|
||||
pub fn set_key_length(&mut self, len: usize) -> Result<(), ErrorStack> {
|
||||
self.assert_cipher();
|
||||
|
||||
let len = c_int::try_from(len).unwrap();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_CIPHER_CTX_set_key_length(self.as_ptr(), len))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns the length of the IV expected by this context.
|
||||
///
|
||||
/// Returns 0 if the cipher does not use an IV.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the context has not been initialized with a cipher.
|
||||
#[corresponds(EVP_CIPHER_CTX_iv_length)]
|
||||
pub fn iv_length(&self) -> usize {
|
||||
self.assert_cipher();
|
||||
|
||||
unsafe { ffi::EVP_CIPHER_CTX_iv_length(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Sets the length of the IV expected by this context.
|
||||
///
|
||||
/// Only some ciphers support configurable IV lengths.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the context has not been initialized with a cipher.
|
||||
#[corresponds(EVP_CIHPER_CTX_ctrl)]
|
||||
pub fn set_iv_length(&mut self, len: usize) -> Result<(), ErrorStack> {
|
||||
self.assert_cipher();
|
||||
|
||||
let len = c_int::try_from(len).unwrap();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
||||
self.as_ptr(),
|
||||
ffi::EVP_CTRL_GCM_SET_IVLEN,
|
||||
len,
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns the length of the authentication tag expected by this context.
|
||||
///
|
||||
/// Returns 0 if the cipher is not authenticated.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the context has not been initialized with a cipher.
|
||||
///
|
||||
/// Requires OpenSSL 3.0.0 or newer.
|
||||
#[corresponds(EVP_CIPHER_CTX_get_tag_length)]
|
||||
#[cfg(ossl300)]
|
||||
pub fn tag_length(&self) -> usize {
|
||||
self.assert_cipher();
|
||||
|
||||
unsafe { ffi::EVP_CIPHER_CTX_get_tag_length(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Retrieves the calculated authentication tag from the context.
|
||||
///
|
||||
/// This should be called after `[Self::cipher_final]`, and is only supported by authenticated ciphers.
|
||||
///
|
||||
/// The size of the buffer indicates the size of the tag. While some ciphers support a range of tag sizes, it is
|
||||
/// recommended to pick the maximum size.
|
||||
#[corresponds(EVP_CIPHER_CTX_ctrl)]
|
||||
pub fn tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> {
|
||||
let len = c_int::try_from(tag.len()).unwrap();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
||||
self.as_ptr(),
|
||||
ffi::EVP_CTRL_GCM_GET_TAG,
|
||||
len,
|
||||
tag.as_mut_ptr() as *mut _,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the length of the generated authentication tag.
|
||||
///
|
||||
/// This must be called when encrypting with a cipher in CCM mode to use a tag size other than the default.
|
||||
#[corresponds(EVP_CIPHER_CTX_ctrl)]
|
||||
pub fn set_tag_length(&mut self, len: usize) -> Result<(), ErrorStack> {
|
||||
let len = c_int::try_from(len).unwrap();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
||||
self.as_ptr(),
|
||||
ffi::EVP_CTRL_GCM_SET_TAG,
|
||||
len,
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the authentication tag for verification during decryption.
|
||||
#[corresponds(EVP_CIPHER_CTX_ctrl)]
|
||||
pub fn set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack> {
|
||||
let len = c_int::try_from(tag.len()).unwrap();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
||||
self.as_ptr(),
|
||||
ffi::EVP_CTRL_GCM_SET_TAG,
|
||||
len,
|
||||
tag.as_ptr() as *mut _,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Enables or disables padding.
|
||||
///
|
||||
/// If padding is disabled, the plaintext must be an exact multiple of the cipher's block size.
|
||||
#[corresponds(EVP_CIPHER_CTX_set_padding)]
|
||||
pub fn set_padding(&mut self, padding: bool) {
|
||||
unsafe {
|
||||
ffi::EVP_CIPHER_CTX_set_padding(self.as_ptr(), padding as c_int);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the total length of plaintext data.
|
||||
///
|
||||
/// This is required for ciphers operating in CCM mode.
|
||||
#[corresponds(EVP_CipherUpdate)]
|
||||
pub fn set_data_len(&mut self, len: usize) -> Result<(), ErrorStack> {
|
||||
let len = c_int::try_from(len).unwrap();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_CipherUpdate(
|
||||
self.as_ptr(),
|
||||
ptr::null_mut(),
|
||||
&mut 0,
|
||||
ptr::null(),
|
||||
len,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Writes data into the context.
|
||||
///
|
||||
/// Providing no output buffer will cause the input to be considered additional authenticated data (AAD).
|
||||
///
|
||||
/// Returns the number of bytes written to `output`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `output.len()` is less than `input.len()` plus the cipher's block size.
|
||||
#[corresponds(EVP_CipherUpdate)]
|
||||
pub fn cipher_update(
|
||||
&mut self,
|
||||
input: &[u8],
|
||||
output: Option<&mut [u8]>,
|
||||
) -> Result<usize, ErrorStack> {
|
||||
let inlen = c_int::try_from(input.len()).unwrap();
|
||||
|
||||
if let Some(output) = &output {
|
||||
let mut block_size = self.block_size();
|
||||
if block_size == 1 {
|
||||
block_size = 0;
|
||||
}
|
||||
assert!(output.len() >= input.len() + block_size);
|
||||
}
|
||||
|
||||
let mut outlen = 0;
|
||||
unsafe {
|
||||
cvt(ffi::EVP_CipherUpdate(
|
||||
self.as_ptr(),
|
||||
output.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
|
||||
&mut outlen,
|
||||
input.as_ptr(),
|
||||
inlen,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(outlen as usize)
|
||||
}
|
||||
|
||||
/// Like [`Self::cipher_update`] except that it appends output to a [`Vec`].
|
||||
pub fn cipher_update_vec(
|
||||
&mut self,
|
||||
input: &[u8],
|
||||
output: &mut Vec<u8>,
|
||||
) -> Result<usize, ErrorStack> {
|
||||
let base = output.len();
|
||||
output.resize(base + input.len() + self.block_size(), 0);
|
||||
let len = self.cipher_update(input, Some(&mut output[base..]))?;
|
||||
output.truncate(base + len);
|
||||
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Finalizes the encryption or decryption process.
|
||||
///
|
||||
/// Any remaining data will be written to the output buffer.
|
||||
///
|
||||
/// Returns the number of bytes written to `output`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `output` is smaller than the cipher's block size.
|
||||
#[corresponds(EVP_CipherFinal)]
|
||||
pub fn cipher_final(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
let block_size = self.block_size();
|
||||
if block_size > 1 {
|
||||
assert!(output.len() >= block_size);
|
||||
}
|
||||
|
||||
let mut outl = 0;
|
||||
unsafe {
|
||||
cvt(ffi::EVP_CipherFinal(
|
||||
self.as_ptr(),
|
||||
output.as_mut_ptr(),
|
||||
&mut outl,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(outl as usize)
|
||||
}
|
||||
|
||||
/// Like [`Self::cipher_final`] except that it appends output to a [`Vec`].
|
||||
pub fn cipher_final_vec(&mut self, output: &mut Vec<u8>) -> Result<usize, ErrorStack> {
|
||||
let base = output.len();
|
||||
output.resize(base + self.block_size(), 0);
|
||||
let len = self.cipher_final(&mut output[base..])?;
|
||||
output.truncate(base + len);
|
||||
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::cipher::Cipher;
|
||||
use std::slice;
|
||||
|
||||
#[test]
|
||||
fn seal_open() {
|
||||
let private_pem = include_bytes!("../test/rsa.pem");
|
||||
let public_pem = include_bytes!("../test/rsa.pem.pub");
|
||||
let private_key = PKey::private_key_from_pem(private_pem).unwrap();
|
||||
let public_key = PKey::public_key_from_pem(public_pem).unwrap();
|
||||
let cipher = Cipher::aes_256_cbc();
|
||||
let secret = b"My secret message";
|
||||
|
||||
let mut ctx = CipherCtx::new().unwrap();
|
||||
let mut encrypted_key = vec![];
|
||||
let mut iv = vec![0; cipher.iv_length()];
|
||||
let mut encrypted = vec![];
|
||||
ctx.seal_init(
|
||||
Some(cipher),
|
||||
&[public_key],
|
||||
slice::from_mut(&mut encrypted_key),
|
||||
Some(&mut iv),
|
||||
)
|
||||
.unwrap();
|
||||
ctx.cipher_update_vec(secret, &mut encrypted).unwrap();
|
||||
ctx.cipher_final_vec(&mut encrypted).unwrap();
|
||||
|
||||
let mut decrypted = vec![];
|
||||
ctx.open_init(Some(cipher), &encrypted_key, Some(&iv), Some(&private_key))
|
||||
.unwrap();
|
||||
ctx.cipher_update_vec(&encrypted, &mut decrypted).unwrap();
|
||||
ctx.cipher_final_vec(&mut decrypted).unwrap();
|
||||
|
||||
assert_eq!(secret, &decrypted[..]);
|
||||
}
|
||||
|
||||
fn aes_128_cbc(cipher: &CipherRef) {
|
||||
// from https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf
|
||||
let key = hex::decode("2b7e151628aed2a6abf7158809cf4f3c").unwrap();
|
||||
let iv = hex::decode("000102030405060708090a0b0c0d0e0f").unwrap();
|
||||
let pt = hex::decode("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51")
|
||||
.unwrap();
|
||||
let ct = hex::decode("7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b2")
|
||||
.unwrap();
|
||||
|
||||
let mut ctx = CipherCtx::new().unwrap();
|
||||
|
||||
ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
|
||||
.unwrap();
|
||||
ctx.set_padding(false);
|
||||
|
||||
let mut buf = vec![];
|
||||
ctx.cipher_update_vec(&pt, &mut buf).unwrap();
|
||||
ctx.cipher_final_vec(&mut buf).unwrap();
|
||||
|
||||
assert_eq!(buf, ct);
|
||||
|
||||
ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv))
|
||||
.unwrap();
|
||||
ctx.set_padding(false);
|
||||
|
||||
let mut buf = vec![];
|
||||
ctx.cipher_update_vec(&ct, &mut buf).unwrap();
|
||||
ctx.cipher_final_vec(&mut buf).unwrap();
|
||||
|
||||
assert_eq!(buf, pt);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl300)]
|
||||
fn fetched_aes_128_cbc() {
|
||||
let cipher = Cipher::fetch(None, "AES-128-CBC", None).unwrap();
|
||||
aes_128_cbc(&cipher);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_aes_128_cbc() {
|
||||
let cipher = Cipher::aes_128_cbc();
|
||||
aes_128_cbc(cipher);
|
||||
}
|
||||
}
|
||||
314
zeroidc/vendor/openssl/src/cms.rs
vendored
Normal file
314
zeroidc/vendor/openssl/src/cms.rs
vendored
Normal file
@@ -0,0 +1,314 @@
|
||||
//! SMIME implementation using CMS
|
||||
//!
|
||||
//! CMS (PKCS#7) is an encryption standard. It allows signing and encrypting data using
|
||||
//! X.509 certificates. The OpenSSL implementation of CMS is used in email encryption
|
||||
//! generated from a `Vec` of bytes. This `Vec` follows the smime protocol standards.
|
||||
//! Data accepted by this module will be smime type `enveloped-data`.
|
||||
|
||||
use bitflags::bitflags;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::c_uint;
|
||||
use std::ptr;
|
||||
|
||||
use crate::bio::{MemBio, MemBioSlice};
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasPrivate, PKeyRef};
|
||||
use crate::stack::StackRef;
|
||||
use crate::symm::Cipher;
|
||||
use crate::x509::{X509Ref, X509};
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
bitflags! {
|
||||
pub struct CMSOptions : c_uint {
|
||||
const TEXT = ffi::CMS_TEXT;
|
||||
const CMS_NOCERTS = ffi::CMS_NOCERTS;
|
||||
const NO_CONTENT_VERIFY = ffi::CMS_NO_CONTENT_VERIFY;
|
||||
const NO_ATTR_VERIFY = ffi::CMS_NO_ATTR_VERIFY;
|
||||
const NOSIGS = ffi::CMS_NOSIGS;
|
||||
const NOINTERN = ffi::CMS_NOINTERN;
|
||||
const NO_SIGNER_CERT_VERIFY = ffi::CMS_NO_SIGNER_CERT_VERIFY;
|
||||
const NOVERIFY = ffi::CMS_NOVERIFY;
|
||||
const DETACHED = ffi::CMS_DETACHED;
|
||||
const BINARY = ffi::CMS_BINARY;
|
||||
const NOATTR = ffi::CMS_NOATTR;
|
||||
const NOSMIMECAP = ffi::CMS_NOSMIMECAP;
|
||||
const NOOLDMIMETYPE = ffi::CMS_NOOLDMIMETYPE;
|
||||
const CRLFEOL = ffi::CMS_CRLFEOL;
|
||||
const STREAM = ffi::CMS_STREAM;
|
||||
const NOCRL = ffi::CMS_NOCRL;
|
||||
const PARTIAL = ffi::CMS_PARTIAL;
|
||||
const REUSE_DIGEST = ffi::CMS_REUSE_DIGEST;
|
||||
const USE_KEYID = ffi::CMS_USE_KEYID;
|
||||
const DEBUG_DECRYPT = ffi::CMS_DEBUG_DECRYPT;
|
||||
#[cfg(all(not(libressl), not(ossl101)))]
|
||||
const KEY_PARAM = ffi::CMS_KEY_PARAM;
|
||||
#[cfg(all(not(libressl), not(ossl101), not(ossl102)))]
|
||||
const ASCIICRLF = ffi::CMS_ASCIICRLF;
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::CMS_ContentInfo;
|
||||
fn drop = ffi::CMS_ContentInfo_free;
|
||||
|
||||
/// High level CMS wrapper
|
||||
///
|
||||
/// CMS supports nesting various types of data, including signatures, certificates,
|
||||
/// encrypted data, smime messages (encrypted email), and data digest. The ContentInfo
|
||||
/// content type is the encapsulation of all those content types. [`RFC 5652`] describes
|
||||
/// CMS and OpenSSL follows this RFC's implementation.
|
||||
///
|
||||
/// [`RFC 5652`]: https://tools.ietf.org/html/rfc5652#page-6
|
||||
pub struct CmsContentInfo;
|
||||
/// Reference to [`CMSContentInfo`]
|
||||
///
|
||||
/// [`CMSContentInfo`]:struct.CmsContentInfo.html
|
||||
pub struct CmsContentInfoRef;
|
||||
}
|
||||
|
||||
impl CmsContentInfoRef {
|
||||
/// Given the sender's private key, `pkey` and the recipient's certificate, `cert`,
|
||||
/// decrypt the data in `self`.
|
||||
#[corresponds(CMS_decrypt)]
|
||||
pub fn decrypt<T>(&self, pkey: &PKeyRef<T>, cert: &X509) -> Result<Vec<u8>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
let pkey = pkey.as_ptr();
|
||||
let cert = cert.as_ptr();
|
||||
let out = MemBio::new()?;
|
||||
|
||||
cvt(ffi::CMS_decrypt(
|
||||
self.as_ptr(),
|
||||
pkey,
|
||||
cert,
|
||||
ptr::null_mut(),
|
||||
out.as_ptr(),
|
||||
0,
|
||||
))?;
|
||||
|
||||
Ok(out.get_buf().to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
/// Given the sender's private key, `pkey`,
|
||||
/// decrypt the data in `self` without validating the recipient certificate.
|
||||
///
|
||||
/// *Warning*: Not checking the recipient certificate may leave you vulnerable to Bleichenbacher's attack on PKCS#1 v1.5 RSA padding.
|
||||
#[corresponds(CMS_decrypt)]
|
||||
// FIXME merge into decrypt
|
||||
pub fn decrypt_without_cert_check<T>(&self, pkey: &PKeyRef<T>) -> Result<Vec<u8>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
let pkey = pkey.as_ptr();
|
||||
let out = MemBio::new()?;
|
||||
|
||||
cvt(ffi::CMS_decrypt(
|
||||
self.as_ptr(),
|
||||
pkey,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
out.as_ptr(),
|
||||
0,
|
||||
))?;
|
||||
|
||||
Ok(out.get_buf().to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes this CmsContentInfo using DER.
|
||||
#[corresponds(i2d_CMS_ContentInfo)]
|
||||
to_der,
|
||||
ffi::i2d_CMS_ContentInfo
|
||||
}
|
||||
|
||||
to_pem! {
|
||||
/// Serializes this CmsContentInfo using DER.
|
||||
#[corresponds(PEM_write_bio_CMS)]
|
||||
to_pem,
|
||||
ffi::PEM_write_bio_CMS
|
||||
}
|
||||
}
|
||||
|
||||
impl CmsContentInfo {
|
||||
/// Parses a smime formatted `vec` of bytes into a `CmsContentInfo`.
|
||||
#[corresponds(SMIME_read_CMS)]
|
||||
pub fn smime_read_cms(smime: &[u8]) -> Result<CmsContentInfo, ErrorStack> {
|
||||
unsafe {
|
||||
let bio = MemBioSlice::new(smime)?;
|
||||
|
||||
let cms = cvt_p(ffi::SMIME_read_CMS(bio.as_ptr(), ptr::null_mut()))?;
|
||||
|
||||
Ok(CmsContentInfo::from_ptr(cms))
|
||||
}
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Deserializes a DER-encoded ContentInfo structure.
|
||||
#[corresponds(d2i_CMS_ContentInfo)]
|
||||
from_der,
|
||||
CmsContentInfo,
|
||||
ffi::d2i_CMS_ContentInfo
|
||||
}
|
||||
|
||||
from_pem! {
|
||||
/// Deserializes a PEM-encoded ContentInfo structure.
|
||||
#[corresponds(PEM_read_bio_CMS)]
|
||||
from_pem,
|
||||
CmsContentInfo,
|
||||
ffi::PEM_read_bio_CMS
|
||||
}
|
||||
|
||||
/// Given a signing cert `signcert`, private key `pkey`, a certificate stack `certs`,
|
||||
/// data `data` and flags `flags`, create a CmsContentInfo struct.
|
||||
///
|
||||
/// All arguments are optional.
|
||||
#[corresponds(CMS_sign)]
|
||||
pub fn sign<T>(
|
||||
signcert: Option<&X509Ref>,
|
||||
pkey: Option<&PKeyRef<T>>,
|
||||
certs: Option<&StackRef<X509>>,
|
||||
data: Option<&[u8]>,
|
||||
flags: CMSOptions,
|
||||
) -> Result<CmsContentInfo, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
let signcert = signcert.map_or(ptr::null_mut(), |p| p.as_ptr());
|
||||
let pkey = pkey.map_or(ptr::null_mut(), |p| p.as_ptr());
|
||||
let data_bio = match data {
|
||||
Some(data) => Some(MemBioSlice::new(data)?),
|
||||
None => None,
|
||||
};
|
||||
let data_bio_ptr = data_bio.as_ref().map_or(ptr::null_mut(), |p| p.as_ptr());
|
||||
let certs = certs.map_or(ptr::null_mut(), |p| p.as_ptr());
|
||||
|
||||
let cms = cvt_p(ffi::CMS_sign(
|
||||
signcert,
|
||||
pkey,
|
||||
certs,
|
||||
data_bio_ptr,
|
||||
flags.bits(),
|
||||
))?;
|
||||
|
||||
Ok(CmsContentInfo::from_ptr(cms))
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a certificate stack `certs`, data `data`, cipher `cipher` and flags `flags`,
|
||||
/// create a CmsContentInfo struct.
|
||||
///
|
||||
/// OpenSSL documentation at [`CMS_encrypt`]
|
||||
///
|
||||
/// [`CMS_encrypt`]: https://www.openssl.org/docs/manmaster/man3/CMS_encrypt.html
|
||||
#[corresponds(CMS_encrypt)]
|
||||
pub fn encrypt(
|
||||
certs: &StackRef<X509>,
|
||||
data: &[u8],
|
||||
cipher: Cipher,
|
||||
flags: CMSOptions,
|
||||
) -> Result<CmsContentInfo, ErrorStack> {
|
||||
unsafe {
|
||||
let data_bio = MemBioSlice::new(data)?;
|
||||
|
||||
let cms = cvt_p(ffi::CMS_encrypt(
|
||||
certs.as_ptr(),
|
||||
data_bio.as_ptr(),
|
||||
cipher.as_ptr(),
|
||||
flags.bits(),
|
||||
))?;
|
||||
|
||||
Ok(CmsContentInfo::from_ptr(cms))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::pkcs12::Pkcs12;
|
||||
use crate::stack::Stack;
|
||||
use crate::x509::X509;
|
||||
|
||||
#[test]
|
||||
fn cms_encrypt_decrypt() {
|
||||
#[cfg(ossl300)]
|
||||
let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
|
||||
|
||||
// load cert with public key only
|
||||
let pub_cert_bytes = include_bytes!("../test/cms_pubkey.der");
|
||||
let pub_cert = X509::from_der(pub_cert_bytes).expect("failed to load pub cert");
|
||||
|
||||
// load cert with private key
|
||||
let priv_cert_bytes = include_bytes!("../test/cms.p12");
|
||||
let priv_cert = Pkcs12::from_der(priv_cert_bytes).expect("failed to load priv cert");
|
||||
let priv_cert = priv_cert
|
||||
.parse("mypass")
|
||||
.expect("failed to parse priv cert");
|
||||
|
||||
// encrypt cms message using public key cert
|
||||
let input = String::from("My Message");
|
||||
let mut cert_stack = Stack::new().expect("failed to create stack");
|
||||
cert_stack
|
||||
.push(pub_cert)
|
||||
.expect("failed to add pub cert to stack");
|
||||
|
||||
let encrypt = CmsContentInfo::encrypt(
|
||||
&cert_stack,
|
||||
input.as_bytes(),
|
||||
Cipher::des_ede3_cbc(),
|
||||
CMSOptions::empty(),
|
||||
)
|
||||
.expect("failed create encrypted cms");
|
||||
|
||||
// decrypt cms message using private key cert (DER)
|
||||
{
|
||||
let encrypted_der = encrypt.to_der().expect("failed to create der from cms");
|
||||
let decrypt =
|
||||
CmsContentInfo::from_der(&encrypted_der).expect("failed read cms from der");
|
||||
|
||||
let decrypt_with_cert_check = decrypt
|
||||
.decrypt(&priv_cert.pkey, &priv_cert.cert)
|
||||
.expect("failed to decrypt cms");
|
||||
let decrypt_with_cert_check = String::from_utf8(decrypt_with_cert_check)
|
||||
.expect("failed to create string from cms content");
|
||||
|
||||
let decrypt_without_cert_check = decrypt
|
||||
.decrypt_without_cert_check(&priv_cert.pkey)
|
||||
.expect("failed to decrypt cms");
|
||||
let decrypt_without_cert_check = String::from_utf8(decrypt_without_cert_check)
|
||||
.expect("failed to create string from cms content");
|
||||
|
||||
assert_eq!(input, decrypt_with_cert_check);
|
||||
assert_eq!(input, decrypt_without_cert_check);
|
||||
}
|
||||
|
||||
// decrypt cms message using private key cert (PEM)
|
||||
{
|
||||
let encrypted_pem = encrypt.to_pem().expect("failed to create pem from cms");
|
||||
let decrypt =
|
||||
CmsContentInfo::from_pem(&encrypted_pem).expect("failed read cms from pem");
|
||||
|
||||
let decrypt_with_cert_check = decrypt
|
||||
.decrypt(&priv_cert.pkey, &priv_cert.cert)
|
||||
.expect("failed to decrypt cms");
|
||||
let decrypt_with_cert_check = String::from_utf8(decrypt_with_cert_check)
|
||||
.expect("failed to create string from cms content");
|
||||
|
||||
let decrypt_without_cert_check = decrypt
|
||||
.decrypt_without_cert_check(&priv_cert.pkey)
|
||||
.expect("failed to decrypt cms");
|
||||
let decrypt_without_cert_check = String::from_utf8(decrypt_without_cert_check)
|
||||
.expect("failed to create string from cms content");
|
||||
|
||||
assert_eq!(input, decrypt_with_cert_check);
|
||||
assert_eq!(input, decrypt_without_cert_check);
|
||||
}
|
||||
}
|
||||
}
|
||||
58
zeroidc/vendor/openssl/src/conf.rs
vendored
Normal file
58
zeroidc/vendor/openssl/src/conf.rs
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
//! Interface for processing OpenSSL configuration files.
|
||||
|
||||
use crate::cvt_p;
|
||||
use crate::error::ErrorStack;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
pub struct ConfMethod(*mut ffi::CONF_METHOD);
|
||||
|
||||
impl ConfMethod {
|
||||
/// Retrieve handle to the default OpenSSL configuration file processing function.
|
||||
#[corresponds(NCONF_default)]
|
||||
pub fn default() -> ConfMethod {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
// `NCONF` stands for "New Conf", as described in crypto/conf/conf_lib.c. This is
|
||||
// a newer API than the "CONF classic" functions.
|
||||
ConfMethod(ffi::NCONF_default())
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct from raw pointer.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that the pointer is valid.
|
||||
pub unsafe fn from_ptr(ptr: *mut ffi::CONF_METHOD) -> ConfMethod {
|
||||
ConfMethod(ptr)
|
||||
}
|
||||
|
||||
/// Convert to raw pointer.
|
||||
pub fn as_ptr(&self) -> *mut ffi::CONF_METHOD {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::CONF;
|
||||
fn drop = ffi::NCONF_free;
|
||||
|
||||
pub struct Conf;
|
||||
pub struct ConfRef;
|
||||
}
|
||||
|
||||
impl Conf {
|
||||
/// Create a configuration parser.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use openssl::conf::{Conf, ConfMethod};
|
||||
///
|
||||
/// let conf = Conf::new(ConfMethod::default());
|
||||
/// ```
|
||||
#[corresponds(NCONF_new)]
|
||||
pub fn new(method: ConfMethod) -> Result<Conf, ErrorStack> {
|
||||
unsafe { cvt_p(ffi::NCONF_new(method.as_ptr())).map(Conf) }
|
||||
}
|
||||
}
|
||||
132
zeroidc/vendor/openssl/src/derive.rs
vendored
Normal file
132
zeroidc/vendor/openssl/src/derive.rs
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
//! Shared secret derivation.
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasPrivate, HasPublic, PKeyRef};
|
||||
use crate::{cvt, cvt_p};
|
||||
|
||||
/// A type used to derive a shared secret between two keys.
|
||||
pub struct Deriver<'a>(*mut ffi::EVP_PKEY_CTX, PhantomData<&'a ()>);
|
||||
|
||||
unsafe impl<'a> Sync for Deriver<'a> {}
|
||||
unsafe impl<'a> Send for Deriver<'a> {}
|
||||
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
impl<'a> Deriver<'a> {
|
||||
/// Creates a new `Deriver` using the provided private key.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_derive_init`].
|
||||
///
|
||||
/// [`EVP_PKEY_derive_init`]: https://www.openssl.org/docs/man1.0.2/crypto/EVP_PKEY_derive_init.html
|
||||
pub fn new<T>(key: &'a PKeyRef<T>) -> Result<Deriver<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
cvt_p(ffi::EVP_PKEY_CTX_new(key.as_ptr(), ptr::null_mut()))
|
||||
.map(|p| Deriver(p, PhantomData))
|
||||
.and_then(|ctx| cvt(ffi::EVP_PKEY_derive_init(ctx.0)).map(|_| ctx))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the peer key used for secret derivation.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_derive_set_peer`]:
|
||||
///
|
||||
/// [`EVP_PKEY_derive_set_peer`]: https://www.openssl.org/docs/man1.0.2/crypto/EVP_PKEY_derive_init.html
|
||||
pub fn set_peer<T>(&mut self, key: &'a PKeyRef<T>) -> Result<(), ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
unsafe { cvt(ffi::EVP_PKEY_derive_set_peer(self.0, key.as_ptr())).map(|_| ()) }
|
||||
}
|
||||
|
||||
/// Returns the size of the shared secret.
|
||||
///
|
||||
/// It can be used to size the buffer passed to [`Deriver::derive`].
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_derive`].
|
||||
///
|
||||
/// [`Deriver::derive`]: #method.derive
|
||||
/// [`EVP_PKEY_derive`]: https://www.openssl.org/docs/man1.0.2/crypto/EVP_PKEY_derive_init.html
|
||||
pub fn len(&mut self) -> Result<usize, ErrorStack> {
|
||||
unsafe {
|
||||
let mut len = 0;
|
||||
cvt(ffi::EVP_PKEY_derive(self.0, ptr::null_mut(), &mut len)).map(|_| len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Derives a shared secret between the two keys, writing it into the buffer.
|
||||
///
|
||||
/// Returns the number of bytes written.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_derive`].
|
||||
///
|
||||
/// [`EVP_PKEY_derive`]: https://www.openssl.org/docs/man1.0.2/crypto/EVP_PKEY_derive_init.html
|
||||
pub fn derive(&mut self, buf: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
let mut len = buf.len();
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_derive(
|
||||
self.0,
|
||||
buf.as_mut_ptr() as *mut _,
|
||||
&mut len,
|
||||
))
|
||||
.map(|_| len)
|
||||
}
|
||||
}
|
||||
|
||||
/// A convenience function which derives a shared secret and returns it in a new buffer.
|
||||
///
|
||||
/// This simply wraps [`Deriver::len`] and [`Deriver::derive`].
|
||||
///
|
||||
/// [`Deriver::len`]: #method.len
|
||||
/// [`Deriver::derive`]: #method.derive
|
||||
pub fn derive_to_vec(&mut self) -> Result<Vec<u8>, ErrorStack> {
|
||||
let len = self.len()?;
|
||||
let mut buf = vec![0; len];
|
||||
let len = self.derive(&mut buf)?;
|
||||
buf.truncate(len);
|
||||
Ok(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for Deriver<'a> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::EVP_PKEY_CTX_free(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
use crate::ec::{EcGroup, EcKey};
|
||||
use crate::nid::Nid;
|
||||
use crate::pkey::PKey;
|
||||
|
||||
#[test]
|
||||
fn derive_without_peer() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let ec_key = EcKey::generate(&group).unwrap();
|
||||
let pkey = PKey::from_ec_key(ec_key).unwrap();
|
||||
let mut deriver = Deriver::new(&pkey).unwrap();
|
||||
deriver.derive_to_vec().unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ec_key_derive() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let ec_key = EcKey::generate(&group).unwrap();
|
||||
let ec_key2 = EcKey::generate(&group).unwrap();
|
||||
let pkey = PKey::from_ec_key(ec_key).unwrap();
|
||||
let pkey2 = PKey::from_ec_key(ec_key2).unwrap();
|
||||
let mut deriver = Deriver::new(&pkey).unwrap();
|
||||
deriver.set_peer(&pkey2).unwrap();
|
||||
let shared = deriver.derive_to_vec().unwrap();
|
||||
assert!(!shared.is_empty());
|
||||
}
|
||||
}
|
||||
414
zeroidc/vendor/openssl/src/dh.rs
vendored
Normal file
414
zeroidc/vendor/openssl/src/dh.rs
vendored
Normal file
@@ -0,0 +1,414 @@
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use crate::bn::{BigNum, BigNumRef};
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasParams, HasPrivate, HasPublic, Params, Private};
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
generic_foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::DH;
|
||||
fn drop = ffi::DH_free;
|
||||
|
||||
pub struct Dh<T>;
|
||||
|
||||
pub struct DhRef<T>;
|
||||
}
|
||||
|
||||
impl<T> DhRef<T>
|
||||
where
|
||||
T: HasParams,
|
||||
{
|
||||
to_pem! {
|
||||
/// Serializes the parameters into a PEM-encoded PKCS#3 DHparameter structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN DH PARAMETERS-----`.
|
||||
#[corresponds(PEM_write_bio_DHparams)]
|
||||
params_to_pem,
|
||||
ffi::PEM_write_bio_DHparams
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes the parameters into a DER-encoded PKCS#3 DHparameter structure.
|
||||
#[corresponds(i2d_DHparams)]
|
||||
params_to_der,
|
||||
ffi::i2d_DHparams
|
||||
}
|
||||
}
|
||||
|
||||
impl Dh<Params> {
|
||||
pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result<Dh<Params>, ErrorStack> {
|
||||
Self::from_pqg(p, Some(q), g)
|
||||
}
|
||||
|
||||
/// Creates a DH instance based upon the given primes and generator params.
|
||||
#[corresponds(DH_set0_pqg)]
|
||||
pub fn from_pqg(
|
||||
prime_p: BigNum,
|
||||
prime_q: Option<BigNum>,
|
||||
generator: BigNum,
|
||||
) -> Result<Dh<Params>, ErrorStack> {
|
||||
unsafe {
|
||||
let dh = Dh::from_ptr(cvt_p(ffi::DH_new())?);
|
||||
cvt(DH_set0_pqg(
|
||||
dh.0,
|
||||
prime_p.as_ptr(),
|
||||
prime_q.as_ref().map_or(ptr::null_mut(), |q| q.as_ptr()),
|
||||
generator.as_ptr(),
|
||||
))?;
|
||||
mem::forget((prime_p, prime_q, generator));
|
||||
Ok(dh)
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the private key on the DH object and recomputes the public key.
|
||||
pub fn set_private_key(self, priv_key: BigNum) -> Result<Dh<Private>, ErrorStack> {
|
||||
unsafe {
|
||||
let dh_ptr = self.0;
|
||||
cvt(DH_set0_key(dh_ptr, ptr::null_mut(), priv_key.as_ptr()))?;
|
||||
mem::forget(priv_key);
|
||||
|
||||
cvt(ffi::DH_generate_key(dh_ptr))?;
|
||||
mem::forget(self);
|
||||
Ok(Dh::from_ptr(dh_ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates DH params based on the given `prime_len` and a fixed `generator` value.
|
||||
#[corresponds(DH_generate_parameters_ex)]
|
||||
pub fn generate_params(prime_len: u32, generator: u32) -> Result<Dh<Params>, ErrorStack> {
|
||||
unsafe {
|
||||
let dh = Dh::from_ptr(cvt_p(ffi::DH_new())?);
|
||||
cvt(ffi::DH_generate_parameters_ex(
|
||||
dh.0,
|
||||
prime_len as i32,
|
||||
generator as i32,
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
Ok(dh)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a public and a private key based on the DH params.
|
||||
#[corresponds(DH_generate_key)]
|
||||
pub fn generate_key(self) -> Result<Dh<Private>, ErrorStack> {
|
||||
unsafe {
|
||||
let dh_ptr = self.0;
|
||||
cvt(ffi::DH_generate_key(dh_ptr))?;
|
||||
mem::forget(self);
|
||||
Ok(Dh::from_ptr(dh_ptr))
|
||||
}
|
||||
}
|
||||
|
||||
from_pem! {
|
||||
/// Deserializes a PEM-encoded PKCS#3 DHpararameters structure.
|
||||
///
|
||||
/// The input should have a header of `-----BEGIN DH PARAMETERS-----`.
|
||||
#[corresponds(PEM_read_bio_DHparams)]
|
||||
params_from_pem,
|
||||
Dh<Params>,
|
||||
ffi::PEM_read_bio_DHparams
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Deserializes a DER-encoded PKCS#3 DHparameters structure.
|
||||
#[corresponds(d2i_DHparams)]
|
||||
params_from_der,
|
||||
Dh<Params>,
|
||||
ffi::d2i_DHparams
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.0.2 or newer.
|
||||
#[corresponds(DH_get_1024_160)]
|
||||
#[cfg(any(ossl102, ossl110))]
|
||||
pub fn get_1024_160() -> Result<Dh<Params>, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
cvt_p(ffi::DH_get_1024_160()).map(|p| Dh::from_ptr(p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.0.2 or newer.
|
||||
#[corresponds(DH_get_2048_224)]
|
||||
#[cfg(any(ossl102, ossl110))]
|
||||
pub fn get_2048_224() -> Result<Dh<Params>, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
cvt_p(ffi::DH_get_2048_224()).map(|p| Dh::from_ptr(p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.0.2 or newer.
|
||||
#[corresponds(DH_get_2048_256)]
|
||||
#[cfg(any(ossl102, ossl110))]
|
||||
pub fn get_2048_256() -> Result<Dh<Params>, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
cvt_p(ffi::DH_get_2048_256()).map(|p| Dh::from_ptr(p))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Dh<T>
|
||||
where
|
||||
T: HasParams,
|
||||
{
|
||||
/// Returns the prime `p` from the DH instance.
|
||||
#[corresponds(DH_get0_pqg)]
|
||||
pub fn prime_p(&self) -> &BigNumRef {
|
||||
let mut p = ptr::null();
|
||||
unsafe {
|
||||
DH_get0_pqg(self.as_ptr(), &mut p, ptr::null_mut(), ptr::null_mut());
|
||||
BigNumRef::from_ptr(p as *mut _)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the prime `q` from the DH instance.
|
||||
#[corresponds(DH_get0_pqg)]
|
||||
pub fn prime_q(&self) -> Option<&BigNumRef> {
|
||||
let mut q = ptr::null();
|
||||
unsafe {
|
||||
DH_get0_pqg(self.as_ptr(), ptr::null_mut(), &mut q, ptr::null_mut());
|
||||
if q.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(BigNumRef::from_ptr(q as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the generator from the DH instance.
|
||||
#[corresponds(DH_get0_pqg)]
|
||||
pub fn generator(&self) -> &BigNumRef {
|
||||
let mut g = ptr::null();
|
||||
unsafe {
|
||||
DH_get0_pqg(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut g);
|
||||
BigNumRef::from_ptr(g as *mut _)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DhRef<T>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
/// Returns the public key from the DH instance.
|
||||
#[corresponds(DH_get0_key)]
|
||||
pub fn public_key(&self) -> &BigNumRef {
|
||||
let mut pub_key = ptr::null();
|
||||
unsafe {
|
||||
DH_get0_key(self.as_ptr(), &mut pub_key, ptr::null_mut());
|
||||
BigNumRef::from_ptr(pub_key as *mut _)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DhRef<T>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
/// Computes a shared secret from the own private key and the given `public_key`.
|
||||
#[corresponds(DH_compute_key)]
|
||||
pub fn compute_key(&self, public_key: &BigNumRef) -> Result<Vec<u8>, ErrorStack> {
|
||||
unsafe {
|
||||
let key_len = ffi::DH_size(self.as_ptr());
|
||||
let mut key = vec![0u8; key_len as usize];
|
||||
cvt(ffi::DH_compute_key(
|
||||
key.as_mut_ptr(),
|
||||
public_key.as_ptr(),
|
||||
self.as_ptr(),
|
||||
))?;
|
||||
Ok(key)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the private key from the DH instance.
|
||||
#[corresponds(DH_get0_key)]
|
||||
pub fn private_key(&self) -> &BigNumRef {
|
||||
let mut priv_key = ptr::null();
|
||||
unsafe {
|
||||
DH_get0_key(self.as_ptr(), ptr::null_mut(), &mut priv_key);
|
||||
BigNumRef::from_ptr(priv_key as *mut _)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl270))] {
|
||||
use ffi::{DH_set0_pqg, DH_get0_pqg, DH_get0_key, DH_set0_key};
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DH_set0_pqg(
|
||||
dh: *mut ffi::DH,
|
||||
p: *mut ffi::BIGNUM,
|
||||
q: *mut ffi::BIGNUM,
|
||||
g: *mut ffi::BIGNUM,
|
||||
) -> ::libc::c_int {
|
||||
(*dh).p = p;
|
||||
(*dh).q = q;
|
||||
(*dh).g = g;
|
||||
1
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DH_get0_pqg(
|
||||
dh: *mut ffi::DH,
|
||||
p: *mut *const ffi::BIGNUM,
|
||||
q: *mut *const ffi::BIGNUM,
|
||||
g: *mut *const ffi::BIGNUM,
|
||||
) {
|
||||
if !p.is_null() {
|
||||
*p = (*dh).p;
|
||||
}
|
||||
if !q.is_null() {
|
||||
*q = (*dh).q;
|
||||
}
|
||||
if !g.is_null() {
|
||||
*g = (*dh).g;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DH_set0_key(
|
||||
dh: *mut ffi::DH,
|
||||
pub_key: *mut ffi::BIGNUM,
|
||||
priv_key: *mut ffi::BIGNUM,
|
||||
) -> ::libc::c_int {
|
||||
(*dh).pub_key = pub_key;
|
||||
(*dh).priv_key = priv_key;
|
||||
1
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DH_get0_key(
|
||||
dh: *mut ffi::DH,
|
||||
pub_key: *mut *const ffi::BIGNUM,
|
||||
priv_key: *mut *const ffi::BIGNUM,
|
||||
) {
|
||||
if !pub_key.is_null() {
|
||||
*pub_key = (*dh).pub_key;
|
||||
}
|
||||
if !priv_key.is_null() {
|
||||
*priv_key = (*dh).priv_key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::bn::BigNum;
|
||||
use crate::dh::Dh;
|
||||
use crate::ssl::{SslContext, SslMethod};
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn test_dh_rfc5114() {
|
||||
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
|
||||
let dh2 = Dh::get_2048_224().unwrap();
|
||||
ctx.set_tmp_dh(&dh2).unwrap();
|
||||
let dh3 = Dh::get_2048_256().unwrap();
|
||||
ctx.set_tmp_dh(&dh3).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dh_params() {
|
||||
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
|
||||
let prime_p = BigNum::from_hex_str(
|
||||
"87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF\
|
||||
4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B47\
|
||||
58C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B6\
|
||||
3ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5\
|
||||
140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710\
|
||||
C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597",
|
||||
).unwrap();
|
||||
let prime_q = BigNum::from_hex_str(
|
||||
"3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED\
|
||||
4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A\
|
||||
57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5\
|
||||
045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E\
|
||||
052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67E\
|
||||
B6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659",
|
||||
).unwrap();
|
||||
let generator = BigNum::from_hex_str(
|
||||
"8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3",
|
||||
)
|
||||
.unwrap();
|
||||
let dh = Dh::from_params(
|
||||
prime_p.to_owned().unwrap(),
|
||||
generator.to_owned().unwrap(),
|
||||
prime_q.to_owned().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
ctx.set_tmp_dh(&dh).unwrap();
|
||||
|
||||
assert_eq!(dh.prime_p(), &prime_p);
|
||||
assert_eq!(dh.prime_q().unwrap(), &prime_q);
|
||||
assert_eq!(dh.generator(), &generator);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn test_dh_stored_restored() {
|
||||
let dh1 = Dh::get_2048_256().unwrap();
|
||||
let key1 = dh1.generate_key().unwrap();
|
||||
|
||||
let dh2 = Dh::get_2048_256().unwrap();
|
||||
let key2 = dh2
|
||||
.set_private_key(key1.private_key().to_owned().unwrap())
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(key1.public_key(), key2.public_key());
|
||||
assert_eq!(key1.private_key(), key2.private_key());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dh_from_pem() {
|
||||
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
|
||||
let params = include_bytes!("../test/dhparams.pem");
|
||||
let dh = Dh::params_from_pem(params).unwrap();
|
||||
ctx.set_tmp_dh(&dh).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dh_from_der() {
|
||||
let params = include_bytes!("../test/dhparams.pem");
|
||||
let dh = Dh::params_from_pem(params).unwrap();
|
||||
let der = dh.params_to_der().unwrap();
|
||||
Dh::params_from_der(&der).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn test_dh_generate_key_compute_key() {
|
||||
let dh1 = Dh::get_2048_224().unwrap().generate_key().unwrap();
|
||||
let dh2 = Dh::get_2048_224().unwrap().generate_key().unwrap();
|
||||
|
||||
let shared_a = dh1.compute_key(dh2.public_key()).unwrap();
|
||||
let shared_b = dh2.compute_key(dh1.public_key()).unwrap();
|
||||
|
||||
assert_eq!(shared_a, shared_b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dh_generate_params_generate_key_compute_key() {
|
||||
let dh_params1 = Dh::generate_params(512, 2).unwrap();
|
||||
let dh_params2 = Dh::from_pqg(
|
||||
dh_params1.prime_p().to_owned().unwrap(),
|
||||
None,
|
||||
dh_params1.generator().to_owned().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let dh1 = dh_params1.generate_key().unwrap();
|
||||
let dh2 = dh_params2.generate_key().unwrap();
|
||||
|
||||
let shared_a = dh1.compute_key(dh2.public_key()).unwrap();
|
||||
let shared_b = dh2.compute_key(dh1.public_key()).unwrap();
|
||||
|
||||
assert_eq!(shared_a, shared_b);
|
||||
}
|
||||
}
|
||||
445
zeroidc/vendor/openssl/src/dsa.rs
vendored
Normal file
445
zeroidc/vendor/openssl/src/dsa.rs
vendored
Normal file
@@ -0,0 +1,445 @@
|
||||
//! Digital Signatures
|
||||
//!
|
||||
//! DSA ensures a message originated from a known sender, and was not modified.
|
||||
//! DSA uses asymmetrical keys and an algorithm to output a signature of the message
|
||||
//! using the private key that can be validated with the public key but not be generated
|
||||
//! without the private key.
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::c_int;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use crate::bn::{BigNum, BigNumRef};
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasParams, HasPrivate, HasPublic, Private, Public};
|
||||
use crate::util::ForeignTypeRefExt;
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
generic_foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::DSA;
|
||||
fn drop = ffi::DSA_free;
|
||||
|
||||
/// Object representing DSA keys.
|
||||
///
|
||||
/// A DSA object contains the parameters p, q, and g. There is a private
|
||||
/// and public key. The values p, g, and q are:
|
||||
///
|
||||
/// * `p`: DSA prime parameter
|
||||
/// * `q`: DSA sub-prime parameter
|
||||
/// * `g`: DSA base parameter
|
||||
///
|
||||
/// These values are used to calculate a pair of asymmetrical keys used for
|
||||
/// signing.
|
||||
///
|
||||
/// OpenSSL documentation at [`DSA_new`]
|
||||
///
|
||||
/// [`DSA_new`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_new.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use openssl::dsa::Dsa;
|
||||
/// use openssl::error::ErrorStack;
|
||||
/// use openssl::pkey::Private;
|
||||
///
|
||||
/// fn create_dsa() -> Result<Dsa<Private>, ErrorStack> {
|
||||
/// let sign = Dsa::generate(2048)?;
|
||||
/// Ok(sign)
|
||||
/// }
|
||||
/// # fn main() {
|
||||
/// # create_dsa();
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct Dsa<T>;
|
||||
/// Reference to [`Dsa`].
|
||||
///
|
||||
/// [`Dsa`]: struct.Dsa.html
|
||||
pub struct DsaRef<T>;
|
||||
}
|
||||
|
||||
impl<T> Clone for Dsa<T> {
|
||||
fn clone(&self) -> Dsa<T> {
|
||||
(**self).to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ToOwned for DsaRef<T> {
|
||||
type Owned = Dsa<T>;
|
||||
|
||||
fn to_owned(&self) -> Dsa<T> {
|
||||
unsafe {
|
||||
ffi::DSA_up_ref(self.as_ptr());
|
||||
Dsa::from_ptr(self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DsaRef<T>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
to_pem! {
|
||||
/// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
|
||||
#[corresponds(PEM_write_bio_DSA_PUBKEY)]
|
||||
public_key_to_pem,
|
||||
ffi::PEM_write_bio_DSA_PUBKEY
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
|
||||
#[corresponds(i2d_DSA_PUBKEY)]
|
||||
public_key_to_der,
|
||||
ffi::i2d_DSA_PUBKEY
|
||||
}
|
||||
|
||||
/// Returns a reference to the public key component of `self`.
|
||||
#[corresponds(DSA_get0_key)]
|
||||
pub fn pub_key(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut pub_key = ptr::null();
|
||||
DSA_get0_key(self.as_ptr(), &mut pub_key, ptr::null_mut());
|
||||
BigNumRef::from_const_ptr(pub_key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DsaRef<T>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
private_key_to_pem! {
|
||||
/// Serializes the private key to a PEM-encoded DSAPrivateKey structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN DSA PRIVATE KEY-----`.
|
||||
#[corresponds(PEM_write_bio_DSAPrivateKey)]
|
||||
private_key_to_pem,
|
||||
/// Serializes the private key to a PEM-encoded encrypted DSAPrivateKey structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN DSA PRIVATE KEY-----`.
|
||||
#[corresponds(PEM_write_bio_DSAPrivateKey)]
|
||||
private_key_to_pem_passphrase,
|
||||
ffi::PEM_write_bio_DSAPrivateKey
|
||||
}
|
||||
|
||||
/// Returns a reference to the private key component of `self`.
|
||||
#[corresponds(DSA_get0_key)]
|
||||
pub fn priv_key(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut priv_key = ptr::null();
|
||||
DSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut priv_key);
|
||||
BigNumRef::from_const_ptr(priv_key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DsaRef<T>
|
||||
where
|
||||
T: HasParams,
|
||||
{
|
||||
/// Returns the maximum size of the signature output by `self` in bytes.
|
||||
#[corresponds(DSA_size)]
|
||||
pub fn size(&self) -> u32 {
|
||||
unsafe { ffi::DSA_size(self.as_ptr()) as u32 }
|
||||
}
|
||||
|
||||
/// Returns the DSA prime parameter of `self`.
|
||||
#[corresponds(DSA_get0_pqg)]
|
||||
pub fn p(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut p = ptr::null();
|
||||
DSA_get0_pqg(self.as_ptr(), &mut p, ptr::null_mut(), ptr::null_mut());
|
||||
BigNumRef::from_const_ptr(p)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the DSA sub-prime parameter of `self`.
|
||||
#[corresponds(DSA_get0_pqg)]
|
||||
pub fn q(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut q = ptr::null();
|
||||
DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), &mut q, ptr::null_mut());
|
||||
BigNumRef::from_const_ptr(q)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the DSA base parameter of `self`.
|
||||
#[corresponds(DSA_get0_pqg)]
|
||||
pub fn g(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut g = ptr::null();
|
||||
DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut g);
|
||||
BigNumRef::from_const_ptr(g)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dsa<Private> {
|
||||
/// Generate a DSA key pair.
|
||||
///
|
||||
/// Calls [`DSA_generate_parameters_ex`] to populate the `p`, `g`, and `q` values.
|
||||
/// These values are used to generate the key pair with [`DSA_generate_key`].
|
||||
///
|
||||
/// The `bits` parameter corresponds to the length of the prime `p`.
|
||||
///
|
||||
/// [`DSA_generate_parameters_ex`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_generate_parameters_ex.html
|
||||
/// [`DSA_generate_key`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_generate_key.html
|
||||
pub fn generate(bits: u32) -> Result<Dsa<Private>, ErrorStack> {
|
||||
ffi::init();
|
||||
unsafe {
|
||||
let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
|
||||
cvt(ffi::DSA_generate_parameters_ex(
|
||||
dsa.0,
|
||||
bits as c_int,
|
||||
ptr::null(),
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
cvt(ffi::DSA_generate_key(dsa.0))?;
|
||||
Ok(dsa)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a DSA key pair with the given parameters
|
||||
///
|
||||
/// `p`, `q` and `g` are the common parameters.
|
||||
/// `priv_key` is the private component of the key pair.
|
||||
/// `pub_key` is the public component of the key. Can be computed via `g^(priv_key) mod p`
|
||||
pub fn from_private_components(
|
||||
p: BigNum,
|
||||
q: BigNum,
|
||||
g: BigNum,
|
||||
priv_key: BigNum,
|
||||
pub_key: BigNum,
|
||||
) -> Result<Dsa<Private>, ErrorStack> {
|
||||
ffi::init();
|
||||
unsafe {
|
||||
let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
|
||||
cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
|
||||
mem::forget((p, q, g));
|
||||
cvt(DSA_set0_key(dsa.0, pub_key.as_ptr(), priv_key.as_ptr()))?;
|
||||
mem::forget((pub_key, priv_key));
|
||||
Ok(dsa)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dsa<Public> {
|
||||
from_pem! {
|
||||
/// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing a DSA key.
|
||||
///
|
||||
/// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
|
||||
#[corresponds(PEM_read_bio_DSA_PUBKEY)]
|
||||
public_key_from_pem,
|
||||
Dsa<Public>,
|
||||
ffi::PEM_read_bio_DSA_PUBKEY
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Decodes a DER-encoded SubjectPublicKeyInfo structure containing a DSA key.
|
||||
#[corresponds(d2i_DSA_PUBKEY)]
|
||||
public_key_from_der,
|
||||
Dsa<Public>,
|
||||
ffi::d2i_DSA_PUBKEY
|
||||
}
|
||||
|
||||
/// Create a new DSA key with only public components.
|
||||
///
|
||||
/// `p`, `q` and `g` are the common parameters.
|
||||
/// `pub_key` is the public component of the key.
|
||||
pub fn from_public_components(
|
||||
p: BigNum,
|
||||
q: BigNum,
|
||||
g: BigNum,
|
||||
pub_key: BigNum,
|
||||
) -> Result<Dsa<Public>, ErrorStack> {
|
||||
ffi::init();
|
||||
unsafe {
|
||||
let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
|
||||
cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
|
||||
mem::forget((p, q, g));
|
||||
cvt(DSA_set0_key(dsa.0, pub_key.as_ptr(), ptr::null_mut()))?;
|
||||
mem::forget(pub_key);
|
||||
Ok(dsa)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for Dsa<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "DSA")
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273))] {
|
||||
use ffi::{DSA_get0_key, DSA_get0_pqg, DSA_set0_key, DSA_set0_pqg};
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DSA_get0_pqg(
|
||||
d: *mut ffi::DSA,
|
||||
p: *mut *const ffi::BIGNUM,
|
||||
q: *mut *const ffi::BIGNUM,
|
||||
g: *mut *const ffi::BIGNUM)
|
||||
{
|
||||
if !p.is_null() {
|
||||
*p = (*d).p;
|
||||
}
|
||||
if !q.is_null() {
|
||||
*q = (*d).q;
|
||||
}
|
||||
if !g.is_null() {
|
||||
*g = (*d).g;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DSA_get0_key(
|
||||
d: *mut ffi::DSA,
|
||||
pub_key: *mut *const ffi::BIGNUM,
|
||||
priv_key: *mut *const ffi::BIGNUM)
|
||||
{
|
||||
if !pub_key.is_null() {
|
||||
*pub_key = (*d).pub_key;
|
||||
}
|
||||
if !priv_key.is_null() {
|
||||
*priv_key = (*d).priv_key;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DSA_set0_key(
|
||||
d: *mut ffi::DSA,
|
||||
pub_key: *mut ffi::BIGNUM,
|
||||
priv_key: *mut ffi::BIGNUM) -> c_int
|
||||
{
|
||||
(*d).pub_key = pub_key;
|
||||
(*d).priv_key = priv_key;
|
||||
1
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DSA_set0_pqg(
|
||||
d: *mut ffi::DSA,
|
||||
p: *mut ffi::BIGNUM,
|
||||
q: *mut ffi::BIGNUM,
|
||||
g: *mut ffi::BIGNUM) -> c_int
|
||||
{
|
||||
(*d).p = p;
|
||||
(*d).q = q;
|
||||
(*d).g = g;
|
||||
1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::bn::BigNumContext;
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::pkey::PKey;
|
||||
use crate::sign::{Signer, Verifier};
|
||||
|
||||
#[test]
|
||||
pub fn test_generate() {
|
||||
Dsa::generate(1024).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pubkey_generation() {
|
||||
let dsa = Dsa::generate(1024).unwrap();
|
||||
let p = dsa.p();
|
||||
let g = dsa.g();
|
||||
let priv_key = dsa.priv_key();
|
||||
let pub_key = dsa.pub_key();
|
||||
let mut ctx = BigNumContext::new().unwrap();
|
||||
let mut calc = BigNum::new().unwrap();
|
||||
calc.mod_exp(g, priv_key, p, &mut ctx).unwrap();
|
||||
assert_eq!(&calc, pub_key)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_priv_key_from_parts() {
|
||||
let p = BigNum::from_u32(283).unwrap();
|
||||
let q = BigNum::from_u32(47).unwrap();
|
||||
let g = BigNum::from_u32(60).unwrap();
|
||||
let priv_key = BigNum::from_u32(15).unwrap();
|
||||
let pub_key = BigNum::from_u32(207).unwrap();
|
||||
|
||||
let dsa = Dsa::from_private_components(p, q, g, priv_key, pub_key).unwrap();
|
||||
assert_eq!(dsa.pub_key(), &BigNum::from_u32(207).unwrap());
|
||||
assert_eq!(dsa.priv_key(), &BigNum::from_u32(15).unwrap());
|
||||
assert_eq!(dsa.p(), &BigNum::from_u32(283).unwrap());
|
||||
assert_eq!(dsa.q(), &BigNum::from_u32(47).unwrap());
|
||||
assert_eq!(dsa.g(), &BigNum::from_u32(60).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pub_key_from_parts() {
|
||||
let p = BigNum::from_u32(283).unwrap();
|
||||
let q = BigNum::from_u32(47).unwrap();
|
||||
let g = BigNum::from_u32(60).unwrap();
|
||||
let pub_key = BigNum::from_u32(207).unwrap();
|
||||
|
||||
let dsa = Dsa::from_public_components(p, q, g, pub_key).unwrap();
|
||||
assert_eq!(dsa.pub_key(), &BigNum::from_u32(207).unwrap());
|
||||
assert_eq!(dsa.p(), &BigNum::from_u32(283).unwrap());
|
||||
assert_eq!(dsa.q(), &BigNum::from_u32(47).unwrap());
|
||||
assert_eq!(dsa.g(), &BigNum::from_u32(60).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_signature() {
|
||||
const TEST_DATA: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
let dsa_ref = Dsa::generate(1024).unwrap();
|
||||
|
||||
let p = dsa_ref.p();
|
||||
let q = dsa_ref.q();
|
||||
let g = dsa_ref.g();
|
||||
|
||||
let pub_key = dsa_ref.pub_key();
|
||||
let priv_key = dsa_ref.priv_key();
|
||||
|
||||
let priv_key = Dsa::from_private_components(
|
||||
BigNumRef::to_owned(p).unwrap(),
|
||||
BigNumRef::to_owned(q).unwrap(),
|
||||
BigNumRef::to_owned(g).unwrap(),
|
||||
BigNumRef::to_owned(priv_key).unwrap(),
|
||||
BigNumRef::to_owned(pub_key).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let priv_key = PKey::from_dsa(priv_key).unwrap();
|
||||
|
||||
let pub_key = Dsa::from_public_components(
|
||||
BigNumRef::to_owned(p).unwrap(),
|
||||
BigNumRef::to_owned(q).unwrap(),
|
||||
BigNumRef::to_owned(g).unwrap(),
|
||||
BigNumRef::to_owned(pub_key).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let pub_key = PKey::from_dsa(pub_key).unwrap();
|
||||
|
||||
let mut signer = Signer::new(MessageDigest::sha256(), &priv_key).unwrap();
|
||||
signer.update(TEST_DATA).unwrap();
|
||||
|
||||
let signature = signer.sign_to_vec().unwrap();
|
||||
let mut verifier = Verifier::new(MessageDigest::sha256(), &pub_key).unwrap();
|
||||
verifier.update(TEST_DATA).unwrap();
|
||||
assert!(verifier.verify(&signature[..]).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::redundant_clone)]
|
||||
fn clone() {
|
||||
let key = Dsa::generate(2048).unwrap();
|
||||
drop(key.clone());
|
||||
}
|
||||
}
|
||||
1071
zeroidc/vendor/openssl/src/ec.rs
vendored
Normal file
1071
zeroidc/vendor/openssl/src/ec.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
224
zeroidc/vendor/openssl/src/ecdsa.rs
vendored
Normal file
224
zeroidc/vendor/openssl/src/ecdsa.rs
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
//! Low level Elliptic Curve Digital Signature Algorithm (ECDSA) functions.
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::c_int;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use crate::bn::{BigNum, BigNumRef};
|
||||
use crate::ec::EcKeyRef;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasPrivate, HasPublic};
|
||||
use crate::util::ForeignTypeRefExt;
|
||||
use crate::{cvt_n, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ECDSA_SIG;
|
||||
fn drop = ffi::ECDSA_SIG_free;
|
||||
|
||||
/// A low level interface to ECDSA.
|
||||
pub struct EcdsaSig;
|
||||
/// A reference to an [`EcdsaSig`].
|
||||
pub struct EcdsaSigRef;
|
||||
}
|
||||
|
||||
impl EcdsaSig {
|
||||
/// Computes a digital signature of the hash value `data` using the private EC key eckey.
|
||||
#[corresponds(ECDSA_do_sign)]
|
||||
pub fn sign<T>(data: &[u8], eckey: &EcKeyRef<T>) -> Result<EcdsaSig, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
assert!(data.len() <= c_int::max_value() as usize);
|
||||
let sig = cvt_p(ffi::ECDSA_do_sign(
|
||||
data.as_ptr(),
|
||||
data.len() as c_int,
|
||||
eckey.as_ptr(),
|
||||
))?;
|
||||
Ok(EcdsaSig::from_ptr(sig))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a new `EcdsaSig` by setting the `r` and `s` values associated with an ECDSA signature.
|
||||
#[corresponds(ECDSA_SIG_set0)]
|
||||
pub fn from_private_components(r: BigNum, s: BigNum) -> Result<EcdsaSig, ErrorStack> {
|
||||
unsafe {
|
||||
let sig = cvt_p(ffi::ECDSA_SIG_new())?;
|
||||
ECDSA_SIG_set0(sig, r.as_ptr(), s.as_ptr());
|
||||
mem::forget((r, s));
|
||||
Ok(EcdsaSig::from_ptr(sig))
|
||||
}
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Decodes a DER-encoded ECDSA signature.
|
||||
#[corresponds(d2i_ECDSA_SIG)]
|
||||
from_der,
|
||||
EcdsaSig,
|
||||
ffi::d2i_ECDSA_SIG
|
||||
}
|
||||
}
|
||||
|
||||
impl EcdsaSigRef {
|
||||
to_der! {
|
||||
/// Serializes the ECDSA signature into a DER-encoded ECDSASignature structure.
|
||||
#[corresponds(i2d_ECDSA_SIG)]
|
||||
to_der,
|
||||
ffi::i2d_ECDSA_SIG
|
||||
}
|
||||
|
||||
/// Verifies if the signature is a valid ECDSA signature using the given public key.
|
||||
#[corresponds(ECDSA_do_verify)]
|
||||
pub fn verify<T>(&self, data: &[u8], eckey: &EcKeyRef<T>) -> Result<bool, ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
unsafe {
|
||||
assert!(data.len() <= c_int::max_value() as usize);
|
||||
cvt_n(ffi::ECDSA_do_verify(
|
||||
data.as_ptr(),
|
||||
data.len() as c_int,
|
||||
self.as_ptr(),
|
||||
eckey.as_ptr(),
|
||||
))
|
||||
.map(|x| x == 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns internal component: `r` of an `EcdsaSig`. (See X9.62 or FIPS 186-2)
|
||||
#[corresponds(ECDSA_SIG_get0)]
|
||||
pub fn r(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut r = ptr::null();
|
||||
ECDSA_SIG_get0(self.as_ptr(), &mut r, ptr::null_mut());
|
||||
BigNumRef::from_const_ptr(r)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns internal components: `s` of an `EcdsaSig`. (See X9.62 or FIPS 186-2)
|
||||
#[corresponds(ECDSA_SIG_get0)]
|
||||
pub fn s(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut s = ptr::null();
|
||||
ECDSA_SIG_get0(self.as_ptr(), ptr::null_mut(), &mut s);
|
||||
BigNumRef::from_const_ptr(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273))] {
|
||||
use ffi::{ECDSA_SIG_set0, ECDSA_SIG_get0};
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn ECDSA_SIG_set0(
|
||||
sig: *mut ffi::ECDSA_SIG,
|
||||
r: *mut ffi::BIGNUM,
|
||||
s: *mut ffi::BIGNUM,
|
||||
) -> c_int {
|
||||
if r.is_null() || s.is_null() {
|
||||
return 0;
|
||||
}
|
||||
ffi::BN_clear_free((*sig).r);
|
||||
ffi::BN_clear_free((*sig).s);
|
||||
(*sig).r = r;
|
||||
(*sig).s = s;
|
||||
1
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn ECDSA_SIG_get0(
|
||||
sig: *const ffi::ECDSA_SIG,
|
||||
pr: *mut *const ffi::BIGNUM,
|
||||
ps: *mut *const ffi::BIGNUM)
|
||||
{
|
||||
if !pr.is_null() {
|
||||
(*pr) = (*sig).r;
|
||||
}
|
||||
if !ps.is_null() {
|
||||
(*ps) = (*sig).s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::ec::EcGroup;
|
||||
use crate::ec::EcKey;
|
||||
use crate::nid::Nid;
|
||||
use crate::pkey::{Private, Public};
|
||||
|
||||
fn get_public_key(group: &EcGroup, x: &EcKey<Private>) -> Result<EcKey<Public>, ErrorStack> {
|
||||
EcKey::from_public_key(group, x.public_key())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(osslconf = "OPENSSL_NO_EC2M", ignore)]
|
||||
fn sign_and_verify() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME192V1).unwrap();
|
||||
let private_key = EcKey::generate(&group).unwrap();
|
||||
let public_key = get_public_key(&group, &private_key).unwrap();
|
||||
|
||||
let private_key2 = EcKey::generate(&group).unwrap();
|
||||
let public_key2 = get_public_key(&group, &private_key2).unwrap();
|
||||
|
||||
let data = String::from("hello");
|
||||
let res = EcdsaSig::sign(data.as_bytes(), &private_key).unwrap();
|
||||
|
||||
// Signature can be verified using the correct data & correct public key
|
||||
let verification = res.verify(data.as_bytes(), &public_key).unwrap();
|
||||
assert!(verification);
|
||||
|
||||
// Signature will not be verified using the incorrect data but the correct public key
|
||||
let verification2 = res
|
||||
.verify(String::from("hello2").as_bytes(), &public_key)
|
||||
.unwrap();
|
||||
assert!(!verification2);
|
||||
|
||||
// Signature will not be verified using the correct data but the incorrect public key
|
||||
let verification3 = res.verify(data.as_bytes(), &public_key2).unwrap();
|
||||
assert!(!verification3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(osslconf = "OPENSSL_NO_EC2M", ignore)]
|
||||
fn check_private_components() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME192V1).unwrap();
|
||||
let private_key = EcKey::generate(&group).unwrap();
|
||||
let public_key = get_public_key(&group, &private_key).unwrap();
|
||||
let data = String::from("hello");
|
||||
let res = EcdsaSig::sign(data.as_bytes(), &private_key).unwrap();
|
||||
|
||||
let verification = res.verify(data.as_bytes(), &public_key).unwrap();
|
||||
assert!(verification);
|
||||
|
||||
let r = res.r().to_owned().unwrap();
|
||||
let s = res.s().to_owned().unwrap();
|
||||
|
||||
let res2 = EcdsaSig::from_private_components(r, s).unwrap();
|
||||
let verification2 = res2.verify(data.as_bytes(), &public_key).unwrap();
|
||||
assert!(verification2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(osslconf = "OPENSSL_NO_EC2M", ignore)]
|
||||
fn serialize_deserialize() {
|
||||
let group = EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
|
||||
let private_key = EcKey::generate(&group).unwrap();
|
||||
let public_key = get_public_key(&group, &private_key).unwrap();
|
||||
|
||||
let data = String::from("hello");
|
||||
let res = EcdsaSig::sign(data.as_bytes(), &private_key).unwrap();
|
||||
|
||||
let der = res.to_der().unwrap();
|
||||
let sig = EcdsaSig::from_der(&der).unwrap();
|
||||
|
||||
let verification = sig.verify(data.as_bytes(), &public_key).unwrap();
|
||||
assert!(verification);
|
||||
}
|
||||
}
|
||||
578
zeroidc/vendor/openssl/src/encrypt.rs
vendored
Normal file
578
zeroidc/vendor/openssl/src/encrypt.rs
vendored
Normal file
@@ -0,0 +1,578 @@
|
||||
//! Message encryption.
|
||||
//!
|
||||
//! The [`Encrypter`] allows for encryption of data given a public key. The [`Decrypter`] can be
|
||||
//! used with the corresponding private key to decrypt the data.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Encrypt and decrypt data given an RSA keypair:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::encrypt::{Encrypter, Decrypter};
|
||||
//! use openssl::rsa::{Rsa, Padding};
|
||||
//! use openssl::pkey::PKey;
|
||||
//!
|
||||
//! // Generate a keypair
|
||||
//! let keypair = Rsa::generate(2048).unwrap();
|
||||
//! let keypair = PKey::from_rsa(keypair).unwrap();
|
||||
//!
|
||||
//! let data = b"hello, world!";
|
||||
//!
|
||||
//! // Encrypt the data with RSA PKCS1
|
||||
//! let mut encrypter = Encrypter::new(&keypair).unwrap();
|
||||
//! encrypter.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
//! // Create an output buffer
|
||||
//! let buffer_len = encrypter.encrypt_len(data).unwrap();
|
||||
//! let mut encrypted = vec![0; buffer_len];
|
||||
//! // Encrypt and truncate the buffer
|
||||
//! let encrypted_len = encrypter.encrypt(data, &mut encrypted).unwrap();
|
||||
//! encrypted.truncate(encrypted_len);
|
||||
//!
|
||||
//! // Decrypt the data
|
||||
//! let mut decrypter = Decrypter::new(&keypair).unwrap();
|
||||
//! decrypter.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
//! // Create an output buffer
|
||||
//! let buffer_len = decrypter.decrypt_len(&encrypted).unwrap();
|
||||
//! let mut decrypted = vec![0; buffer_len];
|
||||
//! // Encrypt and truncate the buffer
|
||||
//! let decrypted_len = decrypter.decrypt(&encrypted, &mut decrypted).unwrap();
|
||||
//! decrypted.truncate(decrypted_len);
|
||||
//! assert_eq!(&*decrypted, data);
|
||||
//! ```
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
use libc::{c_int, c_void};
|
||||
use std::{marker::PhantomData, ptr};
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::pkey::{HasPrivate, HasPublic, PKeyRef};
|
||||
use crate::rsa::Padding;
|
||||
use crate::{cvt, cvt_p};
|
||||
use foreign_types::ForeignTypeRef;
|
||||
|
||||
/// A type which encrypts data.
|
||||
pub struct Encrypter<'a> {
|
||||
pctx: *mut ffi::EVP_PKEY_CTX,
|
||||
_p: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
unsafe impl<'a> Sync for Encrypter<'a> {}
|
||||
unsafe impl<'a> Send for Encrypter<'a> {}
|
||||
|
||||
impl<'a> Drop for Encrypter<'a> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::EVP_PKEY_CTX_free(self.pctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Encrypter<'a> {
|
||||
/// Creates a new `Encrypter`.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_PKEY_encrypt_init`].
|
||||
///
|
||||
/// [`EVP_PKEY_encrypt_init`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt_init.html
|
||||
pub fn new<T>(pkey: &'a PKeyRef<T>) -> Result<Encrypter<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
let pctx = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?;
|
||||
let r = ffi::EVP_PKEY_encrypt_init(pctx);
|
||||
if r != 1 {
|
||||
ffi::EVP_PKEY_CTX_free(pctx);
|
||||
return Err(ErrorStack::get());
|
||||
}
|
||||
|
||||
Ok(Encrypter {
|
||||
pctx,
|
||||
_p: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the RSA padding mode in use.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`.
|
||||
pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
|
||||
unsafe {
|
||||
let mut pad = 0;
|
||||
cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad))
|
||||
.map(|_| Padding::from_raw(pad))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA padding mode.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_padding`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_padding`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_CTX_set_rsa_padding.html
|
||||
pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
|
||||
self.pctx,
|
||||
padding.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA MGF1 algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html
|
||||
pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
|
||||
self.pctx,
|
||||
md.as_ptr() as *mut _,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA OAEP algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_oaep_md`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_oaep_md`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_rsa_oaep_md.html
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
pub fn set_rsa_oaep_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
|
||||
self.pctx,
|
||||
md.as_ptr() as *mut _,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA OAEP label.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set0_rsa_oaep_label`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set0_rsa_oaep_label`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set0_rsa_oaep_label.html
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
let p = cvt_p(ffi::OPENSSL_malloc(label.len() as _))?;
|
||||
ptr::copy_nonoverlapping(label.as_ptr(), p as *mut u8, label.len());
|
||||
|
||||
cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(
|
||||
self.pctx,
|
||||
p as *mut c_void,
|
||||
label.len() as c_int,
|
||||
))
|
||||
.map(|_| ())
|
||||
.map_err(|e| {
|
||||
ffi::OPENSSL_free(p);
|
||||
e
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs public key encryption.
|
||||
///
|
||||
/// In order to know the size needed for the output buffer, use [`encrypt_len`](Encrypter::encrypt_len).
|
||||
/// Note that the length of the output buffer can be greater of the length of the encoded data.
|
||||
/// ```
|
||||
/// # use openssl::{
|
||||
/// # encrypt::Encrypter,
|
||||
/// # pkey::PKey,
|
||||
/// # rsa::{Rsa, Padding},
|
||||
/// # };
|
||||
/// #
|
||||
/// # let key = include_bytes!("../test/rsa.pem");
|
||||
/// # let private_key = Rsa::private_key_from_pem(key).unwrap();
|
||||
/// # let pkey = PKey::from_rsa(private_key).unwrap();
|
||||
/// # let input = b"hello world".to_vec();
|
||||
/// #
|
||||
/// let mut encrypter = Encrypter::new(&pkey).unwrap();
|
||||
/// encrypter.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
///
|
||||
/// // Get the length of the output buffer
|
||||
/// let buffer_len = encrypter.encrypt_len(&input).unwrap();
|
||||
/// let mut encoded = vec![0u8; buffer_len];
|
||||
///
|
||||
/// // Encode the data and get its length
|
||||
/// let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
|
||||
///
|
||||
/// // Use only the part of the buffer with the encoded data
|
||||
/// let encoded = &encoded[..encoded_len];
|
||||
/// ```
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_encrypt`].
|
||||
///
|
||||
/// [`EVP_PKEY_encrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html
|
||||
pub fn encrypt(&self, from: &[u8], to: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
let mut written = to.len();
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_encrypt(
|
||||
self.pctx,
|
||||
to.as_mut_ptr(),
|
||||
&mut written,
|
||||
from.as_ptr(),
|
||||
from.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
/// Gets the size of the buffer needed to encrypt the input data.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_encrypt`] called with a null pointer as output argument.
|
||||
///
|
||||
/// [`EVP_PKEY_encrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html
|
||||
pub fn encrypt_len(&self, from: &[u8]) -> Result<usize, ErrorStack> {
|
||||
let mut written = 0;
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_encrypt(
|
||||
self.pctx,
|
||||
ptr::null_mut(),
|
||||
&mut written,
|
||||
from.as_ptr(),
|
||||
from.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(written)
|
||||
}
|
||||
}
|
||||
|
||||
/// A type which decrypts data.
|
||||
pub struct Decrypter<'a> {
|
||||
pctx: *mut ffi::EVP_PKEY_CTX,
|
||||
_p: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
unsafe impl<'a> Sync for Decrypter<'a> {}
|
||||
unsafe impl<'a> Send for Decrypter<'a> {}
|
||||
|
||||
impl<'a> Drop for Decrypter<'a> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::EVP_PKEY_CTX_free(self.pctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Decrypter<'a> {
|
||||
/// Creates a new `Decrypter`.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_PKEY_decrypt_init`].
|
||||
///
|
||||
/// [`EVP_PKEY_decrypt_init`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_decrypt_init.html
|
||||
pub fn new<T>(pkey: &'a PKeyRef<T>) -> Result<Decrypter<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
let pctx = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?;
|
||||
let r = ffi::EVP_PKEY_decrypt_init(pctx);
|
||||
if r != 1 {
|
||||
ffi::EVP_PKEY_CTX_free(pctx);
|
||||
return Err(ErrorStack::get());
|
||||
}
|
||||
|
||||
Ok(Decrypter {
|
||||
pctx,
|
||||
_p: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the RSA padding mode in use.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`.
|
||||
pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
|
||||
unsafe {
|
||||
let mut pad = 0;
|
||||
cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad))
|
||||
.map(|_| Padding::from_raw(pad))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA padding mode.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_padding`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_padding`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_CTX_set_rsa_padding.html
|
||||
pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
|
||||
self.pctx,
|
||||
padding.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA MGF1 algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html
|
||||
pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
|
||||
self.pctx,
|
||||
md.as_ptr() as *mut _,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA OAEP algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_oaep_md`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_oaep_md`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_rsa_oaep_md.html
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
pub fn set_rsa_oaep_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
|
||||
self.pctx,
|
||||
md.as_ptr() as *mut _,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA OAEP label.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set0_rsa_oaep_label`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set0_rsa_oaep_label`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set0_rsa_oaep_label.html
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
let p = cvt_p(ffi::OPENSSL_malloc(label.len() as _))?;
|
||||
ptr::copy_nonoverlapping(label.as_ptr(), p as *mut u8, label.len());
|
||||
|
||||
cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(
|
||||
self.pctx,
|
||||
p as *mut c_void,
|
||||
label.len() as c_int,
|
||||
))
|
||||
.map(|_| ())
|
||||
.map_err(|e| {
|
||||
ffi::OPENSSL_free(p);
|
||||
e
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs public key decryption.
|
||||
///
|
||||
/// In order to know the size needed for the output buffer, use [`decrypt_len`](Decrypter::decrypt_len).
|
||||
/// Note that the length of the output buffer can be greater of the length of the decoded data.
|
||||
/// ```
|
||||
/// # use openssl::{
|
||||
/// # encrypt::Decrypter,
|
||||
/// # pkey::PKey,
|
||||
/// # rsa::{Rsa, Padding},
|
||||
/// # };
|
||||
/// #
|
||||
/// # const INPUT: &[u8] = b"\
|
||||
/// # \x26\xa1\xc1\x13\xc5\x7f\xb4\x9f\xa0\xb4\xde\x61\x5e\x2e\xc6\xfb\x76\x5c\xd1\x2b\x5f\
|
||||
/// # \x1d\x36\x60\xfa\xf8\xe8\xb3\x21\xf4\x9c\x70\xbc\x03\xea\xea\xac\xce\x4b\xb3\xf6\x45\
|
||||
/// # \xcc\xb3\x80\x9e\xa8\xf7\xc3\x5d\x06\x12\x7a\xa3\x0c\x30\x67\xf1\xe7\x94\x6c\xf6\x26\
|
||||
/// # \xac\x28\x17\x59\x69\xe1\xdc\xed\x7e\xc0\xe9\x62\x57\x49\xce\xdd\x13\x07\xde\x18\x03\
|
||||
/// # \x0f\x9d\x61\x65\xb9\x23\x8c\x78\x4b\xad\x23\x49\x75\x47\x64\xa0\xa0\xa2\x90\xc1\x49\
|
||||
/// # \x1b\x05\x24\xc2\xe9\x2c\x0d\x49\x78\x72\x61\x72\xed\x8b\x6f\x8a\xe8\xca\x05\x5c\x58\
|
||||
/// # \xd6\x95\xd6\x7b\xe3\x2d\x0d\xaa\x3e\x6d\x3c\x9a\x1c\x1d\xb4\x6c\x42\x9d\x9a\x82\x55\
|
||||
/// # \xd9\xde\xc8\x08\x7b\x17\xac\xd7\xaf\x86\x7b\x69\x9e\x3c\xf4\x5e\x1c\x39\x52\x6d\x62\
|
||||
/// # \x50\x51\xbd\xa6\xc8\x4e\xe9\x34\xf0\x37\x0d\xa9\xa9\x77\xe6\xf5\xc2\x47\x2d\xa8\xee\
|
||||
/// # \x3f\x69\x78\xff\xa9\xdc\x70\x22\x20\x9a\x5c\x9b\x70\x15\x90\xd3\xb4\x0e\x54\x9e\x48\
|
||||
/// # \xed\xb6\x2c\x88\xfc\xb4\xa9\x37\x10\xfa\x71\xb2\xec\x75\xe7\xe7\x0e\xf4\x60\x2c\x7b\
|
||||
/// # \x58\xaf\xa0\x53\xbd\x24\xf1\x12\xe3\x2e\x99\x25\x0a\x54\x54\x9d\xa1\xdb\xca\x41\x85\
|
||||
/// # \xf4\x62\x78\x64";
|
||||
/// #
|
||||
/// # let key = include_bytes!("../test/rsa.pem");
|
||||
/// # let private_key = Rsa::private_key_from_pem(key).unwrap();
|
||||
/// # let pkey = PKey::from_rsa(private_key).unwrap();
|
||||
/// # let input = INPUT.to_vec();
|
||||
/// #
|
||||
/// let mut decrypter = Decrypter::new(&pkey).unwrap();
|
||||
/// decrypter.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
///
|
||||
/// // Get the length of the output buffer
|
||||
/// let buffer_len = decrypter.decrypt_len(&input).unwrap();
|
||||
/// let mut decoded = vec![0u8; buffer_len];
|
||||
///
|
||||
/// // Decrypt the data and get its length
|
||||
/// let decoded_len = decrypter.decrypt(&input, &mut decoded).unwrap();
|
||||
///
|
||||
/// // Use only the part of the buffer with the decrypted data
|
||||
/// let decoded = &decoded[..decoded_len];
|
||||
/// ```
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_decrypt`].
|
||||
///
|
||||
/// [`EVP_PKEY_decrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_decrypt.html
|
||||
pub fn decrypt(&self, from: &[u8], to: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
let mut written = to.len();
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_decrypt(
|
||||
self.pctx,
|
||||
to.as_mut_ptr(),
|
||||
&mut written,
|
||||
from.as_ptr(),
|
||||
from.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
/// Gets the size of the buffer needed to decrypt the input data.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_decrypt`] called with a null pointer as output argument.
|
||||
///
|
||||
/// [`EVP_PKEY_decrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_decrypt.html
|
||||
pub fn decrypt_len(&self, from: &[u8]) -> Result<usize, ErrorStack> {
|
||||
let mut written = 0;
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_decrypt(
|
||||
self.pctx,
|
||||
ptr::null_mut(),
|
||||
&mut written,
|
||||
from.as_ptr(),
|
||||
from.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(written)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use hex::FromHex;
|
||||
|
||||
use crate::encrypt::{Decrypter, Encrypter};
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::pkey::PKey;
|
||||
use crate::rsa::{Padding, Rsa};
|
||||
|
||||
const INPUT: &str =
|
||||
"65794a68624763694f694a53557a49314e694a392e65794a7063334d694f694a71623255694c41304b49434a6c\
|
||||
654841694f6a457a4d4441344d546b7a4f44417344516f67496d6830644841364c79396c654746746347786c4c\
|
||||
6d4e76625339706331397962323930496a7030636e566c6651";
|
||||
|
||||
#[test]
|
||||
fn rsa_encrypt_decrypt() {
|
||||
let key = include_bytes!("../test/rsa.pem");
|
||||
let private_key = Rsa::private_key_from_pem(key).unwrap();
|
||||
let pkey = PKey::from_rsa(private_key).unwrap();
|
||||
|
||||
let mut encrypter = Encrypter::new(&pkey).unwrap();
|
||||
encrypter.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
let input = Vec::from_hex(INPUT).unwrap();
|
||||
let buffer_len = encrypter.encrypt_len(&input).unwrap();
|
||||
let mut encoded = vec![0u8; buffer_len];
|
||||
let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
|
||||
let encoded = &encoded[..encoded_len];
|
||||
|
||||
let mut decrypter = Decrypter::new(&pkey).unwrap();
|
||||
decrypter.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
let buffer_len = decrypter.decrypt_len(encoded).unwrap();
|
||||
let mut decoded = vec![0u8; buffer_len];
|
||||
let decoded_len = decrypter.decrypt(encoded, &mut decoded).unwrap();
|
||||
let decoded = &decoded[..decoded_len];
|
||||
|
||||
assert_eq!(decoded, &*input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
fn rsa_encrypt_decrypt_with_sha256() {
|
||||
let key = include_bytes!("../test/rsa.pem");
|
||||
let private_key = Rsa::private_key_from_pem(key).unwrap();
|
||||
let pkey = PKey::from_rsa(private_key).unwrap();
|
||||
|
||||
let md = MessageDigest::sha256();
|
||||
|
||||
let mut encrypter = Encrypter::new(&pkey).unwrap();
|
||||
encrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
|
||||
encrypter.set_rsa_oaep_md(md).unwrap();
|
||||
encrypter.set_rsa_mgf1_md(md).unwrap();
|
||||
let input = Vec::from_hex(INPUT).unwrap();
|
||||
let buffer_len = encrypter.encrypt_len(&input).unwrap();
|
||||
let mut encoded = vec![0u8; buffer_len];
|
||||
let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
|
||||
let encoded = &encoded[..encoded_len];
|
||||
|
||||
let mut decrypter = Decrypter::new(&pkey).unwrap();
|
||||
decrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
|
||||
decrypter.set_rsa_oaep_md(md).unwrap();
|
||||
decrypter.set_rsa_mgf1_md(md).unwrap();
|
||||
let buffer_len = decrypter.decrypt_len(encoded).unwrap();
|
||||
let mut decoded = vec![0u8; buffer_len];
|
||||
let decoded_len = decrypter.decrypt(encoded, &mut decoded).unwrap();
|
||||
let decoded = &decoded[..decoded_len];
|
||||
|
||||
assert_eq!(decoded, &*input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
fn rsa_encrypt_decrypt_oaep_label() {
|
||||
let key = include_bytes!("../test/rsa.pem");
|
||||
let private_key = Rsa::private_key_from_pem(key).unwrap();
|
||||
let pkey = PKey::from_rsa(private_key).unwrap();
|
||||
|
||||
let mut encrypter = Encrypter::new(&pkey).unwrap();
|
||||
encrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
|
||||
encrypter.set_rsa_oaep_label(b"test_oaep_label").unwrap();
|
||||
let input = Vec::from_hex(INPUT).unwrap();
|
||||
let buffer_len = encrypter.encrypt_len(&input).unwrap();
|
||||
let mut encoded = vec![0u8; buffer_len];
|
||||
let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
|
||||
let encoded = &encoded[..encoded_len];
|
||||
|
||||
let mut decrypter = Decrypter::new(&pkey).unwrap();
|
||||
decrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
|
||||
decrypter.set_rsa_oaep_label(b"test_oaep_label").unwrap();
|
||||
let buffer_len = decrypter.decrypt_len(encoded).unwrap();
|
||||
let mut decoded = vec![0u8; buffer_len];
|
||||
let decoded_len = decrypter.decrypt(encoded, &mut decoded).unwrap();
|
||||
let decoded = &decoded[..decoded_len];
|
||||
|
||||
assert_eq!(decoded, &*input);
|
||||
|
||||
decrypter.set_rsa_oaep_label(b"wrong_oaep_label").unwrap();
|
||||
let buffer_len = decrypter.decrypt_len(encoded).unwrap();
|
||||
let mut decoded = vec![0u8; buffer_len];
|
||||
|
||||
assert!(decrypter.decrypt(encoded, &mut decoded).is_err());
|
||||
}
|
||||
}
|
||||
181
zeroidc/vendor/openssl/src/envelope.rs
vendored
Normal file
181
zeroidc/vendor/openssl/src/envelope.rs
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
//! Envelope encryption.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::rsa::Rsa;
|
||||
//! use openssl::envelope::Seal;
|
||||
//! use openssl::pkey::PKey;
|
||||
//! use openssl::symm::Cipher;
|
||||
//!
|
||||
//! let rsa = Rsa::generate(2048).unwrap();
|
||||
//! let key = PKey::from_rsa(rsa).unwrap();
|
||||
//!
|
||||
//! let cipher = Cipher::aes_256_cbc();
|
||||
//! let mut seal = Seal::new(cipher, &[key]).unwrap();
|
||||
//!
|
||||
//! let secret = b"My secret message";
|
||||
//! let mut encrypted = vec![0; secret.len() + cipher.block_size()];
|
||||
//!
|
||||
//! let mut enc_len = seal.update(secret, &mut encrypted).unwrap();
|
||||
//! enc_len += seal.finalize(&mut encrypted[enc_len..]).unwrap();
|
||||
//! encrypted.truncate(enc_len);
|
||||
//! ```
|
||||
use crate::cipher::CipherRef;
|
||||
use crate::cipher_ctx::CipherCtx;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef};
|
||||
use crate::symm::Cipher;
|
||||
use foreign_types::ForeignTypeRef;
|
||||
|
||||
/// Represents an EVP_Seal context.
|
||||
pub struct Seal {
|
||||
ctx: CipherCtx,
|
||||
iv: Option<Vec<u8>>,
|
||||
enc_keys: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl Seal {
|
||||
/// Creates a new `Seal`.
|
||||
pub fn new<T>(cipher: Cipher, pub_keys: &[PKey<T>]) -> Result<Seal, ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
let mut iv = cipher.iv_len().map(|len| vec![0; len]);
|
||||
let mut enc_keys = vec![vec![]; pub_keys.len()];
|
||||
|
||||
let mut ctx = CipherCtx::new()?;
|
||||
ctx.seal_init(
|
||||
Some(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) }),
|
||||
pub_keys,
|
||||
&mut enc_keys,
|
||||
iv.as_deref_mut(),
|
||||
)?;
|
||||
|
||||
Ok(Seal { ctx, iv, enc_keys })
|
||||
}
|
||||
|
||||
/// Returns the initialization vector, if the cipher uses one.
|
||||
#[allow(clippy::option_as_ref_deref)]
|
||||
pub fn iv(&self) -> Option<&[u8]> {
|
||||
self.iv.as_ref().map(|v| &**v)
|
||||
}
|
||||
|
||||
/// Returns the encrypted keys.
|
||||
pub fn encrypted_keys(&self) -> &[Vec<u8>] {
|
||||
&self.enc_keys
|
||||
}
|
||||
|
||||
/// Feeds data from `input` through the cipher, writing encrypted bytes into `output`.
|
||||
///
|
||||
/// The number of bytes written to `output` is returned. Note that this may
|
||||
/// not be equal to the length of `input`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `output.len() < input.len() + block_size` where `block_size` is
|
||||
/// the block size of the cipher (see `Cipher::block_size`), or if
|
||||
/// `output.len() > c_int::max_value()`.
|
||||
pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
self.ctx.cipher_update(input, Some(output))
|
||||
}
|
||||
|
||||
/// Finishes the encryption process, writing any remaining data to `output`.
|
||||
///
|
||||
/// The number of bytes written to `output` is returned.
|
||||
///
|
||||
/// `update` should not be called after this method.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `output` is less than the cipher's block size.
|
||||
pub fn finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
self.ctx.cipher_final(output)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an EVP_Open context.
|
||||
pub struct Open {
|
||||
ctx: CipherCtx,
|
||||
}
|
||||
|
||||
impl Open {
|
||||
/// Creates a new `Open`.
|
||||
pub fn new<T>(
|
||||
cipher: Cipher,
|
||||
priv_key: &PKeyRef<T>,
|
||||
iv: Option<&[u8]>,
|
||||
encrypted_key: &[u8],
|
||||
) -> Result<Open, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
let mut ctx = CipherCtx::new()?;
|
||||
ctx.open_init(
|
||||
Some(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) }),
|
||||
encrypted_key,
|
||||
iv,
|
||||
Some(priv_key),
|
||||
)?;
|
||||
|
||||
Ok(Open { ctx })
|
||||
}
|
||||
|
||||
/// Feeds data from `input` through the cipher, writing decrypted bytes into `output`.
|
||||
///
|
||||
/// The number of bytes written to `output` is returned. Note that this may
|
||||
/// not be equal to the length of `input`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `output.len() < input.len() + block_size` where
|
||||
/// `block_size` is the block size of the cipher (see `Cipher::block_size`),
|
||||
/// or if `output.len() > c_int::max_value()`.
|
||||
pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
self.ctx.cipher_update(input, Some(output))
|
||||
}
|
||||
|
||||
/// Finishes the decryption process, writing any remaining data to `output`.
|
||||
///
|
||||
/// The number of bytes written to `output` is returned.
|
||||
///
|
||||
/// `update` should not be called after this method.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `output` is less than the cipher's block size.
|
||||
pub fn finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
self.ctx.cipher_final(output)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::pkey::PKey;
|
||||
use crate::symm::Cipher;
|
||||
|
||||
#[test]
|
||||
fn public_encrypt_private_decrypt() {
|
||||
let private_pem = include_bytes!("../test/rsa.pem");
|
||||
let public_pem = include_bytes!("../test/rsa.pem.pub");
|
||||
let private_key = PKey::private_key_from_pem(private_pem).unwrap();
|
||||
let public_key = PKey::public_key_from_pem(public_pem).unwrap();
|
||||
let cipher = Cipher::aes_256_cbc();
|
||||
let secret = b"My secret message";
|
||||
|
||||
let mut seal = Seal::new(cipher, &[public_key]).unwrap();
|
||||
let mut encrypted = vec![0; secret.len() + cipher.block_size()];
|
||||
let mut enc_len = seal.update(secret, &mut encrypted).unwrap();
|
||||
enc_len += seal.finalize(&mut encrypted[enc_len..]).unwrap();
|
||||
let iv = seal.iv();
|
||||
let encrypted_key = &seal.encrypted_keys()[0];
|
||||
|
||||
let mut open = Open::new(cipher, &private_key, iv, encrypted_key).unwrap();
|
||||
let mut decrypted = vec![0; enc_len + cipher.block_size()];
|
||||
let mut dec_len = open.update(&encrypted[..enc_len], &mut decrypted).unwrap();
|
||||
dec_len += open.finalize(&mut decrypted[dec_len..]).unwrap();
|
||||
|
||||
assert_eq!(&secret[..], &decrypted[..dec_len]);
|
||||
}
|
||||
}
|
||||
326
zeroidc/vendor/openssl/src/error.rs
vendored
Normal file
326
zeroidc/vendor/openssl/src/error.rs
vendored
Normal file
@@ -0,0 +1,326 @@
|
||||
//! Errors returned by OpenSSL library.
|
||||
//!
|
||||
//! OpenSSL errors are stored in an `ErrorStack`. Most methods in the crate
|
||||
//! returns a `Result<T, ErrorStack>` type.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::error::ErrorStack;
|
||||
//! use openssl::bn::BigNum;
|
||||
//!
|
||||
//! let an_error = BigNum::from_dec_str("Cannot parse letters");
|
||||
//! match an_error {
|
||||
//! Ok(_) => (),
|
||||
//! Err(e) => println!("Parsing Error: {:?}", e),
|
||||
//! }
|
||||
//! ```
|
||||
use cfg_if::cfg_if;
|
||||
use libc::{c_char, c_int, c_ulong};
|
||||
use std::borrow::Cow;
|
||||
use std::error;
|
||||
use std::ffi::CStr;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::ptr;
|
||||
use std::str;
|
||||
|
||||
/// Collection of [`Error`]s from OpenSSL.
|
||||
///
|
||||
/// [`Error`]: struct.Error.html
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ErrorStack(Vec<Error>);
|
||||
|
||||
impl ErrorStack {
|
||||
/// Returns the contents of the OpenSSL error stack.
|
||||
pub fn get() -> ErrorStack {
|
||||
let mut vec = vec![];
|
||||
while let Some(err) = Error::get() {
|
||||
vec.push(err);
|
||||
}
|
||||
ErrorStack(vec)
|
||||
}
|
||||
|
||||
/// Pushes the errors back onto the OpenSSL error stack.
|
||||
pub fn put(&self) {
|
||||
for error in self.errors() {
|
||||
error.put();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorStack {
|
||||
/// Returns the errors in the stack.
|
||||
pub fn errors(&self) -> &[Error] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ErrorStack {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.0.is_empty() {
|
||||
return fmt.write_str("OpenSSL error");
|
||||
}
|
||||
|
||||
let mut first = true;
|
||||
for err in &self.0 {
|
||||
if !first {
|
||||
fmt.write_str(", ")?;
|
||||
}
|
||||
write!(fmt, "{}", err)?;
|
||||
first = false;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for ErrorStack {}
|
||||
|
||||
impl From<ErrorStack> for io::Error {
|
||||
fn from(e: ErrorStack) -> io::Error {
|
||||
io::Error::new(io::ErrorKind::Other, e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ErrorStack> for fmt::Error {
|
||||
fn from(_: ErrorStack) -> fmt::Error {
|
||||
fmt::Error
|
||||
}
|
||||
}
|
||||
|
||||
/// An error reported from OpenSSL.
|
||||
#[derive(Clone)]
|
||||
pub struct Error {
|
||||
code: c_ulong,
|
||||
file: *const c_char,
|
||||
line: c_int,
|
||||
func: *const c_char,
|
||||
data: Option<Cow<'static, str>>,
|
||||
}
|
||||
|
||||
unsafe impl Sync for Error {}
|
||||
unsafe impl Send for Error {}
|
||||
|
||||
impl Error {
|
||||
/// Returns the first error on the OpenSSL error stack.
|
||||
pub fn get() -> Option<Error> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
let mut file = ptr::null();
|
||||
let mut line = 0;
|
||||
let mut func = ptr::null();
|
||||
let mut data = ptr::null();
|
||||
let mut flags = 0;
|
||||
match ERR_get_error_all(&mut file, &mut line, &mut func, &mut data, &mut flags) {
|
||||
0 => None,
|
||||
code => {
|
||||
// The memory referenced by data is only valid until that slot is overwritten
|
||||
// in the error stack, so we'll need to copy it off if it's dynamic
|
||||
let data = if flags & ffi::ERR_TXT_STRING != 0 {
|
||||
let bytes = CStr::from_ptr(data as *const _).to_bytes();
|
||||
let data = str::from_utf8(bytes).unwrap();
|
||||
let data = if flags & ffi::ERR_TXT_MALLOCED != 0 {
|
||||
Cow::Owned(data.to_string())
|
||||
} else {
|
||||
Cow::Borrowed(data)
|
||||
};
|
||||
Some(data)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Some(Error {
|
||||
code,
|
||||
file,
|
||||
line,
|
||||
func,
|
||||
data,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pushes the error back onto the OpenSSL error stack.
|
||||
pub fn put(&self) {
|
||||
self.put_error();
|
||||
|
||||
unsafe {
|
||||
let data = match self.data {
|
||||
Some(Cow::Borrowed(data)) => Some((data.as_ptr() as *mut c_char, 0)),
|
||||
Some(Cow::Owned(ref data)) => {
|
||||
let ptr = ffi::CRYPTO_malloc(
|
||||
(data.len() + 1) as _,
|
||||
concat!(file!(), "\0").as_ptr() as _,
|
||||
line!() as _,
|
||||
) as *mut c_char;
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
ptr::copy_nonoverlapping(data.as_ptr(), ptr as *mut u8, data.len());
|
||||
*ptr.add(data.len()) = 0;
|
||||
Some((ptr, ffi::ERR_TXT_MALLOCED))
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
if let Some((ptr, flags)) = data {
|
||||
ffi::ERR_set_error_data(ptr, flags | ffi::ERR_TXT_STRING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl300)]
|
||||
fn put_error(&self) {
|
||||
unsafe {
|
||||
ffi::ERR_new();
|
||||
ffi::ERR_set_debug(self.file, self.line, self.func);
|
||||
ffi::ERR_set_error(
|
||||
ffi::ERR_GET_LIB(self.code),
|
||||
ffi::ERR_GET_REASON(self.code),
|
||||
ptr::null(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(ossl300))]
|
||||
fn put_error(&self) {
|
||||
unsafe {
|
||||
ffi::ERR_put_error(
|
||||
ffi::ERR_GET_LIB(self.code),
|
||||
ffi::ERR_GET_FUNC(self.code),
|
||||
ffi::ERR_GET_REASON(self.code),
|
||||
self.file,
|
||||
self.line,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the raw OpenSSL error code for this error.
|
||||
pub fn code(&self) -> c_ulong {
|
||||
self.code
|
||||
}
|
||||
|
||||
/// Returns the name of the library reporting the error, if available.
|
||||
pub fn library(&self) -> Option<&'static str> {
|
||||
unsafe {
|
||||
let cstr = ffi::ERR_lib_error_string(self.code);
|
||||
if cstr.is_null() {
|
||||
return None;
|
||||
}
|
||||
let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
|
||||
Some(str::from_utf8(bytes).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the name of the function reporting the error.
|
||||
pub fn function(&self) -> Option<&'static str> {
|
||||
unsafe {
|
||||
if self.func.is_null() {
|
||||
return None;
|
||||
}
|
||||
let bytes = CStr::from_ptr(self.func).to_bytes();
|
||||
Some(str::from_utf8(bytes).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the reason for the error.
|
||||
pub fn reason(&self) -> Option<&'static str> {
|
||||
unsafe {
|
||||
let cstr = ffi::ERR_reason_error_string(self.code);
|
||||
if cstr.is_null() {
|
||||
return None;
|
||||
}
|
||||
let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
|
||||
Some(str::from_utf8(bytes).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the name of the source file which encountered the error.
|
||||
pub fn file(&self) -> &'static str {
|
||||
unsafe {
|
||||
assert!(!self.file.is_null());
|
||||
let bytes = CStr::from_ptr(self.file as *const _).to_bytes();
|
||||
str::from_utf8(bytes).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the line in the source file which encountered the error.
|
||||
pub fn line(&self) -> u32 {
|
||||
self.line as u32
|
||||
}
|
||||
|
||||
/// Returns additional data describing the error.
|
||||
#[allow(clippy::option_as_ref_deref)]
|
||||
pub fn data(&self) -> Option<&str> {
|
||||
self.data.as_ref().map(|s| &**s)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Error {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut builder = fmt.debug_struct("Error");
|
||||
builder.field("code", &self.code());
|
||||
if let Some(library) = self.library() {
|
||||
builder.field("library", &library);
|
||||
}
|
||||
if let Some(function) = self.function() {
|
||||
builder.field("function", &function);
|
||||
}
|
||||
if let Some(reason) = self.reason() {
|
||||
builder.field("reason", &reason);
|
||||
}
|
||||
builder.field("file", &self.file());
|
||||
builder.field("line", &self.line());
|
||||
if let Some(data) = self.data() {
|
||||
builder.field("data", &data);
|
||||
}
|
||||
builder.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "error:{:08X}", self.code())?;
|
||||
match self.library() {
|
||||
Some(l) => write!(fmt, ":{}", l)?,
|
||||
None => write!(fmt, ":lib({})", ffi::ERR_GET_LIB(self.code()))?,
|
||||
}
|
||||
match self.function() {
|
||||
Some(f) => write!(fmt, ":{}", f)?,
|
||||
None => write!(fmt, ":func({})", ffi::ERR_GET_FUNC(self.code()))?,
|
||||
}
|
||||
match self.reason() {
|
||||
Some(r) => write!(fmt, ":{}", r)?,
|
||||
None => write!(fmt, ":reason({})", ffi::ERR_GET_REASON(self.code()))?,
|
||||
}
|
||||
write!(
|
||||
fmt,
|
||||
":{}:{}:{}",
|
||||
self.file(),
|
||||
self.line(),
|
||||
self.data().unwrap_or("")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl300)] {
|
||||
use ffi::ERR_get_error_all;
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe extern "C" fn ERR_get_error_all(
|
||||
file: *mut *const c_char,
|
||||
line: *mut c_int,
|
||||
func: *mut *const c_char,
|
||||
data: *mut *const c_char,
|
||||
flags: *mut c_int,
|
||||
) -> c_ulong {
|
||||
let code = ffi::ERR_get_error_line_data(file, line, data, flags);
|
||||
*func = ffi::ERR_func_error_string(code);
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
32
zeroidc/vendor/openssl/src/ex_data.rs
vendored
Normal file
32
zeroidc/vendor/openssl/src/ex_data.rs
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
use libc::c_int;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// A slot in a type's "extra data" structure.
|
||||
///
|
||||
/// It is parameterized over the type containing the extra data as well as the
|
||||
/// type of the data in the slot.
|
||||
pub struct Index<T, U>(c_int, PhantomData<(T, U)>);
|
||||
|
||||
impl<T, U> Copy for Index<T, U> {}
|
||||
|
||||
impl<T, U> Clone for Index<T, U> {
|
||||
fn clone(&self) -> Index<T, U> {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Index<T, U> {
|
||||
/// Creates an `Index` from a raw integer index.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that the index correctly maps to a `U` value stored in a `T`.
|
||||
pub unsafe fn from_raw(idx: c_int) -> Index<T, U> {
|
||||
Index(idx, PhantomData)
|
||||
}
|
||||
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
21
zeroidc/vendor/openssl/src/fips.rs
vendored
Normal file
21
zeroidc/vendor/openssl/src/fips.rs
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
//! FIPS 140-2 support.
|
||||
//!
|
||||
//! See [OpenSSL's documentation] for details.
|
||||
//!
|
||||
//! [OpenSSL's documentation]: https://www.openssl.org/docs/fips/UserGuide-2.0.pdf
|
||||
use crate::cvt;
|
||||
use crate::error::ErrorStack;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
/// Moves the library into or out of the FIPS 140-2 mode of operation.
|
||||
#[corresponds(FIPS_mode_set)]
|
||||
pub fn enable(enabled: bool) -> Result<(), ErrorStack> {
|
||||
ffi::init();
|
||||
unsafe { cvt(ffi::FIPS_mode_set(enabled as _)).map(|_| ()) }
|
||||
}
|
||||
|
||||
/// Determines if the library is running in the FIPS 140-2 mode of operation.
|
||||
#[corresponds(FIPS_mode)]
|
||||
pub fn enabled() -> bool {
|
||||
unsafe { ffi::FIPS_mode() != 0 }
|
||||
}
|
||||
665
zeroidc/vendor/openssl/src/hash.rs
vendored
Normal file
665
zeroidc/vendor/openssl/src/hash.rs
vendored
Normal file
@@ -0,0 +1,665 @@
|
||||
use cfg_if::cfg_if;
|
||||
use std::ffi::CString;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::ptr;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::nid::Nid;
|
||||
use crate::{cvt, cvt_p};
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl110)] {
|
||||
use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
|
||||
} else {
|
||||
use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub struct MessageDigest(*const ffi::EVP_MD);
|
||||
|
||||
impl MessageDigest {
|
||||
/// Creates a `MessageDigest` from a raw OpenSSL pointer.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure the pointer is valid.
|
||||
pub unsafe fn from_ptr(x: *const ffi::EVP_MD) -> Self {
|
||||
MessageDigest(x)
|
||||
}
|
||||
|
||||
/// Returns the `MessageDigest` corresponding to an `Nid`.
|
||||
///
|
||||
/// This corresponds to [`EVP_get_digestbynid`].
|
||||
///
|
||||
/// [`EVP_get_digestbynid`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_DigestInit.html
|
||||
pub fn from_nid(type_: Nid) -> Option<MessageDigest> {
|
||||
unsafe {
|
||||
let ptr = ffi::EVP_get_digestbynid(type_.as_raw());
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(MessageDigest(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `MessageDigest` corresponding to an algorithm name.
|
||||
///
|
||||
/// This corresponds to [`EVP_get_digestbyname`].
|
||||
///
|
||||
/// [`EVP_get_digestbyname`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_DigestInit.html
|
||||
pub fn from_name(name: &str) -> Option<MessageDigest> {
|
||||
ffi::init();
|
||||
let name = CString::new(name).ok()?;
|
||||
unsafe {
|
||||
let ptr = ffi::EVP_get_digestbyname(name.as_ptr());
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(MessageDigest(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn null() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_md_null()) }
|
||||
}
|
||||
|
||||
pub fn md5() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_md5()) }
|
||||
}
|
||||
|
||||
pub fn sha1() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_sha1()) }
|
||||
}
|
||||
|
||||
pub fn sha224() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_sha224()) }
|
||||
}
|
||||
|
||||
pub fn sha256() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_sha256()) }
|
||||
}
|
||||
|
||||
pub fn sha384() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_sha384()) }
|
||||
}
|
||||
|
||||
pub fn sha512() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_sha512()) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub fn sha3_224() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_sha3_224()) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub fn sha3_256() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_sha3_256()) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub fn sha3_384() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_sha3_384()) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub fn sha3_512() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_sha3_512()) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub fn shake_128() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_shake128()) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub fn shake_256() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_shake256()) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_RMD160"))]
|
||||
pub fn ripemd160() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_ripemd160()) }
|
||||
}
|
||||
|
||||
#[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
|
||||
pub fn sm3() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_sm3()) }
|
||||
}
|
||||
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_ptr(&self) -> *const ffi::EVP_MD {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// The size of the digest in bytes.
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn size(&self) -> usize {
|
||||
unsafe { ffi::EVP_MD_size(self.0) as usize }
|
||||
}
|
||||
|
||||
/// The name of the digest.
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn type_(&self) -> Nid {
|
||||
Nid::from_raw(unsafe { ffi::EVP_MD_type(self.0) })
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Sync for MessageDigest {}
|
||||
unsafe impl Send for MessageDigest {}
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
enum State {
|
||||
Reset,
|
||||
Updated,
|
||||
Finalized,
|
||||
}
|
||||
|
||||
use self::State::*;
|
||||
|
||||
/// Provides message digest (hash) computation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Calculate a hash in one go:
|
||||
///
|
||||
/// ```
|
||||
/// use openssl::hash::{hash, MessageDigest};
|
||||
///
|
||||
/// let data = b"\x42\xF4\x97\xE0";
|
||||
/// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2";
|
||||
/// let res = hash(MessageDigest::md5(), data).unwrap();
|
||||
/// assert_eq!(&*res, spec);
|
||||
/// ```
|
||||
///
|
||||
/// Supply the input in chunks:
|
||||
///
|
||||
/// ```
|
||||
/// use openssl::hash::{Hasher, MessageDigest};
|
||||
///
|
||||
/// let data = [b"\x42\xF4", b"\x97\xE0"];
|
||||
/// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2";
|
||||
/// let mut h = Hasher::new(MessageDigest::md5()).unwrap();
|
||||
/// h.update(data[0]).unwrap();
|
||||
/// h.update(data[1]).unwrap();
|
||||
/// let res = h.finish().unwrap();
|
||||
/// assert_eq!(&*res, spec);
|
||||
/// ```
|
||||
///
|
||||
/// Use an XOF hasher (OpenSSL 1.1.1+):
|
||||
///
|
||||
/// ```
|
||||
/// #[cfg(ossl111)]
|
||||
/// {
|
||||
/// use openssl::hash::{hash_xof, MessageDigest};
|
||||
///
|
||||
/// let data = b"\x41\x6c\x6c\x20\x79\x6f\x75\x72\x20\x62\x61\x73\x65\x20\x61\x72\x65\x20\x62\x65\x6c\x6f\x6e\x67\x20\x74\x6f\x20\x75\x73";
|
||||
/// let spec = b"\x49\xd0\x69\x7f\xf5\x08\x11\x1d\x8b\x84\xf1\x5e\x46\xda\xf1\x35";
|
||||
/// let mut buf = vec![0; 16];
|
||||
/// hash_xof(MessageDigest::shake_128(), data, buf.as_mut_slice()).unwrap();
|
||||
/// assert_eq!(buf, spec);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// Don't actually use MD5 and SHA-1 hashes, they're not secure anymore.
|
||||
///
|
||||
/// Don't ever hash passwords, use the functions in the `pkcs5` module or bcrypt/scrypt instead.
|
||||
///
|
||||
/// For extendable output functions (XOFs, i.e. SHAKE128/SHAKE256), you must use finish_xof instead
|
||||
/// of finish and provide a buf to store the hash. The hash will be as long as the buf.
|
||||
pub struct Hasher {
|
||||
ctx: *mut ffi::EVP_MD_CTX,
|
||||
md: *const ffi::EVP_MD,
|
||||
type_: MessageDigest,
|
||||
state: State,
|
||||
}
|
||||
|
||||
unsafe impl Sync for Hasher {}
|
||||
unsafe impl Send for Hasher {}
|
||||
|
||||
impl Hasher {
|
||||
/// Creates a new `Hasher` with the specified hash type.
|
||||
pub fn new(ty: MessageDigest) -> Result<Hasher, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
let ctx = unsafe { cvt_p(EVP_MD_CTX_new())? };
|
||||
|
||||
let mut h = Hasher {
|
||||
ctx,
|
||||
md: ty.as_ptr(),
|
||||
type_: ty,
|
||||
state: Finalized,
|
||||
};
|
||||
h.init()?;
|
||||
Ok(h)
|
||||
}
|
||||
|
||||
fn init(&mut self) -> Result<(), ErrorStack> {
|
||||
match self.state {
|
||||
Reset => return Ok(()),
|
||||
Updated => {
|
||||
self.finish()?;
|
||||
}
|
||||
Finalized => (),
|
||||
}
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestInit_ex(self.ctx, self.md, ptr::null_mut()))?;
|
||||
}
|
||||
self.state = Reset;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Feeds data into the hasher.
|
||||
pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
|
||||
if self.state == Finalized {
|
||||
self.init()?;
|
||||
}
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestUpdate(
|
||||
self.ctx,
|
||||
data.as_ptr() as *mut _,
|
||||
data.len(),
|
||||
))?;
|
||||
}
|
||||
self.state = Updated;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns the hash of the data written and resets the non-XOF hasher.
|
||||
pub fn finish(&mut self) -> Result<DigestBytes, ErrorStack> {
|
||||
if self.state == Finalized {
|
||||
self.init()?;
|
||||
}
|
||||
unsafe {
|
||||
let mut len = ffi::EVP_MAX_MD_SIZE;
|
||||
let mut buf = [0; ffi::EVP_MAX_MD_SIZE as usize];
|
||||
cvt(ffi::EVP_DigestFinal_ex(
|
||||
self.ctx,
|
||||
buf.as_mut_ptr(),
|
||||
&mut len,
|
||||
))?;
|
||||
self.state = Finalized;
|
||||
Ok(DigestBytes {
|
||||
buf,
|
||||
len: len as usize,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes the hash of the data into the supplied buf and resets the XOF hasher.
|
||||
/// The hash will be as long as the buf.
|
||||
#[cfg(ossl111)]
|
||||
pub fn finish_xof(&mut self, buf: &mut [u8]) -> Result<(), ErrorStack> {
|
||||
if self.state == Finalized {
|
||||
self.init()?;
|
||||
}
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestFinalXOF(
|
||||
self.ctx,
|
||||
buf.as_mut_ptr(),
|
||||
buf.len(),
|
||||
))?;
|
||||
self.state = Finalized;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for Hasher {
|
||||
#[inline]
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.update(buf)?;
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Hasher {
|
||||
fn clone(&self) -> Hasher {
|
||||
let ctx = unsafe {
|
||||
let ctx = EVP_MD_CTX_new();
|
||||
assert!(!ctx.is_null());
|
||||
let r = ffi::EVP_MD_CTX_copy_ex(ctx, self.ctx);
|
||||
assert_eq!(r, 1);
|
||||
ctx
|
||||
};
|
||||
Hasher {
|
||||
ctx,
|
||||
md: self.md,
|
||||
type_: self.type_,
|
||||
state: self.state,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Hasher {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
if self.state != Finalized {
|
||||
drop(self.finish());
|
||||
}
|
||||
EVP_MD_CTX_free(self.ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The resulting bytes of a digest.
|
||||
///
|
||||
/// This type derefs to a byte slice - it exists to avoid allocating memory to
|
||||
/// store the digest data.
|
||||
#[derive(Copy)]
|
||||
pub struct DigestBytes {
|
||||
pub(crate) buf: [u8; ffi::EVP_MAX_MD_SIZE as usize],
|
||||
pub(crate) len: usize,
|
||||
}
|
||||
|
||||
impl Clone for DigestBytes {
|
||||
#[inline]
|
||||
fn clone(&self) -> DigestBytes {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for DigestBytes {
|
||||
type Target = [u8];
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &[u8] {
|
||||
&self.buf[..self.len]
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for DigestBytes {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.buf[..self.len]
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for DigestBytes {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.deref()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for DigestBytes {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the hash of the `data` with the non-XOF hasher `t`.
|
||||
pub fn hash(t: MessageDigest, data: &[u8]) -> Result<DigestBytes, ErrorStack> {
|
||||
let mut h = Hasher::new(t)?;
|
||||
h.update(data)?;
|
||||
h.finish()
|
||||
}
|
||||
|
||||
/// Computes the hash of the `data` with the XOF hasher `t` and stores it in `buf`.
|
||||
#[cfg(ossl111)]
|
||||
pub fn hash_xof(t: MessageDigest, data: &[u8], buf: &mut [u8]) -> Result<(), ErrorStack> {
|
||||
let mut h = Hasher::new(t)?;
|
||||
h.update(data)?;
|
||||
h.finish_xof(buf)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use hex::{self, FromHex};
|
||||
use std::io::prelude::*;
|
||||
|
||||
use super::*;
|
||||
|
||||
fn hash_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
|
||||
let res = hash(hashtype, &Vec::from_hex(hashtest.0).unwrap()).unwrap();
|
||||
assert_eq!(hex::encode(res), hashtest.1);
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
fn hash_xof_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
|
||||
let expected = Vec::from_hex(hashtest.1).unwrap();
|
||||
let mut buf = vec![0; expected.len()];
|
||||
hash_xof(
|
||||
hashtype,
|
||||
&Vec::from_hex(hashtest.0).unwrap(),
|
||||
buf.as_mut_slice(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(buf, expected);
|
||||
}
|
||||
|
||||
fn hash_recycle_test(h: &mut Hasher, hashtest: &(&str, &str)) {
|
||||
h.write_all(&Vec::from_hex(hashtest.0).unwrap()).unwrap();
|
||||
let res = h.finish().unwrap();
|
||||
assert_eq!(hex::encode(res), hashtest.1);
|
||||
}
|
||||
|
||||
// Test vectors from http://www.nsrl.nist.gov/testdata/
|
||||
const MD5_TESTS: [(&str, &str); 13] = [
|
||||
("", "d41d8cd98f00b204e9800998ecf8427e"),
|
||||
("7F", "83acb6e67e50e31db6ed341dd2de1595"),
|
||||
("EC9C", "0b07f0d4ca797d8ac58874f887cb0b68"),
|
||||
("FEE57A", "e0d583171eb06d56198fc0ef22173907"),
|
||||
("42F497E0", "7c430f178aefdf1487fee7144e9641e2"),
|
||||
("C53B777F1C", "75ef141d64cb37ec423da2d9d440c925"),
|
||||
("89D5B576327B", "ebbaf15eb0ed784c6faa9dc32831bf33"),
|
||||
("5D4CCE781EB190", "ce175c4b08172019f05e6b5279889f2c"),
|
||||
("81901FE94932D7B9", "cd4d2f62b8cdb3a0cf968a735a239281"),
|
||||
("C9FFDEE7788EFB4EC9", "e0841a231ab698db30c6c0f3f246c014"),
|
||||
("66AC4B7EBA95E53DC10B", "a3b3cea71910d9af56742aa0bb2fe329"),
|
||||
("A510CD18F7A56852EB0319", "577e216843dd11573574d3fb209b97d8"),
|
||||
(
|
||||
"AAED18DBE8938C19ED734A8D",
|
||||
"6f80fb775f27e0a4ce5c2f42fc72c5f1",
|
||||
),
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn test_md5() {
|
||||
for test in MD5_TESTS.iter() {
|
||||
hash_test(MessageDigest::md5(), test);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_md5_recycle() {
|
||||
let mut h = Hasher::new(MessageDigest::md5()).unwrap();
|
||||
for test in MD5_TESTS.iter() {
|
||||
hash_recycle_test(&mut h, test);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_finish_twice() {
|
||||
let mut h = Hasher::new(MessageDigest::md5()).unwrap();
|
||||
h.write_all(&Vec::from_hex(MD5_TESTS[6].0).unwrap())
|
||||
.unwrap();
|
||||
h.finish().unwrap();
|
||||
let res = h.finish().unwrap();
|
||||
let null = hash(MessageDigest::md5(), &[]).unwrap();
|
||||
assert_eq!(&*res, &*null);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::redundant_clone)]
|
||||
fn test_clone() {
|
||||
let i = 7;
|
||||
let inp = Vec::from_hex(MD5_TESTS[i].0).unwrap();
|
||||
assert!(inp.len() > 2);
|
||||
let p = inp.len() / 2;
|
||||
let h0 = Hasher::new(MessageDigest::md5()).unwrap();
|
||||
|
||||
println!("Clone a new hasher");
|
||||
let mut h1 = h0.clone();
|
||||
h1.write_all(&inp[..p]).unwrap();
|
||||
{
|
||||
println!("Clone an updated hasher");
|
||||
let mut h2 = h1.clone();
|
||||
h2.write_all(&inp[p..]).unwrap();
|
||||
let res = h2.finish().unwrap();
|
||||
assert_eq!(hex::encode(res), MD5_TESTS[i].1);
|
||||
}
|
||||
h1.write_all(&inp[p..]).unwrap();
|
||||
let res = h1.finish().unwrap();
|
||||
assert_eq!(hex::encode(res), MD5_TESTS[i].1);
|
||||
|
||||
println!("Clone a finished hasher");
|
||||
let mut h3 = h1.clone();
|
||||
h3.write_all(&Vec::from_hex(MD5_TESTS[i + 1].0).unwrap())
|
||||
.unwrap();
|
||||
let res = h3.finish().unwrap();
|
||||
assert_eq!(hex::encode(res), MD5_TESTS[i + 1].1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sha1() {
|
||||
let tests = [("616263", "a9993e364706816aba3e25717850c26c9cd0d89d")];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::sha1(), test);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sha256() {
|
||||
let tests = [(
|
||||
"616263",
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::sha256(), test);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[test]
|
||||
fn test_sha3_224() {
|
||||
let tests = [(
|
||||
"416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
|
||||
"1de092dd9fbcbbf450f26264f4778abd48af851f2832924554c56913",
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::sha3_224(), test);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[test]
|
||||
fn test_sha3_256() {
|
||||
let tests = [(
|
||||
"416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
|
||||
"b38e38f08bc1c0091ed4b5f060fe13e86aa4179578513ad11a6e3abba0062f61",
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::sha3_256(), test);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[test]
|
||||
fn test_sha3_384() {
|
||||
let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
|
||||
"966ee786ab3482dd811bf7c8fa8db79aa1f52f6c3c369942ef14240ebd857c6ff626ec35d9e131ff64d328\
|
||||
ef2008ff16"
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::sha3_384(), test);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[test]
|
||||
fn test_sha3_512() {
|
||||
let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
|
||||
"c072288ef728cd53a029c47687960b9225893532f42b923156e37020bdc1eda753aafbf30af859d4f4c3a1\
|
||||
807caee3a79f8eb02dcd61589fbbdf5f40c8787a72"
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::sha3_512(), test);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[test]
|
||||
fn test_shake_128() {
|
||||
let tests = [(
|
||||
"416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
|
||||
"49d0697ff508111d8b84f15e46daf135",
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_xof_test(MessageDigest::shake_128(), test);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[test]
|
||||
fn test_shake_256() {
|
||||
let tests = [(
|
||||
"416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
|
||||
"4e2dfdaa75d1e049d0eaeffe28e76b17cea47b650fb8826fe48b94664326a697",
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_xof_test(MessageDigest::shake_256(), test);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ripemd160() {
|
||||
#[cfg(ossl300)]
|
||||
let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
|
||||
|
||||
let tests = [("616263", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc")];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::ripemd160(), test);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
|
||||
#[test]
|
||||
fn test_sm3() {
|
||||
let tests = [(
|
||||
"616263",
|
||||
"66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::sm3(), test);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_nid() {
|
||||
assert_eq!(
|
||||
MessageDigest::from_nid(Nid::SHA256).unwrap().as_ptr(),
|
||||
MessageDigest::sha256().as_ptr()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_name() {
|
||||
assert_eq!(
|
||||
MessageDigest::from_name("SHA256").unwrap().as_ptr(),
|
||||
MessageDigest::sha256().as_ptr()
|
||||
)
|
||||
}
|
||||
}
|
||||
209
zeroidc/vendor/openssl/src/lib.rs
vendored
Normal file
209
zeroidc/vendor/openssl/src/lib.rs
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
//! Bindings to OpenSSL
|
||||
//!
|
||||
//! This crate provides a safe interface to the popular OpenSSL cryptography library. OpenSSL versions 1.0.1 through
|
||||
//! 1.1.1 and LibreSSL versions 2.5 through 3.4.1 are supported.
|
||||
//!
|
||||
//! # Building
|
||||
//!
|
||||
//! Both OpenSSL libraries and headers are required to build this crate. There are multiple options available to locate
|
||||
//! OpenSSL.
|
||||
//!
|
||||
//! ## Vendored
|
||||
//!
|
||||
//! If the `vendored` Cargo feature is enabled, the `openssl-src` crate will be used to compile and statically link to
|
||||
//! a copy of OpenSSL. The build process requires a C compiler, perl (and perl-core), and make. The OpenSSL version will generally track
|
||||
//! the newest OpenSSL release, and changes to the version are *not* considered breaking changes.
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! openssl = { version = "0.10", features = ["vendored"] }
|
||||
//! ```
|
||||
//!
|
||||
//! The vendored copy will not be configured to automatically find the system's root certificates, but the
|
||||
//! `openssl-probe` crate can be used to do that instead.
|
||||
//!
|
||||
//! ## Automatic
|
||||
//!
|
||||
//! The `openssl-sys` crate will automatically detect OpenSSL installations via Homebrew on macOS and vcpkg on Windows.
|
||||
//! Additionally, it will use `pkg-config` on Unix-like systems to find the system installation.
|
||||
//!
|
||||
//! ```not_rust
|
||||
//! # macOS (Homebrew)
|
||||
//! $ brew install openssl@1.1
|
||||
//!
|
||||
//! # macOS (MacPorts)
|
||||
//! $ sudo port install openssl
|
||||
//!
|
||||
//! # macOS (pkgsrc)
|
||||
//! $ sudo pkgin install openssl
|
||||
//!
|
||||
//! # Arch Linux
|
||||
//! $ sudo pacman -S pkg-config openssl
|
||||
//!
|
||||
//! # Debian and Ubuntu
|
||||
//! $ sudo apt-get install pkg-config libssl-dev
|
||||
//!
|
||||
//! # Fedora
|
||||
//! $ sudo dnf install pkg-config openssl-devel
|
||||
//!
|
||||
//! # Alpine Linux
|
||||
//! $ apk add pkgconfig openssl-dev
|
||||
//! ```
|
||||
//!
|
||||
//! ## Manual
|
||||
//!
|
||||
//! A set of environment variables can be used to point `openssl-sys` towards an OpenSSL installation. They will
|
||||
//! override the automatic detection logic.
|
||||
//!
|
||||
//! * `OPENSSL_DIR` - If specified, the directory of an OpenSSL installation. The directory should contain `lib` and
|
||||
//! `include` subdirectories containing the libraries and headers respectively.
|
||||
//! * `OPENSSL_LIB_DIR` and `OPENSSL_INCLUDE_DIR` - If specified, the directories containing the OpenSSL libraries and
|
||||
//! headers respectively. This can be used if the OpenSSL installation is split in a nonstandard directory layout.
|
||||
//! * `OPENSSL_STATIC` - If set, the crate will statically link to OpenSSL rather than dynamically link.
|
||||
//! * `OPENSSL_LIBS` - If set, a `:`-separated list of library names to link to (e.g. `ssl:crypto`). This can be used
|
||||
//! if nonstandard library names were used for whatever reason.
|
||||
//! * `OPENSSL_NO_VENDOR` - If set, always find OpenSSL in the system, even if the `vendored` feature is enabled.
|
||||
//!
|
||||
//! Additionally, these variables can be prefixed with the upper-cased target architecture (e.g.
|
||||
//! `X86_64_UNKNOWN_LINUX_GNU_OPENSSL_DIR`), which can be useful when cross compiling.
|
||||
//!
|
||||
//! # Feature Detection
|
||||
//!
|
||||
//! APIs have been added to and removed from the various supported OpenSSL versions, and this library exposes the
|
||||
//! functionality available in the version being linked against. This means that methods, constants, and even modules
|
||||
//! will be present when building against one version of OpenSSL but not when building against another! APIs will
|
||||
//! document any version-specific availability restrictions.
|
||||
//!
|
||||
//! A build script can be used to detect the OpenSSL or LibreSSL version at compile time if needed. The `openssl-sys`
|
||||
//! crate propagates the version via the `DEP_OPENSSL_VERSION_NUMBER` and `DEP_OPENSSL_LIBRESSL_VERSION_NUMBER`
|
||||
//! environment variables to build scripts. The version format is a hex-encoding of the OpenSSL release version:
|
||||
//! `0xMNNFFPPS`. For example, version 1.0.2g's encoding is `0x1_00_02_07_0`.
|
||||
//!
|
||||
//! For example, let's say we want to adjust the TLSv1.3 cipher suites used by a client, but also want to compile
|
||||
//! against OpenSSL versions that don't support TLSv1.3:
|
||||
//!
|
||||
//! Cargo.toml:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! openssl-sys = "0.9"
|
||||
//! openssl = "0.10"
|
||||
//! ```
|
||||
//!
|
||||
//! build.rs:
|
||||
//!
|
||||
//! ```
|
||||
//! use std::env;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! if let Ok(v) = env::var("DEP_OPENSSL_VERSION_NUMBER") {
|
||||
//! let version = u64::from_str_radix(&v, 16).unwrap();
|
||||
//!
|
||||
//! if version >= 0x1_01_01_00_0 {
|
||||
//! println!("cargo:rustc-cfg=openssl111");
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! lib.rs:
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::ssl::{SslConnector, SslMethod};
|
||||
//!
|
||||
//! let mut ctx = SslConnector::builder(SslMethod::tls()).unwrap();
|
||||
//!
|
||||
//! // set_ciphersuites was added in OpenSSL 1.1.1, so we can only call it when linking against that version
|
||||
//! #[cfg(openssl111)]
|
||||
//! ctx.set_ciphersuites("TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256").unwrap();
|
||||
//! ```
|
||||
#![doc(html_root_url = "https://docs.rs/openssl/0.10")]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::init;
|
||||
|
||||
use libc::c_int;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
mod bio;
|
||||
#[macro_use]
|
||||
mod util;
|
||||
pub mod aes;
|
||||
pub mod asn1;
|
||||
pub mod base64;
|
||||
pub mod bn;
|
||||
pub mod cipher;
|
||||
pub mod cipher_ctx;
|
||||
#[cfg(all(not(libressl), not(osslconf = "OPENSSL_NO_CMS")))]
|
||||
pub mod cms;
|
||||
pub mod conf;
|
||||
pub mod derive;
|
||||
pub mod dh;
|
||||
pub mod dsa;
|
||||
pub mod ec;
|
||||
pub mod ecdsa;
|
||||
pub mod encrypt;
|
||||
pub mod envelope;
|
||||
pub mod error;
|
||||
pub mod ex_data;
|
||||
#[cfg(not(any(libressl, ossl300)))]
|
||||
pub mod fips;
|
||||
pub mod hash;
|
||||
#[cfg(ossl300)]
|
||||
pub mod lib_ctx;
|
||||
pub mod md;
|
||||
pub mod md_ctx;
|
||||
pub mod memcmp;
|
||||
pub mod nid;
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_OCSP"))]
|
||||
pub mod ocsp;
|
||||
pub mod pkcs12;
|
||||
pub mod pkcs5;
|
||||
pub mod pkcs7;
|
||||
pub mod pkey;
|
||||
pub mod pkey_ctx;
|
||||
#[cfg(ossl300)]
|
||||
pub mod provider;
|
||||
pub mod rand;
|
||||
pub mod rsa;
|
||||
pub mod sha;
|
||||
pub mod sign;
|
||||
pub mod srtp;
|
||||
pub mod ssl;
|
||||
pub mod stack;
|
||||
pub mod string;
|
||||
pub mod symm;
|
||||
pub mod version;
|
||||
pub mod x509;
|
||||
|
||||
#[inline]
|
||||
fn cvt_p<T>(r: *mut T) -> Result<*mut T, ErrorStack> {
|
||||
if r.is_null() {
|
||||
Err(ErrorStack::get())
|
||||
} else {
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn cvt(r: c_int) -> Result<c_int, ErrorStack> {
|
||||
if r <= 0 {
|
||||
Err(ErrorStack::get())
|
||||
} else {
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn cvt_n(r: c_int) -> Result<c_int, ErrorStack> {
|
||||
if r < 0 {
|
||||
Err(ErrorStack::get())
|
||||
} else {
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
22
zeroidc/vendor/openssl/src/lib_ctx.rs
vendored
Normal file
22
zeroidc/vendor/openssl/src/lib_ctx.rs
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
use crate::cvt_p;
|
||||
use crate::error::ErrorStack;
|
||||
use foreign_types::ForeignType;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::OSSL_LIB_CTX;
|
||||
fn drop = ffi::OSSL_LIB_CTX_free;
|
||||
|
||||
pub struct LibCtx;
|
||||
pub struct LibCtxRef;
|
||||
}
|
||||
|
||||
impl LibCtx {
|
||||
#[corresponds(OSSL_LIB_CTX_new)]
|
||||
pub fn new() -> Result<Self, ErrorStack> {
|
||||
unsafe {
|
||||
let ptr = cvt_p(ffi::OSSL_LIB_CTX_new())?;
|
||||
Ok(LibCtx::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
269
zeroidc/vendor/openssl/src/macros.rs
vendored
Normal file
269
zeroidc/vendor/openssl/src/macros.rs
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
macro_rules! private_key_from_pem {
|
||||
($(#[$m:meta])* $n:ident, $(#[$m2:meta])* $n2:ident, $(#[$m3:meta])* $n3:ident, $t:ty, $f:path) => {
|
||||
from_pem!($(#[$m])* $n, $t, $f);
|
||||
|
||||
$(#[$m2])*
|
||||
pub fn $n2(pem: &[u8], passphrase: &[u8]) -> Result<$t, crate::error::ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
let bio = crate::bio::MemBioSlice::new(pem)?;
|
||||
let passphrase = ::std::ffi::CString::new(passphrase).unwrap();
|
||||
cvt_p($f(bio.as_ptr(),
|
||||
ptr::null_mut(),
|
||||
None,
|
||||
passphrase.as_ptr() as *const _ as *mut _))
|
||||
.map(|p| ::foreign_types::ForeignType::from_ptr(p))
|
||||
}
|
||||
}
|
||||
|
||||
$(#[$m3])*
|
||||
pub fn $n3<F>(pem: &[u8], callback: F) -> Result<$t, crate::error::ErrorStack>
|
||||
where F: FnOnce(&mut [u8]) -> Result<usize, crate::error::ErrorStack>
|
||||
{
|
||||
unsafe {
|
||||
ffi::init();
|
||||
let mut cb = crate::util::CallbackState::new(callback);
|
||||
let bio = crate::bio::MemBioSlice::new(pem)?;
|
||||
cvt_p($f(bio.as_ptr(),
|
||||
ptr::null_mut(),
|
||||
Some(crate::util::invoke_passwd_cb::<F>),
|
||||
&mut cb as *mut _ as *mut _))
|
||||
.map(|p| ::foreign_types::ForeignType::from_ptr(p))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! private_key_to_pem {
|
||||
($(#[$m:meta])* $n:ident, $(#[$m2:meta])* $n2:ident, $f:path) => {
|
||||
$(#[$m])*
|
||||
pub fn $n(&self) -> Result<Vec<u8>, crate::error::ErrorStack> {
|
||||
unsafe {
|
||||
let bio = crate::bio::MemBio::new()?;
|
||||
cvt($f(bio.as_ptr(),
|
||||
self.as_ptr(),
|
||||
ptr::null(),
|
||||
ptr::null_mut(),
|
||||
-1,
|
||||
None,
|
||||
ptr::null_mut()))?;
|
||||
Ok(bio.get_buf().to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
$(#[$m2])*
|
||||
pub fn $n2(
|
||||
&self,
|
||||
cipher: crate::symm::Cipher,
|
||||
passphrase: &[u8]
|
||||
) -> Result<Vec<u8>, crate::error::ErrorStack> {
|
||||
unsafe {
|
||||
let bio = crate::bio::MemBio::new()?;
|
||||
assert!(passphrase.len() <= ::libc::c_int::max_value() as usize);
|
||||
cvt($f(bio.as_ptr(),
|
||||
self.as_ptr(),
|
||||
cipher.as_ptr(),
|
||||
passphrase.as_ptr() as *const _ as *mut _,
|
||||
passphrase.len() as ::libc::c_int,
|
||||
None,
|
||||
ptr::null_mut()))?;
|
||||
Ok(bio.get_buf().to_owned())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! to_pem {
|
||||
($(#[$m:meta])* $n:ident, $f:path) => {
|
||||
$(#[$m])*
|
||||
pub fn $n(&self) -> Result<Vec<u8>, crate::error::ErrorStack> {
|
||||
unsafe {
|
||||
let bio = crate::bio::MemBio::new()?;
|
||||
cvt($f(bio.as_ptr(), self.as_ptr()))?;
|
||||
Ok(bio.get_buf().to_owned())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! to_der {
|
||||
($(#[$m:meta])* $n:ident, $f:path) => {
|
||||
$(#[$m])*
|
||||
pub fn $n(&self) -> Result<Vec<u8>, crate::error::ErrorStack> {
|
||||
unsafe {
|
||||
let len = crate::cvt($f(::foreign_types::ForeignTypeRef::as_ptr(self),
|
||||
ptr::null_mut()))?;
|
||||
let mut buf = vec![0; len as usize];
|
||||
crate::cvt($f(::foreign_types::ForeignTypeRef::as_ptr(self),
|
||||
&mut buf.as_mut_ptr()))?;
|
||||
Ok(buf)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! from_der {
|
||||
($(#[$m:meta])* $n:ident, $t:ty, $f:path) => {
|
||||
$(#[$m])*
|
||||
pub fn $n(der: &[u8]) -> Result<$t, crate::error::ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
let len = ::std::cmp::min(der.len(), ::libc::c_long::max_value() as usize) as ::libc::c_long;
|
||||
crate::cvt_p($f(::std::ptr::null_mut(), &mut der.as_ptr(), len))
|
||||
.map(|p| ::foreign_types::ForeignType::from_ptr(p))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! from_pem {
|
||||
($(#[$m:meta])* $n:ident, $t:ty, $f:path) => {
|
||||
$(#[$m])*
|
||||
pub fn $n(pem: &[u8]) -> Result<$t, crate::error::ErrorStack> {
|
||||
unsafe {
|
||||
crate::init();
|
||||
let bio = crate::bio::MemBioSlice::new(pem)?;
|
||||
cvt_p($f(bio.as_ptr(), ::std::ptr::null_mut(), None, ::std::ptr::null_mut()))
|
||||
.map(|p| ::foreign_types::ForeignType::from_ptr(p))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! foreign_type_and_impl_send_sync {
|
||||
(
|
||||
$(#[$impl_attr:meta])*
|
||||
type CType = $ctype:ty;
|
||||
fn drop = $drop:expr;
|
||||
$(fn clone = $clone:expr;)*
|
||||
|
||||
$(#[$owned_attr:meta])*
|
||||
pub struct $owned:ident;
|
||||
$(#[$borrowed_attr:meta])*
|
||||
pub struct $borrowed:ident;
|
||||
)
|
||||
=> {
|
||||
::foreign_types::foreign_type! {
|
||||
$(#[$impl_attr])*
|
||||
type CType = $ctype;
|
||||
fn drop = $drop;
|
||||
$(fn clone = $clone;)*
|
||||
$(#[$owned_attr])*
|
||||
pub struct $owned;
|
||||
$(#[$borrowed_attr])*
|
||||
pub struct $borrowed;
|
||||
}
|
||||
|
||||
unsafe impl Send for $owned{}
|
||||
unsafe impl Send for $borrowed{}
|
||||
unsafe impl Sync for $owned{}
|
||||
unsafe impl Sync for $borrowed{}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! generic_foreign_type_and_impl_send_sync {
|
||||
(
|
||||
$(#[$impl_attr:meta])*
|
||||
type CType = $ctype:ty;
|
||||
fn drop = $drop:expr;
|
||||
$(fn clone = $clone:expr;)*
|
||||
|
||||
$(#[$owned_attr:meta])*
|
||||
pub struct $owned:ident<T>;
|
||||
$(#[$borrowed_attr:meta])*
|
||||
pub struct $borrowed:ident<T>;
|
||||
) => {
|
||||
$(#[$owned_attr])*
|
||||
pub struct $owned<T>(*mut $ctype, ::std::marker::PhantomData<T>);
|
||||
|
||||
$(#[$impl_attr])*
|
||||
impl<T> ::foreign_types::ForeignType for $owned<T> {
|
||||
type CType = $ctype;
|
||||
type Ref = $borrowed<T>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn from_ptr(ptr: *mut $ctype) -> $owned<T> {
|
||||
$owned(ptr, ::std::marker::PhantomData)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut $ctype {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for $owned<T> {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe { $drop(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
$(
|
||||
impl<T> Clone for $owned<T> {
|
||||
#[inline]
|
||||
fn clone(&self) -> $owned<T> {
|
||||
unsafe {
|
||||
let handle: *mut $ctype = $clone(self.0);
|
||||
::foreign_types::ForeignType::from_ptr(handle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ::std::borrow::ToOwned for $borrowed<T> {
|
||||
type Owned = $owned<T>;
|
||||
#[inline]
|
||||
fn to_owned(&self) -> $owned<T> {
|
||||
unsafe {
|
||||
let handle: *mut $ctype =
|
||||
$clone(::foreign_types::ForeignTypeRef::as_ptr(self));
|
||||
$crate::ForeignType::from_ptr(handle)
|
||||
}
|
||||
}
|
||||
}
|
||||
)*
|
||||
|
||||
impl<T> ::std::ops::Deref for $owned<T> {
|
||||
type Target = $borrowed<T>;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &$borrowed<T> {
|
||||
unsafe { ::foreign_types::ForeignTypeRef::from_ptr(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ::std::ops::DerefMut for $owned<T> {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut $borrowed<T> {
|
||||
unsafe { ::foreign_types::ForeignTypeRef::from_ptr_mut(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ::std::borrow::Borrow<$borrowed<T>> for $owned<T> {
|
||||
#[inline]
|
||||
fn borrow(&self) -> &$borrowed<T> {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ::std::convert::AsRef<$borrowed<T>> for $owned<T> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &$borrowed<T> {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
$(#[$borrowed_attr])*
|
||||
pub struct $borrowed<T>(::foreign_types::Opaque, ::std::marker::PhantomData<T>);
|
||||
|
||||
$(#[$impl_attr])*
|
||||
impl<T> ::foreign_types::ForeignTypeRef for $borrowed<T> {
|
||||
type CType = $ctype;
|
||||
}
|
||||
|
||||
unsafe impl<T> Send for $owned<T>{}
|
||||
unsafe impl<T> Send for $borrowed<T>{}
|
||||
unsafe impl<T> Sync for $owned<T>{}
|
||||
unsafe impl<T> Sync for $borrowed<T>{}
|
||||
};
|
||||
}
|
||||
223
zeroidc/vendor/openssl/src/md.rs
vendored
Normal file
223
zeroidc/vendor/openssl/src/md.rs
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
#[cfg(ossl300)]
|
||||
use crate::cvt_p;
|
||||
#[cfg(ossl300)]
|
||||
use crate::error::ErrorStack;
|
||||
#[cfg(ossl300)]
|
||||
use crate::lib_ctx::LibCtxRef;
|
||||
use crate::nid::Nid;
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignTypeRef, Opaque};
|
||||
use openssl_macros::corresponds;
|
||||
#[cfg(ossl300)]
|
||||
use std::ffi::CString;
|
||||
#[cfg(ossl300)]
|
||||
use std::ptr;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl300)] {
|
||||
use foreign_types::ForeignType;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
type Inner = *mut ffi::EVP_MD;
|
||||
|
||||
impl Drop for Md {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::EVP_MD_free(self.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ForeignType for Md {
|
||||
type CType = ffi::EVP_MD;
|
||||
type Ref = MdRef;
|
||||
|
||||
#[inline]
|
||||
unsafe fn from_ptr(ptr: *mut Self::CType) -> Self {
|
||||
Md(ptr)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut Self::CType {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Md {
|
||||
type Target = MdRef;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe {
|
||||
MdRef::from_ptr(self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Md {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe {
|
||||
MdRef::from_ptr_mut(self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
enum Inner {}
|
||||
}
|
||||
}
|
||||
|
||||
/// A message digest algorithm.
|
||||
pub struct Md(Inner);
|
||||
|
||||
unsafe impl Sync for Md {}
|
||||
unsafe impl Send for Md {}
|
||||
|
||||
impl Md {
|
||||
/// Returns the `Md` corresponding to an [`Nid`].
|
||||
#[corresponds(EVP_get_digestbynid)]
|
||||
pub fn from_nid(type_: Nid) -> Option<&'static MdRef> {
|
||||
unsafe {
|
||||
let ptr = ffi::EVP_get_digestbynid(type_.as_raw());
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(MdRef::from_ptr(ptr as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetches an `Md` object corresponding to the specified algorithm name and properties.
|
||||
///
|
||||
/// Requires OpenSSL 3.0.0 or newer.
|
||||
#[corresponds(EVP_MD_fetch)]
|
||||
#[cfg(ossl300)]
|
||||
pub fn fetch(
|
||||
ctx: Option<&LibCtxRef>,
|
||||
algorithm: &str,
|
||||
properties: Option<&str>,
|
||||
) -> Result<Self, ErrorStack> {
|
||||
let algorithm = CString::new(algorithm).unwrap();
|
||||
let properties = properties.map(|s| CString::new(s).unwrap());
|
||||
|
||||
unsafe {
|
||||
let ptr = cvt_p(ffi::EVP_MD_fetch(
|
||||
ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
|
||||
algorithm.as_ptr(),
|
||||
properties.map_or(ptr::null_mut(), |s| s.as_ptr()),
|
||||
))?;
|
||||
|
||||
Ok(Md::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn null() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_md_null() as *mut _) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn md5() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_md5() as *mut _) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sha1() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha1() as *mut _) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sha224() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha224() as *mut _) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sha256() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha256() as *mut _) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sha384() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha384() as *mut _) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sha512() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha512() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[inline]
|
||||
pub fn sha3_224() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha3_224() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[inline]
|
||||
pub fn sha3_256() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha3_256() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[inline]
|
||||
pub fn sha3_384() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha3_384() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[inline]
|
||||
pub fn sha3_512() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha3_512() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[inline]
|
||||
pub fn shake128() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_shake128() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[inline]
|
||||
pub fn shake256() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_shake256() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_RMD160"))]
|
||||
#[inline]
|
||||
pub fn ripemd160() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_ripemd160() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
|
||||
#[inline]
|
||||
pub fn sm3() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sm3() as *mut _) }
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to an [`Md`].
|
||||
pub struct MdRef(Opaque);
|
||||
|
||||
impl ForeignTypeRef for MdRef {
|
||||
type CType = ffi::EVP_MD;
|
||||
}
|
||||
|
||||
unsafe impl Sync for MdRef {}
|
||||
unsafe impl Send for MdRef {}
|
||||
|
||||
impl MdRef {
|
||||
/// Returns the size of the digest in bytes.
|
||||
#[corresponds(EVP_MD_size)]
|
||||
#[inline]
|
||||
pub fn size(&self) -> usize {
|
||||
unsafe { ffi::EVP_MD_size(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Returns the [`Nid`] of the digest.
|
||||
#[corresponds(EVP_MD_type)]
|
||||
#[inline]
|
||||
pub fn type_(&self) -> Nid {
|
||||
unsafe { Nid::from_raw(ffi::EVP_MD_type(self.as_ptr())) }
|
||||
}
|
||||
}
|
||||
406
zeroidc/vendor/openssl/src/md_ctx.rs
vendored
Normal file
406
zeroidc/vendor/openssl/src/md_ctx.rs
vendored
Normal file
@@ -0,0 +1,406 @@
|
||||
//! The message digest context.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Compute the SHA256 checksum of data
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::md::Md;
|
||||
//! use openssl::md_ctx::MdCtx;
|
||||
//!
|
||||
//! let mut ctx = MdCtx::new().unwrap();
|
||||
//! ctx.digest_init(Md::sha256()).unwrap();
|
||||
//! ctx.digest_update(b"Some Crypto Text").unwrap();
|
||||
//! let mut digest = [0; 32];
|
||||
//! ctx.digest_final(&mut digest).unwrap();
|
||||
//!
|
||||
//! assert_eq!(
|
||||
//! digest,
|
||||
//! *b"\x60\x78\x56\x38\x8a\xca\x5c\x51\x83\xc4\xd1\x4d\xc8\xf9\xcc\xf2\
|
||||
//! \xa5\x21\xb3\x10\x93\x72\xfa\xd6\x7c\x55\xf5\xc9\xe3\xd1\x83\x19",
|
||||
//! );
|
||||
//! ```
|
||||
//!
|
||||
//! Sign and verify data with RSA and SHA256
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::md::Md;
|
||||
//! use openssl::md_ctx::MdCtx;
|
||||
//! use openssl::pkey::PKey;
|
||||
//! use openssl::rsa::Rsa;
|
||||
//!
|
||||
//! // Generate a random RSA key.
|
||||
//! let key = Rsa::generate(4096).unwrap();
|
||||
//! let key = PKey::from_rsa(key).unwrap();
|
||||
//!
|
||||
//! let text = b"Some Crypto Text";
|
||||
//!
|
||||
//! // Create the signature.
|
||||
//! let mut ctx = MdCtx::new().unwrap();
|
||||
//! ctx.digest_sign_init(Some(Md::sha256()), &key).unwrap();
|
||||
//! ctx.digest_sign_update(text).unwrap();
|
||||
//! let mut signature = vec![];
|
||||
//! ctx.digest_sign_final_to_vec(&mut signature).unwrap();
|
||||
//!
|
||||
//! // Verify the signature.
|
||||
//! let mut ctx = MdCtx::new().unwrap();
|
||||
//! ctx.digest_verify_init(Some(Md::sha256()), &key).unwrap();
|
||||
//! ctx.digest_verify_update(text).unwrap();
|
||||
//! let valid = ctx.digest_verify_final(&signature).unwrap();
|
||||
//! assert!(valid);
|
||||
//! ```
|
||||
//!
|
||||
//! Compute and verify an HMAC-SHA256
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::md::Md;
|
||||
//! use openssl::md_ctx::MdCtx;
|
||||
//! use openssl::memcmp;
|
||||
//! use openssl::pkey::PKey;
|
||||
//!
|
||||
//! // Create a key with the HMAC secret.
|
||||
//! let key = PKey::hmac(b"my secret").unwrap();
|
||||
//!
|
||||
//! let text = b"Some Crypto Text";
|
||||
//!
|
||||
//! // Compute the HMAC.
|
||||
//! let mut ctx = MdCtx::new().unwrap();
|
||||
//! ctx.digest_sign_init(Some(Md::sha256()), &key).unwrap();
|
||||
//! ctx.digest_sign_update(text).unwrap();
|
||||
//! let mut hmac = vec![];
|
||||
//! ctx.digest_sign_final_to_vec(&mut hmac).unwrap();
|
||||
//!
|
||||
//! // Verify the HMAC. You can't use MdCtx to do this; instead use a constant time equality check.
|
||||
//! # let target = hmac.clone();
|
||||
//! let valid = memcmp::eq(&hmac, &target);
|
||||
//! assert!(valid);
|
||||
//! ```
|
||||
use crate::error::ErrorStack;
|
||||
use crate::md::MdRef;
|
||||
use crate::pkey::{HasPrivate, PKeyRef};
|
||||
use crate::pkey_ctx::PkeyCtxRef;
|
||||
use crate::{cvt, cvt_n, cvt_p};
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use openssl_macros::corresponds;
|
||||
use std::convert::TryFrom;
|
||||
use std::ptr;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl110)] {
|
||||
use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
|
||||
} else {
|
||||
use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::EVP_MD_CTX;
|
||||
fn drop = EVP_MD_CTX_free;
|
||||
|
||||
pub struct MdCtx;
|
||||
/// A reference to an [`MdCtx`].
|
||||
pub struct MdCtxRef;
|
||||
}
|
||||
|
||||
impl MdCtx {
|
||||
/// Creates a new context.
|
||||
#[corresponds(EVP_MD_CTX_new)]
|
||||
#[inline]
|
||||
pub fn new() -> Result<Self, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
unsafe {
|
||||
let ptr = cvt_p(EVP_MD_CTX_new())?;
|
||||
Ok(MdCtx::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MdCtxRef {
|
||||
/// Initializes the context to compute the digest of data.
|
||||
#[corresponds(EVP_DigestInit_ex)]
|
||||
#[inline]
|
||||
pub fn digest_init(&mut self, digest: &MdRef) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestInit_ex(
|
||||
self.as_ptr(),
|
||||
digest.as_ptr(),
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Initializes the context to compute the signature of data.
|
||||
///
|
||||
/// A reference to the context's inner `PkeyCtx` is returned, allowing signature settings to be configured.
|
||||
#[corresponds(EVP_DigestSignInit)]
|
||||
#[inline]
|
||||
pub fn digest_sign_init<'a, T>(
|
||||
&'a mut self,
|
||||
digest: Option<&MdRef>,
|
||||
pkey: &PKeyRef<T>,
|
||||
) -> Result<&'a mut PkeyCtxRef<T>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
let mut p = ptr::null_mut();
|
||||
cvt(ffi::EVP_DigestSignInit(
|
||||
self.as_ptr(),
|
||||
&mut p,
|
||||
digest.map_or(ptr::null(), |p| p.as_ptr()),
|
||||
ptr::null_mut(),
|
||||
pkey.as_ptr(),
|
||||
))?;
|
||||
Ok(PkeyCtxRef::from_ptr_mut(p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes the context to verify the signature of data.
|
||||
///
|
||||
/// A reference to the context's inner `PkeyCtx` is returned, allowing signature settings to be configured.
|
||||
#[corresponds(EVP_DigestVerifyInit)]
|
||||
#[inline]
|
||||
pub fn digest_verify_init<'a, T>(
|
||||
&'a mut self,
|
||||
digest: Option<&MdRef>,
|
||||
pkey: &PKeyRef<T>,
|
||||
) -> Result<&'a mut PkeyCtxRef<T>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
let mut p = ptr::null_mut();
|
||||
cvt(ffi::EVP_DigestVerifyInit(
|
||||
self.as_ptr(),
|
||||
&mut p,
|
||||
digest.map_or(ptr::null(), |p| p.as_ptr()),
|
||||
ptr::null_mut(),
|
||||
pkey.as_ptr(),
|
||||
))?;
|
||||
Ok(PkeyCtxRef::from_ptr_mut(p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates the context with more data.
|
||||
#[corresponds(EVP_DigestUpdate)]
|
||||
#[inline]
|
||||
pub fn digest_update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestUpdate(
|
||||
self.as_ptr(),
|
||||
data.as_ptr() as *const _,
|
||||
data.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Updates the context with more data.
|
||||
#[corresponds(EVP_DigestSignUpdate)]
|
||||
#[inline]
|
||||
pub fn digest_sign_update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestSignUpdate(
|
||||
self.as_ptr(),
|
||||
data.as_ptr() as *const _,
|
||||
data.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Updates the context with more data.
|
||||
#[corresponds(EVP_DigestVerifyUpdate)]
|
||||
#[inline]
|
||||
pub fn digest_verify_update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestVerifyUpdate(
|
||||
self.as_ptr(),
|
||||
data.as_ptr() as *const _,
|
||||
data.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Copies the computed digest into the buffer, returning the number of bytes written.
|
||||
#[corresponds(EVP_DigestFinal)]
|
||||
#[inline]
|
||||
pub fn digest_final(&mut self, out: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
let mut len = u32::try_from(out.len()).unwrap_or(u32::MAX);
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestFinal(
|
||||
self.as_ptr(),
|
||||
out.as_mut_ptr(),
|
||||
&mut len,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(len as usize)
|
||||
}
|
||||
|
||||
/// Copies the computed digest into the buffer.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[corresponds(EVP_DigestFinalXOF)]
|
||||
#[inline]
|
||||
#[cfg(ossl111)]
|
||||
pub fn digest_final_xof(&mut self, out: &mut [u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestFinalXOF(
|
||||
self.as_ptr(),
|
||||
out.as_mut_ptr(),
|
||||
out.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Signs the computed digest.
|
||||
///
|
||||
/// If `out` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
|
||||
/// returned.
|
||||
#[corresponds(EVP_DigestSignFinal)]
|
||||
#[inline]
|
||||
pub fn digest_sign_final(&mut self, out: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
|
||||
let mut len = out.as_ref().map_or(0, |b| b.len());
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestSignFinal(
|
||||
self.as_ptr(),
|
||||
out.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
|
||||
&mut len,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Like [`Self::digest_sign_final`] but appends the signature to a [`Vec`].
|
||||
pub fn digest_sign_final_to_vec(&mut self, out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
|
||||
let base = out.len();
|
||||
let len = self.digest_sign_final(None)?;
|
||||
out.resize(base + len, 0);
|
||||
let len = self.digest_sign_final(Some(&mut out[base..]))?;
|
||||
out.truncate(base + len);
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Verifies the provided signature.
|
||||
///
|
||||
/// Returns `Ok(true)` if the signature is valid, `Ok(false)` if the signature is invalid, and `Err` if an error
|
||||
/// occurred.
|
||||
#[corresponds(EVP_DigestVerifyFinal)]
|
||||
#[inline]
|
||||
pub fn digest_verify_final(&mut self, signature: &[u8]) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
let r = cvt_n(ffi::EVP_DigestVerifyFinal(
|
||||
self.as_ptr(),
|
||||
signature.as_ptr() as *mut _,
|
||||
signature.len(),
|
||||
))?;
|
||||
Ok(r == 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the signature of the data in `from`.
|
||||
///
|
||||
/// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
|
||||
/// returned.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[corresponds(EVP_DigestSign)]
|
||||
#[cfg(ossl111)]
|
||||
#[inline]
|
||||
pub fn digest_sign(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
|
||||
let mut len = to.as_ref().map_or(0, |b| b.len());
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestSign(
|
||||
self.as_ptr(),
|
||||
to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
|
||||
&mut len,
|
||||
from.as_ptr(),
|
||||
from.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Like [`Self::digest_sign`] but appends the signature to a [`Vec`].
|
||||
#[cfg(ossl111)]
|
||||
pub fn digest_sign_to_vec(
|
||||
&mut self,
|
||||
from: &[u8],
|
||||
to: &mut Vec<u8>,
|
||||
) -> Result<usize, ErrorStack> {
|
||||
let base = to.len();
|
||||
let len = self.digest_sign(from, None)?;
|
||||
to.resize(base + len, 0);
|
||||
let len = self.digest_sign(from, Some(&mut to[base..]))?;
|
||||
to.truncate(base + len);
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Verifies the signature of the data in `data`.
|
||||
///
|
||||
/// Returns `Ok(true)` if the signature is valid, `Ok(false)` if the signature is invalid, and `Err` if an error
|
||||
/// occurred.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[corresponds(EVP_DigestVerify)]
|
||||
#[cfg(ossl111)]
|
||||
#[inline]
|
||||
pub fn digest_verify(&mut self, data: &[u8], signature: &[u8]) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
let r = cvt(ffi::EVP_DigestVerify(
|
||||
self.as_ptr(),
|
||||
signature.as_ptr(),
|
||||
signature.len(),
|
||||
data.as_ptr(),
|
||||
data.len(),
|
||||
))?;
|
||||
Ok(r == 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::md::Md;
|
||||
use crate::pkey::PKey;
|
||||
use crate::rsa::Rsa;
|
||||
|
||||
#[test]
|
||||
fn verify_fail() {
|
||||
let key1 = Rsa::generate(4096).unwrap();
|
||||
let key1 = PKey::from_rsa(key1).unwrap();
|
||||
|
||||
let md = Md::sha256();
|
||||
let data = b"Some Crypto Text";
|
||||
|
||||
let mut ctx = MdCtx::new().unwrap();
|
||||
ctx.digest_sign_init(Some(md), &key1).unwrap();
|
||||
ctx.digest_sign_update(data).unwrap();
|
||||
let mut signature = vec![];
|
||||
ctx.digest_sign_final_to_vec(&mut signature).unwrap();
|
||||
|
||||
let bad_data = b"Some Crypto text";
|
||||
|
||||
ctx.digest_verify_init(Some(md), &key1).unwrap();
|
||||
ctx.digest_verify_update(bad_data).unwrap();
|
||||
let valid = ctx.digest_verify_final(&signature).unwrap();
|
||||
assert!(!valid);
|
||||
}
|
||||
}
|
||||
93
zeroidc/vendor/openssl/src/memcmp.rs
vendored
Normal file
93
zeroidc/vendor/openssl/src/memcmp.rs
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
//! Utilities to safely compare cryptographic values.
|
||||
//!
|
||||
//! Extra care must be taken when comparing values in
|
||||
//! cryptographic code. If done incorrectly, it can lead
|
||||
//! to a [timing attack](https://en.wikipedia.org/wiki/Timing_attack).
|
||||
//! By analyzing the time taken to execute parts of a cryptographic
|
||||
//! algorithm, and attacker can attempt to compromise the
|
||||
//! cryptosystem.
|
||||
//!
|
||||
//! The utilities in this module are designed to be resistant
|
||||
//! to this type of attack.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! To perform a constant-time comparison of two arrays of the same length but different
|
||||
//! values:
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::memcmp::eq;
|
||||
//!
|
||||
//! // We want to compare `a` to `b` and `c`, without giving
|
||||
//! // away through timing analysis that `c` is more similar to `a`
|
||||
//! // than `b`.
|
||||
//! let a = [0, 0, 0];
|
||||
//! let b = [1, 1, 1];
|
||||
//! let c = [0, 0, 1];
|
||||
//!
|
||||
//! // These statements will execute in the same amount of time.
|
||||
//! assert!(!eq(&a, &b));
|
||||
//! assert!(!eq(&a, &c));
|
||||
//! ```
|
||||
use libc::size_t;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
/// Returns `true` iff `a` and `b` contain the same bytes.
|
||||
///
|
||||
/// This operation takes an amount of time dependent on the length of the two
|
||||
/// arrays given, but is independent of the contents of a and b.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic the current task if `a` and `b` do not have the same
|
||||
/// length.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// To perform a constant-time comparison of two arrays of the same length but different
|
||||
/// values:
|
||||
///
|
||||
/// ```
|
||||
/// use openssl::memcmp::eq;
|
||||
///
|
||||
/// // We want to compare `a` to `b` and `c`, without giving
|
||||
/// // away through timing analysis that `c` is more similar to `a`
|
||||
/// // than `b`.
|
||||
/// let a = [0, 0, 0];
|
||||
/// let b = [1, 1, 1];
|
||||
/// let c = [0, 0, 1];
|
||||
///
|
||||
/// // These statements will execute in the same amount of time.
|
||||
/// assert!(!eq(&a, &b));
|
||||
/// assert!(!eq(&a, &c));
|
||||
/// ```
|
||||
#[corresponds(CRYPTO_memcmp)]
|
||||
pub fn eq(a: &[u8], b: &[u8]) -> bool {
|
||||
assert!(a.len() == b.len());
|
||||
let ret = unsafe {
|
||||
ffi::CRYPTO_memcmp(
|
||||
a.as_ptr() as *const _,
|
||||
b.as_ptr() as *const _,
|
||||
a.len() as size_t,
|
||||
)
|
||||
};
|
||||
ret == 0
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::eq;
|
||||
|
||||
#[test]
|
||||
fn test_eq() {
|
||||
assert!(eq(&[], &[]));
|
||||
assert!(eq(&[1], &[1]));
|
||||
assert!(!eq(&[1, 2, 3], &[1, 2, 4]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_diff_lens() {
|
||||
eq(&[], &[1]);
|
||||
}
|
||||
}
|
||||
1152
zeroidc/vendor/openssl/src/nid.rs
vendored
Normal file
1152
zeroidc/vendor/openssl/src/nid.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
350
zeroidc/vendor/openssl/src/ocsp.rs
vendored
Normal file
350
zeroidc/vendor/openssl/src/ocsp.rs
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
use bitflags::bitflags;
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use libc::{c_int, c_long, c_ulong};
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use crate::asn1::Asn1GeneralizedTimeRef;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::stack::StackRef;
|
||||
use crate::util::ForeignTypeRefExt;
|
||||
use crate::x509::store::X509StoreRef;
|
||||
use crate::x509::{X509Ref, X509};
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
bitflags! {
|
||||
pub struct OcspFlag: c_ulong {
|
||||
const NO_CERTS = ffi::OCSP_NOCERTS;
|
||||
const NO_INTERN = ffi::OCSP_NOINTERN;
|
||||
const NO_CHAIN = ffi::OCSP_NOCHAIN;
|
||||
const NO_VERIFY = ffi::OCSP_NOVERIFY;
|
||||
const NO_EXPLICIT = ffi::OCSP_NOEXPLICIT;
|
||||
const NO_CA_SIGN = ffi::OCSP_NOCASIGN;
|
||||
const NO_DELEGATED = ffi::OCSP_NODELEGATED;
|
||||
const NO_CHECKS = ffi::OCSP_NOCHECKS;
|
||||
const TRUST_OTHER = ffi::OCSP_TRUSTOTHER;
|
||||
const RESPID_KEY = ffi::OCSP_RESPID_KEY;
|
||||
const NO_TIME = ffi::OCSP_NOTIME;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct OcspResponseStatus(c_int);
|
||||
|
||||
impl OcspResponseStatus {
|
||||
pub const SUCCESSFUL: OcspResponseStatus =
|
||||
OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_SUCCESSFUL);
|
||||
pub const MALFORMED_REQUEST: OcspResponseStatus =
|
||||
OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_MALFORMEDREQUEST);
|
||||
pub const INTERNAL_ERROR: OcspResponseStatus =
|
||||
OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_INTERNALERROR);
|
||||
pub const TRY_LATER: OcspResponseStatus =
|
||||
OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_TRYLATER);
|
||||
pub const SIG_REQUIRED: OcspResponseStatus =
|
||||
OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_SIGREQUIRED);
|
||||
pub const UNAUTHORIZED: OcspResponseStatus =
|
||||
OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_UNAUTHORIZED);
|
||||
|
||||
pub fn from_raw(raw: c_int) -> OcspResponseStatus {
|
||||
OcspResponseStatus(raw)
|
||||
}
|
||||
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct OcspCertStatus(c_int);
|
||||
|
||||
impl OcspCertStatus {
|
||||
pub const GOOD: OcspCertStatus = OcspCertStatus(ffi::V_OCSP_CERTSTATUS_GOOD);
|
||||
pub const REVOKED: OcspCertStatus = OcspCertStatus(ffi::V_OCSP_CERTSTATUS_REVOKED);
|
||||
pub const UNKNOWN: OcspCertStatus = OcspCertStatus(ffi::V_OCSP_CERTSTATUS_UNKNOWN);
|
||||
|
||||
pub fn from_raw(raw: c_int) -> OcspCertStatus {
|
||||
OcspCertStatus(raw)
|
||||
}
|
||||
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct OcspRevokedStatus(c_int);
|
||||
|
||||
impl OcspRevokedStatus {
|
||||
pub const NO_STATUS: OcspRevokedStatus = OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_NOSTATUS);
|
||||
pub const UNSPECIFIED: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_UNSPECIFIED);
|
||||
pub const KEY_COMPROMISE: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_KEYCOMPROMISE);
|
||||
pub const CA_COMPROMISE: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_CACOMPROMISE);
|
||||
pub const AFFILIATION_CHANGED: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_AFFILIATIONCHANGED);
|
||||
pub const STATUS_SUPERSEDED: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_SUPERSEDED);
|
||||
pub const STATUS_CESSATION_OF_OPERATION: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_CESSATIONOFOPERATION);
|
||||
pub const STATUS_CERTIFICATE_HOLD: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_CERTIFICATEHOLD);
|
||||
pub const REMOVE_FROM_CRL: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_REMOVEFROMCRL);
|
||||
|
||||
pub fn from_raw(raw: c_int) -> OcspRevokedStatus {
|
||||
OcspRevokedStatus(raw)
|
||||
}
|
||||
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OcspStatus<'a> {
|
||||
/// The overall status of the response.
|
||||
pub status: OcspCertStatus,
|
||||
/// If `status` is `CERT_STATUS_REVOKED`, the reason for the revocation.
|
||||
pub reason: OcspRevokedStatus,
|
||||
/// If `status` is `CERT_STATUS_REVOKED`, the time at which the certificate was revoked.
|
||||
pub revocation_time: Option<&'a Asn1GeneralizedTimeRef>,
|
||||
/// The time that this revocation check was performed.
|
||||
pub this_update: &'a Asn1GeneralizedTimeRef,
|
||||
/// The time at which this revocation check expires.
|
||||
pub next_update: &'a Asn1GeneralizedTimeRef,
|
||||
}
|
||||
|
||||
impl<'a> OcspStatus<'a> {
|
||||
/// Checks validity of the `this_update` and `next_update` fields.
|
||||
///
|
||||
/// The `nsec` parameter specifies an amount of slack time that will be used when comparing
|
||||
/// those times with the current time to account for delays and clock skew.
|
||||
///
|
||||
/// The `maxsec` parameter limits the maximum age of the `this_update` parameter to prohibit
|
||||
/// very old responses.
|
||||
#[corresponds(OCSP_check_validity)]
|
||||
pub fn check_validity(&self, nsec: u32, maxsec: Option<u32>) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::OCSP_check_validity(
|
||||
self.this_update.as_ptr(),
|
||||
self.next_update.as_ptr(),
|
||||
nsec as c_long,
|
||||
maxsec.map(|n| n as c_long).unwrap_or(-1),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::OCSP_BASICRESP;
|
||||
fn drop = ffi::OCSP_BASICRESP_free;
|
||||
|
||||
pub struct OcspBasicResponse;
|
||||
pub struct OcspBasicResponseRef;
|
||||
}
|
||||
|
||||
impl OcspBasicResponseRef {
|
||||
/// Verifies the validity of the response.
|
||||
///
|
||||
/// The `certs` parameter contains a set of certificates that will be searched when locating the
|
||||
/// OCSP response signing certificate. Some responders do not include this in the response.
|
||||
#[corresponds(OCSP_basic_verify)]
|
||||
pub fn verify(
|
||||
&self,
|
||||
certs: &StackRef<X509>,
|
||||
store: &X509StoreRef,
|
||||
flags: OcspFlag,
|
||||
) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::OCSP_basic_verify(
|
||||
self.as_ptr(),
|
||||
certs.as_ptr(),
|
||||
store.as_ptr(),
|
||||
flags.bits(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Looks up the status for the specified certificate ID.
|
||||
#[corresponds(OCSP_resp_find_status)]
|
||||
pub fn find_status<'a>(&'a self, id: &OcspCertIdRef) -> Option<OcspStatus<'a>> {
|
||||
unsafe {
|
||||
let mut status = ffi::V_OCSP_CERTSTATUS_UNKNOWN;
|
||||
let mut reason = ffi::OCSP_REVOKED_STATUS_NOSTATUS;
|
||||
let mut revocation_time = ptr::null_mut();
|
||||
let mut this_update = ptr::null_mut();
|
||||
let mut next_update = ptr::null_mut();
|
||||
|
||||
let r = ffi::OCSP_resp_find_status(
|
||||
self.as_ptr(),
|
||||
id.as_ptr(),
|
||||
&mut status,
|
||||
&mut reason,
|
||||
&mut revocation_time,
|
||||
&mut this_update,
|
||||
&mut next_update,
|
||||
);
|
||||
if r == 1 {
|
||||
let revocation_time = Asn1GeneralizedTimeRef::from_const_ptr_opt(revocation_time);
|
||||
|
||||
Some(OcspStatus {
|
||||
status: OcspCertStatus(status),
|
||||
reason: OcspRevokedStatus(status),
|
||||
revocation_time,
|
||||
this_update: Asn1GeneralizedTimeRef::from_ptr(this_update),
|
||||
next_update: Asn1GeneralizedTimeRef::from_ptr(next_update),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::OCSP_CERTID;
|
||||
fn drop = ffi::OCSP_CERTID_free;
|
||||
|
||||
pub struct OcspCertId;
|
||||
pub struct OcspCertIdRef;
|
||||
}
|
||||
|
||||
impl OcspCertId {
|
||||
/// Constructs a certificate ID for certificate `subject`.
|
||||
#[corresponds(OCSP_cert_to_id)]
|
||||
pub fn from_cert(
|
||||
digest: MessageDigest,
|
||||
subject: &X509Ref,
|
||||
issuer: &X509Ref,
|
||||
) -> Result<OcspCertId, ErrorStack> {
|
||||
unsafe {
|
||||
cvt_p(ffi::OCSP_cert_to_id(
|
||||
digest.as_ptr(),
|
||||
subject.as_ptr(),
|
||||
issuer.as_ptr(),
|
||||
))
|
||||
.map(OcspCertId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::OCSP_RESPONSE;
|
||||
fn drop = ffi::OCSP_RESPONSE_free;
|
||||
|
||||
pub struct OcspResponse;
|
||||
pub struct OcspResponseRef;
|
||||
}
|
||||
|
||||
impl OcspResponse {
|
||||
/// Creates an OCSP response from the status and optional body.
|
||||
///
|
||||
/// A body should only be provided if `status` is `RESPONSE_STATUS_SUCCESSFUL`.
|
||||
#[corresponds(OCSP_response_create)]
|
||||
pub fn create(
|
||||
status: OcspResponseStatus,
|
||||
body: Option<&OcspBasicResponseRef>,
|
||||
) -> Result<OcspResponse, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
cvt_p(ffi::OCSP_response_create(
|
||||
status.as_raw(),
|
||||
body.map(|r| r.as_ptr()).unwrap_or(ptr::null_mut()),
|
||||
))
|
||||
.map(OcspResponse)
|
||||
}
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Deserializes a DER-encoded OCSP response.
|
||||
#[corresponds(d2i_OCSP_RESPONSE)]
|
||||
from_der,
|
||||
OcspResponse,
|
||||
ffi::d2i_OCSP_RESPONSE
|
||||
}
|
||||
}
|
||||
|
||||
impl OcspResponseRef {
|
||||
to_der! {
|
||||
/// Serializes the response to its standard DER encoding.
|
||||
#[corresponds(i2d_OCSP_RESPONSE)]
|
||||
to_der,
|
||||
ffi::i2d_OCSP_RESPONSE
|
||||
}
|
||||
|
||||
/// Returns the status of the response.
|
||||
#[corresponds(OCSP_response_status)]
|
||||
pub fn status(&self) -> OcspResponseStatus {
|
||||
unsafe { OcspResponseStatus(ffi::OCSP_response_status(self.as_ptr())) }
|
||||
}
|
||||
|
||||
/// Returns the basic response.
|
||||
///
|
||||
/// This will only succeed if `status()` returns `RESPONSE_STATUS_SUCCESSFUL`.
|
||||
#[corresponds(OCSP_response_get1_basic)]
|
||||
pub fn basic(&self) -> Result<OcspBasicResponse, ErrorStack> {
|
||||
unsafe { cvt_p(ffi::OCSP_response_get1_basic(self.as_ptr())).map(OcspBasicResponse) }
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::OCSP_REQUEST;
|
||||
fn drop = ffi::OCSP_REQUEST_free;
|
||||
|
||||
pub struct OcspRequest;
|
||||
pub struct OcspRequestRef;
|
||||
}
|
||||
|
||||
impl OcspRequest {
|
||||
#[corresponds(OCSP_REQUEST_new)]
|
||||
pub fn new() -> Result<OcspRequest, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
cvt_p(ffi::OCSP_REQUEST_new()).map(OcspRequest)
|
||||
}
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Deserializes a DER-encoded OCSP request.
|
||||
#[corresponds(d2i_OCSP_REQUEST)]
|
||||
from_der,
|
||||
OcspRequest,
|
||||
ffi::d2i_OCSP_REQUEST
|
||||
}
|
||||
}
|
||||
|
||||
impl OcspRequestRef {
|
||||
to_der! {
|
||||
/// Serializes the request to its standard DER encoding.
|
||||
#[corresponds(i2d_OCSP_REQUEST)]
|
||||
to_der,
|
||||
ffi::i2d_OCSP_REQUEST
|
||||
}
|
||||
|
||||
#[corresponds(OCSP_request_add0_id)]
|
||||
pub fn add_id(&mut self, id: OcspCertId) -> Result<&mut OcspOneReqRef, ErrorStack> {
|
||||
unsafe {
|
||||
let ptr = cvt_p(ffi::OCSP_request_add0_id(self.as_ptr(), id.as_ptr()))?;
|
||||
mem::forget(id);
|
||||
Ok(OcspOneReqRef::from_ptr_mut(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::OCSP_ONEREQ;
|
||||
fn drop = ffi::OCSP_ONEREQ_free;
|
||||
|
||||
pub struct OcspOneReq;
|
||||
pub struct OcspOneReqRef;
|
||||
}
|
||||
308
zeroidc/vendor/openssl/src/pkcs12.rs
vendored
Normal file
308
zeroidc/vendor/openssl/src/pkcs12.rs
vendored
Normal file
@@ -0,0 +1,308 @@
|
||||
//! PKCS #12 archives.
|
||||
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::c_int;
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::nid::Nid;
|
||||
use crate::pkey::{HasPrivate, PKey, PKeyRef, Private};
|
||||
use crate::stack::Stack;
|
||||
use crate::util::ForeignTypeExt;
|
||||
use crate::x509::{X509Ref, X509};
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::PKCS12;
|
||||
fn drop = ffi::PKCS12_free;
|
||||
|
||||
pub struct Pkcs12;
|
||||
pub struct Pkcs12Ref;
|
||||
}
|
||||
|
||||
impl Pkcs12Ref {
|
||||
to_der! {
|
||||
/// Serializes the `Pkcs12` to its standard DER encoding.
|
||||
#[corresponds(i2d_PKCS12)]
|
||||
to_der,
|
||||
ffi::i2d_PKCS12
|
||||
}
|
||||
|
||||
/// Extracts the contents of the `Pkcs12`.
|
||||
#[corresponds(PKCS12_parse)]
|
||||
pub fn parse(&self, pass: &str) -> Result<ParsedPkcs12, ErrorStack> {
|
||||
unsafe {
|
||||
let pass = CString::new(pass.as_bytes()).unwrap();
|
||||
|
||||
let mut pkey = ptr::null_mut();
|
||||
let mut cert = ptr::null_mut();
|
||||
let mut chain = ptr::null_mut();
|
||||
|
||||
cvt(ffi::PKCS12_parse(
|
||||
self.as_ptr(),
|
||||
pass.as_ptr(),
|
||||
&mut pkey,
|
||||
&mut cert,
|
||||
&mut chain,
|
||||
))?;
|
||||
|
||||
let pkey = PKey::from_ptr(pkey);
|
||||
let cert = X509::from_ptr(cert);
|
||||
|
||||
let chain = Stack::from_ptr_opt(chain);
|
||||
|
||||
Ok(ParsedPkcs12 { pkey, cert, chain })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pkcs12 {
|
||||
from_der! {
|
||||
/// Deserializes a DER-encoded PKCS#12 archive.
|
||||
#[corresponds(d2i_PKCS12)]
|
||||
from_der,
|
||||
Pkcs12,
|
||||
ffi::d2i_PKCS12
|
||||
}
|
||||
|
||||
/// Creates a new builder for a protected pkcs12 certificate.
|
||||
///
|
||||
/// This uses the defaults from the OpenSSL library:
|
||||
///
|
||||
/// * `nid_key` - `AES_256_CBC` (3.0.0+) or `PBE_WITHSHA1AND3_KEY_TRIPLEDES_CBC`
|
||||
/// * `nid_cert` - `AES_256_CBC` (3.0.0+) or `PBE_WITHSHA1AND40BITRC2_CBC`
|
||||
/// * `iter` - `2048`
|
||||
/// * `mac_iter` - `2048`
|
||||
/// * `mac_md` - `SHA-256` (3.0.0+) or `SHA-1`
|
||||
pub fn builder() -> Pkcs12Builder {
|
||||
ffi::init();
|
||||
|
||||
Pkcs12Builder {
|
||||
nid_key: Nid::UNDEF,
|
||||
nid_cert: Nid::UNDEF,
|
||||
iter: ffi::PKCS12_DEFAULT_ITER,
|
||||
mac_iter: ffi::PKCS12_DEFAULT_ITER,
|
||||
mac_md: None,
|
||||
ca: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ParsedPkcs12 {
|
||||
pub pkey: PKey<Private>,
|
||||
pub cert: X509,
|
||||
pub chain: Option<Stack<X509>>,
|
||||
}
|
||||
|
||||
pub struct Pkcs12Builder {
|
||||
nid_key: Nid,
|
||||
nid_cert: Nid,
|
||||
iter: c_int,
|
||||
mac_iter: c_int,
|
||||
mac_md: Option<MessageDigest>,
|
||||
ca: Option<Stack<X509>>,
|
||||
}
|
||||
|
||||
impl Pkcs12Builder {
|
||||
/// The encryption algorithm that should be used for the key
|
||||
pub fn key_algorithm(&mut self, nid: Nid) -> &mut Self {
|
||||
self.nid_key = nid;
|
||||
self
|
||||
}
|
||||
|
||||
/// The encryption algorithm that should be used for the cert
|
||||
pub fn cert_algorithm(&mut self, nid: Nid) -> &mut Self {
|
||||
self.nid_cert = nid;
|
||||
self
|
||||
}
|
||||
|
||||
/// Key iteration count, default is 2048 as of this writing
|
||||
pub fn key_iter(&mut self, iter: u32) -> &mut Self {
|
||||
self.iter = iter as c_int;
|
||||
self
|
||||
}
|
||||
|
||||
/// MAC iteration count, default is the same as key_iter.
|
||||
///
|
||||
/// Old implementations don't understand MAC iterations greater than 1, (pre 1.0.1?), if such
|
||||
/// compatibility is required this should be set to 1.
|
||||
pub fn mac_iter(&mut self, mac_iter: u32) -> &mut Self {
|
||||
self.mac_iter = mac_iter as c_int;
|
||||
self
|
||||
}
|
||||
|
||||
/// MAC message digest type
|
||||
pub fn mac_md(&mut self, md: MessageDigest) -> &mut Self {
|
||||
self.mac_md = Some(md);
|
||||
self
|
||||
}
|
||||
|
||||
/// An additional set of certificates to include in the archive beyond the one provided to
|
||||
/// `build`.
|
||||
pub fn ca(&mut self, ca: Stack<X509>) -> &mut Self {
|
||||
self.ca = Some(ca);
|
||||
self
|
||||
}
|
||||
|
||||
/// Builds the PKCS #12 object
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `password` - the password used to encrypt the key and certificate
|
||||
/// * `friendly_name` - user defined name for the certificate
|
||||
/// * `pkey` - key to store
|
||||
/// * `cert` - certificate to store
|
||||
#[corresponds(PKCS12_create)]
|
||||
pub fn build<T>(
|
||||
self,
|
||||
password: &str,
|
||||
friendly_name: &str,
|
||||
pkey: &PKeyRef<T>,
|
||||
cert: &X509Ref,
|
||||
) -> Result<Pkcs12, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
let pass = CString::new(password).unwrap();
|
||||
let friendly_name = CString::new(friendly_name).unwrap();
|
||||
let pkey = pkey.as_ptr();
|
||||
let cert = cert.as_ptr();
|
||||
let ca = self
|
||||
.ca
|
||||
.as_ref()
|
||||
.map(|ca| ca.as_ptr())
|
||||
.unwrap_or(ptr::null_mut());
|
||||
let nid_key = self.nid_key.as_raw();
|
||||
let nid_cert = self.nid_cert.as_raw();
|
||||
let md_type = self
|
||||
.mac_md
|
||||
.map(|md_type| md_type.as_ptr())
|
||||
.unwrap_or(ptr::null());
|
||||
|
||||
// According to the OpenSSL docs, keytype is a non-standard extension for MSIE,
|
||||
// It's values are KEY_SIG or KEY_EX, see the OpenSSL docs for more information:
|
||||
// https://www.openssl.org/docs/man1.0.2/crypto/PKCS12_create.html
|
||||
let keytype = 0;
|
||||
|
||||
let pkcs12 = cvt_p(ffi::PKCS12_create(
|
||||
pass.as_ptr() as *const _ as *mut _,
|
||||
friendly_name.as_ptr() as *const _ as *mut _,
|
||||
pkey,
|
||||
cert,
|
||||
ca,
|
||||
nid_key,
|
||||
nid_cert,
|
||||
self.iter,
|
||||
-1,
|
||||
keytype,
|
||||
))
|
||||
.map(Pkcs12)?;
|
||||
|
||||
cvt(ffi::PKCS12_set_mac(
|
||||
pkcs12.as_ptr(),
|
||||
pass.as_ptr(),
|
||||
-1,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
self.mac_iter,
|
||||
md_type,
|
||||
))?;
|
||||
|
||||
Ok(pkcs12)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::asn1::Asn1Time;
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::nid::Nid;
|
||||
use crate::pkey::PKey;
|
||||
use crate::rsa::Rsa;
|
||||
use crate::x509::extension::KeyUsage;
|
||||
use crate::x509::{X509Name, X509};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse() {
|
||||
#[cfg(ossl300)]
|
||||
let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
|
||||
|
||||
let der = include_bytes!("../test/identity.p12");
|
||||
let pkcs12 = Pkcs12::from_der(der).unwrap();
|
||||
let parsed = pkcs12.parse("mypass").unwrap();
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(parsed.cert.digest(MessageDigest::sha1()).unwrap()),
|
||||
"59172d9313e84459bcff27f967e79e6e9217e584"
|
||||
);
|
||||
|
||||
let chain = parsed.chain.unwrap();
|
||||
assert_eq!(chain.len(), 1);
|
||||
assert_eq!(
|
||||
hex::encode(chain[0].digest(MessageDigest::sha1()).unwrap()),
|
||||
"c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_empty_chain() {
|
||||
#[cfg(ossl300)]
|
||||
let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
|
||||
|
||||
let der = include_bytes!("../test/keystore-empty-chain.p12");
|
||||
let pkcs12 = Pkcs12::from_der(der).unwrap();
|
||||
let parsed = pkcs12.parse("cassandra").unwrap();
|
||||
assert!(parsed.chain.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create() {
|
||||
let subject_name = "ns.example.com";
|
||||
let rsa = Rsa::generate(2048).unwrap();
|
||||
let pkey = PKey::from_rsa(rsa).unwrap();
|
||||
|
||||
let mut name = X509Name::builder().unwrap();
|
||||
name.append_entry_by_nid(Nid::COMMONNAME, subject_name)
|
||||
.unwrap();
|
||||
let name = name.build();
|
||||
|
||||
let key_usage = KeyUsage::new().digital_signature().build().unwrap();
|
||||
|
||||
let mut builder = X509::builder().unwrap();
|
||||
builder.set_version(2).unwrap();
|
||||
builder
|
||||
.set_not_before(&Asn1Time::days_from_now(0).unwrap())
|
||||
.unwrap();
|
||||
builder
|
||||
.set_not_after(&Asn1Time::days_from_now(365).unwrap())
|
||||
.unwrap();
|
||||
builder.set_subject_name(&name).unwrap();
|
||||
builder.set_issuer_name(&name).unwrap();
|
||||
builder.append_extension(key_usage).unwrap();
|
||||
builder.set_pubkey(&pkey).unwrap();
|
||||
builder.sign(&pkey, MessageDigest::sha256()).unwrap();
|
||||
let cert = builder.build();
|
||||
|
||||
let pkcs12_builder = Pkcs12::builder();
|
||||
let pkcs12 = pkcs12_builder
|
||||
.build("mypass", subject_name, &pkey, &cert)
|
||||
.unwrap();
|
||||
let der = pkcs12.to_der().unwrap();
|
||||
|
||||
let pkcs12 = Pkcs12::from_der(&der).unwrap();
|
||||
let parsed = pkcs12.parse("mypass").unwrap();
|
||||
|
||||
assert_eq!(
|
||||
&*parsed.cert.digest(MessageDigest::sha1()).unwrap(),
|
||||
&*cert.digest(MessageDigest::sha1()).unwrap()
|
||||
);
|
||||
assert!(parsed.pkey.public_eq(&pkey));
|
||||
}
|
||||
}
|
||||
306
zeroidc/vendor/openssl/src/pkcs5.rs
vendored
Normal file
306
zeroidc/vendor/openssl/src/pkcs5.rs
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
use libc::c_int;
|
||||
use std::ptr;
|
||||
|
||||
use crate::cvt;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::symm::Cipher;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct KeyIvPair {
|
||||
pub key: Vec<u8>,
|
||||
pub iv: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
/// Derives a key and an IV from various parameters.
|
||||
///
|
||||
/// If specified, `salt` must be 8 bytes in length.
|
||||
///
|
||||
/// If the total key and IV length is less than 16 bytes and MD5 is used then
|
||||
/// the algorithm is compatible with the key derivation algorithm from PKCS#5
|
||||
/// v1.5 or PBKDF1 from PKCS#5 v2.0.
|
||||
///
|
||||
/// New applications should not use this and instead use
|
||||
/// `pbkdf2_hmac` or another more modern key derivation algorithm.
|
||||
#[corresponds(EVP_BytesToKey)]
|
||||
#[allow(clippy::useless_conversion)]
|
||||
pub fn bytes_to_key(
|
||||
cipher: Cipher,
|
||||
digest: MessageDigest,
|
||||
data: &[u8],
|
||||
salt: Option<&[u8]>,
|
||||
count: i32,
|
||||
) -> Result<KeyIvPair, ErrorStack> {
|
||||
unsafe {
|
||||
assert!(data.len() <= c_int::max_value() as usize);
|
||||
let salt_ptr = match salt {
|
||||
Some(salt) => {
|
||||
assert_eq!(salt.len(), ffi::PKCS5_SALT_LEN as usize);
|
||||
salt.as_ptr()
|
||||
}
|
||||
None => ptr::null(),
|
||||
};
|
||||
|
||||
ffi::init();
|
||||
|
||||
let mut iv = cipher.iv_len().map(|l| vec![0; l]);
|
||||
|
||||
let cipher = cipher.as_ptr();
|
||||
let digest = digest.as_ptr();
|
||||
|
||||
let len = cvt(ffi::EVP_BytesToKey(
|
||||
cipher,
|
||||
digest,
|
||||
salt_ptr,
|
||||
ptr::null(),
|
||||
data.len() as c_int,
|
||||
count.into(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
|
||||
let mut key = vec![0; len as usize];
|
||||
let iv_ptr = iv
|
||||
.as_mut()
|
||||
.map(|v| v.as_mut_ptr())
|
||||
.unwrap_or(ptr::null_mut());
|
||||
|
||||
cvt(ffi::EVP_BytesToKey(
|
||||
cipher,
|
||||
digest,
|
||||
salt_ptr,
|
||||
data.as_ptr(),
|
||||
data.len() as c_int,
|
||||
count as c_int,
|
||||
key.as_mut_ptr(),
|
||||
iv_ptr,
|
||||
))?;
|
||||
|
||||
Ok(KeyIvPair { key, iv })
|
||||
}
|
||||
}
|
||||
|
||||
/// Derives a key from a password and salt using the PBKDF2-HMAC algorithm with a digest function.
|
||||
#[corresponds(PKCS5_PBKDF2_HMAC)]
|
||||
pub fn pbkdf2_hmac(
|
||||
pass: &[u8],
|
||||
salt: &[u8],
|
||||
iter: usize,
|
||||
hash: MessageDigest,
|
||||
key: &mut [u8],
|
||||
) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
assert!(pass.len() <= c_int::max_value() as usize);
|
||||
assert!(salt.len() <= c_int::max_value() as usize);
|
||||
assert!(key.len() <= c_int::max_value() as usize);
|
||||
|
||||
ffi::init();
|
||||
cvt(ffi::PKCS5_PBKDF2_HMAC(
|
||||
pass.as_ptr() as *const _,
|
||||
pass.len() as c_int,
|
||||
salt.as_ptr(),
|
||||
salt.len() as c_int,
|
||||
iter as c_int,
|
||||
hash.as_ptr(),
|
||||
key.len() as c_int,
|
||||
key.as_mut_ptr(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Derives a key from a password and salt using the scrypt algorithm.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[corresponds(EVP_PBE_scrypt)]
|
||||
#[cfg(any(ossl110))]
|
||||
pub fn scrypt(
|
||||
pass: &[u8],
|
||||
salt: &[u8],
|
||||
n: u64,
|
||||
r: u64,
|
||||
p: u64,
|
||||
maxmem: u64,
|
||||
key: &mut [u8],
|
||||
) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
cvt(ffi::EVP_PBE_scrypt(
|
||||
pass.as_ptr() as *const _,
|
||||
pass.len(),
|
||||
salt.as_ptr() as *const _,
|
||||
salt.len(),
|
||||
n,
|
||||
r,
|
||||
p,
|
||||
maxmem,
|
||||
key.as_mut_ptr() as *mut _,
|
||||
key.len(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::symm::Cipher;
|
||||
|
||||
// Test vectors from
|
||||
// https://git.lysator.liu.se/nettle/nettle/blob/nettle_3.1.1_release_20150424/testsuite/pbkdf2-test.c
|
||||
#[test]
|
||||
fn pbkdf2_hmac_sha256() {
|
||||
let mut buf = [0; 16];
|
||||
|
||||
super::pbkdf2_hmac(b"passwd", b"salt", 1, MessageDigest::sha256(), &mut buf).unwrap();
|
||||
assert_eq!(
|
||||
buf,
|
||||
&[
|
||||
0x55_u8, 0xac_u8, 0x04_u8, 0x6e_u8, 0x56_u8, 0xe3_u8, 0x08_u8, 0x9f_u8, 0xec_u8,
|
||||
0x16_u8, 0x91_u8, 0xc2_u8, 0x25_u8, 0x44_u8, 0xb6_u8, 0x05_u8,
|
||||
][..]
|
||||
);
|
||||
|
||||
super::pbkdf2_hmac(
|
||||
b"Password",
|
||||
b"NaCl",
|
||||
80000,
|
||||
MessageDigest::sha256(),
|
||||
&mut buf,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
buf,
|
||||
&[
|
||||
0x4d_u8, 0xdc_u8, 0xd8_u8, 0xf6_u8, 0x0b_u8, 0x98_u8, 0xbe_u8, 0x21_u8, 0x83_u8,
|
||||
0x0c_u8, 0xee_u8, 0x5e_u8, 0xf2_u8, 0x27_u8, 0x01_u8, 0xf9_u8,
|
||||
][..]
|
||||
);
|
||||
}
|
||||
|
||||
// Test vectors from
|
||||
// https://git.lysator.liu.se/nettle/nettle/blob/nettle_3.1.1_release_20150424/testsuite/pbkdf2-test.c
|
||||
#[test]
|
||||
fn pbkdf2_hmac_sha512() {
|
||||
let mut buf = [0; 64];
|
||||
|
||||
super::pbkdf2_hmac(b"password", b"NaCL", 1, MessageDigest::sha512(), &mut buf).unwrap();
|
||||
assert_eq!(
|
||||
&buf[..],
|
||||
&[
|
||||
0x73_u8, 0xde_u8, 0xcf_u8, 0xa5_u8, 0x8a_u8, 0xa2_u8, 0xe8_u8, 0x4f_u8, 0x94_u8,
|
||||
0x77_u8, 0x1a_u8, 0x75_u8, 0x73_u8, 0x6b_u8, 0xb8_u8, 0x8b_u8, 0xd3_u8, 0xc7_u8,
|
||||
0xb3_u8, 0x82_u8, 0x70_u8, 0xcf_u8, 0xb5_u8, 0x0c_u8, 0xb3_u8, 0x90_u8, 0xed_u8,
|
||||
0x78_u8, 0xb3_u8, 0x05_u8, 0x65_u8, 0x6a_u8, 0xf8_u8, 0x14_u8, 0x8e_u8, 0x52_u8,
|
||||
0x45_u8, 0x2b_u8, 0x22_u8, 0x16_u8, 0xb2_u8, 0xb8_u8, 0x09_u8, 0x8b_u8, 0x76_u8,
|
||||
0x1f_u8, 0xc6_u8, 0x33_u8, 0x60_u8, 0x60_u8, 0xa0_u8, 0x9f_u8, 0x76_u8, 0x41_u8,
|
||||
0x5e_u8, 0x9f_u8, 0x71_u8, 0xea_u8, 0x47_u8, 0xf9_u8, 0xe9_u8, 0x06_u8, 0x43_u8,
|
||||
0x06_u8,
|
||||
][..]
|
||||
);
|
||||
|
||||
super::pbkdf2_hmac(
|
||||
b"pass\0word",
|
||||
b"sa\0lt",
|
||||
1,
|
||||
MessageDigest::sha512(),
|
||||
&mut buf,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
&buf[..],
|
||||
&[
|
||||
0x71_u8, 0xa0_u8, 0xec_u8, 0x84_u8, 0x2a_u8, 0xbd_u8, 0x5c_u8, 0x67_u8, 0x8b_u8,
|
||||
0xcf_u8, 0xd1_u8, 0x45_u8, 0xf0_u8, 0x9d_u8, 0x83_u8, 0x52_u8, 0x2f_u8, 0x93_u8,
|
||||
0x36_u8, 0x15_u8, 0x60_u8, 0x56_u8, 0x3c_u8, 0x4d_u8, 0x0d_u8, 0x63_u8, 0xb8_u8,
|
||||
0x83_u8, 0x29_u8, 0x87_u8, 0x10_u8, 0x90_u8, 0xe7_u8, 0x66_u8, 0x04_u8, 0xa4_u8,
|
||||
0x9a_u8, 0xf0_u8, 0x8f_u8, 0xe7_u8, 0xc9_u8, 0xf5_u8, 0x71_u8, 0x56_u8, 0xc8_u8,
|
||||
0x79_u8, 0x09_u8, 0x96_u8, 0xb2_u8, 0x0f_u8, 0x06_u8, 0xbc_u8, 0x53_u8, 0x5e_u8,
|
||||
0x5a_u8, 0xb5_u8, 0x44_u8, 0x0d_u8, 0xf7_u8, 0xe8_u8, 0x78_u8, 0x29_u8, 0x6f_u8,
|
||||
0xa7_u8,
|
||||
][..]
|
||||
);
|
||||
|
||||
super::pbkdf2_hmac(
|
||||
b"passwordPASSWORDpassword",
|
||||
b"salt\0\0\0",
|
||||
50,
|
||||
MessageDigest::sha512(),
|
||||
&mut buf,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
&buf[..],
|
||||
&[
|
||||
0x01_u8, 0x68_u8, 0x71_u8, 0xa4_u8, 0xc4_u8, 0xb7_u8, 0x5f_u8, 0x96_u8, 0x85_u8,
|
||||
0x7f_u8, 0xd2_u8, 0xb9_u8, 0xf8_u8, 0xca_u8, 0x28_u8, 0x02_u8, 0x3b_u8, 0x30_u8,
|
||||
0xee_u8, 0x2a_u8, 0x39_u8, 0xf5_u8, 0xad_u8, 0xca_u8, 0xc8_u8, 0xc9_u8, 0x37_u8,
|
||||
0x5f_u8, 0x9b_u8, 0xda_u8, 0x1c_u8, 0xcd_u8, 0x1b_u8, 0x6f_u8, 0x0b_u8, 0x2f_u8,
|
||||
0xc3_u8, 0xad_u8, 0xda_u8, 0x50_u8, 0x54_u8, 0x12_u8, 0xe7_u8, 0x9d_u8, 0x89_u8,
|
||||
0x00_u8, 0x56_u8, 0xc6_u8, 0x2e_u8, 0x52_u8, 0x4c_u8, 0x7d_u8, 0x51_u8, 0x15_u8,
|
||||
0x4b_u8, 0x1a_u8, 0x85_u8, 0x34_u8, 0x57_u8, 0x5b_u8, 0xd0_u8, 0x2d_u8, 0xee_u8,
|
||||
0x39_u8,
|
||||
][..]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_to_key() {
|
||||
let salt = [16_u8, 34_u8, 19_u8, 23_u8, 141_u8, 4_u8, 207_u8, 221_u8];
|
||||
|
||||
let data = [
|
||||
143_u8, 210_u8, 75_u8, 63_u8, 214_u8, 179_u8, 155_u8, 241_u8, 242_u8, 31_u8, 154_u8,
|
||||
56_u8, 198_u8, 145_u8, 192_u8, 64_u8, 2_u8, 245_u8, 167_u8, 220_u8, 55_u8, 119_u8,
|
||||
233_u8, 136_u8, 139_u8, 27_u8, 71_u8, 242_u8, 119_u8, 175_u8, 65_u8, 207_u8,
|
||||
];
|
||||
|
||||
let expected_key = vec![
|
||||
249_u8, 115_u8, 114_u8, 97_u8, 32_u8, 213_u8, 165_u8, 146_u8, 58_u8, 87_u8, 234_u8,
|
||||
3_u8, 43_u8, 250_u8, 97_u8, 114_u8, 26_u8, 98_u8, 245_u8, 246_u8, 238_u8, 177_u8,
|
||||
229_u8, 161_u8, 183_u8, 224_u8, 174_u8, 3_u8, 6_u8, 244_u8, 236_u8, 255_u8,
|
||||
];
|
||||
let expected_iv = vec![
|
||||
4_u8, 223_u8, 153_u8, 219_u8, 28_u8, 142_u8, 234_u8, 68_u8, 227_u8, 69_u8, 98_u8,
|
||||
107_u8, 208_u8, 14_u8, 236_u8, 60_u8,
|
||||
];
|
||||
|
||||
assert_eq!(
|
||||
super::bytes_to_key(
|
||||
Cipher::aes_256_cbc(),
|
||||
MessageDigest::sha1(),
|
||||
&data,
|
||||
Some(&salt),
|
||||
1,
|
||||
)
|
||||
.unwrap(),
|
||||
super::KeyIvPair {
|
||||
key: expected_key,
|
||||
iv: Some(expected_iv),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl110))]
|
||||
fn scrypt() {
|
||||
let pass = "pleaseletmein";
|
||||
let salt = "SodiumChloride";
|
||||
let expected =
|
||||
"7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613\
|
||||
f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887";
|
||||
|
||||
let mut actual = [0; 64];
|
||||
super::scrypt(
|
||||
pass.as_bytes(),
|
||||
salt.as_bytes(),
|
||||
16384,
|
||||
8,
|
||||
1,
|
||||
0,
|
||||
&mut actual,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(hex::encode(&actual[..]), expected);
|
||||
}
|
||||
}
|
||||
442
zeroidc/vendor/openssl/src/pkcs7.rs
vendored
Normal file
442
zeroidc/vendor/openssl/src/pkcs7.rs
vendored
Normal file
@@ -0,0 +1,442 @@
|
||||
use bitflags::bitflags;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::c_int;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use crate::bio::{MemBio, MemBioSlice};
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasPrivate, PKeyRef};
|
||||
use crate::stack::{Stack, StackRef};
|
||||
use crate::symm::Cipher;
|
||||
use crate::x509::store::X509StoreRef;
|
||||
use crate::x509::{X509Ref, X509};
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::PKCS7;
|
||||
fn drop = ffi::PKCS7_free;
|
||||
|
||||
/// A PKCS#7 structure.
|
||||
///
|
||||
/// Contains signed and/or encrypted data.
|
||||
pub struct Pkcs7;
|
||||
|
||||
/// Reference to `Pkcs7`
|
||||
pub struct Pkcs7Ref;
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct Pkcs7Flags: c_int {
|
||||
const TEXT = ffi::PKCS7_TEXT;
|
||||
const NOCERTS = ffi::PKCS7_NOCERTS;
|
||||
const NOSIGS = ffi::PKCS7_NOSIGS;
|
||||
const NOCHAIN = ffi::PKCS7_NOCHAIN;
|
||||
const NOINTERN = ffi::PKCS7_NOINTERN;
|
||||
const NOVERIFY = ffi::PKCS7_NOVERIFY;
|
||||
const DETACHED = ffi::PKCS7_DETACHED;
|
||||
const BINARY = ffi::PKCS7_BINARY;
|
||||
const NOATTR = ffi::PKCS7_NOATTR;
|
||||
const NOSMIMECAP = ffi::PKCS7_NOSMIMECAP;
|
||||
const NOOLDMIMETYPE = ffi::PKCS7_NOOLDMIMETYPE;
|
||||
const CRLFEOL = ffi::PKCS7_CRLFEOL;
|
||||
const STREAM = ffi::PKCS7_STREAM;
|
||||
const NOCRL = ffi::PKCS7_NOCRL;
|
||||
const PARTIAL = ffi::PKCS7_PARTIAL;
|
||||
const REUSE_DIGEST = ffi::PKCS7_REUSE_DIGEST;
|
||||
#[cfg(not(any(ossl101, ossl102, libressl)))]
|
||||
const NO_DUAL_CONTENT = ffi::PKCS7_NO_DUAL_CONTENT;
|
||||
}
|
||||
}
|
||||
|
||||
impl Pkcs7 {
|
||||
from_pem! {
|
||||
/// Deserializes a PEM-encoded PKCS#7 signature
|
||||
///
|
||||
/// The input should have a header of `-----BEGIN PKCS7-----`.
|
||||
#[corresponds(PEM_read_bio_PKCS7)]
|
||||
from_pem,
|
||||
Pkcs7,
|
||||
ffi::PEM_read_bio_PKCS7
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Deserializes a DER-encoded PKCS#7 signature
|
||||
#[corresponds(d2i_PKCS7)]
|
||||
from_der,
|
||||
Pkcs7,
|
||||
ffi::d2i_PKCS7
|
||||
}
|
||||
|
||||
/// Parses a message in S/MIME format.
|
||||
///
|
||||
/// Returns the loaded signature, along with the cleartext message (if
|
||||
/// available).
|
||||
#[corresponds(SMIME_read_PKCS7)]
|
||||
pub fn from_smime(input: &[u8]) -> Result<(Pkcs7, Option<Vec<u8>>), ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
let input_bio = MemBioSlice::new(input)?;
|
||||
let mut bcont_bio = ptr::null_mut();
|
||||
unsafe {
|
||||
let pkcs7 =
|
||||
cvt_p(ffi::SMIME_read_PKCS7(input_bio.as_ptr(), &mut bcont_bio)).map(Pkcs7)?;
|
||||
let out = if !bcont_bio.is_null() {
|
||||
let bcont_bio = MemBio::from_ptr(bcont_bio);
|
||||
Some(bcont_bio.get_buf().to_vec())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok((pkcs7, out))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates and returns a PKCS#7 `envelopedData` structure.
|
||||
///
|
||||
/// `certs` is a list of recipient certificates. `input` is the content to be
|
||||
/// encrypted. `cipher` is the symmetric cipher to use. `flags` is an optional
|
||||
/// set of flags.
|
||||
#[corresponds(PKCS7_encrypt)]
|
||||
pub fn encrypt(
|
||||
certs: &StackRef<X509>,
|
||||
input: &[u8],
|
||||
cipher: Cipher,
|
||||
flags: Pkcs7Flags,
|
||||
) -> Result<Pkcs7, ErrorStack> {
|
||||
let input_bio = MemBioSlice::new(input)?;
|
||||
|
||||
unsafe {
|
||||
cvt_p(ffi::PKCS7_encrypt(
|
||||
certs.as_ptr(),
|
||||
input_bio.as_ptr(),
|
||||
cipher.as_ptr(),
|
||||
flags.bits,
|
||||
))
|
||||
.map(Pkcs7)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates and returns a PKCS#7 `signedData` structure.
|
||||
///
|
||||
/// `signcert` is the certificate to sign with, `pkey` is the corresponding
|
||||
/// private key. `certs` is an optional additional set of certificates to
|
||||
/// include in the PKCS#7 structure (for example any intermediate CAs in the
|
||||
/// chain).
|
||||
#[corresponds(PKCS7_sign)]
|
||||
pub fn sign<PT>(
|
||||
signcert: &X509Ref,
|
||||
pkey: &PKeyRef<PT>,
|
||||
certs: &StackRef<X509>,
|
||||
input: &[u8],
|
||||
flags: Pkcs7Flags,
|
||||
) -> Result<Pkcs7, ErrorStack>
|
||||
where
|
||||
PT: HasPrivate,
|
||||
{
|
||||
let input_bio = MemBioSlice::new(input)?;
|
||||
unsafe {
|
||||
cvt_p(ffi::PKCS7_sign(
|
||||
signcert.as_ptr(),
|
||||
pkey.as_ptr(),
|
||||
certs.as_ptr(),
|
||||
input_bio.as_ptr(),
|
||||
flags.bits,
|
||||
))
|
||||
.map(Pkcs7)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pkcs7Ref {
|
||||
/// Converts PKCS#7 structure to S/MIME format
|
||||
#[corresponds(SMIME_write_PKCS7)]
|
||||
pub fn to_smime(&self, input: &[u8], flags: Pkcs7Flags) -> Result<Vec<u8>, ErrorStack> {
|
||||
let input_bio = MemBioSlice::new(input)?;
|
||||
let output = MemBio::new()?;
|
||||
unsafe {
|
||||
cvt(ffi::SMIME_write_PKCS7(
|
||||
output.as_ptr(),
|
||||
self.as_ptr(),
|
||||
input_bio.as_ptr(),
|
||||
flags.bits,
|
||||
))
|
||||
.map(|_| output.get_buf().to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
to_pem! {
|
||||
/// Serializes the data into a PEM-encoded PKCS#7 structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN PKCS7-----`.
|
||||
#[corresponds(PEM_write_bio_PKCS7)]
|
||||
to_pem,
|
||||
ffi::PEM_write_bio_PKCS7
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes the data into a DER-encoded PKCS#7 structure.
|
||||
#[corresponds(i2d_PKCS7)]
|
||||
to_der,
|
||||
ffi::i2d_PKCS7
|
||||
}
|
||||
|
||||
/// Decrypts data using the provided private key.
|
||||
///
|
||||
/// `pkey` is the recipient's private key, and `cert` is the recipient's
|
||||
/// certificate.
|
||||
///
|
||||
/// Returns the decrypted message.
|
||||
#[corresponds(PKCS7_decrypt)]
|
||||
pub fn decrypt<PT>(
|
||||
&self,
|
||||
pkey: &PKeyRef<PT>,
|
||||
cert: &X509Ref,
|
||||
flags: Pkcs7Flags,
|
||||
) -> Result<Vec<u8>, ErrorStack>
|
||||
where
|
||||
PT: HasPrivate,
|
||||
{
|
||||
let output = MemBio::new()?;
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::PKCS7_decrypt(
|
||||
self.as_ptr(),
|
||||
pkey.as_ptr(),
|
||||
cert.as_ptr(),
|
||||
output.as_ptr(),
|
||||
flags.bits,
|
||||
))
|
||||
.map(|_| output.get_buf().to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
/// Verifies the PKCS#7 `signedData` structure contained by `&self`.
|
||||
///
|
||||
/// `certs` is a set of certificates in which to search for the signer's
|
||||
/// certificate. `store` is a trusted certificate store (used for chain
|
||||
/// verification). `indata` is the signed data if the content is not present
|
||||
/// in `&self`. The content is written to `out` if it is not `None`.
|
||||
#[corresponds(PKCS7_verify)]
|
||||
pub fn verify(
|
||||
&self,
|
||||
certs: &StackRef<X509>,
|
||||
store: &X509StoreRef,
|
||||
indata: Option<&[u8]>,
|
||||
out: Option<&mut Vec<u8>>,
|
||||
flags: Pkcs7Flags,
|
||||
) -> Result<(), ErrorStack> {
|
||||
let out_bio = MemBio::new()?;
|
||||
|
||||
let indata_bio = match indata {
|
||||
Some(data) => Some(MemBioSlice::new(data)?),
|
||||
None => None,
|
||||
};
|
||||
let indata_bio_ptr = indata_bio.as_ref().map_or(ptr::null_mut(), |p| p.as_ptr());
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::PKCS7_verify(
|
||||
self.as_ptr(),
|
||||
certs.as_ptr(),
|
||||
store.as_ptr(),
|
||||
indata_bio_ptr,
|
||||
out_bio.as_ptr(),
|
||||
flags.bits,
|
||||
))
|
||||
.map(|_| ())?
|
||||
}
|
||||
|
||||
if let Some(data) = out {
|
||||
data.clear();
|
||||
data.extend_from_slice(out_bio.get_buf());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Retrieve the signer's certificates from the PKCS#7 structure without verifying them.
|
||||
#[corresponds(PKCS7_get0_signers)]
|
||||
pub fn signers(
|
||||
&self,
|
||||
certs: &StackRef<X509>,
|
||||
flags: Pkcs7Flags,
|
||||
) -> Result<Stack<X509>, ErrorStack> {
|
||||
unsafe {
|
||||
let ptr = cvt_p(ffi::PKCS7_get0_signers(
|
||||
self.as_ptr(),
|
||||
certs.as_ptr(),
|
||||
flags.bits,
|
||||
))?;
|
||||
|
||||
// The returned stack is owned by the caller, but the certs inside are not! Our stack interface can't deal
|
||||
// with that, so instead we just manually bump the refcount of the certs so that the whole stack is properly
|
||||
// owned.
|
||||
let stack = Stack::<X509>::from_ptr(ptr);
|
||||
for cert in &stack {
|
||||
mem::forget(cert.to_owned());
|
||||
}
|
||||
|
||||
Ok(stack)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::pkcs7::{Pkcs7, Pkcs7Flags};
|
||||
use crate::pkey::PKey;
|
||||
use crate::stack::Stack;
|
||||
use crate::symm::Cipher;
|
||||
use crate::x509::store::X509StoreBuilder;
|
||||
use crate::x509::X509;
|
||||
|
||||
#[test]
|
||||
fn encrypt_decrypt_test() {
|
||||
let cert = include_bytes!("../test/certs.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let mut certs = Stack::new().unwrap();
|
||||
certs.push(cert.clone()).unwrap();
|
||||
let message: String = String::from("foo");
|
||||
let cipher = Cipher::des_ede3_cbc();
|
||||
let flags = Pkcs7Flags::STREAM;
|
||||
let pkey = include_bytes!("../test/key.pem");
|
||||
let pkey = PKey::private_key_from_pem(pkey).unwrap();
|
||||
|
||||
let pkcs7 =
|
||||
Pkcs7::encrypt(&certs, message.as_bytes(), cipher, flags).expect("should succeed");
|
||||
|
||||
let encrypted = pkcs7
|
||||
.to_smime(message.as_bytes(), flags)
|
||||
.expect("should succeed");
|
||||
|
||||
let (pkcs7_decoded, _) = Pkcs7::from_smime(encrypted.as_slice()).expect("should succeed");
|
||||
|
||||
let decoded = pkcs7_decoded
|
||||
.decrypt(&pkey, &cert, Pkcs7Flags::empty())
|
||||
.expect("should succeed");
|
||||
|
||||
assert_eq!(decoded, message.into_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sign_verify_test_detached() {
|
||||
let cert = include_bytes!("../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let certs = Stack::new().unwrap();
|
||||
let message = "foo";
|
||||
let flags = Pkcs7Flags::STREAM | Pkcs7Flags::DETACHED;
|
||||
let pkey = include_bytes!("../test/key.pem");
|
||||
let pkey = PKey::private_key_from_pem(pkey).unwrap();
|
||||
let mut store_builder = X509StoreBuilder::new().expect("should succeed");
|
||||
|
||||
let root_ca = include_bytes!("../test/root-ca.pem");
|
||||
let root_ca = X509::from_pem(root_ca).unwrap();
|
||||
store_builder.add_cert(root_ca).expect("should succeed");
|
||||
|
||||
let store = store_builder.build();
|
||||
|
||||
let pkcs7 =
|
||||
Pkcs7::sign(&cert, &pkey, &certs, message.as_bytes(), flags).expect("should succeed");
|
||||
|
||||
let signed = pkcs7
|
||||
.to_smime(message.as_bytes(), flags)
|
||||
.expect("should succeed");
|
||||
println!("{:?}", String::from_utf8(signed.clone()).unwrap());
|
||||
let (pkcs7_decoded, content) =
|
||||
Pkcs7::from_smime(signed.as_slice()).expect("should succeed");
|
||||
|
||||
let mut output = Vec::new();
|
||||
pkcs7_decoded
|
||||
.verify(
|
||||
&certs,
|
||||
&store,
|
||||
Some(message.as_bytes()),
|
||||
Some(&mut output),
|
||||
flags,
|
||||
)
|
||||
.expect("should succeed");
|
||||
|
||||
assert_eq!(output, message.as_bytes());
|
||||
assert_eq!(content.expect("should be non-empty"), message.as_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sign_verify_test_normal() {
|
||||
let cert = include_bytes!("../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let certs = Stack::new().unwrap();
|
||||
let message = "foo";
|
||||
let flags = Pkcs7Flags::STREAM;
|
||||
let pkey = include_bytes!("../test/key.pem");
|
||||
let pkey = PKey::private_key_from_pem(pkey).unwrap();
|
||||
let mut store_builder = X509StoreBuilder::new().expect("should succeed");
|
||||
|
||||
let root_ca = include_bytes!("../test/root-ca.pem");
|
||||
let root_ca = X509::from_pem(root_ca).unwrap();
|
||||
store_builder.add_cert(root_ca).expect("should succeed");
|
||||
|
||||
let store = store_builder.build();
|
||||
|
||||
let pkcs7 =
|
||||
Pkcs7::sign(&cert, &pkey, &certs, message.as_bytes(), flags).expect("should succeed");
|
||||
|
||||
let signed = pkcs7
|
||||
.to_smime(message.as_bytes(), flags)
|
||||
.expect("should succeed");
|
||||
|
||||
let (pkcs7_decoded, content) =
|
||||
Pkcs7::from_smime(signed.as_slice()).expect("should succeed");
|
||||
|
||||
let mut output = Vec::new();
|
||||
pkcs7_decoded
|
||||
.verify(&certs, &store, None, Some(&mut output), flags)
|
||||
.expect("should succeed");
|
||||
|
||||
assert_eq!(output, message.as_bytes());
|
||||
assert!(content.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn signers() {
|
||||
let cert = include_bytes!("../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let cert_digest = cert.digest(MessageDigest::sha256()).unwrap();
|
||||
let certs = Stack::new().unwrap();
|
||||
let message = "foo";
|
||||
let flags = Pkcs7Flags::STREAM;
|
||||
let pkey = include_bytes!("../test/key.pem");
|
||||
let pkey = PKey::private_key_from_pem(pkey).unwrap();
|
||||
let mut store_builder = X509StoreBuilder::new().expect("should succeed");
|
||||
|
||||
let root_ca = include_bytes!("../test/root-ca.pem");
|
||||
let root_ca = X509::from_pem(root_ca).unwrap();
|
||||
store_builder.add_cert(root_ca).expect("should succeed");
|
||||
|
||||
let pkcs7 =
|
||||
Pkcs7::sign(&cert, &pkey, &certs, message.as_bytes(), flags).expect("should succeed");
|
||||
|
||||
let signed = pkcs7
|
||||
.to_smime(message.as_bytes(), flags)
|
||||
.expect("should succeed");
|
||||
|
||||
let (pkcs7_decoded, _) = Pkcs7::from_smime(signed.as_slice()).expect("should succeed");
|
||||
|
||||
let empty_certs = Stack::new().unwrap();
|
||||
let signer_certs = pkcs7_decoded
|
||||
.signers(&empty_certs, flags)
|
||||
.expect("should succeed");
|
||||
assert_eq!(empty_certs.len(), 0);
|
||||
assert_eq!(signer_certs.len(), 1);
|
||||
let signer_digest = signer_certs[0].digest(MessageDigest::sha256()).unwrap();
|
||||
assert_eq!(*cert_digest, *signer_digest);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_from_smime() {
|
||||
let input = String::from("Invalid SMIME Message");
|
||||
let result = Pkcs7::from_smime(input.as_bytes());
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
||||
1029
zeroidc/vendor/openssl/src/pkey.rs
vendored
Normal file
1029
zeroidc/vendor/openssl/src/pkey.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
760
zeroidc/vendor/openssl/src/pkey_ctx.rs
vendored
Normal file
760
zeroidc/vendor/openssl/src/pkey_ctx.rs
vendored
Normal file
@@ -0,0 +1,760 @@
|
||||
//! The asymmetric encryption context.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Encrypt data with RSA
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::rsa::Rsa;
|
||||
//! use openssl::pkey::PKey;
|
||||
//! use openssl::pkey_ctx::PkeyCtx;
|
||||
//!
|
||||
//! let key = Rsa::generate(4096).unwrap();
|
||||
//! let key = PKey::from_rsa(key).unwrap();
|
||||
//!
|
||||
//! let mut ctx = PkeyCtx::new(&key).unwrap();
|
||||
//! ctx.encrypt_init().unwrap();
|
||||
//!
|
||||
//! let data = b"Some Crypto Text";
|
||||
//! let mut ciphertext = vec![];
|
||||
//! ctx.encrypt_to_vec(data, &mut ciphertext).unwrap();
|
||||
//! ```
|
||||
//!
|
||||
//! Generate a CMAC key
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::pkey_ctx::PkeyCtx;
|
||||
//! use openssl::pkey::Id;
|
||||
//! use openssl::cipher::Cipher;
|
||||
//!
|
||||
//! let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap();
|
||||
//! ctx.keygen_init().unwrap();
|
||||
//! ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap();
|
||||
//! ctx.set_keygen_mac_key(b"0123456789abcdef").unwrap();
|
||||
//! let cmac_key = ctx.keygen().unwrap();
|
||||
//! ```
|
||||
//!
|
||||
//! Sign and verify data with RSA
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::pkey_ctx::PkeyCtx;
|
||||
//! use openssl::pkey::PKey;
|
||||
//! use openssl::rsa::Rsa;
|
||||
//!
|
||||
//! // Generate a random RSA key.
|
||||
//! let key = Rsa::generate(4096).unwrap();
|
||||
//! let key = PKey::from_rsa(key).unwrap();
|
||||
//!
|
||||
//! let text = b"Some Crypto Text";
|
||||
//!
|
||||
//! // Create the signature.
|
||||
//! let mut ctx = PkeyCtx::new(&key).unwrap();
|
||||
//! ctx.sign_init().unwrap();
|
||||
//! let mut signature = vec![];
|
||||
//! ctx.sign_to_vec(text, &mut signature).unwrap();
|
||||
//!
|
||||
//! // Verify the signature.
|
||||
//! let mut ctx = PkeyCtx::new(&key).unwrap();
|
||||
//! ctx.verify_init().unwrap();
|
||||
//! let valid = ctx.verify(text, &signature).unwrap();
|
||||
//! assert!(valid);
|
||||
//! ```
|
||||
use crate::cipher::CipherRef;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::md::MdRef;
|
||||
use crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Private};
|
||||
use crate::rsa::Padding;
|
||||
use crate::{cvt, cvt_n, cvt_p};
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::c_int;
|
||||
use openssl_macros::corresponds;
|
||||
use std::convert::TryFrom;
|
||||
use std::ptr;
|
||||
|
||||
/// HKDF modes of operation.
|
||||
#[cfg(ossl111)]
|
||||
pub struct HkdfMode(c_int);
|
||||
|
||||
#[cfg(ossl111)]
|
||||
impl HkdfMode {
|
||||
pub const EXTRACT_THEN_EXPAND: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND);
|
||||
pub const EXTRACT_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY);
|
||||
pub const EXPAND_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXPAND_ONLY);
|
||||
}
|
||||
|
||||
generic_foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::EVP_PKEY_CTX;
|
||||
fn drop = ffi::EVP_PKEY_CTX_free;
|
||||
|
||||
/// A context object which can perform asymmetric cryptography operations.
|
||||
pub struct PkeyCtx<T>;
|
||||
/// A reference to a [`PkeyCtx`].
|
||||
pub struct PkeyCtxRef<T>;
|
||||
}
|
||||
|
||||
impl<T> PkeyCtx<T> {
|
||||
/// Creates a new pkey context using the provided key.
|
||||
#[corresponds(EVP_PKEY_CTX_new)]
|
||||
#[inline]
|
||||
pub fn new(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack> {
|
||||
unsafe {
|
||||
let ptr = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?;
|
||||
Ok(PkeyCtx::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PkeyCtx<()> {
|
||||
/// Creates a new pkey context for the specified algorithm ID.
|
||||
#[corresponds(EVP_PKEY_new_id)]
|
||||
#[inline]
|
||||
pub fn new_id(id: Id) -> Result<Self, ErrorStack> {
|
||||
unsafe {
|
||||
let ptr = cvt_p(ffi::EVP_PKEY_CTX_new_id(id.as_raw(), ptr::null_mut()))?;
|
||||
Ok(PkeyCtx::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PkeyCtxRef<T>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
/// Prepares the context for encryption using the public key.
|
||||
#[corresponds(EVP_PKEY_encrypt_init)]
|
||||
#[inline]
|
||||
pub fn encrypt_init(&mut self) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_encrypt_init(self.as_ptr()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Prepares the context for signature verification using the public key.
|
||||
#[corresponds(EVP_PKEY_verify_init)]
|
||||
#[inline]
|
||||
pub fn verify_init(&mut self) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_verify_init(self.as_ptr()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Encrypts data using the public key.
|
||||
///
|
||||
/// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
|
||||
/// returned.
|
||||
#[corresponds(EVP_PKEY_encrypt)]
|
||||
#[inline]
|
||||
pub fn encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
|
||||
let mut written = to.as_ref().map_or(0, |b| b.len());
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_encrypt(
|
||||
self.as_ptr(),
|
||||
to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
|
||||
&mut written,
|
||||
from.as_ptr(),
|
||||
from.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
/// Like [`Self::encrypt`] but appends ciphertext to a [`Vec`].
|
||||
pub fn encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
|
||||
let base = out.len();
|
||||
let len = self.encrypt(from, None)?;
|
||||
out.resize(base + len, 0);
|
||||
let len = self.encrypt(from, Some(&mut out[base..]))?;
|
||||
out.truncate(base + len);
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Verifies the signature of data using the public key.
|
||||
///
|
||||
/// Returns `Ok(true)` if the signature is valid, `Ok(false)` if the signature is invalid, and `Err` if an error
|
||||
/// occurred.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This verifies the signature of the *raw* data. It is more common to compute and verify the signature of the
|
||||
/// cryptographic hash of an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do
|
||||
/// that.
|
||||
#[corresponds(EVP_PKEY_verify)]
|
||||
#[inline]
|
||||
pub fn verify(&mut self, data: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
let r = cvt_n(ffi::EVP_PKEY_verify(
|
||||
self.as_ptr(),
|
||||
sig.as_ptr(),
|
||||
sig.len(),
|
||||
data.as_ptr(),
|
||||
data.len(),
|
||||
))?;
|
||||
Ok(r == 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PkeyCtxRef<T>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
/// Prepares the context for decryption using the private key.
|
||||
#[corresponds(EVP_PKEY_decrypt_init)]
|
||||
#[inline]
|
||||
pub fn decrypt_init(&mut self) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_decrypt_init(self.as_ptr()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Prepares the context for signing using the private key.
|
||||
#[corresponds(EVP_PKEY_sign_init)]
|
||||
#[inline]
|
||||
pub fn sign_init(&mut self) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_sign_init(self.as_ptr()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the peer key used for secret derivation.
|
||||
#[corresponds(EVP_PKEY_derive_set_peer)]
|
||||
pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack>
|
||||
where
|
||||
U: HasPublic,
|
||||
{
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), key.as_ptr()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Decrypts data using the private key.
|
||||
///
|
||||
/// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
|
||||
/// returned.
|
||||
#[corresponds(EVP_PKEY_decrypt)]
|
||||
#[inline]
|
||||
pub fn decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
|
||||
let mut written = to.as_ref().map_or(0, |b| b.len());
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_decrypt(
|
||||
self.as_ptr(),
|
||||
to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
|
||||
&mut written,
|
||||
from.as_ptr(),
|
||||
from.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
/// Like [`Self::decrypt`] but appends plaintext to a [`Vec`].
|
||||
pub fn decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
|
||||
let base = out.len();
|
||||
let len = self.decrypt(from, None)?;
|
||||
out.resize(base + len, 0);
|
||||
let len = self.decrypt(from, Some(&mut out[base..]))?;
|
||||
out.truncate(base + len);
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Signs the contents of `data`.
|
||||
///
|
||||
/// If `sig` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
|
||||
/// returned.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This computes the signature of the *raw* bytes of `data`. It is more common to sign the cryptographic hash of
|
||||
/// an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do that.
|
||||
#[corresponds(EVP_PKEY_sign)]
|
||||
#[inline]
|
||||
pub fn sign(&mut self, data: &[u8], sig: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
|
||||
let mut written = sig.as_ref().map_or(0, |b| b.len());
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_sign(
|
||||
self.as_ptr(),
|
||||
sig.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
|
||||
&mut written,
|
||||
data.as_ptr(),
|
||||
data.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
/// Like [`Self::sign`] but appends the signature to a [`Vec`].
|
||||
pub fn sign_to_vec(&mut self, data: &[u8], sig: &mut Vec<u8>) -> Result<usize, ErrorStack> {
|
||||
let base = sig.len();
|
||||
let len = self.sign(data, None)?;
|
||||
sig.resize(base + len, 0);
|
||||
let len = self.sign(data, Some(&mut sig[base..]))?;
|
||||
sig.truncate(base + len);
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PkeyCtxRef<T> {
|
||||
/// Prepares the context for shared secret derivation.
|
||||
#[corresponds(EVP_PKEY_derive_init)]
|
||||
#[inline]
|
||||
pub fn derive_init(&mut self) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_derive_init(self.as_ptr()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Prepares the context for key generation.
|
||||
#[corresponds(EVP_PKEY_keygen_init)]
|
||||
#[inline]
|
||||
pub fn keygen_init(&mut self) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_keygen_init(self.as_ptr()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns the RSA padding mode in use.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
#[corresponds(EVP_PKEY_CTX_get_rsa_padding)]
|
||||
#[inline]
|
||||
pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
|
||||
let mut pad = 0;
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))?;
|
||||
}
|
||||
|
||||
Ok(Padding::from_raw(pad))
|
||||
}
|
||||
|
||||
/// Sets the RSA padding mode.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
#[corresponds(EVP_PKEY_CTX_set_rsa_padding)]
|
||||
#[inline]
|
||||
pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
|
||||
self.as_ptr(),
|
||||
padding.as_raw(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the RSA MGF1 algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
#[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)]
|
||||
#[inline]
|
||||
pub fn set_rsa_mgf1_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
|
||||
self.as_ptr(),
|
||||
md.as_ptr(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the RSA OAEP algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
#[corresponds(EVP_PKEY_CTX_set_rsa_oaep_md)]
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
#[inline]
|
||||
pub fn set_rsa_oaep_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
|
||||
self.as_ptr(),
|
||||
md.as_ptr() as *mut _,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the RSA OAEP label.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
#[corresponds(EVP_PKEY_CTX_set0_rsa_oaep_label)]
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
|
||||
let len = c_int::try_from(label.len()).unwrap();
|
||||
|
||||
unsafe {
|
||||
let p = ffi::OPENSSL_malloc(label.len() as _);
|
||||
ptr::copy_nonoverlapping(label.as_ptr(), p as *mut _, label.len());
|
||||
|
||||
let r = cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(self.as_ptr(), p, len));
|
||||
if r.is_err() {
|
||||
ffi::OPENSSL_free(p);
|
||||
}
|
||||
r?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the cipher used during key generation.
|
||||
#[corresponds(EVP_PKEY_CTX_ctrl)]
|
||||
#[inline]
|
||||
pub fn set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_ctrl(
|
||||
self.as_ptr(),
|
||||
-1,
|
||||
ffi::EVP_PKEY_OP_KEYGEN,
|
||||
ffi::EVP_PKEY_CTRL_CIPHER,
|
||||
0,
|
||||
cipher.as_ptr() as *mut _,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the key MAC key used during key generation.
|
||||
#[corresponds(EVP_PKEY_CTX_ctrl)]
|
||||
#[inline]
|
||||
pub fn set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
|
||||
let len = c_int::try_from(key.len()).unwrap();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_ctrl(
|
||||
self.as_ptr(),
|
||||
-1,
|
||||
ffi::EVP_PKEY_OP_KEYGEN,
|
||||
ffi::EVP_PKEY_CTRL_SET_MAC_KEY,
|
||||
len,
|
||||
key.as_ptr() as *mut _,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the digest used for HKDF derivation.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[corresponds(EVP_PKEY_CTX_set_hkdf_md)]
|
||||
#[cfg(ossl110)]
|
||||
#[inline]
|
||||
pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_hkdf_md(
|
||||
self.as_ptr(),
|
||||
digest.as_ptr(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the HKDF mode of operation.
|
||||
///
|
||||
/// Defaults to [`HkdfMode::EXTRACT_THEN_EXPAND`].
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[corresponds(EVP_PKEY_CTX_set_hkdf_mode)]
|
||||
#[cfg(ossl111)]
|
||||
#[inline]
|
||||
pub fn set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_hkdf_mode(self.as_ptr(), mode.0))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the input keying material for HKDF generation.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[corresponds(EVP_PKEY_CTX_set1_hkdf_key)]
|
||||
#[cfg(ossl110)]
|
||||
#[inline]
|
||||
pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
|
||||
let len = c_int::try_from(key.len()).unwrap();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key(
|
||||
self.as_ptr(),
|
||||
key.as_ptr(),
|
||||
len,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the salt value for HKDF generation.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)]
|
||||
#[cfg(ossl110)]
|
||||
#[inline]
|
||||
pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> {
|
||||
let len = c_int::try_from(salt.len()).unwrap();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt(
|
||||
self.as_ptr(),
|
||||
salt.as_ptr(),
|
||||
len,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Appends info bytes for HKDF generation.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[corresponds(EVP_PKEY_CTX_add1_hkdf_info)]
|
||||
#[cfg(ossl110)]
|
||||
#[inline]
|
||||
pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> {
|
||||
let len = c_int::try_from(info.len()).unwrap();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info(
|
||||
self.as_ptr(),
|
||||
info.as_ptr(),
|
||||
len,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Derives a shared secret between two keys.
|
||||
///
|
||||
/// If `buf` is set to `None`, an upper bound on the number of bytes required for the buffer will be returned.
|
||||
#[corresponds(EVP_PKEY_derive)]
|
||||
pub fn derive(&mut self, buf: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
|
||||
let mut len = buf.as_ref().map_or(0, |b| b.len());
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_derive(
|
||||
self.as_ptr(),
|
||||
buf.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
|
||||
&mut len,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Like [`Self::derive`] but appends the secret to a [`Vec`].
|
||||
pub fn derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack> {
|
||||
let base = buf.len();
|
||||
let len = self.derive(None)?;
|
||||
buf.resize(base + len, 0);
|
||||
let len = self.derive(Some(&mut buf[base..]))?;
|
||||
buf.truncate(base + len);
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Generates a new public/private keypair.
|
||||
#[corresponds(EVP_PKEY_keygen)]
|
||||
#[inline]
|
||||
pub fn keygen(&mut self) -> Result<PKey<Private>, ErrorStack> {
|
||||
unsafe {
|
||||
let mut key = ptr::null_mut();
|
||||
cvt(ffi::EVP_PKEY_keygen(self.as_ptr(), &mut key))?;
|
||||
Ok(PKey::from_ptr(key))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::cipher::Cipher;
|
||||
use crate::ec::{EcGroup, EcKey};
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
use crate::md::Md;
|
||||
use crate::nid::Nid;
|
||||
use crate::pkey::PKey;
|
||||
use crate::rsa::Rsa;
|
||||
|
||||
#[test]
|
||||
fn rsa() {
|
||||
let key = include_bytes!("../test/rsa.pem");
|
||||
let rsa = Rsa::private_key_from_pem(key).unwrap();
|
||||
let pkey = PKey::from_rsa(rsa).unwrap();
|
||||
|
||||
let mut ctx = PkeyCtx::new(&pkey).unwrap();
|
||||
ctx.encrypt_init().unwrap();
|
||||
ctx.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
|
||||
let pt = "hello world".as_bytes();
|
||||
let mut ct = vec![];
|
||||
ctx.encrypt_to_vec(pt, &mut ct).unwrap();
|
||||
|
||||
ctx.decrypt_init().unwrap();
|
||||
ctx.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
|
||||
let mut out = vec![];
|
||||
ctx.decrypt_to_vec(&ct, &mut out).unwrap();
|
||||
|
||||
assert_eq!(pt, out);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
fn rsa_oaep() {
|
||||
let key = include_bytes!("../test/rsa.pem");
|
||||
let rsa = Rsa::private_key_from_pem(key).unwrap();
|
||||
let pkey = PKey::from_rsa(rsa).unwrap();
|
||||
|
||||
let mut ctx = PkeyCtx::new(&pkey).unwrap();
|
||||
ctx.encrypt_init().unwrap();
|
||||
ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
|
||||
ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
|
||||
ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
|
||||
|
||||
let pt = "hello world".as_bytes();
|
||||
let mut ct = vec![];
|
||||
ctx.encrypt_to_vec(pt, &mut ct).unwrap();
|
||||
|
||||
ctx.decrypt_init().unwrap();
|
||||
ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
|
||||
ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
|
||||
ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
|
||||
|
||||
let mut out = vec![];
|
||||
ctx.decrypt_to_vec(&ct, &mut out).unwrap();
|
||||
|
||||
assert_eq!(pt, out);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let key1 = EcKey::generate(&group).unwrap();
|
||||
let key1 = PKey::from_ec_key(key1).unwrap();
|
||||
let key2 = EcKey::generate(&group).unwrap();
|
||||
let key2 = PKey::from_ec_key(key2).unwrap();
|
||||
|
||||
let mut ctx = PkeyCtx::new(&key1).unwrap();
|
||||
ctx.derive_init().unwrap();
|
||||
ctx.derive_set_peer(&key2).unwrap();
|
||||
|
||||
let mut buf = vec![];
|
||||
ctx.derive_to_vec(&mut buf).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cmac_keygen() {
|
||||
let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap();
|
||||
ctx.keygen_init().unwrap();
|
||||
ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap();
|
||||
ctx.set_keygen_mac_key(&hex::decode("9294727a3638bb1c13f48ef8158bfc9d").unwrap())
|
||||
.unwrap();
|
||||
ctx.keygen().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl110)]
|
||||
fn hkdf() {
|
||||
let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
|
||||
ctx.derive_init().unwrap();
|
||||
ctx.set_hkdf_md(Md::sha256()).unwrap();
|
||||
ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
|
||||
.unwrap();
|
||||
ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
|
||||
.unwrap();
|
||||
ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
|
||||
.unwrap();
|
||||
let mut out = [0; 42];
|
||||
ctx.derive(Some(&mut out)).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
&out[..],
|
||||
hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl111)]
|
||||
fn hkdf_expand() {
|
||||
let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
|
||||
ctx.derive_init().unwrap();
|
||||
ctx.set_hkdf_mode(HkdfMode::EXPAND_ONLY).unwrap();
|
||||
ctx.set_hkdf_md(Md::sha256()).unwrap();
|
||||
ctx.set_hkdf_key(
|
||||
&hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
|
||||
.unwrap();
|
||||
let mut out = [0; 42];
|
||||
ctx.derive(Some(&mut out)).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
&out[..],
|
||||
hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl111)]
|
||||
fn hkdf_extract() {
|
||||
let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
|
||||
ctx.derive_init().unwrap();
|
||||
ctx.set_hkdf_mode(HkdfMode::EXTRACT_ONLY).unwrap();
|
||||
ctx.set_hkdf_md(Md::sha256()).unwrap();
|
||||
ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
|
||||
.unwrap();
|
||||
ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
|
||||
.unwrap();
|
||||
let mut out = vec![];
|
||||
ctx.derive_to_vec(&mut out).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
&out[..],
|
||||
hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_fail() {
|
||||
let key1 = Rsa::generate(4096).unwrap();
|
||||
let key1 = PKey::from_rsa(key1).unwrap();
|
||||
|
||||
let data = b"Some Crypto Text";
|
||||
|
||||
let mut ctx = PkeyCtx::new(&key1).unwrap();
|
||||
ctx.sign_init().unwrap();
|
||||
let mut signature = vec![];
|
||||
ctx.sign_to_vec(data, &mut signature).unwrap();
|
||||
|
||||
let bad_data = b"Some Crypto text";
|
||||
|
||||
ctx.verify_init().unwrap();
|
||||
let valid = ctx.verify(bad_data, &signature).unwrap();
|
||||
assert!(!valid);
|
||||
}
|
||||
}
|
||||
61
zeroidc/vendor/openssl/src/provider.rs
vendored
Normal file
61
zeroidc/vendor/openssl/src/provider.rs
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
use crate::cvt_p;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::lib_ctx::LibCtxRef;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use openssl_macros::corresponds;
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::OSSL_PROVIDER;
|
||||
fn drop = ossl_provider_free;
|
||||
|
||||
pub struct Provider;
|
||||
/// A reference to a [`Provider`].
|
||||
pub struct ProviderRef;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn ossl_provider_free(p: *mut ffi::OSSL_PROVIDER) {
|
||||
ffi::OSSL_PROVIDER_unload(p);
|
||||
}
|
||||
|
||||
impl Provider {
|
||||
/// Loads a new provider into the specified library context, disabling the fallback providers.
|
||||
///
|
||||
/// If `ctx` is `None`, the provider will be loaded in to the default library context.
|
||||
#[corresponds(OSSL_provider_load)]
|
||||
pub fn load(ctx: Option<&LibCtxRef>, name: &str) -> Result<Self, ErrorStack> {
|
||||
let name = CString::new(name).unwrap();
|
||||
unsafe {
|
||||
let p = cvt_p(ffi::OSSL_PROVIDER_load(
|
||||
ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
|
||||
name.as_ptr(),
|
||||
))?;
|
||||
|
||||
Ok(Provider::from_ptr(p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Loads a new provider into the specified library context, disabling the fallback providers if `retain_fallbacks`
|
||||
/// is `false` and the load succeeds.
|
||||
///
|
||||
/// If `ctx` is `None`, the provider will be loaded into the default library context.
|
||||
#[corresponds(OSSL_provider_try_load)]
|
||||
pub fn try_load(
|
||||
ctx: Option<&LibCtxRef>,
|
||||
name: &str,
|
||||
retain_fallbacks: bool,
|
||||
) -> Result<Self, ErrorStack> {
|
||||
let name = CString::new(name).unwrap();
|
||||
unsafe {
|
||||
let p = cvt_p(ffi::OSSL_PROVIDER_try_load(
|
||||
ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
|
||||
name.as_ptr(),
|
||||
retain_fallbacks as _,
|
||||
))?;
|
||||
|
||||
Ok(Provider::from_ptr(p))
|
||||
}
|
||||
}
|
||||
}
|
||||
60
zeroidc/vendor/openssl/src/rand.rs
vendored
Normal file
60
zeroidc/vendor/openssl/src/rand.rs
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
//! Utilities for secure random number generation.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! To generate a buffer with cryptographically strong bytes:
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::rand::rand_bytes;
|
||||
//!
|
||||
//! let mut buf = [0; 256];
|
||||
//! rand_bytes(&mut buf).unwrap();
|
||||
//! ```
|
||||
use libc::c_int;
|
||||
|
||||
use crate::cvt;
|
||||
use crate::error::ErrorStack;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
/// Fill buffer with cryptographically strong pseudo-random bytes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// To generate a buffer with cryptographically strong random bytes:
|
||||
///
|
||||
/// ```
|
||||
/// use openssl::rand::rand_bytes;
|
||||
///
|
||||
/// let mut buf = [0; 256];
|
||||
/// rand_bytes(&mut buf).unwrap();
|
||||
/// ```
|
||||
#[corresponds(RAND_bytes)]
|
||||
pub fn rand_bytes(buf: &mut [u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
assert!(buf.len() <= c_int::max_value() as usize);
|
||||
cvt(ffi::RAND_bytes(buf.as_mut_ptr(), buf.len() as c_int)).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Controls random device file descriptor behavior.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[corresponds(RAND_keep_random_devices_open)]
|
||||
#[cfg(ossl111)]
|
||||
pub fn keep_random_devices_open(keep: bool) {
|
||||
unsafe {
|
||||
ffi::RAND_keep_random_devices_open(keep as c_int);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::rand_bytes;
|
||||
|
||||
#[test]
|
||||
fn test_rand_bytes() {
|
||||
let mut buf = [0; 32];
|
||||
rand_bytes(&mut buf).unwrap();
|
||||
}
|
||||
}
|
||||
841
zeroidc/vendor/openssl/src/rsa.rs
vendored
Normal file
841
zeroidc/vendor/openssl/src/rsa.rs
vendored
Normal file
@@ -0,0 +1,841 @@
|
||||
//! Rivest–Shamir–Adleman cryptosystem
|
||||
//!
|
||||
//! RSA is one of the earliest asymmetric public key encryption schemes.
|
||||
//! Like many other cryptosystems, RSA relies on the presumed difficulty of a hard
|
||||
//! mathematical problem, namely factorization of the product of two large prime
|
||||
//! numbers. At the moment there does not exist an algorithm that can factor such
|
||||
//! large numbers in reasonable time. RSA is used in a wide variety of
|
||||
//! applications including digital signatures and key exchanges such as
|
||||
//! establishing a TLS/SSL connection.
|
||||
//!
|
||||
//! The RSA acronym is derived from the first letters of the surnames of the
|
||||
//! algorithm's founding trio.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! Generate a 2048-bit RSA key pair and use the public key to encrypt some data.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::rsa::{Rsa, Padding};
|
||||
//!
|
||||
//! let rsa = Rsa::generate(2048).unwrap();
|
||||
//! let data = b"foobar";
|
||||
//! let mut buf = vec![0; rsa.size() as usize];
|
||||
//! let encrypted_len = rsa.public_encrypt(data, &mut buf, Padding::PKCS1).unwrap();
|
||||
//! ```
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::c_int;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use crate::bn::{BigNum, BigNumRef};
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasPrivate, HasPublic, Private, Public};
|
||||
use crate::util::ForeignTypeRefExt;
|
||||
use crate::{cvt, cvt_n, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
/// Type of encryption padding to use.
|
||||
///
|
||||
/// Random length padding is primarily used to prevent attackers from
|
||||
/// predicting or knowing the exact length of a plaintext message that
|
||||
/// can possibly lead to breaking encryption.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct Padding(c_int);
|
||||
|
||||
impl Padding {
|
||||
pub const NONE: Padding = Padding(ffi::RSA_NO_PADDING);
|
||||
pub const PKCS1: Padding = Padding(ffi::RSA_PKCS1_PADDING);
|
||||
pub const PKCS1_OAEP: Padding = Padding(ffi::RSA_PKCS1_OAEP_PADDING);
|
||||
pub const PKCS1_PSS: Padding = Padding(ffi::RSA_PKCS1_PSS_PADDING);
|
||||
|
||||
/// Creates a `Padding` from an integer representation.
|
||||
pub fn from_raw(value: c_int) -> Padding {
|
||||
Padding(value)
|
||||
}
|
||||
|
||||
/// Returns the integer representation of `Padding`.
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
generic_foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::RSA;
|
||||
fn drop = ffi::RSA_free;
|
||||
|
||||
/// An RSA key.
|
||||
pub struct Rsa<T>;
|
||||
|
||||
/// Reference to `RSA`
|
||||
pub struct RsaRef<T>;
|
||||
}
|
||||
|
||||
impl<T> Clone for Rsa<T> {
|
||||
fn clone(&self) -> Rsa<T> {
|
||||
(**self).to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ToOwned for RsaRef<T> {
|
||||
type Owned = Rsa<T>;
|
||||
|
||||
fn to_owned(&self) -> Rsa<T> {
|
||||
unsafe {
|
||||
ffi::RSA_up_ref(self.as_ptr());
|
||||
Rsa::from_ptr(self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> RsaRef<T>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
private_key_to_pem! {
|
||||
/// Serializes the private key to a PEM-encoded PKCS#1 RSAPrivateKey structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN RSA PRIVATE KEY-----`.
|
||||
#[corresponds(PEM_write_bio_RSAPrivateKey)]
|
||||
private_key_to_pem,
|
||||
/// Serializes the private key to a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN RSA PRIVATE KEY-----`.
|
||||
#[corresponds(PEM_write_bio_RSAPrivateKey)]
|
||||
private_key_to_pem_passphrase,
|
||||
ffi::PEM_write_bio_RSAPrivateKey
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes the private key to a DER-encoded PKCS#1 RSAPrivateKey structure.
|
||||
#[corresponds(i2d_RSAPrivateKey)]
|
||||
private_key_to_der,
|
||||
ffi::i2d_RSAPrivateKey
|
||||
}
|
||||
|
||||
/// Decrypts data using the private key, returning the number of decrypted bytes.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `self` has no private components, or if `to` is smaller
|
||||
/// than `self.size()`.
|
||||
#[corresponds(RSA_private_decrypt)]
|
||||
pub fn private_decrypt(
|
||||
&self,
|
||||
from: &[u8],
|
||||
to: &mut [u8],
|
||||
padding: Padding,
|
||||
) -> Result<usize, ErrorStack> {
|
||||
assert!(from.len() <= i32::max_value() as usize);
|
||||
assert!(to.len() >= self.size() as usize);
|
||||
|
||||
unsafe {
|
||||
let len = cvt_n(ffi::RSA_private_decrypt(
|
||||
from.len() as c_int,
|
||||
from.as_ptr(),
|
||||
to.as_mut_ptr(),
|
||||
self.as_ptr(),
|
||||
padding.0,
|
||||
))?;
|
||||
Ok(len as usize)
|
||||
}
|
||||
}
|
||||
|
||||
/// Encrypts data using the private key, returning the number of encrypted bytes.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `self` has no private components, or if `to` is smaller
|
||||
/// than `self.size()`.
|
||||
#[corresponds(RSA_private_encrypt)]
|
||||
pub fn private_encrypt(
|
||||
&self,
|
||||
from: &[u8],
|
||||
to: &mut [u8],
|
||||
padding: Padding,
|
||||
) -> Result<usize, ErrorStack> {
|
||||
assert!(from.len() <= i32::max_value() as usize);
|
||||
assert!(to.len() >= self.size() as usize);
|
||||
|
||||
unsafe {
|
||||
let len = cvt_n(ffi::RSA_private_encrypt(
|
||||
from.len() as c_int,
|
||||
from.as_ptr(),
|
||||
to.as_mut_ptr(),
|
||||
self.as_ptr(),
|
||||
padding.0,
|
||||
))?;
|
||||
Ok(len as usize)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the private exponent of the key.
|
||||
#[corresponds(RSA_get0_key)]
|
||||
pub fn d(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut d = ptr::null();
|
||||
RSA_get0_key(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut d);
|
||||
BigNumRef::from_const_ptr(d)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the first factor of the exponent of the key.
|
||||
#[corresponds(RSA_get0_factors)]
|
||||
pub fn p(&self) -> Option<&BigNumRef> {
|
||||
unsafe {
|
||||
let mut p = ptr::null();
|
||||
RSA_get0_factors(self.as_ptr(), &mut p, ptr::null_mut());
|
||||
BigNumRef::from_const_ptr_opt(p)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the second factor of the exponent of the key.
|
||||
#[corresponds(RSA_get0_factors)]
|
||||
pub fn q(&self) -> Option<&BigNumRef> {
|
||||
unsafe {
|
||||
let mut q = ptr::null();
|
||||
RSA_get0_factors(self.as_ptr(), ptr::null_mut(), &mut q);
|
||||
BigNumRef::from_const_ptr_opt(q)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the first exponent used for CRT calculations.
|
||||
#[corresponds(RSA_get0_crt_params)]
|
||||
pub fn dmp1(&self) -> Option<&BigNumRef> {
|
||||
unsafe {
|
||||
let mut dp = ptr::null();
|
||||
RSA_get0_crt_params(self.as_ptr(), &mut dp, ptr::null_mut(), ptr::null_mut());
|
||||
BigNumRef::from_const_ptr_opt(dp)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the second exponent used for CRT calculations.
|
||||
#[corresponds(RSA_get0_crt_params)]
|
||||
pub fn dmq1(&self) -> Option<&BigNumRef> {
|
||||
unsafe {
|
||||
let mut dq = ptr::null();
|
||||
RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), &mut dq, ptr::null_mut());
|
||||
BigNumRef::from_const_ptr_opt(dq)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the coefficient used for CRT calculations.
|
||||
#[corresponds(RSA_get0_crt_params)]
|
||||
pub fn iqmp(&self) -> Option<&BigNumRef> {
|
||||
unsafe {
|
||||
let mut qi = ptr::null();
|
||||
RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut qi);
|
||||
BigNumRef::from_const_ptr_opt(qi)
|
||||
}
|
||||
}
|
||||
|
||||
/// Validates RSA parameters for correctness
|
||||
#[corresponds(RSA_check_key)]
|
||||
pub fn check_key(&self) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
let result = ffi::RSA_check_key(self.as_ptr()) as i32;
|
||||
if result == -1 {
|
||||
Err(ErrorStack::get())
|
||||
} else {
|
||||
Ok(result == 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> RsaRef<T>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
to_pem! {
|
||||
/// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
|
||||
#[corresponds(PEM_write_bio_RSA_PUBKEY)]
|
||||
public_key_to_pem,
|
||||
ffi::PEM_write_bio_RSA_PUBKEY
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
|
||||
#[corresponds(i2d_RSA_PUBKEY)]
|
||||
public_key_to_der,
|
||||
ffi::i2d_RSA_PUBKEY
|
||||
}
|
||||
|
||||
to_pem! {
|
||||
/// Serializes the public key into a PEM-encoded PKCS#1 RSAPublicKey structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN RSA PUBLIC KEY-----`.
|
||||
#[corresponds(PEM_write_bio_RSAPublicKey)]
|
||||
public_key_to_pem_pkcs1,
|
||||
ffi::PEM_write_bio_RSAPublicKey
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes the public key into a DER-encoded PKCS#1 RSAPublicKey structure.
|
||||
#[corresponds(i2d_RSAPublicKey)]
|
||||
public_key_to_der_pkcs1,
|
||||
ffi::i2d_RSAPublicKey
|
||||
}
|
||||
|
||||
/// Returns the size of the modulus in bytes.
|
||||
#[corresponds(RSA_size)]
|
||||
pub fn size(&self) -> u32 {
|
||||
unsafe { ffi::RSA_size(self.as_ptr()) as u32 }
|
||||
}
|
||||
|
||||
/// Decrypts data using the public key, returning the number of decrypted bytes.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `to` is smaller than `self.size()`.
|
||||
#[corresponds(RSA_public_decrypt)]
|
||||
pub fn public_decrypt(
|
||||
&self,
|
||||
from: &[u8],
|
||||
to: &mut [u8],
|
||||
padding: Padding,
|
||||
) -> Result<usize, ErrorStack> {
|
||||
assert!(from.len() <= i32::max_value() as usize);
|
||||
assert!(to.len() >= self.size() as usize);
|
||||
|
||||
unsafe {
|
||||
let len = cvt_n(ffi::RSA_public_decrypt(
|
||||
from.len() as c_int,
|
||||
from.as_ptr(),
|
||||
to.as_mut_ptr(),
|
||||
self.as_ptr(),
|
||||
padding.0,
|
||||
))?;
|
||||
Ok(len as usize)
|
||||
}
|
||||
}
|
||||
|
||||
/// Encrypts data using the public key, returning the number of encrypted bytes.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `to` is smaller than `self.size()`.
|
||||
#[corresponds(RSA_public_encrypt)]
|
||||
pub fn public_encrypt(
|
||||
&self,
|
||||
from: &[u8],
|
||||
to: &mut [u8],
|
||||
padding: Padding,
|
||||
) -> Result<usize, ErrorStack> {
|
||||
assert!(from.len() <= i32::max_value() as usize);
|
||||
assert!(to.len() >= self.size() as usize);
|
||||
|
||||
unsafe {
|
||||
let len = cvt_n(ffi::RSA_public_encrypt(
|
||||
from.len() as c_int,
|
||||
from.as_ptr(),
|
||||
to.as_mut_ptr(),
|
||||
self.as_ptr(),
|
||||
padding.0,
|
||||
))?;
|
||||
Ok(len as usize)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the modulus of the key.
|
||||
#[corresponds(RSA_get0_key)]
|
||||
pub fn n(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut n = ptr::null();
|
||||
RSA_get0_key(self.as_ptr(), &mut n, ptr::null_mut(), ptr::null_mut());
|
||||
BigNumRef::from_const_ptr(n)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the public exponent of the key.
|
||||
#[corresponds(RSA_get0_key)]
|
||||
pub fn e(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut e = ptr::null();
|
||||
RSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut e, ptr::null_mut());
|
||||
BigNumRef::from_const_ptr(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Rsa<Public> {
|
||||
/// Creates a new RSA key with only public components.
|
||||
///
|
||||
/// `n` is the modulus common to both public and private key.
|
||||
/// `e` is the public exponent.
|
||||
///
|
||||
/// This corresponds to [`RSA_new`] and uses [`RSA_set0_key`].
|
||||
///
|
||||
/// [`RSA_new`]: https://www.openssl.org/docs/manmaster/crypto/RSA_new.html
|
||||
/// [`RSA_set0_key`]: https://www.openssl.org/docs/manmaster/crypto/RSA_set0_key.html
|
||||
pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa<Public>, ErrorStack> {
|
||||
unsafe {
|
||||
let rsa = cvt_p(ffi::RSA_new())?;
|
||||
RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), ptr::null_mut());
|
||||
mem::forget((n, e));
|
||||
Ok(Rsa::from_ptr(rsa))
|
||||
}
|
||||
}
|
||||
|
||||
from_pem! {
|
||||
/// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing an RSA key.
|
||||
///
|
||||
/// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
|
||||
#[corresponds(PEM_read_bio_RSA_PUBKEY)]
|
||||
public_key_from_pem,
|
||||
Rsa<Public>,
|
||||
ffi::PEM_read_bio_RSA_PUBKEY
|
||||
}
|
||||
|
||||
from_pem! {
|
||||
/// Decodes a PEM-encoded PKCS#1 RSAPublicKey structure.
|
||||
///
|
||||
/// The input should have a header of `-----BEGIN RSA PUBLIC KEY-----`.
|
||||
#[corresponds(PEM_read_bio_RSAPublicKey)]
|
||||
public_key_from_pem_pkcs1,
|
||||
Rsa<Public>,
|
||||
ffi::PEM_read_bio_RSAPublicKey
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Decodes a DER-encoded SubjectPublicKeyInfo structure containing an RSA key.
|
||||
#[corresponds(d2i_RSA_PUBKEY)]
|
||||
public_key_from_der,
|
||||
Rsa<Public>,
|
||||
ffi::d2i_RSA_PUBKEY
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Decodes a DER-encoded PKCS#1 RSAPublicKey structure.
|
||||
#[corresponds(d2i_RSAPublicKey)]
|
||||
public_key_from_der_pkcs1,
|
||||
Rsa<Public>,
|
||||
ffi::d2i_RSAPublicKey
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RsaPrivateKeyBuilder {
|
||||
rsa: Rsa<Private>,
|
||||
}
|
||||
|
||||
impl RsaPrivateKeyBuilder {
|
||||
/// Creates a new `RsaPrivateKeyBuilder`.
|
||||
///
|
||||
/// `n` is the modulus common to both public and private key.
|
||||
/// `e` is the public exponent and `d` is the private exponent.
|
||||
///
|
||||
/// This corresponds to [`RSA_new`] and uses [`RSA_set0_key`].
|
||||
///
|
||||
/// [`RSA_new`]: https://www.openssl.org/docs/manmaster/crypto/RSA_new.html
|
||||
/// [`RSA_set0_key`]: https://www.openssl.org/docs/manmaster/crypto/RSA_set0_key.html
|
||||
pub fn new(n: BigNum, e: BigNum, d: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
|
||||
unsafe {
|
||||
let rsa = cvt_p(ffi::RSA_new())?;
|
||||
RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), d.as_ptr());
|
||||
mem::forget((n, e, d));
|
||||
Ok(RsaPrivateKeyBuilder {
|
||||
rsa: Rsa::from_ptr(rsa),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the factors of the Rsa key.
|
||||
///
|
||||
/// `p` and `q` are the first and second factors of `n`.
|
||||
#[corresponds(RSA_set0_factors)]
|
||||
// FIXME should be infallible
|
||||
pub fn set_factors(self, p: BigNum, q: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
|
||||
unsafe {
|
||||
RSA_set0_factors(self.rsa.as_ptr(), p.as_ptr(), q.as_ptr());
|
||||
mem::forget((p, q));
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Sets the Chinese Remainder Theorem params of the Rsa key.
|
||||
///
|
||||
/// `dmp1`, `dmq1`, and `iqmp` are the exponents and coefficient for
|
||||
/// CRT calculations which is used to speed up RSA operations.
|
||||
#[corresponds(RSA_set0_crt_params)]
|
||||
// FIXME should be infallible
|
||||
pub fn set_crt_params(
|
||||
self,
|
||||
dmp1: BigNum,
|
||||
dmq1: BigNum,
|
||||
iqmp: BigNum,
|
||||
) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
|
||||
unsafe {
|
||||
RSA_set0_crt_params(
|
||||
self.rsa.as_ptr(),
|
||||
dmp1.as_ptr(),
|
||||
dmq1.as_ptr(),
|
||||
iqmp.as_ptr(),
|
||||
);
|
||||
mem::forget((dmp1, dmq1, iqmp));
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Returns the Rsa key.
|
||||
pub fn build(self) -> Rsa<Private> {
|
||||
self.rsa
|
||||
}
|
||||
}
|
||||
|
||||
impl Rsa<Private> {
|
||||
/// Creates a new RSA key with private components (public components are assumed).
|
||||
///
|
||||
/// This a convenience method over
|
||||
/// `Rsa::build(n, e, d)?.set_factors(p, q)?.set_crt_params(dmp1, dmq1, iqmp)?.build()`
|
||||
#[allow(clippy::too_many_arguments, clippy::many_single_char_names)]
|
||||
pub fn from_private_components(
|
||||
n: BigNum,
|
||||
e: BigNum,
|
||||
d: BigNum,
|
||||
p: BigNum,
|
||||
q: BigNum,
|
||||
dmp1: BigNum,
|
||||
dmq1: BigNum,
|
||||
iqmp: BigNum,
|
||||
) -> Result<Rsa<Private>, ErrorStack> {
|
||||
Ok(RsaPrivateKeyBuilder::new(n, e, d)?
|
||||
.set_factors(p, q)?
|
||||
.set_crt_params(dmp1, dmq1, iqmp)?
|
||||
.build())
|
||||
}
|
||||
|
||||
/// Generates a public/private key pair with the specified size.
|
||||
///
|
||||
/// The public exponent will be 65537.
|
||||
#[corresponds(RSA_generate_key_ex)]
|
||||
pub fn generate(bits: u32) -> Result<Rsa<Private>, ErrorStack> {
|
||||
let e = BigNum::from_u32(ffi::RSA_F4 as u32)?;
|
||||
Rsa::generate_with_e(bits, &e)
|
||||
}
|
||||
|
||||
/// Generates a public/private key pair with the specified size and a custom exponent.
|
||||
///
|
||||
/// Unless you have specific needs and know what you're doing, use `Rsa::generate` instead.
|
||||
#[corresponds(RSA_generate_key_ex)]
|
||||
pub fn generate_with_e(bits: u32, e: &BigNumRef) -> Result<Rsa<Private>, ErrorStack> {
|
||||
unsafe {
|
||||
let rsa = Rsa::from_ptr(cvt_p(ffi::RSA_new())?);
|
||||
cvt(ffi::RSA_generate_key_ex(
|
||||
rsa.0,
|
||||
bits as c_int,
|
||||
e.as_ptr(),
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
Ok(rsa)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME these need to identify input formats
|
||||
private_key_from_pem! {
|
||||
/// Deserializes a private key from a PEM-encoded PKCS#1 RSAPrivateKey structure.
|
||||
#[corresponds(PEM_read_bio_RSAPrivateKey)]
|
||||
private_key_from_pem,
|
||||
|
||||
/// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
|
||||
#[corresponds(PEM_read_bio_RSAPrivateKey)]
|
||||
private_key_from_pem_passphrase,
|
||||
|
||||
/// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
|
||||
///
|
||||
/// The callback should fill the password into the provided buffer and return its length.
|
||||
#[corresponds(PEM_read_bio_RSAPrivateKey)]
|
||||
private_key_from_pem_callback,
|
||||
Rsa<Private>,
|
||||
ffi::PEM_read_bio_RSAPrivateKey
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Decodes a DER-encoded PKCS#1 RSAPrivateKey structure.
|
||||
#[corresponds(d2i_RSAPrivateKey)]
|
||||
private_key_from_der,
|
||||
Rsa<Private>,
|
||||
ffi::d2i_RSAPrivateKey
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for Rsa<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Rsa")
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273))] {
|
||||
use ffi::{
|
||||
RSA_get0_key, RSA_get0_factors, RSA_get0_crt_params, RSA_set0_key, RSA_set0_factors,
|
||||
RSA_set0_crt_params,
|
||||
};
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn RSA_get0_key(
|
||||
r: *const ffi::RSA,
|
||||
n: *mut *const ffi::BIGNUM,
|
||||
e: *mut *const ffi::BIGNUM,
|
||||
d: *mut *const ffi::BIGNUM,
|
||||
) {
|
||||
if !n.is_null() {
|
||||
*n = (*r).n;
|
||||
}
|
||||
if !e.is_null() {
|
||||
*e = (*r).e;
|
||||
}
|
||||
if !d.is_null() {
|
||||
*d = (*r).d;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn RSA_get0_factors(
|
||||
r: *const ffi::RSA,
|
||||
p: *mut *const ffi::BIGNUM,
|
||||
q: *mut *const ffi::BIGNUM,
|
||||
) {
|
||||
if !p.is_null() {
|
||||
*p = (*r).p;
|
||||
}
|
||||
if !q.is_null() {
|
||||
*q = (*r).q;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn RSA_get0_crt_params(
|
||||
r: *const ffi::RSA,
|
||||
dmp1: *mut *const ffi::BIGNUM,
|
||||
dmq1: *mut *const ffi::BIGNUM,
|
||||
iqmp: *mut *const ffi::BIGNUM,
|
||||
) {
|
||||
if !dmp1.is_null() {
|
||||
*dmp1 = (*r).dmp1;
|
||||
}
|
||||
if !dmq1.is_null() {
|
||||
*dmq1 = (*r).dmq1;
|
||||
}
|
||||
if !iqmp.is_null() {
|
||||
*iqmp = (*r).iqmp;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn RSA_set0_key(
|
||||
r: *mut ffi::RSA,
|
||||
n: *mut ffi::BIGNUM,
|
||||
e: *mut ffi::BIGNUM,
|
||||
d: *mut ffi::BIGNUM,
|
||||
) -> c_int {
|
||||
(*r).n = n;
|
||||
(*r).e = e;
|
||||
(*r).d = d;
|
||||
1
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn RSA_set0_factors(
|
||||
r: *mut ffi::RSA,
|
||||
p: *mut ffi::BIGNUM,
|
||||
q: *mut ffi::BIGNUM,
|
||||
) -> c_int {
|
||||
(*r).p = p;
|
||||
(*r).q = q;
|
||||
1
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn RSA_set0_crt_params(
|
||||
r: *mut ffi::RSA,
|
||||
dmp1: *mut ffi::BIGNUM,
|
||||
dmq1: *mut ffi::BIGNUM,
|
||||
iqmp: *mut ffi::BIGNUM,
|
||||
) -> c_int {
|
||||
(*r).dmp1 = dmp1;
|
||||
(*r).dmq1 = dmq1;
|
||||
(*r).iqmp = iqmp;
|
||||
1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::symm::Cipher;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_from_password() {
|
||||
let key = include_bytes!("../test/rsa-encrypted.pem");
|
||||
Rsa::private_key_from_pem_passphrase(key, b"mypass").unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_password_callback() {
|
||||
let mut password_queried = false;
|
||||
let key = include_bytes!("../test/rsa-encrypted.pem");
|
||||
Rsa::private_key_from_pem_callback(key, |password| {
|
||||
password_queried = true;
|
||||
password[..6].copy_from_slice(b"mypass");
|
||||
Ok(6)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert!(password_queried);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_password() {
|
||||
let key = Rsa::generate(2048).unwrap();
|
||||
let pem = key
|
||||
.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar")
|
||||
.unwrap();
|
||||
Rsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
|
||||
assert!(Rsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_public_encrypt_private_decrypt_with_padding() {
|
||||
let key = include_bytes!("../test/rsa.pem.pub");
|
||||
let public_key = Rsa::public_key_from_pem(key).unwrap();
|
||||
|
||||
let mut result = vec![0; public_key.size() as usize];
|
||||
let original_data = b"This is test";
|
||||
let len = public_key
|
||||
.public_encrypt(original_data, &mut result, Padding::PKCS1)
|
||||
.unwrap();
|
||||
assert_eq!(len, 256);
|
||||
|
||||
let pkey = include_bytes!("../test/rsa.pem");
|
||||
let private_key = Rsa::private_key_from_pem(pkey).unwrap();
|
||||
let mut dec_result = vec![0; private_key.size() as usize];
|
||||
let len = private_key
|
||||
.private_decrypt(&result, &mut dec_result, Padding::PKCS1)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(&dec_result[..len], original_data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_private_encrypt() {
|
||||
let k0 = super::Rsa::generate(512).unwrap();
|
||||
let k0pkey = k0.public_key_to_pem().unwrap();
|
||||
let k1 = super::Rsa::public_key_from_pem(&k0pkey).unwrap();
|
||||
|
||||
let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8];
|
||||
|
||||
let mut emesg = vec![0; k0.size() as usize];
|
||||
k0.private_encrypt(&msg, &mut emesg, Padding::PKCS1)
|
||||
.unwrap();
|
||||
let mut dmesg = vec![0; k1.size() as usize];
|
||||
let len = k1
|
||||
.public_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
|
||||
.unwrap();
|
||||
assert_eq!(msg, &dmesg[..len]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_public_encrypt() {
|
||||
let k0 = super::Rsa::generate(512).unwrap();
|
||||
let k0pkey = k0.private_key_to_pem().unwrap();
|
||||
let k1 = super::Rsa::private_key_from_pem(&k0pkey).unwrap();
|
||||
|
||||
let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8];
|
||||
|
||||
let mut emesg = vec![0; k0.size() as usize];
|
||||
k0.public_encrypt(&msg, &mut emesg, Padding::PKCS1).unwrap();
|
||||
let mut dmesg = vec![0; k1.size() as usize];
|
||||
let len = k1
|
||||
.private_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
|
||||
.unwrap();
|
||||
assert_eq!(msg, &dmesg[..len]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_public_key_from_pem_pkcs1() {
|
||||
let key = include_bytes!("../test/pkcs1.pem.pub");
|
||||
Rsa::public_key_from_pem_pkcs1(key).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_public_key_from_pem_pkcs1_file_panic() {
|
||||
let key = include_bytes!("../test/key.pem.pub");
|
||||
Rsa::public_key_from_pem_pkcs1(key).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_public_key_to_pem_pkcs1() {
|
||||
let keypair = super::Rsa::generate(512).unwrap();
|
||||
let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
|
||||
super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_public_key_from_pem_pkcs1_generate_panic() {
|
||||
let keypair = super::Rsa::generate(512).unwrap();
|
||||
let pubkey_pem = keypair.public_key_to_pem().unwrap();
|
||||
super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pem_pkcs1_encrypt() {
|
||||
let keypair = super::Rsa::generate(2048).unwrap();
|
||||
let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
|
||||
let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
|
||||
let msg = b"Hello, world!";
|
||||
|
||||
let mut encrypted = vec![0; pubkey.size() as usize];
|
||||
let len = pubkey
|
||||
.public_encrypt(msg, &mut encrypted, Padding::PKCS1)
|
||||
.unwrap();
|
||||
assert!(len > msg.len());
|
||||
let mut decrypted = vec![0; keypair.size() as usize];
|
||||
let len = keypair
|
||||
.private_decrypt(&encrypted, &mut decrypted, Padding::PKCS1)
|
||||
.unwrap();
|
||||
assert_eq!(len, msg.len());
|
||||
assert_eq!(&decrypted[..len], msg);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pem_pkcs1_padding() {
|
||||
let keypair = super::Rsa::generate(2048).unwrap();
|
||||
let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
|
||||
let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
|
||||
let msg = b"foo";
|
||||
|
||||
let mut encrypted1 = vec![0; pubkey.size() as usize];
|
||||
let mut encrypted2 = vec![0; pubkey.size() as usize];
|
||||
let len1 = pubkey
|
||||
.public_encrypt(msg, &mut encrypted1, Padding::PKCS1)
|
||||
.unwrap();
|
||||
let len2 = pubkey
|
||||
.public_encrypt(msg, &mut encrypted2, Padding::PKCS1)
|
||||
.unwrap();
|
||||
assert!(len1 > (msg.len() + 1));
|
||||
assert_eq!(len1, len2);
|
||||
assert_ne!(encrypted1, encrypted2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::redundant_clone)]
|
||||
fn clone() {
|
||||
let key = Rsa::generate(2048).unwrap();
|
||||
drop(key.clone());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generate_with_e() {
|
||||
let e = BigNum::from_u32(0x10001).unwrap();
|
||||
Rsa::generate_with_e(2048, &e).unwrap();
|
||||
}
|
||||
}
|
||||
463
zeroidc/vendor/openssl/src/sha.rs
vendored
Normal file
463
zeroidc/vendor/openssl/src/sha.rs
vendored
Normal file
@@ -0,0 +1,463 @@
|
||||
//! The SHA family of hashes.
|
||||
//!
|
||||
//! SHA, or Secure Hash Algorithms, are a family of cryptographic hashing algorithms published by
|
||||
//! the National Institute of Standards and Technology (NIST). Hash algorithms such as those in
|
||||
//! the SHA family are used to map data of an arbitrary size to a fixed-size string of bytes.
|
||||
//! As cryptographic hashing algorithms, these mappings have the property of being irreversible.
|
||||
//! This property makes hash algorithms like these excellent for uses such as verifying the
|
||||
//! contents of a file- if you know the hash you expect beforehand, then you can verify that the
|
||||
//! data you have is correct if it hashes to the same value.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! When dealing with data that becomes available in chunks, such as while buffering data from IO,
|
||||
//! you can create a hasher that you can repeatedly update to add bytes to.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::sha;
|
||||
//!
|
||||
//! let mut hasher = sha::Sha256::new();
|
||||
//!
|
||||
//! hasher.update(b"Hello, ");
|
||||
//! hasher.update(b"world");
|
||||
//!
|
||||
//! let hash = hasher.finish();
|
||||
//! println!("Hashed \"Hello, world\" to {}", hex::encode(hash));
|
||||
//! ```
|
||||
//!
|
||||
//! On the other hand, if you already have access to all of the data you would like to hash, you
|
||||
//! may prefer to use the slightly simpler method of simply calling the hash function corresponding
|
||||
//! to the algorithm you want to use.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::sha::sha256;
|
||||
//!
|
||||
//! let hash = sha256(b"your data or message");
|
||||
//! println!("Hash = {}", hex::encode(hash));
|
||||
//! ```
|
||||
use cfg_if::cfg_if;
|
||||
use libc::c_void;
|
||||
use openssl_macros::corresponds;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
/// Computes the SHA1 hash of some data.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// SHA1 is known to be insecure - it should not be used unless required for
|
||||
/// compatibility with existing systems.
|
||||
#[corresponds(SHA1)]
|
||||
#[inline]
|
||||
pub fn sha1(data: &[u8]) -> [u8; 20] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 20]>::uninit();
|
||||
ffi::SHA1(data.as_ptr(), data.len(), hash.as_mut_ptr() as *mut _);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the SHA224 hash of some data.
|
||||
#[corresponds(SH224)]
|
||||
#[inline]
|
||||
pub fn sha224(data: &[u8]) -> [u8; 28] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 28]>::uninit();
|
||||
ffi::SHA224(data.as_ptr(), data.len(), hash.as_mut_ptr() as *mut _);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the SHA256 hash of some data.
|
||||
#[corresponds(SHA256)]
|
||||
#[inline]
|
||||
pub fn sha256(data: &[u8]) -> [u8; 32] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 32]>::uninit();
|
||||
ffi::SHA256(data.as_ptr(), data.len(), hash.as_mut_ptr() as *mut _);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the SHA384 hash of some data.
|
||||
#[corresponds(SHA384)]
|
||||
#[inline]
|
||||
pub fn sha384(data: &[u8]) -> [u8; 48] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 48]>::uninit();
|
||||
ffi::SHA384(data.as_ptr(), data.len(), hash.as_mut_ptr() as *mut _);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the SHA512 hash of some data.
|
||||
#[corresponds(SHA512)]
|
||||
#[inline]
|
||||
pub fn sha512(data: &[u8]) -> [u8; 64] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 64]>::uninit();
|
||||
ffi::SHA512(data.as_ptr(), data.len(), hash.as_mut_ptr() as *mut _);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] {
|
||||
/// An object which calculates a SHA1 hash of some data.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// SHA1 is known to be insecure - it should not be used unless required for
|
||||
/// compatibility with existing systems.
|
||||
#[derive(Clone)]
|
||||
pub struct Sha1(ffi::SHA_CTX);
|
||||
|
||||
impl Default for Sha1 {
|
||||
#[inline]
|
||||
fn default() -> Sha1 {
|
||||
Sha1::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Sha1 {
|
||||
/// Creates a new hasher.
|
||||
#[corresponds(SHA1_Init)]
|
||||
#[inline]
|
||||
pub fn new() -> Sha1 {
|
||||
unsafe {
|
||||
let mut ctx = MaybeUninit::uninit();
|
||||
ffi::SHA1_Init( ctx.as_mut_ptr());
|
||||
Sha1(ctx.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds some data into the hasher.
|
||||
///
|
||||
/// This can be called multiple times.
|
||||
#[corresponds(SHA1_Update)]
|
||||
#[inline]
|
||||
pub fn update(&mut self, buf: &[u8]) {
|
||||
unsafe {
|
||||
ffi::SHA1_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len());
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the hash of the data.
|
||||
#[corresponds(SHA1_Final)]
|
||||
#[inline]
|
||||
pub fn finish(mut self) -> [u8; 20] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 20]>::uninit();
|
||||
ffi::SHA1_Final(hash.as_mut_ptr() as *mut _, &mut self.0);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An object which calculates a SHA224 hash of some data.
|
||||
#[derive(Clone)]
|
||||
pub struct Sha224(ffi::SHA256_CTX);
|
||||
|
||||
impl Default for Sha224 {
|
||||
#[inline]
|
||||
fn default() -> Sha224 {
|
||||
Sha224::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Sha224 {
|
||||
/// Creates a new hasher.
|
||||
#[corresponds(SHA224_Init)]
|
||||
#[inline]
|
||||
pub fn new() -> Sha224 {
|
||||
unsafe {
|
||||
let mut ctx = MaybeUninit::uninit();
|
||||
ffi::SHA224_Init(ctx.as_mut_ptr());
|
||||
Sha224(ctx.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds some data into the hasher.
|
||||
///
|
||||
/// This can be called multiple times.
|
||||
#[corresponds(SHA224_Update)]
|
||||
#[inline]
|
||||
pub fn update(&mut self, buf: &[u8]) {
|
||||
unsafe {
|
||||
ffi::SHA224_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len());
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the hash of the data.
|
||||
#[corresponds(SHA224_Final)]
|
||||
#[inline]
|
||||
pub fn finish(mut self) -> [u8; 28] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 28]>::uninit();
|
||||
ffi::SHA224_Final(hash.as_mut_ptr() as *mut _, &mut self.0);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An object which calculates a SHA256 hash of some data.
|
||||
#[derive(Clone)]
|
||||
pub struct Sha256(ffi::SHA256_CTX);
|
||||
|
||||
impl Default for Sha256 {
|
||||
#[inline]
|
||||
fn default() -> Sha256 {
|
||||
Sha256::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Sha256 {
|
||||
/// Creates a new hasher.
|
||||
#[corresponds(SHA256_Init)]
|
||||
#[inline]
|
||||
pub fn new() -> Sha256 {
|
||||
unsafe {
|
||||
let mut ctx = MaybeUninit::uninit();
|
||||
ffi::SHA256_Init(ctx.as_mut_ptr());
|
||||
Sha256(ctx.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds some data into the hasher.
|
||||
///
|
||||
/// This can be called multiple times.
|
||||
#[corresponds(SHA256_Update)]
|
||||
#[inline]
|
||||
pub fn update(&mut self, buf: &[u8]) {
|
||||
unsafe {
|
||||
ffi::SHA256_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len());
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the hash of the data.
|
||||
#[corresponds(SHA256_Final)]
|
||||
#[inline]
|
||||
pub fn finish(mut self) -> [u8; 32] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 32]>::uninit();
|
||||
ffi::SHA256_Final(hash.as_mut_ptr() as *mut _, &mut self.0);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An object which calculates a SHA384 hash of some data.
|
||||
#[derive(Clone)]
|
||||
pub struct Sha384(ffi::SHA512_CTX);
|
||||
|
||||
impl Default for Sha384 {
|
||||
#[inline]
|
||||
fn default() -> Sha384 {
|
||||
Sha384::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Sha384 {
|
||||
/// Creates a new hasher.
|
||||
#[corresponds(SHA384_Init)]
|
||||
#[inline]
|
||||
pub fn new() -> Sha384 {
|
||||
unsafe {
|
||||
let mut ctx = MaybeUninit::uninit();
|
||||
ffi::SHA384_Init(ctx.as_mut_ptr());
|
||||
Sha384(ctx.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds some data into the hasher.
|
||||
///
|
||||
/// This can be called multiple times.
|
||||
#[corresponds(SHA384_Update)]
|
||||
#[inline]
|
||||
pub fn update(&mut self, buf: &[u8]) {
|
||||
unsafe {
|
||||
ffi::SHA384_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len());
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the hash of the data.
|
||||
#[corresponds(SHA384_Final)]
|
||||
#[inline]
|
||||
pub fn finish(mut self) -> [u8; 48] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 48]>::uninit();
|
||||
ffi::SHA384_Final(hash.as_mut_ptr() as *mut _, &mut self.0);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An object which calculates a SHA512 hash of some data.
|
||||
#[derive(Clone)]
|
||||
pub struct Sha512(ffi::SHA512_CTX);
|
||||
|
||||
impl Default for Sha512 {
|
||||
#[inline]
|
||||
fn default() -> Sha512 {
|
||||
Sha512::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Sha512 {
|
||||
/// Creates a new hasher.
|
||||
#[corresponds(SHA512_Init)]
|
||||
#[inline]
|
||||
pub fn new() -> Sha512 {
|
||||
unsafe {
|
||||
let mut ctx = MaybeUninit::uninit();
|
||||
ffi::SHA512_Init(ctx.as_mut_ptr());
|
||||
Sha512(ctx.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds some data into the hasher.
|
||||
///
|
||||
/// This can be called multiple times.
|
||||
#[corresponds(SHA512_Update)]
|
||||
#[inline]
|
||||
pub fn update(&mut self, buf: &[u8]) {
|
||||
unsafe {
|
||||
ffi::SHA512_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len());
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the hash of the data.
|
||||
#[corresponds(SHA512_Final)]
|
||||
#[inline]
|
||||
pub fn finish(mut self) -> [u8; 64] {
|
||||
unsafe {
|
||||
let mut hash= MaybeUninit::<[u8; 64]>::uninit();
|
||||
ffi::SHA512_Final(hash.as_mut_ptr() as *mut _, &mut self.0);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn standalone_1() {
|
||||
let data = b"abc";
|
||||
let expected = "a9993e364706816aba3e25717850c26c9cd0d89d";
|
||||
|
||||
assert_eq!(hex::encode(sha1(data)), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
|
||||
fn struct_1() {
|
||||
let expected = "a9993e364706816aba3e25717850c26c9cd0d89d";
|
||||
|
||||
let mut hasher = Sha1::new();
|
||||
hasher.update(b"a");
|
||||
hasher.update(b"bc");
|
||||
assert_eq!(hex::encode(hasher.finish()), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
|
||||
fn cloning_allows_incremental_hashing() {
|
||||
let expected = "a9993e364706816aba3e25717850c26c9cd0d89d";
|
||||
|
||||
let mut hasher = Sha1::new();
|
||||
hasher.update(b"a");
|
||||
|
||||
let mut incr_hasher = hasher.clone();
|
||||
incr_hasher.update(b"bc");
|
||||
|
||||
assert_eq!(hex::encode(incr_hasher.finish()), expected);
|
||||
assert_ne!(hex::encode(hasher.finish()), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn standalone_224() {
|
||||
let data = b"abc";
|
||||
let expected = "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7";
|
||||
|
||||
assert_eq!(hex::encode(sha224(data)), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
|
||||
fn struct_224() {
|
||||
let expected = "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7";
|
||||
|
||||
let mut hasher = Sha224::new();
|
||||
hasher.update(b"a");
|
||||
hasher.update(b"bc");
|
||||
assert_eq!(hex::encode(hasher.finish()), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn standalone_256() {
|
||||
let data = b"abc";
|
||||
let expected = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
|
||||
|
||||
assert_eq!(hex::encode(sha256(data)), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
|
||||
fn struct_256() {
|
||||
let expected = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
|
||||
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(b"a");
|
||||
hasher.update(b"bc");
|
||||
assert_eq!(hex::encode(hasher.finish()), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn standalone_384() {
|
||||
let data = b"abc";
|
||||
let expected =
|
||||
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e\
|
||||
7cc2358baeca134c825a7";
|
||||
|
||||
assert_eq!(hex::encode(&sha384(data)[..]), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
|
||||
fn struct_384() {
|
||||
let expected =
|
||||
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e\
|
||||
7cc2358baeca134c825a7";
|
||||
|
||||
let mut hasher = Sha384::new();
|
||||
hasher.update(b"a");
|
||||
hasher.update(b"bc");
|
||||
assert_eq!(hex::encode(&hasher.finish()[..]), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn standalone_512() {
|
||||
let data = b"abc";
|
||||
let expected =
|
||||
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274\
|
||||
fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f";
|
||||
|
||||
assert_eq!(hex::encode(&sha512(data)[..]), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
|
||||
fn struct_512() {
|
||||
let expected =
|
||||
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274\
|
||||
fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f";
|
||||
|
||||
let mut hasher = Sha512::new();
|
||||
hasher.update(b"a");
|
||||
hasher.update(b"bc");
|
||||
assert_eq!(hex::encode(&hasher.finish()[..]), expected);
|
||||
}
|
||||
}
|
||||
874
zeroidc/vendor/openssl/src/sign.rs
vendored
Normal file
874
zeroidc/vendor/openssl/src/sign.rs
vendored
Normal file
@@ -0,0 +1,874 @@
|
||||
//! Message signatures.
|
||||
//!
|
||||
//! The `Signer` allows for the computation of cryptographic signatures of
|
||||
//! data given a private key. The `Verifier` can then be used with the
|
||||
//! corresponding public key to verify the integrity and authenticity of that
|
||||
//! data given the signature.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Sign and verify data given an RSA keypair:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::sign::{Signer, Verifier};
|
||||
//! use openssl::rsa::Rsa;
|
||||
//! use openssl::pkey::PKey;
|
||||
//! use openssl::hash::MessageDigest;
|
||||
//!
|
||||
//! // Generate a keypair
|
||||
//! let keypair = Rsa::generate(2048).unwrap();
|
||||
//! let keypair = PKey::from_rsa(keypair).unwrap();
|
||||
//!
|
||||
//! let data = b"hello, world!";
|
||||
//! let data2 = b"hola, mundo!";
|
||||
//!
|
||||
//! // Sign the data
|
||||
//! let mut signer = Signer::new(MessageDigest::sha256(), &keypair).unwrap();
|
||||
//! signer.update(data).unwrap();
|
||||
//! signer.update(data2).unwrap();
|
||||
//! let signature = signer.sign_to_vec().unwrap();
|
||||
//!
|
||||
//! // Verify the data
|
||||
//! let mut verifier = Verifier::new(MessageDigest::sha256(), &keypair).unwrap();
|
||||
//! verifier.update(data).unwrap();
|
||||
//! verifier.update(data2).unwrap();
|
||||
//! assert!(verifier.verify(&signature).unwrap());
|
||||
//! ```
|
||||
//!
|
||||
//! Compute an HMAC:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::hash::MessageDigest;
|
||||
//! use openssl::memcmp;
|
||||
//! use openssl::pkey::PKey;
|
||||
//! use openssl::sign::Signer;
|
||||
//!
|
||||
//! // Create a PKey
|
||||
//! let key = PKey::hmac(b"my secret").unwrap();
|
||||
//!
|
||||
//! let data = b"hello, world!";
|
||||
//! let data2 = b"hola, mundo!";
|
||||
//!
|
||||
//! // Compute the HMAC
|
||||
//! let mut signer = Signer::new(MessageDigest::sha256(), &key).unwrap();
|
||||
//! signer.update(data).unwrap();
|
||||
//! signer.update(data2).unwrap();
|
||||
//! let hmac = signer.sign_to_vec().unwrap();
|
||||
//!
|
||||
//! // `Verifier` cannot be used with HMACs; use the `memcmp::eq` function instead
|
||||
//! //
|
||||
//! // Do not simply check for equality with `==`!
|
||||
//! # let target = hmac.clone();
|
||||
//! assert!(memcmp::eq(&hmac, &target));
|
||||
//! ```
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use libc::c_int;
|
||||
use std::io::{self, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::pkey::{HasPrivate, HasPublic, PKeyRef};
|
||||
use crate::rsa::Padding;
|
||||
use crate::{cvt, cvt_p};
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl110)] {
|
||||
use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
|
||||
} else {
|
||||
use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
|
||||
}
|
||||
}
|
||||
|
||||
/// Salt lengths that must be used with `set_rsa_pss_saltlen`.
|
||||
pub struct RsaPssSaltlen(c_int);
|
||||
|
||||
impl RsaPssSaltlen {
|
||||
/// Returns the integer representation of `RsaPssSaltlen`.
|
||||
fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Sets the salt length to the given value.
|
||||
pub fn custom(val: c_int) -> RsaPssSaltlen {
|
||||
RsaPssSaltlen(val)
|
||||
}
|
||||
|
||||
/// The salt length is set to the digest length.
|
||||
/// Corresponds to the special value `-1`.
|
||||
pub const DIGEST_LENGTH: RsaPssSaltlen = RsaPssSaltlen(-1);
|
||||
/// The salt length is set to the maximum permissible value.
|
||||
/// Corresponds to the special value `-2`.
|
||||
pub const MAXIMUM_LENGTH: RsaPssSaltlen = RsaPssSaltlen(-2);
|
||||
}
|
||||
|
||||
/// A type which computes cryptographic signatures of data.
|
||||
pub struct Signer<'a> {
|
||||
md_ctx: *mut ffi::EVP_MD_CTX,
|
||||
pctx: *mut ffi::EVP_PKEY_CTX,
|
||||
_p: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
unsafe impl<'a> Sync for Signer<'a> {}
|
||||
unsafe impl<'a> Send for Signer<'a> {}
|
||||
|
||||
impl<'a> Drop for Signer<'a> {
|
||||
fn drop(&mut self) {
|
||||
// pkey_ctx is owned by the md_ctx, so no need to explicitly free it.
|
||||
unsafe {
|
||||
EVP_MD_CTX_free(self.md_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
impl<'a> Signer<'a> {
|
||||
/// Creates a new `Signer`.
|
||||
///
|
||||
/// This cannot be used with Ed25519 or Ed448 keys. Please refer to
|
||||
/// `new_without_digest`.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_DigestSignInit`].
|
||||
///
|
||||
/// [`EVP_DigestSignInit`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestSignInit.html
|
||||
pub fn new<T>(type_: MessageDigest, pkey: &'a PKeyRef<T>) -> Result<Signer<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
Self::new_intern(Some(type_), pkey)
|
||||
}
|
||||
|
||||
/// Creates a new `Signer` without a digest.
|
||||
///
|
||||
/// This is the only way to create a `Verifier` for Ed25519 or Ed448 keys.
|
||||
/// It can also be used to create a CMAC.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_DigestSignInit`].
|
||||
///
|
||||
/// [`EVP_DigestSignInit`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestSignInit.html
|
||||
pub fn new_without_digest<T>(pkey: &'a PKeyRef<T>) -> Result<Signer<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
Self::new_intern(None, pkey)
|
||||
}
|
||||
|
||||
fn new_intern<T>(
|
||||
type_: Option<MessageDigest>,
|
||||
pkey: &'a PKeyRef<T>,
|
||||
) -> Result<Signer<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
let ctx = cvt_p(EVP_MD_CTX_new())?;
|
||||
let mut pctx: *mut ffi::EVP_PKEY_CTX = ptr::null_mut();
|
||||
let r = ffi::EVP_DigestSignInit(
|
||||
ctx,
|
||||
&mut pctx,
|
||||
type_.map(|t| t.as_ptr()).unwrap_or(ptr::null()),
|
||||
ptr::null_mut(),
|
||||
pkey.as_ptr(),
|
||||
);
|
||||
if r != 1 {
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return Err(ErrorStack::get());
|
||||
}
|
||||
|
||||
assert!(!pctx.is_null());
|
||||
|
||||
Ok(Signer {
|
||||
md_ctx: ctx,
|
||||
pctx,
|
||||
_p: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the RSA padding mode in use.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`.
|
||||
pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
|
||||
unsafe {
|
||||
let mut pad = 0;
|
||||
cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad))
|
||||
.map(|_| Padding::from_raw(pad))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA padding mode.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_padding`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_padding`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_CTX_set_rsa_padding.html
|
||||
pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
|
||||
self.pctx,
|
||||
padding.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA PSS salt length.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_pss_saltlen`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_pss_saltlen`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_CTX_set_rsa_pss_saltlen.html
|
||||
pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen(
|
||||
self.pctx,
|
||||
len.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA MGF1 algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html
|
||||
pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
|
||||
self.pctx,
|
||||
md.as_ptr() as *mut _,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds more data into the `Signer`.
|
||||
///
|
||||
/// Please note that PureEdDSA (Ed25519 and Ed448 keys) do not support streaming.
|
||||
/// Use `sign_oneshot` instead.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_DigestUpdate`].
|
||||
///
|
||||
/// [`EVP_DigestUpdate`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestInit.html
|
||||
pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestUpdate(
|
||||
self.md_ctx,
|
||||
buf.as_ptr() as *const _,
|
||||
buf.len(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes an upper bound on the signature length.
|
||||
///
|
||||
/// The actual signature may be shorter than this value. Check the return value of
|
||||
/// `sign` to get the exact length.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_DigestSignFinal`].
|
||||
///
|
||||
/// [`EVP_DigestSignFinal`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_DigestSignFinal.html
|
||||
pub fn len(&self) -> Result<usize, ErrorStack> {
|
||||
self.len_intern()
|
||||
}
|
||||
|
||||
#[cfg(not(ossl111))]
|
||||
fn len_intern(&self) -> Result<usize, ErrorStack> {
|
||||
unsafe {
|
||||
let mut len = 0;
|
||||
cvt(ffi::EVP_DigestSignFinal(
|
||||
self.md_ctx,
|
||||
ptr::null_mut(),
|
||||
&mut len,
|
||||
))?;
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
fn len_intern(&self) -> Result<usize, ErrorStack> {
|
||||
unsafe {
|
||||
let mut len = 0;
|
||||
cvt(ffi::EVP_DigestSign(
|
||||
self.md_ctx,
|
||||
ptr::null_mut(),
|
||||
&mut len,
|
||||
ptr::null(),
|
||||
0,
|
||||
))?;
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes the signature into the provided buffer, returning the number of bytes written.
|
||||
///
|
||||
/// This method will fail if the buffer is not large enough for the signature. Use the `len`
|
||||
/// method to get an upper bound on the required size.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_DigestSignFinal`].
|
||||
///
|
||||
/// [`EVP_DigestSignFinal`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_DigestSignFinal.html
|
||||
pub fn sign(&self, buf: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
unsafe {
|
||||
let mut len = buf.len();
|
||||
cvt(ffi::EVP_DigestSignFinal(
|
||||
self.md_ctx,
|
||||
buf.as_mut_ptr() as *mut _,
|
||||
&mut len,
|
||||
))?;
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the signature.
|
||||
///
|
||||
/// This is a simple convenience wrapper over `len` and `sign`.
|
||||
pub fn sign_to_vec(&self) -> Result<Vec<u8>, ErrorStack> {
|
||||
let mut buf = vec![0; self.len()?];
|
||||
let len = self.sign(&mut buf)?;
|
||||
// The advertised length is not always equal to the real length for things like DSA
|
||||
buf.truncate(len);
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
/// Signs the data in `data_buf` and writes the signature into the buffer `sig_buf`, returning the
|
||||
/// number of bytes written.
|
||||
///
|
||||
/// For PureEdDSA (Ed25519 and Ed448 keys), this is the only way to sign data.
|
||||
///
|
||||
/// This method will fail if the buffer is not large enough for the signature. Use the `len`
|
||||
/// method to get an upper bound on the required size.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_DigestSign`].
|
||||
///
|
||||
/// [`EVP_DigestSign`]: https://www.openssl.org/docs/man1.1.1/man3/EVP_DigestSign.html
|
||||
#[cfg(ossl111)]
|
||||
pub fn sign_oneshot(
|
||||
&mut self,
|
||||
sig_buf: &mut [u8],
|
||||
data_buf: &[u8],
|
||||
) -> Result<usize, ErrorStack> {
|
||||
unsafe {
|
||||
let mut sig_len = sig_buf.len();
|
||||
cvt(ffi::EVP_DigestSign(
|
||||
self.md_ctx,
|
||||
sig_buf.as_mut_ptr() as *mut _,
|
||||
&mut sig_len,
|
||||
data_buf.as_ptr() as *const _,
|
||||
data_buf.len(),
|
||||
))?;
|
||||
Ok(sig_len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the signature.
|
||||
///
|
||||
/// This is a simple convenience wrapper over `len` and `sign_oneshot`.
|
||||
#[cfg(ossl111)]
|
||||
pub fn sign_oneshot_to_vec(&mut self, data_buf: &[u8]) -> Result<Vec<u8>, ErrorStack> {
|
||||
let mut sig_buf = vec![0; self.len()?];
|
||||
let len = self.sign_oneshot(&mut sig_buf, data_buf)?;
|
||||
// The advertised length is not always equal to the real length for things like DSA
|
||||
sig_buf.truncate(len);
|
||||
Ok(sig_buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Write for Signer<'a> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.update(buf)?;
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Verifier<'a> {
|
||||
md_ctx: *mut ffi::EVP_MD_CTX,
|
||||
pctx: *mut ffi::EVP_PKEY_CTX,
|
||||
pkey_pd: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
unsafe impl<'a> Sync for Verifier<'a> {}
|
||||
unsafe impl<'a> Send for Verifier<'a> {}
|
||||
|
||||
impl<'a> Drop for Verifier<'a> {
|
||||
fn drop(&mut self) {
|
||||
// pkey_ctx is owned by the md_ctx, so no need to explicitly free it.
|
||||
unsafe {
|
||||
EVP_MD_CTX_free(self.md_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A type which verifies cryptographic signatures of data.
|
||||
impl<'a> Verifier<'a> {
|
||||
/// Creates a new `Verifier`.
|
||||
///
|
||||
/// This cannot be used with Ed25519 or Ed448 keys. Please refer to
|
||||
/// `new_without_digest`.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_DigestVerifyInit`].
|
||||
///
|
||||
/// [`EVP_DigestVerifyInit`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestVerifyInit.html
|
||||
pub fn new<T>(type_: MessageDigest, pkey: &'a PKeyRef<T>) -> Result<Verifier<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
Verifier::new_intern(Some(type_), pkey)
|
||||
}
|
||||
|
||||
/// Creates a new `Verifier` without a digest.
|
||||
///
|
||||
/// This is the only way to create a `Verifier` for Ed25519 or Ed448 keys.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_DigestVerifyInit`].
|
||||
///
|
||||
/// [`EVP_DigestVerifyInit`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestVerifyInit.html
|
||||
pub fn new_without_digest<T>(pkey: &'a PKeyRef<T>) -> Result<Verifier<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
Verifier::new_intern(None, pkey)
|
||||
}
|
||||
|
||||
fn new_intern<T>(
|
||||
type_: Option<MessageDigest>,
|
||||
pkey: &'a PKeyRef<T>,
|
||||
) -> Result<Verifier<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
let ctx = cvt_p(EVP_MD_CTX_new())?;
|
||||
let mut pctx: *mut ffi::EVP_PKEY_CTX = ptr::null_mut();
|
||||
let r = ffi::EVP_DigestVerifyInit(
|
||||
ctx,
|
||||
&mut pctx,
|
||||
type_.map(|t| t.as_ptr()).unwrap_or(ptr::null()),
|
||||
ptr::null_mut(),
|
||||
pkey.as_ptr(),
|
||||
);
|
||||
if r != 1 {
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return Err(ErrorStack::get());
|
||||
}
|
||||
|
||||
assert!(!pctx.is_null());
|
||||
|
||||
Ok(Verifier {
|
||||
md_ctx: ctx,
|
||||
pctx,
|
||||
pkey_pd: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the RSA padding mode in use.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`.
|
||||
pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
|
||||
unsafe {
|
||||
let mut pad = 0;
|
||||
cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad))
|
||||
.map(|_| Padding::from_raw(pad))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA padding mode.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_padding`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_padding`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_CTX_set_rsa_padding.html
|
||||
pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
|
||||
self.pctx,
|
||||
padding.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA PSS salt length.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_pss_saltlen`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_pss_saltlen`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_CTX_set_rsa_pss_saltlen.html
|
||||
pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen(
|
||||
self.pctx,
|
||||
len.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA MGF1 algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html
|
||||
pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
|
||||
self.pctx,
|
||||
md.as_ptr() as *mut _,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds more data into the `Verifier`.
|
||||
///
|
||||
/// Please note that PureEdDSA (Ed25519 and Ed448 keys) do not support streaming.
|
||||
/// Use `verify_oneshot` instead.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_DigestUpdate`].
|
||||
///
|
||||
/// [`EVP_DigestUpdate`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestInit.html
|
||||
pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestUpdate(
|
||||
self.md_ctx,
|
||||
buf.as_ptr() as *const _,
|
||||
buf.len(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines if the data fed into the `Verifier` matches the provided signature.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_DigestVerifyFinal`].
|
||||
///
|
||||
/// [`EVP_DigestVerifyFinal`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestVerifyFinal.html
|
||||
pub fn verify(&self, signature: &[u8]) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
let r =
|
||||
EVP_DigestVerifyFinal(self.md_ctx, signature.as_ptr() as *mut _, signature.len());
|
||||
match r {
|
||||
1 => Ok(true),
|
||||
0 => {
|
||||
ErrorStack::get(); // discard error stack
|
||||
Ok(false)
|
||||
}
|
||||
_ => Err(ErrorStack::get()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines if the data given in `buf` matches the provided signature.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_DigestVerify`].
|
||||
///
|
||||
/// [`EVP_DigestVerify`]: https://www.openssl.org/docs/man1.1.1/man3/EVP_DigestVerify.html
|
||||
#[cfg(ossl111)]
|
||||
pub fn verify_oneshot(&mut self, signature: &[u8], buf: &[u8]) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
let r = ffi::EVP_DigestVerify(
|
||||
self.md_ctx,
|
||||
signature.as_ptr() as *const _,
|
||||
signature.len(),
|
||||
buf.as_ptr() as *const _,
|
||||
buf.len(),
|
||||
);
|
||||
match r {
|
||||
1 => Ok(true),
|
||||
0 => {
|
||||
ErrorStack::get();
|
||||
Ok(false)
|
||||
}
|
||||
_ => Err(ErrorStack::get()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Write for Verifier<'a> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.update(buf)?;
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(ossl101))]
|
||||
use ffi::EVP_DigestVerifyFinal;
|
||||
|
||||
#[cfg(ossl101)]
|
||||
#[allow(bad_style)]
|
||||
unsafe fn EVP_DigestVerifyFinal(
|
||||
ctx: *mut ffi::EVP_MD_CTX,
|
||||
sigret: *const ::libc::c_uchar,
|
||||
siglen: ::libc::size_t,
|
||||
) -> ::libc::c_int {
|
||||
ffi::EVP_DigestVerifyFinal(ctx, sigret as *mut _, siglen)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use hex::{self, FromHex};
|
||||
use std::iter;
|
||||
|
||||
use crate::ec::{EcGroup, EcKey};
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::nid::Nid;
|
||||
use crate::pkey::PKey;
|
||||
use crate::rsa::{Padding, Rsa};
|
||||
#[cfg(ossl111)]
|
||||
use crate::sign::RsaPssSaltlen;
|
||||
use crate::sign::{Signer, Verifier};
|
||||
|
||||
const INPUT: &str =
|
||||
"65794a68624763694f694a53557a49314e694a392e65794a7063334d694f694a71623255694c41304b49434a6c\
|
||||
654841694f6a457a4d4441344d546b7a4f44417344516f67496d6830644841364c79396c654746746347786c4c\
|
||||
6d4e76625339706331397962323930496a7030636e566c6651";
|
||||
|
||||
const SIGNATURE: &str =
|
||||
"702e218943e88fd11eb5d82dbf7845f34106ae1b81fff7731116add1717d83656d420afd3c96eedd73a2663e51\
|
||||
66687b000b87226e0187ed1073f945e582adfcef16d85a798ee8c66ddb3db8975b17d09402beedd5d9d9700710\
|
||||
8db28160d5f8040ca7445762b81fbe7ff9d92e0ae76f24f25b33bbe6f44ae61eb1040acb20044d3ef9128ed401\
|
||||
30795bd4bd3b41eecad066ab651981fde48df77f372dc38b9fafdd3befb18b5da3cc3c2eb02f9e3a41d612caad\
|
||||
15911273a05f23b9e838faaf849d698429ef5a1e88798236c3d40e604522a544c8f27a7a2db80663d16cf7caea\
|
||||
56de405cb2215a45b2c25566b55ac1a748a070dfc8a32a469543d019eefb47";
|
||||
|
||||
#[test]
|
||||
fn rsa_sign() {
|
||||
let key = include_bytes!("../test/rsa.pem");
|
||||
let private_key = Rsa::private_key_from_pem(key).unwrap();
|
||||
let pkey = PKey::from_rsa(private_key).unwrap();
|
||||
|
||||
let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap();
|
||||
assert_eq!(signer.rsa_padding().unwrap(), Padding::PKCS1);
|
||||
signer.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
signer.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
|
||||
let result = signer.sign_to_vec().unwrap();
|
||||
|
||||
assert_eq!(hex::encode(result), SIGNATURE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rsa_verify_ok() {
|
||||
let key = include_bytes!("../test/rsa.pem");
|
||||
let private_key = Rsa::private_key_from_pem(key).unwrap();
|
||||
let pkey = PKey::from_rsa(private_key).unwrap();
|
||||
|
||||
let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap();
|
||||
assert_eq!(verifier.rsa_padding().unwrap(), Padding::PKCS1);
|
||||
verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
|
||||
assert!(verifier.verify(&Vec::from_hex(SIGNATURE).unwrap()).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rsa_verify_invalid() {
|
||||
let key = include_bytes!("../test/rsa.pem");
|
||||
let private_key = Rsa::private_key_from_pem(key).unwrap();
|
||||
let pkey = PKey::from_rsa(private_key).unwrap();
|
||||
|
||||
let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap();
|
||||
verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
|
||||
verifier.update(b"foobar").unwrap();
|
||||
assert!(!verifier.verify(&Vec::from_hex(SIGNATURE).unwrap()).unwrap());
|
||||
}
|
||||
|
||||
fn test_hmac(ty: MessageDigest, tests: &[(Vec<u8>, Vec<u8>, Vec<u8>)]) {
|
||||
for &(ref key, ref data, ref res) in tests.iter() {
|
||||
let pkey = PKey::hmac(key).unwrap();
|
||||
let mut signer = Signer::new(ty, &pkey).unwrap();
|
||||
signer.update(data).unwrap();
|
||||
assert_eq!(signer.sign_to_vec().unwrap(), *res);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hmac_md5() {
|
||||
// test vectors from RFC 2202
|
||||
let tests: [(Vec<u8>, Vec<u8>, Vec<u8>); 7] = [
|
||||
(
|
||||
iter::repeat(0x0b_u8).take(16).collect(),
|
||||
b"Hi There".to_vec(),
|
||||
Vec::from_hex("9294727a3638bb1c13f48ef8158bfc9d").unwrap(),
|
||||
),
|
||||
(
|
||||
b"Jefe".to_vec(),
|
||||
b"what do ya want for nothing?".to_vec(),
|
||||
Vec::from_hex("750c783e6ab0b503eaa86e310a5db738").unwrap(),
|
||||
),
|
||||
(
|
||||
iter::repeat(0xaa_u8).take(16).collect(),
|
||||
iter::repeat(0xdd_u8).take(50).collect(),
|
||||
Vec::from_hex("56be34521d144c88dbb8c733f0e8b3f6").unwrap(),
|
||||
),
|
||||
(
|
||||
Vec::from_hex("0102030405060708090a0b0c0d0e0f10111213141516171819").unwrap(),
|
||||
iter::repeat(0xcd_u8).take(50).collect(),
|
||||
Vec::from_hex("697eaf0aca3a3aea3a75164746ffaa79").unwrap(),
|
||||
),
|
||||
(
|
||||
iter::repeat(0x0c_u8).take(16).collect(),
|
||||
b"Test With Truncation".to_vec(),
|
||||
Vec::from_hex("56461ef2342edc00f9bab995690efd4c").unwrap(),
|
||||
),
|
||||
(
|
||||
iter::repeat(0xaa_u8).take(80).collect(),
|
||||
b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(),
|
||||
Vec::from_hex("6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd").unwrap(),
|
||||
),
|
||||
(
|
||||
iter::repeat(0xaa_u8).take(80).collect(),
|
||||
b"Test Using Larger Than Block-Size Key \
|
||||
and Larger Than One Block-Size Data"
|
||||
.to_vec(),
|
||||
Vec::from_hex("6f630fad67cda0ee1fb1f562db3aa53e").unwrap(),
|
||||
),
|
||||
];
|
||||
|
||||
test_hmac(MessageDigest::md5(), &tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hmac_sha1() {
|
||||
// test vectors from RFC 2202
|
||||
let tests: [(Vec<u8>, Vec<u8>, Vec<u8>); 7] = [
|
||||
(
|
||||
iter::repeat(0x0b_u8).take(20).collect(),
|
||||
b"Hi There".to_vec(),
|
||||
Vec::from_hex("b617318655057264e28bc0b6fb378c8ef146be00").unwrap(),
|
||||
),
|
||||
(
|
||||
b"Jefe".to_vec(),
|
||||
b"what do ya want for nothing?".to_vec(),
|
||||
Vec::from_hex("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79").unwrap(),
|
||||
),
|
||||
(
|
||||
iter::repeat(0xaa_u8).take(20).collect(),
|
||||
iter::repeat(0xdd_u8).take(50).collect(),
|
||||
Vec::from_hex("125d7342b9ac11cd91a39af48aa17b4f63f175d3").unwrap(),
|
||||
),
|
||||
(
|
||||
Vec::from_hex("0102030405060708090a0b0c0d0e0f10111213141516171819").unwrap(),
|
||||
iter::repeat(0xcd_u8).take(50).collect(),
|
||||
Vec::from_hex("4c9007f4026250c6bc8414f9bf50c86c2d7235da").unwrap(),
|
||||
),
|
||||
(
|
||||
iter::repeat(0x0c_u8).take(20).collect(),
|
||||
b"Test With Truncation".to_vec(),
|
||||
Vec::from_hex("4c1a03424b55e07fe7f27be1d58bb9324a9a5a04").unwrap(),
|
||||
),
|
||||
(
|
||||
iter::repeat(0xaa_u8).take(80).collect(),
|
||||
b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(),
|
||||
Vec::from_hex("aa4ae5e15272d00e95705637ce8a3b55ed402112").unwrap(),
|
||||
),
|
||||
(
|
||||
iter::repeat(0xaa_u8).take(80).collect(),
|
||||
b"Test Using Larger Than Block-Size Key \
|
||||
and Larger Than One Block-Size Data"
|
||||
.to_vec(),
|
||||
Vec::from_hex("e8e99d0f45237d786d6bbaa7965c7808bbff1a91").unwrap(),
|
||||
),
|
||||
];
|
||||
|
||||
test_hmac(MessageDigest::sha1(), &tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl110)]
|
||||
fn test_cmac() {
|
||||
let cipher = crate::symm::Cipher::aes_128_cbc();
|
||||
let key = Vec::from_hex("9294727a3638bb1c13f48ef8158bfc9d").unwrap();
|
||||
let pkey = PKey::cmac(&cipher, &key).unwrap();
|
||||
let mut signer = Signer::new_without_digest(&pkey).unwrap();
|
||||
|
||||
let data = b"Hi There";
|
||||
signer.update(data as &[u8]).unwrap();
|
||||
|
||||
let expected = vec![
|
||||
136, 101, 61, 167, 61, 30, 248, 234, 124, 166, 196, 157, 203, 52, 171, 19,
|
||||
];
|
||||
assert_eq!(signer.sign_to_vec().unwrap(), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ec() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let key = EcKey::generate(&group).unwrap();
|
||||
let key = PKey::from_ec_key(key).unwrap();
|
||||
|
||||
let mut signer = Signer::new(MessageDigest::sha256(), &key).unwrap();
|
||||
signer.update(b"hello world").unwrap();
|
||||
let signature = signer.sign_to_vec().unwrap();
|
||||
|
||||
let mut verifier = Verifier::new(MessageDigest::sha256(), &key).unwrap();
|
||||
verifier.update(b"hello world").unwrap();
|
||||
assert!(verifier.verify(&signature).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl111)]
|
||||
fn eddsa() {
|
||||
let key = PKey::generate_ed25519().unwrap();
|
||||
|
||||
let mut signer = Signer::new_without_digest(&key).unwrap();
|
||||
let signature = signer.sign_oneshot_to_vec(b"hello world").unwrap();
|
||||
|
||||
let mut verifier = Verifier::new_without_digest(&key).unwrap();
|
||||
assert!(verifier.verify_oneshot(&signature, b"hello world").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl111)]
|
||||
fn rsa_sign_verify() {
|
||||
let key = include_bytes!("../test/rsa.pem");
|
||||
let private_key = Rsa::private_key_from_pem(key).unwrap();
|
||||
let pkey = PKey::from_rsa(private_key).unwrap();
|
||||
|
||||
let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap();
|
||||
signer.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
|
||||
assert_eq!(signer.rsa_padding().unwrap(), Padding::PKCS1_PSS);
|
||||
signer
|
||||
.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH)
|
||||
.unwrap();
|
||||
signer.set_rsa_mgf1_md(MessageDigest::sha256()).unwrap();
|
||||
signer.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
|
||||
let signature = signer.sign_to_vec().unwrap();
|
||||
|
||||
let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap();
|
||||
verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
|
||||
verifier
|
||||
.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH)
|
||||
.unwrap();
|
||||
verifier.set_rsa_mgf1_md(MessageDigest::sha256()).unwrap();
|
||||
verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
|
||||
assert!(verifier.verify(&signature).unwrap());
|
||||
}
|
||||
}
|
||||
60
zeroidc/vendor/openssl/src/srtp.rs
vendored
Normal file
60
zeroidc/vendor/openssl/src/srtp.rs
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
use crate::stack::Stackable;
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use libc::c_ulong;
|
||||
use std::ffi::CStr;
|
||||
use std::str;
|
||||
|
||||
/// fake free method, since SRTP_PROTECTION_PROFILE is static
|
||||
unsafe fn free(_profile: *mut ffi::SRTP_PROTECTION_PROFILE) {}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::SRTP_PROTECTION_PROFILE;
|
||||
fn drop = free;
|
||||
|
||||
pub struct SrtpProtectionProfile;
|
||||
/// Reference to `SrtpProtectionProfile`.
|
||||
pub struct SrtpProtectionProfileRef;
|
||||
}
|
||||
|
||||
impl Stackable for SrtpProtectionProfile {
|
||||
type StackType = ffi::stack_st_SRTP_PROTECTION_PROFILE;
|
||||
}
|
||||
|
||||
impl SrtpProtectionProfileRef {
|
||||
pub fn id(&self) -> SrtpProfileId {
|
||||
SrtpProfileId::from_raw(unsafe { (*self.as_ptr()).id })
|
||||
}
|
||||
pub fn name(&self) -> &'static str {
|
||||
unsafe { CStr::from_ptr((*self.as_ptr()).name as *const _) }
|
||||
.to_str()
|
||||
.expect("should be UTF-8")
|
||||
}
|
||||
}
|
||||
|
||||
/// An identifier of an SRTP protection profile.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct SrtpProfileId(c_ulong);
|
||||
|
||||
impl SrtpProfileId {
|
||||
pub const SRTP_AES128_CM_SHA1_80: SrtpProfileId = SrtpProfileId(ffi::SRTP_AES128_CM_SHA1_80);
|
||||
pub const SRTP_AES128_CM_SHA1_32: SrtpProfileId = SrtpProfileId(ffi::SRTP_AES128_CM_SHA1_32);
|
||||
pub const SRTP_AES128_F8_SHA1_80: SrtpProfileId = SrtpProfileId(ffi::SRTP_AES128_F8_SHA1_80);
|
||||
pub const SRTP_AES128_F8_SHA1_32: SrtpProfileId = SrtpProfileId(ffi::SRTP_AES128_F8_SHA1_32);
|
||||
pub const SRTP_NULL_SHA1_80: SrtpProfileId = SrtpProfileId(ffi::SRTP_NULL_SHA1_80);
|
||||
pub const SRTP_NULL_SHA1_32: SrtpProfileId = SrtpProfileId(ffi::SRTP_NULL_SHA1_32);
|
||||
#[cfg(ossl110)]
|
||||
pub const SRTP_AEAD_AES_128_GCM: SrtpProfileId = SrtpProfileId(ffi::SRTP_AEAD_AES_128_GCM);
|
||||
#[cfg(ossl110)]
|
||||
pub const SRTP_AEAD_AES_256_GCM: SrtpProfileId = SrtpProfileId(ffi::SRTP_AEAD_AES_256_GCM);
|
||||
|
||||
/// Creates a `SrtpProfileId` from an integer representation.
|
||||
pub fn from_raw(value: c_ulong) -> SrtpProfileId {
|
||||
SrtpProfileId(value)
|
||||
}
|
||||
|
||||
/// Returns the integer representation of `SrtpProfileId`.
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_raw(&self) -> c_ulong {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
290
zeroidc/vendor/openssl/src/ssl/bio.rs
vendored
Normal file
290
zeroidc/vendor/openssl/src/ssl/bio.rs
vendored
Normal file
@@ -0,0 +1,290 @@
|
||||
use cfg_if::cfg_if;
|
||||
use ffi::{
|
||||
self, BIO_clear_retry_flags, BIO_new, BIO_set_retry_read, BIO_set_retry_write, BIO,
|
||||
BIO_CTRL_DGRAM_QUERY_MTU, BIO_CTRL_FLUSH,
|
||||
};
|
||||
use libc::{c_char, c_int, c_long, c_void, strlen};
|
||||
use std::any::Any;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
use crate::cvt_p;
|
||||
use crate::error::ErrorStack;
|
||||
|
||||
pub struct StreamState<S> {
|
||||
pub stream: S,
|
||||
pub error: Option<io::Error>,
|
||||
pub panic: Option<Box<dyn Any + Send>>,
|
||||
pub dtls_mtu_size: c_long,
|
||||
}
|
||||
|
||||
/// Safe wrapper for `BIO_METHOD`
|
||||
pub struct BioMethod(BIO_METHOD);
|
||||
|
||||
impl BioMethod {
|
||||
fn new<S: Read + Write>() -> Result<BioMethod, ErrorStack> {
|
||||
BIO_METHOD::new::<S>().map(BioMethod)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Sync for BioMethod {}
|
||||
unsafe impl Send for BioMethod {}
|
||||
|
||||
pub fn new<S: Read + Write>(stream: S) -> Result<(*mut BIO, BioMethod), ErrorStack> {
|
||||
let method = BioMethod::new::<S>()?;
|
||||
|
||||
let state = Box::new(StreamState {
|
||||
stream,
|
||||
error: None,
|
||||
panic: None,
|
||||
dtls_mtu_size: 0,
|
||||
});
|
||||
|
||||
unsafe {
|
||||
let bio = cvt_p(BIO_new(method.0.get()))?;
|
||||
BIO_set_data(bio, Box::into_raw(state) as *mut _);
|
||||
BIO_set_init(bio, 1);
|
||||
|
||||
Ok((bio, method))
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn take_error<S>(bio: *mut BIO) -> Option<io::Error> {
|
||||
let state = state::<S>(bio);
|
||||
state.error.take()
|
||||
}
|
||||
|
||||
pub unsafe fn take_panic<S>(bio: *mut BIO) -> Option<Box<dyn Any + Send>> {
|
||||
let state = state::<S>(bio);
|
||||
state.panic.take()
|
||||
}
|
||||
|
||||
pub unsafe fn get_ref<'a, S: 'a>(bio: *mut BIO) -> &'a S {
|
||||
let state = &*(BIO_get_data(bio) as *const StreamState<S>);
|
||||
&state.stream
|
||||
}
|
||||
|
||||
pub unsafe fn get_mut<'a, S: 'a>(bio: *mut BIO) -> &'a mut S {
|
||||
&mut state(bio).stream
|
||||
}
|
||||
|
||||
pub unsafe fn set_dtls_mtu_size<S>(bio: *mut BIO, mtu_size: usize) {
|
||||
if mtu_size as u64 > c_long::max_value() as u64 {
|
||||
panic!(
|
||||
"Given MTU size {} can't be represented in a positive `c_long` range",
|
||||
mtu_size
|
||||
)
|
||||
}
|
||||
state::<S>(bio).dtls_mtu_size = mtu_size as c_long;
|
||||
}
|
||||
|
||||
unsafe fn state<'a, S: 'a>(bio: *mut BIO) -> &'a mut StreamState<S> {
|
||||
&mut *(BIO_get_data(bio) as *mut _)
|
||||
}
|
||||
|
||||
unsafe extern "C" fn bwrite<S: Write>(bio: *mut BIO, buf: *const c_char, len: c_int) -> c_int {
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
let state = state::<S>(bio);
|
||||
let buf = slice::from_raw_parts(buf as *const _, len as usize);
|
||||
|
||||
match catch_unwind(AssertUnwindSafe(|| state.stream.write(buf))) {
|
||||
Ok(Ok(len)) => len as c_int,
|
||||
Ok(Err(err)) => {
|
||||
if retriable_error(&err) {
|
||||
BIO_set_retry_write(bio);
|
||||
}
|
||||
state.error = Some(err);
|
||||
-1
|
||||
}
|
||||
Err(err) => {
|
||||
state.panic = Some(err);
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn bread<S: Read>(bio: *mut BIO, buf: *mut c_char, len: c_int) -> c_int {
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
let state = state::<S>(bio);
|
||||
let buf = slice::from_raw_parts_mut(buf as *mut _, len as usize);
|
||||
|
||||
match catch_unwind(AssertUnwindSafe(|| state.stream.read(buf))) {
|
||||
Ok(Ok(len)) => len as c_int,
|
||||
Ok(Err(err)) => {
|
||||
if retriable_error(&err) {
|
||||
BIO_set_retry_read(bio);
|
||||
}
|
||||
state.error = Some(err);
|
||||
-1
|
||||
}
|
||||
Err(err) => {
|
||||
state.panic = Some(err);
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::match_like_matches_macro)] // matches macro requires rust 1.42.0
|
||||
fn retriable_error(err: &io::Error) -> bool {
|
||||
match err.kind() {
|
||||
io::ErrorKind::WouldBlock | io::ErrorKind::NotConnected => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn bputs<S: Write>(bio: *mut BIO, s: *const c_char) -> c_int {
|
||||
bwrite::<S>(bio, s, strlen(s) as c_int)
|
||||
}
|
||||
|
||||
unsafe extern "C" fn ctrl<S: Write>(
|
||||
bio: *mut BIO,
|
||||
cmd: c_int,
|
||||
_num: c_long,
|
||||
_ptr: *mut c_void,
|
||||
) -> c_long {
|
||||
let state = state::<S>(bio);
|
||||
|
||||
if cmd == BIO_CTRL_FLUSH {
|
||||
match catch_unwind(AssertUnwindSafe(|| state.stream.flush())) {
|
||||
Ok(Ok(())) => 1,
|
||||
Ok(Err(err)) => {
|
||||
state.error = Some(err);
|
||||
0
|
||||
}
|
||||
Err(err) => {
|
||||
state.panic = Some(err);
|
||||
0
|
||||
}
|
||||
}
|
||||
} else if cmd == BIO_CTRL_DGRAM_QUERY_MTU {
|
||||
state.dtls_mtu_size
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn create(bio: *mut BIO) -> c_int {
|
||||
BIO_set_init(bio, 0);
|
||||
BIO_set_num(bio, 0);
|
||||
BIO_set_data(bio, ptr::null_mut());
|
||||
BIO_set_flags(bio, 0);
|
||||
1
|
||||
}
|
||||
|
||||
unsafe extern "C" fn destroy<S>(bio: *mut BIO) -> c_int {
|
||||
if bio.is_null() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let data = BIO_get_data(bio);
|
||||
assert!(!data.is_null());
|
||||
Box::<StreamState<S>>::from_raw(data as *mut _);
|
||||
BIO_set_data(bio, ptr::null_mut());
|
||||
BIO_set_init(bio, 0);
|
||||
1
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273))] {
|
||||
use ffi::{BIO_get_data, BIO_set_data, BIO_set_flags, BIO_set_init};
|
||||
use crate::cvt;
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn BIO_set_num(_bio: *mut ffi::BIO, _num: c_int) {}
|
||||
|
||||
#[allow(bad_style, clippy::upper_case_acronyms)]
|
||||
struct BIO_METHOD(*mut ffi::BIO_METHOD);
|
||||
|
||||
impl BIO_METHOD {
|
||||
fn new<S: Read + Write>() -> Result<BIO_METHOD, ErrorStack> {
|
||||
unsafe {
|
||||
let ptr = cvt_p(ffi::BIO_meth_new(ffi::BIO_TYPE_NONE, b"rust\0".as_ptr() as *const _))?;
|
||||
let method = BIO_METHOD(ptr);
|
||||
cvt(ffi::BIO_meth_set_write__fixed_rust(method.0, Some(bwrite::<S>)))?;
|
||||
cvt(ffi::BIO_meth_set_read__fixed_rust(method.0, Some(bread::<S>)))?;
|
||||
cvt(ffi::BIO_meth_set_puts__fixed_rust(method.0, Some(bputs::<S>)))?;
|
||||
cvt(ffi::BIO_meth_set_ctrl__fixed_rust(method.0, Some(ctrl::<S>)))?;
|
||||
cvt(ffi::BIO_meth_set_create__fixed_rust(method.0, Some(create)))?;
|
||||
cvt(ffi::BIO_meth_set_destroy__fixed_rust(method.0, Some(destroy::<S>)))?;
|
||||
Ok(method)
|
||||
}
|
||||
}
|
||||
|
||||
fn get(&self) -> *mut ffi::BIO_METHOD {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for BIO_METHOD {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::BIO_meth_free(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#[allow(bad_style, clippy::upper_case_acronyms)]
|
||||
struct BIO_METHOD(*mut ffi::BIO_METHOD);
|
||||
|
||||
impl BIO_METHOD {
|
||||
fn new<S: Read + Write>() -> Result<BIO_METHOD, ErrorStack> {
|
||||
let ptr = Box::new(ffi::BIO_METHOD {
|
||||
type_: ffi::BIO_TYPE_NONE,
|
||||
name: b"rust\0".as_ptr() as *const _,
|
||||
bwrite: Some(bwrite::<S>),
|
||||
bread: Some(bread::<S>),
|
||||
bputs: Some(bputs::<S>),
|
||||
bgets: None,
|
||||
ctrl: Some(ctrl::<S>),
|
||||
create: Some(create),
|
||||
destroy: Some(destroy::<S>),
|
||||
callback_ctrl: None,
|
||||
});
|
||||
|
||||
Ok(BIO_METHOD(Box::into_raw(ptr)))
|
||||
}
|
||||
|
||||
fn get(&self) -> *mut ffi::BIO_METHOD {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for BIO_METHOD {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
Box::<ffi::BIO_METHOD>::from_raw(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn BIO_set_init(bio: *mut ffi::BIO, init: c_int) {
|
||||
(*bio).init = init;
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn BIO_set_flags(bio: *mut ffi::BIO, flags: c_int) {
|
||||
(*bio).flags = flags;
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn BIO_get_data(bio: *mut ffi::BIO) -> *mut c_void {
|
||||
(*bio).ptr
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn BIO_set_data(bio: *mut ffi::BIO, data: *mut c_void) {
|
||||
(*bio).ptr = data;
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn BIO_set_num(bio: *mut ffi::BIO, num: c_int) {
|
||||
(*bio).num = num;
|
||||
}
|
||||
}
|
||||
}
|
||||
695
zeroidc/vendor/openssl/src/ssl/callbacks.rs
vendored
Normal file
695
zeroidc/vendor/openssl/src/ssl/callbacks.rs
vendored
Normal file
@@ -0,0 +1,695 @@
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::ForeignType;
|
||||
use foreign_types::ForeignTypeRef;
|
||||
#[cfg(any(ossl111, not(osslconf = "OPENSSL_NO_PSK")))]
|
||||
use libc::c_char;
|
||||
#[cfg(ossl111)]
|
||||
use libc::size_t;
|
||||
use libc::{c_int, c_uchar, c_uint, c_void};
|
||||
#[cfg(any(ossl111, not(osslconf = "OPENSSL_NO_PSK")))]
|
||||
use std::ffi::CStr;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
#[cfg(ossl111)]
|
||||
use std::str;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::dh::Dh;
|
||||
#[cfg(all(ossl101, not(ossl110)))]
|
||||
use crate::ec::EcKey;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::Params;
|
||||
#[cfg(any(ossl102, libressl261))]
|
||||
use crate::ssl::AlpnError;
|
||||
use crate::ssl::{
|
||||
try_get_session_ctx_index, SniError, Ssl, SslAlert, SslContext, SslContextRef, SslRef,
|
||||
SslSession, SslSessionRef,
|
||||
};
|
||||
#[cfg(ossl111)]
|
||||
use crate::ssl::{ClientHelloResponse, ExtensionContext};
|
||||
#[cfg(ossl111)]
|
||||
use crate::util::ForeignTypeRefExt;
|
||||
#[cfg(ossl111)]
|
||||
use crate::x509::X509Ref;
|
||||
use crate::x509::{X509StoreContext, X509StoreContextRef};
|
||||
|
||||
pub extern "C" fn raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int
|
||||
where
|
||||
F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ctx = X509StoreContextRef::from_ptr_mut(x509_ctx);
|
||||
let ssl_idx = X509StoreContext::ssl_idx().expect("BUG: store context ssl index missing");
|
||||
let verify_idx = SslContext::cached_ex_index::<F>();
|
||||
|
||||
// raw pointer shenanigans to break the borrow of ctx
|
||||
// the callback can't mess with its own ex_data slot so this is safe
|
||||
let verify = ctx
|
||||
.ex_data(ssl_idx)
|
||||
.expect("BUG: store context missing ssl")
|
||||
.ssl_context()
|
||||
.ex_data(verify_idx)
|
||||
.expect("BUG: verify callback missing") as *const F;
|
||||
|
||||
(*verify)(preverify_ok != 0, ctx) as c_int
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
|
||||
pub extern "C" fn raw_client_psk<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
hint: *const c_char,
|
||||
identity: *mut c_char,
|
||||
max_identity_len: c_uint,
|
||||
psk: *mut c_uchar,
|
||||
max_psk_len: c_uint,
|
||||
) -> c_uint
|
||||
where
|
||||
F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
|
||||
+ 'static
|
||||
+ Sync
|
||||
+ Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback_idx = SslContext::cached_ex_index::<F>();
|
||||
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(callback_idx)
|
||||
.expect("BUG: psk callback missing") as *const F;
|
||||
let hint = if !hint.is_null() {
|
||||
Some(CStr::from_ptr(hint).to_bytes())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
// Give the callback mutable slices into which it can write the identity and psk.
|
||||
let identity_sl = slice::from_raw_parts_mut(identity as *mut u8, max_identity_len as usize);
|
||||
let psk_sl = slice::from_raw_parts_mut(psk as *mut u8, max_psk_len as usize);
|
||||
match (*callback)(ssl, hint, identity_sl, psk_sl) {
|
||||
Ok(psk_len) => psk_len as u32,
|
||||
Err(e) => {
|
||||
e.put();
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
|
||||
pub extern "C" fn raw_server_psk<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
identity: *const c_char,
|
||||
psk: *mut c_uchar,
|
||||
max_psk_len: c_uint,
|
||||
) -> c_uint
|
||||
where
|
||||
F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
|
||||
+ 'static
|
||||
+ Sync
|
||||
+ Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback_idx = SslContext::cached_ex_index::<F>();
|
||||
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(callback_idx)
|
||||
.expect("BUG: psk callback missing") as *const F;
|
||||
let identity = if identity.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(CStr::from_ptr(identity).to_bytes())
|
||||
};
|
||||
// Give the callback mutable slices into which it can write the psk.
|
||||
let psk_sl = slice::from_raw_parts_mut(psk as *mut u8, max_psk_len as usize);
|
||||
match (*callback)(ssl, identity, psk_sl) {
|
||||
Ok(psk_len) => psk_len as u32,
|
||||
Err(e) => {
|
||||
e.put();
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub extern "C" fn ssl_raw_verify<F>(
|
||||
preverify_ok: c_int,
|
||||
x509_ctx: *mut ffi::X509_STORE_CTX,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ctx = X509StoreContextRef::from_ptr_mut(x509_ctx);
|
||||
let ssl_idx = X509StoreContext::ssl_idx().expect("BUG: store context ssl index missing");
|
||||
let callback_idx = Ssl::cached_ex_index::<Arc<F>>();
|
||||
|
||||
let callback = ctx
|
||||
.ex_data(ssl_idx)
|
||||
.expect("BUG: store context missing ssl")
|
||||
.ex_data(callback_idx)
|
||||
.expect("BUG: ssl verify callback missing")
|
||||
.clone();
|
||||
|
||||
callback(preverify_ok != 0, ctx) as c_int
|
||||
}
|
||||
}
|
||||
|
||||
pub extern "C" fn raw_sni<F>(ssl: *mut ffi::SSL, al: *mut c_int, arg: *mut c_void) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = arg as *const F;
|
||||
let mut alert = SslAlert(*al);
|
||||
|
||||
let r = (*callback)(ssl, &mut alert);
|
||||
*al = alert.0;
|
||||
match r {
|
||||
Ok(()) => ffi::SSL_TLSEXT_ERR_OK,
|
||||
Err(e) => e.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl102, libressl261))]
|
||||
pub extern "C" fn raw_alpn_select<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
out: *mut *const c_uchar,
|
||||
outlen: *mut c_uchar,
|
||||
inbuf: *const c_uchar,
|
||||
inlen: c_uint,
|
||||
_arg: *mut c_void,
|
||||
) -> c_int
|
||||
where
|
||||
F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: alpn callback missing") as *const F;
|
||||
let protos = slice::from_raw_parts(inbuf as *const u8, inlen as usize);
|
||||
|
||||
match (*callback)(ssl, protos) {
|
||||
Ok(proto) => {
|
||||
*out = proto.as_ptr() as *const c_uchar;
|
||||
*outlen = proto.len() as c_uchar;
|
||||
ffi::SSL_TLSEXT_ERR_OK
|
||||
}
|
||||
Err(e) => e.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn raw_tmp_dh<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
is_export: c_int,
|
||||
keylength: c_int,
|
||||
) -> *mut ffi::DH
|
||||
where
|
||||
F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: tmp dh callback missing") as *const F;
|
||||
|
||||
match (*callback)(ssl, is_export != 0, keylength as u32) {
|
||||
Ok(dh) => {
|
||||
let ptr = dh.as_ptr();
|
||||
mem::forget(dh);
|
||||
ptr
|
||||
}
|
||||
Err(e) => {
|
||||
e.put();
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(ossl101, not(ossl110)))]
|
||||
pub unsafe extern "C" fn raw_tmp_ecdh<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
is_export: c_int,
|
||||
keylength: c_int,
|
||||
) -> *mut ffi::EC_KEY
|
||||
where
|
||||
F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: tmp ecdh callback missing") as *const F;
|
||||
|
||||
match (*callback)(ssl, is_export != 0, keylength as u32) {
|
||||
Ok(ec_key) => {
|
||||
let ptr = ec_key.as_ptr();
|
||||
mem::forget(ec_key);
|
||||
ptr
|
||||
}
|
||||
Err(e) => {
|
||||
e.put();
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn raw_tmp_dh_ssl<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
is_export: c_int,
|
||||
keylength: c_int,
|
||||
) -> *mut ffi::DH
|
||||
where
|
||||
F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ex_data(Ssl::cached_ex_index::<Arc<F>>())
|
||||
.expect("BUG: ssl tmp dh callback missing")
|
||||
.clone();
|
||||
|
||||
match callback(ssl, is_export != 0, keylength as u32) {
|
||||
Ok(dh) => {
|
||||
let ptr = dh.as_ptr();
|
||||
mem::forget(dh);
|
||||
ptr
|
||||
}
|
||||
Err(e) => {
|
||||
e.put();
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(ossl101, not(ossl110)))]
|
||||
pub unsafe extern "C" fn raw_tmp_ecdh_ssl<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
is_export: c_int,
|
||||
keylength: c_int,
|
||||
) -> *mut ffi::EC_KEY
|
||||
where
|
||||
F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ex_data(Ssl::cached_ex_index::<Arc<F>>())
|
||||
.expect("BUG: ssl tmp ecdh callback missing")
|
||||
.clone();
|
||||
|
||||
match callback(ssl, is_export != 0, keylength as u32) {
|
||||
Ok(ec_key) => {
|
||||
let ptr = ec_key.as_ptr();
|
||||
mem::forget(ec_key);
|
||||
ptr
|
||||
}
|
||||
Err(e) => {
|
||||
e.put();
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn raw_tlsext_status<F>(ssl: *mut ffi::SSL, _: *mut c_void) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: ocsp callback missing") as *const F;
|
||||
let ret = (*callback)(ssl);
|
||||
|
||||
if ssl.is_server() {
|
||||
match ret {
|
||||
Ok(true) => ffi::SSL_TLSEXT_ERR_OK,
|
||||
Ok(false) => ffi::SSL_TLSEXT_ERR_NOACK,
|
||||
Err(e) => {
|
||||
e.put();
|
||||
ffi::SSL_TLSEXT_ERR_ALERT_FATAL
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match ret {
|
||||
Ok(true) => 1,
|
||||
Ok(false) => 0,
|
||||
Err(e) => {
|
||||
e.put();
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn raw_new_session<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
session: *mut ffi::SSL_SESSION,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
|
||||
{
|
||||
let session_ctx_index =
|
||||
try_get_session_ctx_index().expect("BUG: session context index initialization failed");
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ex_data(*session_ctx_index)
|
||||
.expect("BUG: session context missing")
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: new session callback missing") as *const F;
|
||||
let session = SslSession::from_ptr(session);
|
||||
|
||||
(*callback)(ssl, session);
|
||||
|
||||
// the return code doesn't indicate error vs success, but whether or not we consumed the session
|
||||
1
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn raw_remove_session<F>(
|
||||
ctx: *mut ffi::SSL_CTX,
|
||||
session: *mut ffi::SSL_SESSION,
|
||||
) where
|
||||
F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
|
||||
{
|
||||
let ctx = SslContextRef::from_ptr(ctx);
|
||||
let callback = ctx
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: remove session callback missing");
|
||||
let session = SslSessionRef::from_ptr(session);
|
||||
|
||||
callback(ctx, session)
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl280))] {
|
||||
type DataPtr = *const c_uchar;
|
||||
} else {
|
||||
type DataPtr = *mut c_uchar;
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn raw_get_session<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
data: DataPtr,
|
||||
len: c_int,
|
||||
copy: *mut c_int,
|
||||
) -> *mut ffi::SSL_SESSION
|
||||
where
|
||||
F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
|
||||
{
|
||||
let session_ctx_index =
|
||||
try_get_session_ctx_index().expect("BUG: session context index initialization failed");
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ex_data(*session_ctx_index)
|
||||
.expect("BUG: session context missing")
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: get session callback missing") as *const F;
|
||||
let data = slice::from_raw_parts(data as *const u8, len as usize);
|
||||
|
||||
match (*callback)(ssl, data) {
|
||||
Some(session) => {
|
||||
let p = session.as_ptr();
|
||||
mem::forget(session);
|
||||
*copy = 0;
|
||||
p
|
||||
}
|
||||
None => ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub unsafe extern "C" fn raw_keylog<F>(ssl: *const ffi::SSL, line: *const c_char)
|
||||
where
|
||||
F: Fn(&SslRef, &str) + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_const_ptr(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: get session callback missing");
|
||||
let line = CStr::from_ptr(line).to_bytes();
|
||||
let line = str::from_utf8_unchecked(line);
|
||||
|
||||
callback(ssl, line);
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub unsafe extern "C" fn raw_stateless_cookie_generate<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
cookie: *mut c_uchar,
|
||||
cookie_len: *mut size_t,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: stateless cookie generate callback missing") as *const F;
|
||||
let slice = slice::from_raw_parts_mut(cookie as *mut u8, ffi::SSL_COOKIE_LENGTH as usize);
|
||||
match (*callback)(ssl, slice) {
|
||||
Ok(len) => {
|
||||
*cookie_len = len as size_t;
|
||||
1
|
||||
}
|
||||
Err(e) => {
|
||||
e.put();
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub unsafe extern "C" fn raw_stateless_cookie_verify<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
cookie: *const c_uchar,
|
||||
cookie_len: size_t,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: stateless cookie verify callback missing") as *const F;
|
||||
let slice = slice::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len as usize);
|
||||
(*callback)(ssl, slice) as c_int
|
||||
}
|
||||
|
||||
pub extern "C" fn raw_cookie_generate<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
cookie: *mut c_uchar,
|
||||
cookie_len: *mut c_uint,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: cookie generate callback missing") as *const F;
|
||||
// We subtract 1 from DTLS1_COOKIE_LENGTH as the ostensible value, 256, is erroneous but retained for
|
||||
// compatibility. See comments in dtls1.h.
|
||||
let slice =
|
||||
slice::from_raw_parts_mut(cookie as *mut u8, ffi::DTLS1_COOKIE_LENGTH as usize - 1);
|
||||
match (*callback)(ssl, slice) {
|
||||
Ok(len) => {
|
||||
*cookie_len = len as c_uint;
|
||||
1
|
||||
}
|
||||
Err(e) => {
|
||||
e.put();
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl280))] {
|
||||
type CookiePtr = *const c_uchar;
|
||||
} else {
|
||||
type CookiePtr = *mut c_uchar;
|
||||
}
|
||||
}
|
||||
|
||||
pub extern "C" fn raw_cookie_verify<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
cookie: CookiePtr,
|
||||
cookie_len: c_uint,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: cookie verify callback missing") as *const F;
|
||||
let slice =
|
||||
slice::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len as usize);
|
||||
(*callback)(ssl, slice) as c_int
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub struct CustomExtAddState<T>(Option<T>);
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub extern "C" fn raw_custom_ext_add<F, T>(
|
||||
ssl: *mut ffi::SSL,
|
||||
_: c_uint,
|
||||
context: c_uint,
|
||||
out: *mut *const c_uchar,
|
||||
outlen: *mut size_t,
|
||||
x: *mut ffi::X509,
|
||||
chainidx: size_t,
|
||||
al: *mut c_int,
|
||||
_: *mut c_void,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, ExtensionContext, Option<(usize, &X509Ref)>) -> Result<Option<T>, SslAlert>
|
||||
+ 'static
|
||||
+ Sync
|
||||
+ Send,
|
||||
T: AsRef<[u8]> + 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: custom ext add callback missing") as *const F;
|
||||
let ectx = ExtensionContext::from_bits_truncate(context);
|
||||
let cert = if ectx.contains(ExtensionContext::TLS1_3_CERTIFICATE) {
|
||||
Some((chainidx, X509Ref::from_ptr(x)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
match (*callback)(ssl, ectx, cert) {
|
||||
Ok(None) => 0,
|
||||
Ok(Some(buf)) => {
|
||||
*outlen = buf.as_ref().len();
|
||||
*out = buf.as_ref().as_ptr();
|
||||
|
||||
let idx = Ssl::cached_ex_index::<CustomExtAddState<T>>();
|
||||
let mut buf = Some(buf);
|
||||
let new = match ssl.ex_data_mut(idx) {
|
||||
Some(state) => {
|
||||
state.0 = buf.take();
|
||||
false
|
||||
}
|
||||
None => true,
|
||||
};
|
||||
if new {
|
||||
ssl.set_ex_data(idx, CustomExtAddState(buf));
|
||||
}
|
||||
1
|
||||
}
|
||||
Err(alert) => {
|
||||
*al = alert.0;
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub extern "C" fn raw_custom_ext_free<T>(
|
||||
ssl: *mut ffi::SSL,
|
||||
_: c_uint,
|
||||
_: c_uint,
|
||||
_: *const c_uchar,
|
||||
_: *mut c_void,
|
||||
) where
|
||||
T: 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let idx = Ssl::cached_ex_index::<CustomExtAddState<T>>();
|
||||
if let Some(state) = ssl.ex_data_mut(idx) {
|
||||
state.0 = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub extern "C" fn raw_custom_ext_parse<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
_: c_uint,
|
||||
context: c_uint,
|
||||
input: *const c_uchar,
|
||||
inlen: size_t,
|
||||
x: *mut ffi::X509,
|
||||
chainidx: size_t,
|
||||
al: *mut c_int,
|
||||
_: *mut c_void,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, ExtensionContext, &[u8], Option<(usize, &X509Ref)>) -> Result<(), SslAlert>
|
||||
+ 'static
|
||||
+ Sync
|
||||
+ Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: custom ext parse callback missing") as *const F;
|
||||
let ectx = ExtensionContext::from_bits_truncate(context);
|
||||
let slice = slice::from_raw_parts(input as *const u8, inlen as usize);
|
||||
let cert = if ectx.contains(ExtensionContext::TLS1_3_CERTIFICATE) {
|
||||
Some((chainidx, X509Ref::from_ptr(x)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
match (*callback)(ssl, ectx, slice, cert) {
|
||||
Ok(()) => 1,
|
||||
Err(alert) => {
|
||||
*al = alert.0;
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub unsafe extern "C" fn raw_client_hello<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
al: *mut c_int,
|
||||
arg: *mut c_void,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack>
|
||||
+ 'static
|
||||
+ Sync
|
||||
+ Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = arg as *const F;
|
||||
let mut alert = SslAlert(*al);
|
||||
|
||||
let r = (*callback)(ssl, &mut alert);
|
||||
*al = alert.0;
|
||||
match r {
|
||||
Ok(c) => c.0,
|
||||
Err(e) => {
|
||||
e.put();
|
||||
ffi::SSL_CLIENT_HELLO_ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
598
zeroidc/vendor/openssl/src/ssl/connector.rs
vendored
Normal file
598
zeroidc/vendor/openssl/src/ssl/connector.rs
vendored
Normal file
@@ -0,0 +1,598 @@
|
||||
use cfg_if::cfg_if;
|
||||
use std::io::{Read, Write};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use crate::dh::Dh;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::ssl::{
|
||||
HandshakeError, Ssl, SslContext, SslContextBuilder, SslContextRef, SslMethod, SslMode,
|
||||
SslOptions, SslRef, SslStream, SslVerifyMode,
|
||||
};
|
||||
use crate::version;
|
||||
|
||||
const FFDHE_2048: &str = "
|
||||
-----BEGIN DH PARAMETERS-----
|
||||
MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
|
||||
+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
|
||||
87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
|
||||
YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
|
||||
7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
|
||||
ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
|
||||
-----END DH PARAMETERS-----
|
||||
";
|
||||
|
||||
#[allow(clippy::inconsistent_digit_grouping, clippy::unusual_byte_groupings)]
|
||||
fn ctx(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
|
||||
let mut ctx = SslContextBuilder::new(method)?;
|
||||
|
||||
let mut opts = SslOptions::ALL
|
||||
| SslOptions::NO_COMPRESSION
|
||||
| SslOptions::NO_SSLV2
|
||||
| SslOptions::NO_SSLV3
|
||||
| SslOptions::SINGLE_DH_USE
|
||||
| SslOptions::SINGLE_ECDH_USE;
|
||||
opts &= !SslOptions::DONT_INSERT_EMPTY_FRAGMENTS;
|
||||
|
||||
ctx.set_options(opts);
|
||||
|
||||
let mut mode =
|
||||
SslMode::AUTO_RETRY | SslMode::ACCEPT_MOVING_WRITE_BUFFER | SslMode::ENABLE_PARTIAL_WRITE;
|
||||
|
||||
// This is quite a useful optimization for saving memory, but historically
|
||||
// caused CVEs in OpenSSL pre-1.0.1h, according to
|
||||
// https://bugs.python.org/issue25672
|
||||
if version::number() >= 0x1_00_01_08_0 {
|
||||
mode |= SslMode::RELEASE_BUFFERS;
|
||||
}
|
||||
|
||||
ctx.set_mode(mode);
|
||||
|
||||
Ok(ctx)
|
||||
}
|
||||
|
||||
/// A type which wraps client-side streams in a TLS session.
|
||||
///
|
||||
/// OpenSSL's default configuration is highly insecure. This connector manages the OpenSSL
|
||||
/// structures, configuring cipher suites, session options, hostname verification, and more.
|
||||
///
|
||||
/// OpenSSL's built-in hostname verification is used when linking against OpenSSL 1.0.2 or 1.1.0,
|
||||
/// and a custom implementation is used when linking against OpenSSL 1.0.1.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SslConnector(SslContext);
|
||||
|
||||
impl SslConnector {
|
||||
/// Creates a new builder for TLS connections.
|
||||
///
|
||||
/// The default configuration is subject to change, and is currently derived from Python.
|
||||
pub fn builder(method: SslMethod) -> Result<SslConnectorBuilder, ErrorStack> {
|
||||
let mut ctx = ctx(method)?;
|
||||
ctx.set_default_verify_paths()?;
|
||||
ctx.set_cipher_list(
|
||||
"DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK",
|
||||
)?;
|
||||
setup_verify(&mut ctx);
|
||||
|
||||
Ok(SslConnectorBuilder(ctx))
|
||||
}
|
||||
|
||||
/// Initiates a client-side TLS session on a stream.
|
||||
///
|
||||
/// The domain is used for SNI and hostname verification.
|
||||
pub fn connect<S>(&self, domain: &str, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
|
||||
where
|
||||
S: Read + Write,
|
||||
{
|
||||
self.configure()?.connect(domain, stream)
|
||||
}
|
||||
|
||||
/// Returns a structure allowing for configuration of a single TLS session before connection.
|
||||
pub fn configure(&self) -> Result<ConnectConfiguration, ErrorStack> {
|
||||
Ssl::new(&self.0).map(|ssl| ConnectConfiguration {
|
||||
ssl,
|
||||
sni: true,
|
||||
verify_hostname: true,
|
||||
})
|
||||
}
|
||||
|
||||
/// Consumes the `SslConnector`, returning the inner raw `SslContext`.
|
||||
pub fn into_context(self) -> SslContext {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns a shared reference to the inner raw `SslContext`.
|
||||
pub fn context(&self) -> &SslContextRef {
|
||||
&*self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A builder for `SslConnector`s.
|
||||
pub struct SslConnectorBuilder(SslContextBuilder);
|
||||
|
||||
impl SslConnectorBuilder {
|
||||
/// Consumes the builder, returning an `SslConnector`.
|
||||
pub fn build(self) -> SslConnector {
|
||||
SslConnector(self.0.build())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for SslConnectorBuilder {
|
||||
type Target = SslContextBuilder;
|
||||
|
||||
fn deref(&self) -> &SslContextBuilder {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for SslConnectorBuilder {
|
||||
fn deref_mut(&mut self) -> &mut SslContextBuilder {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A type which allows for configuration of a client-side TLS session before connection.
|
||||
pub struct ConnectConfiguration {
|
||||
ssl: Ssl,
|
||||
sni: bool,
|
||||
verify_hostname: bool,
|
||||
}
|
||||
|
||||
impl ConnectConfiguration {
|
||||
/// A builder-style version of `set_use_server_name_indication`.
|
||||
pub fn use_server_name_indication(mut self, use_sni: bool) -> ConnectConfiguration {
|
||||
self.set_use_server_name_indication(use_sni);
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the use of Server Name Indication (SNI) when connecting.
|
||||
///
|
||||
/// Defaults to `true`.
|
||||
pub fn set_use_server_name_indication(&mut self, use_sni: bool) {
|
||||
self.sni = use_sni;
|
||||
}
|
||||
|
||||
/// A builder-style version of `set_verify_hostname`.
|
||||
pub fn verify_hostname(mut self, verify_hostname: bool) -> ConnectConfiguration {
|
||||
self.set_verify_hostname(verify_hostname);
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the use of hostname verification when connecting.
|
||||
///
|
||||
/// Defaults to `true`.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// You should think very carefully before you use this method. If hostname verification is not
|
||||
/// used, *any* valid certificate for *any* site will be trusted for use from any other. This
|
||||
/// introduces a significant vulnerability to man-in-the-middle attacks.
|
||||
pub fn set_verify_hostname(&mut self, verify_hostname: bool) {
|
||||
self.verify_hostname = verify_hostname;
|
||||
}
|
||||
|
||||
/// Returns an `Ssl` configured to connect to the provided domain.
|
||||
///
|
||||
/// The domain is used for SNI and hostname verification if enabled.
|
||||
pub fn into_ssl(mut self, domain: &str) -> Result<Ssl, ErrorStack> {
|
||||
if self.sni {
|
||||
self.ssl.set_hostname(domain)?;
|
||||
}
|
||||
|
||||
if self.verify_hostname {
|
||||
setup_verify_hostname(&mut self.ssl, domain)?;
|
||||
}
|
||||
|
||||
Ok(self.ssl)
|
||||
}
|
||||
|
||||
/// Initiates a client-side TLS session on a stream.
|
||||
///
|
||||
/// The domain is used for SNI and hostname verification if enabled.
|
||||
pub fn connect<S>(self, domain: &str, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
|
||||
where
|
||||
S: Read + Write,
|
||||
{
|
||||
self.into_ssl(domain)?.connect(stream)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for ConnectConfiguration {
|
||||
type Target = SslRef;
|
||||
|
||||
fn deref(&self) -> &SslRef {
|
||||
&self.ssl
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for ConnectConfiguration {
|
||||
fn deref_mut(&mut self) -> &mut SslRef {
|
||||
&mut self.ssl
|
||||
}
|
||||
}
|
||||
|
||||
/// A type which wraps server-side streams in a TLS session.
|
||||
///
|
||||
/// OpenSSL's default configuration is highly insecure. This connector manages the OpenSSL
|
||||
/// structures, configuring cipher suites, session options, and more.
|
||||
#[derive(Clone)]
|
||||
pub struct SslAcceptor(SslContext);
|
||||
|
||||
impl SslAcceptor {
|
||||
/// Creates a new builder configured to connect to non-legacy clients. This should generally be
|
||||
/// considered a reasonable default choice.
|
||||
///
|
||||
/// This corresponds to the intermediate configuration of version 5 of Mozilla's server side TLS
|
||||
/// recommendations. See its [documentation][docs] for more details on specifics.
|
||||
///
|
||||
/// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS
|
||||
pub fn mozilla_intermediate_v5(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
|
||||
let mut ctx = ctx(method)?;
|
||||
ctx.set_options(SslOptions::NO_TLSV1 | SslOptions::NO_TLSV1_1);
|
||||
let dh = Dh::params_from_pem(FFDHE_2048.as_bytes())?;
|
||||
ctx.set_tmp_dh(&dh)?;
|
||||
setup_curves(&mut ctx)?;
|
||||
ctx.set_cipher_list(
|
||||
"ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:\
|
||||
ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\
|
||||
DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
|
||||
)?;
|
||||
#[cfg(ossl111)]
|
||||
ctx.set_ciphersuites(
|
||||
"TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256",
|
||||
)?;
|
||||
Ok(SslAcceptorBuilder(ctx))
|
||||
}
|
||||
|
||||
/// Creates a new builder configured to connect to modern clients.
|
||||
///
|
||||
/// This corresponds to the modern configuration of version 5 of Mozilla's server side TLS recommendations.
|
||||
/// See its [documentation][docs] for more details on specifics.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
///
|
||||
/// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS
|
||||
#[cfg(ossl111)]
|
||||
pub fn mozilla_modern_v5(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
|
||||
let mut ctx = ctx(method)?;
|
||||
ctx.set_options(SslOptions::NO_SSL_MASK & !SslOptions::NO_TLSV1_3);
|
||||
ctx.set_ciphersuites(
|
||||
"TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256",
|
||||
)?;
|
||||
Ok(SslAcceptorBuilder(ctx))
|
||||
}
|
||||
|
||||
/// Creates a new builder configured to connect to non-legacy clients. This should generally be
|
||||
/// considered a reasonable default choice.
|
||||
///
|
||||
/// This corresponds to the intermediate configuration of version 4 of Mozilla's server side TLS
|
||||
/// recommendations. See its [documentation][docs] for more details on specifics.
|
||||
///
|
||||
/// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS
|
||||
// FIXME remove in next major version
|
||||
pub fn mozilla_intermediate(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
|
||||
let mut ctx = ctx(method)?;
|
||||
ctx.set_options(SslOptions::CIPHER_SERVER_PREFERENCE);
|
||||
#[cfg(ossl111)]
|
||||
ctx.set_options(SslOptions::NO_TLSV1_3);
|
||||
let dh = Dh::params_from_pem(FFDHE_2048.as_bytes())?;
|
||||
ctx.set_tmp_dh(&dh)?;
|
||||
setup_curves(&mut ctx)?;
|
||||
ctx.set_cipher_list(
|
||||
"ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305: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-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:\
|
||||
ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:\
|
||||
ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:\
|
||||
DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:\
|
||||
EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:\
|
||||
AES256-SHA:DES-CBC3-SHA:!DSS",
|
||||
)?;
|
||||
Ok(SslAcceptorBuilder(ctx))
|
||||
}
|
||||
|
||||
/// Creates a new builder configured to connect to modern clients.
|
||||
///
|
||||
/// This corresponds to the modern configuration of version 4 of Mozilla's server side TLS recommendations.
|
||||
/// See its [documentation][docs] for more details on specifics.
|
||||
///
|
||||
/// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS
|
||||
// FIXME remove in next major version
|
||||
pub fn mozilla_modern(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
|
||||
let mut ctx = ctx(method)?;
|
||||
ctx.set_options(
|
||||
SslOptions::CIPHER_SERVER_PREFERENCE | SslOptions::NO_TLSV1 | SslOptions::NO_TLSV1_1,
|
||||
);
|
||||
#[cfg(ossl111)]
|
||||
ctx.set_options(SslOptions::NO_TLSV1_3);
|
||||
setup_curves(&mut ctx)?;
|
||||
ctx.set_cipher_list(
|
||||
"ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:\
|
||||
ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:\
|
||||
ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256",
|
||||
)?;
|
||||
Ok(SslAcceptorBuilder(ctx))
|
||||
}
|
||||
|
||||
/// Initiates a server-side TLS session on a stream.
|
||||
pub fn accept<S>(&self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
|
||||
where
|
||||
S: Read + Write,
|
||||
{
|
||||
let ssl = Ssl::new(&self.0)?;
|
||||
ssl.accept(stream)
|
||||
}
|
||||
|
||||
/// Consumes the `SslAcceptor`, returning the inner raw `SslContext`.
|
||||
pub fn into_context(self) -> SslContext {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns a shared reference to the inner raw `SslContext`.
|
||||
pub fn context(&self) -> &SslContextRef {
|
||||
&*self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A builder for `SslAcceptor`s.
|
||||
pub struct SslAcceptorBuilder(SslContextBuilder);
|
||||
|
||||
impl SslAcceptorBuilder {
|
||||
/// Consumes the builder, returning a `SslAcceptor`.
|
||||
pub fn build(self) -> SslAcceptor {
|
||||
SslAcceptor(self.0.build())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for SslAcceptorBuilder {
|
||||
type Target = SslContextBuilder;
|
||||
|
||||
fn deref(&self) -> &SslContextBuilder {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for SslAcceptorBuilder {
|
||||
fn deref_mut(&mut self) -> &mut SslContextBuilder {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl110)] {
|
||||
#[allow(clippy::unnecessary_wraps)]
|
||||
fn setup_curves(_: &mut SslContextBuilder) -> Result<(), ErrorStack> {
|
||||
Ok(())
|
||||
}
|
||||
} else if #[cfg(any(ossl102, libressl))] {
|
||||
fn setup_curves(ctx: &mut SslContextBuilder) -> Result<(), ErrorStack> {
|
||||
ctx.set_ecdh_auto(true)
|
||||
}
|
||||
} else {
|
||||
fn setup_curves(ctx: &mut SslContextBuilder) -> Result<(), ErrorStack> {
|
||||
use crate::ec::EcKey;
|
||||
use crate::nid::Nid;
|
||||
|
||||
let curve = EcKey::from_curve_name(Nid::X9_62_PRIME256V1)?;
|
||||
ctx.set_tmp_ecdh(&curve)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl102, libressl261))] {
|
||||
fn setup_verify(ctx: &mut SslContextBuilder) {
|
||||
ctx.set_verify(SslVerifyMode::PEER);
|
||||
}
|
||||
|
||||
fn setup_verify_hostname(ssl: &mut SslRef, domain: &str) -> Result<(), ErrorStack> {
|
||||
use crate::x509::verify::X509CheckFlags;
|
||||
|
||||
let param = ssl.param_mut();
|
||||
param.set_hostflags(X509CheckFlags::NO_PARTIAL_WILDCARDS);
|
||||
match domain.parse() {
|
||||
Ok(ip) => param.set_ip(ip),
|
||||
Err(_) => param.set_host(domain),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fn setup_verify(ctx: &mut SslContextBuilder) {
|
||||
ctx.set_verify_callback(SslVerifyMode::PEER, verify::verify_callback);
|
||||
}
|
||||
|
||||
fn setup_verify_hostname(ssl: &mut Ssl, domain: &str) -> Result<(), ErrorStack> {
|
||||
let domain = domain.to_string();
|
||||
let hostname_idx = verify::try_get_hostname_idx()?;
|
||||
ssl.set_ex_data(*hostname_idx, domain);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
mod verify {
|
||||
use std::net::IpAddr;
|
||||
use std::str;
|
||||
use once_cell::sync::OnceCell;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::ex_data::Index;
|
||||
use crate::nid::Nid;
|
||||
use crate::ssl::Ssl;
|
||||
use crate::stack::Stack;
|
||||
use crate::x509::{
|
||||
GeneralName, X509NameRef, X509Ref, X509StoreContext, X509StoreContextRef,
|
||||
X509VerifyResult,
|
||||
};
|
||||
|
||||
static HOSTNAME_IDX: OnceCell<Index<Ssl, String>> = OnceCell::new();
|
||||
|
||||
pub fn try_get_hostname_idx() -> Result<&'static Index<Ssl, String>, ErrorStack> {
|
||||
HOSTNAME_IDX.get_or_try_init(Ssl::new_ex_index)
|
||||
}
|
||||
|
||||
pub fn verify_callback(preverify_ok: bool, x509_ctx: &mut X509StoreContextRef) -> bool {
|
||||
if !preverify_ok || x509_ctx.error_depth() != 0 {
|
||||
return preverify_ok;
|
||||
}
|
||||
|
||||
let hostname_idx =
|
||||
try_get_hostname_idx().expect("failed to initialize hostname index");
|
||||
let ok = match (
|
||||
x509_ctx.current_cert(),
|
||||
X509StoreContext::ssl_idx()
|
||||
.ok()
|
||||
.and_then(|idx| x509_ctx.ex_data(idx))
|
||||
.and_then(|ssl| ssl.ex_data(*hostname_idx)),
|
||||
) {
|
||||
(Some(x509), Some(domain)) => verify_hostname(domain, &x509),
|
||||
_ => true,
|
||||
};
|
||||
|
||||
if !ok {
|
||||
x509_ctx.set_error(X509VerifyResult::APPLICATION_VERIFICATION);
|
||||
}
|
||||
|
||||
ok
|
||||
}
|
||||
|
||||
fn verify_hostname(domain: &str, cert: &X509Ref) -> bool {
|
||||
match cert.subject_alt_names() {
|
||||
Some(names) => verify_subject_alt_names(domain, names),
|
||||
None => verify_subject_name(domain, &cert.subject_name()),
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_subject_alt_names(domain: &str, names: Stack<GeneralName>) -> bool {
|
||||
let ip = domain.parse();
|
||||
|
||||
for name in &names {
|
||||
match ip {
|
||||
Ok(ip) => {
|
||||
if let Some(actual) = name.ipaddress() {
|
||||
if matches_ip(&ip, actual) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
if let Some(pattern) = name.dnsname() {
|
||||
if matches_dns(pattern, domain) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn verify_subject_name(domain: &str, subject_name: &X509NameRef) -> bool {
|
||||
match subject_name.entries_by_nid(Nid::COMMONNAME).next() {
|
||||
Some(pattern) => {
|
||||
let pattern = match str::from_utf8(pattern.data().as_slice()) {
|
||||
Ok(pattern) => pattern,
|
||||
Err(_) => return false,
|
||||
};
|
||||
|
||||
// Unlike SANs, IP addresses in the subject name don't have a
|
||||
// different encoding.
|
||||
match domain.parse::<IpAddr>() {
|
||||
Ok(ip) => pattern
|
||||
.parse::<IpAddr>()
|
||||
.ok()
|
||||
.map_or(false, |pattern| pattern == ip),
|
||||
Err(_) => matches_dns(pattern, domain),
|
||||
}
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn matches_dns(mut pattern: &str, mut hostname: &str) -> bool {
|
||||
// first strip trailing . off of pattern and hostname to normalize
|
||||
if pattern.ends_with('.') {
|
||||
pattern = &pattern[..pattern.len() - 1];
|
||||
}
|
||||
if hostname.ends_with('.') {
|
||||
hostname = &hostname[..hostname.len() - 1];
|
||||
}
|
||||
|
||||
matches_wildcard(pattern, hostname).unwrap_or_else(|| pattern.eq_ignore_ascii_case(hostname))
|
||||
}
|
||||
|
||||
fn matches_wildcard(pattern: &str, hostname: &str) -> Option<bool> {
|
||||
let wildcard_location = match pattern.find('*') {
|
||||
Some(l) => l,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
let mut dot_idxs = pattern.match_indices('.').map(|(l, _)| l);
|
||||
let wildcard_end = match dot_idxs.next() {
|
||||
Some(l) => l,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
// Never match wildcards if the pattern has less than 2 '.'s (no *.com)
|
||||
//
|
||||
// This is a bit dubious, as it doesn't disallow other TLDs like *.co.uk.
|
||||
// Chrome has a black- and white-list for this, but Firefox (via NSS) does
|
||||
// the same thing we do here.
|
||||
//
|
||||
// The Public Suffix (https://www.publicsuffix.org/) list could
|
||||
// potentially be used here, but it's both huge and updated frequently
|
||||
// enough that management would be a PITA.
|
||||
if dot_idxs.next().is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Wildcards can only be in the first component, and must be the entire first label
|
||||
if wildcard_location != 0 || wildcard_end != wildcard_location + 1 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let hostname_label_end = match hostname.find('.') {
|
||||
Some(l) => l,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
let pattern_after_wildcard = &pattern[wildcard_end..];
|
||||
let hostname_after_wildcard = &hostname[hostname_label_end..];
|
||||
|
||||
Some(pattern_after_wildcard.eq_ignore_ascii_case(hostname_after_wildcard))
|
||||
}
|
||||
|
||||
fn matches_ip(expected: &IpAddr, actual: &[u8]) -> bool {
|
||||
match *expected {
|
||||
IpAddr::V4(ref addr) => actual == addr.octets(),
|
||||
IpAddr::V6(ref addr) => actual == addr.octets(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dns_match() {
|
||||
use crate::ssl::connector::verify::matches_dns;
|
||||
assert!(matches_dns("website.tld", "website.tld")); // A name should match itself.
|
||||
assert!(matches_dns("website.tld", "wEbSiTe.tLd")); // DNS name matching ignores case of hostname.
|
||||
assert!(matches_dns("wEbSiTe.TlD", "website.tld")); // DNS name matching ignores case of subject.
|
||||
|
||||
assert!(matches_dns("xn--bcher-kva.tld", "xn--bcher-kva.tld")); // Likewise, nothing special to punycode names.
|
||||
assert!(matches_dns("xn--bcher-kva.tld", "xn--BcHer-Kva.tLd")); // And punycode must be compared similarly case-insensitively.
|
||||
|
||||
assert!(matches_dns("*.example.com", "subdomain.example.com")); // Wildcard matching works.
|
||||
assert!(matches_dns("*.eXaMpLe.cOm", "subdomain.example.com")); // Wildcard matching ignores case of subject.
|
||||
assert!(matches_dns("*.example.com", "sUbDoMaIn.eXaMpLe.cOm")); // Wildcard matching ignores case of hostname.
|
||||
|
||||
assert!(!matches_dns("prefix*.example.com", "p.example.com")); // Prefix longer than the label works and does not match.
|
||||
assert!(!matches_dns("*suffix.example.com", "s.example.com")); // Suffix longer than the label works and does not match.
|
||||
|
||||
assert!(!matches_dns("prefix*.example.com", "prefix.example.com")); // Partial wildcards do not work.
|
||||
assert!(!matches_dns("*suffix.example.com", "suffix.example.com")); // Partial wildcards do not work.
|
||||
|
||||
assert!(!matches_dns("prefix*.example.com", "prefixdomain.example.com")); // Partial wildcards do not work.
|
||||
assert!(!matches_dns("*suffix.example.com", "domainsuffix.example.com")); // Partial wildcards do not work.
|
||||
|
||||
assert!(!matches_dns("xn--*.example.com", "subdomain.example.com")); // Punycode domains with wildcard parts do not match.
|
||||
assert!(!matches_dns("xN--*.example.com", "subdomain.example.com")); // And we can't bypass a punycode test with weird casing.
|
||||
assert!(!matches_dns("Xn--*.example.com", "subdomain.example.com")); // And we can't bypass a punycode test with weird casing.
|
||||
assert!(!matches_dns("XN--*.example.com", "subdomain.example.com")); // And we can't bypass a punycode test with weird casing.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
185
zeroidc/vendor/openssl/src/ssl/error.rs
vendored
Normal file
185
zeroidc/vendor/openssl/src/ssl/error.rs
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
use libc::c_int;
|
||||
use std::error;
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::ssl::MidHandshakeSslStream;
|
||||
use crate::x509::X509VerifyResult;
|
||||
|
||||
/// An error code returned from SSL functions.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct ErrorCode(c_int);
|
||||
|
||||
impl ErrorCode {
|
||||
/// The SSL session has been closed.
|
||||
pub const ZERO_RETURN: ErrorCode = ErrorCode(ffi::SSL_ERROR_ZERO_RETURN);
|
||||
|
||||
/// An attempt to read data from the underlying socket returned `WouldBlock`.
|
||||
///
|
||||
/// Wait for read readiness and retry the operation.
|
||||
pub const WANT_READ: ErrorCode = ErrorCode(ffi::SSL_ERROR_WANT_READ);
|
||||
|
||||
/// An attempt to write data to the underlying socket returned `WouldBlock`.
|
||||
///
|
||||
/// Wait for write readiness and retry the operation.
|
||||
pub const WANT_WRITE: ErrorCode = ErrorCode(ffi::SSL_ERROR_WANT_WRITE);
|
||||
|
||||
/// A non-recoverable IO error occurred.
|
||||
pub const SYSCALL: ErrorCode = ErrorCode(ffi::SSL_ERROR_SYSCALL);
|
||||
|
||||
/// An error occurred in the SSL library.
|
||||
pub const SSL: ErrorCode = ErrorCode(ffi::SSL_ERROR_SSL);
|
||||
|
||||
/// The client hello callback indicated that it needed to be retried.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[cfg(ossl111)]
|
||||
pub const WANT_CLIENT_HELLO_CB: ErrorCode = ErrorCode(ffi::SSL_ERROR_WANT_CLIENT_HELLO_CB);
|
||||
|
||||
pub fn from_raw(raw: c_int) -> ErrorCode {
|
||||
ErrorCode(raw)
|
||||
}
|
||||
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum InnerError {
|
||||
Io(io::Error),
|
||||
Ssl(ErrorStack),
|
||||
}
|
||||
|
||||
/// An SSL error.
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
pub(crate) code: ErrorCode,
|
||||
pub(crate) cause: Option<InnerError>,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn code(&self) -> ErrorCode {
|
||||
self.code
|
||||
}
|
||||
|
||||
pub fn io_error(&self) -> Option<&io::Error> {
|
||||
match self.cause {
|
||||
Some(InnerError::Io(ref e)) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_io_error(self) -> Result<io::Error, Error> {
|
||||
match self.cause {
|
||||
Some(InnerError::Io(e)) => Ok(e),
|
||||
_ => Err(self),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ssl_error(&self) -> Option<&ErrorStack> {
|
||||
match self.cause {
|
||||
Some(InnerError::Ssl(ref e)) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ErrorStack> for Error {
|
||||
fn from(e: ErrorStack) -> Error {
|
||||
Error {
|
||||
code: ErrorCode::SSL,
|
||||
cause: Some(InnerError::Ssl(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.code {
|
||||
ErrorCode::ZERO_RETURN => fmt.write_str("the SSL session has been shut down"),
|
||||
ErrorCode::WANT_READ => match self.io_error() {
|
||||
Some(_) => fmt.write_str("a nonblocking read call would have blocked"),
|
||||
None => fmt.write_str("the operation should be retried"),
|
||||
},
|
||||
ErrorCode::WANT_WRITE => match self.io_error() {
|
||||
Some(_) => fmt.write_str("a nonblocking write call would have blocked"),
|
||||
None => fmt.write_str("the operation should be retried"),
|
||||
},
|
||||
ErrorCode::SYSCALL => match self.io_error() {
|
||||
Some(err) => write!(fmt, "{}", err),
|
||||
None => fmt.write_str("unexpected EOF"),
|
||||
},
|
||||
ErrorCode::SSL => match self.ssl_error() {
|
||||
Some(e) => write!(fmt, "{}", e),
|
||||
None => fmt.write_str("OpenSSL error"),
|
||||
},
|
||||
ErrorCode(code) => write!(fmt, "unknown error code {}", code),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match self.cause {
|
||||
Some(InnerError::Io(ref e)) => Some(e),
|
||||
Some(InnerError::Ssl(ref e)) => Some(e),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An error or intermediate state after a TLS handshake attempt.
|
||||
// FIXME overhaul
|
||||
#[derive(Debug)]
|
||||
pub enum HandshakeError<S> {
|
||||
/// Setup failed.
|
||||
SetupFailure(ErrorStack),
|
||||
/// The handshake failed.
|
||||
Failure(MidHandshakeSslStream<S>),
|
||||
/// The handshake encountered a `WouldBlock` error midway through.
|
||||
///
|
||||
/// This error will never be returned for blocking streams.
|
||||
WouldBlock(MidHandshakeSslStream<S>),
|
||||
}
|
||||
|
||||
impl<S: fmt::Debug> StdError for HandshakeError<S> {
|
||||
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
||||
match *self {
|
||||
HandshakeError::SetupFailure(ref e) => Some(e),
|
||||
HandshakeError::Failure(ref s) | HandshakeError::WouldBlock(ref s) => Some(s.error()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: fmt::Debug> fmt::Display for HandshakeError<S> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
HandshakeError::SetupFailure(ref e) => write!(f, "stream setup failed: {}", e)?,
|
||||
HandshakeError::Failure(ref s) => {
|
||||
write!(f, "the handshake failed: {}", s.error())?;
|
||||
let verify = s.ssl().verify_result();
|
||||
if verify != X509VerifyResult::OK {
|
||||
write!(f, ": {}", verify)?;
|
||||
}
|
||||
}
|
||||
HandshakeError::WouldBlock(ref s) => {
|
||||
write!(f, "the handshake was interrupted: {}", s.error())?;
|
||||
let verify = s.ssl().verify_result();
|
||||
if verify != X509VerifyResult::OK {
|
||||
write!(f, ": {}", verify)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<ErrorStack> for HandshakeError<S> {
|
||||
fn from(e: ErrorStack) -> HandshakeError<S> {
|
||||
HandshakeError::SetupFailure(e)
|
||||
}
|
||||
}
|
||||
3794
zeroidc/vendor/openssl/src/ssl/mod.rs
vendored
Normal file
3794
zeroidc/vendor/openssl/src/ssl/mod.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1405
zeroidc/vendor/openssl/src/ssl/test/mod.rs
vendored
Normal file
1405
zeroidc/vendor/openssl/src/ssl/test/mod.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
167
zeroidc/vendor/openssl/src/ssl/test/server.rs
vendored
Normal file
167
zeroidc/vendor/openssl/src/ssl/test/server.rs
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
use std::io::{Read, Write};
|
||||
use std::net::{SocketAddr, TcpListener, TcpStream};
|
||||
use std::thread::{self, JoinHandle};
|
||||
|
||||
use crate::ssl::{Ssl, SslContext, SslContextBuilder, SslFiletype, SslMethod, SslRef, SslStream};
|
||||
|
||||
pub struct Server {
|
||||
handle: Option<JoinHandle<()>>,
|
||||
addr: SocketAddr,
|
||||
}
|
||||
|
||||
impl Drop for Server {
|
||||
fn drop(&mut self) {
|
||||
if !thread::panicking() {
|
||||
self.handle.take().unwrap().join().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Server {
|
||||
pub fn builder() -> Builder {
|
||||
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
|
||||
ctx.set_certificate_chain_file("test/cert.pem").unwrap();
|
||||
ctx.set_private_key_file("test/key.pem", SslFiletype::PEM)
|
||||
.unwrap();
|
||||
|
||||
Builder {
|
||||
ctx,
|
||||
ssl_cb: Box::new(|_| {}),
|
||||
io_cb: Box::new(|_| {}),
|
||||
should_error: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn client(&self) -> ClientBuilder {
|
||||
ClientBuilder {
|
||||
ctx: SslContext::builder(SslMethod::tls()).unwrap(),
|
||||
addr: self.addr,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connect_tcp(&self) -> TcpStream {
|
||||
TcpStream::connect(self.addr).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Builder {
|
||||
ctx: SslContextBuilder,
|
||||
ssl_cb: Box<dyn FnMut(&mut SslRef) + Send>,
|
||||
io_cb: Box<dyn FnMut(SslStream<TcpStream>) + Send>,
|
||||
should_error: bool,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
pub fn ctx(&mut self) -> &mut SslContextBuilder {
|
||||
&mut self.ctx
|
||||
}
|
||||
|
||||
pub fn ssl_cb<F>(&mut self, cb: F)
|
||||
where
|
||||
F: 'static + FnMut(&mut SslRef) + Send,
|
||||
{
|
||||
self.ssl_cb = Box::new(cb);
|
||||
}
|
||||
|
||||
pub fn io_cb<F>(&mut self, cb: F)
|
||||
where
|
||||
F: 'static + FnMut(SslStream<TcpStream>) + Send,
|
||||
{
|
||||
self.io_cb = Box::new(cb);
|
||||
}
|
||||
|
||||
pub fn should_error(&mut self) {
|
||||
self.should_error = true;
|
||||
}
|
||||
|
||||
pub fn build(self) -> Server {
|
||||
let ctx = self.ctx.build();
|
||||
let socket = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let addr = socket.local_addr().unwrap();
|
||||
let mut ssl_cb = self.ssl_cb;
|
||||
let mut io_cb = self.io_cb;
|
||||
let should_error = self.should_error;
|
||||
|
||||
let handle = thread::spawn(move || {
|
||||
let socket = socket.accept().unwrap().0;
|
||||
let mut ssl = Ssl::new(&ctx).unwrap();
|
||||
ssl_cb(&mut ssl);
|
||||
let r = ssl.accept(socket);
|
||||
if should_error {
|
||||
r.unwrap_err();
|
||||
} else {
|
||||
let mut socket = r.unwrap();
|
||||
socket.write_all(&[0]).unwrap();
|
||||
io_cb(socket);
|
||||
}
|
||||
});
|
||||
|
||||
Server {
|
||||
handle: Some(handle),
|
||||
addr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClientBuilder {
|
||||
ctx: SslContextBuilder,
|
||||
addr: SocketAddr,
|
||||
}
|
||||
|
||||
impl ClientBuilder {
|
||||
pub fn ctx(&mut self) -> &mut SslContextBuilder {
|
||||
&mut self.ctx
|
||||
}
|
||||
|
||||
pub fn build(self) -> Client {
|
||||
Client {
|
||||
ctx: self.ctx.build(),
|
||||
addr: self.addr,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connect(self) -> SslStream<TcpStream> {
|
||||
self.build().builder().connect()
|
||||
}
|
||||
|
||||
pub fn connect_err(self) {
|
||||
self.build().builder().connect_err();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Client {
|
||||
ctx: SslContext,
|
||||
addr: SocketAddr,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn builder(&self) -> ClientSslBuilder {
|
||||
ClientSslBuilder {
|
||||
ssl: Ssl::new(&self.ctx).unwrap(),
|
||||
addr: self.addr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClientSslBuilder {
|
||||
ssl: Ssl,
|
||||
addr: SocketAddr,
|
||||
}
|
||||
|
||||
impl ClientSslBuilder {
|
||||
pub fn ssl(&mut self) -> &mut SslRef {
|
||||
&mut self.ssl
|
||||
}
|
||||
|
||||
pub fn connect(self) -> SslStream<TcpStream> {
|
||||
let socket = TcpStream::connect(self.addr).unwrap();
|
||||
let mut s = self.ssl.connect(socket).unwrap();
|
||||
s.read_exact(&mut [0]).unwrap();
|
||||
s
|
||||
}
|
||||
|
||||
pub fn connect_err(self) {
|
||||
let socket = TcpStream::connect(self.addr).unwrap();
|
||||
self.ssl.connect(socket).unwrap_err();
|
||||
}
|
||||
}
|
||||
380
zeroidc/vendor/openssl/src/stack.rs
vendored
Normal file
380
zeroidc/vendor/openssl/src/stack.rs
vendored
Normal file
@@ -0,0 +1,380 @@
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
|
||||
use libc::c_int;
|
||||
use std::borrow::Borrow;
|
||||
use std::convert::AsRef;
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut, Index, IndexMut, Range};
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::util::ForeignTypeExt;
|
||||
use crate::{cvt, cvt_p};
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl110)] {
|
||||
use ffi::{
|
||||
OPENSSL_sk_pop, OPENSSL_sk_free, OPENSSL_sk_num, OPENSSL_sk_value, OPENSSL_STACK,
|
||||
OPENSSL_sk_new_null, OPENSSL_sk_push,
|
||||
};
|
||||
} else {
|
||||
use ffi::{
|
||||
sk_pop as OPENSSL_sk_pop, sk_free as OPENSSL_sk_free, sk_num as OPENSSL_sk_num,
|
||||
sk_value as OPENSSL_sk_value, _STACK as OPENSSL_STACK,
|
||||
sk_new_null as OPENSSL_sk_new_null, sk_push as OPENSSL_sk_push,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait implemented by types which can be placed in a stack.
|
||||
///
|
||||
/// It should not be implemented for any type outside of this crate.
|
||||
pub trait Stackable: ForeignType {
|
||||
/// The C stack type for this element.
|
||||
///
|
||||
/// Generally called `stack_st_{ELEMENT_TYPE}`, normally hidden by the
|
||||
/// `STACK_OF(ELEMENT_TYPE)` macro in the OpenSSL API.
|
||||
type StackType;
|
||||
}
|
||||
|
||||
/// An owned stack of `T`.
|
||||
pub struct Stack<T: Stackable>(*mut T::StackType);
|
||||
|
||||
unsafe impl<T: Stackable + Send> Send for Stack<T> {}
|
||||
unsafe impl<T: Stackable + Sync> Sync for Stack<T> {}
|
||||
|
||||
impl<T> fmt::Debug for Stack<T>
|
||||
where
|
||||
T: Stackable,
|
||||
T::Ref: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_list().entries(self).finish()
|
||||
}
|
||||
}
|
||||
impl<T: Stackable> Drop for Stack<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
while self.pop().is_some() {}
|
||||
OPENSSL_sk_free(self.0 as *mut _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> Stack<T> {
|
||||
pub fn new() -> Result<Stack<T>, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
let ptr = cvt_p(OPENSSL_sk_new_null())?;
|
||||
Ok(Stack(ptr as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> iter::IntoIterator for Stack<T> {
|
||||
type IntoIter = IntoIter<T>;
|
||||
type Item = T;
|
||||
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
let it = IntoIter {
|
||||
stack: self.0,
|
||||
idxs: 0..self.len() as c_int,
|
||||
};
|
||||
mem::forget(self);
|
||||
it
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> AsRef<StackRef<T>> for Stack<T> {
|
||||
fn as_ref(&self) -> &StackRef<T> {
|
||||
&*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> Borrow<StackRef<T>> for Stack<T> {
|
||||
fn borrow(&self) -> &StackRef<T> {
|
||||
&*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> ForeignType for Stack<T> {
|
||||
type CType = T::StackType;
|
||||
type Ref = StackRef<T>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn from_ptr(ptr: *mut T::StackType) -> Stack<T> {
|
||||
assert!(
|
||||
!ptr.is_null(),
|
||||
"Must not instantiate a Stack from a null-ptr - use Stack::new() in \
|
||||
that case"
|
||||
);
|
||||
Stack(ptr)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut T::StackType {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> Deref for Stack<T> {
|
||||
type Target = StackRef<T>;
|
||||
|
||||
fn deref(&self) -> &StackRef<T> {
|
||||
unsafe { StackRef::from_ptr(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> DerefMut for Stack<T> {
|
||||
fn deref_mut(&mut self) -> &mut StackRef<T> {
|
||||
unsafe { StackRef::from_ptr_mut(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IntoIter<T: Stackable> {
|
||||
stack: *mut T::StackType,
|
||||
idxs: Range<c_int>,
|
||||
}
|
||||
|
||||
impl<T: Stackable> Drop for IntoIter<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// https://github.com/rust-lang/rust-clippy/issues/7510
|
||||
#[allow(clippy::while_let_on_iterator)]
|
||||
while let Some(_) = self.next() {}
|
||||
OPENSSL_sk_free(self.stack as *mut _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> Iterator for IntoIter<T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
unsafe {
|
||||
self.idxs
|
||||
.next()
|
||||
.map(|i| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, i) as *mut _))
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.idxs.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> DoubleEndedIterator for IntoIter<T> {
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
unsafe {
|
||||
self.idxs
|
||||
.next_back()
|
||||
.map(|i| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, i) as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> ExactSizeIterator for IntoIter<T> {}
|
||||
|
||||
pub struct StackRef<T: Stackable>(Opaque, PhantomData<T>);
|
||||
|
||||
unsafe impl<T: Stackable + Send> Send for StackRef<T> {}
|
||||
unsafe impl<T: Stackable + Sync> Sync for StackRef<T> {}
|
||||
|
||||
impl<T: Stackable> ForeignTypeRef for StackRef<T> {
|
||||
type CType = T::StackType;
|
||||
}
|
||||
|
||||
impl<T: Stackable> StackRef<T> {
|
||||
fn as_stack(&self) -> *mut OPENSSL_STACK {
|
||||
self.as_ptr() as *mut _
|
||||
}
|
||||
|
||||
/// Returns the number of items in the stack.
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { OPENSSL_sk_num(self.as_stack()) as usize }
|
||||
}
|
||||
|
||||
/// Determines if the stack is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> Iter<'_, T> {
|
||||
Iter {
|
||||
stack: self,
|
||||
idxs: 0..self.len() as c_int,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
|
||||
IterMut {
|
||||
idxs: 0..self.len() as c_int,
|
||||
stack: self,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the element at the given index in the
|
||||
/// stack or `None` if the index is out of bounds
|
||||
pub fn get(&self, idx: usize) -> Option<&T::Ref> {
|
||||
unsafe {
|
||||
if idx >= self.len() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(T::Ref::from_ptr(self._get(idx)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the element at the given index in the
|
||||
/// stack or `None` if the index is out of bounds
|
||||
pub fn get_mut(&mut self, idx: usize) -> Option<&mut T::Ref> {
|
||||
unsafe {
|
||||
if idx >= self.len() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(T::Ref::from_ptr_mut(self._get(idx)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Pushes a value onto the top of the stack.
|
||||
pub fn push(&mut self, data: T) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(OPENSSL_sk_push(self.as_stack(), data.as_ptr() as *mut _))?;
|
||||
mem::forget(data);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes the last element from the stack and returns it.
|
||||
pub fn pop(&mut self) -> Option<T> {
|
||||
unsafe {
|
||||
let ptr = OPENSSL_sk_pop(self.as_stack());
|
||||
T::from_ptr_opt(ptr as *mut _)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn _get(&self, idx: usize) -> *mut T::CType {
|
||||
OPENSSL_sk_value(self.as_stack(), idx as c_int) as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> Index<usize> for StackRef<T> {
|
||||
type Output = T::Ref;
|
||||
|
||||
fn index(&self, index: usize) -> &T::Ref {
|
||||
self.get(index).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> IndexMut<usize> for StackRef<T> {
|
||||
fn index_mut(&mut self, index: usize) -> &mut T::Ref {
|
||||
self.get_mut(index).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Stackable> iter::IntoIterator for &'a StackRef<T> {
|
||||
type Item = &'a T::Ref;
|
||||
type IntoIter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Stackable> iter::IntoIterator for &'a mut StackRef<T> {
|
||||
type Item = &'a mut T::Ref;
|
||||
type IntoIter = IterMut<'a, T>;
|
||||
|
||||
fn into_iter(self) -> IterMut<'a, T> {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Stackable> iter::IntoIterator for &'a Stack<T> {
|
||||
type Item = &'a T::Ref;
|
||||
type IntoIter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Stackable> iter::IntoIterator for &'a mut Stack<T> {
|
||||
type Item = &'a mut T::Ref;
|
||||
type IntoIter = IterMut<'a, T>;
|
||||
|
||||
fn into_iter(self) -> IterMut<'a, T> {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the stack's contents.
|
||||
pub struct Iter<'a, T: Stackable> {
|
||||
stack: &'a StackRef<T>,
|
||||
idxs: Range<c_int>,
|
||||
}
|
||||
|
||||
impl<'a, T: Stackable> Iterator for Iter<'a, T> {
|
||||
type Item = &'a T::Ref;
|
||||
|
||||
fn next(&mut self) -> Option<&'a T::Ref> {
|
||||
unsafe {
|
||||
self.idxs
|
||||
.next()
|
||||
.map(|i| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.idxs.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Stackable> DoubleEndedIterator for Iter<'a, T> {
|
||||
fn next_back(&mut self) -> Option<&'a T::Ref> {
|
||||
unsafe {
|
||||
self.idxs
|
||||
.next_back()
|
||||
.map(|i| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Stackable> ExactSizeIterator for Iter<'a, T> {}
|
||||
|
||||
/// A mutable iterator over the stack's contents.
|
||||
pub struct IterMut<'a, T: Stackable> {
|
||||
stack: &'a mut StackRef<T>,
|
||||
idxs: Range<c_int>,
|
||||
}
|
||||
|
||||
impl<'a, T: Stackable> Iterator for IterMut<'a, T> {
|
||||
type Item = &'a mut T::Ref;
|
||||
|
||||
fn next(&mut self) -> Option<&'a mut T::Ref> {
|
||||
unsafe {
|
||||
self.idxs
|
||||
.next()
|
||||
.map(|i| T::Ref::from_ptr_mut(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.idxs.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Stackable> DoubleEndedIterator for IterMut<'a, T> {
|
||||
fn next_back(&mut self) -> Option<&'a mut T::Ref> {
|
||||
unsafe {
|
||||
self.idxs
|
||||
.next_back()
|
||||
.map(|i| T::Ref::from_ptr_mut(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Stackable> ExactSizeIterator for IterMut<'a, T> {}
|
||||
85
zeroidc/vendor/openssl/src/string.rs
vendored
Normal file
85
zeroidc/vendor/openssl/src/string.rs
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use libc::{c_char, c_void};
|
||||
use std::convert::AsRef;
|
||||
use std::ffi::CStr;
|
||||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
use std::str;
|
||||
|
||||
use crate::stack::Stackable;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = c_char;
|
||||
fn drop = free;
|
||||
|
||||
pub struct OpensslString;
|
||||
pub struct OpensslStringRef;
|
||||
}
|
||||
|
||||
impl fmt::Display for OpensslString {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for OpensslString {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Stackable for OpensslString {
|
||||
type StackType = ffi::stack_st_OPENSSL_STRING;
|
||||
}
|
||||
|
||||
impl AsRef<str> for OpensslString {
|
||||
fn as_ref(&self) -> &str {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for OpensslString {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for OpensslStringRef {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &str {
|
||||
unsafe {
|
||||
let slice = CStr::from_ptr(self.as_ptr()).to_bytes();
|
||||
str::from_utf8_unchecked(slice)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for OpensslStringRef {
|
||||
fn as_ref(&self) -> &str {
|
||||
&*self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for OpensslStringRef {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for OpensslStringRef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for OpensslStringRef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn free(buf: *mut c_char) {
|
||||
ffi::OPENSSL_free(buf as *mut c_void);
|
||||
}
|
||||
1523
zeroidc/vendor/openssl/src/symm.rs
vendored
Normal file
1523
zeroidc/vendor/openssl/src/symm.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
93
zeroidc/vendor/openssl/src/util.rs
vendored
Normal file
93
zeroidc/vendor/openssl/src/util.rs
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
use crate::error::ErrorStack;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::{c_char, c_int, c_void};
|
||||
use std::any::Any;
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use std::slice;
|
||||
|
||||
/// Wraps a user-supplied callback and a slot for panics thrown inside the callback (while FFI
|
||||
/// frames are on the stack).
|
||||
///
|
||||
/// When dropped, checks if the callback has panicked, and resumes unwinding if so.
|
||||
pub struct CallbackState<F> {
|
||||
/// The user callback. Taken out of the `Option` when called.
|
||||
cb: Option<F>,
|
||||
/// If the callback panics, we place the panic object here, to be re-thrown once OpenSSL
|
||||
/// returns.
|
||||
panic: Option<Box<dyn Any + Send + 'static>>,
|
||||
}
|
||||
|
||||
impl<F> CallbackState<F> {
|
||||
pub fn new(callback: F) -> Self {
|
||||
CallbackState {
|
||||
cb: Some(callback),
|
||||
panic: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Drop for CallbackState<F> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(panic) = self.panic.take() {
|
||||
panic::resume_unwind(panic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Password callback function, passed to private key loading functions.
|
||||
///
|
||||
/// `cb_state` is expected to be a pointer to a `CallbackState`.
|
||||
pub unsafe extern "C" fn invoke_passwd_cb<F>(
|
||||
buf: *mut c_char,
|
||||
size: c_int,
|
||||
_rwflag: c_int,
|
||||
cb_state: *mut c_void,
|
||||
) -> c_int
|
||||
where
|
||||
F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,
|
||||
{
|
||||
let callback = &mut *(cb_state as *mut CallbackState<F>);
|
||||
|
||||
let result = panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
let pass_slice = slice::from_raw_parts_mut(buf as *mut u8, size as usize);
|
||||
callback.cb.take().unwrap()(pass_slice)
|
||||
}));
|
||||
|
||||
match result {
|
||||
Ok(Ok(len)) => len as c_int,
|
||||
Ok(Err(_)) => {
|
||||
// FIXME restore error stack
|
||||
0
|
||||
}
|
||||
Err(err) => {
|
||||
callback.panic = Some(err);
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ForeignTypeExt: ForeignType {
|
||||
unsafe fn from_ptr_opt(ptr: *mut Self::CType) -> Option<Self> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(Self::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<FT: ForeignType> ForeignTypeExt for FT {}
|
||||
|
||||
pub trait ForeignTypeRefExt: ForeignTypeRef {
|
||||
unsafe fn from_const_ptr<'a>(ptr: *const Self::CType) -> &'a Self {
|
||||
Self::from_ptr(ptr as *mut Self::CType)
|
||||
}
|
||||
|
||||
unsafe fn from_const_ptr_opt<'a>(ptr: *const Self::CType) -> Option<&'a Self> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(Self::from_const_ptr(ptr as *mut Self::CType))
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<FT: ForeignTypeRef> ForeignTypeRefExt for FT {}
|
||||
129
zeroidc/vendor/openssl/src/version.rs
vendored
Normal file
129
zeroidc/vendor/openssl/src/version.rs
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use openssl_macros::corresponds;
|
||||
use std::ffi::CStr;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl271))] {
|
||||
use ffi::{
|
||||
OPENSSL_VERSION, OPENSSL_CFLAGS, OPENSSL_BUILT_ON, OPENSSL_PLATFORM, OPENSSL_DIR,
|
||||
OpenSSL_version_num, OpenSSL_version,
|
||||
};
|
||||
} else {
|
||||
use ffi::{
|
||||
SSLEAY_VERSION as OPENSSL_VERSION, SSLEAY_CFLAGS as OPENSSL_CFLAGS,
|
||||
SSLEAY_BUILT_ON as OPENSSL_BUILT_ON, SSLEAY_PLATFORM as OPENSSL_PLATFORM,
|
||||
SSLEAY_DIR as OPENSSL_DIR, SSLeay as OpenSSL_version_num,
|
||||
SSLeay_version as OpenSSL_version,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// OPENSSL_VERSION_NUMBER is a numeric release version identifier:
|
||||
///
|
||||
/// `MNNFFPPS: major minor fix patch status`
|
||||
///
|
||||
/// The status nibble has one of the values 0 for development, 1 to e for betas 1 to 14, and f for release.
|
||||
///
|
||||
/// for example
|
||||
///
|
||||
/// `0x000906000 == 0.9.6 dev`
|
||||
/// `0x000906023 == 0.9.6b beta 3`
|
||||
/// `0x00090605f == 0.9.6e release`
|
||||
#[corresponds(OpenSSL_version_num)]
|
||||
pub fn number() -> i64 {
|
||||
unsafe { OpenSSL_version_num() as i64 }
|
||||
}
|
||||
|
||||
/// The text variant of the version number and the release date. For example, "OpenSSL 0.9.5a 1 Apr 2000".
|
||||
#[corresponds(OpenSSL_version)]
|
||||
pub fn version() -> &'static str {
|
||||
unsafe {
|
||||
CStr::from_ptr(OpenSSL_version(OPENSSL_VERSION))
|
||||
.to_str()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// The compiler flags set for the compilation process in the form "compiler: ..." if available or
|
||||
/// "compiler: information not available" otherwise.
|
||||
#[corresponds(OpenSSL_version)]
|
||||
pub fn c_flags() -> &'static str {
|
||||
unsafe {
|
||||
CStr::from_ptr(OpenSSL_version(OPENSSL_CFLAGS))
|
||||
.to_str()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// The date of the build process in the form "built on: ..." if available or "built on: date not available" otherwise.
|
||||
#[corresponds(OpenSSL_version)]
|
||||
pub fn built_on() -> &'static str {
|
||||
unsafe {
|
||||
CStr::from_ptr(OpenSSL_version(OPENSSL_BUILT_ON))
|
||||
.to_str()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// The "Configure" target of the library build in the form "platform: ..." if available or "platform: information not available" otherwise.
|
||||
#[corresponds(OpenSSL_version)]
|
||||
pub fn platform() -> &'static str {
|
||||
unsafe {
|
||||
CStr::from_ptr(OpenSSL_version(OPENSSL_PLATFORM))
|
||||
.to_str()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// The "OPENSSLDIR" setting of the library build in the form "OPENSSLDIR: "..."" if available or "OPENSSLDIR: N/A" otherwise.
|
||||
#[corresponds(OpenSSL_version)]
|
||||
pub fn dir() -> &'static str {
|
||||
unsafe {
|
||||
CStr::from_ptr(OpenSSL_version(OPENSSL_DIR))
|
||||
.to_str()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// This test ensures that we do not segfault when calling the functions of this module
|
||||
/// and that the strings respect a reasonable format.
|
||||
#[test]
|
||||
fn test_versions() {
|
||||
println!("Number: '{}'", number());
|
||||
println!("Version: '{}'", version());
|
||||
println!("C flags: '{}'", c_flags());
|
||||
println!("Built on: '{}'", built_on());
|
||||
println!("Platform: '{}'", platform());
|
||||
println!("Dir: '{}'", dir());
|
||||
|
||||
#[cfg(not(libressl))]
|
||||
fn expected_name() -> &'static str {
|
||||
"OpenSSL"
|
||||
}
|
||||
#[cfg(libressl)]
|
||||
fn expected_name() -> &'static str {
|
||||
"LibreSSL"
|
||||
}
|
||||
|
||||
assert!(number() > 0);
|
||||
assert!(version().starts_with(expected_name()));
|
||||
assert!(c_flags().starts_with("compiler:"));
|
||||
// some distributions patch out dates out of openssl so that the builds are reproducible
|
||||
if !built_on().is_empty() {
|
||||
assert!(built_on().starts_with("built on:"));
|
||||
}
|
||||
assert!(dir().starts_with("OPENSSLDIR:"));
|
||||
}
|
||||
558
zeroidc/vendor/openssl/src/x509/extension.rs
vendored
Normal file
558
zeroidc/vendor/openssl/src/x509/extension.rs
vendored
Normal file
@@ -0,0 +1,558 @@
|
||||
//! Add extensions to an `X509` certificate or certificate request.
|
||||
//!
|
||||
//! The extensions defined for X.509 v3 certificates provide methods for
|
||||
//! associating additional attributes with users or public keys and for
|
||||
//! managing relationships between CAs. The extensions created using this
|
||||
//! module can be used with `X509v3Context` objects.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::x509::extension::BasicConstraints;
|
||||
//! use openssl::x509::X509Extension;
|
||||
//!
|
||||
//! let mut bc = BasicConstraints::new();
|
||||
//! let bc = bc.critical().ca().pathlen(1);
|
||||
//!
|
||||
//! let extension: X509Extension = bc.build().unwrap();
|
||||
//! ```
|
||||
use std::fmt::Write;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::nid::Nid;
|
||||
use crate::x509::{X509Extension, X509v3Context};
|
||||
|
||||
/// An extension which indicates whether a certificate is a CA certificate.
|
||||
pub struct BasicConstraints {
|
||||
critical: bool,
|
||||
ca: bool,
|
||||
pathlen: Option<u32>,
|
||||
}
|
||||
|
||||
impl Default for BasicConstraints {
|
||||
fn default() -> BasicConstraints {
|
||||
BasicConstraints::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl BasicConstraints {
|
||||
/// Construct a new `BasicConstraints` extension.
|
||||
pub fn new() -> BasicConstraints {
|
||||
BasicConstraints {
|
||||
critical: false,
|
||||
ca: false,
|
||||
pathlen: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the `critical` flag to `true`. The extension will be critical.
|
||||
pub fn critical(&mut self) -> &mut BasicConstraints {
|
||||
self.critical = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `ca` flag to `true`.
|
||||
pub fn ca(&mut self) -> &mut BasicConstraints {
|
||||
self.ca = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `pathlen` to an optional non-negative value. The `pathlen` is the
|
||||
/// maximum number of CAs that can appear below this one in a chain.
|
||||
pub fn pathlen(&mut self, pathlen: u32) -> &mut BasicConstraints {
|
||||
self.pathlen = Some(pathlen);
|
||||
self
|
||||
}
|
||||
|
||||
/// Return the `BasicConstraints` extension as an `X509Extension`.
|
||||
pub fn build(&self) -> Result<X509Extension, ErrorStack> {
|
||||
let mut value = String::new();
|
||||
if self.critical {
|
||||
value.push_str("critical,");
|
||||
}
|
||||
value.push_str("CA:");
|
||||
if self.ca {
|
||||
value.push_str("TRUE");
|
||||
} else {
|
||||
value.push_str("FALSE");
|
||||
}
|
||||
if let Some(pathlen) = self.pathlen {
|
||||
write!(value, ",pathlen:{}", pathlen).unwrap();
|
||||
}
|
||||
X509Extension::new_nid(None, None, Nid::BASIC_CONSTRAINTS, &value)
|
||||
}
|
||||
}
|
||||
|
||||
/// An extension consisting of a list of names of the permitted key usages.
|
||||
pub struct KeyUsage {
|
||||
critical: bool,
|
||||
digital_signature: bool,
|
||||
non_repudiation: bool,
|
||||
key_encipherment: bool,
|
||||
data_encipherment: bool,
|
||||
key_agreement: bool,
|
||||
key_cert_sign: bool,
|
||||
crl_sign: bool,
|
||||
encipher_only: bool,
|
||||
decipher_only: bool,
|
||||
}
|
||||
|
||||
impl Default for KeyUsage {
|
||||
fn default() -> KeyUsage {
|
||||
KeyUsage::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl KeyUsage {
|
||||
/// Construct a new `KeyUsage` extension.
|
||||
pub fn new() -> KeyUsage {
|
||||
KeyUsage {
|
||||
critical: false,
|
||||
digital_signature: false,
|
||||
non_repudiation: false,
|
||||
key_encipherment: false,
|
||||
data_encipherment: false,
|
||||
key_agreement: false,
|
||||
key_cert_sign: false,
|
||||
crl_sign: false,
|
||||
encipher_only: false,
|
||||
decipher_only: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the `critical` flag to `true`. The extension will be critical.
|
||||
pub fn critical(&mut self) -> &mut KeyUsage {
|
||||
self.critical = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `digitalSignature` flag to `true`.
|
||||
pub fn digital_signature(&mut self) -> &mut KeyUsage {
|
||||
self.digital_signature = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `nonRepudiation` flag to `true`.
|
||||
pub fn non_repudiation(&mut self) -> &mut KeyUsage {
|
||||
self.non_repudiation = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `keyEncipherment` flag to `true`.
|
||||
pub fn key_encipherment(&mut self) -> &mut KeyUsage {
|
||||
self.key_encipherment = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `dataEncipherment` flag to `true`.
|
||||
pub fn data_encipherment(&mut self) -> &mut KeyUsage {
|
||||
self.data_encipherment = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `keyAgreement` flag to `true`.
|
||||
pub fn key_agreement(&mut self) -> &mut KeyUsage {
|
||||
self.key_agreement = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `keyCertSign` flag to `true`.
|
||||
pub fn key_cert_sign(&mut self) -> &mut KeyUsage {
|
||||
self.key_cert_sign = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `cRLSign` flag to `true`.
|
||||
pub fn crl_sign(&mut self) -> &mut KeyUsage {
|
||||
self.crl_sign = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `encipherOnly` flag to `true`.
|
||||
pub fn encipher_only(&mut self) -> &mut KeyUsage {
|
||||
self.encipher_only = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `decipherOnly` flag to `true`.
|
||||
pub fn decipher_only(&mut self) -> &mut KeyUsage {
|
||||
self.decipher_only = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Return the `KeyUsage` extension as an `X509Extension`.
|
||||
pub fn build(&self) -> Result<X509Extension, ErrorStack> {
|
||||
let mut value = String::new();
|
||||
let mut first = true;
|
||||
append(&mut value, &mut first, self.critical, "critical");
|
||||
append(
|
||||
&mut value,
|
||||
&mut first,
|
||||
self.digital_signature,
|
||||
"digitalSignature",
|
||||
);
|
||||
append(
|
||||
&mut value,
|
||||
&mut first,
|
||||
self.non_repudiation,
|
||||
"nonRepudiation",
|
||||
);
|
||||
append(
|
||||
&mut value,
|
||||
&mut first,
|
||||
self.key_encipherment,
|
||||
"keyEncipherment",
|
||||
);
|
||||
append(
|
||||
&mut value,
|
||||
&mut first,
|
||||
self.data_encipherment,
|
||||
"dataEncipherment",
|
||||
);
|
||||
append(&mut value, &mut first, self.key_agreement, "keyAgreement");
|
||||
append(&mut value, &mut first, self.key_cert_sign, "keyCertSign");
|
||||
append(&mut value, &mut first, self.crl_sign, "cRLSign");
|
||||
append(&mut value, &mut first, self.encipher_only, "encipherOnly");
|
||||
append(&mut value, &mut first, self.decipher_only, "decipherOnly");
|
||||
X509Extension::new_nid(None, None, Nid::KEY_USAGE, &value)
|
||||
}
|
||||
}
|
||||
|
||||
/// An extension consisting of a list of usages indicating purposes
|
||||
/// for which the certificate public key can be used for.
|
||||
pub struct ExtendedKeyUsage {
|
||||
critical: bool,
|
||||
server_auth: bool,
|
||||
client_auth: bool,
|
||||
code_signing: bool,
|
||||
email_protection: bool,
|
||||
time_stamping: bool,
|
||||
ms_code_ind: bool,
|
||||
ms_code_com: bool,
|
||||
ms_ctl_sign: bool,
|
||||
ms_sgc: bool,
|
||||
ms_efs: bool,
|
||||
ns_sgc: bool,
|
||||
other: Vec<String>,
|
||||
}
|
||||
|
||||
impl Default for ExtendedKeyUsage {
|
||||
fn default() -> ExtendedKeyUsage {
|
||||
ExtendedKeyUsage::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtendedKeyUsage {
|
||||
/// Construct a new `ExtendedKeyUsage` extension.
|
||||
pub fn new() -> ExtendedKeyUsage {
|
||||
ExtendedKeyUsage {
|
||||
critical: false,
|
||||
server_auth: false,
|
||||
client_auth: false,
|
||||
code_signing: false,
|
||||
email_protection: false,
|
||||
time_stamping: false,
|
||||
ms_code_ind: false,
|
||||
ms_code_com: false,
|
||||
ms_ctl_sign: false,
|
||||
ms_sgc: false,
|
||||
ms_efs: false,
|
||||
ns_sgc: false,
|
||||
other: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the `critical` flag to `true`. The extension will be critical.
|
||||
pub fn critical(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.critical = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `serverAuth` flag to `true`.
|
||||
pub fn server_auth(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.server_auth = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `clientAuth` flag to `true`.
|
||||
pub fn client_auth(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.client_auth = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `codeSigning` flag to `true`.
|
||||
pub fn code_signing(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.code_signing = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `emailProtection` flag to `true`.
|
||||
pub fn email_protection(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.email_protection = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `timeStamping` flag to `true`.
|
||||
pub fn time_stamping(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.time_stamping = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `msCodeInd` flag to `true`.
|
||||
pub fn ms_code_ind(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.ms_code_ind = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `msCodeCom` flag to `true`.
|
||||
pub fn ms_code_com(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.ms_code_com = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `msCTLSign` flag to `true`.
|
||||
pub fn ms_ctl_sign(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.ms_ctl_sign = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `msSGC` flag to `true`.
|
||||
pub fn ms_sgc(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.ms_sgc = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `msEFS` flag to `true`.
|
||||
pub fn ms_efs(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.ms_efs = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `nsSGC` flag to `true`.
|
||||
pub fn ns_sgc(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.ns_sgc = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets a flag not already defined.
|
||||
pub fn other(&mut self, other: &str) -> &mut ExtendedKeyUsage {
|
||||
self.other.push(other.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
/// Return the `ExtendedKeyUsage` extension as an `X509Extension`.
|
||||
pub fn build(&self) -> Result<X509Extension, ErrorStack> {
|
||||
let mut value = String::new();
|
||||
let mut first = true;
|
||||
append(&mut value, &mut first, self.critical, "critical");
|
||||
append(&mut value, &mut first, self.server_auth, "serverAuth");
|
||||
append(&mut value, &mut first, self.client_auth, "clientAuth");
|
||||
append(&mut value, &mut first, self.code_signing, "codeSigning");
|
||||
append(
|
||||
&mut value,
|
||||
&mut first,
|
||||
self.email_protection,
|
||||
"emailProtection",
|
||||
);
|
||||
append(&mut value, &mut first, self.time_stamping, "timeStamping");
|
||||
append(&mut value, &mut first, self.ms_code_ind, "msCodeInd");
|
||||
append(&mut value, &mut first, self.ms_code_com, "msCodeCom");
|
||||
append(&mut value, &mut first, self.ms_ctl_sign, "msCTLSign");
|
||||
append(&mut value, &mut first, self.ms_sgc, "msSGC");
|
||||
append(&mut value, &mut first, self.ms_efs, "msEFS");
|
||||
append(&mut value, &mut first, self.ns_sgc, "nsSGC");
|
||||
for other in &self.other {
|
||||
append(&mut value, &mut first, true, other);
|
||||
}
|
||||
X509Extension::new_nid(None, None, Nid::EXT_KEY_USAGE, &value)
|
||||
}
|
||||
}
|
||||
|
||||
/// An extension that provides a means of identifying certificates that contain a
|
||||
/// particular public key.
|
||||
pub struct SubjectKeyIdentifier {
|
||||
critical: bool,
|
||||
}
|
||||
|
||||
impl Default for SubjectKeyIdentifier {
|
||||
fn default() -> SubjectKeyIdentifier {
|
||||
SubjectKeyIdentifier::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl SubjectKeyIdentifier {
|
||||
/// Construct a new `SubjectKeyIdentifier` extension.
|
||||
pub fn new() -> SubjectKeyIdentifier {
|
||||
SubjectKeyIdentifier { critical: false }
|
||||
}
|
||||
|
||||
/// Sets the `critical` flag to `true`. The extension will be critical.
|
||||
pub fn critical(&mut self) -> &mut SubjectKeyIdentifier {
|
||||
self.critical = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Return a `SubjectKeyIdentifier` extension as an `X509Extension`.
|
||||
pub fn build(&self, ctx: &X509v3Context<'_>) -> Result<X509Extension, ErrorStack> {
|
||||
let mut value = String::new();
|
||||
let mut first = true;
|
||||
append(&mut value, &mut first, self.critical, "critical");
|
||||
append(&mut value, &mut first, true, "hash");
|
||||
X509Extension::new_nid(None, Some(ctx), Nid::SUBJECT_KEY_IDENTIFIER, &value)
|
||||
}
|
||||
}
|
||||
|
||||
/// An extension that provides a means of identifying the public key corresponding
|
||||
/// to the private key used to sign a CRL.
|
||||
pub struct AuthorityKeyIdentifier {
|
||||
critical: bool,
|
||||
keyid: Option<bool>,
|
||||
issuer: Option<bool>,
|
||||
}
|
||||
|
||||
impl Default for AuthorityKeyIdentifier {
|
||||
fn default() -> AuthorityKeyIdentifier {
|
||||
AuthorityKeyIdentifier::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl AuthorityKeyIdentifier {
|
||||
/// Construct a new `AuthorityKeyIdentifier` extension.
|
||||
pub fn new() -> AuthorityKeyIdentifier {
|
||||
AuthorityKeyIdentifier {
|
||||
critical: false,
|
||||
keyid: None,
|
||||
issuer: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the `critical` flag to `true`. The extension will be critical.
|
||||
pub fn critical(&mut self) -> &mut AuthorityKeyIdentifier {
|
||||
self.critical = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `keyid` flag.
|
||||
pub fn keyid(&mut self, always: bool) -> &mut AuthorityKeyIdentifier {
|
||||
self.keyid = Some(always);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `issuer` flag.
|
||||
pub fn issuer(&mut self, always: bool) -> &mut AuthorityKeyIdentifier {
|
||||
self.issuer = Some(always);
|
||||
self
|
||||
}
|
||||
|
||||
/// Return a `AuthorityKeyIdentifier` extension as an `X509Extension`.
|
||||
pub fn build(&self, ctx: &X509v3Context<'_>) -> Result<X509Extension, ErrorStack> {
|
||||
let mut value = String::new();
|
||||
let mut first = true;
|
||||
append(&mut value, &mut first, self.critical, "critical");
|
||||
match self.keyid {
|
||||
Some(true) => append(&mut value, &mut first, true, "keyid:always"),
|
||||
Some(false) => append(&mut value, &mut first, true, "keyid"),
|
||||
None => {}
|
||||
}
|
||||
match self.issuer {
|
||||
Some(true) => append(&mut value, &mut first, true, "issuer:always"),
|
||||
Some(false) => append(&mut value, &mut first, true, "issuer"),
|
||||
None => {}
|
||||
}
|
||||
X509Extension::new_nid(None, Some(ctx), Nid::AUTHORITY_KEY_IDENTIFIER, &value)
|
||||
}
|
||||
}
|
||||
|
||||
/// An extension that allows additional identities to be bound to the subject
|
||||
/// of the certificate.
|
||||
pub struct SubjectAlternativeName {
|
||||
critical: bool,
|
||||
names: Vec<String>,
|
||||
}
|
||||
|
||||
impl Default for SubjectAlternativeName {
|
||||
fn default() -> SubjectAlternativeName {
|
||||
SubjectAlternativeName::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl SubjectAlternativeName {
|
||||
/// Construct a new `SubjectAlternativeName` extension.
|
||||
pub fn new() -> SubjectAlternativeName {
|
||||
SubjectAlternativeName {
|
||||
critical: false,
|
||||
names: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the `critical` flag to `true`. The extension will be critical.
|
||||
pub fn critical(&mut self) -> &mut SubjectAlternativeName {
|
||||
self.critical = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `email` flag.
|
||||
pub fn email(&mut self, email: &str) -> &mut SubjectAlternativeName {
|
||||
self.names.push(format!("email:{}", email));
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `uri` flag.
|
||||
pub fn uri(&mut self, uri: &str) -> &mut SubjectAlternativeName {
|
||||
self.names.push(format!("URI:{}", uri));
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `dns` flag.
|
||||
pub fn dns(&mut self, dns: &str) -> &mut SubjectAlternativeName {
|
||||
self.names.push(format!("DNS:{}", dns));
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `rid` flag.
|
||||
pub fn rid(&mut self, rid: &str) -> &mut SubjectAlternativeName {
|
||||
self.names.push(format!("RID:{}", rid));
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `ip` flag.
|
||||
pub fn ip(&mut self, ip: &str) -> &mut SubjectAlternativeName {
|
||||
self.names.push(format!("IP:{}", ip));
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `dirName` flag.
|
||||
pub fn dir_name(&mut self, dir_name: &str) -> &mut SubjectAlternativeName {
|
||||
self.names.push(format!("dirName:{}", dir_name));
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `otherName` flag.
|
||||
pub fn other_name(&mut self, other_name: &str) -> &mut SubjectAlternativeName {
|
||||
self.names.push(format!("otherName:{}", other_name));
|
||||
self
|
||||
}
|
||||
|
||||
/// Return a `SubjectAlternativeName` extension as an `X509Extension`.
|
||||
pub fn build(&self, ctx: &X509v3Context<'_>) -> Result<X509Extension, ErrorStack> {
|
||||
let mut value = String::new();
|
||||
let mut first = true;
|
||||
append(&mut value, &mut first, self.critical, "critical");
|
||||
for name in &self.names {
|
||||
append(&mut value, &mut first, true, name);
|
||||
}
|
||||
X509Extension::new_nid(None, Some(ctx), Nid::SUBJECT_ALT_NAME, &value)
|
||||
}
|
||||
}
|
||||
|
||||
fn append(value: &mut String, first: &mut bool, should: bool, element: &str) {
|
||||
if !should {
|
||||
return;
|
||||
}
|
||||
|
||||
if !*first {
|
||||
value.push(',');
|
||||
}
|
||||
*first = false;
|
||||
value.push_str(element);
|
||||
}
|
||||
1601
zeroidc/vendor/openssl/src/x509/mod.rs
vendored
Normal file
1601
zeroidc/vendor/openssl/src/x509/mod.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
209
zeroidc/vendor/openssl/src/x509/store.rs
vendored
Normal file
209
zeroidc/vendor/openssl/src/x509/store.rs
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
//! Describe a context in which to verify an `X509` certificate.
|
||||
//!
|
||||
//! The `X509` certificate store holds trusted CA certificates used to verify
|
||||
//! peer certificates.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::x509::store::{X509StoreBuilder, X509Store};
|
||||
//! use openssl::x509::{X509, X509Name};
|
||||
//! use openssl::pkey::PKey;
|
||||
//! use openssl::hash::MessageDigest;
|
||||
//! use openssl::rsa::Rsa;
|
||||
//! use openssl::nid::Nid;
|
||||
//!
|
||||
//! let rsa = Rsa::generate(2048).unwrap();
|
||||
//! let pkey = PKey::from_rsa(rsa).unwrap();
|
||||
//!
|
||||
//! let mut name = X509Name::builder().unwrap();
|
||||
//! name.append_entry_by_nid(Nid::COMMONNAME, "foobar.com").unwrap();
|
||||
//! let name = name.build();
|
||||
//!
|
||||
//! let mut builder = X509::builder().unwrap();
|
||||
//! builder.set_version(2).unwrap();
|
||||
//! builder.set_subject_name(&name).unwrap();
|
||||
//! builder.set_issuer_name(&name).unwrap();
|
||||
//! builder.set_pubkey(&pkey).unwrap();
|
||||
//! builder.sign(&pkey, MessageDigest::sha256()).unwrap();
|
||||
//!
|
||||
//! let certificate: X509 = builder.build();
|
||||
//!
|
||||
//! let mut builder = X509StoreBuilder::new().unwrap();
|
||||
//! let _ = builder.add_cert(certificate);
|
||||
//!
|
||||
//! let store: X509Store = builder.build();
|
||||
//! ```
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use std::mem;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::ssl::SslFiletype;
|
||||
use crate::stack::StackRef;
|
||||
#[cfg(any(ossl102, libressl261))]
|
||||
use crate::x509::verify::X509VerifyFlags;
|
||||
use crate::x509::{X509Object, X509};
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
use std::ffi::CString;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::X509_STORE;
|
||||
fn drop = ffi::X509_STORE_free;
|
||||
|
||||
/// A builder type used to construct an `X509Store`.
|
||||
pub struct X509StoreBuilder;
|
||||
/// A reference to an [`X509StoreBuilder`].
|
||||
pub struct X509StoreBuilderRef;
|
||||
}
|
||||
|
||||
impl X509StoreBuilder {
|
||||
/// Returns a builder for a certificate store.
|
||||
///
|
||||
/// The store is initially empty.
|
||||
#[corresponds(X509_STORE_new)]
|
||||
pub fn new() -> Result<X509StoreBuilder, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
cvt_p(ffi::X509_STORE_new()).map(X509StoreBuilder)
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs the `X509Store`.
|
||||
pub fn build(self) -> X509Store {
|
||||
let store = X509Store(self.0);
|
||||
mem::forget(self);
|
||||
store
|
||||
}
|
||||
}
|
||||
|
||||
impl X509StoreBuilderRef {
|
||||
/// Adds a certificate to the certificate store.
|
||||
// FIXME should take an &X509Ref
|
||||
#[corresponds(X509_STORE_add_cert)]
|
||||
pub fn add_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
|
||||
unsafe { cvt(ffi::X509_STORE_add_cert(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
|
||||
}
|
||||
|
||||
/// Load certificates from their default locations.
|
||||
///
|
||||
/// These locations are read from the `SSL_CERT_FILE` and `SSL_CERT_DIR`
|
||||
/// environment variables if present, or defaults specified at OpenSSL
|
||||
/// build time otherwise.
|
||||
#[corresponds(X509_STORE_set_default_paths)]
|
||||
pub fn set_default_paths(&mut self) -> Result<(), ErrorStack> {
|
||||
unsafe { cvt(ffi::X509_STORE_set_default_paths(self.as_ptr())).map(|_| ()) }
|
||||
}
|
||||
|
||||
/// Adds a lookup method to the store.
|
||||
#[corresponds(X509_STORE_add_lookup)]
|
||||
pub fn add_lookup<T>(
|
||||
&mut self,
|
||||
method: &'static X509LookupMethodRef<T>,
|
||||
) -> Result<&mut X509LookupRef<T>, ErrorStack> {
|
||||
let lookup = unsafe { ffi::X509_STORE_add_lookup(self.as_ptr(), method.as_ptr()) };
|
||||
cvt_p(lookup).map(|ptr| unsafe { X509LookupRef::from_ptr_mut(ptr) })
|
||||
}
|
||||
|
||||
/// Sets certificate chain validation related flags.
|
||||
#[corresponds(X509_STORE_set_flags)]
|
||||
#[cfg(any(ossl102, libressl261))]
|
||||
pub fn set_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack> {
|
||||
unsafe { cvt(ffi::X509_STORE_set_flags(self.as_ptr(), flags.bits())).map(|_| ()) }
|
||||
}
|
||||
}
|
||||
|
||||
generic_foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::X509_LOOKUP;
|
||||
fn drop = ffi::X509_LOOKUP_free;
|
||||
|
||||
/// Information used by an `X509Store` to look up certificates and CRLs.
|
||||
pub struct X509Lookup<T>;
|
||||
/// A reference to an [`X509Lookup`].
|
||||
pub struct X509LookupRef<T>;
|
||||
}
|
||||
|
||||
/// Marker type corresponding to the [`X509_LOOKUP_hash_dir`] lookup method.
|
||||
///
|
||||
/// [`X509_LOOKUP_hash_dir`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_LOOKUP_hash_dir.html
|
||||
// FIXME should be an enum
|
||||
pub struct HashDir;
|
||||
|
||||
impl X509Lookup<HashDir> {
|
||||
/// Lookup method that loads certificates and CRLs on demand and caches
|
||||
/// them in memory once they are loaded. It also checks for newer CRLs upon
|
||||
/// each lookup, so that newer CRLs are used as soon as they appear in the
|
||||
/// directory.
|
||||
#[corresponds(X509_LOOKUP_hash_dir)]
|
||||
pub fn hash_dir() -> &'static X509LookupMethodRef<HashDir> {
|
||||
unsafe { X509LookupMethodRef::from_ptr(ffi::X509_LOOKUP_hash_dir()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl X509LookupRef<HashDir> {
|
||||
/// Specifies a directory from which certificates and CRLs will be loaded
|
||||
/// on-demand. Must be used with `X509Lookup::hash_dir`.
|
||||
#[corresponds(X509_LOOKUP_add_dir)]
|
||||
pub fn add_dir(&mut self, name: &str, file_type: SslFiletype) -> Result<(), ErrorStack> {
|
||||
let name = CString::new(name).unwrap();
|
||||
unsafe {
|
||||
cvt(ffi::X509_LOOKUP_add_dir(
|
||||
self.as_ptr(),
|
||||
name.as_ptr(),
|
||||
file_type.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generic_foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::X509_LOOKUP_METHOD;
|
||||
fn drop = X509_LOOKUP_meth_free;
|
||||
|
||||
/// Method used to look up certificates and CRLs.
|
||||
pub struct X509LookupMethod<T>;
|
||||
/// A reference to an [`X509LookupMethod`].
|
||||
pub struct X509LookupMethodRef<T>;
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::X509_STORE;
|
||||
fn drop = ffi::X509_STORE_free;
|
||||
|
||||
/// A certificate store to hold trusted `X509` certificates.
|
||||
pub struct X509Store;
|
||||
/// Reference to an `X509Store`.
|
||||
pub struct X509StoreRef;
|
||||
}
|
||||
|
||||
impl X509StoreRef {
|
||||
/// Get a reference to the cache of certificates in this store.
|
||||
#[corresponds(X509_STORE_get0_objects)]
|
||||
pub fn objects(&self) -> &StackRef<X509Object> {
|
||||
unsafe { StackRef::from_ptr(X509_STORE_get0_objects(self.as_ptr())) }
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl270))] {
|
||||
use ffi::X509_STORE_get0_objects;
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn X509_STORE_get0_objects(x: *mut ffi::X509_STORE) -> *mut ffi::stack_st_X509_OBJECT {
|
||||
(*x).objs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl110)] {
|
||||
use ffi::X509_LOOKUP_meth_free;
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn X509_LOOKUP_meth_free(_x: *mut ffi::X509_LOOKUP_METHOD) {}
|
||||
}
|
||||
}
|
||||
504
zeroidc/vendor/openssl/src/x509/tests.rs
vendored
Normal file
504
zeroidc/vendor/openssl/src/x509/tests.rs
vendored
Normal file
@@ -0,0 +1,504 @@
|
||||
use crate::asn1::Asn1Time;
|
||||
use crate::bn::{BigNum, MsbOption};
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::nid::Nid;
|
||||
use crate::pkey::{PKey, Private};
|
||||
use crate::rsa::Rsa;
|
||||
use crate::stack::Stack;
|
||||
use crate::x509::extension::{
|
||||
AuthorityKeyIdentifier, BasicConstraints, ExtendedKeyUsage, KeyUsage, SubjectAlternativeName,
|
||||
SubjectKeyIdentifier,
|
||||
};
|
||||
use crate::x509::store::X509StoreBuilder;
|
||||
#[cfg(any(ossl102, libressl261))]
|
||||
use crate::x509::verify::X509VerifyFlags;
|
||||
#[cfg(ossl110)]
|
||||
use crate::x509::X509Builder;
|
||||
use crate::x509::{X509Name, X509Req, X509StoreContext, X509VerifyResult, X509};
|
||||
use hex::{self, FromHex};
|
||||
|
||||
fn pkey() -> PKey<Private> {
|
||||
let rsa = Rsa::generate(2048).unwrap();
|
||||
PKey::from_rsa(rsa).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cert_loading() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let fingerprint = cert.digest(MessageDigest::sha1()).unwrap();
|
||||
|
||||
let hash_str = "59172d9313e84459bcff27f967e79e6e9217e584";
|
||||
let hash_vec = Vec::from_hex(hash_str).unwrap();
|
||||
|
||||
assert_eq!(hash_vec, &*fingerprint);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_debug() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let debugged = format!("{:#?}", cert);
|
||||
assert!(debugged.contains(r#"serial_number: "8771F7BDEE982FA5""#));
|
||||
assert!(debugged.contains(r#"signature_algorithm: sha256WithRSAEncryption"#));
|
||||
assert!(debugged.contains(r#"countryName = "AU""#));
|
||||
assert!(debugged.contains(r#"stateOrProvinceName = "Some-State""#));
|
||||
assert!(debugged.contains(r#"not_before: Aug 14 17:00:03 2016 GMT"#));
|
||||
assert!(debugged.contains(r#"not_after: Aug 12 17:00:03 2026 GMT"#));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cert_issue_validity() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let not_before = cert.not_before().to_string();
|
||||
let not_after = cert.not_after().to_string();
|
||||
|
||||
assert_eq!(not_before, "Aug 14 17:00:03 2016 GMT");
|
||||
assert_eq!(not_after, "Aug 12 17:00:03 2026 GMT");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_save_der() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
|
||||
let der = cert.to_der().unwrap();
|
||||
assert!(!der.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_subject_read_cn() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let subject = cert.subject_name();
|
||||
let cn = subject.entries_by_nid(Nid::COMMONNAME).next().unwrap();
|
||||
assert_eq!(cn.data().as_slice(), b"foobar.com")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nid_values() {
|
||||
let cert = include_bytes!("../../test/nid_test_cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let subject = cert.subject_name();
|
||||
|
||||
let cn = subject.entries_by_nid(Nid::COMMONNAME).next().unwrap();
|
||||
assert_eq!(cn.data().as_slice(), b"example.com");
|
||||
|
||||
let email = subject
|
||||
.entries_by_nid(Nid::PKCS9_EMAILADDRESS)
|
||||
.next()
|
||||
.unwrap();
|
||||
assert_eq!(email.data().as_slice(), b"test@example.com");
|
||||
|
||||
let friendly = subject.entries_by_nid(Nid::FRIENDLYNAME).next().unwrap();
|
||||
assert_eq!(&**friendly.data().as_utf8().unwrap(), "Example");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nameref_iterator() {
|
||||
let cert = include_bytes!("../../test/nid_test_cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let subject = cert.subject_name();
|
||||
let mut all_entries = subject.entries();
|
||||
|
||||
let email = all_entries.next().unwrap();
|
||||
assert_eq!(
|
||||
email.object().nid().as_raw(),
|
||||
Nid::PKCS9_EMAILADDRESS.as_raw()
|
||||
);
|
||||
assert_eq!(email.data().as_slice(), b"test@example.com");
|
||||
|
||||
let cn = all_entries.next().unwrap();
|
||||
assert_eq!(cn.object().nid().as_raw(), Nid::COMMONNAME.as_raw());
|
||||
assert_eq!(cn.data().as_slice(), b"example.com");
|
||||
|
||||
let friendly = all_entries.next().unwrap();
|
||||
assert_eq!(friendly.object().nid().as_raw(), Nid::FRIENDLYNAME.as_raw());
|
||||
assert_eq!(&**friendly.data().as_utf8().unwrap(), "Example");
|
||||
|
||||
if all_entries.next().is_some() {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nid_uid_value() {
|
||||
let cert = include_bytes!("../../test/nid_uid_test_cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let subject = cert.subject_name();
|
||||
|
||||
let cn = subject.entries_by_nid(Nid::USERID).next().unwrap();
|
||||
assert_eq!(cn.data().as_slice(), b"this is the userId");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_subject_alt_name() {
|
||||
let cert = include_bytes!("../../test/alt_name_cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
|
||||
let subject_alt_names = cert.subject_alt_names().unwrap();
|
||||
assert_eq!(5, subject_alt_names.len());
|
||||
assert_eq!(Some("example.com"), subject_alt_names[0].dnsname());
|
||||
assert_eq!(subject_alt_names[1].ipaddress(), Some(&[127, 0, 0, 1][..]));
|
||||
assert_eq!(
|
||||
subject_alt_names[2].ipaddress(),
|
||||
Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])
|
||||
);
|
||||
assert_eq!(Some("test@example.com"), subject_alt_names[3].email());
|
||||
assert_eq!(Some("http://www.example.com"), subject_alt_names[4].uri());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_subject_alt_name_iter() {
|
||||
let cert = include_bytes!("../../test/alt_name_cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
|
||||
let subject_alt_names = cert.subject_alt_names().unwrap();
|
||||
let mut subject_alt_names_iter = subject_alt_names.iter();
|
||||
assert_eq!(
|
||||
subject_alt_names_iter.next().unwrap().dnsname(),
|
||||
Some("example.com")
|
||||
);
|
||||
assert_eq!(
|
||||
subject_alt_names_iter.next().unwrap().ipaddress(),
|
||||
Some(&[127, 0, 0, 1][..])
|
||||
);
|
||||
assert_eq!(
|
||||
subject_alt_names_iter.next().unwrap().ipaddress(),
|
||||
Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])
|
||||
);
|
||||
assert_eq!(
|
||||
subject_alt_names_iter.next().unwrap().email(),
|
||||
Some("test@example.com")
|
||||
);
|
||||
assert_eq!(
|
||||
subject_alt_names_iter.next().unwrap().uri(),
|
||||
Some("http://www.example.com")
|
||||
);
|
||||
assert!(subject_alt_names_iter.next().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_aia_ca_issuer() {
|
||||
// With AIA
|
||||
let cert = include_bytes!("../../test/aia_test_cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let authority_info = cert.authority_info().unwrap();
|
||||
assert_eq!(authority_info.len(), 1);
|
||||
assert_eq!(authority_info[0].method().to_string(), "CA Issuers");
|
||||
assert_eq!(
|
||||
authority_info[0].location().uri(),
|
||||
Some("http://www.example.com/cert.pem")
|
||||
);
|
||||
// Without AIA
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
assert!(cert.authority_info().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn x509_builder() {
|
||||
let pkey = pkey();
|
||||
|
||||
let mut name = X509Name::builder().unwrap();
|
||||
name.append_entry_by_nid(Nid::COMMONNAME, "foobar.com")
|
||||
.unwrap();
|
||||
let name = name.build();
|
||||
|
||||
let mut builder = X509::builder().unwrap();
|
||||
builder.set_version(2).unwrap();
|
||||
builder.set_subject_name(&name).unwrap();
|
||||
builder.set_issuer_name(&name).unwrap();
|
||||
builder
|
||||
.set_not_before(&Asn1Time::days_from_now(0).unwrap())
|
||||
.unwrap();
|
||||
builder
|
||||
.set_not_after(&Asn1Time::days_from_now(365).unwrap())
|
||||
.unwrap();
|
||||
builder.set_pubkey(&pkey).unwrap();
|
||||
|
||||
let mut serial = BigNum::new().unwrap();
|
||||
serial.rand(128, MsbOption::MAYBE_ZERO, false).unwrap();
|
||||
builder
|
||||
.set_serial_number(&serial.to_asn1_integer().unwrap())
|
||||
.unwrap();
|
||||
|
||||
let basic_constraints = BasicConstraints::new().critical().ca().build().unwrap();
|
||||
builder.append_extension(basic_constraints).unwrap();
|
||||
let key_usage = KeyUsage::new()
|
||||
.digital_signature()
|
||||
.key_encipherment()
|
||||
.build()
|
||||
.unwrap();
|
||||
builder.append_extension(key_usage).unwrap();
|
||||
let ext_key_usage = ExtendedKeyUsage::new()
|
||||
.client_auth()
|
||||
.server_auth()
|
||||
.other("2.999.1")
|
||||
.build()
|
||||
.unwrap();
|
||||
builder.append_extension(ext_key_usage).unwrap();
|
||||
let subject_key_identifier = SubjectKeyIdentifier::new()
|
||||
.build(&builder.x509v3_context(None, None))
|
||||
.unwrap();
|
||||
builder.append_extension(subject_key_identifier).unwrap();
|
||||
let authority_key_identifier = AuthorityKeyIdentifier::new()
|
||||
.keyid(true)
|
||||
.build(&builder.x509v3_context(None, None))
|
||||
.unwrap();
|
||||
builder.append_extension(authority_key_identifier).unwrap();
|
||||
let subject_alternative_name = SubjectAlternativeName::new()
|
||||
.dns("example.com")
|
||||
.build(&builder.x509v3_context(None, None))
|
||||
.unwrap();
|
||||
builder.append_extension(subject_alternative_name).unwrap();
|
||||
|
||||
builder.sign(&pkey, MessageDigest::sha256()).unwrap();
|
||||
|
||||
let x509 = builder.build();
|
||||
|
||||
assert!(pkey.public_eq(&x509.public_key().unwrap()));
|
||||
assert!(x509.verify(&pkey).unwrap());
|
||||
|
||||
let cn = x509
|
||||
.subject_name()
|
||||
.entries_by_nid(Nid::COMMONNAME)
|
||||
.next()
|
||||
.unwrap();
|
||||
assert_eq!(cn.data().as_slice(), b"foobar.com");
|
||||
assert_eq!(serial, x509.serial_number().to_bn().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn x509_req_builder() {
|
||||
let pkey = pkey();
|
||||
|
||||
let mut name = X509Name::builder().unwrap();
|
||||
name.append_entry_by_nid(Nid::COMMONNAME, "foobar.com")
|
||||
.unwrap();
|
||||
let name = name.build();
|
||||
|
||||
let mut builder = X509Req::builder().unwrap();
|
||||
builder.set_version(2).unwrap();
|
||||
builder.set_subject_name(&name).unwrap();
|
||||
builder.set_pubkey(&pkey).unwrap();
|
||||
|
||||
let mut extensions = Stack::new().unwrap();
|
||||
let key_usage = KeyUsage::new()
|
||||
.digital_signature()
|
||||
.key_encipherment()
|
||||
.build()
|
||||
.unwrap();
|
||||
extensions.push(key_usage).unwrap();
|
||||
let subject_alternative_name = SubjectAlternativeName::new()
|
||||
.dns("example.com")
|
||||
.build(&builder.x509v3_context(None))
|
||||
.unwrap();
|
||||
extensions.push(subject_alternative_name).unwrap();
|
||||
builder.add_extensions(&extensions).unwrap();
|
||||
|
||||
builder.sign(&pkey, MessageDigest::sha256()).unwrap();
|
||||
|
||||
let req = builder.build();
|
||||
assert!(req.public_key().unwrap().public_eq(&pkey));
|
||||
assert_eq!(req.extensions().unwrap().len(), extensions.len());
|
||||
assert!(req.verify(&pkey).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stack_from_pem() {
|
||||
let certs = include_bytes!("../../test/certs.pem");
|
||||
let certs = X509::stack_from_pem(certs).unwrap();
|
||||
|
||||
assert_eq!(certs.len(), 2);
|
||||
assert_eq!(
|
||||
hex::encode(certs[0].digest(MessageDigest::sha1()).unwrap()),
|
||||
"59172d9313e84459bcff27f967e79e6e9217e584"
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(certs[1].digest(MessageDigest::sha1()).unwrap()),
|
||||
"c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issued() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let ca = include_bytes!("../../test/root-ca.pem");
|
||||
let ca = X509::from_pem(ca).unwrap();
|
||||
|
||||
assert_eq!(ca.issued(&cert), X509VerifyResult::OK);
|
||||
assert_ne!(cert.issued(&cert), X509VerifyResult::OK);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn signature() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let signature = cert.signature();
|
||||
assert_eq!(
|
||||
hex::encode(signature.as_slice()),
|
||||
"4af607b889790b43470442cfa551cdb8b6d0b0340d2958f76b9e3ef6ad4992230cead6842587f0ecad5\
|
||||
78e6e11a221521e940187e3d6652de14e84e82f6671f097cc47932e022add3c0cb54a26bf27fa84c107\
|
||||
4971caa6bee2e42d34a5b066c427f2d452038082b8073993399548088429de034fdd589dcfb0dd33be7\
|
||||
ebdfdf698a28d628a89568881d658151276bde333600969502c4e62e1d3470a683364dfb241f78d310a\
|
||||
89c119297df093eb36b7fd7540224f488806780305d1e79ffc938fe2275441726522ab36d88348e6c51\
|
||||
f13dcc46b5e1cdac23c974fd5ef86aa41e91c9311655090a52333bc79687c748d833595d4c5f987508f\
|
||||
e121997410d37c"
|
||||
);
|
||||
let algorithm = cert.signature_algorithm();
|
||||
assert_eq!(algorithm.object().nid(), Nid::SHA256WITHRSAENCRYPTION);
|
||||
assert_eq!(algorithm.object().to_string(), "sha256WithRSAEncryption");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::redundant_clone)]
|
||||
fn clone_x509() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
drop(cert.clone());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_cert() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let ca = include_bytes!("../../test/root-ca.pem");
|
||||
let ca = X509::from_pem(ca).unwrap();
|
||||
let chain = Stack::new().unwrap();
|
||||
|
||||
let mut store_bldr = X509StoreBuilder::new().unwrap();
|
||||
store_bldr.add_cert(ca).unwrap();
|
||||
let store = store_bldr.build();
|
||||
|
||||
let mut context = X509StoreContext::new().unwrap();
|
||||
assert!(context
|
||||
.init(&store, &cert, &chain, |c| c.verify_cert())
|
||||
.unwrap());
|
||||
assert!(context
|
||||
.init(&store, &cert, &chain, |c| c.verify_cert())
|
||||
.unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_fails() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let ca = include_bytes!("../../test/alt_name_cert.pem");
|
||||
let ca = X509::from_pem(ca).unwrap();
|
||||
let chain = Stack::new().unwrap();
|
||||
|
||||
let mut store_bldr = X509StoreBuilder::new().unwrap();
|
||||
store_bldr.add_cert(ca).unwrap();
|
||||
let store = store_bldr.build();
|
||||
|
||||
let mut context = X509StoreContext::new().unwrap();
|
||||
assert!(!context
|
||||
.init(&store, &cert, &chain, |c| c.verify_cert())
|
||||
.unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl102, libressl261))]
|
||||
fn test_verify_fails_with_crl_flag_set_and_no_crl() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let ca = include_bytes!("../../test/root-ca.pem");
|
||||
let ca = X509::from_pem(ca).unwrap();
|
||||
let chain = Stack::new().unwrap();
|
||||
|
||||
let mut store_bldr = X509StoreBuilder::new().unwrap();
|
||||
store_bldr.add_cert(ca).unwrap();
|
||||
store_bldr.set_flags(X509VerifyFlags::CRL_CHECK).unwrap();
|
||||
let store = store_bldr.build();
|
||||
|
||||
let mut context = X509StoreContext::new().unwrap();
|
||||
assert_eq!(
|
||||
context
|
||||
.init(&store, &cert, &chain, |c| {
|
||||
c.verify_cert()?;
|
||||
Ok(c.error())
|
||||
})
|
||||
.unwrap()
|
||||
.error_string(),
|
||||
"unable to get certificate CRL"
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
#[test]
|
||||
fn x509_ref_version() {
|
||||
let mut builder = X509Builder::new().unwrap();
|
||||
let expected_version = 2;
|
||||
builder
|
||||
.set_version(expected_version)
|
||||
.expect("Failed to set certificate version");
|
||||
let cert = builder.build();
|
||||
let actual_version = cert.version();
|
||||
assert_eq!(
|
||||
expected_version, actual_version,
|
||||
"Obtained certificate version is incorrect",
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
#[test]
|
||||
fn x509_ref_version_no_version_set() {
|
||||
let cert = X509Builder::new().unwrap().build();
|
||||
let actual_version = cert.version();
|
||||
assert_eq!(
|
||||
0, actual_version,
|
||||
"Default certificate version is incorrect",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_save_subject_der() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
|
||||
let der = cert.subject_name().to_der().unwrap();
|
||||
println!("der: {:?}", der);
|
||||
assert!(!der.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_load_subject_der() {
|
||||
// The subject from ../../test/cert.pem
|
||||
const SUBJECT_DER: &[u8] = &[
|
||||
48, 90, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 65, 85, 49, 19, 48, 17, 6, 3, 85, 4, 8, 12,
|
||||
10, 83, 111, 109, 101, 45, 83, 116, 97, 116, 101, 49, 33, 48, 31, 6, 3, 85, 4, 10, 12, 24,
|
||||
73, 110, 116, 101, 114, 110, 101, 116, 32, 87, 105, 100, 103, 105, 116, 115, 32, 80, 116,
|
||||
121, 32, 76, 116, 100, 49, 19, 48, 17, 6, 3, 85, 4, 3, 12, 10, 102, 111, 111, 98, 97, 114,
|
||||
46, 99, 111, 109,
|
||||
];
|
||||
X509Name::from_der(SUBJECT_DER).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_convert_to_text() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
|
||||
const SUBSTRINGS: &[&str] = &[
|
||||
"Certificate:\n",
|
||||
"Serial Number:",
|
||||
"Signature Algorithm:",
|
||||
"Issuer: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd\n",
|
||||
"Subject: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=foobar.com\n",
|
||||
"Subject Public Key Info:",
|
||||
];
|
||||
|
||||
let text = String::from_utf8(cert.to_text().unwrap()).unwrap();
|
||||
|
||||
for substring in SUBSTRINGS {
|
||||
assert!(
|
||||
text.contains(substring),
|
||||
"{:?} not found inside {}",
|
||||
substring,
|
||||
text
|
||||
);
|
||||
}
|
||||
}
|
||||
142
zeroidc/vendor/openssl/src/x509/verify.rs
vendored
Normal file
142
zeroidc/vendor/openssl/src/x509/verify.rs
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
use bitflags::bitflags;
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use libc::{c_uint, c_ulong};
|
||||
use std::net::IpAddr;
|
||||
|
||||
use crate::cvt;
|
||||
use crate::error::ErrorStack;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
bitflags! {
|
||||
/// Flags used to check an `X509` certificate.
|
||||
pub struct X509CheckFlags: c_uint {
|
||||
const ALWAYS_CHECK_SUBJECT = ffi::X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT;
|
||||
const NO_WILDCARDS = ffi::X509_CHECK_FLAG_NO_WILDCARDS;
|
||||
const NO_PARTIAL_WILDCARDS = ffi::X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS;
|
||||
const MULTI_LABEL_WILDCARDS = ffi::X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS;
|
||||
const SINGLE_LABEL_SUBDOMAINS = ffi::X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS;
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(any(ossl110))]
|
||||
const NEVER_CHECK_SUBJECT = ffi::X509_CHECK_FLAG_NEVER_CHECK_SUBJECT;
|
||||
|
||||
#[deprecated(since = "0.10.6", note = "renamed to NO_WILDCARDS")]
|
||||
const FLAG_NO_WILDCARDS = ffi::X509_CHECK_FLAG_NO_WILDCARDS;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags used to verify an `X509` certificate chain.
|
||||
pub struct X509VerifyFlags: c_ulong {
|
||||
const CB_ISSUER_CHECK = ffi::X509_V_FLAG_CB_ISSUER_CHECK;
|
||||
const USE_CHECK_TIME = ffi::X509_V_FLAG_USE_CHECK_TIME;
|
||||
const CRL_CHECK = ffi::X509_V_FLAG_CRL_CHECK;
|
||||
const CRL_CHECK_ALL = ffi::X509_V_FLAG_CRL_CHECK_ALL;
|
||||
const IGNORE_CRITICAL = ffi::X509_V_FLAG_IGNORE_CRITICAL;
|
||||
const X509_STRICT = ffi::X509_V_FLAG_X509_STRICT;
|
||||
const ALLOW_PROXY_CERTS = ffi::X509_V_FLAG_ALLOW_PROXY_CERTS;
|
||||
const POLICY_CHECK = ffi::X509_V_FLAG_POLICY_CHECK;
|
||||
const EXPLICIT_POLICY = ffi::X509_V_FLAG_EXPLICIT_POLICY;
|
||||
const INHIBIT_ANY = ffi::X509_V_FLAG_INHIBIT_ANY;
|
||||
const INHIBIT_MAP = ffi::X509_V_FLAG_INHIBIT_MAP;
|
||||
const NOTIFY_POLICY = ffi::X509_V_FLAG_NOTIFY_POLICY;
|
||||
const EXTENDED_CRL_SUPPORT = ffi::X509_V_FLAG_EXTENDED_CRL_SUPPORT;
|
||||
const USE_DELTAS = ffi::X509_V_FLAG_USE_DELTAS;
|
||||
const CHECK_SS_SIGNATURE = ffi::X509_V_FLAG_CHECK_SS_SIGNATURE;
|
||||
#[cfg(ossl102)]
|
||||
const TRUSTED_FIRST = ffi::X509_V_FLAG_TRUSTED_FIRST;
|
||||
#[cfg(ossl102)]
|
||||
const SUITEB_128_LOS_ONLY = ffi::X509_V_FLAG_SUITEB_128_LOS_ONLY;
|
||||
#[cfg(ossl102)]
|
||||
const SUITEB_192_LOS = ffi::X509_V_FLAG_SUITEB_128_LOS;
|
||||
#[cfg(ossl102)]
|
||||
const SUITEB_128_LOS = ffi::X509_V_FLAG_SUITEB_192_LOS;
|
||||
#[cfg(ossl102)]
|
||||
const PARTIAL_CHAIN = ffi::X509_V_FLAG_PARTIAL_CHAIN;
|
||||
#[cfg(ossl110)]
|
||||
const NO_ALT_CHAINS = ffi::X509_V_FLAG_NO_ALT_CHAINS;
|
||||
#[cfg(ossl110)]
|
||||
const NO_CHECK_TIME = ffi::X509_V_FLAG_NO_CHECK_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::X509_VERIFY_PARAM;
|
||||
fn drop = ffi::X509_VERIFY_PARAM_free;
|
||||
|
||||
/// Adjust parameters associated with certificate verification.
|
||||
pub struct X509VerifyParam;
|
||||
/// Reference to `X509VerifyParam`.
|
||||
pub struct X509VerifyParamRef;
|
||||
}
|
||||
|
||||
impl X509VerifyParamRef {
|
||||
/// Set the host flags.
|
||||
#[corresponds(X509_VERIFY_PARAM_set_hostflags)]
|
||||
pub fn set_hostflags(&mut self, hostflags: X509CheckFlags) {
|
||||
unsafe {
|
||||
ffi::X509_VERIFY_PARAM_set_hostflags(self.as_ptr(), hostflags.bits);
|
||||
}
|
||||
}
|
||||
|
||||
/// Set verification flags.
|
||||
#[corresponds(X509_VERIFY_PARAM_set_flags)]
|
||||
pub fn set_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack> {
|
||||
unsafe { cvt(ffi::X509_VERIFY_PARAM_set_flags(self.as_ptr(), flags.bits)).map(|_| ()) }
|
||||
}
|
||||
|
||||
/// Clear verification flags.
|
||||
#[corresponds(X509_VERIFY_PARAM_clear_flags)]
|
||||
pub fn clear_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::X509_VERIFY_PARAM_clear_flags(
|
||||
self.as_ptr(),
|
||||
flags.bits,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets verification flags.
|
||||
#[corresponds(X509_VERIFY_PARAM_get_flags)]
|
||||
pub fn flags(&mut self) -> X509VerifyFlags {
|
||||
let bits = unsafe { ffi::X509_VERIFY_PARAM_get_flags(self.as_ptr()) };
|
||||
X509VerifyFlags { bits }
|
||||
}
|
||||
|
||||
/// Set the expected DNS hostname.
|
||||
#[corresponds(X509_VERIFY_PARAM_set1_host)]
|
||||
pub fn set_host(&mut self, host: &str) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::X509_VERIFY_PARAM_set1_host(
|
||||
self.as_ptr(),
|
||||
host.as_ptr() as *const _,
|
||||
host.len(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the expected IPv4 or IPv6 address.
|
||||
#[corresponds(X509_VERIFY_PARAM_set1_ip)]
|
||||
pub fn set_ip(&mut self, ip: IpAddr) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
let mut buf = [0; 16];
|
||||
let len = match ip {
|
||||
IpAddr::V4(addr) => {
|
||||
buf[..4].copy_from_slice(&addr.octets());
|
||||
4
|
||||
}
|
||||
IpAddr::V6(addr) => {
|
||||
buf.copy_from_slice(&addr.octets());
|
||||
16
|
||||
}
|
||||
};
|
||||
cvt(ffi::X509_VERIFY_PARAM_set1_ip(
|
||||
self.as_ptr(),
|
||||
buf.as_ptr() as *const _,
|
||||
len,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
}
|
||||
22
zeroidc/vendor/openssl/test/aia_test_cert.pem
vendored
Normal file
22
zeroidc/vendor/openssl/test/aia_test_cert.pem
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDozCCAougAwIBAgIJAJayG40CARAjMA0GCSqGSIb3DQEBCwUAMA8xDTALBgNV
|
||||
BAMMBHRlc3QwHhcNMjEwMzAyMDA1NzQ3WhcNNDgwNzE4MDA1NzQ3WjBzMQswCQYD
|
||||
VQQGEwJYWDELMAkGA1UECAwCWFgxEDAOBgNVBAcMB25vd2hlcmUxEDAOBgNVBAoM
|
||||
B3Rlc3RvcmcxEjAQBgNVBAsMCXRlc3Rncm91cDEfMB0GA1UEAwwWbWFjaGluZS0w
|
||||
Lm15aG9zdC5teW5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANKA
|
||||
3zhwC70hbxFVdC0dYk9BHaNntZ4LPUVwFSG2HBn34oO8zCp4wkH+VIi9vOhWiySK
|
||||
Gs3gW4qpjMbF82Gqc3dG2KfqUrOtWY+u54zAzqpgiJf08wmREHPoZmjqfCfgM3FO
|
||||
VMEA8g1BQxXEd+y7UEDoXhPIoeFnqzMu9sg4npnL9U5BLaQJiWnXHClnBrvAAKXW
|
||||
E8KDNmcavtFvo2xQVC09C6dJG5CrigWcZe4CaUl44rHiPaQd+jOp0HAccl/XLA0/
|
||||
QyHvW6ksjco/mb7ia1U9ohaC/3NHmzUA1S3kdq/qgnkPsjmy5v8k5vizowNc5rFO
|
||||
XsV86BIv44rh1Jut52ECAwEAAaOBnTCBmjAMBgNVHRMEBTADAQH/MAsGA1UdDwQE
|
||||
AwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwIQYDVR0RBBowGIIW
|
||||
bWFjaGluZS0wLm15aG9zdC5teW5ldDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUH
|
||||
MAKGH2h0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2VydC5wZW0wDQYJKoZIhvcNAQEL
|
||||
BQADggEBAH+ayx8qGvxzrG57jgXJudq+z783O6E2xGBJn1cT9Jhrg1VnlU+tHcNd
|
||||
fFcsp0gdQZCmm3pu3E0m/FsgTpfHUgdCOmZQp45QrxCz2oRdWQM71SSA/x1VfQ9w
|
||||
670iZOEY15/ss2nRl0woaYO7tBVadpZfymW5+OhsTKn5gL0pVmW3RciHuAmbIvQO
|
||||
bouUwzuZIJMfca7T1MqZYdrKoJrOBj0LaPTutjfQB7O/02vUCPjTTIH20aqsMe5K
|
||||
KXCrjiZO2jkxQ49Hz5uwfPx12dSVHNLpsnfOAH+MUToeW+SPx2OPvl/uAHcph2lj
|
||||
MLA6Wi64rSUxzkcFLFsGpKcK6QKcHUw=
|
||||
-----END CERTIFICATE-----
|
||||
22
zeroidc/vendor/openssl/test/alt_name_cert.pem
vendored
Normal file
22
zeroidc/vendor/openssl/test/alt_name_cert.pem
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDsDCCApigAwIBAgIBATANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJBVTET
|
||||
MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
|
||||
dHkgTHRkMB4XDTE4MDExNTExMDcwM1oXDTI4MDExMzExMDcwM1owfDELMAkGA1UE
|
||||
BhMCVVMxCzAJBgNVBAgMAk5ZMREwDwYDVQQHDAhOZXcgWW9yazEVMBMGA1UECgwM
|
||||
RXhhbXBsZSwgTExDMTYwNAYDVQQDDC1FeGFtcGxlIENvbXBhbnkvZW1haWxBZGRy
|
||||
ZXNzPXRlc3RAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||
AoIBAQCo9CWMRLMXo1CF/iORh9B4NhtJF/8tR9PlG95sNvyWuQQ/8jfev+8zErpl
|
||||
xfLkt0pJqcoiZG8g9NU0kU6o5T+/1QgZclCAoZaS0Jqxmoo2Yk/1Qsj16pnMBc10
|
||||
uSDk6V9aJSX1vKwONVNSwiHA1MhX+i7Wf7/K0niq+k7hOkhleFkWgZtUq41gXh1V
|
||||
fOugka7UktYnk9mrBbAMjmaloZNn2pMMAQxVg4ThiLm3zvuWqvXASWzUZc7IAd1G
|
||||
bN4AtDuhs252eqE9E4iTHk7F14wAS1JWqv666hReGHrmZJGx0xQTM9vPD1HN5t2U
|
||||
3KTfhO/mTlAUWVyg9tCtOzboKgs1AgMBAAGjdDByMAkGA1UdEwQCMAAwCwYDVR0P
|
||||
BAQDAgWgMFgGA1UdEQRRME+CC2V4YW1wbGUuY29thwR/AAABhxAAAAAAAAAAAAAA
|
||||
AAAAAAABgRB0ZXN0QGV4YW1wbGUuY29thhZodHRwOi8vd3d3LmV4YW1wbGUuY29t
|
||||
MA0GCSqGSIb3DQEBCwUAA4IBAQAx14G99z/MnSbs8h5jSos+dgLvhc2IQB/3CChE
|
||||
hPyELc7iyw1iteRs7bS1m2NZx6gv6TZ6VydDrK1dnWSatQ7sskXTO+zfC6qjMwXl
|
||||
IV+u7T8EREwciniIA82d8GWs60BGyBL3zp2iUOr5ULG4+c/S6OLdlyJv+fDKv+Xo
|
||||
fKv1UGDi5rcvUBikeNkpEPTN9UsE9/A8XJfDyq+4RKuDW19EtzOOeVx4xpHOMnAy
|
||||
VVAQVMKJzhoXtLF4k2j409na+f6FIcZSBet+plmzfB+WZNIgUUi/7MQIXOFQRkj4
|
||||
zH3SnsPm/IYpJzlH2vHhlqIBdaSoTWpGVWPq7D+H8OS3mmXF
|
||||
-----END CERTIFICATE-----
|
||||
19
zeroidc/vendor/openssl/test/cert.pem
vendored
Normal file
19
zeroidc/vendor/openssl/test/cert.pem
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDGzCCAgMCCQCHcfe97pgvpTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB
|
||||
VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
|
||||
cyBQdHkgTHRkMB4XDTE2MDgxNDE3MDAwM1oXDTI2MDgxMjE3MDAwM1owWjELMAkG
|
||||
A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
|
||||
IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKZm9vYmFyLmNvbTCCASIwDQYJKoZI
|
||||
hvcNAQEBBQADggEPADCCAQoCggEBAKj0JYxEsxejUIX+I5GH0Hg2G0kX/y1H0+Ub
|
||||
3mw2/Ja5BD/yN96/7zMSumXF8uS3SkmpyiJkbyD01TSRTqjlP7/VCBlyUIChlpLQ
|
||||
mrGaijZiT/VCyPXqmcwFzXS5IOTpX1olJfW8rA41U1LCIcDUyFf6LtZ/v8rSeKr6
|
||||
TuE6SGV4WRaBm1SrjWBeHVV866CRrtSS1ieT2asFsAyOZqWhk2fakwwBDFWDhOGI
|
||||
ubfO+5aq9cBJbNRlzsgB3UZs3gC0O6GzbnZ6oT0TiJMeTsXXjABLUlaq/rrqFF4Y
|
||||
euZkkbHTFBMz288PUc3m3ZTcpN+E7+ZOUBRZXKD20K07NugqCzUCAwEAATANBgkq
|
||||
hkiG9w0BAQsFAAOCAQEASvYHuIl5C0NHBELPpVHNuLbQsDQNKVj3a54+9q1JkiMM
|
||||
6taEJYfw7K1Xjm4RoiFSHpQBh+PWZS3hToToL2Zx8JfMR5MuAirdPAy1Sia/J/qE
|
||||
wQdJccqmvuLkLTSlsGbEJ/LUUgOAgrgHOZM5lUgIhCneA0/dWJ3PsN0zvn69/faY
|
||||
oo1iiolWiIHWWBUSdr3jM2AJaVAsTmLh00cKaDNk37JB940xConBGSl98JPrNrf9
|
||||
dUAiT0iIBngDBdHnn/yTj+InVEFyZSKrNtiDSObFHxPcxGteHNrCPJdP1e+GqkHp
|
||||
HJMRZVCQpSMzvHlofHSNgzWV1MX5h1CP4SGZdBDTfA==
|
||||
-----END CERTIFICATE-----
|
||||
40
zeroidc/vendor/openssl/test/certs.pem
vendored
Normal file
40
zeroidc/vendor/openssl/test/certs.pem
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDGzCCAgMCCQCHcfe97pgvpTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB
|
||||
VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
|
||||
cyBQdHkgTHRkMB4XDTE2MDgxNDE3MDAwM1oXDTI2MDgxMjE3MDAwM1owWjELMAkG
|
||||
A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
|
||||
IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKZm9vYmFyLmNvbTCCASIwDQYJKoZI
|
||||
hvcNAQEBBQADggEPADCCAQoCggEBAKj0JYxEsxejUIX+I5GH0Hg2G0kX/y1H0+Ub
|
||||
3mw2/Ja5BD/yN96/7zMSumXF8uS3SkmpyiJkbyD01TSRTqjlP7/VCBlyUIChlpLQ
|
||||
mrGaijZiT/VCyPXqmcwFzXS5IOTpX1olJfW8rA41U1LCIcDUyFf6LtZ/v8rSeKr6
|
||||
TuE6SGV4WRaBm1SrjWBeHVV866CRrtSS1ieT2asFsAyOZqWhk2fakwwBDFWDhOGI
|
||||
ubfO+5aq9cBJbNRlzsgB3UZs3gC0O6GzbnZ6oT0TiJMeTsXXjABLUlaq/rrqFF4Y
|
||||
euZkkbHTFBMz288PUc3m3ZTcpN+E7+ZOUBRZXKD20K07NugqCzUCAwEAATANBgkq
|
||||
hkiG9w0BAQsFAAOCAQEASvYHuIl5C0NHBELPpVHNuLbQsDQNKVj3a54+9q1JkiMM
|
||||
6taEJYfw7K1Xjm4RoiFSHpQBh+PWZS3hToToL2Zx8JfMR5MuAirdPAy1Sia/J/qE
|
||||
wQdJccqmvuLkLTSlsGbEJ/LUUgOAgrgHOZM5lUgIhCneA0/dWJ3PsN0zvn69/faY
|
||||
oo1iiolWiIHWWBUSdr3jM2AJaVAsTmLh00cKaDNk37JB940xConBGSl98JPrNrf9
|
||||
dUAiT0iIBngDBdHnn/yTj+InVEFyZSKrNtiDSObFHxPcxGteHNrCPJdP1e+GqkHp
|
||||
HJMRZVCQpSMzvHlofHSNgzWV1MX5h1CP4SGZdBDTfA==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDXTCCAkWgAwIBAgIJAOIvDiVb18eVMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
|
||||
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
||||
aWRnaXRzIFB0eSBMdGQwHhcNMTYwODE0MTY1NjExWhcNMjYwODEyMTY1NjExWjBF
|
||||
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
|
||||
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEArVHWFn52Lbl1l59exduZntVSZyDYpzDND+S2LUcO6fRBWhV/1Kzox+2G
|
||||
ZptbuMGmfI3iAnb0CFT4uC3kBkQQlXonGATSVyaFTFR+jq/lc0SP+9Bd7SBXieIV
|
||||
eIXlY1TvlwIvj3Ntw9zX+scTA4SXxH6M0rKv9gTOub2vCMSHeF16X8DQr4XsZuQr
|
||||
7Cp7j1I4aqOJyap5JTl5ijmG8cnu0n+8UcRlBzy99dLWJG0AfI3VRJdWpGTNVZ92
|
||||
aFff3RpK3F/WI2gp3qV1ynRAKuvmncGC3LDvYfcc2dgsc1N6Ffq8GIrkgRob6eBc
|
||||
klDHp1d023Lwre+VaVDSo1//Y72UFwIDAQABo1AwTjAdBgNVHQ4EFgQUbNOlA6sN
|
||||
XyzJjYqciKeId7g3/ZowHwYDVR0jBBgwFoAUbNOlA6sNXyzJjYqciKeId7g3/Zow
|
||||
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAVVaR5QWLZIRR4Dw6TSBn
|
||||
BQiLpBSXN6oAxdDw6n4PtwW6CzydaA+creiK6LfwEsiifUfQe9f+T+TBSpdIYtMv
|
||||
Z2H2tjlFX8VrjUFvPrvn5c28CuLI0foBgY8XGSkR2YMYzWw2jPEq3Th/KM5Catn3
|
||||
AFm3bGKWMtGPR4v+90chEN0jzaAmJYRrVUh9vea27bOCn31Nse6XXQPmSI6Gyncy
|
||||
OAPUsvPClF3IjeL1tmBotWqSGn1cYxLo+Lwjk22A9h6vjcNQRyZF2VLVvtwYrNU3
|
||||
mwJ6GCLsLHpwW/yjyvn8iEltnJvByM/eeRnfXV6WDObyiZsE/n6DxIRJodQzFqy9
|
||||
GA==
|
||||
-----END CERTIFICATE-----
|
||||
BIN
zeroidc/vendor/openssl/test/cms.p12
vendored
Normal file
BIN
zeroidc/vendor/openssl/test/cms.p12
vendored
Normal file
Binary file not shown.
BIN
zeroidc/vendor/openssl/test/cms_pubkey.der
vendored
Normal file
BIN
zeroidc/vendor/openssl/test/cms_pubkey.der
vendored
Normal file
Binary file not shown.
8
zeroidc/vendor/openssl/test/dhparams.pem
vendored
Normal file
8
zeroidc/vendor/openssl/test/dhparams.pem
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
-----BEGIN DH PARAMETERS-----
|
||||
MIIBCAKCAQEAh3Betv+hf5jNsOmGXU8oxuABD2B8r0yU8FVgjnCZBSVo61qJ0A2d
|
||||
J6r8rYKbjtolnrZN/V4IPSzYvxurHbu8nbiFVyhOySPchI2Fu+YT/HsSe/0MH9bW
|
||||
gJTNzmutWoy9VxtWLCmXnOSZHep3MZ1ZNimno6Kh2qQ7VJr0+KF8GbxUKOPv4SqK
|
||||
NBwouIQXFc0pE9kGhcGKbr7TnHhyJFCRLNP1OVDQZbcoKjk1Vh+5sy7vM2VUTQmM
|
||||
yOToT2LEZVAUJXNumcYMki9MIwfYCwYZbNt0ZEolyHzUEesuyHfU1eJd6+sKEjUz
|
||||
5GteQIR7AehxZIS+cytu7BXO7B0owLJ2awIBAg==
|
||||
-----END DH PARAMETERS-----
|
||||
12
zeroidc/vendor/openssl/test/dsa.pem
vendored
Normal file
12
zeroidc/vendor/openssl/test/dsa.pem
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
-----BEGIN DSA PRIVATE KEY-----
|
||||
MIIBuwIBAAKBgQCkKe/jtYKJNQafaE7kg2aaJOEPUV0Doi451jkXHp5UfLh6+t42
|
||||
eabSGkE9WBAlILgaB8yHckLe9+zozN39+SUDp94kb2r38/8w/9Ffhbsep9uiyOj2
|
||||
ZRQur6SkpKQDKcnAd6IMZXZcvdSgPC90A6qraYUZKq7Csjn63gbC+IvXHwIVAIgS
|
||||
PE43lXD8/rGYxos4cxCgGGAxAoGASMV56WhLvVQtWMVI36WSIxbZnC2EsnNIKeVW
|
||||
yXnP/OmPJ2mdezG7i1alcwsO2TnSLbvjvGPlyzIqZzHvWC8EmDqsfbU+n8we/Eal
|
||||
sm5nloC8m9ECWpbTzbNdvrAAj9UPVWjcDwg7grAGGysh6lGbBv5P+4zL/niq1UiE
|
||||
LnKcifgCgYEAo6mAasO0+MVcu8shxxUXXNeTLsZ8NB/BIx9EZ/dzE23ivNW8dq1A
|
||||
eecAAYhssI2m/CspQvyKw+seCvg4FccxJgB3+mGOe+blFHwO3eAwoyRn/t3DZDHh
|
||||
FjxKKRsQdy4BkZv+vhTyIYYCw0iPZ5Wfln+pyGGTveIDED1MPG+J6c8CFCJAUlEl
|
||||
4nHvbC15xLXXpd46zycY
|
||||
-----END DSA PRIVATE KEY-----
|
||||
12
zeroidc/vendor/openssl/test/dsa.pem.pub
vendored
Normal file
12
zeroidc/vendor/openssl/test/dsa.pem.pub
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBtzCCASsGByqGSM44BAEwggEeAoGBAKQp7+O1gok1Bp9oTuSDZpok4Q9RXQOi
|
||||
LjnWORcenlR8uHr63jZ5ptIaQT1YECUguBoHzIdyQt737OjM3f35JQOn3iRvavfz
|
||||
/zD/0V+Fux6n26LI6PZlFC6vpKSkpAMpycB3ogxldly91KA8L3QDqqtphRkqrsKy
|
||||
OfreBsL4i9cfAhUAiBI8TjeVcPz+sZjGizhzEKAYYDECgYBIxXnpaEu9VC1YxUjf
|
||||
pZIjFtmcLYSyc0gp5VbJec/86Y8naZ17MbuLVqVzCw7ZOdItu+O8Y+XLMipnMe9Y
|
||||
LwSYOqx9tT6fzB78RqWybmeWgLyb0QJaltPNs12+sACP1Q9VaNwPCDuCsAYbKyHq
|
||||
UZsG/k/7jMv+eKrVSIQucpyJ+AOBhQACgYEAo6mAasO0+MVcu8shxxUXXNeTLsZ8
|
||||
NB/BIx9EZ/dzE23ivNW8dq1AeecAAYhssI2m/CspQvyKw+seCvg4FccxJgB3+mGO
|
||||
e+blFHwO3eAwoyRn/t3DZDHhFjxKKRsQdy4BkZv+vhTyIYYCw0iPZ5Wfln+pyGGT
|
||||
veIDED1MPG+J6c8=
|
||||
-----END PUBLIC KEY-----
|
||||
9
zeroidc/vendor/openssl/test/dsaparam.pem
vendored
Normal file
9
zeroidc/vendor/openssl/test/dsaparam.pem
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
-----BEGIN DSA PARAMETERS-----
|
||||
MIIBHgKBgQCkKe/jtYKJNQafaE7kg2aaJOEPUV0Doi451jkXHp5UfLh6+t42eabS
|
||||
GkE9WBAlILgaB8yHckLe9+zozN39+SUDp94kb2r38/8w/9Ffhbsep9uiyOj2ZRQu
|
||||
r6SkpKQDKcnAd6IMZXZcvdSgPC90A6qraYUZKq7Csjn63gbC+IvXHwIVAIgSPE43
|
||||
lXD8/rGYxos4cxCgGGAxAoGASMV56WhLvVQtWMVI36WSIxbZnC2EsnNIKeVWyXnP
|
||||
/OmPJ2mdezG7i1alcwsO2TnSLbvjvGPlyzIqZzHvWC8EmDqsfbU+n8we/Ealsm5n
|
||||
loC8m9ECWpbTzbNdvrAAj9UPVWjcDwg7grAGGysh6lGbBv5P+4zL/niq1UiELnKc
|
||||
ifg=
|
||||
-----END DSA PARAMETERS-----
|
||||
BIN
zeroidc/vendor/openssl/test/identity.p12
vendored
Normal file
BIN
zeroidc/vendor/openssl/test/identity.p12
vendored
Normal file
Binary file not shown.
BIN
zeroidc/vendor/openssl/test/key.der
vendored
Normal file
BIN
zeroidc/vendor/openssl/test/key.der
vendored
Normal file
Binary file not shown.
BIN
zeroidc/vendor/openssl/test/key.der.pub
vendored
Normal file
BIN
zeroidc/vendor/openssl/test/key.der.pub
vendored
Normal file
Binary file not shown.
28
zeroidc/vendor/openssl/test/key.pem
vendored
Normal file
28
zeroidc/vendor/openssl/test/key.pem
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCo9CWMRLMXo1CF
|
||||
/iORh9B4NhtJF/8tR9PlG95sNvyWuQQ/8jfev+8zErplxfLkt0pJqcoiZG8g9NU0
|
||||
kU6o5T+/1QgZclCAoZaS0Jqxmoo2Yk/1Qsj16pnMBc10uSDk6V9aJSX1vKwONVNS
|
||||
wiHA1MhX+i7Wf7/K0niq+k7hOkhleFkWgZtUq41gXh1VfOugka7UktYnk9mrBbAM
|
||||
jmaloZNn2pMMAQxVg4ThiLm3zvuWqvXASWzUZc7IAd1GbN4AtDuhs252eqE9E4iT
|
||||
Hk7F14wAS1JWqv666hReGHrmZJGx0xQTM9vPD1HN5t2U3KTfhO/mTlAUWVyg9tCt
|
||||
OzboKgs1AgMBAAECggEBAKLj6IOJBKXolczpzb8UkyAjAkGBektcseV07gelJ/fk
|
||||
3z0LuWPv5p12E/HlXB24vU2x/ikUbbP3eMsawRzDEahQqmNmPEkYAYUAy/Qpi9GN
|
||||
DYvn3LqDec4jVgeQKS+p9H2DzUpTogp8zR2//yzbuWBg2+F//xh7vU0S0RQCziPM
|
||||
x7RSBgbhxSfChfEJbS2sDnzfh0jRQmoY95iFv7puet1FJtzdZ4fgCd1RqmC2lFM5
|
||||
H0eZtN/Cz19lieVs0b996DErdEBqClVZO00eYbRozCDaBzRU3ybB/dMrGJxhkkXm
|
||||
wb3kWMtziH9qOYsostuHIFu8eKFLloKxFnq2R4DGxOECgYEA2KUIZISOeGJSBcLJ
|
||||
JAUK2gvgXPNo4HHWIwOA9xeN3ZJlsnPlffXQNnm6t1st1V2gfMm9I2n0m/F0y2B/
|
||||
n/XGSa8bghfPA9l0c2h58lkL3JQJR/paa8ycTz+YZPrznEyN7Qa0RrJXUvZv9lQL
|
||||
Hc3+FHcSHgMqDV2f2bHAEu9YGi0CgYEAx6VEIPNvrHFgjo/jk1RTuk+m0xEWQsZL
|
||||
Cs+izQMr2TaeJn8LG+93AvFuYn0J0nT3WuStLPrUg8i4IhSS6lf1tId5ivIZPm4r
|
||||
YwMyblBJXhnHbk7Uqodjfw/3s6V2HAu++B7hTdyVr9DFuST9uv4m8bkPV8rfX1jE
|
||||
I2rAPVWvgikCgYB+wNAQP547wQrMZBLbCDg5KwmyWJfb+b6X7czexOEz6humNTjo
|
||||
YZHYzY/5B1fhpk3ntQD8X1nGg5caBvOk21+QbOtjShrM3cXMYCw5JvBRtitX+Zo9
|
||||
yBEMLOE0877ki8XeEDYZxu5gk98d+D4oygUGZEQtWxyXhVepPt5qNa8OYQKBgQDH
|
||||
RVgZI6KFlqzv3wMh3PutbS9wYQ+9GrtwUQuIYe/0YSW9+vSVr5E0qNKrD28sV39F
|
||||
hBauXLady0yvB6YUrjMbPFW+sCMuQzyfGWPO4+g3OrfqjFiM1ZIkE0YEU9Tt7XNx
|
||||
qTDtTI1D7bhNMnTnniI1B6ge0und+3XafAThs5L48QKBgQCTTpfqMt8kU3tcI9sf
|
||||
0MK03y7kA76d5uw0pZbWFy7KI4qnzWutCzb+FMPWWsoFtLJLPZy//u/ZCUVFVa4d
|
||||
0Y/ASNQIESVPXFLAltlLo4MSmsg1vCBsbviEEaPeEjvMrgki93pYtd/aOSgkYC1T
|
||||
mEq154s5rmqh+h+XRIf7Au0SLw==
|
||||
-----END PRIVATE KEY-----
|
||||
9
zeroidc/vendor/openssl/test/key.pem.pub
vendored
Normal file
9
zeroidc/vendor/openssl/test/key.pem.pub
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr1bXMptaIgOL9PVL8a7W
|
||||
KG/C8+IbxP018eMBQZT0SnPQmXp0Q8Aai/F+AEDE7b5sO5U7WdxU4GRYw0wqkQNF
|
||||
si78KNfoj2ZMlx6NRfl4UKuzrpGTPgQxuKDYedngPpWcbmW4P3zEL2Y7b18n9NJr
|
||||
atRUzH1Zh/ReRO525Xadu58aviPw1Mzgse7cKyzb03Gll9noLnYNIIpO8jL+QyrD
|
||||
8qNmfacmR20U0a6XDTtmsmk7AitGETICbTT0KRf+oAP0yIHoonllPpNLUEPZQjrp
|
||||
ClS/S/wKdj7gaq9TaMbHULhFMjbCV8cuPu//rUAuWp3riaznZGOVQyn3Dp2CB3ad
|
||||
yQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
BIN
zeroidc/vendor/openssl/test/keystore-empty-chain.p12
vendored
Normal file
BIN
zeroidc/vendor/openssl/test/keystore-empty-chain.p12
vendored
Normal file
Binary file not shown.
12
zeroidc/vendor/openssl/test/nid_test_cert.pem
vendored
Normal file
12
zeroidc/vendor/openssl/test/nid_test_cert.pem
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIB1DCCAX6gAwIBAgIJAMzXWZGWHleWMA0GCSqGSIb3DQEBCwUAMFYxHzAdBgkq
|
||||
hkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20xFDASBgNVBAMMC2V4YW1wbGUuY29t
|
||||
MR0wGwYJKoZIhvcNAQkUHg4ARQB4AGEAbQBwAGwAZTAeFw0xNTA3MDEwNjQ3NDRa
|
||||
Fw0xNTA3MzEwNjQ3NDRaMFYxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5j
|
||||
b20xFDASBgNVBAMMC2V4YW1wbGUuY29tMR0wGwYJKoZIhvcNAQkUHg4ARQB4AGEA
|
||||
bQBwAGwAZTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCmejzp4+o35FD0hAnx2trL
|
||||
08h07X5jZca9DgZH35hWXPh7fMucLt/IPXIRnz2zKEa/Mo6D2V/fx03Mqo0epid7
|
||||
AgMBAAGjLzAtMB0GA1UdDgQWBBRQa57tXz3rZNRz+fTbo3w3jQJMBTAMBgNVHRME
|
||||
BTADAQH/MA0GCSqGSIb3DQEBCwUAA0EAm0iY9cr+gvC+vcQIebdofpQ4GcDW8U6W
|
||||
Bxs8ZXinLl69P0jYLum3+XITNFRiyQqcivaxdxthxDNOX7P+aKwkJA==
|
||||
-----END CERTIFICATE-----
|
||||
24
zeroidc/vendor/openssl/test/nid_uid_test_cert.pem
vendored
Normal file
24
zeroidc/vendor/openssl/test/nid_uid_test_cert.pem
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEGTCCAwGgAwIBAgIJAItKTzcGfL1lMA0GCSqGSIb3DQEBCwUAMIGiMSIwIAYK
|
||||
CZImiZPyLGQBAQwSdGhpcyBpcyB0aGUgdXNlcklkMQswCQYDVQQGEwJVUzETMBEG
|
||||
A1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJU3Vubnl2YWxlMRUwEwYDVQQKDAxS
|
||||
dXN0IE9wZW5TU0wxDDAKBgNVBAsMA09TUzEhMB8GA1UEAwwYcnVzdC1vcGVuc3Ns
|
||||
LmV4YW1wbGUuY29tMB4XDTE2MDIwMjE3MjIwMVoXDTE2MDMwMzE3MjIwMVowgaIx
|
||||
IjAgBgoJkiaJk/IsZAEBDBJ0aGlzIGlzIHRoZSB1c2VySWQxCzAJBgNVBAYTAlVT
|
||||
MRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlTdW5ueXZhbGUxFTATBgNV
|
||||
BAoMDFJ1c3QgT3BlblNTTDEMMAoGA1UECwwDT1NTMSEwHwYDVQQDDBhydXN0LW9w
|
||||
ZW5zc2wuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
||||
AQDa3Gc+IE5DOhTv1m5DZW8qKiyNLd7v4DaAYLXSsDuLs+9wJ+Bs+wlBfrg+PT0t
|
||||
EJlPaLL9IfD5eR3WpFu62TUexYhnJh+3vhCGsFHOXcTjtM+wy/dzZtOVh2wTzvqE
|
||||
/FHBGw1eG3Ww+RkSFbwYmtm8JhIN8ffYxGn2O0yQpxypf5hNPYrC81zX+52X2w1h
|
||||
jDYLpYt55w+e6q+iRRFk0tKiWHEqqh/r6UQQRpj2EeS+xTloZlO6h0nl2NPkVF3r
|
||||
CXBoT8Ittxr7sqcYqf8TAA0I4qZRYXKYehFmv/VkSt85CcURJ/zXeoJ1TpxSvQie
|
||||
2R9cRDkYROrIOAFbB/0mmHLBAgMBAAGjUDBOMB0GA1UdDgQWBBRKfPqtgrbdbTmH
|
||||
XR6RC/p8t/65GjAfBgNVHSMEGDAWgBRKfPqtgrbdbTmHXR6RC/p8t/65GjAMBgNV
|
||||
HRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCKfeGRduGsIwKNiGcDUNkNrc7Z
|
||||
f8SWAmb/R6xiDfgjbhrtfBDowIZ5natEkTgf6kQPMJKyjg2NEM2uJWBc55rLOHIv
|
||||
es1wQOlYjfEUmFD3lTIt2TM/IUgXn2j+zV1CRkJthQLVFChXsidd0Bqq2fBjd3ad
|
||||
Yjzrxf3uOTBAs27koh2INNHfcUZCRsx8hP739zz2kw/r5NB/9iyENEyJKQvxo0jb
|
||||
oN0JK2joGZrWetDukQrqf032TsdkboW5JresYybbAD3326Ljp+hlT/3WINc+3nZJ
|
||||
Dn+pPMdpuZ5BUZ+u+XyNEPum3k3P3K19AF+zWYGooX0J1cmuCBrrqce20Lwy
|
||||
-----END CERTIFICATE-----
|
||||
8
zeroidc/vendor/openssl/test/pkcs1.pem.pub
vendored
Normal file
8
zeroidc/vendor/openssl/test/pkcs1.pem.pub
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIBCgKCAQEAyrcf7lv42BCoiDd3LYmF8eaGO4rhmGzGgi+NSZowkEuLhibHGQle
|
||||
FkZC7h1VKsxKFgy7Fx+GYHkv9OLm9H5fdp3HhYlo19bZVGvSJ66OJe/Bc4S02bBb
|
||||
Y8vwpc/N5O77m5J/nHLuL7XJtpfSKkX+3NPiX1X2L99iipt7F0a7hNws3G3Lxg6t
|
||||
P3Yc55TPjXzXvDIgjt/fag6iF8L/bR3augJJdDhLzNucR8A5HcvPtIVo51R631Zq
|
||||
MCh+dZvgz9zGCXwsvSky/iOJTHN3wnpsWuCAzS1iJMfjR783Tfv6sWFs19FH7pHP
|
||||
xBA3b2enPM9KBzINGOly0eM4h0fh+VBltQIDAQAB
|
||||
-----END RSA PUBLIC KEY-----
|
||||
BIN
zeroidc/vendor/openssl/test/pkcs8-nocrypt.der
vendored
Normal file
BIN
zeroidc/vendor/openssl/test/pkcs8-nocrypt.der
vendored
Normal file
Binary file not shown.
BIN
zeroidc/vendor/openssl/test/pkcs8.der
vendored
Normal file
BIN
zeroidc/vendor/openssl/test/pkcs8.der
vendored
Normal file
Binary file not shown.
27
zeroidc/vendor/openssl/test/root-ca.key
vendored
Normal file
27
zeroidc/vendor/openssl/test/root-ca.key
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEArVHWFn52Lbl1l59exduZntVSZyDYpzDND+S2LUcO6fRBWhV/
|
||||
1Kzox+2GZptbuMGmfI3iAnb0CFT4uC3kBkQQlXonGATSVyaFTFR+jq/lc0SP+9Bd
|
||||
7SBXieIVeIXlY1TvlwIvj3Ntw9zX+scTA4SXxH6M0rKv9gTOub2vCMSHeF16X8DQ
|
||||
r4XsZuQr7Cp7j1I4aqOJyap5JTl5ijmG8cnu0n+8UcRlBzy99dLWJG0AfI3VRJdW
|
||||
pGTNVZ92aFff3RpK3F/WI2gp3qV1ynRAKuvmncGC3LDvYfcc2dgsc1N6Ffq8GIrk
|
||||
gRob6eBcklDHp1d023Lwre+VaVDSo1//Y72UFwIDAQABAoIBAGZrnd/dC2kp11uq
|
||||
Sg8SHk3GMdPPjTf/lq51sVJAU4fdV2Eso0XCiCzdKDcqR6F+jiu8jHp4YO0riW8N
|
||||
b1pkjohGjyOaddIaaVsZ80/OkgDz20Ird9XQ7uoEODvopA12+755BDH5PDwqHVeM
|
||||
nKfPiwAK6Jz6CxGO9bq9ZNoBiSyO1uofaB4Cpp8t74XVeAuPiI/Bb6WJ8TW5K5dt
|
||||
x0Jihdo46QgZR+z4PnyWIoACkhSoQmtTb9NUrpKceBcxdCrZ/kEmYpnPq/PuSw6g
|
||||
6HthjYP/H9Xulz69UR5Ez6z+1pU1rKFmQ46qK7X3zVHg233MlGekMzxdmShEjzCP
|
||||
BMGYpQECgYEA5tqTZsUJwx3HDhkaZ/XOtaQqwOnZm9wPwTjGbV1t4+NUJzsl5gjP
|
||||
ho+I8ZSGZ6MnNSh+ClpYhUHYBq0rTuAAYL2arcMOuOs1GrMmiZJbXm8zq8M7gYr5
|
||||
V99H/7akSx66WV/agPkLIvh/BWxlWgQcoVAIzZibbLUxr7Ye50pCLfECgYEAwDLn
|
||||
mFz0mFMvGtaSp8RnTDTFCz9czCeDt0GujCxG1epdvtuxlg/S1QH+mGzA/AHkiu7z
|
||||
uzCwGKWozNTdRkqVwYoJTB+AYHseSkuGP+a1zr39w+xBW/vESb2oP95GIwprXcG2
|
||||
b/qdeQVzuLQhYoqWI2u8CBwlHFfpQO4Bp2ea+ocCgYEAurIgLSfCqlpFpiAlG9hN
|
||||
8NYwgU1d4E+LKj+JMd8yRO+PGh8amjub4X3pST5NqDjpN3Nk42iHWFWUqGmZsbM0
|
||||
ewg7tLUgDeqiStKBoxaK8AdMqWc9k5lZ53e6mZISsnHKUQdVBaLjH8gJqdAs8yyK
|
||||
HudEB0mYwMSUxz6pJXIHrXECgYEAhJkaCpXm8chB8UQj/baUhZDKeI4IWZjRWHbq
|
||||
Ey7g1+hPMMOk6yCTlf1ARqyRH8u2ftuIL5bRhs+Te21IE5yVYOb4rxn0mZuXNC6S
|
||||
ujdTKwUMtESkeu9hZnaAQz/4J2ii1hY05WCDj+DhC4bKmY9/MYS8PuQb/kfwVqld
|
||||
Xr8tvrUCgYEAmslHocXBUFXyRDkEOx/aKo+t9fPBr95PBZzFUt9ejrTP4PXsLa46
|
||||
3/PNOCGdrQxh5qHHcvLwR4bPL++Dj+qMUTJXANrArKPDpE2WqH6pqWIC6yaZvzUk
|
||||
17QbpXR6bHcdJV045pWpw40UCStTocVynY1lBfOw8VqxBIBlpVBBzew=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
21
zeroidc/vendor/openssl/test/root-ca.pem
vendored
Normal file
21
zeroidc/vendor/openssl/test/root-ca.pem
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDXTCCAkWgAwIBAgIJAOIvDiVb18eVMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
|
||||
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
||||
aWRnaXRzIFB0eSBMdGQwHhcNMTYwODE0MTY1NjExWhcNMjYwODEyMTY1NjExWjBF
|
||||
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
|
||||
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEArVHWFn52Lbl1l59exduZntVSZyDYpzDND+S2LUcO6fRBWhV/1Kzox+2G
|
||||
ZptbuMGmfI3iAnb0CFT4uC3kBkQQlXonGATSVyaFTFR+jq/lc0SP+9Bd7SBXieIV
|
||||
eIXlY1TvlwIvj3Ntw9zX+scTA4SXxH6M0rKv9gTOub2vCMSHeF16X8DQr4XsZuQr
|
||||
7Cp7j1I4aqOJyap5JTl5ijmG8cnu0n+8UcRlBzy99dLWJG0AfI3VRJdWpGTNVZ92
|
||||
aFff3RpK3F/WI2gp3qV1ynRAKuvmncGC3LDvYfcc2dgsc1N6Ffq8GIrkgRob6eBc
|
||||
klDHp1d023Lwre+VaVDSo1//Y72UFwIDAQABo1AwTjAdBgNVHQ4EFgQUbNOlA6sN
|
||||
XyzJjYqciKeId7g3/ZowHwYDVR0jBBgwFoAUbNOlA6sNXyzJjYqciKeId7g3/Zow
|
||||
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAVVaR5QWLZIRR4Dw6TSBn
|
||||
BQiLpBSXN6oAxdDw6n4PtwW6CzydaA+creiK6LfwEsiifUfQe9f+T+TBSpdIYtMv
|
||||
Z2H2tjlFX8VrjUFvPrvn5c28CuLI0foBgY8XGSkR2YMYzWw2jPEq3Th/KM5Catn3
|
||||
AFm3bGKWMtGPR4v+90chEN0jzaAmJYRrVUh9vea27bOCn31Nse6XXQPmSI6Gyncy
|
||||
OAPUsvPClF3IjeL1tmBotWqSGn1cYxLo+Lwjk22A9h6vjcNQRyZF2VLVvtwYrNU3
|
||||
mwJ6GCLsLHpwW/yjyvn8iEltnJvByM/eeRnfXV6WDObyiZsE/n6DxIRJodQzFqy9
|
||||
GA==
|
||||
-----END CERTIFICATE-----
|
||||
30
zeroidc/vendor/openssl/test/rsa-encrypted.pem
vendored
Normal file
30
zeroidc/vendor/openssl/test/rsa-encrypted.pem
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-128-CBC,E2F16153E2BA3D617285A68C896BA6AF
|
||||
|
||||
vO9SnhtGjGe8pG1pN//vsONnvJr+DjU+lFCiSqGMPT7tezDnbehLfS+9kus2HV7r
|
||||
HmI14JvVG9O7NpF7zMyBRlHYdWcCCWED9Yar0NsWN9419e5pMe/bqIXAzAiJbtT4
|
||||
OB9U5XF3m+349zjN1dVXPPLGRmMC1pcHAlofeb5nIUFTvUi5xcsbe1itGjgkkvHb
|
||||
Bt8NioHTBun8kKrlsFQOuB55ylBU/eWG8DQBtvFOmQ7iWp0RnGQfh8k5e5rcZNpQ
|
||||
fD9ygc7UVISl0xTrIG4IH15g34H+nrBauKtIPOpNPuXQPOMHCZv3XH8wnhrWHHwT
|
||||
ZFnQBdXbSpQtMsRh0phG2G+VIlyCgSn4+CxjCJ+TgFtsoK/tU0unmRYc59QnTxxb
|
||||
qkHYsPs3E0NApQAgH1ENEGl1M+FGLYQH7gftjc3ophBTeRA17sRmD7Y4QBInggsq
|
||||
Gv6tImPVBdekAjz/Ls/EyMwjAvvrL5eAokqrIsAarGo+zmbJKHzknw2KUz2En0+k
|
||||
YYaxB4oy9u7bzuQlvio6xYHJEb4K197bby4Dldmqv7YCCJBJwhOBAInMD687viKv
|
||||
vcUwL8YuS6cW5E8MbvEENlY4+lvKKj3M8Bnyb79cYIPQe92EuCwXU9DZXPRMLwwM
|
||||
oFEJpF5E/PmNJzu+B52ahHtDrh83WSx71fWqjdTqwkPZhAYo3ztsfFkb/UqUcq8u
|
||||
rBSebeUjZh0XZ9B04eshZQ5vJUcXGtYIe/77beV3Pv89/fw+zTZjpiP9Q3sZALzf
|
||||
Qt0YGp0/6qBuqR1tcqdu65AS2hun7yFw7uRavqYKvww4axRiz2do+xWmZFuoCAwD
|
||||
EWktaUujltpvAc1lo7lg4C6nByefJB9Xqk22N/vpqOsWr1NbAntT42Qj/HF9BVWR
|
||||
osvN3yMnKYWYe6oSTVnNBDM5obWAIHd3I9gcxTOTb1KsEwt2RrDs5EpB5ptS3Fjo
|
||||
JfBRhNZQ3cXttrIIhsHgDn9BDNg865/xpIgktKj0gEd60Abx0PqkAIm6IZTh4Efg
|
||||
7uZwfzxB+saOcddbrW2gNdzVZMC0s2Ye3sqHhtLbAJ3BlXYTxE4CAvTg54Ny+5hF
|
||||
IjvjlOKgXceSG1cSfk21/wyp9RY3Ft0AEYvvp0kZScWZaoA2aSFDUrchXVhgrEbn
|
||||
lJ7UptjefwRFIreAlwbKSbIDDNWnyzvIWyHfQ2aYqgnb7W7XqNPSgH9cALCfzirI
|
||||
dlRHjha0bMUtrjPCC/YfMXzJBVniy0gG6Pd5uC7vz/Awn6/6HRQVNaTQASphPBQ7
|
||||
bJuz+JTfzI9OUVCMRMdnb6b35U4P9tibFmnPvzTIPe+3WUmf8aRsLS3NN3G1Webd
|
||||
PMYVZpMycPaAI0Ht87axhsOzlxCWHYWjdHa+WoNNc1J90TxLCmAHquh5BDaWvjMK
|
||||
0DySftJZjV7Tf1p2KosmU83LRl39B5NHMbZb1xOEZl9IWwhT/PVKTVZ25xdxWLfb
|
||||
hF4l8rfvKehIp5r4t8zW1bvI2Hl6vrUvmcUVWt3BfKjxlgwRVD0vvwonMt1INesF
|
||||
204vUBeXbDsUUicLwOyUgaFvJ3XU3dOyvL9MhOgM5OgoFRRhG+4AS8a5JCD8iLtq
|
||||
-----END RSA PRIVATE KEY-----
|
||||
27
zeroidc/vendor/openssl/test/rsa.pem
vendored
Normal file
27
zeroidc/vendor/openssl/test/rsa.pem
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd/wWJcyQoTbji9k0
|
||||
l8W26mPddxHmfHQp+Vaw+4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL+yRT+SFd2lZS+pC
|
||||
gNMsD1W/YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb/7OMg0LOL+bSf63kpaSHSX
|
||||
ndS5z5rexMdbBYUsLA9e+KXBdQOS+UTo7WTBEMa2R2CapHg665xsmtdVMTBQY4uD
|
||||
Zlxvb3qCo5ZwKh9kG4LT6/I5IhlJH7aGhyxXFvUK+DWNmoudF8NAco9/h9iaGNj8
|
||||
q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQIDAQABAoIBABKucaRpzQorw35S
|
||||
bEUAVx8dYXUdZOlJcHtiWQ+dC6V8ljxAHj/PLyzTveyI5QO/xkObCyjIL303l2cf
|
||||
UhPu2MFaJdjVzqACXuOrLot/eSFvxjvqVidTtAZExqFRJ9mylUVAoLvhowVWmC1O
|
||||
n95fZCXxTUtxNEG1Xcc7m0rtzJKs45J+N/V9DP1edYH6USyPSWGp6wuA+KgHRnKK
|
||||
Vf9GRx80JQY7nVNkL17eHoTWEwga+lwi0FEoW9Y7lDtWXYmKBWhUE+U8PGxlJf8f
|
||||
40493HDw1WRQ/aSLoS4QTp3rn7gYgeHEvfJdkkf0UMhlknlo53M09EFPdadQ4TlU
|
||||
bjqKc50CgYEA4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH/5IB3jw3bcxGn6QLvnE
|
||||
tfdUdiYrqBdss1l58BQ3KhooKeQTa9AB0Hw/Py5PJdTJNPY8cQn7ouZ2KKDcmnPG
|
||||
BY5t7yLc1QlQ5xHdwW1VhvKn+nXqhJTBgIPgtldC+KDV5z+y2XDwGUcCgYEAuQPE
|
||||
fgmVtjL0Uyyx88GZFF1fOunH3+7cepKmtH4pxhtCoHqpWmT8YAmZxaewHgHAjLYs
|
||||
p1ZSe7zFYHj7C6ul7TjeLQeZD/YwD66t62wDmpe/HlB+TnBA+njbglfIsRLtXlnD
|
||||
zQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdcCgYAHAp9XcCSrn8wVkMVkKdb7
|
||||
DOX4IKjzdahm+ctDAJN4O/y7OW5FKebvUjdAIt2GuoTZ71iTG+7F0F+lP88jtjP4
|
||||
U4qe7VHoewl4MKOfXZKTe+YCS1XbNvfgwJ3Ltyl1OH9hWvu2yza7q+d5PCsDzqtm
|
||||
27kxuvULVeya+TEdAB1ijQKBgQCH/3r6YrVH/uCWGy6bzV1nGNOdjKc9tmkfOJmN
|
||||
54dxdixdpozCQ6U4OxZrsj3FcOhHBsqAHvX2uuYjagqvo3cOj1TRqNocX40omfCC
|
||||
Mx3bD1yPPf/6TI2XECva/ggqEY2mYzmIiA5LVVmc5nrybr+lssFKneeyxN2Wq93S
|
||||
0iJMdQKBgCGHewxzoa1r8ZMD0LETNrToK423K377UCYqXfg5XMclbrjPbEC3YI1Z
|
||||
NqMtuhdBJqUnBi6tjKMF+34Xf0CUN8ncuXGO2CAYvO8PdyCixHX52ybaDjy1FtCE
|
||||
6yUXjoKNXKvUm7MWGsAYH6f4IegOetN5NvmUMFStCSkh7ixZLkN1
|
||||
-----END RSA PRIVATE KEY-----
|
||||
9
zeroidc/vendor/openssl/test/rsa.pem.pub
vendored
Normal file
9
zeroidc/vendor/openssl/test/rsa.pem.pub
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAofgWCuLjybRlzo0tZWJj
|
||||
NiuSfb4p4fAkd/wWJcyQoTbji9k0l8W26mPddxHmfHQp+Vaw+4qPCJrcS2mJPMEz
|
||||
P1Pt0Bm4d4QlL+yRT+SFd2lZS+pCgNMsD1W/YpRPEwOWvG6b32690r2jZ47soMZo
|
||||
9wGzjb/7OMg0LOL+bSf63kpaSHSXndS5z5rexMdbBYUsLA9e+KXBdQOS+UTo7WTB
|
||||
EMa2R2CapHg665xsmtdVMTBQY4uDZlxvb3qCo5ZwKh9kG4LT6/I5IhlJH7aGhyxX
|
||||
FvUK+DWNmoudF8NAco9/h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXp
|
||||
oQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
Reference in New Issue
Block a user