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:
Adam Ierymenko
2022-06-08 07:32:16 -04:00
parent 373ca30269
commit d5ca4e5f52
12611 changed files with 2898014 additions and 284 deletions

File diff suppressed because one or more lines are too long

644
zeroidc/vendor/openssl/CHANGELOG.md vendored Normal file
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,22 @@
# rust-openssl
[![crates.io](https://img.shields.io/crates/v/openssl.svg)](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
View 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");
}
}
}

View 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(&not_before)?;
let not_after = Asn1Time::days_from_now(365)?;
cert_builder.set_not_after(&not_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(&not_before)?;
let not_after = Asn1Time::days_from_now(365)?;
cert_builder.set_not_after(&not_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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

388
zeroidc/vendor/openssl/src/cipher.rs vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

224
zeroidc/vendor/openssl/src/ecdsa.rs vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

350
zeroidc/vendor/openssl/src/ocsp.rs vendored Normal file
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

760
zeroidc/vendor/openssl/src/pkey_ctx.rs vendored Normal file
View 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
View 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
View 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
View File

@@ -0,0 +1,841 @@
//! RivestShamirAdleman 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
View 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
View 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
View 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
View 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;
}
}
}

View 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
}
}
}

View 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
View 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

File diff suppressed because it is too large Load Diff

1405
zeroidc/vendor/openssl/src/ssl/test/mod.rs vendored Normal file

File diff suppressed because it is too large Load Diff

View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

93
zeroidc/vendor/openssl/src/util.rs vendored Normal file
View 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
View 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:"));
}

View 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

File diff suppressed because it is too large Load Diff

209
zeroidc/vendor/openssl/src/x509/store.rs vendored Normal file
View 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
View 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
);
}
}

View 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(|_| ())
}
}
}

View 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-----

View 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
View 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
View 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

Binary file not shown.

Binary file not shown.

View 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
View 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
View 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-----

View 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

Binary file not shown.

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

Binary file not shown.

28
zeroidc/vendor/openssl/test/key.pem vendored Normal file
View 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-----

View 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-----

Binary file not shown.

View 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-----

View 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-----

View 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-----

Binary file not shown.

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
View 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
View 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-----

View 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
View 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-----

View 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-----