diff --git a/Cargo.lock b/Cargo.lock index c56a6f081cac2..317582a4de497 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5163,7 +5163,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.10", "tokio", "tower-service", "tracing 0.1.44", @@ -7595,7 +7595,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.75" +version = "0.10.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" dependencies = [ "bitflags 2.10.0", "cfg-if", @@ -7634,9 +7636,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.111" +version = "0.9.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" dependencies = [ "cc", "libc", diff --git a/Cargo.toml b/Cargo.toml index d626b1aaf67c5..8a6eafdade05e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -407,7 +407,7 @@ async-nats = { version = "0.42.0", default-features = false, optional = true, fe nkeys = { version = "0.4.5", default-features = false, optional = true } nom = { workspace = true, optional = true } notify = { version = "8.1.0", default-features = false, features = ["macos_fsevent"] } -openssl = { version = "0.10.73", default-features = false} +openssl = { version = "0.10.75", default-features = false} openssl-probe = { version = "0.1.6", default-features = false } ordered-float.workspace = true percent-encoding = { version = "2.3.1", default-features = false } @@ -500,7 +500,6 @@ zstd = { version = "0.13.0", default-features = false } # The `heim` crates depend on `ntapi` 0.3.7 on Windows, but that version has an # unaligned access bug fixed in the following revision. ntapi = { git = "https://github.com/MSxDOS/ntapi.git", rev = "24fc1e47677fc9f6e38e5f154e6011dc9b270da6" } -openssl = { path = "patch/openssl" } hyper = { path = "patch/hyper" } [features] diff --git a/lib/vector-core/src/tls/mod.rs b/lib/vector-core/src/tls/mod.rs index 5e2e06aa4462b..88e1753fec215 100644 --- a/lib/vector-core/src/tls/mod.rs +++ b/lib/vector-core/src/tls/mod.rs @@ -4,7 +4,7 @@ use std::{fmt::Debug, net::SocketAddr, num::TryFromIntError, path::PathBuf, time use openssl::{ error::ErrorStack, - ssl::{ConnectConfiguration, SslConnector, SslConnectorBuilder, SslMethod}, + ssl::{ConnectConfiguration, SslConnector, SslConnectorBuilder, SslMethod, SslVersion}, }; use snafu::{ResultExt, Snafu}; use tokio::net::TcpStream; @@ -131,6 +131,16 @@ pub enum TlsError { NewCaStack { source: ErrorStack }, #[snafu(display("Could not push intermediate certificate onto stack"))] CaStackPush { source: ErrorStack }, + // BEGIN RED HAT - TLS security profile support (LOG-3398) + #[snafu(display("Invalid TLS version: {}", version))] + InvalidTlsVersion { version: String }, + #[snafu(display("Invalid or empty ciphersuite string"))] + InvalidCiphersuite, + #[snafu(display("Could not set minimum TLS version: {}", source))] + SetMinTlsVersion { source: ErrorStack }, + #[snafu(display("Could not set cipher list: {}", source))] + SetCipherList { source: ErrorStack }, + // END RED HAT - TLS security profile support (LOG-3398) } impl MaybeTlsStream { @@ -175,6 +185,47 @@ impl MaybeTlsStream { } } +// BEGIN RED HAT - TLS security profile support (LOG-3398) +/// Apply TLS security profile settings (min version, ciphersuites) to an SSL context builder. +/// +/// Maps `OpenShift` TLS security profile version strings (`VersionTLS10`..`VersionTLS13`) +/// to OpenSSL protocol versions and configures ciphersuites accordingly. +pub fn apply_tls_security_profile( + ctx: &mut openssl::ssl::SslContextBuilder, + min_tls_version: &Option, + ciphersuites: &Option, +) -> Result<()> { + let mut resolved_version = SslVersion::TLS1; + if let Some(version_str) = min_tls_version { + resolved_version = match version_str.as_str() { + "VersionTLS10" => SslVersion::TLS1, + "VersionTLS11" => SslVersion::TLS1_1, + "VersionTLS12" => SslVersion::TLS1_2, + "VersionTLS13" => SslVersion::TLS1_3, + _ => { + return Err(TlsError::InvalidTlsVersion { + version: version_str.clone(), + }); + } + }; + ctx.set_min_proto_version(Some(resolved_version)) + .context(SetMinTlsVersionSnafu)?; + } + if let Some(suites) = ciphersuites { + if suites.is_empty() { + return Err(TlsError::InvalidCiphersuite); + } + let suites = suites.replace(',', ":"); + if resolved_version == SslVersion::TLS1_3 { + ctx.set_ciphersuites(&suites).context(SetCipherListSnafu)?; + } else { + ctx.set_cipher_list(&suites).context(SetCipherListSnafu)?; + } + } + Ok(()) +} +// END RED HAT - TLS security profile support (LOG-3398) + pub fn tls_connector_builder(settings: &MaybeTlsSettings) -> Result { let mut builder = SslConnector::builder(SslMethod::tls()).context(TlsBuildConnectorSnafu)?; if let Some(settings) = settings.tls() { diff --git a/lib/vector-core/src/tls/settings.rs b/lib/vector-core/src/tls/settings.rs index 3a766c6b44f69..2f926568bc26b 100644 --- a/lib/vector-core/src/tls/settings.rs +++ b/lib/vector-core/src/tls/settings.rs @@ -6,10 +6,25 @@ use std::{ }; use super::{ - AddCertToStoreSnafu, AddExtraChainCertSnafu, CaStackPushSnafu, EncodeAlpnProtocolsSnafu, - FileOpenFailedSnafu, FileReadFailedSnafu, MaybeTls, NewCaStackSnafu, NewStoreBuilderSnafu, - ParsePkcs12Snafu, PrivateKeyParseSnafu, Result, SetAlpnProtocolsSnafu, SetCertificateSnafu, - SetPrivateKeySnafu, SetVerifyCertSnafu, TlsError, X509ParseSnafu, + AddCertToStoreSnafu, + AddExtraChainCertSnafu, + CaStackPushSnafu, + EncodeAlpnProtocolsSnafu, + FileOpenFailedSnafu, + FileReadFailedSnafu, + MaybeTls, + NewCaStackSnafu, + NewStoreBuilderSnafu, + ParsePkcs12Snafu, + PrivateKeyParseSnafu, + Result, + SetAlpnProtocolsSnafu, + SetCertificateSnafu, + SetPrivateKeySnafu, + SetVerifyCertSnafu, + TlsError, + X509ParseSnafu, + apply_tls_security_profile, // RED HAT - TLS security profile support (LOG-3398) }; use cfg_if::cfg_if; use lookup::lookup_v2::OptionalValuePath; @@ -157,11 +172,13 @@ pub struct TlsConfig { #[configurable(metadata(docs::human_name = "Server Name"))] pub server_name: Option, + // BEGIN RED HAT - TLS security profile support (LOG-3398) /// Minimal enabled TLS version. pub min_tls_version: Option, /// TLS ciphersuites to enable. pub ciphersuites: Option, + // END RED HAT - TLS security profile support (LOG-3398) } impl TlsConfig { @@ -184,8 +201,10 @@ pub struct TlsSettings { pub(super) identity: Option, alpn_protocols: Option>, server_name: Option, + // BEGIN RED HAT - TLS security profile support (LOG-3398) pub min_tls_version: Option, pub ciphersuites: Option, + // END RED HAT - TLS security profile support (LOG-3398) } /// Identity store in PEM format @@ -228,6 +247,7 @@ impl TlsSettings { identity: options.load_identity()?, alpn_protocols: options.parse_alpn_protocols()?, server_name: options.server_name.clone(), + // RED HAT - TLS security profile support (LOG-3398) min_tls_version: options.min_tls_version.clone(), ciphersuites: options.ciphersuites.clone(), }) @@ -347,6 +367,9 @@ impl TlsSettings { } } + // RED HAT - TLS security profile support (LOG-3398) + apply_tls_security_profile(context, &self.min_tls_version, &self.ciphersuites)?; + Ok(()) } @@ -662,7 +685,7 @@ fn open_read(filename: &Path, note: &'static str) -> Result<(Vec, PathBuf)> #[cfg(test)] mod test { - use openssl::ssl::{ErrorEx, SslMethod, SslVersion}; + use openssl::ssl::{SslMethod, SslVersion}; use super::*; @@ -831,102 +854,79 @@ mod test { assert!(config.is_tls()); } + // BEGIN RED HAT - TLS security profile tests (LOG-3398) #[test] fn from_min_tls_version() { - use std::result::Result; - - struct TlsVersionTest { - text: Option, - num: Option, - want: Result<(), ErrorEx>, + use super::super::apply_tls_security_profile; + + // Valid version strings set the correct min protocol version + let valid_cases = [ + ("VersionTLS10", SslVersion::TLS1), + ("VersionTLS11", SslVersion::TLS1_1), + ("VersionTLS12", SslVersion::TLS1_2), + ("VersionTLS13", SslVersion::TLS1_3), + ]; + for (version_str, expected_version) in valid_cases { + let mut builder = SslContextBuilder::new(SslMethod::tls()).unwrap(); + apply_tls_security_profile(&mut builder, &Some(version_str.to_string()), &None) + .unwrap_or_else(|_| panic!("should accept {version_str}")); + assert_eq!(builder.min_proto_version(), Some(expected_version)); } + + // None leaves the default unchanged let mut builder = SslContextBuilder::new(SslMethod::tls()).unwrap(); - let orig_min_proto_version = builder.min_proto_version(); - let tests = [ - TlsVersionTest { - text: None, - num: orig_min_proto_version, - want: Ok(()), - }, - TlsVersionTest { - text: Some(String::new()), - num: orig_min_proto_version, - want: Err(ErrorEx::InvalidTlsVersion), - }, - TlsVersionTest { - text: Some("foobar".to_string()), - num: Some(SslVersion::TLS1), - want: Err(ErrorEx::InvalidTlsVersion), - }, - TlsVersionTest { - text: Some("VersionTLS10".to_string()), - num: Some(SslVersion::TLS1), - want: Ok(()), - }, - TlsVersionTest { - text: Some("VersionTLS11".to_string()), - num: Some(SslVersion::TLS1_1), - want: Ok(()), - }, - TlsVersionTest { - text: Some("VersionTLS12".to_string()), - num: Some(SslVersion::TLS1_2), - want: Ok(()), - }, - TlsVersionTest { - text: Some("VersionTLS13".to_string()), - num: Some(SslVersion::TLS1_3), - want: Ok(()), - }, - ]; - for t in tests { - match builder.set_min_tls_version_and_ciphersuites(&t.text, &None) { - Ok(()) => { - assert!(t.want.is_ok()); - assert_eq!(builder.min_proto_version(), t.num); - } - Err(e) => assert_eq!(t.want.err().unwrap(), e), - } + let orig = builder.min_proto_version(); + apply_tls_security_profile(&mut builder, &None, &None).unwrap(); + assert_eq!(builder.min_proto_version(), orig); + + // Invalid version strings return InvalidTlsVersion + for bad in ["", "foobar"] { + let mut builder = SslContextBuilder::new(SslMethod::tls()).unwrap(); + let err = apply_tls_security_profile(&mut builder, &Some(bad.to_string()), &None) + .expect_err(&format!("should reject {bad:?}")); + assert!( + matches!(err, TlsError::InvalidTlsVersion { .. }), + "expected InvalidTlsVersion for {bad:?}, got {err:?}" + ); } } #[test] fn from_min_tls_version_and_ciphersuites() { - use std::result::Result; + use super::super::apply_tls_security_profile; - struct TlsCiphersuiteTest { - min_tls_version: Option, - ciphersuite: Option, - want: Result<(), ErrorEx>, - } + // Empty ciphersuite string returns InvalidCiphersuite + let mut builder = SslContextBuilder::new(SslMethod::tls()).unwrap(); + let err = apply_tls_security_profile( + &mut builder, + &Some("VersionTLS10".to_string()), + &Some(String::new()), + ) + .expect_err("should reject empty ciphersuite"); + assert!( + matches!(err, TlsError::InvalidCiphersuite), + "expected InvalidCiphersuite, got {err:?}" + ); + // TLS 1.2 cipher list is accepted let mut builder = SslContextBuilder::new(SslMethod::tls()).unwrap(); - let tests = [ - TlsCiphersuiteTest { - min_tls_version: Some("VersionTLS10".to_string()), - ciphersuite: Some(String::new()), - want: Err(ErrorEx::InvalidCiphersuite), - }, - TlsCiphersuiteTest { - min_tls_version: Some("VersionTLS12".to_string()), - ciphersuite: Some("AES128-SHA256".to_string()), - want: Ok(()), - }, - TlsCiphersuiteTest { - min_tls_version: Some("VersionTLS13".to_string()), - ciphersuite: Some( - "TLS_CHACHA20_POLY1305_SHA256,TLS_AES_256_GCM_SHA384".to_string(), - ), - want: Ok(()), - }, - ]; - for t in tests { - match builder.set_min_tls_version_and_ciphersuites(&t.min_tls_version, &t.ciphersuite) { - Ok(()) => assert!(t.want.is_ok()), - Err(e) => assert_eq!(t.want.err().unwrap(), e), - } - } + apply_tls_security_profile( + &mut builder, + &Some("VersionTLS12".to_string()), + &Some("AES128-SHA256".to_string()), + ) + .expect("should accept TLS 1.2 cipher list"); + + // TLS 1.3 ciphersuites are accepted + let mut builder = SslContextBuilder::new(SslMethod::tls()).unwrap(); + apply_tls_security_profile( + &mut builder, + &Some("VersionTLS13".to_string()), + &Some("TLS_CHACHA20_POLY1305_SHA256,TLS_AES_256_GCM_SHA384".to_string()), + ) + .expect("should accept TLS 1.3 ciphersuites"); } + // END RED HAT - TLS security profile tests (LOG-3398) fn settings_from_config( enabled: Option, diff --git a/patch/openssl/CHANGELOG.md b/patch/openssl/CHANGELOG.md deleted file mode 100644 index 8f917a96e8918..0000000000000 --- a/patch/openssl/CHANGELOG.md +++ /dev/null @@ -1,1102 +0,0 @@ -# Change Log - -## [Unreleased] - -## [v0.10.75] - 2025-11-07 - -### Added - -* Added support for `set_rsa_oaep_label` on AWS-LC/BoringSSL. -* Added `Asn1GeneralizedTime::from_str`. -* Added `OcspStatus::next_update` method. - -### Fixed - -* Fixed unsound OCSP `find_status` handling of optional next_update field. If an OCSP response does not have a `nextUpdate`, `OcspStatus::next_update` will store a sentinel value. Use `OcspStatus::next_update()` instead. - -### Deprecated - -* Deprecated `OcspStatus::next_update` field in favor of the `next_update()` method. - -## [v0.10.74] - 2025-10-14 - -### Added - -* Added parameter generation support (`PkeyCtx::paramgen` and `PkeyCtx::paramgen_init`). -* Added key generation methods for RSA, DSA, DH, and EC via `PkeyCtx`. -* Added `Cipher::get_protocol_id`. -* Added `EcPointRef::set_affine_coordinates`. -* Added `EcGroup::order_bits` on BoringSSL, LibreSSL, and AWS-LC. -* Added `X509::append_entry` on BoringSSL and AWS-LC. -* Added XOF squeeze support on AWS-LC. -* Added argon2d and argon2i KDF variants. - -### Changed - -* Bumped MSRV to 1.70. -* The repository has moved to the rust-openssl github organization. - -### Fixed - -* Disabled AES-CFB128 ciphers for BoringSSL. - -### Removed - -* Removed support for OpenSSL <1.0.2. -* Removed support for LibreSSL <3.5. - -## [v0.10.73] - 2025-05-28 - -### Fixed - -* Fixed building on the latest BoringSSL. - -### Changed - -* Replaced ctest2 with ctest in systest. - -## [v0.10.72] - 2025-04-04 - -### Fixed - -* Fixed use-after-free in `Md::fetch` and `Cipher::fetch` when `properties` is `Some(...)`. In practice this use-after-free most likely resulted in OpenSSL treating the `properties` as `b""`. - -### Added - -* Support for building with AWS-LC. - -## [v0.10.71] - 2025-02-15 - -### Added - -* Added `Cipher::rc2_cbc` and `Cipher::rc2_40_cbc`. - -## [v0.10.70] - 2025-02-02 - -### Fixed - -* Fixed improper lifetime constraints in `ssl::select_next_proto` that allowed a use after free. - -### Added - -* Added `SslMethod::dtls_client` and `SslMethod::dtls_server`. - -## [v0.10.69] - 2025-01-25 - -### Fixed - -* Fixed the version constraint on `openssl-macros`. - -### Added - -* Added `SslContextBuilder::load_verify_locations`. -* Added `Hasher::squeeze_xof`. -* Added `SslContextBuilder::set_alpn_select_callback` support for boringssl. - -## [v0.10.68] - 2024-10-16 - -### Fixed - -* Fixed building on Rust 1.63.0 (our MSRV) with OpenSSL 3.2 or newer. - -## [v0.10.67] - 2024-10-15 - -### Added - -* Added support for LibreSSL 4.0.x. -* Added `argon2id` - -### Fixed - -* Fixed a case where `MdCtxRef::digest_verify_final` could leave an error on the stack. -* Fixed a case where `RsaRef::check_key` could leave an error on the stack. - -### Changed - -* `openssl` is now a 2021 edition crate -* Explicitly specify the MSRV in `Cargo.toml` - -## [v0.10.66] - 2024-07-21 - -### Fixed - -- Fixed undefined behavior in `MemBio::get_buf` when the resulting buffer had a length of 0. - -## [v0.10.65] - 2024-07-20 - -### Fixed - -* Ensure we are initialized in `MessageDigest::from_nid`, `Md::from_nid`, `Md::fetch` - -### Changed - -* Expose `SslContextBuilder::set_keylog_callback` on BoringSSL - -## [v0.10.64] - 2024-02-19 - -### Added - -* Added `PkeyCtxRef::{nonce_type, set_nonce_type}`. -* Added `X509Ref::alias`. - - -## [v0.10.63] - 2024-01-19 - -### Added - -* Added `Pkcs7Ref::{type_,signed}`. -* Added `Pkcs7SignedRef::certificates`. -* Added `Cipher::{aes_256_xts,des_ede3_ecb,des_ede3_cfb8,des_ede3_ofb,camellia128_ofb,camellia192_ofb,camellia256_ofb,cast5_ofb,idea_ofb}` -* Added `PKey::from_dhx` -* Added `PKey::{public_key_from_pem_passphrase,public_key_from_pem_callback}`. - -### Changed - -* `Cipher::aes_128_ofb` is now available on BoringSSL -* `Nid::{BRAINPOOL_P256R1,BRAINPOOL_P320R1,BRAINPOOL_P384R1,BRAINPOOL_P512R1}` are now available on LibreSSL. - -## [v0.10.62] - 2023-12-22 - -### Added - -* Added `Nid::BRAINPOOL_P320R1` -* Added `rand_priv_bytes` - -### Fixed - -* Fixed building on the latest version of BoringSSL - -## [v0.10.61] - 2023-12-04 - -### Changed - -* `SslStream` now uses `SSL_read_ex`, `SSL_write_ex`, and `SSL_peek_ex` when available - -### Added - -* Added `SslStream::{read_uninit, ssl_read_uninit}`. - -## [v0.10.60] - 2023-11-22 - -### Deprecated - -* Deprecated `X509StoreRef::objects`. It is unsound. All callers should migrate to using `X509StoreRef::all_certificates` instead. - -### Fixed - -* Fixed a memory leak when calling `SslContextBuilder::set_ex_data` and `SslRef::set_ex_data` multiple times with the same index. - -### Added - -* Added `X509StoreRef::all_certificates` -* Added `cipher::Cipher::{camellia128_cbc,camellia192_cbc,camellia256_cbc,cast5_cbc,idea_cbc}` -* Added `symm::Cipher::{des_ede3_ecb,des_ede3_cfb8,des_ede3_ofb,camellia_128_ecb,camellia_128_ofb,camellia_128_cfb128,camellia_192_ecb,camellia_192_ofb,camellia_192_cfb128,camellia_256_ecb,camellia_256_ofb,camellia_256_cfb128,cast5_ecb,cast5_ofb,cast5_cfb64,idea_ecb,idea_ofb,idea_cfb64}` -* Added `Crypter::update_unchecked` -* Added `SslRef::{peer_tmp_key,tmp_key}` - -### Changed - -* `cipher::Cipher::chacha20` is now available on LibreSSL -* `symm::Cipher::chacha20` is now available on LibreSSL - -## [v0.10.59] - 2023-11-03 - -### Added - -* Added `Nid::CHACHA20_POLY1305` - -### Changed - -* Fixed the availability of `Id::RSA_PSS` on OpenSSL - -## [v0.10.58] - 2023-11-01 - -### Added - -* Added `Id::{RSA_PSS,DHX}` constants -* Added `SslContextBuilder::set_security_level` -* Added `SslContextRef::security_level` -* Added `SslRef::set_security_level`, `SslRef::security_level` -* Added `Cipher::{camellia_128_cbc, camellia_192_cbc, camellia_256_cbc, cast5_cbc, idea_cbc}` -* Added `X509CrlRef::extension` -* Added `X509PurposeId::CODE_SIGN` - -### Changed - -* `Pkey` HKDF functionality now works on LibreSSL -* `BigNum::mod_sqrt` is now available on all OpenSSLs -* `MessageDigest::sha3*` are now available on LibreSSL - -## [v0.10.57] - 2023-08-27 - -### Added -* Added `X509VerifyParam::set_email` -* `Cipher::chacha20_poly1305` is now available on LibreSSL -* Added `CipherCtx::copy` - -### Changed -* Updated `bitflags` dependency to the 2.x series - -## [v0.10.56] - 2023-08-06 - -## Added - -* Added `BigNumRef::mod_sqrt`. -* Added `PkeyCtxRef::set_signature_md` and `PkeyCtxRef::set_rsa_pss_saltlen`. -* Added `PkeyCtxRef::verify_recover_init` and `PkeyCtxRef::verify_recover`. -* Added `BigNumRef::is_even` and `BigNumRef::is_odd`. -* Added `EcPointRef::to_hex_str` and `EcPoint::from_hex_str`. -* Added support for AES key wrap and wrap pad. - -## [v0.10.55] - 2023-06-20 - -### Fixed - -* Fixed compilation with the latest version of BoringSSL. -* Fixed compilation when OpenSSL is compiled with `OPENSSL_NO_OCB`. -* Fixed a segfault in `X509VerifyParamRef::set_host` when called with an empty string. - -### Added - -* Added `Deriver::set_peer_ex`. -* Added `EcGroupRef::asn1_flag`. -* Exposed `EcPointRef::affine_coordinates` on BoringSSL and LibreSSL. -* Added `Nid::SM2` and `Id::SM2` - -## [v0.10.54] - 2023-05-31 - -### Fixed - -* `PKey::private_key_to_pkcs8_passphrase` no longer panics if a `passphrase` contains a NUL byte. - -## [v0.10.53] - 2023-05-30 - -### Added - -* Added `Dsa::from_pqg`, `Dsa::generate_key`, and `Dsa::generate_params`. -* Added `SslRef::bytes_to_cipher_list`. -* Added `SubjectAlternativeName::other_name2` - -## [v0.10.52] - 2023-04-24 - -### Added - -* Added `DhRef::check_key`. -* Added `Id::POLY1305`. -* Added `X509Ref::subject_key_id`, `X509Ref::authority_key_id`, `X509Ref::authority_issuer`, and `X509Ref::authority_serial`. - - -## [v0.10.51] - 2023-04-20 - -### Added - -* Added `X509RevokedRef::issuer_name` and `X509RevokedRef::reason_code`. -* Added `Dh::set_key` and `Dh::set_public_key` -* Added `Asn1OctetString` and `Asn1OctetStringRef1` -* Added `X509Extension::new_from_der` - -### Deprecated - -* Deprecated `X509Extension::new` and `X509Extension::new_nid` in favor of `X509Extension::new_from_der` and the `extensions` module. -* Deprecated `X509Extension::add_alias`, it is not required with `new_from_der` or the `extensions` module. - -## [v0.10.50] - 2023-04-09 - -### Added - -* Added `CipherCtxRef::cipher_update_inplace`. - -## [v0.10.49] - 2023-04-01 - -### Fixed - -* `SslConnector` no longer sets the SNI extension when connecting to an IP address. - -### Added - -* Implemented `Ord`, `PartialOrd`, `Eq`, and `PartialEq` for `Asn1Integer` and `Asn1IntegerRef`. -* Added `X509Ref::crl_distribution_points`, and `DistPoint`. - -## [v0.10.48] - 2023-03-23 - -### Fixed - -* Fixed injection vulnerabilities where OpenSSL's configuration mini-language could be used via `x509::extension::SubjectAlternativeName` and `x509::extension::ExtendedKeyUsage`. The mini-language can read arbitrary files amongst other things. - * As part of fixing this `SubjectAlternativeName::dir_name` and `SubjectAlternativeName::other_name` are deprecated and their implementations always `panic!`. If you have a use case for these, please file an issue. -* Fixed several NULL pointer dereferences in OpenSSL that could be triggered via `x509::X509Extension::new` and `x509::X509Extension::new_nid`. Note that these methods still accept OpenSSL's configuration mini-language, and therefore should not be used with untrusted data. -* Fixed a data-race with `x509::X509Name` that are created with `x509::X509NameBuilder` and then used concurrently. -* Fixed LibreSSL version checking. More functions should now be correctly available on LibreSSL. - -## [v0.10.47] - 2023-03-19 - -### Added - -* Added support for X25519 and Ed25519 on LibreSSL and BoringSSL. -* Added `Error::library_code` and `Error::reason_code`. - -## [v0.10.46] - 2023-03-14 - -### Fixed - -* Fixed a potential null-pointer deref when parsing a PKCS#12 archive with no identity. -* Fixed builds against OpenSSL built with `no-cast`. -* Fixed debug formatting of `GeneralName`. - -### Deprecated - -* Deprecated `PKcs12Ref::parse` in favor of `Pkcs12Ref::parse2`. -* Deprecated `ParsedPkcs12` in favor of `ParsedPkcs12_2`. -* Deprecated `Pkcs12Builder::build` in favor of `Pkcs12Builder::build2`. - -### Added - -* Added `X509VerifyParamRef::set_auth_level`, `X509VerifyParamRef::auth_level`, and `X509VerifyParamRef::set_purpose`. -* Added `X509PurposeId` and `X509Purpose`. -* Added `X509NameBuilder::append_entry`. -* Added `PKeyRef::private_key_to_pkcs8`. -* Added `X509LookupRef::load_crl_file`. -* Added `Pkcs12Builder::name`, `Pkcs12Builder::pkey`, and `Pkcs12Builder::cert`. -* Added `SslRef::set_method`, `SslRef::set_private_key_file`, `SslRef::set_private_key`, `SslRef::set_certificate`, `SslRef::set_certificate_chain_file`, `SslRef::add_client_ca`, `SslRef::set_client_ca_list`, `SslRef::set_min_proto_version`, `SslREf::set_max_proto_version`, `SslRef::set_ciphersuites`, `SslRef::set_cipher_list`, `SslRef::set_verify_cert_store`. -* Added `X509NameRef::to_owned`. -* Added `SslContextBuilder::set_num_tickets`, `SslContextRef::num_tickets`, `SslRef::set_num_tickets`, and `SslRef::num_tickets`. -* Added `CmsContentInfo::verify`. - -## [v0.10.45] - 2022-12-20 - -### Fixed - -* Removed the newly added `CipherCtxRef::minimal_output_size` method, which did not work properly. -* Added `NO_DEPRECATED_3_0` cfg checks for more APIs. - -### Added - -* Added `SslRef::add_chain_cert`. -* Added `PKeyRef::security_bits`. -* Added `Provider::set_default_search_path`. -* Added `CipherCtxRef::cipher_final_unchecked`. - -## [v0.10.44] - 2022-12-06 - -### Added - -* Added `CipherCtxRef::num`, `CipherCtxRef::minimal_output_size`, and `CipherCtxRef::cipher_update_unchecked`. -* Improved output buffer size checks in `CipherCtxRef::cipher_update`. -* Added `X509Lookup::file` and `X509LookupRef::load_cert_file`. - -## [v0.10.43] - 2022-11-23 - -### Added - -* Added `Nid::BRAINPOOL_P256R1`, `Nid::BRAINPOOL_P384R1`, `Nid::BRAINPOOL_P512R1`. -* Added `BigNumRef::copy_from_slice`. -* Added `Cipher` constructors for Camellia, CAST5, and IDEA ciphers. -* Added `DsaSig`. -* Added `X509StoreBuilderRef::set_param`. -* Added `X509VerifyParam::new`, `X509VerifyParamRef::set_time`, and `X509VerifyParamRef::set_depth`. - -## [v0.10.42] - 2022-09-26 - -### Added - -* Added `SslRef::psk_identity_hint` and `SslRef::psk_identity`. -* Added SHA-3 constants to `Nid`. -* Added `SslOptions::PRIORITIZE_CHACHA`. -* Added `X509ReqRef::to_text`. -* Added `MdCtxRef::size`. -* Added `X509NameRef::try_cmp`. -* Added `MdCtxRef::reset`. -* Added experimental, unstable support for BoringSSL. - -### Fixed - -* Fixed `MdCtxRef::digest_verify_init` to support `PKey`s with only public components. - -## [v0.10.41] - 2022-06-09 - -### Fixed - -* Fixed a use-after-free in `Error::function` and `Error::file` with OpenSSL 3.x. - -### Added - -* Added `MessageDigest::block_size` and `MdRef::block_size`. -* Implemented `Ord` and `Eq` for `X509` and `X509Ref`. -* Added `X509Extension::add_alias`. -* Added SM4 support. -* Added `EcGroup::from_components` `EcGropuRef::set_generator`, and `EcPointRef::set_affine_coordinates_gfp`. - -## [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` 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` rather than a `PKey`. 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 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/rust-openssl/rust-openssl/compare/openssl-v0.10.75...master -[v0.10.75]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.74...openssl-v0.10.75 -[v0.10.74]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.73...openssl-v0.10.74 -[v0.10.73]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.72...openssl-v0.10.73 -[v0.10.72]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.71...openssl-v0.10.72 -[v0.10.71]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.70...openssl-v0.10.71 -[v0.10.70]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.69...openssl-v0.10.70 -[v0.10.69]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.68...openssl-v0.10.69 -[v0.10.68]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.67...openssl-v0.10.68 -[v0.10.67]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.66...openssl-v0.10.67 -[v0.10.66]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.65...openssl-v0.10.66 -[v0.10.65]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.64...openssl-v0.10.65 -[v0.10.64]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.63...openssl-v0.10.64 -[v0.10.63]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.62...openssl-v0.10.63 -[v0.10.62]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.61...openssl-v0.10.62 -[v0.10.61]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.60...openssl-v0.10.61 -[v0.10.60]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.59...openssl-v0.10.60 -[v0.10.59]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.58...openssl-v0.10.59 -[v0.10.58]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.57...openssl-v0.10.58 -[v0.10.57]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.56...openssl-v0.10.57 -[v0.10.56]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.55...openssl-v0.10.56 -[v0.10.55]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.54...openssl-v0.10.55 -[v0.10.54]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.53...openssl-v0.10.54 -[v0.10.53]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.52...openssl-v0.10.53 -[v0.10.52]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.51...openssl-v0.10.52 -[v0.10.51]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.50...openssl-v0.10.51 -[v0.10.50]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.49...openssl-v0.10.50 -[v0.10.49]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.48...openssl-v0.10.49 -[v0.10.48]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.47...openssl-v0.10.48 -[v0.10.47]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.46...openssl-v0.10.47 -[v0.10.46]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.45...openssl-v0.10.46 -[v0.10.45]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.44...openssl-v0.10.45 -[v0.10.44]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.43...openssl-v0.10.44 -[v0.10.43]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.42...openssl-v0.10.43 -[v0.10.42]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.41...openssl-v0.10.42 -[v0.10.41]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.40...openssl-v0.10.41 -[v0.10.40]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.39...openssl-v0.10.40 -[v0.10.39]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.38...openssl-v0.10.39 -[v0.10.38]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.37...openssl-v0.10.38 -[v0.10.37]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.36...openssl-v0.10.37 -[v0.10.36]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.35...openssl-v0.10.36 -[v0.10.35]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.34...openssl-v0.10.35 -[v0.10.34]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.33...openssl-v0.10.34 -[v0.10.33]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.32...openssl-v0.10.33 -[v0.10.32]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.31...openssl-v0.10.32 -[v0.10.31]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.30...openssl-v0.10.31 -[v0.10.30]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.29...openssl-v0.10.30 -[v0.10.29]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.28...openssl-v0.10.29 -[v0.10.28]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.27...openssl-v0.10.28 -[v0.10.27]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.26...openssl-v0.10.27 -[v0.10.26]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.25...openssl-v0.10.26 -[v0.10.25]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.24...openssl-v0.10.25 -[v0.10.24]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.23...openssl-v0.10.24 -[v0.10.23]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.22...openssl-v0.10.23 -[v0.10.22]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.21...openssl-v0.10.22 -[v0.10.21]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.20...openssl-v0.10.21 -[v0.10.20]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.19...openssl-v0.10.20 -[v0.10.19]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.18...openssl-v0.10.19 -[v0.10.18]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.17...openssl-v0.10.18 -[v0.10.17]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.16...openssl-v0.10.17 -[v0.10.16]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.15...openssl-v0.10.16 -[v0.10.15]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.14...openssl-v0.10.15 -[v0.10.14]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.13...openssl-v0.10.14 -[v0.10.13]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.12...openssl-v0.10.13 -[v0.10.12]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.11...openssl-v0.10.12 -[v0.10.11]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.10...openssl-v0.10.11 -[v0.10.10]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.9...openssl-v0.10.10 -[v0.10.9]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.8...openssl-v0.10.9 -[v0.10.8]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.7...openssl-v0.10.8 -[v0.10.7]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.6...openssl-v0.10.7 -[v0.10.6]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.5...openssl-v0.10.6 -[v0.10.5]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.4...openssl-v0.10.5 -[v0.10.4]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.3...openssl-v0.10.4 -[v0.10.3]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.2...openssl-v0.10.3 -[v0.10.2]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.1...openssl-v0.10.2 -[v0.10.1]: https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.0...openssl-v0.10.1 -[v0.10.0]: https://github.com/rust-openssl/rust-openssl/compare/v0.9.23...openssl-v0.10.0 -[release tags]: https://github.com/rust-openssl/rust-openssl/releases diff --git a/patch/openssl/Cargo.toml b/patch/openssl/Cargo.toml deleted file mode 100644 index b7f24200f5a8c..0000000000000 --- a/patch/openssl/Cargo.toml +++ /dev/null @@ -1,82 +0,0 @@ -# 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 = "2021" -rust-version = "1.70.0" -name = "openssl" -version = "0.10.75" -authors = ["Steven Fackler "] -build = "build.rs" -autolib = false -autobins = false -autoexamples = false -autotests = false -autobenches = false -description = "OpenSSL bindings" -readme = "README.md" -keywords = [ - "crypto", - "tls", - "ssl", - "dtls", -] -categories = [ - "cryptography", - "api-bindings", -] -license = "Apache-2.0" -repository = "https://github.com/rust-openssl/rust-openssl" - -[features] -aws-lc = ["ffi/aws-lc"] -aws-lc-fips = ["ffi/aws-lc-fips"] -bindgen = ["ffi/bindgen"] -default = [] -unstable_boringssl = ["ffi/unstable_boringssl"] -v101 = [] -v102 = [] -v110 = [] -v111 = [] -vendored = ["ffi/vendored"] - -[lib] -name = "openssl" -path = "src/lib.rs" -# -#[[example]] -#name = "mk_certs" -#path = "examples/mk_certs.rs" - -[dependencies.bitflags] -version = "2.2.1" - -[dependencies.cfg-if] -version = "1.0" - -[dependencies.ffi] -version = "0.9.111" -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.1" - -[dev-dependencies.hex] -version = "0.4" diff --git a/patch/openssl/LICENSE b/patch/openssl/LICENSE deleted file mode 100644 index f259067e9a54a..0000000000000 --- a/patch/openssl/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -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. diff --git a/patch/openssl/LICENSE-APACHE b/patch/openssl/LICENSE-APACHE deleted file mode 100644 index 8f71f43fee3f7..0000000000000 --- a/patch/openssl/LICENSE-APACHE +++ /dev/null @@ -1,202 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - 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. - diff --git a/patch/openssl/README.md b/patch/openssl/README.md deleted file mode 100644 index 50c6d57722901..0000000000000 --- a/patch/openssl/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# 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. diff --git a/patch/openssl/build.rs b/patch/openssl/build.rs deleted file mode 100644 index 5d8f251c9658b..0000000000000 --- a/patch/openssl/build.rs +++ /dev/null @@ -1,162 +0,0 @@ -#![allow( - clippy::inconsistent_digit_grouping, - clippy::uninlined_format_args, - clippy::unusual_byte_groupings -)] - -use std::env; - -fn main() { - println!("cargo:rustc-check-cfg=cfg(osslconf, values(\"OPENSSL_NO_OCB\", \"OPENSSL_NO_SM4\", \"OPENSSL_NO_SEED\", \"OPENSSL_NO_CHACHA\", \"OPENSSL_NO_CAST\", \"OPENSSL_NO_IDEA\", \"OPENSSL_NO_CAMELLIA\", \"OPENSSL_NO_RC4\", \"OPENSSL_NO_BF\", \"OPENSSL_NO_PSK\", \"OPENSSL_NO_DEPRECATED_3_0\", \"OPENSSL_NO_SCRYPT\", \"OPENSSL_NO_SM3\", \"OPENSSL_NO_RMD160\", \"OPENSSL_NO_EC2M\", \"OPENSSL_NO_OCSP\", \"OPENSSL_NO_SRTP\", \"OPENSSL_NO_CMS\", \"OPENSSL_NO_EC\", \"OPENSSL_NO_ARGON2\", \"OPENSSL_NO_RC2\"))"); - - println!("cargo:rustc-check-cfg=cfg(libressl)"); - println!("cargo:rustc-check-cfg=cfg(boringssl)"); - println!("cargo:rustc-check-cfg=cfg(awslc)"); - println!("cargo:rustc-check-cfg=cfg(awslc_fips)"); - - println!("cargo:rustc-check-cfg=cfg(libressl250)"); - println!("cargo:rustc-check-cfg=cfg(libressl251)"); - println!("cargo:rustc-check-cfg=cfg(libressl261)"); - println!("cargo:rustc-check-cfg=cfg(libressl270)"); - println!("cargo:rustc-check-cfg=cfg(libressl271)"); - println!("cargo:rustc-check-cfg=cfg(libressl273)"); - println!("cargo:rustc-check-cfg=cfg(libressl280)"); - println!("cargo:rustc-check-cfg=cfg(libressl291)"); - println!("cargo:rustc-check-cfg=cfg(libressl310)"); - println!("cargo:rustc-check-cfg=cfg(libressl321)"); - println!("cargo:rustc-check-cfg=cfg(libressl332)"); - println!("cargo:rustc-check-cfg=cfg(libressl340)"); - println!("cargo:rustc-check-cfg=cfg(libressl350)"); - println!("cargo:rustc-check-cfg=cfg(libressl360)"); - println!("cargo:rustc-check-cfg=cfg(libressl361)"); - println!("cargo:rustc-check-cfg=cfg(libressl370)"); - println!("cargo:rustc-check-cfg=cfg(libressl380)"); - println!("cargo:rustc-check-cfg=cfg(libressl382)"); - println!("cargo:rustc-check-cfg=cfg(libressl390)"); - println!("cargo:rustc-check-cfg=cfg(libressl400)"); - println!("cargo:rustc-check-cfg=cfg(libressl410)"); - println!("cargo:rustc-check-cfg=cfg(libressl420)"); - - println!("cargo:rustc-check-cfg=cfg(ossl101)"); - println!("cargo:rustc-check-cfg=cfg(ossl102)"); - println!("cargo:rustc-check-cfg=cfg(ossl110)"); - println!("cargo:rustc-check-cfg=cfg(ossl110g)"); - println!("cargo:rustc-check-cfg=cfg(ossl110h)"); - println!("cargo:rustc-check-cfg=cfg(ossl111)"); - println!("cargo:rustc-check-cfg=cfg(ossl111d)"); - println!("cargo:rustc-check-cfg=cfg(ossl300)"); - println!("cargo:rustc-check-cfg=cfg(ossl310)"); - println!("cargo:rustc-check-cfg=cfg(ossl320)"); - println!("cargo:rustc-check-cfg=cfg(ossl330)"); - println!("cargo:rustc-check-cfg=cfg(ossl340)"); - println!("cargo:rustc-check-cfg=cfg(ossl350)"); - - if env::var("DEP_OPENSSL_LIBRESSL").is_ok() { - println!("cargo:rustc-cfg=libressl"); - } - - if env::var("DEP_OPENSSL_BORINGSSL").is_ok() { - println!("cargo:rustc-cfg=boringssl"); - } - - if env::var("DEP_OPENSSL_AWSLC").is_ok() { - println!("cargo:rustc-cfg=awslc"); - } - - if env::var("DEP_OPENSSL_AWSLC_FIPS").is_ok() { - println!("cargo:rustc-cfg=awslc"); - println!("cargo:rustc-cfg=awslc_fips"); - } - - if let Ok(v) = env::var("DEP_OPENSSL_LIBRESSL_VERSION_NUMBER") { - let version = u64::from_str_radix(&v, 16).unwrap(); - - println!("cargo:rustc-cfg=libressl250"); - println!("cargo:rustc-cfg=libressl251"); - println!("cargo:rustc-cfg=libressl261"); - println!("cargo:rustc-cfg=libressl270"); - println!("cargo:rustc-cfg=libressl271"); - println!("cargo:rustc-cfg=libressl273"); - println!("cargo:rustc-cfg=libressl280"); - println!("cargo:rustc-cfg=libressl291"); - println!("cargo:rustc-cfg=libressl310"); - println!("cargo:rustc-cfg=libressl321"); - println!("cargo:rustc-cfg=libressl332"); - println!("cargo:rustc-cfg=libressl340"); - println!("cargo:rustc-cfg=libressl350"); - - if version >= 0x3_06_00_00_0 { - println!("cargo:rustc-cfg=libressl360"); - } - if version >= 0x3_06_01_00_0 { - println!("cargo:rustc-cfg=libressl361"); - } - if version >= 0x3_07_00_00_0 { - println!("cargo:rustc-cfg=libressl370"); - } - if version >= 0x3_08_00_00_0 { - println!("cargo:rustc-cfg=libressl380"); - } - if version >= 0x3_08_02_00_0 { - println!("cargo:rustc-cfg=libressl382"); - } - if version >= 0x3_09_00_00_0 { - println!("cargo:rustc-cfg=libressl390"); - } - if version >= 0x4_00_00_00_0 { - println!("cargo:rustc-cfg=libressl400"); - } - if version >= 0x4_01_00_00_0 { - println!("cargo:rustc-cfg=libressl410"); - } - if version >= 0x4_02_00_00_0 { - println!("cargo:rustc-cfg=libressl420"); - } - } - - 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(); - println!("cargo:rustc-cfg=ossl101"); - 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 >= 0x1_01_01_04_0 { - println!("cargo:rustc-cfg=ossl111d"); - } - if version >= 0x3_00_00_00_0 { - println!("cargo:rustc-cfg=ossl300"); - } - if version >= 0x3_01_00_00_0 { - println!("cargo:rustc-cfg=ossl310"); - } - if version >= 0x3_02_00_00_0 { - println!("cargo:rustc-cfg=ossl320"); - } - if version >= 0x3_03_00_00_0 { - println!("cargo:rustc-cfg=ossl330"); - } - if version >= 0x3_04_00_00_0 { - println!("cargo:rustc-cfg=ossl340"); - } - if version >= 0x3_05_00_00_0 { - println!("cargo:rustc-cfg=ossl350"); - } - } -} diff --git a/patch/openssl/examples/mk_certs.rs b/patch/openssl/examples/mk_certs.rs deleted file mode 100644 index 48538c7a74163..0000000000000 --- a/patch/openssl/examples/mk_certs.rs +++ /dev/null @@ -1,160 +0,0 @@ -#![allow(clippy::uninlined_format_args)] - -//! 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), ErrorStack> { - let rsa = Rsa::generate(2048)?; - let key_pair = PKey::from_rsa(rsa)?; - - let mut x509_name = X509NameBuilder::new()?; - x509_name.append_entry_by_text("C", "US")?; - x509_name.append_entry_by_text("ST", "TX")?; - x509_name.append_entry_by_text("O", "Some CA organization")?; - x509_name.append_entry_by_text("CN", "ca test")?; - let x509_name = x509_name.build(); - - let mut cert_builder = X509::builder()?; - cert_builder.set_version(2)?; - let serial_number = { - let mut serial = BigNum::new()?; - serial.rand(159, MsbOption::MAYBE_ZERO, false)?; - serial.to_asn1_integer()? - }; - cert_builder.set_serial_number(&serial_number)?; - cert_builder.set_subject_name(&x509_name)?; - cert_builder.set_issuer_name(&x509_name)?; - cert_builder.set_pubkey(&key_pair)?; - let not_before = Asn1Time::days_from_now(0)?; - cert_builder.set_not_before(¬_before)?; - let not_after = Asn1Time::days_from_now(365)?; - cert_builder.set_not_after(¬_after)?; - - cert_builder.append_extension(BasicConstraints::new().critical().ca().build()?)?; - cert_builder.append_extension( - KeyUsage::new() - .critical() - .key_cert_sign() - .crl_sign() - .build()?, - )?; - - let subject_key_identifier = - SubjectKeyIdentifier::new().build(&cert_builder.x509v3_context(None, None))?; - cert_builder.append_extension(subject_key_identifier)?; - - cert_builder.sign(&key_pair, MessageDigest::sha256())?; - let cert = cert_builder.build(); - - Ok((cert, key_pair)) -} - -/// Make a X509 request with the given private key -fn mk_request(key_pair: &PKey) -> Result { - 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, -) -> Result<(X509, PKey), ErrorStack> { - let rsa = Rsa::generate(2048)?; - let key_pair = PKey::from_rsa(rsa)?; - - let req = mk_request(&key_pair)?; - - let mut cert_builder = X509::builder()?; - cert_builder.set_version(2)?; - let serial_number = { - let mut serial = BigNum::new()?; - serial.rand(159, MsbOption::MAYBE_ZERO, false)?; - serial.to_asn1_integer()? - }; - cert_builder.set_serial_number(&serial_number)?; - cert_builder.set_subject_name(req.subject_name())?; - cert_builder.set_issuer_name(ca_cert.subject_name())?; - cert_builder.set_pubkey(&key_pair)?; - let not_before = Asn1Time::days_from_now(0)?; - cert_builder.set_not_before(¬_before)?; - let not_after = Asn1Time::days_from_now(365)?; - cert_builder.set_not_after(¬_after)?; - - cert_builder.append_extension(BasicConstraints::new().build()?)?; - - cert_builder.append_extension( - KeyUsage::new() - .critical() - .non_repudiation() - .digital_signature() - .key_encipherment() - .build()?, - )?; - - let subject_key_identifier = - SubjectKeyIdentifier::new().build(&cert_builder.x509v3_context(Some(ca_cert), None))?; - cert_builder.append_extension(subject_key_identifier)?; - - let auth_key_identifier = AuthorityKeyIdentifier::new() - .keyid(false) - .issuer(false) - .build(&cert_builder.x509v3_context(Some(ca_cert), None))?; - cert_builder.append_extension(auth_key_identifier)?; - - let subject_alt_name = SubjectAlternativeName::new() - .dns("*.example.com") - .dns("hello.com") - .build(&cert_builder.x509v3_context(Some(ca_cert), None))?; - cert_builder.append_extension(subject_alt_name)?; - - cert_builder.sign(ca_key_pair, MessageDigest::sha256())?; - let cert = cert_builder.build(); - - Ok((cert, key_pair)) -} - -fn real_main() -> Result<(), ErrorStack> { - let (ca_cert, ca_key_pair) = mk_ca_cert()?; - let (cert, _key_pair) = mk_ca_signed_cert(&ca_cert, &ca_key_pair)?; - - // Verify that this cert was issued by this ca - match ca_cert.issued(&cert) { - X509VerifyResult::OK => println!("Certificate verified!"), - ver_err => println!("Failed to verify certificate: {}", ver_err), - }; - - Ok(()) -} - -fn main() { - match real_main() { - Ok(()) => println!("Finished."), - Err(e) => println!("Error: {}", e), - }; -} diff --git a/patch/openssl/src/aes.rs b/patch/openssl/src/aes.rs deleted file mode 100644 index 25de83d5c0d80..0000000000000 --- a/patch/openssl/src/aes.rs +++ /dev/null @@ -1,323 +0,0 @@ -//! 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 - -#![cfg_attr( - all( - not(boringssl), - not(awslc), - not(osslconf = "OPENSSL_NO_DEPRECATED_3_0") - ), - doc = r#"\ -## 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 cfg_if::cfg_if; -use libc::{c_int, c_uint}; -use std::mem::MaybeUninit; -use std::ptr; - -#[cfg(not(any(boringssl, awslc)))] -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); - -cfg_if! { - if #[cfg(any(boringssl, awslc))] { - type AesBitType = c_uint; - type AesSizeType = usize; - } else { - type AesBitType = c_int; - type AesSizeType = c_uint; - } -} - -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 { - unsafe { - assert!(key.len() <= c_int::MAX as usize / 8); - - let mut aes_key = MaybeUninit::uninit(); - let r = ffi::AES_set_encrypt_key( - key.as_ptr() as *const _, - key.len() as AesBitType * 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 { - unsafe { - assert!(key.len() <= c_int::MAX as usize / 8); - - let mut aes_key = MaybeUninit::uninit(); - let r = ffi::AES_set_decrypt_key( - key.as_ptr() as *const _, - key.len() as AesBitType * 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. -#[cfg(not(any(boringssl, awslc)))] -#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] -#[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 { - 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 AesSizeType, - ); - 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 { - 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 AesSizeType, - ); - - if written <= 0 { - Err(KeyError(())) - } else { - Ok(written as usize) - } - } -} - -#[cfg(test)] -mod test { - use hex::FromHex; - - use super::*; - #[cfg(not(any(boringssl, awslc)))] - use crate::symm::Mode; - - // From https://www.mgp25.com/AESIGE/ - #[test] - #[cfg(not(any(boringssl, awslc)))] - #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] - 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[..]); - } -} diff --git a/patch/openssl/src/asn1.rs b/patch/openssl/src/asn1.rs deleted file mode 100644 index 0e2e2a3a1e39d..0000000000000 --- a/patch/openssl/src/asn1.rs +++ /dev/null @@ -1,922 +0,0 @@ -#![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}; -use std::cmp::Ordering; -use std::convert::TryInto; -use std::ffi::CString; -use std::fmt; -use std::ptr; -use std::str; - -use crate::bio::MemBio; -use crate::bn::{BigNum, BigNumRef}; -use crate::error::ErrorStack; -use crate::nid::Nid; -use crate::stack::Stackable; -use crate::string::OpensslString; -use crate::{cvt, cvt_p, util}; -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://docs.openssl.org/master/man3/ASN1_GENERALIZEDTIME_set/ - 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())), - } - } - } -} - -impl Asn1GeneralizedTime { - /// Creates a new generalized time corresponding to the specified ASN1 time - /// string. - #[corresponds(ASN1_GENERALIZEDTIME_set_string)] - #[allow(clippy::should_implement_trait)] - pub fn from_str(s: &str) -> Result { - unsafe { - ffi::init(); - - let time_str = CString::new(s).unwrap(); - let ptr = cvt_p(ffi::ASN1_GENERALIZEDTIME_new())?; - let time = Asn1GeneralizedTime::from_ptr(ptr); - - cvt(ffi::ASN1_GENERALIZEDTIME_set_string( - time.as_ptr(), - time_str.as_ptr(), - ))?; - - Ok(time) - } - } -} - -/// 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)] -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://docs.openssl.org/master/man3/ASN1_TIME_set/ - 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)] - pub fn diff(&self, compare: &Self) -> Result { - 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)] - pub fn compare(&self, other: &Self) -> Result { - 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) - } -} - -impl PartialEq for Asn1TimeRef { - fn eq(&self, other: &Asn1TimeRef) -> bool { - self.diff(other) - .map(|t| t.days == 0 && t.secs == 0) - .unwrap_or(false) - } -} - -impl PartialEq for Asn1TimeRef { - fn eq(&self, other: &Asn1Time) -> bool { - self.diff(other) - .map(|t| t.days == 0 && t.secs == 0) - .unwrap_or(false) - } -} - -impl PartialEq for &Asn1TimeRef { - fn eq(&self, other: &Asn1Time) -> bool { - self.diff(other) - .map(|t| t.days == 0 && t.secs == 0) - .unwrap_or(false) - } -} - -impl PartialOrd for Asn1TimeRef { - fn partial_cmp(&self, other: &Asn1TimeRef) -> Option { - self.compare(other).ok() - } -} - -impl PartialOrd for Asn1TimeRef { - fn partial_cmp(&self, other: &Asn1Time) -> Option { - self.compare(other).ok() - } -} - -impl PartialOrd for &Asn1TimeRef { - fn partial_cmp(&self, other: &Asn1Time) -> Option { - 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 { - 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 { - 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::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 { - 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 { - 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 BoringSSL or OpenSSL 1.1.1 or newer. - #[corresponds(ASN1_TIME_set_string_X509)] - #[cfg(any(ossl111, boringssl, awslc))] - pub fn from_str_x509(s: &str) -> Result { - 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) - } - } -} - -impl PartialEq for Asn1Time { - fn eq(&self, other: &Asn1Time) -> bool { - self.diff(other) - .map(|t| t.days == 0 && t.secs == 0) - .unwrap_or(false) - } -} - -impl PartialEq for Asn1Time { - fn eq(&self, other: &Asn1TimeRef) -> bool { - self.diff(other) - .map(|t| t.days == 0 && t.secs == 0) - .unwrap_or(false) - } -} - -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) - } -} - -impl PartialOrd for Asn1Time { - fn partial_cmp(&self, other: &Asn1Time) -> Option { - self.compare(other).ok() - } -} - -impl PartialOrd for Asn1Time { - fn partial_cmp(&self, other: &Asn1TimeRef) -> Option { - self.compare(other).ok() - } -} - -impl<'a> PartialOrd<&'a Asn1TimeRef> for Asn1Time { - fn partial_cmp(&self, other: &&'a Asn1TimeRef) -> Option { - 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://docs.openssl.org/master/man3/ASN1_STRING_to_UTF8/ - 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 { - 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 { util::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://docs.openssl.org/master/man3/ASN1_INTEGER_set/ - 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://docs.openssl.org/master/man3/BN_to_ASN1_INTEGER/ - /// [`BigNumRef::to_asn1_integer`]: ../bn/struct.BigNumRef.html#method.to_asn1_integer - pub fn from_bn(bn: &BigNumRef) -> Result { - bn.to_asn1_integer() - } -} - -impl Ord for Asn1Integer { - fn cmp(&self, other: &Self) -> Ordering { - Asn1IntegerRef::cmp(self, other) - } -} -impl PartialOrd for Asn1Integer { - fn partial_cmp(&self, other: &Asn1Integer) -> Option { - Some(self.cmp(other)) - } -} -impl Eq for Asn1Integer {} -impl PartialEq for Asn1Integer { - fn eq(&self, other: &Asn1Integer) -> bool { - Asn1IntegerRef::eq(self, other) - } -} - -impl Asn1IntegerRef { - #[allow(missing_docs, clippy::unnecessary_cast)] - #[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 { - 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(|_| ()) } - } - - /// Creates a new Asn1Integer with the same value. - #[corresponds(ASN1_INTEGER_dup)] - pub fn to_owned(&self) -> Result { - unsafe { cvt_p(ffi::ASN1_INTEGER_dup(self.as_ptr())).map(|p| Asn1Integer::from_ptr(p)) } - } -} - -impl Ord for Asn1IntegerRef { - fn cmp(&self, other: &Self) -> Ordering { - let res = unsafe { ffi::ASN1_INTEGER_cmp(self.as_ptr(), other.as_ptr()) }; - res.cmp(&0) - } -} -impl PartialOrd for Asn1IntegerRef { - fn partial_cmp(&self, other: &Asn1IntegerRef) -> Option { - Some(self.cmp(other)) - } -} -impl Eq for Asn1IntegerRef {} -impl PartialEq for Asn1IntegerRef { - fn eq(&self, other: &Asn1IntegerRef) -> bool { - self.cmp(other) == Ordering::Equal - } -} - -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 { util::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_OCTET_STRING; - fn drop = ffi::ASN1_OCTET_STRING_free; - /// ASN.1 OCTET STRING type - pub struct Asn1OctetString; - /// A reference to an [`Asn1OctetString`]. - pub struct Asn1OctetStringRef; -} - -impl Asn1OctetString { - /// Creates an Asn1OctetString from bytes - pub fn new_from_bytes(value: &[u8]) -> Result { - ffi::init(); - unsafe { - let s = cvt_p(ffi::ASN1_OCTET_STRING_new())?; - ffi::ASN1_OCTET_STRING_set(s, value.as_ptr(), value.len().try_into().unwrap()); - Ok(Self::from_ptr(s)) - } - } -} - -impl Asn1OctetStringRef { - /// Returns the octet string as an array of bytes. - #[corresponds(ASN1_STRING_get0_data)] - pub fn as_slice(&self) -> &[u8] { - unsafe { util::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr().cast()), self.len()) } - } - - /// Returns the number of bytes in the octet string. - #[corresponds(ASN1_STRING_length)] - pub fn len(&self) -> usize { - unsafe { ffi::ASN1_STRING_length(self.as_ptr().cast()) 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; - fn clone = ffi::OBJ_dup; - - /// 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://docs.openssl.org/master/man3/OBJ_obj2nid/ - pub struct Asn1Object; - /// A reference to an [`Asn1Object`]. - pub struct Asn1ObjectRef; -} - -impl Stackable for Asn1Object { - type StackType = ffi::stack_st_ASN1_OBJECT; -} - -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 { - 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()); - util::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, libressl, boringssl, awslc))] { - 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) - } - } -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::ASN1_ENUMERATED; - fn drop = ffi::ASN1_ENUMERATED_free; - - /// An ASN.1 enumerated. - pub struct Asn1Enumerated; - /// A reference to an [`Asn1Enumerated`]. - pub struct Asn1EnumeratedRef; -} - -impl Asn1EnumeratedRef { - /// Get the value, if it fits in the required bounds. - #[corresponds(ASN1_ENUMERATED_get_int64)] - #[cfg(ossl110)] - pub fn get_i64(&self) -> Result { - let mut crl_reason = 0; - unsafe { - cvt(ffi::ASN1_ENUMERATED_get_int64( - &mut crl_reason, - self.as_ptr(), - ))?; - } - Ok(crl_reason) - } -} - -#[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 generalized_time_from_str() { - let time = Asn1GeneralizedTime::from_str("99991231235959Z").unwrap(); - assert_eq!("Dec 31 23:59:59 9999 GMT", time.to_string()); - } - - #[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] - 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] - 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 integer_to_owned() { - let a = Asn1Integer::from_bn(&BigNum::from_dec_str("42").unwrap()).unwrap(); - let b = a.to_owned().unwrap(); - assert_eq!( - a.to_bn().unwrap().to_dec_str().unwrap().to_string(), - b.to_bn().unwrap().to_dec_str().unwrap().to_string(), - ); - assert_ne!(a.as_ptr(), b.as_ptr()); - } - - #[test] - fn integer_cmp() { - let a = Asn1Integer::from_bn(&BigNum::from_dec_str("42").unwrap()).unwrap(); - let b = Asn1Integer::from_bn(&BigNum::from_dec_str("42").unwrap()).unwrap(); - let c = Asn1Integer::from_bn(&BigNum::from_dec_str("43").unwrap()).unwrap(); - assert!(a == b); - assert!(a != c); - assert!(a < c); - assert!(c > b); - } - - #[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], - ); - } - - #[test] - fn asn1_octet_string() { - let octet_string = Asn1OctetString::new_from_bytes(b"hello world").unwrap(); - assert_eq!(octet_string.as_slice(), b"hello world"); - assert_eq!(octet_string.len(), 11); - } -} diff --git a/patch/openssl/src/base64.rs b/patch/openssl/src/base64.rs deleted file mode 100644 index 5ac3547355cf5..0000000000000 --- a/patch/openssl/src/base64.rs +++ /dev/null @@ -1,128 +0,0 @@ -//! Base64 encoding support. -use crate::error::ErrorStack; -use crate::{cvt_n, LenType}; -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 as usize); - let src_len = src.len() as LenType; - - 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, 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 as usize); - let src_len = src.len() as LenType; - - 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: LenType) -> Option { - 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: LenType) -> Option { - 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()); - } -} diff --git a/patch/openssl/src/bio.rs b/patch/openssl/src/bio.rs deleted file mode 100644 index 6f0fcca941f35..0000000000000 --- a/patch/openssl/src/bio.rs +++ /dev/null @@ -1,84 +0,0 @@ -use libc::c_int; -use std::marker::PhantomData; -use std::ptr; - -use crate::cvt_p; -use crate::error::ErrorStack; -use crate::util; - -pub struct MemBioSlice<'a>(*mut ffi::BIO, PhantomData<&'a [u8]>); - -impl Drop for MemBioSlice<'_> { - fn drop(&mut self) { - unsafe { - ffi::BIO_free_all(self.0); - } - } -} - -impl<'a> MemBioSlice<'a> { - pub fn new(buf: &'a [u8]) -> Result, ErrorStack> { - ffi::init(); - - assert!(buf.len() <= c_int::MAX as usize); - let bio = unsafe { - cvt_p(ffi::BIO_new_mem_buf( - buf.as_ptr() as *const _, - buf.len() as crate::SLenType, - ))? - }; - - 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 { - 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); - util::from_raw_parts(ptr as *const _ as *const _, len as usize) - } - } - - #[cfg(not(any(boringssl, awslc)))] - pub unsafe fn from_ptr(bio: *mut ffi::BIO) -> MemBio { - MemBio(bio) - } -} - -#[cfg(test)] -mod tests { - use super::MemBio; - - #[test] - fn test_mem_bio_get_buf_empty() { - let b = MemBio::new().unwrap(); - assert_eq!(b.get_buf(), &[]); - } -} diff --git a/patch/openssl/src/bn.rs b/patch/openssl/src/bn.rs deleted file mode 100644 index b2334d516e8c9..0000000000000 --- a/patch/openssl/src/bn.rs +++ /dev/null @@ -1,1529 +0,0 @@ -//! BigNum implementation -//! -//! Large numbers are important for a cryptographic library. OpenSSL implementation -//! of BigNum uses dynamically assigned memory to store an array of bit chunks. This -//! allows numbers of any size to be compared and mathematical functions performed. -//! -//! OpenSSL wiki describes the [`BIGNUM`] data structure. -//! -//! # Examples -//! -//! ``` -//! use openssl::bn::BigNum; -//! use openssl::error::ErrorStack; -//! -//! fn main() -> Result<(), ErrorStack> { -//! let a = BigNum::new()?; // a = 0 -//! let b = BigNum::from_dec_str("1234567890123456789012345")?; -//! let c = &a * &b; -//! assert_eq!(a, c); -//! Ok(()) -//! } -//! ``` -//! -//! [`BIGNUM`]: https://wiki.openssl.org/index.php/Manual:Bn_internal(3) -use cfg_if::cfg_if; -use foreign_types::{ForeignType, ForeignTypeRef}; -use libc::c_int; -use std::cmp::Ordering; -use std::ffi::CString; -use std::ops::{Add, Deref, Div, Mul, Neg, Rem, Shl, Shr, Sub}; -use std::{fmt, ptr}; - -use crate::asn1::Asn1Integer; -use crate::error::ErrorStack; -use crate::string::OpensslString; -use crate::{cvt, cvt_n, cvt_p, LenType}; -use openssl_macros::corresponds; - -cfg_if! { - if #[cfg(any(ossl110, libressl, awslc))] { - use ffi::{ - BN_get_rfc3526_prime_1536, BN_get_rfc3526_prime_2048, BN_get_rfc3526_prime_3072, BN_get_rfc3526_prime_4096, - BN_get_rfc3526_prime_6144, BN_get_rfc3526_prime_8192, BN_is_negative, - }; - } else if #[cfg(boringssl)] { - use ffi::BN_is_negative; - } else { - use ffi::{ - get_rfc3526_prime_1536 as BN_get_rfc3526_prime_1536, - get_rfc3526_prime_2048 as BN_get_rfc3526_prime_2048, - get_rfc3526_prime_3072 as BN_get_rfc3526_prime_3072, - get_rfc3526_prime_4096 as BN_get_rfc3526_prime_4096, - get_rfc3526_prime_6144 as BN_get_rfc3526_prime_6144, - get_rfc3526_prime_8192 as BN_get_rfc3526_prime_8192, - }; - - #[allow(bad_style)] - unsafe fn BN_is_negative(bn: *const ffi::BIGNUM) -> c_int { - (*bn).neg - } - } -} - -cfg_if! { - if #[cfg(any(ossl110, libressl))] { - use ffi::{ - BN_get_rfc2409_prime_1024, BN_get_rfc2409_prime_768 - }; - } else if #[cfg(not(any(boringssl, awslc)))] { - use ffi::{ - get_rfc2409_prime_1024 as BN_get_rfc2409_prime_1024, - get_rfc2409_prime_768 as BN_get_rfc2409_prime_768, - }; - } -} - -/// Options for the most significant bits of a randomly generated `BigNum`. -pub struct MsbOption(c_int); - -impl MsbOption { - /// The most significant bit of the number may be 0. - pub const MAYBE_ZERO: MsbOption = MsbOption(-1); - - /// The most significant bit of the number must be 1. - pub const ONE: MsbOption = MsbOption(0); - - /// The most significant two bits of the number must be 1. - /// - /// The number of bits in the product of two such numbers will always be exactly twice the - /// number of bits in the original numbers. - pub const TWO_ONES: MsbOption = MsbOption(1); -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::BN_CTX; - fn drop = ffi::BN_CTX_free; - - /// Temporary storage for BigNums on the secure heap - /// - /// BigNum values are stored dynamically and therefore can be expensive - /// to allocate. BigNumContext and the OpenSSL [`BN_CTX`] structure are used - /// internally when passing BigNum values between subroutines. - /// - /// [`BN_CTX`]: https://docs.openssl.org/master/man3/BN_CTX_new/ - pub struct BigNumContext; - /// Reference to [`BigNumContext`] - /// - /// [`BigNumContext`]: struct.BigNumContext.html - pub struct BigNumContextRef; -} - -impl BigNumContext { - /// Returns a new `BigNumContext`. - #[corresponds(BN_CTX_new)] - pub fn new() -> Result { - unsafe { - ffi::init(); - cvt_p(ffi::BN_CTX_new()).map(BigNumContext) - } - } - - /// Returns a new secure `BigNumContext`. - #[corresponds(BN_CTX_secure_new)] - #[cfg(ossl110)] - pub fn new_secure() -> Result { - unsafe { - ffi::init(); - cvt_p(ffi::BN_CTX_secure_new()).map(BigNumContext) - } - } -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::BIGNUM; - fn drop = ffi::BN_free; - - /// Dynamically sized large number implementation - /// - /// Perform large number mathematics. Create a new BigNum - /// with [`new`]. Perform standard mathematics on large numbers using - /// methods from [`Dref`] - /// - /// OpenSSL documentation at [`BN_new`]. - /// - /// [`new`]: struct.BigNum.html#method.new - /// [`Dref`]: struct.BigNum.html#deref-methods - /// [`BN_new`]: https://docs.openssl.org/master/man3/BN_new/ - /// - /// # Examples - /// ``` - /// use openssl::bn::BigNum; - /// # use openssl::error::ErrorStack; - /// # fn bignums() -> Result< (), ErrorStack > { - /// let little_big = BigNum::from_u32(std::u32::MAX)?; - /// assert_eq!(*&little_big.num_bytes(), 4); - /// # Ok(()) - /// # } - /// # fn main () { bignums(); } - /// ``` - pub struct BigNum; - /// Reference to a [`BigNum`] - /// - /// [`BigNum`]: struct.BigNum.html - pub struct BigNumRef; -} - -impl BigNumRef { - /// Erases the memory used by this `BigNum`, resetting its value to 0. - /// - /// This can be used to destroy sensitive data such as keys when they are no longer needed. - #[corresponds(BN_clear)] - pub fn clear(&mut self) { - unsafe { ffi::BN_clear(self.as_ptr()) } - } - - /// Adds a `u32` to `self`. - #[corresponds(BN_add_word)] - pub fn add_word(&mut self, w: u32) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::BN_add_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) } - } - - /// Subtracts a `u32` from `self`. - #[corresponds(BN_sub_word)] - pub fn sub_word(&mut self, w: u32) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::BN_sub_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) } - } - - /// Multiplies a `u32` by `self`. - #[corresponds(BN_mul_word)] - pub fn mul_word(&mut self, w: u32) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::BN_mul_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) } - } - - /// Divides `self` by a `u32`, returning the remainder. - #[corresponds(BN_div_word)] - #[allow(clippy::useless_conversion)] - pub fn div_word(&mut self, w: u32) -> Result { - unsafe { - let r = ffi::BN_div_word(self.as_ptr(), w.into()); - if r == ffi::BN_ULONG::MAX { - Err(ErrorStack::get()) - } else { - Ok(r.into()) - } - } - } - - /// Returns the result of `self` modulo `w`. - #[corresponds(BN_mod_word)] - #[allow(clippy::useless_conversion)] - pub fn mod_word(&self, w: u32) -> Result { - unsafe { - let r = ffi::BN_mod_word(self.as_ptr(), w.into()); - if r == ffi::BN_ULONG::MAX { - Err(ErrorStack::get()) - } else { - Ok(r.into()) - } - } - } - - /// Places a cryptographically-secure pseudo-random nonnegative - /// number less than `self` in `rnd`. - #[corresponds(BN_rand_range)] - pub fn rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::BN_rand_range(rnd.as_ptr(), self.as_ptr())).map(|_| ()) } - } - - /// The cryptographically weak counterpart to `rand_in_range`. - #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] - #[corresponds(BN_pseudo_rand_range)] - pub fn pseudo_rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::BN_pseudo_rand_range(rnd.as_ptr(), self.as_ptr())).map(|_| ()) } - } - - /// Sets bit `n`. Equivalent to `self |= (1 << n)`. - /// - /// When setting a bit outside of `self`, it is expanded. - #[corresponds(BN_set_bit)] - #[allow(clippy::useless_conversion)] - pub fn set_bit(&mut self, n: i32) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::BN_set_bit(self.as_ptr(), n.into())).map(|_| ()) } - } - - /// Clears bit `n`, setting it to 0. Equivalent to `self &= ~(1 << n)`. - /// - /// When clearing a bit outside of `self`, an error is returned. - #[corresponds(BN_clear_bit)] - #[allow(clippy::useless_conversion)] - pub fn clear_bit(&mut self, n: i32) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::BN_clear_bit(self.as_ptr(), n.into())).map(|_| ()) } - } - - /// Returns `true` if the `n`th bit of `self` is set to 1, `false` otherwise. - #[corresponds(BN_is_bit_set)] - #[allow(clippy::useless_conversion)] - pub fn is_bit_set(&self, n: i32) -> bool { - unsafe { ffi::BN_is_bit_set(self.as_ptr(), n.into()) == 1 } - } - - /// Truncates `self` to the lowest `n` bits. - /// - /// An error occurs if `self` is already shorter than `n` bits. - #[corresponds(BN_mask_bits)] - #[allow(clippy::useless_conversion)] - pub fn mask_bits(&mut self, n: i32) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::BN_mask_bits(self.as_ptr(), n.into())).map(|_| ()) } - } - - /// Places `a << 1` in `self`. Equivalent to `self * 2`. - #[corresponds(BN_lshift1)] - pub fn lshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::BN_lshift1(self.as_ptr(), a.as_ptr())).map(|_| ()) } - } - - /// Places `a >> 1` in `self`. Equivalent to `self / 2`. - #[corresponds(BN_rshift1)] - pub fn rshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::BN_rshift1(self.as_ptr(), a.as_ptr())).map(|_| ()) } - } - - /// Places `a + b` in `self`. [`core::ops::Add`] is also implemented for `BigNumRef`. - /// - /// [`core::ops::Add`]: struct.BigNumRef.html#method.add - #[corresponds(BN_add)] - pub fn checked_add(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::BN_add(self.as_ptr(), a.as_ptr(), b.as_ptr())).map(|_| ()) } - } - - /// Places `a - b` in `self`. [`core::ops::Sub`] is also implemented for `BigNumRef`. - /// - /// [`core::ops::Sub`]: struct.BigNumRef.html#method.sub - #[corresponds(BN_sub)] - pub fn checked_sub(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::BN_sub(self.as_ptr(), a.as_ptr(), b.as_ptr())).map(|_| ()) } - } - - /// Places `a << n` in `self`. Equivalent to `a * 2 ^ n`. - #[corresponds(BN_lshift)] - #[allow(clippy::useless_conversion)] - pub fn lshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::BN_lshift(self.as_ptr(), a.as_ptr(), n.into())).map(|_| ()) } - } - - /// Places `a >> n` in `self`. Equivalent to `a / 2 ^ n`. - #[corresponds(BN_rshift)] - #[allow(clippy::useless_conversion)] - pub fn rshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::BN_rshift(self.as_ptr(), a.as_ptr(), n.into())).map(|_| ()) } - } - - /// Creates a new BigNum with the same value. - #[corresponds(BN_dup)] - pub fn to_owned(&self) -> Result { - unsafe { cvt_p(ffi::BN_dup(self.as_ptr())).map(|b| BigNum::from_ptr(b)) } - } - - /// Sets the sign of `self`. Pass true to set `self` to a negative. False sets - /// `self` positive. - #[corresponds(BN_set_negative)] - pub fn set_negative(&mut self, negative: bool) { - unsafe { ffi::BN_set_negative(self.as_ptr(), negative as c_int) } - } - - /// Compare the absolute values of `self` and `oth`. - /// - /// # Examples - /// - /// ``` - /// # use openssl::bn::BigNum; - /// # use std::cmp::Ordering; - /// let s = -BigNum::from_u32(8).unwrap(); - /// let o = BigNum::from_u32(8).unwrap(); - /// - /// assert_eq!(s.ucmp(&o), Ordering::Equal); - /// ``` - #[corresponds(BN_ucmp)] - pub fn ucmp(&self, oth: &BigNumRef) -> Ordering { - unsafe { ffi::BN_ucmp(self.as_ptr(), oth.as_ptr()).cmp(&0) } - } - - /// Returns `true` if `self` is negative. - #[corresponds(BN_is_negative)] - pub fn is_negative(&self) -> bool { - unsafe { BN_is_negative(self.as_ptr()) == 1 } - } - - /// Returns `true` is `self` is even. - #[corresponds(BN_is_even)] - #[cfg(any(ossl110, boringssl, libressl, awslc))] - pub fn is_even(&self) -> bool { - !self.is_odd() - } - - /// Returns `true` is `self` is odd. - #[corresponds(BN_is_odd)] - #[cfg(any(ossl110, boringssl, libressl, awslc))] - pub fn is_odd(&self) -> bool { - unsafe { ffi::BN_is_odd(self.as_ptr()) == 1 } - } - - /// Returns the number of significant bits in `self`. - #[corresponds(BN_num_bits)] - #[allow(clippy::unnecessary_cast)] - pub fn num_bits(&self) -> i32 { - unsafe { ffi::BN_num_bits(self.as_ptr()) as i32 } - } - - /// Returns the size of `self` in bytes. Implemented natively. - pub fn num_bytes(&self) -> i32 { - (self.num_bits() + 7) / 8 - } - - /// Generates a cryptographically strong pseudo-random `BigNum`, placing it in `self`. - /// - /// # Parameters - /// - /// * `bits`: Length of the number in bits. - /// * `msb`: The desired properties of the most significant bit. See [`constants`]. - /// * `odd`: If `true`, the generated number will be odd. - /// - /// # Examples - /// - /// ``` - /// use openssl::bn::{BigNum, MsbOption}; - /// use openssl::error::ErrorStack; - /// - /// fn generate_random() -> Result< BigNum, ErrorStack > { - /// let mut big = BigNum::new()?; - /// - /// // Generates a 128-bit odd random number - /// big.rand(128, MsbOption::MAYBE_ZERO, true); - /// Ok((big)) - /// } - /// ``` - /// - /// [`constants`]: index.html#constants - #[corresponds(BN_rand)] - #[allow(clippy::useless_conversion)] - pub fn rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::BN_rand( - self.as_ptr(), - bits.into(), - msb.0, - odd as c_int, - )) - .map(|_| ()) - } - } - - /// The cryptographically weak counterpart to `rand`. Not suitable for key generation. - #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] - #[corresponds(BN_pseudo_rand)] - #[allow(clippy::useless_conversion)] - pub fn pseudo_rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::BN_pseudo_rand( - self.as_ptr(), - bits.into(), - msb.0, - odd as c_int, - )) - .map(|_| ()) - } - } - - /// Generates a prime number, placing it in `self`. - /// - /// # Parameters - /// - /// * `bits`: The length of the prime in bits (lower bound). - /// * `safe`: If true, returns a "safe" prime `p` so that `(p-1)/2` is also prime. - /// * `add`/`rem`: If `add` is set to `Some(add)`, `p % add == rem` will hold, where `p` is the - /// generated prime and `rem` is `1` if not specified (`None`). - /// - /// # Examples - /// - /// ``` - /// use openssl::bn::BigNum; - /// use openssl::error::ErrorStack; - /// - /// fn generate_weak_prime() -> Result< BigNum, ErrorStack > { - /// let mut big = BigNum::new()?; - /// - /// // Generates a 128-bit simple prime number - /// big.generate_prime(128, false, None, None); - /// Ok((big)) - /// } - /// ``` - #[corresponds(BN_generate_prime_ex)] - pub fn generate_prime( - &mut self, - bits: i32, - safe: bool, - add: Option<&BigNumRef>, - rem: Option<&BigNumRef>, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::BN_generate_prime_ex( - self.as_ptr(), - bits as c_int, - safe as c_int, - add.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()), - rem.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()), - ptr::null_mut(), - )) - .map(|_| ()) - } - } - - /// Places the result of `a * b` in `self`. - /// [`core::ops::Mul`] is also implemented for `BigNumRef`. - /// - /// [`core::ops::Mul`]: struct.BigNumRef.html#method.mul - #[corresponds(BN_mul)] - pub fn checked_mul( - &mut self, - a: &BigNumRef, - b: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::BN_mul( - self.as_ptr(), - a.as_ptr(), - b.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places the result of `a / b` in `self`. The remainder is discarded. - /// [`core::ops::Div`] is also implemented for `BigNumRef`. - /// - /// [`core::ops::Div`]: struct.BigNumRef.html#method.div - #[corresponds(BN_div)] - pub fn checked_div( - &mut self, - a: &BigNumRef, - b: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::BN_div( - self.as_ptr(), - ptr::null_mut(), - a.as_ptr(), - b.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places the result of `a % b` in `self`. - #[corresponds(BN_div)] - pub fn checked_rem( - &mut self, - a: &BigNumRef, - b: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::BN_div( - ptr::null_mut(), - self.as_ptr(), - a.as_ptr(), - b.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places the result of `a / b` in `self` and `a % b` in `rem`. - #[corresponds(BN_div)] - pub fn div_rem( - &mut self, - rem: &mut BigNumRef, - a: &BigNumRef, - b: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::BN_div( - self.as_ptr(), - rem.as_ptr(), - a.as_ptr(), - b.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places the result of `a²` in `self`. - #[corresponds(BN_sqr)] - pub fn sqr(&mut self, a: &BigNumRef, ctx: &mut BigNumContextRef) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::BN_sqr(self.as_ptr(), a.as_ptr(), ctx.as_ptr())).map(|_| ()) } - } - - /// Places the result of `a mod m` in `self`. As opposed to `div_rem` - /// the result is non-negative. - #[corresponds(BN_nnmod)] - pub fn nnmod( - &mut self, - a: &BigNumRef, - m: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::BN_nnmod( - self.as_ptr(), - a.as_ptr(), - m.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places the result of `(a + b) mod m` in `self`. - #[corresponds(BN_mod_add)] - pub fn mod_add( - &mut self, - a: &BigNumRef, - b: &BigNumRef, - m: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::BN_mod_add( - self.as_ptr(), - a.as_ptr(), - b.as_ptr(), - m.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places the result of `(a - b) mod m` in `self`. - #[corresponds(BN_mod_sub)] - pub fn mod_sub( - &mut self, - a: &BigNumRef, - b: &BigNumRef, - m: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::BN_mod_sub( - self.as_ptr(), - a.as_ptr(), - b.as_ptr(), - m.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places the result of `(a * b) mod m` in `self`. - #[corresponds(BN_mod_mul)] - pub fn mod_mul( - &mut self, - a: &BigNumRef, - b: &BigNumRef, - m: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::BN_mod_mul( - self.as_ptr(), - a.as_ptr(), - b.as_ptr(), - m.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places the result of `a² mod m` in `self`. - #[corresponds(BN_mod_sqr)] - pub fn mod_sqr( - &mut self, - a: &BigNumRef, - m: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::BN_mod_sqr( - self.as_ptr(), - a.as_ptr(), - m.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places into `self` the modular square root of `a` such that `self^2 = a (mod p)` - #[corresponds(BN_mod_sqrt)] - pub fn mod_sqrt( - &mut self, - a: &BigNumRef, - p: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt_p(ffi::BN_mod_sqrt( - self.as_ptr(), - a.as_ptr(), - p.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places the result of `a^p` in `self`. - #[corresponds(BN_exp)] - pub fn exp( - &mut self, - a: &BigNumRef, - p: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::BN_exp( - self.as_ptr(), - a.as_ptr(), - p.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places the result of `a^p mod m` in `self`. - #[corresponds(BN_mod_exp)] - pub fn mod_exp( - &mut self, - a: &BigNumRef, - p: &BigNumRef, - m: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::BN_mod_exp( - self.as_ptr(), - a.as_ptr(), - p.as_ptr(), - m.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places the inverse of `a` modulo `n` in `self`. - #[corresponds(BN_mod_inverse)] - pub fn mod_inverse( - &mut self, - a: &BigNumRef, - n: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt_p(ffi::BN_mod_inverse( - self.as_ptr(), - a.as_ptr(), - n.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places the greatest common denominator of `a` and `b` in `self`. - #[corresponds(BN_gcd)] - pub fn gcd( - &mut self, - a: &BigNumRef, - b: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::BN_gcd( - self.as_ptr(), - a.as_ptr(), - b.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Checks whether `self` is prime. - /// - /// Performs a Miller-Rabin probabilistic primality test with `checks` iterations. - /// - /// # Return Value - /// - /// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`. - #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] - #[corresponds(BN_is_prime_ex)] - #[allow(clippy::useless_conversion)] - pub fn is_prime(&self, checks: i32, ctx: &mut BigNumContextRef) -> Result { - unsafe { - cvt_n(ffi::BN_is_prime_ex( - self.as_ptr(), - checks.into(), - ctx.as_ptr(), - ptr::null_mut(), - )) - .map(|r| r != 0) - } - } - - /// Checks whether `self` is prime with optional trial division. - /// - /// If `do_trial_division` is `true`, first performs trial division by a number of small primes. - /// Then, like `is_prime`, performs a Miller-Rabin probabilistic primality test with `checks` - /// iterations. - /// - /// # Return Value - /// - /// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`. - #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] - #[corresponds(BN_is_prime_fasttest_ex)] - #[allow(clippy::useless_conversion)] - pub fn is_prime_fasttest( - &self, - checks: i32, - ctx: &mut BigNumContextRef, - do_trial_division: bool, - ) -> Result { - unsafe { - cvt_n(ffi::BN_is_prime_fasttest_ex( - self.as_ptr(), - checks.into(), - ctx.as_ptr(), - do_trial_division as c_int, - ptr::null_mut(), - )) - .map(|r| r != 0) - } - } - - /// Returns a big-endian byte vector representation of the absolute value of `self`. - /// - /// `self` can be recreated by using `from_slice`. - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let s = -BigNum::from_u32(4543).unwrap(); - /// let r = BigNum::from_u32(4543).unwrap(); - /// - /// let s_vec = s.to_vec(); - /// assert_eq!(BigNum::from_slice(&s_vec).unwrap(), r); - /// ``` - #[corresponds(BN_bn2bin)] - pub fn to_vec(&self) -> Vec { - let size = self.num_bytes() as usize; - let mut v = Vec::with_capacity(size); - unsafe { - ffi::BN_bn2bin(self.as_ptr(), v.as_mut_ptr()); - v.set_len(size); - } - v - } - - /// Returns a big-endian byte vector representation of the absolute value of `self` padded - /// to `pad_to` bytes. - /// - /// If `pad_to` is less than `self.num_bytes()` then an error is returned. - /// - /// `self` can be recreated by using `from_slice`. - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let bn = BigNum::from_u32(0x4543).unwrap(); - /// - /// let bn_vec = bn.to_vec_padded(4).unwrap(); - /// assert_eq!(&bn_vec, &[0, 0, 0x45, 0x43]); - /// - /// let r = bn.to_vec_padded(1); - /// assert!(r.is_err()); - /// - /// let bn = -BigNum::from_u32(0x4543).unwrap(); - /// let bn_vec = bn.to_vec_padded(4).unwrap(); - /// assert_eq!(&bn_vec, &[0, 0, 0x45, 0x43]); - /// ``` - #[corresponds(BN_bn2binpad)] - #[cfg(any(ossl110, libressl, boringssl, awslc))] - pub fn to_vec_padded(&self, pad_to: i32) -> Result, ErrorStack> { - let mut v = Vec::with_capacity(pad_to as usize); - unsafe { - cvt(ffi::BN_bn2binpad(self.as_ptr(), v.as_mut_ptr(), pad_to))?; - v.set_len(pad_to as usize); - } - Ok(v) - } - - /// Returns a decimal string representation of `self`. - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let s = -BigNum::from_u32(12345).unwrap(); - /// - /// assert_eq!(&**s.to_dec_str().unwrap(), "-12345"); - /// ``` - #[corresponds(BN_bn2dec)] - pub fn to_dec_str(&self) -> Result { - unsafe { - let buf = cvt_p(ffi::BN_bn2dec(self.as_ptr()))?; - Ok(OpensslString::from_ptr(buf)) - } - } - - /// Returns a hexadecimal string representation of `self`. - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let s = -BigNum::from_u32(0x99ff).unwrap(); - /// - /// assert_eq!(s.to_hex_str().unwrap().to_uppercase(), "-99FF"); - /// ``` - #[corresponds(BN_bn2hex)] - pub fn to_hex_str(&self) -> Result { - unsafe { - let buf = cvt_p(ffi::BN_bn2hex(self.as_ptr()))?; - Ok(OpensslString::from_ptr(buf)) - } - } - - /// Returns an `Asn1Integer` containing the value of `self`. - #[corresponds(BN_to_ASN1_INTEGER)] - pub fn to_asn1_integer(&self) -> Result { - unsafe { - cvt_p(ffi::BN_to_ASN1_INTEGER(self.as_ptr(), ptr::null_mut())) - .map(|p| Asn1Integer::from_ptr(p)) - } - } - - /// Force constant time computation on this value. - #[corresponds(BN_set_flags)] - #[cfg(ossl110)] - pub fn set_const_time(&mut self) { - unsafe { ffi::BN_set_flags(self.as_ptr(), ffi::BN_FLG_CONSTTIME) } - } - - /// Returns true if `self` is in const time mode. - #[corresponds(BN_get_flags)] - #[cfg(ossl110)] - pub fn is_const_time(&self) -> bool { - unsafe { - let ret = ffi::BN_get_flags(self.as_ptr(), ffi::BN_FLG_CONSTTIME); - ret == ffi::BN_FLG_CONSTTIME - } - } - - /// Returns true if `self` was created with [`BigNum::new_secure`]. - #[corresponds(BN_get_flags)] - #[cfg(ossl110)] - pub fn is_secure(&self) -> bool { - unsafe { - let ret = ffi::BN_get_flags(self.as_ptr(), ffi::BN_FLG_SECURE); - ret == ffi::BN_FLG_SECURE - } - } -} - -impl BigNum { - /// Creates a new `BigNum` with the value 0. - #[corresponds(BN_new)] - pub fn new() -> Result { - unsafe { - ffi::init(); - let v = cvt_p(ffi::BN_new())?; - Ok(BigNum::from_ptr(v)) - } - } - - /// Returns a new secure `BigNum`. - #[corresponds(BN_secure_new)] - #[cfg(ossl110)] - pub fn new_secure() -> Result { - unsafe { - ffi::init(); - let v = cvt_p(ffi::BN_secure_new())?; - Ok(BigNum::from_ptr(v)) - } - } - - /// Creates a new `BigNum` with the given value. - #[corresponds(BN_set_word)] - pub fn from_u32(n: u32) -> Result { - BigNum::new().and_then(|v| unsafe { - cvt(ffi::BN_set_word(v.as_ptr(), n as ffi::BN_ULONG)).map(|_| v) - }) - } - - /// Creates a `BigNum` from a decimal string. - #[corresponds(BN_dec2bn)] - pub fn from_dec_str(s: &str) -> Result { - unsafe { - ffi::init(); - let c_str = CString::new(s.as_bytes()).unwrap(); - let mut bn = ptr::null_mut(); - cvt(ffi::BN_dec2bn(&mut bn, c_str.as_ptr() as *const _))?; - Ok(BigNum::from_ptr(bn)) - } - } - - /// Creates a `BigNum` from a hexadecimal string. - #[corresponds(BN_hex2bn)] - pub fn from_hex_str(s: &str) -> Result { - unsafe { - ffi::init(); - let c_str = CString::new(s.as_bytes()).unwrap(); - let mut bn = ptr::null_mut(); - cvt(ffi::BN_hex2bn(&mut bn, c_str.as_ptr() as *const _))?; - Ok(BigNum::from_ptr(bn)) - } - } - - /// Returns a constant used in IKE as defined in [`RFC 2409`]. This prime number is in - /// the order of magnitude of `2 ^ 768`. This number is used during calculated key - /// exchanges such as Diffie-Hellman. This number is labeled Oakley group id 1. - /// - /// [`RFC 2409`]: https://tools.ietf.org/html/rfc2409#page-21 - #[corresponds(BN_get_rfc2409_prime_768)] - #[cfg(not(any(boringssl, awslc)))] - pub fn get_rfc2409_prime_768() -> Result { - unsafe { - ffi::init(); - cvt_p(BN_get_rfc2409_prime_768(ptr::null_mut())).map(BigNum) - } - } - - /// Returns a constant used in IKE as defined in [`RFC 2409`]. This prime number is in - /// the order of magnitude of `2 ^ 1024`. This number is used during calculated key - /// exchanges such as Diffie-Hellman. This number is labeled Oakly group 2. - /// - /// [`RFC 2409`]: https://tools.ietf.org/html/rfc2409#page-21 - #[corresponds(BN_get_rfc2409_prime_1024)] - #[cfg(not(any(boringssl, awslc)))] - pub fn get_rfc2409_prime_1024() -> Result { - unsafe { - ffi::init(); - cvt_p(BN_get_rfc2409_prime_1024(ptr::null_mut())).map(BigNum) - } - } - - /// Returns a constant used in IKE as defined in [`RFC 3526`]. The prime is in the order - /// of magnitude of `2 ^ 1536`. This number is used during calculated key - /// exchanges such as Diffie-Hellman. This number is labeled MODP group 5. - /// - /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-3 - #[corresponds(BN_get_rfc3526_prime_1536)] - #[cfg(not(boringssl))] - pub fn get_rfc3526_prime_1536() -> Result { - unsafe { - ffi::init(); - cvt_p(BN_get_rfc3526_prime_1536(ptr::null_mut())).map(BigNum) - } - } - - /// Returns a constant used in IKE as defined in [`RFC 3526`]. The prime is in the order - /// of magnitude of `2 ^ 2048`. This number is used during calculated key - /// exchanges such as Diffie-Hellman. This number is labeled MODP group 14. - /// - /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-3 - #[corresponds(BN_get_rfc3526_prime_2048)] - #[cfg(not(boringssl))] - pub fn get_rfc3526_prime_2048() -> Result { - unsafe { - ffi::init(); - cvt_p(BN_get_rfc3526_prime_2048(ptr::null_mut())).map(BigNum) - } - } - - /// Returns a constant used in IKE as defined in [`RFC 3526`]. The prime is in the order - /// of magnitude of `2 ^ 3072`. This number is used during calculated key - /// exchanges such as Diffie-Hellman. This number is labeled MODP group 15. - /// - /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-4 - #[corresponds(BN_get_rfc3526_prime_3072)] - #[cfg(not(boringssl))] - pub fn get_rfc3526_prime_3072() -> Result { - unsafe { - ffi::init(); - cvt_p(BN_get_rfc3526_prime_3072(ptr::null_mut())).map(BigNum) - } - } - - /// Returns a constant used in IKE as defined in [`RFC 3526`]. The prime is in the order - /// of magnitude of `2 ^ 4096`. This number is used during calculated key - /// exchanges such as Diffie-Hellman. This number is labeled MODP group 16. - /// - /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-4 - #[corresponds(BN_get_rfc3526_prime_4096)] - #[cfg(not(boringssl))] - pub fn get_rfc3526_prime_4096() -> Result { - unsafe { - ffi::init(); - cvt_p(BN_get_rfc3526_prime_4096(ptr::null_mut())).map(BigNum) - } - } - - /// Returns a constant used in IKE as defined in [`RFC 3526`]. The prime is in the order - /// of magnitude of `2 ^ 6144`. This number is used during calculated key - /// exchanges such as Diffie-Hellman. This number is labeled MODP group 17. - /// - /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-6 - #[corresponds(BN_get_rfc3526_prime_6114)] - #[cfg(not(boringssl))] - pub fn get_rfc3526_prime_6144() -> Result { - unsafe { - ffi::init(); - cvt_p(BN_get_rfc3526_prime_6144(ptr::null_mut())).map(BigNum) - } - } - - /// Returns a constant used in IKE as defined in [`RFC 3526`]. The prime is in the order - /// of magnitude of `2 ^ 8192`. This number is used during calculated key - /// exchanges such as Diffie-Hellman. This number is labeled MODP group 18. - /// - /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-6 - #[corresponds(BN_get_rfc3526_prime_8192)] - #[cfg(not(boringssl))] - pub fn get_rfc3526_prime_8192() -> Result { - unsafe { - ffi::init(); - cvt_p(BN_get_rfc3526_prime_8192(ptr::null_mut())).map(BigNum) - } - } - - /// Creates a new `BigNum` from an unsigned, big-endian encoded number of arbitrary length. - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let bignum = BigNum::from_slice(&[0x12, 0x00, 0x34]).unwrap(); - /// - /// assert_eq!(bignum, BigNum::from_u32(0x120034).unwrap()); - /// ``` - #[corresponds(BN_bin2bn)] - pub fn from_slice(n: &[u8]) -> Result { - unsafe { - ffi::init(); - assert!(n.len() <= LenType::MAX as usize); - - cvt_p(ffi::BN_bin2bn( - n.as_ptr(), - n.len() as LenType, - ptr::null_mut(), - )) - .map(|p| BigNum::from_ptr(p)) - } - } - - /// Copies data from a slice overwriting what was in the BigNum. - /// - /// This function can be used to copy data from a slice to a - /// [secure BigNum][`BigNum::new_secure`]. - /// - /// # Examples - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let mut bignum = BigNum::new().unwrap(); - /// bignum.copy_from_slice(&[0x12, 0x00, 0x34]).unwrap(); - /// - /// assert_eq!(bignum, BigNum::from_u32(0x120034).unwrap()); - /// ``` - #[corresponds(BN_bin2bn)] - pub fn copy_from_slice(&mut self, n: &[u8]) -> Result<(), ErrorStack> { - unsafe { - assert!(n.len() <= LenType::MAX as usize); - - cvt_p(ffi::BN_bin2bn(n.as_ptr(), n.len() as LenType, self.0))?; - Ok(()) - } - } -} - -impl fmt::Debug for BigNumRef { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.to_dec_str() { - Ok(s) => f.write_str(&s), - Err(e) => Err(e.into()), - } - } -} - -impl fmt::Debug for BigNum { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.to_dec_str() { - Ok(s) => f.write_str(&s), - Err(e) => Err(e.into()), - } - } -} - -impl fmt::Display for BigNumRef { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.to_dec_str() { - Ok(s) => f.write_str(&s), - Err(e) => Err(e.into()), - } - } -} - -impl fmt::Display for BigNum { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.to_dec_str() { - Ok(s) => f.write_str(&s), - Err(e) => Err(e.into()), - } - } -} - -impl PartialEq for BigNumRef { - fn eq(&self, oth: &BigNumRef) -> bool { - self.cmp(oth) == Ordering::Equal - } -} - -impl PartialEq for BigNumRef { - fn eq(&self, oth: &BigNum) -> bool { - self.eq(oth.deref()) - } -} - -impl Eq for BigNumRef {} - -impl PartialEq for BigNum { - fn eq(&self, oth: &BigNum) -> bool { - self.deref().eq(oth) - } -} - -impl PartialEq for BigNum { - fn eq(&self, oth: &BigNumRef) -> bool { - self.deref().eq(oth) - } -} - -impl Eq for BigNum {} - -impl PartialOrd for BigNumRef { - fn partial_cmp(&self, oth: &BigNumRef) -> Option { - Some(self.cmp(oth)) - } -} - -impl PartialOrd for BigNumRef { - fn partial_cmp(&self, oth: &BigNum) -> Option { - Some(self.cmp(oth.deref())) - } -} - -impl Ord for BigNumRef { - fn cmp(&self, oth: &BigNumRef) -> Ordering { - unsafe { ffi::BN_cmp(self.as_ptr(), oth.as_ptr()).cmp(&0) } - } -} - -impl PartialOrd for BigNum { - fn partial_cmp(&self, oth: &BigNum) -> Option { - Some(self.cmp(oth)) - } -} - -impl PartialOrd for BigNum { - fn partial_cmp(&self, oth: &BigNumRef) -> Option { - self.deref().partial_cmp(oth) - } -} - -impl Ord for BigNum { - fn cmp(&self, oth: &BigNum) -> Ordering { - self.deref().cmp(oth.deref()) - } -} - -macro_rules! delegate { - ($t:ident, $m:ident) => { - impl<'a, 'b> $t<&'b BigNum> for &'a BigNumRef { - type Output = BigNum; - - fn $m(self, oth: &BigNum) -> BigNum { - $t::$m(self, oth.deref()) - } - } - - impl<'a, 'b> $t<&'b BigNumRef> for &'a BigNum { - type Output = BigNum; - - fn $m(self, oth: &BigNumRef) -> BigNum { - $t::$m(self.deref(), oth) - } - } - - impl<'a, 'b> $t<&'b BigNum> for &'a BigNum { - type Output = BigNum; - - fn $m(self, oth: &BigNum) -> BigNum { - $t::$m(self.deref(), oth.deref()) - } - } - }; -} - -impl Add<&BigNumRef> for &BigNumRef { - type Output = BigNum; - - fn add(self, oth: &BigNumRef) -> BigNum { - let mut r = BigNum::new().unwrap(); - r.checked_add(self, oth).unwrap(); - r - } -} - -delegate!(Add, add); - -impl Sub<&BigNumRef> for &BigNumRef { - type Output = BigNum; - - fn sub(self, oth: &BigNumRef) -> BigNum { - let mut r = BigNum::new().unwrap(); - r.checked_sub(self, oth).unwrap(); - r - } -} - -delegate!(Sub, sub); - -impl Mul<&BigNumRef> for &BigNumRef { - type Output = BigNum; - - fn mul(self, oth: &BigNumRef) -> BigNum { - let mut ctx = BigNumContext::new().unwrap(); - let mut r = BigNum::new().unwrap(); - r.checked_mul(self, oth, &mut ctx).unwrap(); - r - } -} - -delegate!(Mul, mul); - -impl<'b> Div<&'b BigNumRef> for &BigNumRef { - type Output = BigNum; - - fn div(self, oth: &'b BigNumRef) -> BigNum { - let mut ctx = BigNumContext::new().unwrap(); - let mut r = BigNum::new().unwrap(); - r.checked_div(self, oth, &mut ctx).unwrap(); - r - } -} - -delegate!(Div, div); - -impl<'b> Rem<&'b BigNumRef> for &BigNumRef { - type Output = BigNum; - - fn rem(self, oth: &'b BigNumRef) -> BigNum { - let mut ctx = BigNumContext::new().unwrap(); - let mut r = BigNum::new().unwrap(); - r.checked_rem(self, oth, &mut ctx).unwrap(); - r - } -} - -delegate!(Rem, rem); - -impl Shl for &BigNumRef { - type Output = BigNum; - - fn shl(self, n: i32) -> BigNum { - let mut r = BigNum::new().unwrap(); - r.lshift(self, n).unwrap(); - r - } -} - -impl Shl for &BigNum { - type Output = BigNum; - - fn shl(self, n: i32) -> BigNum { - self.deref().shl(n) - } -} - -impl Shr for &BigNumRef { - type Output = BigNum; - - fn shr(self, n: i32) -> BigNum { - let mut r = BigNum::new().unwrap(); - r.rshift(self, n).unwrap(); - r - } -} - -impl Shr for &BigNum { - type Output = BigNum; - - fn shr(self, n: i32) -> BigNum { - self.deref().shr(n) - } -} - -impl Neg for &BigNumRef { - type Output = BigNum; - - fn neg(self) -> BigNum { - self.to_owned().unwrap().neg() - } -} - -impl Neg for &BigNum { - type Output = BigNum; - - fn neg(self) -> BigNum { - self.deref().neg() - } -} - -impl Neg for BigNum { - type Output = BigNum; - - fn neg(mut self) -> BigNum { - let negative = self.is_negative(); - self.set_negative(!negative); - self - } -} - -#[cfg(test)] -mod tests { - use crate::bn::{BigNum, BigNumContext}; - - #[test] - fn test_to_from_slice() { - let v0 = BigNum::from_u32(10_203_004).unwrap(); - let vec = v0.to_vec(); - let v1 = BigNum::from_slice(&vec).unwrap(); - - assert_eq!(v0, v1); - } - - #[test] - fn test_negation() { - let a = BigNum::from_u32(909_829_283).unwrap(); - - assert!(!a.is_negative()); - assert!((-a).is_negative()); - } - - #[test] - fn test_shift() { - let a = BigNum::from_u32(909_829_283).unwrap(); - - assert_eq!(a, &(&a << 1) >> 1); - } - - #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] - #[test] - fn test_rand_range() { - let range = BigNum::from_u32(909_829_283).unwrap(); - let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap(); - range.rand_range(&mut result).unwrap(); - assert!(result >= BigNum::from_u32(0).unwrap() && result < range); - } - - #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] - #[test] - fn test_pseudo_rand_range() { - let range = BigNum::from_u32(909_829_283).unwrap(); - let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap(); - range.pseudo_rand_range(&mut result).unwrap(); - assert!(result >= BigNum::from_u32(0).unwrap() && result < range); - } - - #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] - #[test] - fn test_prime_numbers() { - let a = BigNum::from_u32(19_029_017).unwrap(); - let mut p = BigNum::new().unwrap(); - p.generate_prime(128, true, None, Some(&a)).unwrap(); - - let mut ctx = BigNumContext::new().unwrap(); - assert!(p.is_prime(100, &mut ctx).unwrap()); - assert!(p.is_prime_fasttest(100, &mut ctx, true).unwrap()); - } - - #[cfg(ossl110)] - #[test] - fn test_secure_bn_ctx() { - let mut cxt = BigNumContext::new_secure().unwrap(); - let a = BigNum::from_u32(8).unwrap(); - let b = BigNum::from_u32(3).unwrap(); - - let mut remainder = BigNum::new().unwrap(); - remainder.nnmod(&a, &b, &mut cxt).unwrap(); - - assert!(remainder.eq(&BigNum::from_u32(2).unwrap())); - } - - #[cfg(ossl110)] - #[test] - fn test_secure_bn() { - let a = BigNum::new().unwrap(); - assert!(!a.is_secure()); - - let b = BigNum::new_secure().unwrap(); - assert!(b.is_secure()) - } - - #[cfg(ossl110)] - #[test] - fn test_const_time_bn() { - let a = BigNum::new().unwrap(); - assert!(!a.is_const_time()); - - let mut b = BigNum::new().unwrap(); - b.set_const_time(); - assert!(b.is_const_time()) - } - - #[test] - fn test_mod_sqrt() { - let mut ctx = BigNumContext::new().unwrap(); - - let s = BigNum::from_hex_str("2").unwrap(); - let p = BigNum::from_hex_str("7DEB1").unwrap(); - let mut sqrt = BigNum::new().unwrap(); - let mut out = BigNum::new().unwrap(); - - // Square the root because OpenSSL randomly returns one of 2E42C or 4FA85 - sqrt.mod_sqrt(&s, &p, &mut ctx).unwrap(); - out.mod_sqr(&sqrt, &p, &mut ctx).unwrap(); - assert!(out == s); - - let s = BigNum::from_hex_str("3").unwrap(); - let p = BigNum::from_hex_str("5").unwrap(); - assert!(out.mod_sqrt(&s, &p, &mut ctx).is_err()); - } - - #[test] - #[cfg(any(ossl110, boringssl, libressl, awslc))] - fn test_odd_even() { - let a = BigNum::from_u32(17).unwrap(); - let b = BigNum::from_u32(18).unwrap(); - - assert!(a.is_odd()); - assert!(!b.is_odd()); - - assert!(!a.is_even()); - assert!(b.is_even()); - } -} diff --git a/patch/openssl/src/cipher.rs b/patch/openssl/src/cipher.rs deleted file mode 100644 index 6c6d271ead769..0000000000000 --- a/patch/openssl/src/cipher.rs +++ /dev/null @@ -1,611 +0,0 @@ -//! 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; -use std::ops::{Deref, DerefMut}; -#[cfg(ossl300)] -use std::ptr; - -cfg_if! { - if #[cfg(any(boringssl, ossl110, libressl, awslc))] { - 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; - - 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 {} - - impl Deref for Cipher { - type Target = CipherRef; - - #[inline] - fn deref(&self) -> &Self::Target { - match self.0 {} - } - } - - impl DerefMut for Cipher { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - match self.0 {} - } - } - } -} - -/// 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 { - 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.as_ref().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 _) } - } - - #[cfg(not(any(boringssl, awslc)))] - pub fn aes_128_xts() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_xts() as *mut _) } - } - - #[cfg(not(boringssl))] - pub fn aes_256_xts() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_xts() as *mut _) } - } - - pub fn aes_128_ctr() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ctr() as *mut _) } - } - - #[cfg(not(boringssl))] - pub fn aes_128_cfb1() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb1() as *mut _) } - } - - #[cfg(not(boringssl))] - pub fn aes_128_cfb128() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb128() as *mut _) } - } - - #[cfg(not(boringssl))] - 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 _) } - } - - #[cfg(not(boringssl))] - 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(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))] - pub fn aes_128_ocb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ocb() as *mut _) } - } - - /// Requires OpenSSL 1.0.2 or newer. - #[cfg(ossl102)] - pub fn aes_128_wrap() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_wrap() as *mut _) } - } - - /// Requires OpenSSL 1.1.0 or newer. - #[cfg(ossl110)] - pub fn aes_128_wrap_pad() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_wrap_pad() 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 _) } - } - - #[cfg(not(boringssl))] - pub fn aes_192_cfb1() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb1() as *mut _) } - } - - #[cfg(not(boringssl))] - pub fn aes_192_cfb128() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb128() as *mut _) } - } - - #[cfg(not(boringssl))] - 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 _) } - } - - #[cfg(not(boringssl))] - 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(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))] - pub fn aes_192_ocb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ocb() as *mut _) } - } - - /// Requires OpenSSL 1.0.2 or newer. - #[cfg(ossl102)] - pub fn aes_192_wrap() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_wrap() as *mut _) } - } - - /// Requires OpenSSL 1.1.0 or newer. - #[cfg(ossl110)] - pub fn aes_192_wrap_pad() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_wrap_pad() 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 _) } - } - - #[cfg(not(boringssl))] - pub fn aes_256_cfb1() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb1() as *mut _) } - } - - #[cfg(not(boringssl))] - pub fn aes_256_cfb128() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb128() as *mut _) } - } - - #[cfg(not(boringssl))] - 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 _) } - } - - #[cfg(not(boringssl))] - 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(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))] - pub fn aes_256_ocb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ocb() as *mut _) } - } - - /// Requires OpenSSL 1.0.2 or newer. - #[cfg(ossl102)] - pub fn aes_256_wrap() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_wrap() as *mut _) } - } - - /// Requires OpenSSL 1.1.0 or newer. - #[cfg(ossl110)] - pub fn aes_256_wrap_pad() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_wrap_pad() 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_ecb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_ecb() as *mut _) } - } - - pub fn des_ede3_cbc() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cbc() as *mut _) } - } - - #[cfg(not(any(boringssl, awslc)))] - pub fn des_ede3_cfb8() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cfb8() as *mut _) } - } - - #[cfg(not(any(boringssl, awslc)))] - pub fn des_ede3_cfb64() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cfb64() as *mut _) } - } - - #[cfg(not(any(boringssl, awslc)))] - pub fn des_ede3_ofb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_ofb() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_RC4"))] - pub fn rc4() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_rc4() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia128_cfb128() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_camellia_128_cfb128() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia128_ecb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_camellia_128_ecb() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia128_cbc() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_camellia_128_cbc() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia128_ofb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_camellia_128_ofb() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia192_cfb128() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_camellia_192_cfb128() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia192_ecb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_camellia_192_ecb() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia192_cbc() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_camellia_192_cbc() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia192_ofb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_camellia_192_ofb() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia256_cfb128() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_camellia_256_cfb128() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia256_ecb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_camellia_256_ecb() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia256_cbc() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_camellia_256_cbc() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia256_ofb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_camellia_256_ofb() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAST"))] - pub fn cast5_cfb64() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_cast5_cfb64() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAST"))] - pub fn cast5_ecb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_cast5_ecb() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAST"))] - pub fn cast5_cbc() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_cast5_cbc() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAST"))] - pub fn cast5_ofb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_cast5_ofb() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))] - pub fn idea_cfb64() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_idea_cfb64() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))] - pub fn idea_ecb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_idea_ecb() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))] - pub fn idea_cbc() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_idea_cbc() as *mut _) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))] - pub fn idea_ofb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_idea_ofb() as *mut _) } - } - - #[cfg(all(any(ossl110, libressl), not(osslconf = "OPENSSL_NO_CHACHA")))] - pub fn chacha20() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_chacha20() as *mut _) } - } - - #[cfg(all(any(ossl110, libressl360, awslc), 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 _) } - } - - #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))] - pub fn sm4_ecb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_sm4_ecb() as *mut _) } - } - - #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))] - pub fn sm4_cbc() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_sm4_cbc() as *mut _) } - } - - #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))] - pub fn sm4_ctr() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_sm4_ctr() as *mut _) } - } - - #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))] - pub fn sm4_cfb128() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_sm4_cfb128() as *mut _) } - } - - #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))] - pub fn sm4_ofb() -> &'static CipherRef { - unsafe { CipherRef::from_ptr(ffi::EVP_sm4_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 } - } -} - -#[cfg(test)] -mod test { - #[cfg(ossl300)] - use super::Cipher; - - #[test] - #[cfg(ossl300)] - fn test_cipher_fetch_properties() { - assert!(Cipher::fetch(None, "AES-128-GCM", Some("provider=gibberish")).is_err()); - } -} diff --git a/patch/openssl/src/cipher_ctx.rs b/patch/openssl/src/cipher_ctx.rs deleted file mode 100644 index dc8887239caf3..0000000000000 --- a/patch/openssl/src/cipher_ctx.rs +++ /dev/null @@ -1,1271 +0,0 @@ -//! 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; -#[cfg(not(any(boringssl, awslc)))] -use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef}; -use crate::{cvt, cvt_p}; -#[cfg(ossl102)] -use bitflags::bitflags; -use cfg_if::cfg_if; -use foreign_types::{ForeignType, ForeignTypeRef}; -use libc::{c_int, c_uchar}; -use openssl_macros::corresponds; -use std::convert::{TryFrom, TryInto}; -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; -} - -#[cfg(ossl102)] -bitflags! { - /// Flags for `EVP_CIPHER_CTX`. - pub struct CipherCtxFlags : c_int { - /// The flag used to opt into AES key wrap ciphers. - const FLAG_WRAP_ALLOW = ffi::EVP_CIPHER_CTX_FLAG_WRAP_ALLOW; - } -} - -impl CipherCtx { - /// Creates a new context. - #[corresponds(EVP_CIPHER_CTX_new)] - pub fn new() -> Result { - ffi::init(); - - unsafe { - let ptr = cvt_p(ffi::EVP_CIPHER_CTX_new())?; - Ok(CipherCtx::from_ptr(ptr)) - } - } -} - -impl CipherCtxRef { - #[corresponds(EVP_CIPHER_CTX_copy)] - pub fn copy(&mut self, src: &CipherCtxRef) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EVP_CIPHER_CTX_copy(self.as_ptr(), src.as_ptr()))?; - Ok(()) - } - } - - /// 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)] - #[cfg(not(any(boringssl, awslc)))] - pub fn seal_init( - &mut self, - type_: Option<&CipherRef>, - pub_keys: &[PKey], - encrypted_keys: &mut [Vec], - 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::>(); - 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)] - #[cfg(not(any(boringssl, awslc)))] - pub fn open_init( - &mut self, - type_: Option<&CipherRef>, - encrypted_key: &[u8], - iv: Option<&[u8]>, - priv_key: Option<&PKeyRef>, - ) -> 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. - #[corresponds(EVP_CIPHER_CTX_rand_key)] - #[cfg(not(any(boringssl, awslc)))] - 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(); - - unsafe { - cvt(ffi::EVP_CIPHER_CTX_set_key_length( - self.as_ptr(), - len.try_into().unwrap(), - ))?; - } - - 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 } - } - - /// Returns the `num` parameter of the cipher. - /// - /// Built-in ciphers typically use this to track how much of the - /// current underlying block has been "used" already. - /// - /// # Panics - /// - /// Panics if the context has not been initialized with a cipher. - #[corresponds(EVP_CIPHER_CTX_num)] - #[cfg(ossl110)] - pub fn num(&self) -> usize { - self.assert_cipher(); - - unsafe { ffi::EVP_CIPHER_CTX_num(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_CIPHER_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(()) - } - - /// Set ctx flags. - /// - /// This function is currently used to enable AES key wrap feature supported by OpenSSL 1.0.2 or newer. - #[corresponds(EVP_CIPHER_CTX_set_flags)] - #[cfg(ossl102)] - pub fn set_flags(&mut self, flags: CipherCtxFlags) { - unsafe { - ffi::EVP_CIPHER_CTX_set_flags(self.as_ptr(), flags.bits()); - } - } - - /// 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` doesn't contain enough space for data to be - /// written. - #[corresponds(EVP_CipherUpdate)] - pub fn cipher_update( - &mut self, - input: &[u8], - output: Option<&mut [u8]>, - ) -> Result { - if let Some(output) = &output { - let mut block_size = self.block_size(); - if block_size == 1 { - block_size = 0; - } - let min_output_size = input.len() + block_size; - assert!( - output.len() >= min_output_size, - "Output buffer size should be at least {} bytes.", - min_output_size - ); - } - - unsafe { self.cipher_update_unchecked(input, output) } - } - - /// 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`. - /// - /// This function is the same as [`Self::cipher_update`] but with the - /// output size check removed. It can be used when the exact - /// buffer size control is maintained by the caller. - /// - /// # Safety - /// - /// The caller is expected to provide `output` buffer - /// large enough to contain correct number of bytes. For streaming - /// ciphers the output buffer size should be at least as big as - /// the input buffer. For block ciphers the size of the output - /// buffer depends on the state of partially updated blocks. - #[corresponds(EVP_CipherUpdate)] - pub unsafe fn cipher_update_unchecked( - &mut self, - input: &[u8], - output: Option<&mut [u8]>, - ) -> Result { - let inlen = c_int::try_from(input.len()).unwrap(); - - let mut outlen = 0; - - 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, - ) -> Result { - 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) - } - - /// Like [`Self::cipher_update`] except that it writes output into the - /// `data` buffer. The `inlen` parameter specifies the number of bytes in - /// `data` that are considered the input. For streaming ciphers, the size of - /// `data` must be at least the input size. Otherwise, it must be at least - /// an additional block size larger. - /// - /// Note: Use [`Self::cipher_update`] with no output argument to write AAD. - /// - /// # Panics - /// - /// This function panics if the input size cannot be represented as `int` or - /// exceeds the buffer size, or if the output buffer does not contain enough - /// additional space. - #[corresponds(EVP_CipherUpdate)] - pub fn cipher_update_inplace( - &mut self, - data: &mut [u8], - inlen: usize, - ) -> Result { - assert!(inlen <= data.len(), "Input size may not exceed buffer size"); - let block_size = self.block_size(); - if block_size != 1 { - assert!( - data.len() >= inlen + block_size, - "Output buffer size must be at least {} bytes.", - inlen + block_size - ); - } - - let inlen = c_int::try_from(inlen).unwrap(); - let mut outlen = 0; - unsafe { - cvt(ffi::EVP_CipherUpdate( - self.as_ptr(), - data.as_mut_ptr(), - &mut outlen, - data.as_ptr(), - inlen, - )) - }?; - - Ok(outlen as usize) - } - - /// 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 { - let block_size = self.block_size(); - if block_size > 1 { - assert!(output.len() >= block_size); - } - - unsafe { self.cipher_final_unchecked(output) } - } - - /// Finalizes the encryption or decryption process. - /// - /// Any remaining data will be written to the output buffer. - /// - /// Returns the number of bytes written to `output`. - /// - /// This function is the same as [`Self::cipher_final`] but with - /// the output buffer size check removed. - /// - /// # Safety - /// - /// The caller is expected to provide `output` buffer - /// large enough to contain correct number of bytes. For streaming - /// ciphers the output buffer can be empty, for block ciphers the - /// output buffer should be at least as big as the block. - #[corresponds(EVP_CipherFinal)] - pub unsafe fn cipher_final_unchecked( - &mut self, - output: &mut [u8], - ) -> Result { - let mut outl = 0; - - 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) -> Result { - 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, rand::rand_bytes}; - #[cfg(not(any(boringssl, awslc)))] - use std::slice; - - #[test] - #[cfg(not(any(boringssl, awslc)))] - 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); - } - - #[cfg(not(boringssl))] - #[test] - fn default_aes_128_ccm() { - // from https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/mac/ccmtestvectors.zip - let cipher = Cipher::aes_128_ccm(); - aes_ccm( - cipher, - "26511fb51fcfa75cb4b44da75a6e5a0e", - "ea98ec44f5a86715014783172e", - "4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10", - "e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810", - "1bf0ba0ebb20d8edba59f29a9371750c9c714078f73c335d", - "2f1322ac69b848b001476323aed84c47", - ); - } - - #[cfg(not(boringssl))] - #[test] - fn default_aes_192_ccm() { - // from https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/mac/ccmtestvectors.zip - let cipher = Cipher::aes_192_ccm(); - aes_ccm( - cipher, - "26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886", - "ea98ec44f5a86715014783172e", - "4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10", - "e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810", - "30c154c616946eccc2e241d336ad33720953e449a0e6b0f0", - "dbf8e9464909bdf337e48093c082a10b", - ); - } - - #[cfg(not(boringssl))] - #[test] - fn default_aes_256_ccm() { - // from https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/mac/ccmtestvectors.zip - let cipher = Cipher::aes_256_ccm(); - aes_ccm( - cipher, - "314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e", - "3542fbe0f59a6d5f3abf619b7d", - "c5b3d71312ea14f2f8fae5bd1a453192b6604a45db75c5ed", - "dd4531f158a2fa3bc8a339f770595048f4a42bc1b03f2e824efc6ba4985119d8", - "39c2e8f6edfe663b90963b98eb79e2d4f7f28a5053ae8881", - "567a6b4426f1667136bed4a5e32a2bc1", - ); - } - - #[cfg(not(boringssl))] - fn aes_ccm( - cipher: &CipherRef, - key: &'static str, - iv: &'static str, - pt: &'static str, - aad: &'static str, - ct: &'static str, - tag: &'static str, - ) { - let key = hex::decode(key).unwrap(); - let iv = hex::decode(iv).unwrap(); - let pt = hex::decode(pt).unwrap(); - let ct = hex::decode(ct).unwrap(); - let aad = hex::decode(aad).unwrap(); - let tag = hex::decode(tag).unwrap(); - - let mut ctx = CipherCtx::new().unwrap(); - - ctx.encrypt_init(Some(cipher), None, None).unwrap(); - ctx.set_iv_length(iv.len()).unwrap(); - ctx.set_tag_length(tag.len()).unwrap(); - ctx.encrypt_init(None, Some(&key), Some(&iv)).unwrap(); - ctx.set_data_len(pt.len()).unwrap(); - - let mut buf = vec![]; - ctx.cipher_update(&aad, None).unwrap(); - ctx.cipher_update_vec(&pt, &mut buf).unwrap(); - ctx.cipher_final_vec(&mut buf).unwrap(); - assert_eq!(buf, ct); - - let mut out_tag = vec![0u8; tag.len()]; - ctx.tag(&mut out_tag).unwrap(); - assert_eq!(tag, out_tag); - - ctx.decrypt_init(Some(cipher), None, None).unwrap(); - ctx.set_iv_length(iv.len()).unwrap(); - ctx.set_tag(&tag).unwrap(); - ctx.decrypt_init(None, Some(&key), Some(&iv)).unwrap(); - ctx.set_data_len(pt.len()).unwrap(); - - let mut buf = vec![]; - ctx.cipher_update(&aad, None).unwrap(); - ctx.cipher_update_vec(&ct, &mut buf).unwrap(); - // Some older libraries don't support calling EVP_CipherFinal/EVP_DecryptFinal for CCM - // https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption#Authenticated_Decryption_using_CCM_mode - #[cfg(any(ossl111, awslc, boringssl))] - ctx.cipher_final_vec(&mut buf).unwrap(); - - assert_eq!(buf, pt); - } - - #[cfg(not(any(boringssl, awslc)))] - #[test] - fn default_aes_128_xts() { - // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/aes/XTSTestVectors.zip - let cipher = Cipher::aes_128_xts(); - aes_xts( - cipher, - "a1b90cba3f06ac353b2c343876081762090923026e91771815f29dab01932f2f", - "4faef7117cda59c66e4b92013e768ad5", - "ebabce95b14d3c8d6fb350390790311c", - "778ae8b43cb98d5a825081d5be471c63", - ); - } - - #[cfg(not(boringssl))] - #[test] - fn default_aes_256_xts() { - // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/aes/XTSTestVectors.zip - let cipher = Cipher::aes_256_xts(); - aes_xts(cipher, "1ea661c58d943a0e4801e42f4b0947149e7f9f8e3e68d0c7505210bd311a0e7cd6e13ffdf2418d8d1911c004cda58da3d619b7e2b9141e58318eea392cf41b08", "adf8d92627464ad2f0428e84a9f87564", "2eedea52cd8215e1acc647e810bbc3642e87287f8d2e57e36c0a24fbc12a202e", "cbaad0e2f6cea3f50b37f934d46a9b130b9d54f07e34f36af793e86f73c6d7db"); - } - - #[cfg(not(boringssl))] - fn aes_xts( - cipher: &CipherRef, - key: &'static str, - i: &'static str, - pt: &'static str, - ct: &'static str, - ) { - let key = hex::decode(key).unwrap(); - let i = hex::decode(i).unwrap(); - let pt = hex::decode(pt).unwrap(); - let ct = hex::decode(ct).unwrap(); - - let mut ctx = CipherCtx::new().unwrap(); - ctx.encrypt_init(Some(cipher), Some(&key), Some(&i)) - .unwrap(); - let mut buf = vec![]; - ctx.cipher_update_vec(&pt, &mut buf).unwrap(); - ctx.cipher_final_vec(&mut buf).unwrap(); - - assert_eq!(ct, buf); - - ctx.decrypt_init(Some(cipher), Some(&key), Some(&i)) - .unwrap(); - let mut buf = vec![]; - ctx.cipher_update_vec(&ct, &mut buf).unwrap(); - ctx.cipher_final_vec(&mut buf).unwrap(); - - assert_eq!(pt, buf); - } - - #[test] - fn test_stream_ciphers() { - #[cfg(not(boringssl))] - { - test_stream_cipher(Cipher::aes_128_cfb1()); - test_stream_cipher(Cipher::aes_128_cfb8()); - test_stream_cipher(Cipher::aes_128_cfb128()); - test_stream_cipher(Cipher::aes_192_cfb1()); - test_stream_cipher(Cipher::aes_192_cfb8()); - test_stream_cipher(Cipher::aes_192_cfb128()); - test_stream_cipher(Cipher::aes_256_cfb1()); - test_stream_cipher(Cipher::aes_256_cfb8()); - test_stream_cipher(Cipher::aes_256_cfb128()); - } - test_stream_cipher(Cipher::aes_192_ctr()); - test_stream_cipher(Cipher::aes_256_ctr()); - } - - fn test_stream_cipher(cipher: &'static CipherRef) { - let mut key = vec![0; cipher.key_length()]; - rand_bytes(&mut key).unwrap(); - let mut iv = vec![0; cipher.iv_length()]; - rand_bytes(&mut iv).unwrap(); - - let mut ctx = CipherCtx::new().unwrap(); - - ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv)) - .unwrap(); - ctx.set_padding(false); - - assert_eq!( - 1, - cipher.block_size(), - "Need a stream cipher, not a block cipher" - ); - - // update cipher with non-full block - // this is a streaming cipher so the number of output bytes - // will be the same as the number of input bytes - let mut output = vec![0; 32]; - let outlen = ctx - .cipher_update(&[1; 15], Some(&mut output[0..15])) - .unwrap(); - assert_eq!(15, outlen); - - // update cipher with missing bytes from the previous block - // as previously it will output the same number of bytes as - // the input - let outlen = ctx - .cipher_update(&[1; 17], Some(&mut output[15..])) - .unwrap(); - assert_eq!(17, outlen); - - ctx.cipher_final_vec(&mut vec![0; 0]).unwrap(); - - // encrypt again, but use in-place encryption this time - // First reset the IV - ctx.encrypt_init(None, None, Some(&iv)).unwrap(); - ctx.set_padding(false); - let mut data_inplace: [u8; 32] = [1; 32]; - let outlen = ctx - .cipher_update_inplace(&mut data_inplace[0..15], 15) - .unwrap(); - assert_eq!(15, outlen); - - let outlen = ctx - .cipher_update_inplace(&mut data_inplace[15..32], 17) - .unwrap(); - assert_eq!(17, outlen); - - ctx.cipher_final(&mut [0u8; 0]).unwrap(); - - // Check that the resulting data is encrypted in the same manner - assert_eq!(data_inplace.as_slice(), output.as_slice()); - - // try to decrypt - ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv)) - .unwrap(); - ctx.set_padding(false); - - // update cipher with non-full block - // expect that the output for stream cipher will contain - // the same number of bytes as the input - let mut output_decrypted = vec![0; 32]; - let outlen = ctx - .cipher_update(&output[0..15], Some(&mut output_decrypted[0..15])) - .unwrap(); - assert_eq!(15, outlen); - - let outlen = ctx - .cipher_update(&output[15..], Some(&mut output_decrypted[15..])) - .unwrap(); - assert_eq!(17, outlen); - - ctx.cipher_final_vec(&mut vec![0; 0]).unwrap(); - // check if the decrypted blocks are the same as input (all ones) - assert_eq!(output_decrypted, vec![1; 32]); - - // decrypt again, but now the output in-place - ctx.decrypt_init(None, None, Some(&iv)).unwrap(); - ctx.set_padding(false); - - let outlen = ctx.cipher_update_inplace(&mut output[0..15], 15).unwrap(); - assert_eq!(15, outlen); - - let outlen = ctx.cipher_update_inplace(&mut output[15..], 17).unwrap(); - assert_eq!(17, outlen); - - ctx.cipher_final_vec(&mut vec![0; 0]).unwrap(); - assert_eq!(output_decrypted, output); - } - - #[test] - #[should_panic(expected = "Output buffer size should be at least 33 bytes.")] - fn full_block_updates_aes_128() { - output_buffer_too_small(Cipher::aes_128_cbc()); - } - - #[test] - #[should_panic(expected = "Output buffer size should be at least 33 bytes.")] - fn full_block_updates_aes_256() { - output_buffer_too_small(Cipher::aes_256_cbc()); - } - - #[test] - #[should_panic(expected = "Output buffer size should be at least 17 bytes.")] - fn full_block_updates_3des() { - output_buffer_too_small(Cipher::des_ede3_cbc()); - } - - fn output_buffer_too_small(cipher: &'static CipherRef) { - let mut key = vec![0; cipher.key_length()]; - rand_bytes(&mut key).unwrap(); - let mut iv = vec![0; cipher.iv_length()]; - rand_bytes(&mut iv).unwrap(); - - let mut ctx = CipherCtx::new().unwrap(); - - ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv)) - .unwrap(); - ctx.set_padding(false); - - let block_size = cipher.block_size(); - assert!(block_size > 1, "Need a block cipher, not a stream cipher"); - - ctx.cipher_update(&vec![0; block_size + 1], Some(&mut vec![0; block_size - 1])) - .unwrap(); - } - - #[cfg(ossl102)] - fn cipher_wrap_test(cipher: &CipherRef, pt: &str, ct: &str, key: &str, iv: Option<&str>) { - let pt = hex::decode(pt).unwrap(); - let key = hex::decode(key).unwrap(); - let expected = hex::decode(ct).unwrap(); - let iv = iv.map(|v| hex::decode(v).unwrap()); - let padding = 8 - pt.len() % 8; - let mut computed = vec![0; pt.len() + padding + cipher.block_size() * 2]; - let mut ctx = CipherCtx::new().unwrap(); - - ctx.set_flags(CipherCtxFlags::FLAG_WRAP_ALLOW); - ctx.encrypt_init(Some(cipher), Some(&key), iv.as_deref()) - .unwrap(); - - let count = ctx.cipher_update(&pt, Some(&mut computed)).unwrap(); - let rest = ctx.cipher_final(&mut computed[count..]).unwrap(); - computed.truncate(count + rest); - - if computed != expected { - println!("Computed: {}", hex::encode(&computed)); - println!("Expected: {}", hex::encode(&expected)); - if computed.len() != expected.len() { - println!( - "Lengths differ: {} in computed vs {} expected", - computed.len(), - expected.len() - ); - } - panic!("test failure"); - } - } - - #[test] - #[cfg(ossl102)] - fn test_aes128_wrap() { - let pt = "00112233445566778899aabbccddeeff"; - let ct = "7940ff694448b5bb5139c959a4896832e55d69aa04daa27e"; - let key = "2b7e151628aed2a6abf7158809cf4f3c"; - let iv = "0001020304050607"; - - cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, Some(iv)); - } - - #[test] - #[cfg(ossl102)] - fn test_aes128_wrap_default_iv() { - let pt = "00112233445566778899aabbccddeeff"; - let ct = "38f1215f0212526f8a70b51955b9fbdc9fe3041d9832306e"; - let key = "2b7e151628aed2a6abf7158809cf4f3c"; - - cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, None); - } - - #[test] - #[cfg(ossl110)] - fn test_aes128_wrap_pad() { - let pt = "00112233445566778899aabbccddee"; - let ct = "f13998f5ab32ef82a1bdbcbe585e1d837385b529572a1e1b"; - let key = "2b7e151628aed2a6abf7158809cf4f3c"; - let iv = "00010203"; - - cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, Some(iv)); - } - - #[test] - #[cfg(ossl110)] - fn test_aes128_wrap_pad_default_iv() { - let pt = "00112233445566778899aabbccddee"; - let ct = "3a501085fb8cf66f4186b7df851914d471ed823411598add"; - let key = "2b7e151628aed2a6abf7158809cf4f3c"; - - cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, None); - } - - #[test] - #[cfg(ossl102)] - fn test_aes192_wrap() { - let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b"; - let ct = "83b89142dfeeb4871e078bfb81134d33e23fedc19b03a1cf689973d3831b6813"; - let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; - let iv = "0001020304050607"; - - cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, Some(iv)); - } - - #[test] - #[cfg(ossl102)] - fn test_aes192_wrap_default_iv() { - let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b"; - let ct = "c02c2cf11505d3e4851030d5534cbf5a1d7eca7ba8839adbf239756daf1b43e6"; - let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; - - cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, None); - } - - #[test] - #[cfg(ossl110)] - fn test_aes192_wrap_pad() { - let pt = "00112233445566778899aabbccddee"; - let ct = "b4f6bb167ef7caf061a74da82b36ad038ca057ab51e98d3a"; - let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; - let iv = "00010203"; - - cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, Some(iv)); - } - - #[test] - #[cfg(ossl110)] - fn test_aes192_wrap_pad_default_iv() { - let pt = "00112233445566778899aabbccddee"; - let ct = "b2c37a28cc602753a7c944a4c2555a2df9c98b2eded5312e"; - let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; - - cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, None); - } - - #[test] - #[cfg(ossl102)] - fn test_aes256_wrap() { - let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"; - let ct = "cc05da2a7f56f7dd0c144231f90bce58648fa20a8278f5a6b7d13bba6aa57a33229d4333866b7fd6"; - let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; - let iv = "0001020304050607"; - - cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, Some(iv)); - } - - #[test] - #[cfg(ossl102)] - fn test_aes256_wrap_default_iv() { - let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"; - let ct = "0b24f068b50e52bc6987868411c36e1b03900866ed12af81eb87cef70a8d1911731c1d7abf789d88"; - let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; - - cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, None); - } - - #[test] - #[cfg(ossl110)] - fn test_aes256_wrap_pad() { - let pt = "00112233445566778899aabbccddee"; - let ct = "91594e044ccc06130d60e6c84a996aa4f96a9faff8c5f6e7"; - let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; - let iv = "00010203"; - - cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, Some(iv)); - } - - #[test] - #[cfg(ossl110)] - fn test_aes256_wrap_pad_default_iv() { - let pt = "00112233445566778899aabbccddee"; - let ct = "dc3c166a854afd68aea624a4272693554bf2e4fcbae602cd"; - let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; - - cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, None); - } -} diff --git a/patch/openssl/src/cms.rs b/patch/openssl/src/cms.rs deleted file mode 100644 index 45bad89a43a28..0000000000000 --- a/patch/openssl/src/cms.rs +++ /dev/null @@ -1,481 +0,0 @@ -//! 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::{store::X509StoreRef, X509Ref, X509}; -use crate::{cvt, cvt_p}; -use openssl_macros::corresponds; - -bitflags! { - #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - #[repr(transparent)] - 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(any(ossl102, libressl))] - const KEY_PARAM = ffi::CMS_KEY_PARAM; - #[cfg(any(ossl110, libressl))] - 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(&self, pkey: &PKeyRef, cert: &X509) -> Result, 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(&self, pkey: &PKeyRef) -> Result, 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 { - 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( - signcert: Option<&X509Ref>, - pkey: Option<&PKeyRef>, - certs: Option<&StackRef>, - data: Option<&[u8]>, - flags: CMSOptions, - ) -> Result - 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. - /// - #[corresponds(CMS_encrypt)] - pub fn encrypt( - certs: &StackRef, - data: &[u8], - cipher: Cipher, - flags: CMSOptions, - ) -> Result { - 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)) - } - } - - /// Verify this CmsContentInfo's signature, - /// This will search the 'certs' list for the signing certificate. - /// Additional certificates, needed for building the certificate chain, may be - /// given in 'store' as well as additional CRLs. - /// A detached signature may be passed in `detached_data`. The signed content - /// without signature, will be copied into output_data if it is present. - /// - #[corresponds(CMS_verify)] - pub fn verify( - &mut self, - certs: Option<&StackRef>, - store: Option<&X509StoreRef>, - detached_data: Option<&[u8]>, - output_data: Option<&mut Vec>, - flags: CMSOptions, - ) -> Result<(), ErrorStack> { - unsafe { - let certs_ptr = certs.map_or(ptr::null_mut(), |p| p.as_ptr()); - let store_ptr = store.map_or(ptr::null_mut(), |p| p.as_ptr()); - let detached_data_bio = match detached_data { - Some(data) => Some(MemBioSlice::new(data)?), - None => None, - }; - let detached_data_bio_ptr = detached_data_bio - .as_ref() - .map_or(ptr::null_mut(), |p| p.as_ptr()); - let out_bio = MemBio::new()?; - - cvt(ffi::CMS_verify( - self.as_ptr(), - certs_ptr, - store_ptr, - detached_data_bio_ptr, - out_bio.as_ptr(), - flags.bits(), - ))?; - - if let Some(data) = output_data { - data.clear(); - data.extend_from_slice(out_bio.get_buf()); - }; - - Ok(()) - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - use crate::pkcs12::Pkcs12; - use crate::pkey::PKey; - use crate::stack::Stack; - use crate::x509::{ - store::{X509Store, X509StoreBuilder}, - 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 - .parse2("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.as_ref().unwrap(), - priv_cert.cert.as_ref().unwrap(), - ) - .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.as_ref().unwrap()) - .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.as_ref().unwrap(), - priv_cert.cert.as_ref().unwrap(), - ) - .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.as_ref().unwrap()) - .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); - } - } - - fn cms_sign_verify_generic_helper(is_detached: bool) { - // load cert with private key - let cert_bytes = include_bytes!("../test/cert.pem"); - let cert = X509::from_pem(cert_bytes).expect("failed to load cert.pem"); - - let key_bytes = include_bytes!("../test/key.pem"); - let key = PKey::private_key_from_pem(key_bytes).expect("failed to load key.pem"); - - let root_bytes = include_bytes!("../test/root-ca.pem"); - let root = X509::from_pem(root_bytes).expect("failed to load root-ca.pem"); - - // sign cms message using public key cert - let data = b"Hello world!"; - - let (opt, ext_data): (CMSOptions, Option<&[u8]>) = if is_detached { - (CMSOptions::DETACHED | CMSOptions::BINARY, Some(data)) - } else { - (CMSOptions::empty(), None) - }; - - let mut cms = CmsContentInfo::sign(Some(&cert), Some(&key), None, Some(data), opt) - .expect("failed to CMS sign a message"); - - // check CMS signature length - let pem_cms = cms - .to_pem() - .expect("failed to pack CmsContentInfo into PEM"); - assert!(!pem_cms.is_empty()); - - // verify CMS signature - let mut builder = X509StoreBuilder::new().expect("failed to create X509StoreBuilder"); - builder - .add_cert(root) - .expect("failed to add root-ca into X509StoreBuilder"); - let store: X509Store = builder.build(); - let mut out_data: Vec = Vec::new(); - let res = cms.verify( - None, - Some(&store), - ext_data, - Some(&mut out_data), - CMSOptions::empty(), - ); - - // check verification result - valid signature - res.unwrap(); - assert_eq!(data.to_vec(), out_data); - } - - #[test] - fn cms_sign_verify_ok() { - cms_sign_verify_generic_helper(false); - } - - #[test] - fn cms_sign_verify_detached_ok() { - cms_sign_verify_generic_helper(true); - } - - #[test] - fn cms_sign_verify_error() { - #[cfg(ossl300)] - let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); - - // 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 - .parse2("mypass") - .expect("failed to parse priv cert"); - - // sign cms message using public key cert - let data = b"Hello world!"; - let mut cms = CmsContentInfo::sign( - Some(&priv_cert.cert.unwrap()), - Some(&priv_cert.pkey.unwrap()), - None, - Some(data), - CMSOptions::empty(), - ) - .expect("failed to CMS sign a message"); - - // check CMS signature length - let pem_cms = cms - .to_pem() - .expect("failed to pack CmsContentInfo into PEM"); - assert!(!pem_cms.is_empty()); - - let empty_store = X509StoreBuilder::new() - .expect("failed to create X509StoreBuilder") - .build(); - - // verify CMS signature - let res = cms.verify( - None, - Some(&empty_store), - Some(data), - None, - CMSOptions::empty(), - ); - - // check verification result - this is an invalid signature - // defined in openssl crypto/cms/cms.h - const CMS_R_CERTIFICATE_VERIFY_ERROR: i32 = 100; - let es = res.unwrap_err(); - let error_array = es.errors(); - assert_eq!(1, error_array.len()); - let code = error_array[0].reason_code(); - assert_eq!(code, CMS_R_CERTIFICATE_VERIFY_ERROR); - } -} diff --git a/patch/openssl/src/conf.rs b/patch/openssl/src/conf.rs deleted file mode 100644 index 8fc0d0542f4e7..0000000000000 --- a/patch/openssl/src/conf.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! Interface for processing OpenSSL configuration files. - -foreign_type_and_impl_send_sync! { - type CType = ffi::CONF; - fn drop = ffi::NCONF_free; - - pub struct Conf; - pub struct ConfRef; -} - -#[cfg(not(any(boringssl, libressl400, awslc)))] -mod methods { - use super::Conf; - 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)] - #[allow(clippy::should_implement_trait)] - 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 - } - } - - 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 { - unsafe { cvt_p(ffi::NCONF_new(method.as_ptr())).map(Conf) } - } - } -} -#[cfg(not(any(boringssl, libressl400, awslc)))] -pub use methods::*; diff --git a/patch/openssl/src/derive.rs b/patch/openssl/src/derive.rs deleted file mode 100644 index e0d35720b2930..0000000000000 --- a/patch/openssl/src/derive.rs +++ /dev/null @@ -1,211 +0,0 @@ -//! Shared secret derivation. -//! -//! # Example -//! -//! The following example implements [ECDH] using `NIST P-384` keys: -//! -//! ``` -//! # fn main() -> Result<(), Box> { -//! # use std::convert::TryInto; -//! use openssl::bn::BigNumContext; -//! use openssl::pkey::PKey; -//! use openssl::derive::Deriver; -//! use openssl::ec::{EcGroup, EcKey, EcPoint, PointConversionForm}; -//! use openssl::nid::Nid; -//! -//! let group = EcGroup::from_curve_name(Nid::SECP384R1)?; -//! -//! let first: PKey<_> = EcKey::generate(&group)?.try_into()?; -//! -//! // second party generates an ephemeral key and derives -//! // a shared secret using first party's public key -//! let shared_key = EcKey::generate(&group)?; -//! // shared_public is sent to first party -//! let mut ctx = BigNumContext::new()?; -//! let shared_public = shared_key.public_key().to_bytes( -//! &group, -//! PointConversionForm::COMPRESSED, -//! &mut ctx, -//! )?; -//! -//! let shared_key: PKey<_> = shared_key.try_into()?; -//! let mut deriver = Deriver::new(&shared_key)?; -//! deriver.set_peer(&first)?; -//! // secret can be used e.g. as a symmetric encryption key -//! let secret = deriver.derive_to_vec()?; -//! # drop(deriver); -//! -//! // first party derives the same shared secret using -//! // shared_public -//! let point = EcPoint::from_bytes(&group, &shared_public, &mut ctx)?; -//! let recipient_key: PKey<_> = EcKey::from_public_key(&group, &point)?.try_into()?; -//! let mut deriver = Deriver::new(&first)?; -//! deriver.set_peer(&recipient_key)?; -//! let first_secret = deriver.derive_to_vec()?; -//! -//! assert_eq!(secret, first_secret); -//! # Ok(()) } -//! ``` -//! -//! [ECDH]: https://wiki.openssl.org/index.php/Elliptic_Curve_Diffie_Hellman - -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}; -use openssl_macros::corresponds; - -/// A type used to derive a shared secret between two keys. -pub struct Deriver<'a>(*mut ffi::EVP_PKEY_CTX, PhantomData<&'a ()>); - -unsafe impl Sync for Deriver<'_> {} -unsafe impl Send for Deriver<'_> {} - -#[allow(clippy::len_without_is_empty)] -impl<'a> Deriver<'a> { - /// Creates a new `Deriver` using the provided private key. - #[corresponds(EVP_PKEY_derive_init)] - pub fn new(key: &'a PKeyRef) -> Result, 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. - #[corresponds(EVP_PKEY_derive_set_peer)] - pub fn set_peer(&mut self, key: &'a PKeyRef) -> Result<(), ErrorStack> - where - T: HasPublic, - { - unsafe { cvt(ffi::EVP_PKEY_derive_set_peer(self.0, key.as_ptr())).map(|_| ()) } - } - - /// Sets the peer key used for secret derivation along with optionally validating the peer public key. - /// - /// Requires OpenSSL 3.0.0 or newer. - #[corresponds(EVP_PKEY_derive_set_peer_ex)] - #[cfg(ossl300)] - pub fn set_peer_ex( - &mut self, - key: &'a PKeyRef, - validate_peer: bool, - ) -> Result<(), ErrorStack> - where - T: HasPublic, - { - unsafe { - cvt(ffi::EVP_PKEY_derive_set_peer_ex( - self.0, - key.as_ptr(), - validate_peer as i32, - )) - .map(|_| ()) - } - } - - /// Returns the size of the shared secret. - /// - /// It can be used to size the buffer passed to [`Deriver::derive`]. - /// - /// It can be used to size the buffer passed to [`Deriver::derive`]. - /// - /// [`Deriver::derive`]: #method.derive - #[corresponds(EVP_PKEY_derive)] - pub fn len(&mut self) -> Result { - 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. - #[corresponds(EVP_PKEY_derive)] - pub fn derive(&mut self, buf: &mut [u8]) -> Result { - 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, ErrorStack> { - let len = self.len()?; - let mut buf = vec![0; len]; - let len = self.derive(&mut buf)?; - buf.truncate(len); - Ok(buf) - } -} - -impl Drop for Deriver<'_> { - 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()); - } - - #[test] - #[cfg(ossl300)] - fn test_ec_key_derive_ex() { - 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_ex(&pkey2, true).unwrap(); - let shared = deriver.derive_to_vec().unwrap(); - assert!(!shared.is_empty()); - } -} diff --git a/patch/openssl/src/dh.rs b/patch/openssl/src/dh.rs deleted file mode 100644 index f434bbe9abe4e..0000000000000 --- a/patch/openssl/src/dh.rs +++ /dev/null @@ -1,499 +0,0 @@ -//! Diffie-Hellman key agreement. - -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, Public}; -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; - - pub struct DhRef; -} - -impl DhRef -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 - } - - /// Validates DH parameters for correctness - #[corresponds(DH_check_key)] - pub fn check_key(&self) -> Result { - unsafe { - let mut codes = 0; - cvt(ffi::DH_check(self.as_ptr(), &mut codes))?; - Ok(codes == 0) - } - } -} - -impl Dh { - pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result, 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, - generator: BigNum, - ) -> Result, 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 public key on the DH object. - pub fn set_public_key(self, pub_key: BigNum) -> Result, ErrorStack> { - unsafe { - let dh_ptr = self.0; - cvt(DH_set0_key(dh_ptr, pub_key.as_ptr(), ptr::null_mut()))?; - mem::forget((self, pub_key)); - Ok(Dh::from_ptr(dh_ptr)) - } - } - - /// Sets the private key on the DH object and recomputes the public key. - pub fn set_private_key(self, priv_key: BigNum) -> Result, 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)) - } - } - - /// Sets the public and private keys on the DH object. - pub fn set_key(self, pub_key: BigNum, priv_key: BigNum) -> Result, ErrorStack> { - unsafe { - let dh_ptr = self.0; - cvt(DH_set0_key(dh_ptr, pub_key.as_ptr(), priv_key.as_ptr()))?; - mem::forget((self, pub_key, priv_key)); - 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, 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, 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, - ffi::PEM_read_bio_DHparams - } - - from_der! { - /// Deserializes a DER-encoded PKCS#3 DHparameters structure. - #[corresponds(d2i_DHparams)] - params_from_der, - Dh, - ffi::d2i_DHparams - } - - /// Requires OpenSSL 1.0.2 or newer. - #[corresponds(DH_get_1024_160)] - #[cfg(ossl102)] - pub fn get_1024_160() -> Result, 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(ossl102)] - pub fn get_2048_224() -> Result, 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(ossl102)] - pub fn get_2048_256() -> Result, ErrorStack> { - unsafe { - ffi::init(); - cvt_p(ffi::DH_get_2048_256()).map(|p| Dh::from_ptr(p)) - } - } -} - -impl Dh -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 DhRef -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 DhRef -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, 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, libressl, boringssl, awslc))] { - 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; - #[cfg(all(not(any(boringssl, awslc)), ossl110))] - use crate::pkey::PKey; - 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(all(not(any(boringssl, awslc)), ossl110))] - fn test_from_dhx_serializes_q() { - let p = BigNum::from_hex_str("00ad107e1e9123a9d0d660faa79559c51fa20d64e5683b9fd1b54b1597b61d0a75e6fa141df95a56dbaf9a3c407ba1df15eb3d688a309c180e1de6b85a1274a0a66d3f8152ad6ac2129037c9edefda4df8d91e8fef55b7394b7ad5b7d0b6c12207c9f98d11ed34dbf6c6ba0b2c8bbc27be6a00e0a0b9c49708b3bf8a317091883681286130bc8985db1602e714415d9330278273c7de31efdc7310f7121fd5a07415987d9adc0a486dcdf93acc44328387315d75e198c641a480cd86a1b9e587e8be60e69cc928b2b9c52172e413042e9b23f10b0e16e79763c9b53dcf4ba80a29e3fb73c16b8e75b97ef363e2ffa31f71cf9de5384e71b81c0ac4dffe0c10e64f").unwrap(); - let g = BigNum::from_hex_str("00ac4032ef4f2d9ae39df30b5c8ffdac506cdebe7b89998caf74866a08cfe4ffe3a6824a4e10b9a6f0dd921f01a70c4afaab739d7700c29f52c57db17c620a8652be5e9001a8d66ad7c17669101999024af4d027275ac1348bb8a762d0521bc98ae247150422ea1ed409939d54da7460cdb5f6c6b250717cbef180eb34118e98d119529a45d6f834566e3025e316a330efbb77a86f0c1ab15b051ae3d428c8f8acb70a8137150b8eeb10e183edd19963ddd9e263e4770589ef6aa21e7f5f2ff381b539cce3409d13cd566afbb48d6c019181e1bcfe94b30269edfe72fe9b6aa4bd7b5a0f1c71cfff4c19c418e1f6ec017981bc087f2a7065b384b890d3191f2bfa").unwrap(); - let q = BigNum::from_hex_str("00801c0d34c58d93fe997177101f80535a4738cebcbf389a99b36371eb") - .unwrap(); - let y = BigNum::from_hex_str("0082c165bb576243ecf46d58c3d1501616955fca0320fa95ea11d2e6c1b9cf217676720dc1c08c85bf20c4d232b60a29a1e51c7b773bc645014587c525c86151b30d75486ec7b6c98efb5f74955b83116d01d0af1232af89213c2de574369d701aba9357300b920d3d8b98252d46c46952c16a5f33554b38317809c7b9add4701f5c158c1b7035e9fe39366ececb90d2896b78c523c4a577287ef5ba7a2663ed58aa20b5ec66e30f316610dfaa38583e495ab6af771c284387e660edbef4edb872e2e80e1d244ee95622e76d028e61c1e887c2aa792717362139f4dd26eafd49b2366eeb2350b01fe1b56022a2809e379559c37b375ba01c4eaacc14fd1b247837").unwrap(); - - let dh = Dh::from_params(p, g, q).unwrap(); - let dh = dh.set_public_key(y).unwrap(); - - // Verify that 'q' is serialized in the public key. - let pkey = PKey::from_dhx(dh).unwrap(); - assert_eq!(pkey.public_key_to_der().unwrap(), b"\x30\x82\x03\x44\x30\x82\x02\x36\x06\x07\x2a\x86\x48\xce\x3e\x02\x01\x30\x82\x02\x29\x02\x82\x01\x01\x00\xad\x10\x7e\x1e\x91\x23\xa9\xd0\xd6\x60\xfa\xa7\x95\x59\xc5\x1f\xa2\x0d\x64\xe5\x68\x3b\x9f\xd1\xb5\x4b\x15\x97\xb6\x1d\x0a\x75\xe6\xfa\x14\x1d\xf9\x5a\x56\xdb\xaf\x9a\x3c\x40\x7b\xa1\xdf\x15\xeb\x3d\x68\x8a\x30\x9c\x18\x0e\x1d\xe6\xb8\x5a\x12\x74\xa0\xa6\x6d\x3f\x81\x52\xad\x6a\xc2\x12\x90\x37\xc9\xed\xef\xda\x4d\xf8\xd9\x1e\x8f\xef\x55\xb7\x39\x4b\x7a\xd5\xb7\xd0\xb6\xc1\x22\x07\xc9\xf9\x8d\x11\xed\x34\xdb\xf6\xc6\xba\x0b\x2c\x8b\xbc\x27\xbe\x6a\x00\xe0\xa0\xb9\xc4\x97\x08\xb3\xbf\x8a\x31\x70\x91\x88\x36\x81\x28\x61\x30\xbc\x89\x85\xdb\x16\x02\xe7\x14\x41\x5d\x93\x30\x27\x82\x73\xc7\xde\x31\xef\xdc\x73\x10\xf7\x12\x1f\xd5\xa0\x74\x15\x98\x7d\x9a\xdc\x0a\x48\x6d\xcd\xf9\x3a\xcc\x44\x32\x83\x87\x31\x5d\x75\xe1\x98\xc6\x41\xa4\x80\xcd\x86\xa1\xb9\xe5\x87\xe8\xbe\x60\xe6\x9c\xc9\x28\xb2\xb9\xc5\x21\x72\xe4\x13\x04\x2e\x9b\x23\xf1\x0b\x0e\x16\xe7\x97\x63\xc9\xb5\x3d\xcf\x4b\xa8\x0a\x29\xe3\xfb\x73\xc1\x6b\x8e\x75\xb9\x7e\xf3\x63\xe2\xff\xa3\x1f\x71\xcf\x9d\xe5\x38\x4e\x71\xb8\x1c\x0a\xc4\xdf\xfe\x0c\x10\xe6\x4f\x02\x82\x01\x01\x00\xac\x40\x32\xef\x4f\x2d\x9a\xe3\x9d\xf3\x0b\x5c\x8f\xfd\xac\x50\x6c\xde\xbe\x7b\x89\x99\x8c\xaf\x74\x86\x6a\x08\xcf\xe4\xff\xe3\xa6\x82\x4a\x4e\x10\xb9\xa6\xf0\xdd\x92\x1f\x01\xa7\x0c\x4a\xfa\xab\x73\x9d\x77\x00\xc2\x9f\x52\xc5\x7d\xb1\x7c\x62\x0a\x86\x52\xbe\x5e\x90\x01\xa8\xd6\x6a\xd7\xc1\x76\x69\x10\x19\x99\x02\x4a\xf4\xd0\x27\x27\x5a\xc1\x34\x8b\xb8\xa7\x62\xd0\x52\x1b\xc9\x8a\xe2\x47\x15\x04\x22\xea\x1e\xd4\x09\x93\x9d\x54\xda\x74\x60\xcd\xb5\xf6\xc6\xb2\x50\x71\x7c\xbe\xf1\x80\xeb\x34\x11\x8e\x98\xd1\x19\x52\x9a\x45\xd6\xf8\x34\x56\x6e\x30\x25\xe3\x16\xa3\x30\xef\xbb\x77\xa8\x6f\x0c\x1a\xb1\x5b\x05\x1a\xe3\xd4\x28\xc8\xf8\xac\xb7\x0a\x81\x37\x15\x0b\x8e\xeb\x10\xe1\x83\xed\xd1\x99\x63\xdd\xd9\xe2\x63\xe4\x77\x05\x89\xef\x6a\xa2\x1e\x7f\x5f\x2f\xf3\x81\xb5\x39\xcc\xe3\x40\x9d\x13\xcd\x56\x6a\xfb\xb4\x8d\x6c\x01\x91\x81\xe1\xbc\xfe\x94\xb3\x02\x69\xed\xfe\x72\xfe\x9b\x6a\xa4\xbd\x7b\x5a\x0f\x1c\x71\xcf\xff\x4c\x19\xc4\x18\xe1\xf6\xec\x01\x79\x81\xbc\x08\x7f\x2a\x70\x65\xb3\x84\xb8\x90\xd3\x19\x1f\x2b\xfa\x02\x1d\x00\x80\x1c\x0d\x34\xc5\x8d\x93\xfe\x99\x71\x77\x10\x1f\x80\x53\x5a\x47\x38\xce\xbc\xbf\x38\x9a\x99\xb3\x63\x71\xeb\x03\x82\x01\x06\x00\x02\x82\x01\x01\x00\x82\xc1\x65\xbb\x57\x62\x43\xec\xf4\x6d\x58\xc3\xd1\x50\x16\x16\x95\x5f\xca\x03\x20\xfa\x95\xea\x11\xd2\xe6\xc1\xb9\xcf\x21\x76\x76\x72\x0d\xc1\xc0\x8c\x85\xbf\x20\xc4\xd2\x32\xb6\x0a\x29\xa1\xe5\x1c\x7b\x77\x3b\xc6\x45\x01\x45\x87\xc5\x25\xc8\x61\x51\xb3\x0d\x75\x48\x6e\xc7\xb6\xc9\x8e\xfb\x5f\x74\x95\x5b\x83\x11\x6d\x01\xd0\xaf\x12\x32\xaf\x89\x21\x3c\x2d\xe5\x74\x36\x9d\x70\x1a\xba\x93\x57\x30\x0b\x92\x0d\x3d\x8b\x98\x25\x2d\x46\xc4\x69\x52\xc1\x6a\x5f\x33\x55\x4b\x38\x31\x78\x09\xc7\xb9\xad\xd4\x70\x1f\x5c\x15\x8c\x1b\x70\x35\xe9\xfe\x39\x36\x6e\xce\xcb\x90\xd2\x89\x6b\x78\xc5\x23\xc4\xa5\x77\x28\x7e\xf5\xba\x7a\x26\x63\xed\x58\xaa\x20\xb5\xec\x66\xe3\x0f\x31\x66\x10\xdf\xaa\x38\x58\x3e\x49\x5a\xb6\xaf\x77\x1c\x28\x43\x87\xe6\x60\xed\xbe\xf4\xed\xb8\x72\xe2\xe8\x0e\x1d\x24\x4e\xe9\x56\x22\xe7\x6d\x02\x8e\x61\xc1\xe8\x87\xc2\xaa\x79\x27\x17\x36\x21\x39\xf4\xdd\x26\xea\xfd\x49\xb2\x36\x6e\xeb\x23\x50\xb0\x1f\xe1\xb5\x60\x22\xa2\x80\x9e\x37\x95\x59\xc3\x7b\x37\x5b\xa0\x1c\x4e\xaa\xcc\x14\xfd\x1b\x24\x78\x37"); - } - - #[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] - #[cfg(ossl102)] - fn test_set_keys() { - let dh1 = Dh::get_2048_256().unwrap(); - let key1 = dh1.generate_key().unwrap(); - - let dh2 = Dh::get_2048_256().unwrap(); - let key2 = dh2 - .set_public_key(key1.public_key().to_owned().unwrap()) - .unwrap(); - - assert_eq!(key1.public_key(), key2.public_key()); - - let dh3 = Dh::get_2048_256().unwrap(); - let key3 = dh3 - .set_key( - key1.public_key().to_owned().unwrap(), - key1.private_key().to_owned().unwrap(), - ) - .unwrap(); - assert_eq!(key1.public_key(), key3.public_key()); - assert_eq!(key1.private_key(), key3.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); - } - - #[test] - fn test_dh_check_key() { - let dh1 = Dh::generate_params(512, 2).unwrap(); - let p = BigNum::from_hex_str("04").unwrap(); - let g = BigNum::from_hex_str("02").unwrap(); - let dh2 = Dh::from_pqg(p, None, g).unwrap(); - assert!(dh1.check_key().unwrap()); - assert!(matches!(dh2.check_key(), Ok(false) | Err(_))); - } -} diff --git a/patch/openssl/src/dsa.rs b/patch/openssl/src/dsa.rs deleted file mode 100644 index 49d3d340c12ba..0000000000000 --- a/patch/openssl/src/dsa.rs +++ /dev/null @@ -1,697 +0,0 @@ -//! 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}; -#[cfg(not(any(boringssl, awslc)))] -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, Params, 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://docs.openssl.org/master/man3/DSA_new/ - /// - /// # Examples - /// - /// ``` - /// use openssl::dsa::Dsa; - /// use openssl::error::ErrorStack; - /// use openssl::pkey::Private; - /// - /// fn create_dsa() -> Result, ErrorStack> { - /// let sign = Dsa::generate(2048)?; - /// Ok(sign) - /// } - /// # fn main() { - /// # create_dsa(); - /// # } - /// ``` - pub struct Dsa; - /// Reference to [`Dsa`]. - /// - /// [`Dsa`]: struct.Dsa.html - pub struct DsaRef; -} - -impl Clone for Dsa { - fn clone(&self) -> Dsa { - (**self).to_owned() - } -} - -impl ToOwned for DsaRef { - type Owned = Dsa; - - fn to_owned(&self) -> Dsa { - unsafe { - ffi::DSA_up_ref(self.as_ptr()); - Dsa::from_ptr(self.as_ptr()) - } - } -} - -impl DsaRef -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 DsaRef -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 - } - - to_der! { - /// Serializes the private_key to a DER-encoded `DSAPrivateKey` structure. - #[corresponds(i2d_DSAPrivateKey)] - private_key_to_der, - ffi::i2d_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 DsaRef -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) - } - } -} -#[cfg(any(boringssl, awslc))] -type BitType = libc::c_uint; -#[cfg(not(any(boringssl, awslc)))] -type BitType = c_int; - -impl Dsa { - /// Creates a DSA params based upon the given parameters. - #[corresponds(DSA_set0_pqg)] - pub fn from_pqg(p: BigNum, q: BigNum, g: BigNum) -> Result, ErrorStack> { - 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)); - Ok(dsa) - } - } - - /// Generates DSA params based on the given number of bits. - #[corresponds(DSA_generate_parameters_ex)] - pub fn generate_params(bits: u32) -> Result, ErrorStack> { - ffi::init(); - unsafe { - let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?); - cvt(ffi::DSA_generate_parameters_ex( - dsa.0, - bits as BitType, - ptr::null(), - 0, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ))?; - Ok(dsa) - } - } - - /// Generates a private key based on the DSA params. - #[corresponds(DSA_generate_key)] - pub fn generate_key(self) -> Result, ErrorStack> { - unsafe { - let dsa_ptr = self.0; - cvt(ffi::DSA_generate_key(dsa_ptr))?; - mem::forget(self); - Ok(Dsa::from_ptr(dsa_ptr)) - } - } -} - -impl Dsa { - /// Generate a DSA key pair. - /// - /// The `bits` parameter corresponds to the length of the prime `p`. - pub fn generate(bits: u32) -> Result, ErrorStack> { - let params = Dsa::generate_params(bits)?; - params.generate_key() - } - - /// 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, 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 { - 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, - 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, - 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, 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 fmt::Debug for Dsa { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "DSA") - } -} - -cfg_if! { - if #[cfg(any(ossl110, libressl, boringssl, awslc))] { - 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 - } - } -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::DSA_SIG; - fn drop = ffi::DSA_SIG_free; - - /// Object representing DSA signature. - /// - /// DSA signatures consist of two components: `r` and `s`. - /// - /// # Examples - /// - /// ``` - /// use std::convert::TryInto; - /// - /// use openssl::bn::BigNum; - /// use openssl::dsa::{Dsa, DsaSig}; - /// use openssl::hash::MessageDigest; - /// use openssl::pkey::PKey; - /// use openssl::sign::{Signer, Verifier}; - /// - /// const TEST_DATA: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - /// let dsa_ref = Dsa::generate(1024).unwrap(); - /// - /// let pub_key: PKey<_> = dsa_ref.clone().try_into().unwrap(); - /// let priv_key: PKey<_> = dsa_ref.try_into().unwrap(); - /// - /// let mut signer = if let Ok(signer) = Signer::new(MessageDigest::sha256(), &priv_key) { - /// signer - /// } else { - /// // DSA signing is not supported (eg. BoringSSL) - /// return; - /// }; - /// - /// signer.update(TEST_DATA).unwrap(); - /// - /// let signature = signer.sign_to_vec().unwrap(); - /// // Parse DER-encoded DSA signature - /// let signature = DsaSig::from_der(&signature).unwrap(); - /// - /// // Extract components `r` and `s` - /// let r = BigNum::from_slice(&signature.r().to_vec()).unwrap(); - /// let s = BigNum::from_slice(&signature.s().to_vec()).unwrap(); - /// - /// // Construct new DSA signature from components - /// let signature = DsaSig::from_private_components(r, s).unwrap(); - /// - /// // Serialize DSA signature to DER - /// let signature = signature.to_der().unwrap(); - /// - /// let mut verifier = Verifier::new(MessageDigest::sha256(), &pub_key).unwrap(); - /// verifier.update(TEST_DATA).unwrap(); - /// assert!(verifier.verify(&signature[..]).unwrap()); - /// ``` - pub struct DsaSig; - - /// Reference to a [`DsaSig`]. - pub struct DsaSigRef; -} - -impl DsaSig { - /// Returns a new `DsaSig` by setting the `r` and `s` values associated with an DSA signature. - #[corresponds(DSA_SIG_set0)] - pub fn from_private_components(r: BigNum, s: BigNum) -> Result { - unsafe { - let sig = cvt_p(ffi::DSA_SIG_new())?; - DSA_SIG_set0(sig, r.as_ptr(), s.as_ptr()); - mem::forget((r, s)); - Ok(DsaSig::from_ptr(sig)) - } - } - - from_der! { - /// Decodes a DER-encoded DSA signature. - #[corresponds(d2i_DSA_SIG)] - from_der, - DsaSig, - ffi::d2i_DSA_SIG - } -} - -impl fmt::Debug for DsaSig { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("DsaSig") - .field("r", self.r()) - .field("s", self.s()) - .finish() - } -} - -impl DsaSigRef { - to_der! { - /// Serializes the DSA signature into a DER-encoded `DSASignature` structure. - #[corresponds(i2d_DSA_SIG)] - to_der, - ffi::i2d_DSA_SIG - } - - /// Returns internal component `r` of an `DsaSig`. - #[corresponds(DSA_SIG_get0)] - pub fn r(&self) -> &BigNumRef { - unsafe { - let mut r = ptr::null(); - DSA_SIG_get0(self.as_ptr(), &mut r, ptr::null_mut()); - BigNumRef::from_const_ptr(r) - } - } - - /// Returns internal component `s` of an `DsaSig`. - #[corresponds(DSA_SIG_get0)] - pub fn s(&self) -> &BigNumRef { - unsafe { - let mut s = ptr::null(); - DSA_SIG_get0(self.as_ptr(), ptr::null_mut(), &mut s); - BigNumRef::from_const_ptr(s) - } - } -} - -cfg_if! { - if #[cfg(any(ossl110, libressl, boringssl, awslc))] { - use ffi::{DSA_SIG_set0, DSA_SIG_get0}; - } else { - #[allow(bad_style)] - unsafe fn DSA_SIG_set0( - sig: *mut ffi::DSA_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 DSA_SIG_get0( - sig: *const ffi::DSA_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::bn::BigNumContext; - #[cfg(not(any(boringssl, awslc_fips)))] - use crate::hash::MessageDigest; - #[cfg(not(any(boringssl, awslc_fips)))] - use crate::pkey::PKey; - #[cfg(not(any(boringssl, awslc_fips)))] - 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_params() { - let params = Dsa::generate_params(1024).unwrap(); - let p = params.p().to_owned().unwrap(); - let q = params.q().to_owned().unwrap(); - let g = params.g().to_owned().unwrap(); - let key = params.generate_key().unwrap(); - let params2 = Dsa::from_pqg( - key.p().to_owned().unwrap(), - key.q().to_owned().unwrap(), - key.g().to_owned().unwrap(), - ) - .unwrap(); - assert_eq!(p, *params2.p()); - assert_eq!(q, *params2.q()); - assert_eq!(g, *params2.g()); - } - - #[test] - #[cfg(not(any(boringssl, awslc_fips)))] - 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] - #[cfg(not(any(boringssl, awslc_fips)))] - fn test_signature_der() { - use std::convert::TryInto; - - const TEST_DATA: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - let dsa_ref = Dsa::generate(1024).unwrap(); - - let pub_key: PKey<_> = dsa_ref.clone().try_into().unwrap(); - let priv_key: PKey<_> = dsa_ref.try_into().unwrap(); - - let mut signer = Signer::new(MessageDigest::sha256(), &priv_key).unwrap(); - signer.update(TEST_DATA).unwrap(); - - let signature = signer.sign_to_vec().unwrap(); - eprintln!("{:?}", signature); - let signature = DsaSig::from_der(&signature).unwrap(); - - let r = BigNum::from_slice(&signature.r().to_vec()).unwrap(); - let s = BigNum::from_slice(&signature.s().to_vec()).unwrap(); - - let signature = DsaSig::from_private_components(r, s).unwrap(); - let signature = signature.to_der().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()); - } - - #[test] - fn dsa_sig_debug() { - let sig = DsaSig::from_der(&[ - 48, 46, 2, 21, 0, 135, 169, 24, 58, 153, 37, 175, 248, 200, 45, 251, 112, 238, 238, 89, - 172, 177, 182, 166, 237, 2, 21, 0, 159, 146, 151, 237, 187, 8, 82, 115, 14, 183, 103, - 12, 203, 46, 161, 208, 251, 167, 123, 131, - ]) - .unwrap(); - let s = format!("{:?}", sig); - assert_eq!(s, "DsaSig { r: 774484690634577222213819810519929266740561094381, s: 910998676210681457251421818099943952372231273347 }"); - } -} diff --git a/patch/openssl/src/ec.rs b/patch/openssl/src/ec.rs deleted file mode 100644 index d646fdd90ae65..0000000000000 --- a/patch/openssl/src/ec.rs +++ /dev/null @@ -1,1385 +0,0 @@ -//! Elliptic Curve -//! -//! Cryptography relies on the difficulty of solving mathematical problems, such as the factor -//! of large integers composed of two large prime numbers and the discrete logarithm of a -//! random elliptic curve. This module provides low-level features of the latter. -//! Elliptic Curve protocols can provide the same security with smaller keys. -//! -//! There are 2 forms of elliptic curves, `Fp` and `F2^m`. These curves use irreducible -//! trinomial or pentanomial. Being a generic interface to a wide range of algorithms, -//! the curves are generally referenced by [`EcGroup`]. There are many built-in groups -//! found in [`Nid`]. -//! -//! OpenSSL Wiki explains the fields and curves in detail at [Elliptic Curve Cryptography]. -//! -//! [`EcGroup`]: struct.EcGroup.html -//! [`Nid`]: ../nid/struct.Nid.html -//! [Elliptic Curve Cryptography]: https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography -use cfg_if::cfg_if; -use foreign_types::{ForeignType, ForeignTypeRef}; -use libc::c_int; -use std::fmt; -use std::ptr; - -use crate::bn::{BigNum, BigNumContextRef, BigNumRef}; -use crate::error::ErrorStack; -use crate::nid::Nid; -use crate::pkey::{HasParams, HasPrivate, HasPublic, Params, Private, Public}; -use crate::util::ForeignTypeRefExt; -use crate::{cvt, cvt_n, cvt_p, init}; -use openssl_macros::corresponds; - -cfg_if! { - if #[cfg(not(any(boringssl, awslc)))] { - use std::ffi::CString; - use crate::string::OpensslString; - } -} - -/// Compressed or Uncompressed conversion -/// -/// Conversion from the binary value of the point on the curve is performed in one of -/// compressed, uncompressed, or hybrid conversions. The default is compressed, except -/// for binary curves. -/// -/// Further documentation is available in the [X9.62] standard. -/// -/// [X9.62]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.202.2977&rep=rep1&type=pdf -#[derive(Copy, Clone)] -pub struct PointConversionForm(ffi::point_conversion_form_t); - -impl PointConversionForm { - /// Compressed conversion from point value. - pub const COMPRESSED: PointConversionForm = - PointConversionForm(ffi::point_conversion_form_t::POINT_CONVERSION_COMPRESSED); - - /// Uncompressed conversion from point value. - pub const UNCOMPRESSED: PointConversionForm = - PointConversionForm(ffi::point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED); - - /// Performs both compressed and uncompressed conversions. - pub const HYBRID: PointConversionForm = - PointConversionForm(ffi::point_conversion_form_t::POINT_CONVERSION_HYBRID); -} - -/// Named Curve or Explicit -/// -/// This type acts as a boolean as to whether the `EcGroup` is named or explicit. -#[derive(Copy, Clone, Debug, PartialEq)] -pub struct Asn1Flag(c_int); - -impl Asn1Flag { - /// Curve defined using polynomial parameters - /// - /// Most applications use a named EC_GROUP curve, however, support - /// is included to explicitly define the curve used to calculate keys - /// This information would need to be known by both endpoint to make communication - /// effective. - /// - /// OPENSSL_EC_EXPLICIT_CURVE, but that was only added in 1.1. - /// Man page documents that 0 can be used in older versions. - /// - /// OpenSSL documentation at [`EC_GROUP`] - /// - /// [`EC_GROUP`]: https://docs.openssl.org/master/man3/EC_GROUP_get_seed_len/ - pub const EXPLICIT_CURVE: Asn1Flag = Asn1Flag(0); - - /// Standard Curves - /// - /// Curves that make up the typical encryption use cases. The collection of curves - /// are well known but extensible. - /// - /// OpenSSL documentation at [`EC_GROUP`] - /// - /// [`EC_GROUP`]: https://docs.openssl.org/master/man3/EC_GROUP_order_bits/ - pub const NAMED_CURVE: Asn1Flag = Asn1Flag(ffi::OPENSSL_EC_NAMED_CURVE); -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::EC_GROUP; - fn drop = ffi::EC_GROUP_free; - - /// Describes the curve - /// - /// A curve can be of the named curve type. These curves can be discovered - /// using openssl binary `openssl ecparam -list_curves`. Other operations - /// are available in the [wiki]. These named curves are available in the - /// [`Nid`] module. - /// - /// Curves can also be generated using prime field parameters or a binary field. - /// - /// Prime fields use the formula `y^2 mod p = x^3 + ax + b mod p`. Binary - /// fields use the formula `y^2 + xy = x^3 + ax^2 + b`. Named curves have - /// assured security. To prevent accidental vulnerabilities, they should - /// be preferred. - /// - /// [wiki]: https://wiki.openssl.org/index.php/Command_Line_Elliptic_Curve_Operations - /// [`Nid`]: ../nid/index.html - pub struct EcGroup; - /// Reference to [`EcGroup`] - /// - /// [`EcGroup`]: struct.EcGroup.html - pub struct EcGroupRef; -} - -impl EcGroup { - /// Returns the group of a standard named curve. - /// - /// # Examples - /// - /// ``` - /// # fn main() -> Result<(), Box> { - /// use openssl::nid::Nid; - /// use openssl::ec::{EcGroup, EcKey}; - /// - /// let nid = Nid::X9_62_PRIME256V1; // NIST P-256 curve - /// let group = EcGroup::from_curve_name(nid)?; - /// let key = EcKey::generate(&group)?; - /// # Ok(()) } - /// ``` - #[corresponds(EC_GROUP_new_by_curve_name)] - pub fn from_curve_name(nid: Nid) -> Result { - unsafe { - init(); - cvt_p(ffi::EC_GROUP_new_by_curve_name(nid.as_raw())).map(EcGroup) - } - } - - /// Returns the group for given parameters - #[corresponds(EC_GROUP_new_curve_GFp)] - pub fn from_components( - p: BigNum, - a: BigNum, - b: BigNum, - ctx: &mut BigNumContextRef, - ) -> Result { - unsafe { - cvt_p(ffi::EC_GROUP_new_curve_GFp( - p.as_ptr(), - a.as_ptr(), - b.as_ptr(), - ctx.as_ptr(), - )) - .map(EcGroup) - } - } -} - -impl EcGroupRef { - /// Places the components of a curve over a prime field in the provided `BigNum`s. - /// The components make up the formula `y^2 mod p = x^3 + ax + b mod p`. - #[corresponds(EC_GROUP_get_curve_GFp)] - pub fn components_gfp( - &self, - p: &mut BigNumRef, - a: &mut BigNumRef, - b: &mut BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EC_GROUP_get_curve_GFp( - self.as_ptr(), - p.as_ptr(), - a.as_ptr(), - b.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places the components of a curve over a binary field in the provided `BigNum`s. - /// The components make up the formula `y^2 + xy = x^3 + ax^2 + b`. - /// - /// In this form `p` relates to the irreducible polynomial. Each bit represents - /// a term in the polynomial. It will be set to 3 `1`s or 5 `1`s depending on - /// using a trinomial or pentanomial. - #[corresponds(EC_GROUP_get_curve_GF2m)] - #[cfg(not(osslconf = "OPENSSL_NO_EC2M"))] - pub fn components_gf2m( - &self, - p: &mut BigNumRef, - a: &mut BigNumRef, - b: &mut BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EC_GROUP_get_curve_GF2m( - self.as_ptr(), - p.as_ptr(), - a.as_ptr(), - b.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places the cofactor of the group in the provided `BigNum`. - #[corresponds(EC_GROUP_get_cofactor)] - pub fn cofactor( - &self, - cofactor: &mut BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EC_GROUP_get_cofactor( - self.as_ptr(), - cofactor.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Returns the degree of the curve. - #[corresponds(EC_GROUP_get_degree)] - pub fn degree(&self) -> u32 { - unsafe { ffi::EC_GROUP_get_degree(self.as_ptr()) as u32 } - } - - /// Returns the number of bits in the group order. - #[corresponds(EC_GROUP_order_bits)] - #[cfg(any(ossl110, libressl, awslc, boringssl))] - pub fn order_bits(&self) -> u32 { - unsafe { ffi::EC_GROUP_order_bits(self.as_ptr()) as u32 } - } - - /// Returns the generator for the given curve as an [`EcPoint`]. - #[corresponds(EC_GROUP_get0_generator)] - pub fn generator(&self) -> &EcPointRef { - unsafe { - let ptr = ffi::EC_GROUP_get0_generator(self.as_ptr()); - EcPointRef::from_const_ptr(ptr) - } - } - - /// Sets the generator point for the given curve - #[corresponds(EC_GROUP_set_generator)] - pub fn set_generator( - &mut self, - generator: EcPoint, - order: BigNum, - cofactor: BigNum, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EC_GROUP_set_generator( - self.as_ptr(), - generator.as_ptr(), - order.as_ptr(), - cofactor.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places the order of the curve in the provided `BigNum`. - #[corresponds(EC_GROUP_get_order)] - pub fn order( - &self, - order: &mut BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EC_GROUP_get_order( - self.as_ptr(), - order.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Sets the flag determining if the group corresponds to a named curve or must be explicitly - /// parameterized. - /// - /// This defaults to `EXPLICIT_CURVE` in OpenSSL 1.0.2, but `NAMED_CURVE` in OpenSSL - /// 1.1.0. - #[corresponds(EC_GROUP_set_asn1_flag)] - pub fn set_asn1_flag(&mut self, flag: Asn1Flag) { - unsafe { - ffi::EC_GROUP_set_asn1_flag(self.as_ptr(), flag.0); - } - } - - /// Gets the flag determining if the group corresponds to a named curve. - #[corresponds(EC_GROUP_get_asn1_flag)] - pub fn asn1_flag(&self) -> Asn1Flag { - unsafe { Asn1Flag(ffi::EC_GROUP_get_asn1_flag(self.as_ptr())) } - } - - /// Returns the name of the curve, if a name is associated. - #[corresponds(EC_GROUP_get_curve_name)] - pub fn curve_name(&self) -> Option { - let nid = unsafe { ffi::EC_GROUP_get_curve_name(self.as_ptr()) }; - if nid > 0 { - Some(Nid::from_raw(nid)) - } else { - None - } - } -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::EC_POINT; - fn drop = ffi::EC_POINT_free; - - /// Represents a point on the curve - pub struct EcPoint; - /// A reference a borrowed [`EcPoint`]. - pub struct EcPointRef; -} - -impl EcPointRef { - /// Computes `a + b`, storing the result in `self`. - #[corresponds(EC_POINT_add)] - pub fn add( - &mut self, - group: &EcGroupRef, - a: &EcPointRef, - b: &EcPointRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EC_POINT_add( - group.as_ptr(), - self.as_ptr(), - a.as_ptr(), - b.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Computes `q * m`, storing the result in `self`. - #[corresponds(EC_POINT_mul)] - pub fn mul( - &mut self, - group: &EcGroupRef, - q: &EcPointRef, - m: &BigNumRef, - // FIXME should be &mut - ctx: &BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EC_POINT_mul( - group.as_ptr(), - self.as_ptr(), - ptr::null(), - q.as_ptr(), - m.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Computes `generator * n`, storing the result in `self`. - #[corresponds(EC_POINT_mul)] - pub fn mul_generator( - &mut self, - group: &EcGroupRef, - n: &BigNumRef, - // FIXME should be &mut - ctx: &BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EC_POINT_mul( - group.as_ptr(), - self.as_ptr(), - n.as_ptr(), - ptr::null(), - ptr::null(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Computes `generator * n + q * m`, storing the result in `self`. - #[corresponds(EC_POINT_mul)] - pub fn mul_full( - &mut self, - group: &EcGroupRef, - n: &BigNumRef, - q: &EcPointRef, - m: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EC_POINT_mul( - group.as_ptr(), - self.as_ptr(), - n.as_ptr(), - q.as_ptr(), - m.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Inverts `self`. - #[corresponds(EC_POINT_invert)] - // FIXME should be mutable - pub fn invert(&mut self, group: &EcGroupRef, ctx: &BigNumContextRef) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EC_POINT_invert( - group.as_ptr(), - self.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Serializes the point to a binary representation. - #[corresponds(EC_POINT_point2oct)] - pub fn to_bytes( - &self, - group: &EcGroupRef, - form: PointConversionForm, - ctx: &mut BigNumContextRef, - ) -> Result, ErrorStack> { - unsafe { - let len = ffi::EC_POINT_point2oct( - group.as_ptr(), - self.as_ptr(), - form.0, - ptr::null_mut(), - 0, - ctx.as_ptr(), - ); - if len == 0 { - return Err(ErrorStack::get()); - } - let mut buf = vec![0; len]; - let len = ffi::EC_POINT_point2oct( - group.as_ptr(), - self.as_ptr(), - form.0, - buf.as_mut_ptr(), - len, - ctx.as_ptr(), - ); - if len == 0 { - Err(ErrorStack::get()) - } else { - Ok(buf) - } - } - } - - /// Serializes the point to a hexadecimal string representation. - #[corresponds(EC_POINT_point2hex)] - #[cfg(not(any(boringssl, awslc)))] - pub fn to_hex_str( - &self, - group: &EcGroupRef, - form: PointConversionForm, - ctx: &mut BigNumContextRef, - ) -> Result { - unsafe { - let buf = cvt_p(ffi::EC_POINT_point2hex( - group.as_ptr(), - self.as_ptr(), - form.0, - ctx.as_ptr(), - ))?; - Ok(OpensslString::from_ptr(buf)) - } - } - - /// Creates a new point on the specified curve with the same value. - #[corresponds(EC_POINT_dup)] - pub fn to_owned(&self, group: &EcGroupRef) -> Result { - unsafe { cvt_p(ffi::EC_POINT_dup(self.as_ptr(), group.as_ptr())).map(EcPoint) } - } - - /// Determines if this point is equal to another. - #[corresponds(EC_POINT_cmp)] - pub fn eq( - &self, - group: &EcGroupRef, - other: &EcPointRef, - ctx: &mut BigNumContextRef, - ) -> Result { - unsafe { - let res = cvt_n(ffi::EC_POINT_cmp( - group.as_ptr(), - self.as_ptr(), - other.as_ptr(), - ctx.as_ptr(), - ))?; - Ok(res == 0) - } - } - - /// Places affine coordinates of a curve over a prime field in the provided - /// `x` and `y` `BigNum`s. - #[corresponds(EC_POINT_get_affine_coordinates)] - #[cfg(any(ossl111, boringssl, libressl, awslc))] - pub fn affine_coordinates( - &self, - group: &EcGroupRef, - x: &mut BigNumRef, - y: &mut BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EC_POINT_get_affine_coordinates( - group.as_ptr(), - self.as_ptr(), - x.as_ptr(), - y.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places affine coordinates of a curve over a prime field in the provided - /// `x` and `y` `BigNum`s - #[corresponds(EC_POINT_get_affine_coordinates_GFp)] - pub fn affine_coordinates_gfp( - &self, - group: &EcGroupRef, - x: &mut BigNumRef, - y: &mut BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EC_POINT_get_affine_coordinates_GFp( - group.as_ptr(), - self.as_ptr(), - x.as_ptr(), - y.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Sets affine coordinates of a point on an elliptic curve using the provided - /// `x` and `y` `BigNum`s - #[corresponds(EC_POINT_set_affine_coordinates)] - #[cfg(any(ossl111, boringssl, libressl, awslc))] - pub fn set_affine_coordinates( - &mut self, - group: &EcGroupRef, - x: &BigNumRef, - y: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EC_POINT_set_affine_coordinates( - group.as_ptr(), - self.as_ptr(), - x.as_ptr(), - y.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Sets affine coordinates of a curve over a prime field using the provided - /// `x` and `y` `BigNum`s - #[corresponds(EC_POINT_set_affine_coordinates_GFp)] - pub fn set_affine_coordinates_gfp( - &mut self, - group: &EcGroupRef, - x: &BigNumRef, - y: &BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EC_POINT_set_affine_coordinates_GFp( - group.as_ptr(), - self.as_ptr(), - x.as_ptr(), - y.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Places affine coordinates of a curve over a binary field in the provided - /// `x` and `y` `BigNum`s - #[corresponds(EC_POINT_get_affine_coordinates_GF2m)] - #[cfg(not(osslconf = "OPENSSL_NO_EC2M"))] - pub fn affine_coordinates_gf2m( - &self, - group: &EcGroupRef, - x: &mut BigNumRef, - y: &mut BigNumRef, - ctx: &mut BigNumContextRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EC_POINT_get_affine_coordinates_GF2m( - group.as_ptr(), - self.as_ptr(), - x.as_ptr(), - y.as_ptr(), - ctx.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Checks if point is infinity - #[corresponds(EC_POINT_is_at_infinity)] - pub fn is_infinity(&self, group: &EcGroupRef) -> bool { - unsafe { - let res = ffi::EC_POINT_is_at_infinity(group.as_ptr(), self.as_ptr()); - res == 1 - } - } - - /// Checks if point is on a given curve - #[corresponds(EC_POINT_is_on_curve)] - pub fn is_on_curve( - &self, - group: &EcGroupRef, - ctx: &mut BigNumContextRef, - ) -> Result { - unsafe { - let res = cvt_n(ffi::EC_POINT_is_on_curve( - group.as_ptr(), - self.as_ptr(), - ctx.as_ptr(), - ))?; - Ok(res == 1) - } - } -} - -impl EcPoint { - /// Creates a new point on the specified curve. - #[corresponds(EC_POINT_new)] - pub fn new(group: &EcGroupRef) -> Result { - unsafe { cvt_p(ffi::EC_POINT_new(group.as_ptr())).map(EcPoint) } - } - - /// Creates point from a binary representation - #[corresponds(EC_POINT_oct2point)] - pub fn from_bytes( - group: &EcGroupRef, - buf: &[u8], - ctx: &mut BigNumContextRef, - ) -> Result { - let point = EcPoint::new(group)?; - unsafe { - cvt(ffi::EC_POINT_oct2point( - group.as_ptr(), - point.as_ptr(), - buf.as_ptr(), - buf.len(), - ctx.as_ptr(), - ))?; - } - Ok(point) - } - - /// Creates point from a hexadecimal string representation - #[corresponds(EC_POINT_hex2point)] - #[cfg(not(any(boringssl, awslc)))] - pub fn from_hex_str( - group: &EcGroupRef, - s: &str, - ctx: &mut BigNumContextRef, - ) -> Result { - let point = EcPoint::new(group)?; - unsafe { - let c_str = CString::new(s.as_bytes()).unwrap(); - cvt_p(ffi::EC_POINT_hex2point( - group.as_ptr(), - c_str.as_ptr() as *const _, - point.as_ptr(), - ctx.as_ptr(), - ))?; - } - Ok(point) - } -} - -generic_foreign_type_and_impl_send_sync! { - type CType = ffi::EC_KEY; - fn drop = ffi::EC_KEY_free; - - /// Public and optional private key on the given curve. - pub struct EcKey; - /// A reference to an [`EcKey`]. - pub struct EcKeyRef; -} - -impl EcKeyRef -where - T: HasPrivate, -{ - private_key_to_pem! { - /// Serializes the private key to a PEM-encoded ECPrivateKey structure. - /// - /// The output will have a header of `-----BEGIN EC PRIVATE KEY-----`. - #[corresponds(PEM_write_bio_ECPrivateKey)] - private_key_to_pem, - /// Serializes the private key to a PEM-encoded encrypted ECPrivateKey structure. - /// - /// The output will have a header of `-----BEGIN EC PRIVATE KEY-----`. - #[corresponds(PEM_write_bio_ECPrivateKey)] - private_key_to_pem_passphrase, - ffi::PEM_write_bio_ECPrivateKey - } - - to_der! { - /// Serializes the private key into a DER-encoded ECPrivateKey structure. - #[corresponds(i2d_ECPrivateKey)] - private_key_to_der, - ffi::i2d_ECPrivateKey - } - - /// Returns the private key value. - #[corresponds(EC_KEY_get0_private_key)] - pub fn private_key(&self) -> &BigNumRef { - unsafe { - let ptr = ffi::EC_KEY_get0_private_key(self.as_ptr()); - BigNumRef::from_const_ptr(ptr) - } - } -} - -impl EcKeyRef -where - T: HasPublic, -{ - /// Returns the public key. - #[corresponds(EC_KEY_get0_public_key)] - pub fn public_key(&self) -> &EcPointRef { - unsafe { - let ptr = ffi::EC_KEY_get0_public_key(self.as_ptr()); - EcPointRef::from_const_ptr(ptr) - } - } - - 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_EC_PUBKEY)] - public_key_to_pem, - ffi::PEM_write_bio_EC_PUBKEY - } - - to_der! { - /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure. - #[corresponds(i2d_EC_PUBKEY)] - public_key_to_der, - ffi::i2d_EC_PUBKEY - } -} - -impl EcKeyRef -where - T: HasParams, -{ - /// Returns the key's group. - #[corresponds(EC_KEY_get0_group)] - pub fn group(&self) -> &EcGroupRef { - unsafe { - let ptr = ffi::EC_KEY_get0_group(self.as_ptr()); - EcGroupRef::from_const_ptr(ptr) - } - } - - /// Checks the key for validity. - #[corresponds(EC_KEY_check_key)] - pub fn check_key(&self) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::EC_KEY_check_key(self.as_ptr())).map(|_| ()) } - } -} - -impl ToOwned for EcKeyRef { - type Owned = EcKey; - - fn to_owned(&self) -> EcKey { - unsafe { - let r = ffi::EC_KEY_up_ref(self.as_ptr()); - assert!(r == 1); - EcKey::from_ptr(self.as_ptr()) - } - } -} - -impl EcKey { - /// Constructs an `EcKey` corresponding to a known curve. - /// - /// It will not have an associated public or private key. This kind of key is primarily useful - /// to be provided to the `set_tmp_ecdh` methods on `Ssl` and `SslContextBuilder`. - #[corresponds(EC_KEY_new_by_curve_name)] - pub fn from_curve_name(nid: Nid) -> Result, ErrorStack> { - unsafe { - init(); - cvt_p(ffi::EC_KEY_new_by_curve_name(nid.as_raw())).map(|p| EcKey::from_ptr(p)) - } - } - - /// Constructs an `EcKey` corresponding to a curve. - #[corresponds(EC_KEY_set_group)] - pub fn from_group(group: &EcGroupRef) -> Result, ErrorStack> { - unsafe { - cvt_p(ffi::EC_KEY_new()) - .map(|p| EcKey::from_ptr(p)) - .and_then(|key| { - cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key) - }) - } - } -} - -impl EcKey { - /// Constructs an `EcKey` from the specified group with the associated [`EcPoint`]: `public_key`. - /// - /// This will only have the associated `public_key`. - /// - /// # Example - /// - /// ``` - /// # fn main() -> Result<(), Box> { - /// use openssl::bn::BigNumContext; - /// use openssl::ec::*; - /// use openssl::nid::Nid; - /// use openssl::pkey::PKey; - /// - /// let group = EcGroup::from_curve_name(Nid::SECP384R1)?; - /// let mut ctx = BigNumContext::new()?; - /// - /// // get bytes from somewhere - /// let public_key = // ... - /// # EcKey::generate(&group)?.public_key().to_bytes(&group, - /// # PointConversionForm::COMPRESSED, &mut ctx)?; - /// - /// // create an EcKey from the binary form of a EcPoint - /// let point = EcPoint::from_bytes(&group, &public_key, &mut ctx)?; - /// let key = EcKey::from_public_key(&group, &point)?; - /// key.check_key()?; - /// # Ok(()) } - /// ``` - #[corresponds(EC_KEY_set_public_key)] - pub fn from_public_key( - group: &EcGroupRef, - public_key: &EcPointRef, - ) -> Result, ErrorStack> { - unsafe { - cvt_p(ffi::EC_KEY_new()) - .map(|p| EcKey::from_ptr(p)) - .and_then(|key| { - cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key) - }) - .and_then(|key| { - cvt(ffi::EC_KEY_set_public_key( - key.as_ptr(), - public_key.as_ptr(), - )) - .map(|_| key) - }) - } - } - - /// Constructs a public key from its affine coordinates. - #[corresponds(EC_KEY_set_public_key_affine_coordinates)] - pub fn from_public_key_affine_coordinates( - group: &EcGroupRef, - x: &BigNumRef, - y: &BigNumRef, - ) -> Result, ErrorStack> { - unsafe { - cvt_p(ffi::EC_KEY_new()) - .map(|p| EcKey::from_ptr(p)) - .and_then(|key| { - cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key) - }) - .and_then(|key| { - cvt(ffi::EC_KEY_set_public_key_affine_coordinates( - key.as_ptr(), - x.as_ptr(), - y.as_ptr(), - )) - .map(|_| key) - }) - } - } - - from_pem! { - /// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing a EC key. - /// - /// The input should have a header of `-----BEGIN PUBLIC KEY-----`. - #[corresponds(PEM_read_bio_EC_PUBKEY)] - public_key_from_pem, - EcKey, - ffi::PEM_read_bio_EC_PUBKEY - } - - from_der! { - /// Decodes a DER-encoded SubjectPublicKeyInfo structure containing a EC key. - #[corresponds(d2i_EC_PUBKEY)] - public_key_from_der, - EcKey, - ffi::d2i_EC_PUBKEY - } -} - -impl EcKey { - /// Generates a new public/private key pair on the specified curve. - /// - /// # Examples - /// - /// ``` - /// # fn main() -> Result<(), Box> { - /// use openssl::bn::BigNumContext; - /// use openssl::nid::Nid; - /// use openssl::ec::{EcGroup, EcKey, PointConversionForm}; - /// - /// let nid = Nid::X9_62_PRIME256V1; // NIST P-256 curve - /// let group = EcGroup::from_curve_name(nid)?; - /// let key = EcKey::generate(&group)?; - /// - /// let mut ctx = BigNumContext::new()?; - /// - /// let public_key = &key.public_key().to_bytes( - /// &group, - /// PointConversionForm::COMPRESSED, - /// &mut ctx, - /// )?; - /// assert_eq!(public_key.len(), 33); - /// assert_ne!(public_key[0], 0x04); - /// - /// let private_key = key.private_key().to_vec(); - /// assert!(private_key.len() >= 31); - /// # Ok(()) } - /// ``` - #[corresponds(EC_KEY_generate_key)] - pub fn generate(group: &EcGroupRef) -> Result, ErrorStack> { - unsafe { - cvt_p(ffi::EC_KEY_new()) - .map(|p| EcKey::from_ptr(p)) - .and_then(|key| { - cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key) - }) - .and_then(|key| cvt(ffi::EC_KEY_generate_key(key.as_ptr())).map(|_| key)) - } - } - - /// Constructs an public/private key pair given a curve, a private key and a public key point. - #[corresponds(EC_KEY_set_private_key)] - pub fn from_private_components( - group: &EcGroupRef, - private_number: &BigNumRef, - public_key: &EcPointRef, - ) -> Result, ErrorStack> { - unsafe { - cvt_p(ffi::EC_KEY_new()) - .map(|p| EcKey::from_ptr(p)) - .and_then(|key| { - cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key) - }) - .and_then(|key| { - cvt(ffi::EC_KEY_set_private_key( - key.as_ptr(), - private_number.as_ptr(), - )) - .map(|_| key) - }) - .and_then(|key| { - cvt(ffi::EC_KEY_set_public_key( - key.as_ptr(), - public_key.as_ptr(), - )) - .map(|_| key) - }) - } - } - - private_key_from_pem! { - /// Deserializes a private key from a PEM-encoded ECPrivateKey structure. - /// - /// The input should have a header of `-----BEGIN EC PRIVATE KEY-----`. - #[corresponds(PEM_read_bio_ECPrivateKey)] - private_key_from_pem, - - /// Deserializes a private key from a PEM-encoded encrypted ECPrivateKey structure. - /// - /// The input should have a header of `-----BEGIN EC PRIVATE KEY-----`. - #[corresponds(PEM_read_bio_ECPrivateKey)] - private_key_from_pem_passphrase, - - /// Deserializes a private key from a PEM-encoded encrypted ECPrivateKey structure. - /// - /// The callback should fill the password into the provided buffer and return its length. - /// - /// The input should have a header of `-----BEGIN EC PRIVATE KEY-----`. - #[corresponds(PEM_read_bio_ECPrivateKey)] - private_key_from_pem_callback, - EcKey, - ffi::PEM_read_bio_ECPrivateKey - } - - from_der! { - /// Decodes a DER-encoded elliptic curve private key structure. - #[corresponds(d2i_ECPrivateKey)] - private_key_from_der, - EcKey, - ffi::d2i_ECPrivateKey - } -} - -impl Clone for EcKey { - fn clone(&self) -> EcKey { - (**self).to_owned() - } -} - -impl fmt::Debug for EcKey { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "EcKey") - } -} - -#[cfg(test)] -mod test { - use hex::FromHex; - - use super::*; - use crate::bn::{BigNum, BigNumContext}; - use crate::nid::Nid; - - #[test] - fn key_new_by_curve_name() { - EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - } - - #[test] - fn generate() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - EcKey::generate(&group).unwrap(); - } - - #[test] - fn ec_group_from_components() { - // parameters are from secp256r1 - let p = BigNum::from_hex_str( - "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", - ) - .unwrap(); - let a = BigNum::from_hex_str( - "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", - ) - .unwrap(); - let b = BigNum::from_hex_str( - "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", - ) - .unwrap(); - let mut ctx = BigNumContext::new().unwrap(); - - let _curve = EcGroup::from_components(p, a, b, &mut ctx).unwrap(); - } - - fn set_affine_coords_test( - set_affine_coords: fn( - &mut EcPointRef, - &EcGroupRef, - &BigNumRef, - &BigNumRef, - &mut BigNumContextRef, - ) -> Result<(), ErrorStack>, - ) { - // parameters are from secp256r1 - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let mut ctx = BigNumContext::new().unwrap(); - let mut gen_point = EcPoint::new(&group).unwrap(); - let gen_x = BigNum::from_hex_str( - "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", - ) - .unwrap(); - let gen_y = BigNum::from_hex_str( - "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", - ) - .unwrap(); - set_affine_coords(&mut gen_point, &group, &gen_x, &gen_y, &mut ctx).unwrap(); - - assert!(gen_point.is_on_curve(&group, &mut ctx).unwrap()); - } - - #[test] - fn ec_point_set_affine_gfp() { - set_affine_coords_test(EcPointRef::set_affine_coordinates_gfp) - } - - #[test] - #[cfg(any(ossl111, boringssl, libressl, awslc))] - fn ec_point_set_affine() { - set_affine_coords_test(EcPointRef::set_affine_coordinates) - } - - #[test] - fn ec_group_set_generator() { - // parameters are from secp256r1 - let mut ctx = BigNumContext::new().unwrap(); - let p = BigNum::from_hex_str( - "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", - ) - .unwrap(); - let a = BigNum::from_hex_str( - "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", - ) - .unwrap(); - let b = BigNum::from_hex_str( - "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", - ) - .unwrap(); - - let mut group = EcGroup::from_components(p, a, b, &mut ctx).unwrap(); - - let mut gen_point = EcPoint::new(&group).unwrap(); - let gen_x = BigNum::from_hex_str( - "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", - ) - .unwrap(); - let gen_y = BigNum::from_hex_str( - "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", - ) - .unwrap(); - gen_point - .set_affine_coordinates_gfp(&group, &gen_x, &gen_y, &mut ctx) - .unwrap(); - - let order = BigNum::from_hex_str( - "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", - ) - .unwrap(); - let cofactor = BigNum::from_hex_str("01").unwrap(); - group.set_generator(gen_point, order, cofactor).unwrap(); - let mut constructed_order = BigNum::new().unwrap(); - group.order(&mut constructed_order, &mut ctx).unwrap(); - - let named_group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let mut named_order = BigNum::new().unwrap(); - named_group.order(&mut named_order, &mut ctx).unwrap(); - - assert_eq!( - constructed_order.ucmp(&named_order), - std::cmp::Ordering::Equal - ); - } - - #[test] - fn cofactor() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let mut ctx = BigNumContext::new().unwrap(); - let mut cofactor = BigNum::new().unwrap(); - group.cofactor(&mut cofactor, &mut ctx).unwrap(); - let one = BigNum::from_u32(1).unwrap(); - assert_eq!(cofactor, one); - } - - #[test] - #[allow(clippy::redundant_clone)] - fn dup() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let key = EcKey::generate(&group).unwrap(); - drop(key.clone()); - } - - #[test] - fn point_new() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - EcPoint::new(&group).unwrap(); - } - - #[test] - fn point_bytes() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let key = EcKey::generate(&group).unwrap(); - let point = key.public_key(); - let mut ctx = BigNumContext::new().unwrap(); - let bytes = point - .to_bytes(&group, PointConversionForm::COMPRESSED, &mut ctx) - .unwrap(); - let point2 = EcPoint::from_bytes(&group, &bytes, &mut ctx).unwrap(); - assert!(point.eq(&group, &point2, &mut ctx).unwrap()); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn point_hex_str() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let key = EcKey::generate(&group).unwrap(); - let point = key.public_key(); - let mut ctx = BigNumContext::new().unwrap(); - let hex = point - .to_hex_str(&group, PointConversionForm::COMPRESSED, &mut ctx) - .unwrap(); - let point2 = EcPoint::from_hex_str(&group, &hex, &mut ctx).unwrap(); - assert!(point.eq(&group, &point2, &mut ctx).unwrap()); - } - - #[test] - fn point_owned() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let key = EcKey::generate(&group).unwrap(); - let point = key.public_key(); - let owned = point.to_owned(&group).unwrap(); - let mut ctx = BigNumContext::new().unwrap(); - assert!(owned.eq(&group, point, &mut ctx).unwrap()); - } - - #[test] - fn mul_generator() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let key = EcKey::generate(&group).unwrap(); - let mut ctx = BigNumContext::new().unwrap(); - let mut public_key = EcPoint::new(&group).unwrap(); - public_key - .mul_generator(&group, key.private_key(), &ctx) - .unwrap(); - assert!(public_key.eq(&group, key.public_key(), &mut ctx).unwrap()); - } - - #[test] - fn generator() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let gen = group.generator(); - let one = BigNum::from_u32(1).unwrap(); - let mut ctx = BigNumContext::new().unwrap(); - let mut ecp = EcPoint::new(&group).unwrap(); - ecp.mul_generator(&group, &one, &ctx).unwrap(); - assert!(ecp.eq(&group, gen, &mut ctx).unwrap()); - } - - #[test] - fn key_from_public_key() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let key = EcKey::generate(&group).unwrap(); - let mut ctx = BigNumContext::new().unwrap(); - let bytes = key - .public_key() - .to_bytes(&group, PointConversionForm::COMPRESSED, &mut ctx) - .unwrap(); - - drop(key); - let public_key = EcPoint::from_bytes(&group, &bytes, &mut ctx).unwrap(); - let ec_key = EcKey::from_public_key(&group, &public_key).unwrap(); - assert!(ec_key.check_key().is_ok()); - } - - #[test] - fn key_from_private_components() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let key = EcKey::generate(&group).unwrap(); - - let dup_key = - EcKey::from_private_components(&group, key.private_key(), key.public_key()).unwrap(); - dup_key.check_key().unwrap(); - - assert!(key.private_key() == dup_key.private_key()); - } - - #[test] - fn key_from_affine_coordinates() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let x = Vec::from_hex("30a0424cd21c2944838a2d75c92b37e76ea20d9f00893a3b4eee8a3c0aafec3e") - .unwrap(); - let y = Vec::from_hex("e04b65e92456d9888b52b379bdfbd51ee869ef1f0fc65b6659695b6cce081723") - .unwrap(); - - let xbn = BigNum::from_slice(&x).unwrap(); - let ybn = BigNum::from_slice(&y).unwrap(); - - let ec_key = EcKey::from_public_key_affine_coordinates(&group, &xbn, &ybn).unwrap(); - assert!(ec_key.check_key().is_ok()); - } - - #[cfg(any(ossl111, boringssl, libressl, awslc))] - #[test] - fn get_affine_coordinates() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let x = Vec::from_hex("30a0424cd21c2944838a2d75c92b37e76ea20d9f00893a3b4eee8a3c0aafec3e") - .unwrap(); - let y = Vec::from_hex("e04b65e92456d9888b52b379bdfbd51ee869ef1f0fc65b6659695b6cce081723") - .unwrap(); - - let xbn = BigNum::from_slice(&x).unwrap(); - let ybn = BigNum::from_slice(&y).unwrap(); - - let ec_key = EcKey::from_public_key_affine_coordinates(&group, &xbn, &ybn).unwrap(); - - let mut xbn2 = BigNum::new().unwrap(); - let mut ybn2 = BigNum::new().unwrap(); - let mut ctx = BigNumContext::new().unwrap(); - let ec_key_pk = ec_key.public_key(); - ec_key_pk - .affine_coordinates(&group, &mut xbn2, &mut ybn2, &mut ctx) - .unwrap(); - assert_eq!(xbn2, xbn); - assert_eq!(ybn2, ybn); - } - - #[test] - fn get_affine_coordinates_gfp() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let x = Vec::from_hex("30a0424cd21c2944838a2d75c92b37e76ea20d9f00893a3b4eee8a3c0aafec3e") - .unwrap(); - let y = Vec::from_hex("e04b65e92456d9888b52b379bdfbd51ee869ef1f0fc65b6659695b6cce081723") - .unwrap(); - - let xbn = BigNum::from_slice(&x).unwrap(); - let ybn = BigNum::from_slice(&y).unwrap(); - - let ec_key = EcKey::from_public_key_affine_coordinates(&group, &xbn, &ybn).unwrap(); - - let mut xbn2 = BigNum::new().unwrap(); - let mut ybn2 = BigNum::new().unwrap(); - let mut ctx = BigNumContext::new().unwrap(); - let ec_key_pk = ec_key.public_key(); - ec_key_pk - .affine_coordinates_gfp(&group, &mut xbn2, &mut ybn2, &mut ctx) - .unwrap(); - assert_eq!(xbn2, xbn); - assert_eq!(ybn2, ybn); - } - - #[test] - fn is_infinity() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let mut ctx = BigNumContext::new().unwrap(); - let g = group.generator(); - assert!(!g.is_infinity(&group)); - - let mut order = BigNum::new().unwrap(); - group.order(&mut order, &mut ctx).unwrap(); - let mut inf = EcPoint::new(&group).unwrap(); - inf.mul_generator(&group, &order, &ctx).unwrap(); - assert!(inf.is_infinity(&group)); - } - - #[test] - #[cfg(not(osslconf = "OPENSSL_NO_EC2M"))] - fn is_on_curve() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let mut ctx = BigNumContext::new().unwrap(); - let g = group.generator(); - assert!(g.is_on_curve(&group, &mut ctx).unwrap()); - - let group2 = EcGroup::from_curve_name(Nid::X9_62_PRIME239V3).unwrap(); - assert!(!g.is_on_curve(&group2, &mut ctx).unwrap()); - } - - #[test] - #[cfg(any(boringssl, ossl111, libressl, awslc))] - fn asn1_flag() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let flag = group.asn1_flag(); - assert_eq!(flag, Asn1Flag::NAMED_CURVE); - } -} diff --git a/patch/openssl/src/ecdsa.rs b/patch/openssl/src/ecdsa.rs deleted file mode 100644 index 25f0934cbd3d8..0000000000000 --- a/patch/openssl/src/ecdsa.rs +++ /dev/null @@ -1,224 +0,0 @@ -//! 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, LenType}; -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(data: &[u8], eckey: &EcKeyRef) -> Result - where - T: HasPrivate, - { - unsafe { - assert!(data.len() <= c_int::MAX as usize); - let sig = cvt_p(ffi::ECDSA_do_sign( - data.as_ptr(), - data.len() as LenType, - 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 { - 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(&self, data: &[u8], eckey: &EcKeyRef) -> Result - where - T: HasPublic, - { - unsafe { - assert!(data.len() <= c_int::MAX as usize); - cvt_n(ffi::ECDSA_do_verify( - data.as_ptr(), - data.len() as LenType, - 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, libressl, boringssl, awslc))] { - 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) -> Result, ErrorStack> { - EcKey::from_public_key(group, x.public_key()) - } - - #[test] - #[cfg_attr(osslconf = "OPENSSL_NO_EC", ignore)] - fn sign_and_verify() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).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_EC", ignore)] - fn check_private_components() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).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_EC", ignore)] - fn serialize_deserialize() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).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); - } -} diff --git a/patch/openssl/src/encrypt.rs b/patch/openssl/src/encrypt.rs deleted file mode 100644 index 7cadb31e5e36b..0000000000000 --- a/patch/openssl/src/encrypt.rs +++ /dev/null @@ -1,534 +0,0 @@ -//! 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); -//! ``` -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; -use openssl_macros::corresponds; - -/// A type which encrypts data. -pub struct Encrypter<'a> { - pctx: *mut ffi::EVP_PKEY_CTX, - _p: PhantomData<&'a ()>, -} - -unsafe impl Sync for Encrypter<'_> {} -unsafe impl Send for Encrypter<'_> {} - -impl Drop for Encrypter<'_> { - fn drop(&mut self) { - unsafe { - ffi::EVP_PKEY_CTX_free(self.pctx); - } - } -} - -impl<'a> Encrypter<'a> { - /// Creates a new `Encrypter`. - #[corresponds(EVP_PKEY_encrypt_init)] - pub fn new(pkey: &'a PKeyRef) -> Result, 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 { - 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. - #[corresponds(EVP_PKEY_CTX_set_rsa_padding)] - 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. - #[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)] - 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. - #[corresponds(EVP_PKEY_CTX_set_rsa_oaep_md)] - 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. - #[corresponds(EVP_PKEY_CTX_set0_rsa_oaep_label)] - 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.cast(), - label.len() as _, - )) - .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]; - /// ``` - /// - #[corresponds(EVP_PKEY_encrypt)] - pub fn encrypt(&self, from: &[u8], to: &mut [u8]) -> Result { - 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. - #[corresponds(EVP_PKEY_encrypt)] - pub fn encrypt_len(&self, from: &[u8]) -> Result { - 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 Sync for Decrypter<'_> {} -unsafe impl Send for Decrypter<'_> {} - -impl Drop for Decrypter<'_> { - fn drop(&mut self) { - unsafe { - ffi::EVP_PKEY_CTX_free(self.pctx); - } - } -} - -impl<'a> Decrypter<'a> { - /// Creates a new `Decrypter`. - #[corresponds(EVP_PKEY_decrypt_init)] - pub fn new(pkey: &'a PKeyRef) -> Result, 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 { - 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. - #[corresponds(EVP_PKEY_CTX_set_rsa_padding)] - 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. - #[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)] - 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. - #[corresponds(EVP_PKEY_CTX_set_rsa_oaep_md)] - 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. - #[corresponds(EVP_PKEY_CTX_set0_rsa_oaep_label)] - 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.cast(), - label.len() as _, - )) - .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]; - /// ``` - /// - #[corresponds(EVP_PKEY_decrypt)] - pub fn decrypt(&self, from: &[u8], to: &mut [u8]) -> Result { - 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. - #[corresponds(EVP_PKEY_decrypt)] - pub fn decrypt_len(&self, from: &[u8]) -> Result { - 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}; - 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] - 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] - 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()); - } -} diff --git a/patch/openssl/src/envelope.rs b/patch/openssl/src/envelope.rs deleted file mode 100644 index f6ebc722f42bd..0000000000000 --- a/patch/openssl/src/envelope.rs +++ /dev/null @@ -1,181 +0,0 @@ -//! 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>, - enc_keys: Vec>, -} - -impl Seal { - /// Creates a new `Seal`. - pub fn new(cipher: Cipher, pub_keys: &[PKey]) -> Result - 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] { - &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`. - pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result { - 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 { - self.ctx.cipher_final(output) - } -} - -/// Represents an EVP_Open context. -pub struct Open { - ctx: CipherCtx, -} - -impl Open { - /// Creates a new `Open`. - pub fn new( - cipher: Cipher, - priv_key: &PKeyRef, - iv: Option<&[u8]>, - encrypted_key: &[u8], - ) -> Result - 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`. - pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result { - 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 { - 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]); - } -} diff --git a/patch/openssl/src/error.rs b/patch/openssl/src/error.rs deleted file mode 100644 index c4553c68674b9..0000000000000 --- a/patch/openssl/src/error.rs +++ /dev/null @@ -1,418 +0,0 @@ -//! Errors returned by OpenSSL library. -//! -//! OpenSSL errors are stored in an `ErrorStack`. Most methods in the crate -//! returns a `Result` 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}; -use std::borrow::Cow; -#[cfg(any(boringssl, awslc))] -use std::convert::TryInto; -use std::error; -use std::ffi::CStr; -use std::fmt; -use std::io; -use std::ptr; -use std::str; - -#[cfg(not(any(boringssl, awslc)))] -type ErrType = libc::c_ulong; -#[cfg(any(boringssl, awslc))] -type ErrType = libc::c_uint; - -/// Collection of [`Error`]s from OpenSSL. -/// -/// [`Error`]: struct.Error.html -#[derive(Debug, Clone)] -pub struct ErrorStack(Vec); - -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 for io::Error { - fn from(e: ErrorStack) -> io::Error { - io::Error::new(io::ErrorKind::Other, e) - } -} - -impl From for fmt::Error { - fn from(_: ErrorStack) -> fmt::Error { - fmt::Error - } -} - -/// An error reported from OpenSSL. -#[derive(Clone)] -pub struct Error { - code: ErrType, - file: ShimStr, - line: c_int, - func: Option, - data: Option>, -} - -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 { - 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(); - #[cfg(not(any(boringssl, awslc)))] - let data = if flags & ffi::ERR_TXT_MALLOCED != 0 { - Cow::Owned(data.to_string()) - } else { - Cow::Borrowed(data) - }; - #[cfg(any(boringssl, awslc))] - let data = Cow::Borrowed(data); - Some(data) - } else { - None - }; - - let file = ShimStr::new(file); - - let func = if func.is_null() { - None - } else { - Some(ShimStr::new(func)) - }; - - 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.as_ptr(), - self.line, - self.func.as_ref().map_or(ptr::null(), |s| s.as_ptr()), - ); - ffi::ERR_set_error(self.library_code(), self.reason_code(), ptr::null()); - } - } - - #[cfg(not(ossl300))] - fn put_error(&self) { - #[cfg(not(any(boringssl, awslc)))] - let line = self.line; - #[cfg(any(boringssl, awslc))] - let line = self.line.try_into().unwrap(); - unsafe { - ffi::ERR_put_error( - self.library_code(), - ffi::ERR_GET_FUNC(self.code), - self.reason_code(), - self.file.as_ptr(), - line, - ); - } - } - - /// Returns the raw OpenSSL error code for this error. - pub fn code(&self) -> ErrType { - 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 raw OpenSSL error constant for the library reporting the - /// error. - // On AWS-LC and BoringSSL ERR_GET_{LIB,FUNC,REASON} are `unsafe`, but on - // OpenSSL/LibreSSL they're safe. - #[allow(unused_unsafe)] - pub fn library_code(&self) -> libc::c_int { - unsafe { ffi::ERR_GET_LIB(self.code) } - } - - /// Returns the name of the function reporting the error. - pub fn function(&self) -> Option> { - self.func.as_ref().map(|s| s.as_str()) - } - - /// 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 raw OpenSSL error constant for the reason for the error. - // On AWS-LC and BoringSSL ERR_GET_{LIB,FUNC,REASON} are `unsafe`, but on - // OpenSSL/LibreSSL they're safe. - #[allow(unused_unsafe)] - pub fn reason_code(&self) -> libc::c_int { - unsafe { ffi::ERR_GET_REASON(self.code) } - } - - /// Returns the name of the source file which encountered the error. - pub fn file(&self) -> RetStr<'_> { - self.file.as_str() - } - - /// 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 { - // On AWS-LC and BoringSSL ERR_GET_{LIB,FUNC,REASON} are `unsafe`, but on - // OpenSSL/LibreSSL they're safe. - #[allow(unused_unsafe)] - 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({})", self.library_code())?, - } - match self.function() { - Some(f) => write!(fmt, ":{}", f)?, - None => write!(fmt, ":func({})", unsafe { ffi::ERR_GET_FUNC(self.code()) })?, - } - match self.reason() { - Some(r) => write!(fmt, ":{}", r)?, - None => write!(fmt, ":reason({})", self.reason_code())?, - } - write!( - fmt, - ":{}:{}:{}", - self.file(), - self.line(), - self.data().unwrap_or("") - ) - } -} - -impl error::Error for Error {} - -cfg_if! { - if #[cfg(ossl300)] { - use std::ffi::{CString}; - use ffi::ERR_get_error_all; - - type RetStr<'a> = &'a str; - - #[derive(Clone)] - struct ShimStr(CString); - - impl ShimStr { - unsafe fn new(s: *const c_char) -> Self { - ShimStr(CStr::from_ptr(s).to_owned()) - } - - fn as_ptr(&self) -> *const c_char { - self.0.as_ptr() - } - - fn as_str(&self) -> &str { - self.0.to_str().unwrap() - } - } - } 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, - ) -> ErrType { - let code = ffi::ERR_get_error_line_data(file, line, data, flags); - *func = ffi::ERR_func_error_string(code); - code - } - - type RetStr<'a> = &'static str; - - #[derive(Clone)] - struct ShimStr(*const c_char); - - impl ShimStr { - unsafe fn new(s: *const c_char) -> Self { - ShimStr(s) - } - - fn as_ptr(&self) -> *const c_char { - self.0 - } - - fn as_str(&self) -> &'static str { - unsafe { - CStr::from_ptr(self.0).to_str().unwrap() - } - } - } - } -} - -#[cfg(test)] -mod tests { - #[cfg(not(ossl310))] - use crate::nid::Nid; - - #[test] - // Due to a bug in OpenSSL 3.1.0, this test can hang there. Skip for now. - #[cfg(not(ossl310))] - fn test_error_library_code() { - let stack = Nid::create("not-an-oid", "invalid", "invalid").unwrap_err(); - let errors = stack.errors(); - #[cfg(not(any(boringssl, awslc)))] - assert_eq!(errors[0].library_code(), ffi::ERR_LIB_ASN1); - #[cfg(any(boringssl, awslc))] - assert_eq!(errors[0].library_code(), ffi::ERR_LIB_OBJ as libc::c_int); - } -} diff --git a/patch/openssl/src/ex_data.rs b/patch/openssl/src/ex_data.rs deleted file mode 100644 index d4f0021293a69..0000000000000 --- a/patch/openssl/src/ex_data.rs +++ /dev/null @@ -1,32 +0,0 @@ -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(c_int, PhantomData<(T, U)>); - -impl Copy for Index {} - -impl Clone for Index { - fn clone(&self) -> Index { - *self - } -} - -impl Index { - /// 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 { - Index(idx, PhantomData) - } - - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn as_raw(&self) -> c_int { - self.0 - } -} diff --git a/patch/openssl/src/fips.rs b/patch/openssl/src/fips.rs deleted file mode 100644 index 2a8a2fe18d18e..0000000000000 --- a/patch/openssl/src/fips.rs +++ /dev/null @@ -1,21 +0,0 @@ -//! 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 } -} diff --git a/patch/openssl/src/hash.rs b/patch/openssl/src/hash.rs deleted file mode 100644 index fac3443a8e97b..0000000000000 --- a/patch/openssl/src/hash.rs +++ /dev/null @@ -1,891 +0,0 @@ -//! Message digest (hash) computation support. -//! -//! # Examples -//! -//! Calculate a hash in one go: -//! -//! ``` -//! # fn main() -> Result<(), Box> { -//! 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)?; -//! assert_eq!(&*res, spec); -//! # Ok(()) } -//! ``` -//! -//! Supply the input in chunks: -//! -//! ``` -//! use openssl::hash::{Hasher, MessageDigest}; -//! -//! # fn main() -> Result<(), Box> { -//! let mut hasher = Hasher::new(MessageDigest::sha256())?; -//! hasher.update(b"test")?; -//! hasher.update(b"this")?; -//! let digest: &[u8] = &hasher.finish()?; -//! -//! let expected = hex::decode("9740e652ab5b4acd997a7cca13d6696702ccb2d441cca59fc6e285127f28cfe6")?; -//! assert_eq!(digest, expected); -//! # Ok(()) } -//! ``` -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}; -use openssl_macros::corresponds; - -cfg_if! { - if #[cfg(any(ossl110, boringssl, libressl382, awslc))] { - 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}; - } -} - -/// A message digest algorithm. -#[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`. - #[corresponds(EVP_get_digestbynid)] - pub fn from_nid(type_: Nid) -> Option { - ffi::init(); - 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. - #[corresponds(EVP_get_digestbyname)] - pub fn from_name(name: &str) -> Option { - 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)) - } - } - } - - #[cfg(not(boringssl))] - 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(any(ossl111, libressl380, awslc))] - pub fn sha3_224() -> MessageDigest { - unsafe { MessageDigest(ffi::EVP_sha3_224()) } - } - - #[cfg(any(ossl111, libressl380, awslc))] - pub fn sha3_256() -> MessageDigest { - unsafe { MessageDigest(ffi::EVP_sha3_256()) } - } - - #[cfg(any(ossl111, libressl380, awslc))] - pub fn sha3_384() -> MessageDigest { - unsafe { MessageDigest(ffi::EVP_sha3_384()) } - } - - #[cfg(any(ossl111, libressl380, awslc))] - pub fn sha3_512() -> MessageDigest { - unsafe { MessageDigest(ffi::EVP_sha3_512()) } - } - - #[cfg(any(ossl111, awslc))] - pub fn shake_128() -> MessageDigest { - unsafe { MessageDigest(ffi::EVP_shake128()) } - } - - #[cfg(any(ossl111, awslc))] - 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, libressl), 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 block size of the digest in bytes. - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn block_size(&self) -> usize { - unsafe { ffi::EVP_MD_block_size(self.0) as usize } - } - - /// 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, - #[cfg(any(ossl330, awslc))] - Squeeze, - Finalized, -} - -use self::State::*; - -/// Provides message digest (hash) computation. -/// -/// # Examples -/// -/// ``` -/// use openssl::hash::{Hasher, MessageDigest}; -/// -/// # fn main() -> Result<(), Box> { -/// 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())?; -/// h.update(data[0])?; -/// h.update(data[1])?; -/// let res = h.finish()?; -/// assert_eq!(&*res, spec); -/// # Ok(()) } -/// ``` -/// -/// # 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 [`Hasher::finish_xof`] instead of [`Hasher::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 { - 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()?; - } - #[cfg(any(ossl330, awslc))] - Squeeze => (), - 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()?; - } - #[cfg(any(ossl330, awslc))] - if self.state == Squeeze { - // [`EVP_DigestUpdate`], depending on the implementation, may allow Updates after Squeezes. - // But, [FIPS 202], as shown in Figure 7, has a distinguished absorbing phase followed by a squeezing phase. - // Indeed, the [`sha3.c`] implementation disallows Updates after Squeezes. - // For consistency, we always return an error when Update is called after Squeeze. - // - // [`EVP_DigestUpdate`]: https://github.com/openssl/openssl/blob/b3bb214720f20f3b126ae4b9c330e9a48b835415/crypto/evp/digest.c#L385-L393 - // [FIPS 202]: https://dx.doi.org/10.6028/NIST.FIPS.202 - // [`sha3.c`]: https://github.com/openssl/openssl/blob/b3bb214720f20f3b126ae4b9c330e9a48b835415/crypto/sha/sha3.c#L52-L63 - let errors = ErrorStack::get(); - return Err(errors); - } - unsafe { - cvt(ffi::EVP_DigestUpdate( - self.ctx, - data.as_ptr() as *mut _, - data.len(), - ))?; - } - self.state = Updated; - Ok(()) - } - - /// Squeezes buf out of the hasher. Can be called multiple times, unlike `finish_xof`. - /// The output will be as long as the buf. - #[cfg(any(ossl330, awslc))] - pub fn squeeze_xof(&mut self, buf: &mut [u8]) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EVP_DigestSqueeze( - self.ctx, - buf.as_mut_ptr(), - buf.len(), - ))?; - self.state = Squeeze; - Ok(()) - } - } - - /// Returns the hash of the data written and resets the non-XOF hasher. - pub fn finish(&mut self) -> Result { - if self.state == Finalized { - self.init()?; - } - unsafe { - #[cfg(not(any(boringssl, awslc)))] - let mut len = ffi::EVP_MAX_MD_SIZE; - #[cfg(any(boringssl, awslc))] - let mut len = ffi::EVP_MAX_MD_SIZE as u32; - 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(any(ossl111, awslc))] - 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 { - 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`. -/// -/// # Examples -/// -/// ``` -/// # fn main() -> Result<(), Box> { -/// 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)?; -/// assert_eq!(&*res, spec); -/// # Ok(()) } -/// ``` -pub fn hash(t: MessageDigest, data: &[u8]) -> Result { - 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`. -/// -/// # Examples -/// -/// ``` -/// 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); -/// ``` -/// -#[cfg(any(ossl111, awslc))] -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(any(ossl111, awslc))] - 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); - } - - /// Squeezes the expected length by doing two squeezes. - #[cfg(any(ossl330, awslc))] - fn hash_xof_squeeze_test(hashtype: MessageDigest, hashtest: &(&str, &str)) { - let data = Vec::from_hex(hashtest.0).unwrap(); - let mut h = Hasher::new(hashtype).unwrap(); - h.update(&data).unwrap(); - - let expected = Vec::from_hex(hashtest.1).unwrap(); - let mut buf = vec![0; expected.len()]; - assert!(expected.len() > 10); - h.squeeze_xof(&mut buf[..10]).unwrap(); - h.squeeze_xof(&mut buf[10..]).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); - } - - assert_eq!(MessageDigest::md5().block_size(), 64); - assert_eq!(MessageDigest::md5().size(), 16); - assert_eq!(MessageDigest::md5().type_().as_raw(), Nid::MD5.as_raw()); - } - - #[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); - } - - #[cfg(any(ossl330, awslc))] - #[test] - fn test_finish_then_squeeze() { - let digest = MessageDigest::shake_128(); - let mut h = Hasher::new(digest).unwrap(); - let mut buf = vec![0; digest.size()]; - h.finish_xof(&mut buf).unwrap(); - h.squeeze_xof(&mut buf) - .expect_err("squeezing after finalize should fail"); - } - - #[cfg(any(ossl330, awslc))] - #[test] - fn test_squeeze_then_update() { - let digest = MessageDigest::shake_128(); - let data = Vec::from_hex(MD5_TESTS[6].0).unwrap(); - let mut h = Hasher::new(digest).unwrap(); - let mut buf = vec![0; digest.size()]; - h.squeeze_xof(&mut buf).unwrap(); - h.update(&data) - .expect_err("updating after squeeze should fail"); - } - - #[cfg(any(ossl330, awslc))] - #[test] - fn test_squeeze_then_finalize() { - let digest = MessageDigest::shake_128(); - let mut h = Hasher::new(digest).unwrap(); - let mut buf = vec![0; digest.size()]; - h.squeeze_xof(&mut buf).unwrap(); - if cfg!(ossl330) { - h.finish_xof(&mut buf) - .expect_err("finalize after squeeze should fail"); - } else if cfg!(awslc) { - h.finish_xof(&mut buf).unwrap(); - } - } - - #[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); - } - - assert_eq!(MessageDigest::sha1().block_size(), 64); - assert_eq!(MessageDigest::sha1().size(), 20); - assert_eq!(MessageDigest::sha1().type_().as_raw(), Nid::SHA1.as_raw()); - } - - #[test] - fn test_sha256() { - let tests = [( - "616263", - "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", - )]; - - for test in tests.iter() { - hash_test(MessageDigest::sha256(), test); - } - - assert_eq!(MessageDigest::sha256().block_size(), 64); - assert_eq!(MessageDigest::sha256().size(), 32); - assert_eq!( - MessageDigest::sha256().type_().as_raw(), - Nid::SHA256.as_raw() - ); - } - - #[test] - fn test_sha512() { - let tests = [( - "737465766566696e647365766572797468696e67", - "ba61d1f1af0f2dd80729f6cc900f19c0966bd38ba5c75e4471ef11b771dfe7551afab7fcbd300fdc4418f2\ - b07a028fcd99e7b6446a566f2d9bcd7c604a1ea801", - )]; - - for test in tests.iter() { - hash_test(MessageDigest::sha512(), test); - } - - assert_eq!(MessageDigest::sha512().block_size(), 128); - assert_eq!(MessageDigest::sha512().size(), 64); - assert_eq!( - MessageDigest::sha512().type_().as_raw(), - Nid::SHA512.as_raw() - ); - } - - #[cfg(any(ossl111, libressl380, awslc))] - #[test] - fn test_sha3_224() { - let tests = [( - "416c6c20796f75722062617365206172652062656c6f6e6720746f207573", - "1de092dd9fbcbbf450f26264f4778abd48af851f2832924554c56913", - )]; - - for test in tests.iter() { - hash_test(MessageDigest::sha3_224(), test); - } - - assert_eq!(MessageDigest::sha3_224().block_size(), 144); - assert_eq!(MessageDigest::sha3_224().size(), 28); - assert_eq!( - MessageDigest::sha3_224().type_().as_raw(), - Nid::SHA3_224.as_raw() - ); - } - - #[cfg(any(ossl111, libressl380, awslc))] - #[test] - fn test_sha3_256() { - let tests = [( - "416c6c20796f75722062617365206172652062656c6f6e6720746f207573", - "b38e38f08bc1c0091ed4b5f060fe13e86aa4179578513ad11a6e3abba0062f61", - )]; - - for test in tests.iter() { - hash_test(MessageDigest::sha3_256(), test); - } - - assert_eq!(MessageDigest::sha3_256().block_size(), 136); - assert_eq!(MessageDigest::sha3_256().size(), 32); - assert_eq!( - MessageDigest::sha3_256().type_().as_raw(), - Nid::SHA3_256.as_raw() - ); - } - - #[cfg(any(ossl111, libressl380, awslc))] - #[test] - fn test_sha3_384() { - let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573", - "966ee786ab3482dd811bf7c8fa8db79aa1f52f6c3c369942ef14240ebd857c6ff626ec35d9e131ff64d328\ - ef2008ff16" - )]; - - for test in tests.iter() { - hash_test(MessageDigest::sha3_384(), test); - } - - assert_eq!(MessageDigest::sha3_384().block_size(), 104); - assert_eq!(MessageDigest::sha3_384().size(), 48); - assert_eq!( - MessageDigest::sha3_384().type_().as_raw(), - Nid::SHA3_384.as_raw() - ); - } - - #[cfg(any(ossl111, libressl380, awslc))] - #[test] - fn test_sha3_512() { - let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573", - "c072288ef728cd53a029c47687960b9225893532f42b923156e37020bdc1eda753aafbf30af859d4f4c3a1\ - 807caee3a79f8eb02dcd61589fbbdf5f40c8787a72" - )]; - - for test in tests.iter() { - hash_test(MessageDigest::sha3_512(), test); - } - - assert_eq!(MessageDigest::sha3_512().block_size(), 72); - assert_eq!(MessageDigest::sha3_512().size(), 64); - assert_eq!( - MessageDigest::sha3_512().type_().as_raw(), - Nid::SHA3_512.as_raw() - ); - } - - #[cfg(any(ossl111, awslc))] - #[test] - fn test_shake_128() { - let tests = [( - "416c6c20796f75722062617365206172652062656c6f6e6720746f207573", - "49d0697ff508111d8b84f15e46daf135", - )]; - - for test in tests.iter() { - hash_xof_test(MessageDigest::shake_128(), test); - #[cfg(any(ossl330, awslc))] - hash_xof_squeeze_test(MessageDigest::shake_128(), test); - } - - assert_eq!(MessageDigest::shake_128().block_size(), 168); - #[cfg(ossl111)] - assert_eq!(MessageDigest::shake_128().size(), 16); - #[cfg(awslc)] - assert_eq!(MessageDigest::shake_128().size(), 0); - assert_eq!( - MessageDigest::shake_128().type_().as_raw(), - Nid::SHAKE128.as_raw() - ); - } - - #[cfg(any(ossl111, awslc))] - #[test] - fn test_shake_256() { - let tests = [( - "416c6c20796f75722062617365206172652062656c6f6e6720746f207573", - "4e2dfdaa75d1e049d0eaeffe28e76b17cea47b650fb8826fe48b94664326a697", - )]; - - for test in tests.iter() { - hash_xof_test(MessageDigest::shake_256(), test); - #[cfg(any(ossl330, awslc))] - hash_xof_squeeze_test(MessageDigest::shake_256(), test); - } - - assert_eq!(MessageDigest::shake_256().block_size(), 136); - #[cfg(ossl111)] - assert_eq!(MessageDigest::shake_256().size(), 32); - #[cfg(awslc)] - assert_eq!(MessageDigest::shake_256().size(), 0); - assert_eq!( - MessageDigest::shake_256().type_().as_raw(), - Nid::SHAKE256.as_raw() - ); - } - - #[test] - #[cfg(not(osslconf = "OPENSSL_NO_RMD160"))] - #[cfg_attr(ossl300, ignore)] - 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); - } - - assert_eq!(MessageDigest::ripemd160().block_size(), 64); - assert_eq!(MessageDigest::ripemd160().size(), 20); - assert_eq!( - MessageDigest::ripemd160().type_().as_raw(), - Nid::RIPEMD160.as_raw() - ); - } - - #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM3")))] - #[test] - fn test_sm3() { - let tests = [( - "616263", - "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0", - )]; - - for test in tests.iter() { - hash_test(MessageDigest::sm3(), test); - } - - assert_eq!(MessageDigest::sm3().block_size(), 64); - assert_eq!(MessageDigest::sm3().size(), 32); - assert_eq!(MessageDigest::sm3().type_().as_raw(), Nid::SM3.as_raw()); - } - - #[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() - ) - } -} diff --git a/patch/openssl/src/kdf.rs b/patch/openssl/src/kdf.rs deleted file mode 100644 index 902b532d5c1d1..0000000000000 --- a/patch/openssl/src/kdf.rs +++ /dev/null @@ -1,258 +0,0 @@ -#[cfg(ossl320)] -struct EvpKdf(*mut ffi::EVP_KDF); - -#[cfg(ossl320)] -impl Drop for EvpKdf { - fn drop(&mut self) { - unsafe { - ffi::EVP_KDF_free(self.0); - } - } -} - -#[cfg(ossl320)] -struct EvpKdfCtx(*mut ffi::EVP_KDF_CTX); - -#[cfg(ossl320)] -impl Drop for EvpKdfCtx { - fn drop(&mut self) { - unsafe { - ffi::EVP_KDF_CTX_free(self.0); - } - } -} - -cfg_if::cfg_if! { - if #[cfg(all(ossl320, not(osslconf = "OPENSSL_NO_ARGON2")))] { - use std::cmp; - use std::ffi::CStr; - use std::ptr; - use foreign_types::ForeignTypeRef; - use libc::c_char; - use crate::{cvt, cvt_p}; - use crate::lib_ctx::LibCtxRef; - use crate::error::ErrorStack; - use crate::ossl_param::OsslParamBuilder; - - // Safety: these all have null terminators. - // We cen remove these CStr::from_bytes_with_nul_unchecked calls - // when we upgrade to Rust 1.77+ with literal c"" syntax. - - const OSSL_KDF_PARAM_PASSWORD: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"pass\0") }; - const OSSL_KDF_PARAM_SALT: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"salt\0") }; - const OSSL_KDF_PARAM_SECRET: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"secret\0") }; - const OSSL_KDF_PARAM_ITER: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"iter\0") }; - const OSSL_KDF_PARAM_SIZE: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"size\0") }; - const OSSL_KDF_PARAM_THREADS: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"threads\0") }; - const OSSL_KDF_PARAM_ARGON2_AD: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"ad\0") }; - const OSSL_KDF_PARAM_ARGON2_LANES: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"lanes\0") }; - const OSSL_KDF_PARAM_ARGON2_MEMCOST: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"memcost\0") }; - - #[allow(clippy::too_many_arguments)] - pub fn argon2d( - ctx: Option<&LibCtxRef>, - pass: &[u8], - salt: &[u8], - ad: Option<&[u8]>, - secret: Option<&[u8]>, - iter: u32, - lanes: u32, - memcost: u32, - out: &mut [u8], - ) -> Result<(), ErrorStack> { - argon2_helper(CStr::from_bytes_with_nul(b"ARGON2D\0").unwrap(), ctx, pass, salt, ad, secret, iter, lanes, memcost, out) - } - - #[allow(clippy::too_many_arguments)] - pub fn argon2i( - ctx: Option<&LibCtxRef>, - pass: &[u8], - salt: &[u8], - ad: Option<&[u8]>, - secret: Option<&[u8]>, - iter: u32, - lanes: u32, - memcost: u32, - out: &mut [u8], - ) -> Result<(), ErrorStack> { - argon2_helper(CStr::from_bytes_with_nul(b"ARGON2I\0").unwrap(), ctx, pass, salt, ad, secret, iter, lanes, memcost, out) - } - - #[allow(clippy::too_many_arguments)] - pub fn argon2id( - ctx: Option<&LibCtxRef>, - pass: &[u8], - salt: &[u8], - ad: Option<&[u8]>, - secret: Option<&[u8]>, - iter: u32, - lanes: u32, - memcost: u32, - out: &mut [u8], - ) -> Result<(), ErrorStack> { - argon2_helper(CStr::from_bytes_with_nul(b"ARGON2ID\0").unwrap(), ctx, pass, salt, ad, secret, iter, lanes, memcost, out) - } - - /// Derives a key using the argon2* algorithms. - /// - /// To use multiple cores to process the lanes in parallel you must - /// set a global max thread count using `OSSL_set_max_threads`. On - /// builds with no threads all lanes will be processed sequentially. - /// - /// Requires OpenSSL 3.2.0 or newer. - #[allow(clippy::too_many_arguments)] - fn argon2_helper( - kdf_identifier: &CStr, - ctx: Option<&LibCtxRef>, - pass: &[u8], - salt: &[u8], - ad: Option<&[u8]>, - secret: Option<&[u8]>, - iter: u32, - lanes: u32, - memcost: u32, - out: &mut [u8], - ) -> Result<(), ErrorStack> { - let libctx = ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr); - let max_threads = unsafe { - ffi::init(); - ffi::OSSL_get_max_threads(libctx) - }; - let mut threads = 1; - // If max_threads is 0, then this isn't a threaded build. - // If max_threads is > u32::MAX we need to clamp since - // argon2id's threads parameter is a u32. - if max_threads > 0 { - threads = cmp::min(lanes, cmp::min(max_threads, u32::MAX as u64) as u32); - } - let mut bld = OsslParamBuilder::new()?; - bld.add_octet_string(OSSL_KDF_PARAM_PASSWORD, pass)?; - bld.add_octet_string(OSSL_KDF_PARAM_SALT, salt)?; - bld.add_uint(OSSL_KDF_PARAM_THREADS, threads)?; - bld.add_uint(OSSL_KDF_PARAM_ARGON2_LANES, lanes)?; - bld.add_uint(OSSL_KDF_PARAM_ARGON2_MEMCOST, memcost)?; - bld.add_uint(OSSL_KDF_PARAM_ITER, iter)?; - let size = out.len() as u32; - bld.add_uint(OSSL_KDF_PARAM_SIZE, size)?; - if let Some(ad) = ad { - bld.add_octet_string(OSSL_KDF_PARAM_ARGON2_AD, ad)?; - } - if let Some(secret) = secret { - bld.add_octet_string(OSSL_KDF_PARAM_SECRET, secret)?; - } - let params = bld.to_param()?; - unsafe { - let argon2 = EvpKdf(cvt_p(ffi::EVP_KDF_fetch( - libctx, - kdf_identifier.as_ptr() as *const c_char, - ptr::null(), - ))?); - let ctx = EvpKdfCtx(cvt_p(ffi::EVP_KDF_CTX_new(argon2.0))?); - cvt(ffi::EVP_KDF_derive( - ctx.0, - out.as_mut_ptr(), - out.len(), - params.as_ptr(), - )) - .map(|_| ()) - } - } - } -} - -#[cfg(test)] -mod tests { - #[test] - #[cfg(all(ossl320, not(osslconf = "OPENSSL_NO_ARGON2")))] - fn argon2id() { - // RFC 9106 test vector for argon2id - let pass = hex::decode("0101010101010101010101010101010101010101010101010101010101010101") - .unwrap(); - let salt = hex::decode("02020202020202020202020202020202").unwrap(); - let secret = hex::decode("0303030303030303").unwrap(); - let ad = hex::decode("040404040404040404040404").unwrap(); - let expected = "0d640df58d78766c08c037a34a8b53c9d01ef0452d75b65eb52520e96b01e659"; - - let mut actual = [0u8; 32]; - super::argon2id( - None, - &pass, - &salt, - Some(&ad), - Some(&secret), - 3, - 4, - 32, - &mut actual, - ) - .unwrap(); - assert_eq!(hex::encode(&actual[..]), expected); - } - - #[test] - #[cfg(all(ossl320, not(osslconf = "OPENSSL_NO_ARGON2")))] - fn argon2d() { - // RFC 9106 test vector for argon2d - let pass = hex::decode("0101010101010101010101010101010101010101010101010101010101010101") - .unwrap(); - let salt = hex::decode("02020202020202020202020202020202").unwrap(); - let secret = hex::decode("0303030303030303").unwrap(); - let ad = hex::decode("040404040404040404040404").unwrap(); - let expected = "512b391b6f1162975371d30919734294f868e3be3984f3c1a13a4db9fabe4acb"; - - let mut actual = [0u8; 32]; - super::argon2d( - None, - &pass, - &salt, - Some(&ad), - Some(&secret), - 3, - 4, - 32, - &mut actual, - ) - .unwrap(); - assert_eq!(hex::encode(&actual[..]), expected); - } - - #[test] - #[cfg(all(ossl320, not(osslconf = "OPENSSL_NO_ARGON2")))] - fn argon2i() { - // RFC 9106 test vector for argon2i - let pass = hex::decode("0101010101010101010101010101010101010101010101010101010101010101") - .unwrap(); - let salt = hex::decode("02020202020202020202020202020202").unwrap(); - let secret = hex::decode("0303030303030303").unwrap(); - let ad = hex::decode("040404040404040404040404").unwrap(); - let expected = "c814d9d1dc7f37aa13f0d77f2494bda1c8de6b016dd388d29952a4c4672b6ce8"; - - let mut actual = [0u8; 32]; - super::argon2i( - None, - &pass, - &salt, - Some(&ad), - Some(&secret), - 3, - 4, - 32, - &mut actual, - ) - .unwrap(); - assert_eq!(hex::encode(&actual[..]), expected); - } - - #[test] - #[cfg(all(ossl320, not(osslconf = "OPENSSL_NO_ARGON2")))] - fn argon2id_no_ad_secret() { - // Test vector from OpenSSL - let pass = b""; - let salt = hex::decode("02020202020202020202020202020202").unwrap(); - let expected = "0a34f1abde67086c82e785eaf17c68382259a264f4e61b91cd2763cb75ac189a"; - - let mut actual = [0u8; 32]; - super::argon2id(None, pass, &salt, None, None, 3, 4, 32, &mut actual).unwrap(); - assert_eq!(hex::encode(&actual[..]), expected); - } -} diff --git a/patch/openssl/src/lib.rs b/patch/openssl/src/lib.rs deleted file mode 100644 index eddf5d5bcb2c5..0000000000000 --- a/patch/openssl/src/lib.rs +++ /dev/null @@ -1,259 +0,0 @@ -//! Bindings to OpenSSL -//! -//! This crate provides a safe interface to the popular OpenSSL cryptography library. OpenSSL versions 1.0.2 through -//! 3.x.x and LibreSSL versions 3.5 through 4.2.x 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 be configured to automatically find a configuration and root certificates at `/usr/local/ssl`. -//! This path can be overridden with an environment variable (see the manual section below). -//! Alternatively, the `openssl-probe` crate can be used to find root certificates at runtime. -//! -//! ## 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@3 -//! -//! # macOS (MacPorts) -//! $ sudo port install openssl -//! -//! # macOS (pkgsrc) -//! $ sudo pkgin install openssl -//! -//! # Arch Linux -//! $ sudo pacman -S pkgconf openssl -//! -//! # Debian and Ubuntu -//! $ sudo apt-get install pkg-config libssl-dev -//! -//! # Fedora -//! $ sudo dnf install pkgconf perl-FindBin perl-IPC-Cmd openssl-devel -//! -//! # Alpine Linux -//! $ apk add pkgconf openssl-dev -//! -//! # openSUSE -//! $ sudo zypper in libopenssl-devel -//! ``` -//! -//! ## 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. -//! -//! If the `vendored` Cargo feature is enabled, the following environment variable can also be used to further configure -//! the OpenSSL build. -//! -//! * `OPENSSL_CONFIG_DIR` - If set, the copy of OpenSSL built by the `openssl-src` crate will be configured to look for -//! configuration files and root certificates in this directory. -//! -//! 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)] -#![allow(clippy::uninlined_format_args, clippy::needless_doctest_main)] - -#[doc(inline)] -pub use ffi::init; - -use libc::c_int; -#[cfg(ossl300)] -use libc::c_long; - -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; -#[cfg(not(any(boringssl, awslc)))] -pub mod envelope; -pub mod error; -pub mod ex_data; -#[cfg(not(any(libressl, ossl300)))] -pub mod fips; -pub mod hash; -pub mod kdf; -#[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; -#[cfg(ossl300)] -mod ossl_param; -pub mod pkcs12; -pub mod pkcs5; -#[cfg(not(any(boringssl, awslc)))] -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; - -#[cfg(any(boringssl, awslc))] -type LenType = libc::size_t; -#[cfg(not(any(boringssl, awslc)))] -type LenType = libc::c_int; - -#[cfg(any(boringssl, awslc))] -type SLenType = libc::ssize_t; -#[cfg(not(any(boringssl, awslc)))] -type SLenType = libc::c_int; - -#[inline] -fn cvt_p(r: *mut T) -> Result<*mut T, ErrorStack> { - if r.is_null() { - Err(ErrorStack::get()) - } else { - Ok(r) - } -} - -#[inline] -fn cvt_p_const(r: *const T) -> Result<*const T, ErrorStack> { - if r.is_null() { - Err(ErrorStack::get()) - } else { - Ok(r) - } -} - -#[inline] -fn cvt(r: c_int) -> Result { - if r <= 0 { - Err(ErrorStack::get()) - } else { - Ok(r) - } -} - -// cvt_long is currently only used in functions that require openssl >= 3.0.0, -// so this cfg statement is used to avoid "unused function" errors when -// compiling with openssl < 3.0.0 -#[inline] -#[cfg(ossl300)] -fn cvt_long(r: c_long) -> Result { - if r <= 0 { - Err(ErrorStack::get()) - } else { - Ok(r) - } -} - -#[inline] -fn cvt_n(r: c_int) -> Result { - if r < 0 { - Err(ErrorStack::get()) - } else { - Ok(r) - } -} diff --git a/patch/openssl/src/lib_ctx.rs b/patch/openssl/src/lib_ctx.rs deleted file mode 100644 index 1fcdc65ab255e..0000000000000 --- a/patch/openssl/src/lib_ctx.rs +++ /dev/null @@ -1,22 +0,0 @@ -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 { - unsafe { - let ptr = cvt_p(ffi::OSSL_LIB_CTX_new())?; - Ok(LibCtx::from_ptr(ptr)) - } - } -} diff --git a/patch/openssl/src/macros.rs b/patch/openssl/src/macros.rs deleted file mode 100644 index 8b561822d3e2c..0000000000000 --- a/patch/openssl/src/macros.rs +++ /dev/null @@ -1,270 +0,0 @@ -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(); - crate::cvt_p($f(bio.as_ptr(), - ::std::ptr::null_mut(), - None, - passphrase.as_ptr() as *const _ as *mut _)) - .map(|p| ::foreign_types::ForeignType::from_ptr(p)) - } - } - - $(#[$m3])* - pub fn $n3(pem: &[u8], callback: F) -> Result<$t, crate::error::ErrorStack> - where F: FnOnce(&mut [u8]) -> Result - { - unsafe { - ffi::init(); - let mut cb = crate::util::CallbackState::new(callback); - let bio = crate::bio::MemBioSlice::new(pem)?; - crate::cvt_p($f(bio.as_ptr(), - ::std::ptr::null_mut(), - Some(crate::util::invoke_passwd_cb::), - &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, crate::error::ErrorStack> { - unsafe { - let bio = crate::bio::MemBio::new()?; - crate::cvt($f(bio.as_ptr(), - self.as_ptr(), - ::std::ptr::null(), - ::std::ptr::null_mut(), - -1, - None, - ::std::ptr::null_mut()))?; - Ok(bio.get_buf().to_owned()) - } - } - - $(#[$m2])* - pub fn $n2( - &self, - cipher: crate::symm::Cipher, - passphrase: &[u8] - ) -> Result, crate::error::ErrorStack> { - unsafe { - let bio = crate::bio::MemBio::new()?; - assert!(passphrase.len() <= ::libc::c_int::MAX as usize); - crate::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, - ::std::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, crate::error::ErrorStack> { - unsafe { - let bio = crate::bio::MemBio::new()?; - crate::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, crate::error::ErrorStack> { - unsafe { - let len = crate::cvt($f(::foreign_types::ForeignTypeRef::as_ptr(self), - ::std::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> { - use std::convert::TryInto; - unsafe { - ffi::init(); - let len = ::std::cmp::min(der.len(), ::libc::c_long::MAX as usize) as ::libc::c_long; - crate::cvt_p($f(::std::ptr::null_mut(), &mut der.as_ptr(), len.try_into().unwrap())) - .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)?; - crate::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; - $(#[$borrowed_attr:meta])* - pub struct $borrowed:ident; - ) => { - $(#[$owned_attr])* - pub struct $owned(*mut $ctype, ::std::marker::PhantomData); - - $(#[$impl_attr])* - impl ::foreign_types::ForeignType for $owned { - type CType = $ctype; - type Ref = $borrowed; - - #[inline] - unsafe fn from_ptr(ptr: *mut $ctype) -> $owned { - $owned(ptr, ::std::marker::PhantomData) - } - - #[inline] - fn as_ptr(&self) -> *mut $ctype { - self.0 - } - } - - impl Drop for $owned { - #[inline] - fn drop(&mut self) { - unsafe { $drop(self.0) } - } - } - - $( - impl Clone for $owned { - #[inline] - fn clone(&self) -> $owned { - unsafe { - let handle: *mut $ctype = $clone(self.0); - ::foreign_types::ForeignType::from_ptr(handle) - } - } - } - - impl ::std::borrow::ToOwned for $borrowed { - type Owned = $owned; - #[inline] - fn to_owned(&self) -> $owned { - unsafe { - let handle: *mut $ctype = - $clone(::foreign_types::ForeignTypeRef::as_ptr(self)); - $crate::ForeignType::from_ptr(handle) - } - } - } - )* - - impl ::std::ops::Deref for $owned { - type Target = $borrowed; - - #[inline] - fn deref(&self) -> &$borrowed { - unsafe { ::foreign_types::ForeignTypeRef::from_ptr(self.0) } - } - } - - impl ::std::ops::DerefMut for $owned { - #[inline] - fn deref_mut(&mut self) -> &mut $borrowed { - unsafe { ::foreign_types::ForeignTypeRef::from_ptr_mut(self.0) } - } - } - - impl ::std::borrow::Borrow<$borrowed> for $owned { - #[inline] - fn borrow(&self) -> &$borrowed { - &**self - } - } - - impl ::std::convert::AsRef<$borrowed> for $owned { - #[inline] - fn as_ref(&self) -> &$borrowed { - &**self - } - } - - $(#[$borrowed_attr])* - pub struct $borrowed(::foreign_types::Opaque, ::std::marker::PhantomData); - - $(#[$impl_attr])* - impl ::foreign_types::ForeignTypeRef for $borrowed { - type CType = $ctype; - } - - unsafe impl Send for $owned{} - unsafe impl Send for $borrowed{} - unsafe impl Sync for $owned{} - unsafe impl Sync for $borrowed{} - }; -} diff --git a/patch/openssl/src/md.rs b/patch/openssl/src/md.rs deleted file mode 100644 index 1ac9d5e313711..0000000000000 --- a/patch/openssl/src/md.rs +++ /dev/null @@ -1,247 +0,0 @@ -//! Message digest algorithms. - -#[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> { - ffi::init(); - 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 { - ffi::init(); - 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.as_ref().map_or(ptr::null_mut(), |s| s.as_ptr()), - ))?; - - Ok(Md::from_ptr(ptr)) - } - } - - #[inline] - #[cfg(not(boringssl))] - 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(any(ossl111, libressl380))] - #[inline] - pub fn sha3_224() -> &'static MdRef { - unsafe { MdRef::from_ptr(ffi::EVP_sha3_224() as *mut _) } - } - - #[cfg(any(ossl111, libressl380))] - #[inline] - pub fn sha3_256() -> &'static MdRef { - unsafe { MdRef::from_ptr(ffi::EVP_sha3_256() as *mut _) } - } - - #[cfg(any(ossl111, libressl380))] - #[inline] - pub fn sha3_384() -> &'static MdRef { - unsafe { MdRef::from_ptr(ffi::EVP_sha3_384() as *mut _) } - } - - #[cfg(any(ossl111, libressl380))] - #[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, libressl), 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 block size of the digest in bytes. - #[corresponds(EVP_MD_block_size)] - #[inline] - pub fn block_size(&self) -> usize { - unsafe { ffi::EVP_MD_block_size(self.as_ptr()) as usize } - } - - /// 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())) } - } -} - -#[cfg(test)] -mod test { - #[cfg(ossl300)] - use super::Md; - - #[test] - #[cfg(ossl300)] - fn test_md_fetch_properties() { - assert!(Md::fetch(None, "SHA-256", Some("provider=gibberish")).is_err()); - } -} diff --git a/patch/openssl/src/md_ctx.rs b/patch/openssl/src/md_ctx.rs deleted file mode 100644 index 0182907ad6e40..0000000000000 --- a/patch/openssl/src/md_ctx.rs +++ /dev/null @@ -1,552 +0,0 @@ -//! 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); -//! ``` -//! - -#![cfg_attr( - not(any(boringssl, awslc)), - doc = r#"\ -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, HasPublic, PKeyRef}; -use crate::pkey_ctx::PkeyCtxRef; -use crate::{cvt, 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(any(ossl110, boringssl, libressl382, awslc))] { - 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 { - 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, - ) -> Result<&'a mut PkeyCtxRef, 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, - ) -> Result<&'a mut PkeyCtxRef, ErrorStack> - where - T: HasPublic, - { - 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 { - 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(any(ossl111, awslc))] - 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 { - 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) -> Result { - 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 { - unsafe { - let r = ffi::EVP_DigestVerifyFinal( - self.as_ptr(), - signature.as_ptr() as *mut _, - signature.len(), - ); - if r == 1 { - Ok(true) - } else { - let errors = ErrorStack::get(); - if errors.errors().is_empty() { - Ok(false) - } else { - Err(errors) - } - } - } - } - - /// 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 { - 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, - ) -> Result { - 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 { - unsafe { - let r = cvt(ffi::EVP_DigestVerify( - self.as_ptr(), - signature.as_ptr(), - signature.len(), - data.as_ptr(), - data.len(), - ))?; - Ok(r == 1) - } - } - - /// Returns the size of the message digest, i.e. the size of the hash - #[corresponds(EVP_MD_CTX_size)] - #[inline] - pub fn size(&self) -> usize { - unsafe { ffi::EVP_MD_CTX_size(self.as_ptr()) as usize } - } - - /// Resets the underlying EVP_MD_CTX instance - #[corresponds(EVP_MD_CTX_reset)] - #[cfg(ossl111)] - #[inline] - pub fn reset(&mut self) -> Result<(), ErrorStack> { - unsafe { - let _ = cvt(ffi::EVP_MD_CTX_reset(self.as_ptr()))?; - Ok(()) - } - } -} - -#[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(); - assert!(matches!( - ctx.digest_verify_final(&signature), - Ok(false) | Err(_) - )); - assert!(ErrorStack::get().errors().is_empty()); - } - - #[test] - fn verify_success() { - let key1 = Rsa::generate(2048).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 good_data = b"Some Crypto Text"; - - ctx.digest_verify_init(Some(md), &key1).unwrap(); - ctx.digest_verify_update(good_data).unwrap(); - let valid = ctx.digest_verify_final(&signature).unwrap(); - assert!(valid); - } - - #[test] - fn verify_with_public_success() { - let rsa = Rsa::generate(2048).unwrap(); - let key1 = PKey::from_rsa(rsa.clone()).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 good_data = b"Some Crypto Text"; - - // try to verify using only public components of the key - let n = rsa.n().to_owned().unwrap(); - let e = rsa.e().to_owned().unwrap(); - - let rsa = Rsa::from_public_components(n, e).unwrap(); - let key1 = PKey::from_rsa(rsa).unwrap(); - - ctx.digest_verify_init(Some(md), &key1).unwrap(); - ctx.digest_verify_update(good_data).unwrap(); - let valid = ctx.digest_verify_final(&signature).unwrap(); - assert!(valid); - } - - #[test] - fn verify_md_ctx_size() { - let mut ctx = MdCtx::new().unwrap(); - ctx.digest_init(Md::sha224()).unwrap(); - assert_eq!(Md::sha224().size(), ctx.size()); - assert_eq!(Md::sha224().size(), 28); - - let mut ctx = MdCtx::new().unwrap(); - ctx.digest_init(Md::sha256()).unwrap(); - assert_eq!(Md::sha256().size(), ctx.size()); - assert_eq!(Md::sha256().size(), 32); - - let mut ctx = MdCtx::new().unwrap(); - ctx.digest_init(Md::sha384()).unwrap(); - assert_eq!(Md::sha384().size(), ctx.size()); - assert_eq!(Md::sha384().size(), 48); - - let mut ctx = MdCtx::new().unwrap(); - ctx.digest_init(Md::sha512()).unwrap(); - assert_eq!(Md::sha512().size(), ctx.size()); - assert_eq!(Md::sha512().size(), 64); - } - - #[test] - #[cfg(ossl111)] - fn verify_md_ctx_reset() { - let hello_expected = - hex::decode("185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969") - .unwrap(); - let world_expected = - hex::decode("78ae647dc5544d227130a0682a51e30bc7777fbb6d8a8f17007463a3ecd1d524") - .unwrap(); - // Calculate SHA-256 digest of "Hello" - let mut ctx = MdCtx::new().unwrap(); - ctx.digest_init(Md::sha256()).unwrap(); - ctx.digest_update(b"Hello").unwrap(); - let mut result = vec![0; 32]; - let result_len = ctx.digest_final(result.as_mut_slice()).unwrap(); - assert_eq!(result_len, result.len()); - // Validate result of "Hello" - assert_eq!(result, hello_expected); - - // Create new context - let mut ctx = MdCtx::new().unwrap(); - // Initialize and update to "Hello" - ctx.digest_init(Md::sha256()).unwrap(); - ctx.digest_update(b"Hello").unwrap(); - // Now reset, init to SHA-256 and use "World" - ctx.reset().unwrap(); - ctx.digest_init(Md::sha256()).unwrap(); - ctx.digest_update(b"World").unwrap(); - - let mut reset_result = vec![0; 32]; - let result_len = ctx.digest_final(reset_result.as_mut_slice()).unwrap(); - assert_eq!(result_len, reset_result.len()); - // Validate result of digest of "World" - assert_eq!(reset_result, world_expected); - } -} diff --git a/patch/openssl/src/memcmp.rs b/patch/openssl/src/memcmp.rs deleted file mode 100644 index 91281b9af304b..0000000000000 --- a/patch/openssl/src/memcmp.rs +++ /dev/null @@ -1,93 +0,0 @@ -//! 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]); - } -} diff --git a/patch/openssl/src/nid.rs b/patch/openssl/src/nid.rs deleted file mode 100644 index b4aba6bcbc1e4..0000000000000 --- a/patch/openssl/src/nid.rs +++ /dev/null @@ -1,1181 +0,0 @@ -//! A collection of numerical identifiers for OpenSSL objects. -use libc::{c_char, c_int}; - -use std::ffi::CStr; -use std::ffi::CString; -use std::str; - -use crate::cvt_p; -use crate::error::ErrorStack; -use openssl_macros::corresponds; - -/// The digest and public-key algorithms associated with a signature. -pub struct SignatureAlgorithms { - /// The signature's digest. - /// - /// If the signature does not specify a digest, this will be `NID::UNDEF`. - pub digest: Nid, - - /// The signature's public-key. - pub pkey: Nid, -} - -/// A numerical identifier for an OpenSSL object. -/// -/// Objects in OpenSSL can have a short name, a long name, and -/// a numerical identifier (NID). For convenience, objects -/// are usually represented in source code using these numeric -/// identifiers. -/// -/// Users should generally not need to create new `Nid`s. -/// -/// # Examples -/// -/// To view the integer representation of a `Nid`: -/// -/// ``` -/// use openssl::nid::Nid; -/// -/// assert!(Nid::AES_256_GCM.as_raw() == 901); -/// ``` -/// -/// # External Documentation -/// -/// The following documentation provides context about `Nid`s and their usage -/// in OpenSSL. -/// -/// - [Obj_nid2obj](https://docs.openssl.org/master/man3/OBJ_create/) -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct Nid(c_int); - -#[allow(non_snake_case)] -impl Nid { - /// Create a `Nid` from an integer representation. - pub const fn from_raw(raw: c_int) -> Nid { - Nid(raw) - } - - /// Return the integer representation of a `Nid`. - #[allow(clippy::trivially_copy_pass_by_ref)] - pub const fn as_raw(&self) -> c_int { - self.0 - } - - /// Creates a new `Nid` for the `oid` with short name `sn` and long name `ln`. - #[corresponds(OBJ_create)] - pub fn create(oid: &str, sn: &str, ln: &str) -> Result { - unsafe { - ffi::init(); - let oid = CString::new(oid).unwrap(); - let sn = CString::new(sn).unwrap(); - let ln = CString::new(ln).unwrap(); - let raw = ffi::OBJ_create(oid.as_ptr(), sn.as_ptr(), ln.as_ptr()); - if raw == ffi::NID_undef { - Err(ErrorStack::get()) - } else { - Ok(Nid(raw)) - } - } - } - - /// Returns the `Nid`s of the digest and public key algorithms associated with a signature ID. - #[corresponds(OBJ_find_sigid_algs)] - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn signature_algorithms(&self) -> Option { - unsafe { - let mut digest = 0; - let mut pkey = 0; - if ffi::OBJ_find_sigid_algs(self.0, &mut digest, &mut pkey) == 1 { - Some(SignatureAlgorithms { - digest: Nid(digest), - pkey: Nid(pkey), - }) - } else { - None - } - } - } - - /// Returns the string representation of a `Nid` (long). - #[corresponds(OBJ_nid2ln)] - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn long_name(&self) -> Result<&'static str, ErrorStack> { - unsafe { - cvt_p(ffi::OBJ_nid2ln(self.0) as *mut c_char) - .map(|nameptr| str::from_utf8(CStr::from_ptr(nameptr).to_bytes()).unwrap()) - } - } - - /// Returns the string representation of a `Nid` (short). - #[corresponds(OBJ_nid2sn)] - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn short_name(&self) -> Result<&'static str, ErrorStack> { - unsafe { - cvt_p(ffi::OBJ_nid2sn(self.0) as *mut c_char) - .map(|nameptr| str::from_utf8(CStr::from_ptr(nameptr).to_bytes()).unwrap()) - } - } - - pub const UNDEF: Nid = Nid(ffi::NID_undef); - pub const ITU_T: Nid = Nid(ffi::NID_itu_t); - #[cfg(not(any(boringssl, awslc)))] - pub const CCITT: Nid = Nid(ffi::NID_ccitt); - pub const ISO: Nid = Nid(ffi::NID_iso); - pub const JOINT_ISO_ITU_T: Nid = Nid(ffi::NID_joint_iso_itu_t); - #[cfg(not(any(boringssl, awslc)))] - pub const JOINT_ISO_CCITT: Nid = Nid(ffi::NID_joint_iso_ccitt); - pub const MEMBER_BODY: Nid = Nid(ffi::NID_member_body); - pub const IDENTIFIED_ORGANIZATION: Nid = Nid(ffi::NID_identified_organization); - pub const HMAC_MD5: Nid = Nid(ffi::NID_hmac_md5); - pub const HMAC_SHA1: Nid = Nid(ffi::NID_hmac_sha1); - pub const CERTICOM_ARC: Nid = Nid(ffi::NID_certicom_arc); - pub const INTERNATIONAL_ORGANIZATIONS: Nid = Nid(ffi::NID_international_organizations); - pub const WAP: Nid = Nid(ffi::NID_wap); - pub const WAP_WSG: Nid = Nid(ffi::NID_wap_wsg); - pub const SELECTED_ATTRIBUTE_TYPES: Nid = Nid(ffi::NID_selected_attribute_types); - pub const CLEARANCE: Nid = Nid(ffi::NID_clearance); - pub const ISO_US: Nid = Nid(ffi::NID_ISO_US); - pub const X9_57: Nid = Nid(ffi::NID_X9_57); - pub const X9CM: Nid = Nid(ffi::NID_X9cm); - pub const DSA: Nid = Nid(ffi::NID_dsa); - pub const DSAWITHSHA1: Nid = Nid(ffi::NID_dsaWithSHA1); - pub const ANSI_X9_62: Nid = Nid(ffi::NID_ansi_X9_62); - pub const X9_62_PRIME_FIELD: Nid = Nid(ffi::NID_X9_62_prime_field); - pub const X9_62_CHARACTERISTIC_TWO_FIELD: Nid = Nid(ffi::NID_X9_62_characteristic_two_field); - pub const X9_62_ID_CHARACTERISTIC_TWO_BASIS: Nid = - Nid(ffi::NID_X9_62_id_characteristic_two_basis); - pub const X9_62_ONBASIS: Nid = Nid(ffi::NID_X9_62_onBasis); - pub const X9_62_TPBASIS: Nid = Nid(ffi::NID_X9_62_tpBasis); - pub const X9_62_PPBASIS: Nid = Nid(ffi::NID_X9_62_ppBasis); - pub const X9_62_ID_ECPUBLICKEY: Nid = Nid(ffi::NID_X9_62_id_ecPublicKey); - pub const X9_62_C2PNB163V1: Nid = Nid(ffi::NID_X9_62_c2pnb163v1); - pub const X9_62_C2PNB163V2: Nid = Nid(ffi::NID_X9_62_c2pnb163v2); - pub const X9_62_C2PNB163V3: Nid = Nid(ffi::NID_X9_62_c2pnb163v3); - pub const X9_62_C2PNB176V1: Nid = Nid(ffi::NID_X9_62_c2pnb176v1); - pub const X9_62_C2TNB191V1: Nid = Nid(ffi::NID_X9_62_c2tnb191v1); - pub const X9_62_C2TNB191V2: Nid = Nid(ffi::NID_X9_62_c2tnb191v2); - pub const X9_62_C2TNB191V3: Nid = Nid(ffi::NID_X9_62_c2tnb191v3); - pub const X9_62_C2ONB191V4: Nid = Nid(ffi::NID_X9_62_c2onb191v4); - pub const X9_62_C2ONB191V5: Nid = Nid(ffi::NID_X9_62_c2onb191v5); - pub const X9_62_C2PNB208W1: Nid = Nid(ffi::NID_X9_62_c2pnb208w1); - pub const X9_62_C2TNB239V1: Nid = Nid(ffi::NID_X9_62_c2tnb239v1); - pub const X9_62_C2TNB239V2: Nid = Nid(ffi::NID_X9_62_c2tnb239v2); - pub const X9_62_C2TNB239V3: Nid = Nid(ffi::NID_X9_62_c2tnb239v3); - pub const X9_62_C2ONB239V4: Nid = Nid(ffi::NID_X9_62_c2onb239v4); - pub const X9_62_C2ONB239V5: Nid = Nid(ffi::NID_X9_62_c2onb239v5); - pub const X9_62_C2PNB272W1: Nid = Nid(ffi::NID_X9_62_c2pnb272w1); - pub const X9_62_C2PNB304W1: Nid = Nid(ffi::NID_X9_62_c2pnb304w1); - pub const X9_62_C2TNB359V1: Nid = Nid(ffi::NID_X9_62_c2tnb359v1); - pub const X9_62_C2PNB368W1: Nid = Nid(ffi::NID_X9_62_c2pnb368w1); - pub const X9_62_C2TNB431R1: Nid = Nid(ffi::NID_X9_62_c2tnb431r1); - pub const X9_62_PRIME192V1: Nid = Nid(ffi::NID_X9_62_prime192v1); - pub const X9_62_PRIME192V2: Nid = Nid(ffi::NID_X9_62_prime192v2); - pub const X9_62_PRIME192V3: Nid = Nid(ffi::NID_X9_62_prime192v3); - pub const X9_62_PRIME239V1: Nid = Nid(ffi::NID_X9_62_prime239v1); - pub const X9_62_PRIME239V2: Nid = Nid(ffi::NID_X9_62_prime239v2); - pub const X9_62_PRIME239V3: Nid = Nid(ffi::NID_X9_62_prime239v3); - pub const X9_62_PRIME256V1: Nid = Nid(ffi::NID_X9_62_prime256v1); - pub const ECDSA_WITH_SHA1: Nid = Nid(ffi::NID_ecdsa_with_SHA1); - pub const ECDSA_WITH_RECOMMENDED: Nid = Nid(ffi::NID_ecdsa_with_Recommended); - pub const ECDSA_WITH_SPECIFIED: Nid = Nid(ffi::NID_ecdsa_with_Specified); - pub const ECDSA_WITH_SHA224: Nid = Nid(ffi::NID_ecdsa_with_SHA224); - pub const ECDSA_WITH_SHA256: Nid = Nid(ffi::NID_ecdsa_with_SHA256); - pub const ECDSA_WITH_SHA384: Nid = Nid(ffi::NID_ecdsa_with_SHA384); - pub const ECDSA_WITH_SHA512: Nid = Nid(ffi::NID_ecdsa_with_SHA512); - pub const SECP112R1: Nid = Nid(ffi::NID_secp112r1); - pub const SECP112R2: Nid = Nid(ffi::NID_secp112r2); - pub const SECP128R1: Nid = Nid(ffi::NID_secp128r1); - pub const SECP128R2: Nid = Nid(ffi::NID_secp128r2); - pub const SECP160K1: Nid = Nid(ffi::NID_secp160k1); - pub const SECP160R1: Nid = Nid(ffi::NID_secp160r1); - pub const SECP160R2: Nid = Nid(ffi::NID_secp160r2); - pub const SECP192K1: Nid = Nid(ffi::NID_secp192k1); - pub const SECP224K1: Nid = Nid(ffi::NID_secp224k1); - pub const SECP224R1: Nid = Nid(ffi::NID_secp224r1); - pub const SECP256K1: Nid = Nid(ffi::NID_secp256k1); - pub const SECP384R1: Nid = Nid(ffi::NID_secp384r1); - pub const SECP521R1: Nid = Nid(ffi::NID_secp521r1); - pub const SECT113R1: Nid = Nid(ffi::NID_sect113r1); - pub const SECT113R2: Nid = Nid(ffi::NID_sect113r2); - pub const SECT131R1: Nid = Nid(ffi::NID_sect131r1); - pub const SECT131R2: Nid = Nid(ffi::NID_sect131r2); - pub const SECT163K1: Nid = Nid(ffi::NID_sect163k1); - pub const SECT163R1: Nid = Nid(ffi::NID_sect163r1); - pub const SECT163R2: Nid = Nid(ffi::NID_sect163r2); - pub const SECT193R1: Nid = Nid(ffi::NID_sect193r1); - pub const SECT193R2: Nid = Nid(ffi::NID_sect193r2); - pub const SECT233K1: Nid = Nid(ffi::NID_sect233k1); - pub const SECT233R1: Nid = Nid(ffi::NID_sect233r1); - pub const SECT239K1: Nid = Nid(ffi::NID_sect239k1); - pub const SECT283K1: Nid = Nid(ffi::NID_sect283k1); - pub const SECT283R1: Nid = Nid(ffi::NID_sect283r1); - pub const SECT409K1: Nid = Nid(ffi::NID_sect409k1); - pub const SECT409R1: Nid = Nid(ffi::NID_sect409r1); - pub const SECT571K1: Nid = Nid(ffi::NID_sect571k1); - pub const SECT571R1: Nid = Nid(ffi::NID_sect571r1); - #[cfg(any(ossl110, libressl))] - pub const BRAINPOOL_P256R1: Nid = Nid(ffi::NID_brainpoolP256r1); - #[cfg(any(ossl110, libressl))] - pub const BRAINPOOL_P320R1: Nid = Nid(ffi::NID_brainpoolP320r1); - #[cfg(any(ossl110, libressl))] - pub const BRAINPOOL_P384R1: Nid = Nid(ffi::NID_brainpoolP384r1); - #[cfg(any(ossl110, libressl))] - pub const BRAINPOOL_P512R1: Nid = Nid(ffi::NID_brainpoolP512r1); - pub const WAP_WSG_IDM_ECID_WTLS1: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls1); - pub const WAP_WSG_IDM_ECID_WTLS3: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls3); - pub const WAP_WSG_IDM_ECID_WTLS4: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls4); - pub const WAP_WSG_IDM_ECID_WTLS5: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls5); - pub const WAP_WSG_IDM_ECID_WTLS6: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls6); - pub const WAP_WSG_IDM_ECID_WTLS7: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls7); - pub const WAP_WSG_IDM_ECID_WTLS8: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls8); - pub const WAP_WSG_IDM_ECID_WTLS9: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls9); - pub const WAP_WSG_IDM_ECID_WTLS10: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls10); - pub const WAP_WSG_IDM_ECID_WTLS11: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls11); - pub const WAP_WSG_IDM_ECID_WTLS12: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls12); - pub const CAST5_CBC: Nid = Nid(ffi::NID_cast5_cbc); - pub const CAST5_ECB: Nid = Nid(ffi::NID_cast5_ecb); - pub const CAST5_CFB64: Nid = Nid(ffi::NID_cast5_cfb64); - pub const CAST5_OFB64: Nid = Nid(ffi::NID_cast5_ofb64); - pub const PBEWITHMD5ANDCAST5_CBC: Nid = Nid(ffi::NID_pbeWithMD5AndCast5_CBC); - pub const ID_PASSWORDBASEDMAC: Nid = Nid(ffi::NID_id_PasswordBasedMAC); - pub const ID_DHBASEDMAC: Nid = Nid(ffi::NID_id_DHBasedMac); - pub const RSADSI: Nid = Nid(ffi::NID_rsadsi); - pub const PKCS: Nid = Nid(ffi::NID_pkcs); - pub const PKCS1: Nid = Nid(ffi::NID_pkcs1); - pub const RSAENCRYPTION: Nid = Nid(ffi::NID_rsaEncryption); - pub const MD2WITHRSAENCRYPTION: Nid = Nid(ffi::NID_md2WithRSAEncryption); - pub const MD4WITHRSAENCRYPTION: Nid = Nid(ffi::NID_md4WithRSAEncryption); - pub const MD5WITHRSAENCRYPTION: Nid = Nid(ffi::NID_md5WithRSAEncryption); - pub const SHA1WITHRSAENCRYPTION: Nid = Nid(ffi::NID_sha1WithRSAEncryption); - pub const RSAESOAEP: Nid = Nid(ffi::NID_rsaesOaep); - pub const MGF1: Nid = Nid(ffi::NID_mgf1); - pub const RSASSAPSS: Nid = Nid(ffi::NID_rsassaPss); - pub const SHA256WITHRSAENCRYPTION: Nid = Nid(ffi::NID_sha256WithRSAEncryption); - pub const SHA384WITHRSAENCRYPTION: Nid = Nid(ffi::NID_sha384WithRSAEncryption); - pub const SHA512WITHRSAENCRYPTION: Nid = Nid(ffi::NID_sha512WithRSAEncryption); - pub const SHA224WITHRSAENCRYPTION: Nid = Nid(ffi::NID_sha224WithRSAEncryption); - pub const PKCS3: Nid = Nid(ffi::NID_pkcs3); - pub const DHKEYAGREEMENT: Nid = Nid(ffi::NID_dhKeyAgreement); - pub const PKCS5: Nid = Nid(ffi::NID_pkcs5); - pub const PBEWITHMD2ANDDES_CBC: Nid = Nid(ffi::NID_pbeWithMD2AndDES_CBC); - pub const PBEWITHMD5ANDDES_CBC: Nid = Nid(ffi::NID_pbeWithMD5AndDES_CBC); - pub const PBEWITHMD2ANDRC2_CBC: Nid = Nid(ffi::NID_pbeWithMD2AndRC2_CBC); - pub const PBEWITHMD5ANDRC2_CBC: Nid = Nid(ffi::NID_pbeWithMD5AndRC2_CBC); - pub const PBEWITHSHA1ANDDES_CBC: Nid = Nid(ffi::NID_pbeWithSHA1AndDES_CBC); - pub const PBEWITHSHA1ANDRC2_CBC: Nid = Nid(ffi::NID_pbeWithSHA1AndRC2_CBC); - pub const ID_PBKDF2: Nid = Nid(ffi::NID_id_pbkdf2); - pub const PBES2: Nid = Nid(ffi::NID_pbes2); - pub const PBMAC1: Nid = Nid(ffi::NID_pbmac1); - pub const PKCS7: Nid = Nid(ffi::NID_pkcs7); - pub const PKCS7_DATA: Nid = Nid(ffi::NID_pkcs7_data); - pub const PKCS7_SIGNED: Nid = Nid(ffi::NID_pkcs7_signed); - pub const PKCS7_ENVELOPED: Nid = Nid(ffi::NID_pkcs7_enveloped); - pub const PKCS7_SIGNEDANDENVELOPED: Nid = Nid(ffi::NID_pkcs7_signedAndEnveloped); - pub const PKCS7_DIGEST: Nid = Nid(ffi::NID_pkcs7_digest); - pub const PKCS7_ENCRYPTED: Nid = Nid(ffi::NID_pkcs7_encrypted); - pub const PKCS9: Nid = Nid(ffi::NID_pkcs9); - pub const PKCS9_EMAILADDRESS: Nid = Nid(ffi::NID_pkcs9_emailAddress); - pub const PKCS9_UNSTRUCTUREDNAME: Nid = Nid(ffi::NID_pkcs9_unstructuredName); - pub const PKCS9_CONTENTTYPE: Nid = Nid(ffi::NID_pkcs9_contentType); - pub const PKCS9_MESSAGEDIGEST: Nid = Nid(ffi::NID_pkcs9_messageDigest); - pub const PKCS9_SIGNINGTIME: Nid = Nid(ffi::NID_pkcs9_signingTime); - pub const PKCS9_COUNTERSIGNATURE: Nid = Nid(ffi::NID_pkcs9_countersignature); - pub const PKCS9_CHALLENGEPASSWORD: Nid = Nid(ffi::NID_pkcs9_challengePassword); - pub const PKCS9_UNSTRUCTUREDADDRESS: Nid = Nid(ffi::NID_pkcs9_unstructuredAddress); - pub const PKCS9_EXTCERTATTRIBUTES: Nid = Nid(ffi::NID_pkcs9_extCertAttributes); - pub const EXT_REQ: Nid = Nid(ffi::NID_ext_req); - pub const SMIMECAPABILITIES: Nid = Nid(ffi::NID_SMIMECapabilities); - pub const SMIME: Nid = Nid(ffi::NID_SMIME); - pub const ID_SMIME_MOD: Nid = Nid(ffi::NID_id_smime_mod); - pub const ID_SMIME_CT: Nid = Nid(ffi::NID_id_smime_ct); - pub const ID_SMIME_AA: Nid = Nid(ffi::NID_id_smime_aa); - pub const ID_SMIME_ALG: Nid = Nid(ffi::NID_id_smime_alg); - pub const ID_SMIME_CD: Nid = Nid(ffi::NID_id_smime_cd); - pub const ID_SMIME_SPQ: Nid = Nid(ffi::NID_id_smime_spq); - pub const ID_SMIME_CTI: Nid = Nid(ffi::NID_id_smime_cti); - pub const ID_SMIME_MOD_CMS: Nid = Nid(ffi::NID_id_smime_mod_cms); - pub const ID_SMIME_MOD_ESS: Nid = Nid(ffi::NID_id_smime_mod_ess); - pub const ID_SMIME_MOD_OID: Nid = Nid(ffi::NID_id_smime_mod_oid); - pub const ID_SMIME_MOD_MSG_V3: Nid = Nid(ffi::NID_id_smime_mod_msg_v3); - pub const ID_SMIME_MOD_ETS_ESIGNATURE_88: Nid = Nid(ffi::NID_id_smime_mod_ets_eSignature_88); - pub const ID_SMIME_MOD_ETS_ESIGNATURE_97: Nid = Nid(ffi::NID_id_smime_mod_ets_eSignature_97); - pub const ID_SMIME_MOD_ETS_ESIGPOLICY_88: Nid = Nid(ffi::NID_id_smime_mod_ets_eSigPolicy_88); - pub const ID_SMIME_MOD_ETS_ESIGPOLICY_97: Nid = Nid(ffi::NID_id_smime_mod_ets_eSigPolicy_97); - pub const ID_SMIME_CT_RECEIPT: Nid = Nid(ffi::NID_id_smime_ct_receipt); - pub const ID_SMIME_CT_AUTHDATA: Nid = Nid(ffi::NID_id_smime_ct_authData); - pub const ID_SMIME_CT_PUBLISHCERT: Nid = Nid(ffi::NID_id_smime_ct_publishCert); - pub const ID_SMIME_CT_TSTINFO: Nid = Nid(ffi::NID_id_smime_ct_TSTInfo); - pub const ID_SMIME_CT_TDTINFO: Nid = Nid(ffi::NID_id_smime_ct_TDTInfo); - pub const ID_SMIME_CT_CONTENTINFO: Nid = Nid(ffi::NID_id_smime_ct_contentInfo); - pub const ID_SMIME_CT_DVCSREQUESTDATA: Nid = Nid(ffi::NID_id_smime_ct_DVCSRequestData); - pub const ID_SMIME_CT_DVCSRESPONSEDATA: Nid = Nid(ffi::NID_id_smime_ct_DVCSResponseData); - pub const ID_SMIME_CT_COMPRESSEDDATA: Nid = Nid(ffi::NID_id_smime_ct_compressedData); - pub const ID_CT_ASCIITEXTWITHCRLF: Nid = Nid(ffi::NID_id_ct_asciiTextWithCRLF); - pub const ID_SMIME_AA_RECEIPTREQUEST: Nid = Nid(ffi::NID_id_smime_aa_receiptRequest); - pub const ID_SMIME_AA_SECURITYLABEL: Nid = Nid(ffi::NID_id_smime_aa_securityLabel); - pub const ID_SMIME_AA_MLEXPANDHISTORY: Nid = Nid(ffi::NID_id_smime_aa_mlExpandHistory); - pub const ID_SMIME_AA_CONTENTHINT: Nid = Nid(ffi::NID_id_smime_aa_contentHint); - pub const ID_SMIME_AA_MSGSIGDIGEST: Nid = Nid(ffi::NID_id_smime_aa_msgSigDigest); - pub const ID_SMIME_AA_ENCAPCONTENTTYPE: Nid = Nid(ffi::NID_id_smime_aa_encapContentType); - pub const ID_SMIME_AA_CONTENTIDENTIFIER: Nid = Nid(ffi::NID_id_smime_aa_contentIdentifier); - pub const ID_SMIME_AA_MACVALUE: Nid = Nid(ffi::NID_id_smime_aa_macValue); - pub const ID_SMIME_AA_EQUIVALENTLABELS: Nid = Nid(ffi::NID_id_smime_aa_equivalentLabels); - pub const ID_SMIME_AA_CONTENTREFERENCE: Nid = Nid(ffi::NID_id_smime_aa_contentReference); - pub const ID_SMIME_AA_ENCRYPKEYPREF: Nid = Nid(ffi::NID_id_smime_aa_encrypKeyPref); - pub const ID_SMIME_AA_SIGNINGCERTIFICATE: Nid = Nid(ffi::NID_id_smime_aa_signingCertificate); - pub const ID_SMIME_AA_SMIMEENCRYPTCERTS: Nid = Nid(ffi::NID_id_smime_aa_smimeEncryptCerts); - pub const ID_SMIME_AA_TIMESTAMPTOKEN: Nid = Nid(ffi::NID_id_smime_aa_timeStampToken); - pub const ID_SMIME_AA_ETS_SIGPOLICYID: Nid = Nid(ffi::NID_id_smime_aa_ets_sigPolicyId); - pub const ID_SMIME_AA_ETS_COMMITMENTTYPE: Nid = Nid(ffi::NID_id_smime_aa_ets_commitmentType); - pub const ID_SMIME_AA_ETS_SIGNERLOCATION: Nid = Nid(ffi::NID_id_smime_aa_ets_signerLocation); - pub const ID_SMIME_AA_ETS_SIGNERATTR: Nid = Nid(ffi::NID_id_smime_aa_ets_signerAttr); - pub const ID_SMIME_AA_ETS_OTHERSIGCERT: Nid = Nid(ffi::NID_id_smime_aa_ets_otherSigCert); - pub const ID_SMIME_AA_ETS_CONTENTTIMESTAMP: Nid = - Nid(ffi::NID_id_smime_aa_ets_contentTimestamp); - pub const ID_SMIME_AA_ETS_CERTIFICATEREFS: Nid = Nid(ffi::NID_id_smime_aa_ets_CertificateRefs); - pub const ID_SMIME_AA_ETS_REVOCATIONREFS: Nid = Nid(ffi::NID_id_smime_aa_ets_RevocationRefs); - pub const ID_SMIME_AA_ETS_CERTVALUES: Nid = Nid(ffi::NID_id_smime_aa_ets_certValues); - pub const ID_SMIME_AA_ETS_REVOCATIONVALUES: Nid = - Nid(ffi::NID_id_smime_aa_ets_revocationValues); - pub const ID_SMIME_AA_ETS_ESCTIMESTAMP: Nid = Nid(ffi::NID_id_smime_aa_ets_escTimeStamp); - pub const ID_SMIME_AA_ETS_CERTCRLTIMESTAMP: Nid = - Nid(ffi::NID_id_smime_aa_ets_certCRLTimestamp); - pub const ID_SMIME_AA_ETS_ARCHIVETIMESTAMP: Nid = - Nid(ffi::NID_id_smime_aa_ets_archiveTimeStamp); - pub const ID_SMIME_AA_SIGNATURETYPE: Nid = Nid(ffi::NID_id_smime_aa_signatureType); - pub const ID_SMIME_AA_DVCS_DVC: Nid = Nid(ffi::NID_id_smime_aa_dvcs_dvc); - pub const ID_SMIME_ALG_ESDHWITH3DES: Nid = Nid(ffi::NID_id_smime_alg_ESDHwith3DES); - pub const ID_SMIME_ALG_ESDHWITHRC2: Nid = Nid(ffi::NID_id_smime_alg_ESDHwithRC2); - pub const ID_SMIME_ALG_3DESWRAP: Nid = Nid(ffi::NID_id_smime_alg_3DESwrap); - pub const ID_SMIME_ALG_RC2WRAP: Nid = Nid(ffi::NID_id_smime_alg_RC2wrap); - pub const ID_SMIME_ALG_ESDH: Nid = Nid(ffi::NID_id_smime_alg_ESDH); - pub const ID_SMIME_ALG_CMS3DESWRAP: Nid = Nid(ffi::NID_id_smime_alg_CMS3DESwrap); - pub const ID_SMIME_ALG_CMSRC2WRAP: Nid = Nid(ffi::NID_id_smime_alg_CMSRC2wrap); - pub const ID_ALG_PWRI_KEK: Nid = Nid(ffi::NID_id_alg_PWRI_KEK); - pub const ID_SMIME_CD_LDAP: Nid = Nid(ffi::NID_id_smime_cd_ldap); - pub const ID_SMIME_SPQ_ETS_SQT_URI: Nid = Nid(ffi::NID_id_smime_spq_ets_sqt_uri); - pub const ID_SMIME_SPQ_ETS_SQT_UNOTICE: Nid = Nid(ffi::NID_id_smime_spq_ets_sqt_unotice); - pub const ID_SMIME_CTI_ETS_PROOFOFORIGIN: Nid = Nid(ffi::NID_id_smime_cti_ets_proofOfOrigin); - pub const ID_SMIME_CTI_ETS_PROOFOFRECEIPT: Nid = Nid(ffi::NID_id_smime_cti_ets_proofOfReceipt); - pub const ID_SMIME_CTI_ETS_PROOFOFDELIVERY: Nid = - Nid(ffi::NID_id_smime_cti_ets_proofOfDelivery); - pub const ID_SMIME_CTI_ETS_PROOFOFSENDER: Nid = Nid(ffi::NID_id_smime_cti_ets_proofOfSender); - pub const ID_SMIME_CTI_ETS_PROOFOFAPPROVAL: Nid = - Nid(ffi::NID_id_smime_cti_ets_proofOfApproval); - pub const ID_SMIME_CTI_ETS_PROOFOFCREATION: Nid = - Nid(ffi::NID_id_smime_cti_ets_proofOfCreation); - pub const FRIENDLYNAME: Nid = Nid(ffi::NID_friendlyName); - pub const LOCALKEYID: Nid = Nid(ffi::NID_localKeyID); - pub const MS_CSP_NAME: Nid = Nid(ffi::NID_ms_csp_name); - pub const LOCALKEYSET: Nid = Nid(ffi::NID_LocalKeySet); - pub const X509CERTIFICATE: Nid = Nid(ffi::NID_x509Certificate); - pub const SDSICERTIFICATE: Nid = Nid(ffi::NID_sdsiCertificate); - pub const X509CRL: Nid = Nid(ffi::NID_x509Crl); - pub const PBE_WITHSHA1AND128BITRC4: Nid = Nid(ffi::NID_pbe_WithSHA1And128BitRC4); - pub const PBE_WITHSHA1AND40BITRC4: Nid = Nid(ffi::NID_pbe_WithSHA1And40BitRC4); - pub const PBE_WITHSHA1AND3_KEY_TRIPLEDES_CBC: Nid = - Nid(ffi::NID_pbe_WithSHA1And3_Key_TripleDES_CBC); - pub const PBE_WITHSHA1AND2_KEY_TRIPLEDES_CBC: Nid = - Nid(ffi::NID_pbe_WithSHA1And2_Key_TripleDES_CBC); - pub const PBE_WITHSHA1AND128BITRC2_CBC: Nid = Nid(ffi::NID_pbe_WithSHA1And128BitRC2_CBC); - pub const PBE_WITHSHA1AND40BITRC2_CBC: Nid = Nid(ffi::NID_pbe_WithSHA1And40BitRC2_CBC); - pub const KEYBAG: Nid = Nid(ffi::NID_keyBag); - pub const PKCS8SHROUDEDKEYBAG: Nid = Nid(ffi::NID_pkcs8ShroudedKeyBag); - pub const CERTBAG: Nid = Nid(ffi::NID_certBag); - pub const CRLBAG: Nid = Nid(ffi::NID_crlBag); - pub const SECRETBAG: Nid = Nid(ffi::NID_secretBag); - pub const SAFECONTENTSBAG: Nid = Nid(ffi::NID_safeContentsBag); - pub const MD2: Nid = Nid(ffi::NID_md2); - pub const MD4: Nid = Nid(ffi::NID_md4); - pub const MD5: Nid = Nid(ffi::NID_md5); - pub const MD5_SHA1: Nid = Nid(ffi::NID_md5_sha1); - pub const HMACWITHMD5: Nid = Nid(ffi::NID_hmacWithMD5); - pub const HMACWITHSHA1: Nid = Nid(ffi::NID_hmacWithSHA1); - pub const HMACWITHSHA224: Nid = Nid(ffi::NID_hmacWithSHA224); - pub const HMACWITHSHA256: Nid = Nid(ffi::NID_hmacWithSHA256); - pub const HMACWITHSHA384: Nid = Nid(ffi::NID_hmacWithSHA384); - pub const HMACWITHSHA512: Nid = Nid(ffi::NID_hmacWithSHA512); - pub const RC2_CBC: Nid = Nid(ffi::NID_rc2_cbc); - pub const RC2_ECB: Nid = Nid(ffi::NID_rc2_ecb); - pub const RC2_CFB64: Nid = Nid(ffi::NID_rc2_cfb64); - pub const RC2_OFB64: Nid = Nid(ffi::NID_rc2_ofb64); - pub const RC2_40_CBC: Nid = Nid(ffi::NID_rc2_40_cbc); - pub const RC2_64_CBC: Nid = Nid(ffi::NID_rc2_64_cbc); - pub const RC4: Nid = Nid(ffi::NID_rc4); - pub const RC4_40: Nid = Nid(ffi::NID_rc4_40); - pub const DES_EDE3_CBC: Nid = Nid(ffi::NID_des_ede3_cbc); - pub const RC5_CBC: Nid = Nid(ffi::NID_rc5_cbc); - pub const RC5_ECB: Nid = Nid(ffi::NID_rc5_ecb); - pub const RC5_CFB64: Nid = Nid(ffi::NID_rc5_cfb64); - pub const RC5_OFB64: Nid = Nid(ffi::NID_rc5_ofb64); - pub const MS_EXT_REQ: Nid = Nid(ffi::NID_ms_ext_req); - pub const MS_CODE_IND: Nid = Nid(ffi::NID_ms_code_ind); - pub const MS_CODE_COM: Nid = Nid(ffi::NID_ms_code_com); - pub const MS_CTL_SIGN: Nid = Nid(ffi::NID_ms_ctl_sign); - pub const MS_SGC: Nid = Nid(ffi::NID_ms_sgc); - pub const MS_EFS: Nid = Nid(ffi::NID_ms_efs); - pub const MS_SMARTCARD_LOGIN: Nid = Nid(ffi::NID_ms_smartcard_login); - pub const MS_UPN: Nid = Nid(ffi::NID_ms_upn); - pub const IDEA_CBC: Nid = Nid(ffi::NID_idea_cbc); - pub const IDEA_ECB: Nid = Nid(ffi::NID_idea_ecb); - pub const IDEA_CFB64: Nid = Nid(ffi::NID_idea_cfb64); - pub const IDEA_OFB64: Nid = Nid(ffi::NID_idea_ofb64); - pub const BF_CBC: Nid = Nid(ffi::NID_bf_cbc); - pub const BF_ECB: Nid = Nid(ffi::NID_bf_ecb); - pub const BF_CFB64: Nid = Nid(ffi::NID_bf_cfb64); - pub const BF_OFB64: Nid = Nid(ffi::NID_bf_ofb64); - pub const ID_PKIX: Nid = Nid(ffi::NID_id_pkix); - pub const ID_PKIX_MOD: Nid = Nid(ffi::NID_id_pkix_mod); - pub const ID_PE: Nid = Nid(ffi::NID_id_pe); - pub const ID_QT: Nid = Nid(ffi::NID_id_qt); - pub const ID_KP: Nid = Nid(ffi::NID_id_kp); - pub const ID_IT: Nid = Nid(ffi::NID_id_it); - pub const ID_PKIP: Nid = Nid(ffi::NID_id_pkip); - pub const ID_ALG: Nid = Nid(ffi::NID_id_alg); - pub const ID_CMC: Nid = Nid(ffi::NID_id_cmc); - pub const ID_ON: Nid = Nid(ffi::NID_id_on); - pub const ID_PDA: Nid = Nid(ffi::NID_id_pda); - pub const ID_ACA: Nid = Nid(ffi::NID_id_aca); - pub const ID_QCS: Nid = Nid(ffi::NID_id_qcs); - pub const ID_CCT: Nid = Nid(ffi::NID_id_cct); - pub const ID_PPL: Nid = Nid(ffi::NID_id_ppl); - pub const ID_AD: Nid = Nid(ffi::NID_id_ad); - pub const ID_PKIX1_EXPLICIT_88: Nid = Nid(ffi::NID_id_pkix1_explicit_88); - pub const ID_PKIX1_IMPLICIT_88: Nid = Nid(ffi::NID_id_pkix1_implicit_88); - pub const ID_PKIX1_EXPLICIT_93: Nid = Nid(ffi::NID_id_pkix1_explicit_93); - pub const ID_PKIX1_IMPLICIT_93: Nid = Nid(ffi::NID_id_pkix1_implicit_93); - pub const ID_MOD_CRMF: Nid = Nid(ffi::NID_id_mod_crmf); - pub const ID_MOD_CMC: Nid = Nid(ffi::NID_id_mod_cmc); - pub const ID_MOD_KEA_PROFILE_88: Nid = Nid(ffi::NID_id_mod_kea_profile_88); - pub const ID_MOD_KEA_PROFILE_93: Nid = Nid(ffi::NID_id_mod_kea_profile_93); - pub const ID_MOD_CMP: Nid = Nid(ffi::NID_id_mod_cmp); - pub const ID_MOD_QUALIFIED_CERT_88: Nid = Nid(ffi::NID_id_mod_qualified_cert_88); - pub const ID_MOD_QUALIFIED_CERT_93: Nid = Nid(ffi::NID_id_mod_qualified_cert_93); - pub const ID_MOD_ATTRIBUTE_CERT: Nid = Nid(ffi::NID_id_mod_attribute_cert); - pub const ID_MOD_TIMESTAMP_PROTOCOL: Nid = Nid(ffi::NID_id_mod_timestamp_protocol); - pub const ID_MOD_OCSP: Nid = Nid(ffi::NID_id_mod_ocsp); - pub const ID_MOD_DVCS: Nid = Nid(ffi::NID_id_mod_dvcs); - pub const ID_MOD_CMP2000: Nid = Nid(ffi::NID_id_mod_cmp2000); - pub const INFO_ACCESS: Nid = Nid(ffi::NID_info_access); - pub const BIOMETRICINFO: Nid = Nid(ffi::NID_biometricInfo); - pub const QCSTATEMENTS: Nid = Nid(ffi::NID_qcStatements); - pub const AC_AUDITENTITY: Nid = Nid(ffi::NID_ac_auditEntity); - pub const AC_TARGETING: Nid = Nid(ffi::NID_ac_targeting); - pub const AACONTROLS: Nid = Nid(ffi::NID_aaControls); - pub const SBGP_IPADDRBLOCK: Nid = Nid(ffi::NID_sbgp_ipAddrBlock); - pub const SBGP_AUTONOMOUSSYSNUM: Nid = Nid(ffi::NID_sbgp_autonomousSysNum); - pub const SBGP_ROUTERIDENTIFIER: Nid = Nid(ffi::NID_sbgp_routerIdentifier); - pub const AC_PROXYING: Nid = Nid(ffi::NID_ac_proxying); - pub const SINFO_ACCESS: Nid = Nid(ffi::NID_sinfo_access); - pub const PROXYCERTINFO: Nid = Nid(ffi::NID_proxyCertInfo); - pub const ID_QT_CPS: Nid = Nid(ffi::NID_id_qt_cps); - pub const ID_QT_UNOTICE: Nid = Nid(ffi::NID_id_qt_unotice); - pub const TEXTNOTICE: Nid = Nid(ffi::NID_textNotice); - pub const SERVER_AUTH: Nid = Nid(ffi::NID_server_auth); - pub const CLIENT_AUTH: Nid = Nid(ffi::NID_client_auth); - pub const CODE_SIGN: Nid = Nid(ffi::NID_code_sign); - pub const EMAIL_PROTECT: Nid = Nid(ffi::NID_email_protect); - pub const IPSECENDSYSTEM: Nid = Nid(ffi::NID_ipsecEndSystem); - pub const IPSECTUNNEL: Nid = Nid(ffi::NID_ipsecTunnel); - pub const IPSECUSER: Nid = Nid(ffi::NID_ipsecUser); - pub const TIME_STAMP: Nid = Nid(ffi::NID_time_stamp); - pub const OCSP_SIGN: Nid = Nid(ffi::NID_OCSP_sign); - pub const DVCS: Nid = Nid(ffi::NID_dvcs); - pub const ID_IT_CAPROTENCCERT: Nid = Nid(ffi::NID_id_it_caProtEncCert); - pub const ID_IT_SIGNKEYPAIRTYPES: Nid = Nid(ffi::NID_id_it_signKeyPairTypes); - pub const ID_IT_ENCKEYPAIRTYPES: Nid = Nid(ffi::NID_id_it_encKeyPairTypes); - pub const ID_IT_PREFERREDSYMMALG: Nid = Nid(ffi::NID_id_it_preferredSymmAlg); - pub const ID_IT_CAKEYUPDATEINFO: Nid = Nid(ffi::NID_id_it_caKeyUpdateInfo); - pub const ID_IT_CURRENTCRL: Nid = Nid(ffi::NID_id_it_currentCRL); - pub const ID_IT_UNSUPPORTEDOIDS: Nid = Nid(ffi::NID_id_it_unsupportedOIDs); - pub const ID_IT_SUBSCRIPTIONREQUEST: Nid = Nid(ffi::NID_id_it_subscriptionRequest); - pub const ID_IT_SUBSCRIPTIONRESPONSE: Nid = Nid(ffi::NID_id_it_subscriptionResponse); - pub const ID_IT_KEYPAIRPARAMREQ: Nid = Nid(ffi::NID_id_it_keyPairParamReq); - pub const ID_IT_KEYPAIRPARAMREP: Nid = Nid(ffi::NID_id_it_keyPairParamRep); - pub const ID_IT_REVPASSPHRASE: Nid = Nid(ffi::NID_id_it_revPassphrase); - pub const ID_IT_IMPLICITCONFIRM: Nid = Nid(ffi::NID_id_it_implicitConfirm); - pub const ID_IT_CONFIRMWAITTIME: Nid = Nid(ffi::NID_id_it_confirmWaitTime); - pub const ID_IT_ORIGPKIMESSAGE: Nid = Nid(ffi::NID_id_it_origPKIMessage); - pub const ID_IT_SUPPLANGTAGS: Nid = Nid(ffi::NID_id_it_suppLangTags); - pub const ID_REGCTRL: Nid = Nid(ffi::NID_id_regCtrl); - pub const ID_REGINFO: Nid = Nid(ffi::NID_id_regInfo); - pub const ID_REGCTRL_REGTOKEN: Nid = Nid(ffi::NID_id_regCtrl_regToken); - pub const ID_REGCTRL_AUTHENTICATOR: Nid = Nid(ffi::NID_id_regCtrl_authenticator); - pub const ID_REGCTRL_PKIPUBLICATIONINFO: Nid = Nid(ffi::NID_id_regCtrl_pkiPublicationInfo); - pub const ID_REGCTRL_PKIARCHIVEOPTIONS: Nid = Nid(ffi::NID_id_regCtrl_pkiArchiveOptions); - pub const ID_REGCTRL_OLDCERTID: Nid = Nid(ffi::NID_id_regCtrl_oldCertID); - pub const ID_REGCTRL_PROTOCOLENCRKEY: Nid = Nid(ffi::NID_id_regCtrl_protocolEncrKey); - pub const ID_REGINFO_UTF8PAIRS: Nid = Nid(ffi::NID_id_regInfo_utf8Pairs); - pub const ID_REGINFO_CERTREQ: Nid = Nid(ffi::NID_id_regInfo_certReq); - pub const ID_ALG_DES40: Nid = Nid(ffi::NID_id_alg_des40); - pub const ID_ALG_NOSIGNATURE: Nid = Nid(ffi::NID_id_alg_noSignature); - pub const ID_ALG_DH_SIG_HMAC_SHA1: Nid = Nid(ffi::NID_id_alg_dh_sig_hmac_sha1); - pub const ID_ALG_DH_POP: Nid = Nid(ffi::NID_id_alg_dh_pop); - pub const ID_CMC_STATUSINFO: Nid = Nid(ffi::NID_id_cmc_statusInfo); - pub const ID_CMC_IDENTIFICATION: Nid = Nid(ffi::NID_id_cmc_identification); - pub const ID_CMC_IDENTITYPROOF: Nid = Nid(ffi::NID_id_cmc_identityProof); - pub const ID_CMC_DATARETURN: Nid = Nid(ffi::NID_id_cmc_dataReturn); - pub const ID_CMC_TRANSACTIONID: Nid = Nid(ffi::NID_id_cmc_transactionId); - pub const ID_CMC_SENDERNONCE: Nid = Nid(ffi::NID_id_cmc_senderNonce); - pub const ID_CMC_RECIPIENTNONCE: Nid = Nid(ffi::NID_id_cmc_recipientNonce); - pub const ID_CMC_ADDEXTENSIONS: Nid = Nid(ffi::NID_id_cmc_addExtensions); - pub const ID_CMC_ENCRYPTEDPOP: Nid = Nid(ffi::NID_id_cmc_encryptedPOP); - pub const ID_CMC_DECRYPTEDPOP: Nid = Nid(ffi::NID_id_cmc_decryptedPOP); - pub const ID_CMC_LRAPOPWITNESS: Nid = Nid(ffi::NID_id_cmc_lraPOPWitness); - pub const ID_CMC_GETCERT: Nid = Nid(ffi::NID_id_cmc_getCert); - pub const ID_CMC_GETCRL: Nid = Nid(ffi::NID_id_cmc_getCRL); - pub const ID_CMC_REVOKEREQUEST: Nid = Nid(ffi::NID_id_cmc_revokeRequest); - pub const ID_CMC_REGINFO: Nid = Nid(ffi::NID_id_cmc_regInfo); - pub const ID_CMC_RESPONSEINFO: Nid = Nid(ffi::NID_id_cmc_responseInfo); - pub const ID_CMC_QUERYPENDING: Nid = Nid(ffi::NID_id_cmc_queryPending); - pub const ID_CMC_POPLINKRANDOM: Nid = Nid(ffi::NID_id_cmc_popLinkRandom); - pub const ID_CMC_POPLINKWITNESS: Nid = Nid(ffi::NID_id_cmc_popLinkWitness); - pub const ID_CMC_CONFIRMCERTACCEPTANCE: Nid = Nid(ffi::NID_id_cmc_confirmCertAcceptance); - pub const ID_ON_PERSONALDATA: Nid = Nid(ffi::NID_id_on_personalData); - pub const ID_ON_PERMANENTIDENTIFIER: Nid = Nid(ffi::NID_id_on_permanentIdentifier); - pub const ID_PDA_DATEOFBIRTH: Nid = Nid(ffi::NID_id_pda_dateOfBirth); - pub const ID_PDA_PLACEOFBIRTH: Nid = Nid(ffi::NID_id_pda_placeOfBirth); - pub const ID_PDA_GENDER: Nid = Nid(ffi::NID_id_pda_gender); - pub const ID_PDA_COUNTRYOFCITIZENSHIP: Nid = Nid(ffi::NID_id_pda_countryOfCitizenship); - pub const ID_PDA_COUNTRYOFRESIDENCE: Nid = Nid(ffi::NID_id_pda_countryOfResidence); - pub const ID_ACA_AUTHENTICATIONINFO: Nid = Nid(ffi::NID_id_aca_authenticationInfo); - pub const ID_ACA_ACCESSIDENTITY: Nid = Nid(ffi::NID_id_aca_accessIdentity); - pub const ID_ACA_CHARGINGIDENTITY: Nid = Nid(ffi::NID_id_aca_chargingIdentity); - pub const ID_ACA_GROUP: Nid = Nid(ffi::NID_id_aca_group); - pub const ID_ACA_ROLE: Nid = Nid(ffi::NID_id_aca_role); - pub const ID_ACA_ENCATTRS: Nid = Nid(ffi::NID_id_aca_encAttrs); - pub const ID_QCS_PKIXQCSYNTAX_V1: Nid = Nid(ffi::NID_id_qcs_pkixQCSyntax_v1); - pub const ID_CCT_CRS: Nid = Nid(ffi::NID_id_cct_crs); - pub const ID_CCT_PKIDATA: Nid = Nid(ffi::NID_id_cct_PKIData); - pub const ID_CCT_PKIRESPONSE: Nid = Nid(ffi::NID_id_cct_PKIResponse); - pub const ID_PPL_ANYLANGUAGE: Nid = Nid(ffi::NID_id_ppl_anyLanguage); - pub const ID_PPL_INHERITALL: Nid = Nid(ffi::NID_id_ppl_inheritAll); - pub const INDEPENDENT: Nid = Nid(ffi::NID_Independent); - pub const AD_OCSP: Nid = Nid(ffi::NID_ad_OCSP); - pub const AD_CA_ISSUERS: Nid = Nid(ffi::NID_ad_ca_issuers); - pub const AD_TIMESTAMPING: Nid = Nid(ffi::NID_ad_timeStamping); - pub const AD_DVCS: Nid = Nid(ffi::NID_ad_dvcs); - pub const CAREPOSITORY: Nid = Nid(ffi::NID_caRepository); - pub const ID_PKIX_OCSP_BASIC: Nid = Nid(ffi::NID_id_pkix_OCSP_basic); - pub const ID_PKIX_OCSP_NONCE: Nid = Nid(ffi::NID_id_pkix_OCSP_Nonce); - pub const ID_PKIX_OCSP_CRLID: Nid = Nid(ffi::NID_id_pkix_OCSP_CrlID); - pub const ID_PKIX_OCSP_ACCEPTABLERESPONSES: Nid = - Nid(ffi::NID_id_pkix_OCSP_acceptableResponses); - pub const ID_PKIX_OCSP_NOCHECK: Nid = Nid(ffi::NID_id_pkix_OCSP_noCheck); - pub const ID_PKIX_OCSP_ARCHIVECUTOFF: Nid = Nid(ffi::NID_id_pkix_OCSP_archiveCutoff); - pub const ID_PKIX_OCSP_SERVICELOCATOR: Nid = Nid(ffi::NID_id_pkix_OCSP_serviceLocator); - pub const ID_PKIX_OCSP_EXTENDEDSTATUS: Nid = Nid(ffi::NID_id_pkix_OCSP_extendedStatus); - pub const ID_PKIX_OCSP_VALID: Nid = Nid(ffi::NID_id_pkix_OCSP_valid); - pub const ID_PKIX_OCSP_PATH: Nid = Nid(ffi::NID_id_pkix_OCSP_path); - pub const ID_PKIX_OCSP_TRUSTROOT: Nid = Nid(ffi::NID_id_pkix_OCSP_trustRoot); - pub const ALGORITHM: Nid = Nid(ffi::NID_algorithm); - pub const MD5WITHRSA: Nid = Nid(ffi::NID_md5WithRSA); - pub const DES_ECB: Nid = Nid(ffi::NID_des_ecb); - pub const DES_CBC: Nid = Nid(ffi::NID_des_cbc); - pub const DES_OFB64: Nid = Nid(ffi::NID_des_ofb64); - pub const DES_CFB64: Nid = Nid(ffi::NID_des_cfb64); - pub const RSASIGNATURE: Nid = Nid(ffi::NID_rsaSignature); - pub const DSA_2: Nid = Nid(ffi::NID_dsa_2); - pub const DSAWITHSHA: Nid = Nid(ffi::NID_dsaWithSHA); - pub const SHAWITHRSAENCRYPTION: Nid = Nid(ffi::NID_shaWithRSAEncryption); - pub const DES_EDE_ECB: Nid = Nid(ffi::NID_des_ede_ecb); - pub const DES_EDE3_ECB: Nid = Nid(ffi::NID_des_ede3_ecb); - pub const DES_EDE_CBC: Nid = Nid(ffi::NID_des_ede_cbc); - pub const DES_EDE_CFB64: Nid = Nid(ffi::NID_des_ede_cfb64); - pub const DES_EDE3_CFB64: Nid = Nid(ffi::NID_des_ede3_cfb64); - pub const DES_EDE_OFB64: Nid = Nid(ffi::NID_des_ede_ofb64); - pub const DES_EDE3_OFB64: Nid = Nid(ffi::NID_des_ede3_ofb64); - pub const DESX_CBC: Nid = Nid(ffi::NID_desx_cbc); - pub const SHA: Nid = Nid(ffi::NID_sha); - pub const SHA1: Nid = Nid(ffi::NID_sha1); - pub const DSAWITHSHA1_2: Nid = Nid(ffi::NID_dsaWithSHA1_2); - pub const SHA1WITHRSA: Nid = Nid(ffi::NID_sha1WithRSA); - pub const RIPEMD160: Nid = Nid(ffi::NID_ripemd160); - pub const RIPEMD160WITHRSA: Nid = Nid(ffi::NID_ripemd160WithRSA); - pub const SXNET: Nid = Nid(ffi::NID_sxnet); - pub const X500: Nid = Nid(ffi::NID_X500); - pub const X509: Nid = Nid(ffi::NID_X509); - pub const COMMONNAME: Nid = Nid(ffi::NID_commonName); - pub const SURNAME: Nid = Nid(ffi::NID_surname); - pub const SERIALNUMBER: Nid = Nid(ffi::NID_serialNumber); - pub const COUNTRYNAME: Nid = Nid(ffi::NID_countryName); - pub const LOCALITYNAME: Nid = Nid(ffi::NID_localityName); - pub const STATEORPROVINCENAME: Nid = Nid(ffi::NID_stateOrProvinceName); - pub const STREETADDRESS: Nid = Nid(ffi::NID_streetAddress); - pub const ORGANIZATIONNAME: Nid = Nid(ffi::NID_organizationName); - pub const ORGANIZATIONALUNITNAME: Nid = Nid(ffi::NID_organizationalUnitName); - pub const TITLE: Nid = Nid(ffi::NID_title); - pub const DESCRIPTION: Nid = Nid(ffi::NID_description); - pub const SEARCHGUIDE: Nid = Nid(ffi::NID_searchGuide); - pub const BUSINESSCATEGORY: Nid = Nid(ffi::NID_businessCategory); - pub const POSTALADDRESS: Nid = Nid(ffi::NID_postalAddress); - pub const POSTALCODE: Nid = Nid(ffi::NID_postalCode); - pub const POSTOFFICEBOX: Nid = Nid(ffi::NID_postOfficeBox); - pub const PHYSICALDELIVERYOFFICENAME: Nid = Nid(ffi::NID_physicalDeliveryOfficeName); - pub const TELEPHONENUMBER: Nid = Nid(ffi::NID_telephoneNumber); - pub const TELEXNUMBER: Nid = Nid(ffi::NID_telexNumber); - pub const TELETEXTERMINALIDENTIFIER: Nid = Nid(ffi::NID_teletexTerminalIdentifier); - pub const FACSIMILETELEPHONENUMBER: Nid = Nid(ffi::NID_facsimileTelephoneNumber); - pub const X121ADDRESS: Nid = Nid(ffi::NID_x121Address); - pub const INTERNATIONALISDNNUMBER: Nid = Nid(ffi::NID_internationaliSDNNumber); - pub const REGISTEREDADDRESS: Nid = Nid(ffi::NID_registeredAddress); - pub const DESTINATIONINDICATOR: Nid = Nid(ffi::NID_destinationIndicator); - pub const PREFERREDDELIVERYMETHOD: Nid = Nid(ffi::NID_preferredDeliveryMethod); - pub const PRESENTATIONADDRESS: Nid = Nid(ffi::NID_presentationAddress); - pub const SUPPORTEDAPPLICATIONCONTEXT: Nid = Nid(ffi::NID_supportedApplicationContext); - pub const MEMBER: Nid = Nid(ffi::NID_member); - pub const OWNER: Nid = Nid(ffi::NID_owner); - pub const ROLEOCCUPANT: Nid = Nid(ffi::NID_roleOccupant); - pub const SEEALSO: Nid = Nid(ffi::NID_seeAlso); - pub const USERPASSWORD: Nid = Nid(ffi::NID_userPassword); - pub const USERCERTIFICATE: Nid = Nid(ffi::NID_userCertificate); - pub const CACERTIFICATE: Nid = Nid(ffi::NID_cACertificate); - pub const AUTHORITYREVOCATIONLIST: Nid = Nid(ffi::NID_authorityRevocationList); - pub const CERTIFICATEREVOCATIONLIST: Nid = Nid(ffi::NID_certificateRevocationList); - pub const CROSSCERTIFICATEPAIR: Nid = Nid(ffi::NID_crossCertificatePair); - pub const NAME: Nid = Nid(ffi::NID_name); - pub const GIVENNAME: Nid = Nid(ffi::NID_givenName); - pub const INITIALS: Nid = Nid(ffi::NID_initials); - pub const GENERATIONQUALIFIER: Nid = Nid(ffi::NID_generationQualifier); - pub const X500UNIQUEIDENTIFIER: Nid = Nid(ffi::NID_x500UniqueIdentifier); - pub const DNQUALIFIER: Nid = Nid(ffi::NID_dnQualifier); - pub const ENHANCEDSEARCHGUIDE: Nid = Nid(ffi::NID_enhancedSearchGuide); - pub const PROTOCOLINFORMATION: Nid = Nid(ffi::NID_protocolInformation); - pub const DISTINGUISHEDNAME: Nid = Nid(ffi::NID_distinguishedName); - pub const UNIQUEMEMBER: Nid = Nid(ffi::NID_uniqueMember); - pub const HOUSEIDENTIFIER: Nid = Nid(ffi::NID_houseIdentifier); - pub const SUPPORTEDALGORITHMS: Nid = Nid(ffi::NID_supportedAlgorithms); - pub const DELTAREVOCATIONLIST: Nid = Nid(ffi::NID_deltaRevocationList); - pub const DMDNAME: Nid = Nid(ffi::NID_dmdName); - pub const PSEUDONYM: Nid = Nid(ffi::NID_pseudonym); - pub const ROLE: Nid = Nid(ffi::NID_role); - pub const X500ALGORITHMS: Nid = Nid(ffi::NID_X500algorithms); - pub const RSA: Nid = Nid(ffi::NID_rsa); - pub const MDC2WITHRSA: Nid = Nid(ffi::NID_mdc2WithRSA); - pub const MDC2: Nid = Nid(ffi::NID_mdc2); - pub const ID_CE: Nid = Nid(ffi::NID_id_ce); - pub const SUBJECT_DIRECTORY_ATTRIBUTES: Nid = Nid(ffi::NID_subject_directory_attributes); - pub const SUBJECT_KEY_IDENTIFIER: Nid = Nid(ffi::NID_subject_key_identifier); - pub const KEY_USAGE: Nid = Nid(ffi::NID_key_usage); - pub const PRIVATE_KEY_USAGE_PERIOD: Nid = Nid(ffi::NID_private_key_usage_period); - pub const SUBJECT_ALT_NAME: Nid = Nid(ffi::NID_subject_alt_name); - pub const ISSUER_ALT_NAME: Nid = Nid(ffi::NID_issuer_alt_name); - pub const BASIC_CONSTRAINTS: Nid = Nid(ffi::NID_basic_constraints); - pub const CRL_NUMBER: Nid = Nid(ffi::NID_crl_number); - pub const CRL_REASON: Nid = Nid(ffi::NID_crl_reason); - pub const INVALIDITY_DATE: Nid = Nid(ffi::NID_invalidity_date); - pub const DELTA_CRL: Nid = Nid(ffi::NID_delta_crl); - pub const ISSUING_DISTRIBUTION_POINT: Nid = Nid(ffi::NID_issuing_distribution_point); - pub const CERTIFICATE_ISSUER: Nid = Nid(ffi::NID_certificate_issuer); - pub const NAME_CONSTRAINTS: Nid = Nid(ffi::NID_name_constraints); - pub const CRL_DISTRIBUTION_POINTS: Nid = Nid(ffi::NID_crl_distribution_points); - pub const CERTIFICATE_POLICIES: Nid = Nid(ffi::NID_certificate_policies); - pub const ANY_POLICY: Nid = Nid(ffi::NID_any_policy); - pub const POLICY_MAPPINGS: Nid = Nid(ffi::NID_policy_mappings); - pub const AUTHORITY_KEY_IDENTIFIER: Nid = Nid(ffi::NID_authority_key_identifier); - pub const POLICY_CONSTRAINTS: Nid = Nid(ffi::NID_policy_constraints); - pub const EXT_KEY_USAGE: Nid = Nid(ffi::NID_ext_key_usage); - pub const FRESHEST_CRL: Nid = Nid(ffi::NID_freshest_crl); - pub const INHIBIT_ANY_POLICY: Nid = Nid(ffi::NID_inhibit_any_policy); - pub const TARGET_INFORMATION: Nid = Nid(ffi::NID_target_information); - pub const NO_REV_AVAIL: Nid = Nid(ffi::NID_no_rev_avail); - pub const ANYEXTENDEDKEYUSAGE: Nid = Nid(ffi::NID_anyExtendedKeyUsage); - pub const NETSCAPE: Nid = Nid(ffi::NID_netscape); - pub const NETSCAPE_CERT_EXTENSION: Nid = Nid(ffi::NID_netscape_cert_extension); - pub const NETSCAPE_DATA_TYPE: Nid = Nid(ffi::NID_netscape_data_type); - pub const NETSCAPE_CERT_TYPE: Nid = Nid(ffi::NID_netscape_cert_type); - pub const NETSCAPE_BASE_URL: Nid = Nid(ffi::NID_netscape_base_url); - pub const NETSCAPE_REVOCATION_URL: Nid = Nid(ffi::NID_netscape_revocation_url); - pub const NETSCAPE_CA_REVOCATION_URL: Nid = Nid(ffi::NID_netscape_ca_revocation_url); - pub const NETSCAPE_RENEWAL_URL: Nid = Nid(ffi::NID_netscape_renewal_url); - pub const NETSCAPE_CA_POLICY_URL: Nid = Nid(ffi::NID_netscape_ca_policy_url); - pub const NETSCAPE_SSL_SERVER_NAME: Nid = Nid(ffi::NID_netscape_ssl_server_name); - pub const NETSCAPE_COMMENT: Nid = Nid(ffi::NID_netscape_comment); - pub const NETSCAPE_CERT_SEQUENCE: Nid = Nid(ffi::NID_netscape_cert_sequence); - pub const NS_SGC: Nid = Nid(ffi::NID_ns_sgc); - pub const ORG: Nid = Nid(ffi::NID_org); - pub const DOD: Nid = Nid(ffi::NID_dod); - pub const IANA: Nid = Nid(ffi::NID_iana); - pub const DIRECTORY: Nid = Nid(ffi::NID_Directory); - pub const MANAGEMENT: Nid = Nid(ffi::NID_Management); - pub const EXPERIMENTAL: Nid = Nid(ffi::NID_Experimental); - pub const PRIVATE: Nid = Nid(ffi::NID_Private); - pub const SECURITY: Nid = Nid(ffi::NID_Security); - pub const SNMPV2: Nid = Nid(ffi::NID_SNMPv2); - pub const MAIL: Nid = Nid(ffi::NID_Mail); - pub const ENTERPRISES: Nid = Nid(ffi::NID_Enterprises); - pub const DCOBJECT: Nid = Nid(ffi::NID_dcObject); - pub const MIME_MHS: Nid = Nid(ffi::NID_mime_mhs); - pub const MIME_MHS_HEADINGS: Nid = Nid(ffi::NID_mime_mhs_headings); - pub const MIME_MHS_BODIES: Nid = Nid(ffi::NID_mime_mhs_bodies); - pub const ID_HEX_PARTIAL_MESSAGE: Nid = Nid(ffi::NID_id_hex_partial_message); - pub const ID_HEX_MULTIPART_MESSAGE: Nid = Nid(ffi::NID_id_hex_multipart_message); - pub const ZLIB_COMPRESSION: Nid = Nid(ffi::NID_zlib_compression); - pub const AES_128_ECB: Nid = Nid(ffi::NID_aes_128_ecb); - pub const AES_128_CBC: Nid = Nid(ffi::NID_aes_128_cbc); - pub const AES_128_OFB128: Nid = Nid(ffi::NID_aes_128_ofb128); - pub const AES_128_CFB128: Nid = Nid(ffi::NID_aes_128_cfb128); - pub const ID_AES128_WRAP: Nid = Nid(ffi::NID_id_aes128_wrap); - pub const AES_128_GCM: Nid = Nid(ffi::NID_aes_128_gcm); - pub const AES_128_CCM: Nid = Nid(ffi::NID_aes_128_ccm); - pub const ID_AES128_WRAP_PAD: Nid = Nid(ffi::NID_id_aes128_wrap_pad); - pub const AES_192_ECB: Nid = Nid(ffi::NID_aes_192_ecb); - pub const AES_192_CBC: Nid = Nid(ffi::NID_aes_192_cbc); - pub const AES_192_OFB128: Nid = Nid(ffi::NID_aes_192_ofb128); - pub const AES_192_CFB128: Nid = Nid(ffi::NID_aes_192_cfb128); - pub const ID_AES192_WRAP: Nid = Nid(ffi::NID_id_aes192_wrap); - pub const AES_192_GCM: Nid = Nid(ffi::NID_aes_192_gcm); - pub const AES_192_CCM: Nid = Nid(ffi::NID_aes_192_ccm); - pub const ID_AES192_WRAP_PAD: Nid = Nid(ffi::NID_id_aes192_wrap_pad); - pub const AES_256_ECB: Nid = Nid(ffi::NID_aes_256_ecb); - pub const AES_256_CBC: Nid = Nid(ffi::NID_aes_256_cbc); - pub const AES_256_OFB128: Nid = Nid(ffi::NID_aes_256_ofb128); - pub const AES_256_CFB128: Nid = Nid(ffi::NID_aes_256_cfb128); - pub const ID_AES256_WRAP: Nid = Nid(ffi::NID_id_aes256_wrap); - pub const AES_256_GCM: Nid = Nid(ffi::NID_aes_256_gcm); - pub const AES_256_CCM: Nid = Nid(ffi::NID_aes_256_ccm); - pub const ID_AES256_WRAP_PAD: Nid = Nid(ffi::NID_id_aes256_wrap_pad); - pub const AES_128_CFB1: Nid = Nid(ffi::NID_aes_128_cfb1); - pub const AES_192_CFB1: Nid = Nid(ffi::NID_aes_192_cfb1); - pub const AES_256_CFB1: Nid = Nid(ffi::NID_aes_256_cfb1); - pub const AES_128_CFB8: Nid = Nid(ffi::NID_aes_128_cfb8); - pub const AES_192_CFB8: Nid = Nid(ffi::NID_aes_192_cfb8); - pub const AES_256_CFB8: Nid = Nid(ffi::NID_aes_256_cfb8); - pub const AES_128_CTR: Nid = Nid(ffi::NID_aes_128_ctr); - pub const AES_192_CTR: Nid = Nid(ffi::NID_aes_192_ctr); - pub const AES_256_CTR: Nid = Nid(ffi::NID_aes_256_ctr); - pub const AES_128_XTS: Nid = Nid(ffi::NID_aes_128_xts); - pub const AES_256_XTS: Nid = Nid(ffi::NID_aes_256_xts); - pub const DES_CFB1: Nid = Nid(ffi::NID_des_cfb1); - pub const DES_CFB8: Nid = Nid(ffi::NID_des_cfb8); - pub const DES_EDE3_CFB1: Nid = Nid(ffi::NID_des_ede3_cfb1); - pub const DES_EDE3_CFB8: Nid = Nid(ffi::NID_des_ede3_cfb8); - pub const SHA256: Nid = Nid(ffi::NID_sha256); - pub const SHA384: Nid = Nid(ffi::NID_sha384); - pub const SHA512: Nid = Nid(ffi::NID_sha512); - pub const SHA224: Nid = Nid(ffi::NID_sha224); - pub const DSA_WITH_SHA224: Nid = Nid(ffi::NID_dsa_with_SHA224); - pub const DSA_WITH_SHA256: Nid = Nid(ffi::NID_dsa_with_SHA256); - pub const HOLD_INSTRUCTION_CODE: Nid = Nid(ffi::NID_hold_instruction_code); - pub const HOLD_INSTRUCTION_NONE: Nid = Nid(ffi::NID_hold_instruction_none); - pub const HOLD_INSTRUCTION_CALL_ISSUER: Nid = Nid(ffi::NID_hold_instruction_call_issuer); - pub const HOLD_INSTRUCTION_REJECT: Nid = Nid(ffi::NID_hold_instruction_reject); - pub const DATA: Nid = Nid(ffi::NID_data); - pub const PSS: Nid = Nid(ffi::NID_pss); - pub const UCL: Nid = Nid(ffi::NID_ucl); - pub const PILOT: Nid = Nid(ffi::NID_pilot); - pub const PILOTATTRIBUTETYPE: Nid = Nid(ffi::NID_pilotAttributeType); - pub const PILOTATTRIBUTESYNTAX: Nid = Nid(ffi::NID_pilotAttributeSyntax); - pub const PILOTOBJECTCLASS: Nid = Nid(ffi::NID_pilotObjectClass); - pub const PILOTGROUPS: Nid = Nid(ffi::NID_pilotGroups); - pub const IA5STRINGSYNTAX: Nid = Nid(ffi::NID_iA5StringSyntax); - pub const CASEIGNOREIA5STRINGSYNTAX: Nid = Nid(ffi::NID_caseIgnoreIA5StringSyntax); - pub const PILOTOBJECT: Nid = Nid(ffi::NID_pilotObject); - pub const PILOTPERSON: Nid = Nid(ffi::NID_pilotPerson); - pub const ACCOUNT: Nid = Nid(ffi::NID_account); - pub const DOCUMENT: Nid = Nid(ffi::NID_document); - pub const ROOM: Nid = Nid(ffi::NID_room); - pub const DOCUMENTSERIES: Nid = Nid(ffi::NID_documentSeries); - pub const DOMAIN: Nid = Nid(ffi::NID_Domain); - pub const RFC822LOCALPART: Nid = Nid(ffi::NID_rFC822localPart); - pub const DNSDOMAIN: Nid = Nid(ffi::NID_dNSDomain); - pub const DOMAINRELATEDOBJECT: Nid = Nid(ffi::NID_domainRelatedObject); - pub const FRIENDLYCOUNTRY: Nid = Nid(ffi::NID_friendlyCountry); - pub const SIMPLESECURITYOBJECT: Nid = Nid(ffi::NID_simpleSecurityObject); - pub const PILOTORGANIZATION: Nid = Nid(ffi::NID_pilotOrganization); - pub const PILOTDSA: Nid = Nid(ffi::NID_pilotDSA); - pub const QUALITYLABELLEDDATA: Nid = Nid(ffi::NID_qualityLabelledData); - pub const USERID: Nid = Nid(ffi::NID_userId); - pub const TEXTENCODEDORADDRESS: Nid = Nid(ffi::NID_textEncodedORAddress); - pub const RFC822MAILBOX: Nid = Nid(ffi::NID_rfc822Mailbox); - pub const INFO: Nid = Nid(ffi::NID_info); - pub const FAVOURITEDRINK: Nid = Nid(ffi::NID_favouriteDrink); - pub const ROOMNUMBER: Nid = Nid(ffi::NID_roomNumber); - pub const PHOTO: Nid = Nid(ffi::NID_photo); - pub const USERCLASS: Nid = Nid(ffi::NID_userClass); - pub const HOST: Nid = Nid(ffi::NID_host); - pub const MANAGER: Nid = Nid(ffi::NID_manager); - pub const DOCUMENTIDENTIFIER: Nid = Nid(ffi::NID_documentIdentifier); - pub const DOCUMENTTITLE: Nid = Nid(ffi::NID_documentTitle); - pub const DOCUMENTVERSION: Nid = Nid(ffi::NID_documentVersion); - pub const DOCUMENTAUTHOR: Nid = Nid(ffi::NID_documentAuthor); - pub const DOCUMENTLOCATION: Nid = Nid(ffi::NID_documentLocation); - pub const HOMETELEPHONENUMBER: Nid = Nid(ffi::NID_homeTelephoneNumber); - pub const SECRETARY: Nid = Nid(ffi::NID_secretary); - pub const OTHERMAILBOX: Nid = Nid(ffi::NID_otherMailbox); - pub const LASTMODIFIEDTIME: Nid = Nid(ffi::NID_lastModifiedTime); - pub const LASTMODIFIEDBY: Nid = Nid(ffi::NID_lastModifiedBy); - pub const DOMAINCOMPONENT: Nid = Nid(ffi::NID_domainComponent); - pub const ARECORD: Nid = Nid(ffi::NID_aRecord); - pub const PILOTATTRIBUTETYPE27: Nid = Nid(ffi::NID_pilotAttributeType27); - pub const MXRECORD: Nid = Nid(ffi::NID_mXRecord); - pub const NSRECORD: Nid = Nid(ffi::NID_nSRecord); - pub const SOARECORD: Nid = Nid(ffi::NID_sOARecord); - pub const CNAMERECORD: Nid = Nid(ffi::NID_cNAMERecord); - pub const ASSOCIATEDDOMAIN: Nid = Nid(ffi::NID_associatedDomain); - pub const ASSOCIATEDNAME: Nid = Nid(ffi::NID_associatedName); - pub const HOMEPOSTALADDRESS: Nid = Nid(ffi::NID_homePostalAddress); - pub const PERSONALTITLE: Nid = Nid(ffi::NID_personalTitle); - pub const MOBILETELEPHONENUMBER: Nid = Nid(ffi::NID_mobileTelephoneNumber); - pub const PAGERTELEPHONENUMBER: Nid = Nid(ffi::NID_pagerTelephoneNumber); - pub const FRIENDLYCOUNTRYNAME: Nid = Nid(ffi::NID_friendlyCountryName); - pub const ORGANIZATIONALSTATUS: Nid = Nid(ffi::NID_organizationalStatus); - pub const JANETMAILBOX: Nid = Nid(ffi::NID_janetMailbox); - pub const MAILPREFERENCEOPTION: Nid = Nid(ffi::NID_mailPreferenceOption); - pub const BUILDINGNAME: Nid = Nid(ffi::NID_buildingName); - pub const DSAQUALITY: Nid = Nid(ffi::NID_dSAQuality); - pub const SINGLELEVELQUALITY: Nid = Nid(ffi::NID_singleLevelQuality); - pub const SUBTREEMINIMUMQUALITY: Nid = Nid(ffi::NID_subtreeMinimumQuality); - pub const SUBTREEMAXIMUMQUALITY: Nid = Nid(ffi::NID_subtreeMaximumQuality); - pub const PERSONALSIGNATURE: Nid = Nid(ffi::NID_personalSignature); - pub const DITREDIRECT: Nid = Nid(ffi::NID_dITRedirect); - pub const AUDIO: Nid = Nid(ffi::NID_audio); - pub const DOCUMENTPUBLISHER: Nid = Nid(ffi::NID_documentPublisher); - pub const ID_SET: Nid = Nid(ffi::NID_id_set); - pub const SET_CTYPE: Nid = Nid(ffi::NID_set_ctype); - pub const SET_MSGEXT: Nid = Nid(ffi::NID_set_msgExt); - pub const SET_ATTR: Nid = Nid(ffi::NID_set_attr); - pub const SET_POLICY: Nid = Nid(ffi::NID_set_policy); - pub const SET_CERTEXT: Nid = Nid(ffi::NID_set_certExt); - pub const SET_BRAND: Nid = Nid(ffi::NID_set_brand); - pub const SETCT_PANDATA: Nid = Nid(ffi::NID_setct_PANData); - pub const SETCT_PANTOKEN: Nid = Nid(ffi::NID_setct_PANToken); - pub const SETCT_PANONLY: Nid = Nid(ffi::NID_setct_PANOnly); - pub const SETCT_OIDATA: Nid = Nid(ffi::NID_setct_OIData); - pub const SETCT_PI: Nid = Nid(ffi::NID_setct_PI); - pub const SETCT_PIDATA: Nid = Nid(ffi::NID_setct_PIData); - pub const SETCT_PIDATAUNSIGNED: Nid = Nid(ffi::NID_setct_PIDataUnsigned); - pub const SETCT_HODINPUT: Nid = Nid(ffi::NID_setct_HODInput); - pub const SETCT_AUTHRESBAGGAGE: Nid = Nid(ffi::NID_setct_AuthResBaggage); - pub const SETCT_AUTHREVREQBAGGAGE: Nid = Nid(ffi::NID_setct_AuthRevReqBaggage); - pub const SETCT_AUTHREVRESBAGGAGE: Nid = Nid(ffi::NID_setct_AuthRevResBaggage); - pub const SETCT_CAPTOKENSEQ: Nid = Nid(ffi::NID_setct_CapTokenSeq); - pub const SETCT_PINITRESDATA: Nid = Nid(ffi::NID_setct_PInitResData); - pub const SETCT_PI_TBS: Nid = Nid(ffi::NID_setct_PI_TBS); - pub const SETCT_PRESDATA: Nid = Nid(ffi::NID_setct_PResData); - pub const SETCT_AUTHREQTBS: Nid = Nid(ffi::NID_setct_AuthReqTBS); - pub const SETCT_AUTHRESTBS: Nid = Nid(ffi::NID_setct_AuthResTBS); - pub const SETCT_AUTHRESTBSX: Nid = Nid(ffi::NID_setct_AuthResTBSX); - pub const SETCT_AUTHTOKENTBS: Nid = Nid(ffi::NID_setct_AuthTokenTBS); - pub const SETCT_CAPTOKENDATA: Nid = Nid(ffi::NID_setct_CapTokenData); - pub const SETCT_CAPTOKENTBS: Nid = Nid(ffi::NID_setct_CapTokenTBS); - pub const SETCT_ACQCARDCODEMSG: Nid = Nid(ffi::NID_setct_AcqCardCodeMsg); - pub const SETCT_AUTHREVREQTBS: Nid = Nid(ffi::NID_setct_AuthRevReqTBS); - pub const SETCT_AUTHREVRESDATA: Nid = Nid(ffi::NID_setct_AuthRevResData); - pub const SETCT_AUTHREVRESTBS: Nid = Nid(ffi::NID_setct_AuthRevResTBS); - pub const SETCT_CAPREQTBS: Nid = Nid(ffi::NID_setct_CapReqTBS); - pub const SETCT_CAPREQTBSX: Nid = Nid(ffi::NID_setct_CapReqTBSX); - pub const SETCT_CAPRESDATA: Nid = Nid(ffi::NID_setct_CapResData); - pub const SETCT_CAPREVREQTBS: Nid = Nid(ffi::NID_setct_CapRevReqTBS); - pub const SETCT_CAPREVREQTBSX: Nid = Nid(ffi::NID_setct_CapRevReqTBSX); - pub const SETCT_CAPREVRESDATA: Nid = Nid(ffi::NID_setct_CapRevResData); - pub const SETCT_CREDREQTBS: Nid = Nid(ffi::NID_setct_CredReqTBS); - pub const SETCT_CREDREQTBSX: Nid = Nid(ffi::NID_setct_CredReqTBSX); - pub const SETCT_CREDRESDATA: Nid = Nid(ffi::NID_setct_CredResData); - pub const SETCT_CREDREVREQTBS: Nid = Nid(ffi::NID_setct_CredRevReqTBS); - pub const SETCT_CREDREVREQTBSX: Nid = Nid(ffi::NID_setct_CredRevReqTBSX); - pub const SETCT_CREDREVRESDATA: Nid = Nid(ffi::NID_setct_CredRevResData); - pub const SETCT_PCERTREQDATA: Nid = Nid(ffi::NID_setct_PCertReqData); - pub const SETCT_PCERTRESTBS: Nid = Nid(ffi::NID_setct_PCertResTBS); - pub const SETCT_BATCHADMINREQDATA: Nid = Nid(ffi::NID_setct_BatchAdminReqData); - pub const SETCT_BATCHADMINRESDATA: Nid = Nid(ffi::NID_setct_BatchAdminResData); - pub const SETCT_CARDCINITRESTBS: Nid = Nid(ffi::NID_setct_CardCInitResTBS); - pub const SETCT_MEAQCINITRESTBS: Nid = Nid(ffi::NID_setct_MeAqCInitResTBS); - pub const SETCT_REGFORMRESTBS: Nid = Nid(ffi::NID_setct_RegFormResTBS); - pub const SETCT_CERTREQDATA: Nid = Nid(ffi::NID_setct_CertReqData); - pub const SETCT_CERTREQTBS: Nid = Nid(ffi::NID_setct_CertReqTBS); - pub const SETCT_CERTRESDATA: Nid = Nid(ffi::NID_setct_CertResData); - pub const SETCT_CERTINQREQTBS: Nid = Nid(ffi::NID_setct_CertInqReqTBS); - pub const SETCT_ERRORTBS: Nid = Nid(ffi::NID_setct_ErrorTBS); - pub const SETCT_PIDUALSIGNEDTBE: Nid = Nid(ffi::NID_setct_PIDualSignedTBE); - pub const SETCT_PIUNSIGNEDTBE: Nid = Nid(ffi::NID_setct_PIUnsignedTBE); - pub const SETCT_AUTHREQTBE: Nid = Nid(ffi::NID_setct_AuthReqTBE); - pub const SETCT_AUTHRESTBE: Nid = Nid(ffi::NID_setct_AuthResTBE); - pub const SETCT_AUTHRESTBEX: Nid = Nid(ffi::NID_setct_AuthResTBEX); - pub const SETCT_AUTHTOKENTBE: Nid = Nid(ffi::NID_setct_AuthTokenTBE); - pub const SETCT_CAPTOKENTBE: Nid = Nid(ffi::NID_setct_CapTokenTBE); - pub const SETCT_CAPTOKENTBEX: Nid = Nid(ffi::NID_setct_CapTokenTBEX); - pub const SETCT_ACQCARDCODEMSGTBE: Nid = Nid(ffi::NID_setct_AcqCardCodeMsgTBE); - pub const SETCT_AUTHREVREQTBE: Nid = Nid(ffi::NID_setct_AuthRevReqTBE); - pub const SETCT_AUTHREVRESTBE: Nid = Nid(ffi::NID_setct_AuthRevResTBE); - pub const SETCT_AUTHREVRESTBEB: Nid = Nid(ffi::NID_setct_AuthRevResTBEB); - pub const SETCT_CAPREQTBE: Nid = Nid(ffi::NID_setct_CapReqTBE); - pub const SETCT_CAPREQTBEX: Nid = Nid(ffi::NID_setct_CapReqTBEX); - pub const SETCT_CAPRESTBE: Nid = Nid(ffi::NID_setct_CapResTBE); - pub const SETCT_CAPREVREQTBE: Nid = Nid(ffi::NID_setct_CapRevReqTBE); - pub const SETCT_CAPREVREQTBEX: Nid = Nid(ffi::NID_setct_CapRevReqTBEX); - pub const SETCT_CAPREVRESTBE: Nid = Nid(ffi::NID_setct_CapRevResTBE); - pub const SETCT_CREDREQTBE: Nid = Nid(ffi::NID_setct_CredReqTBE); - pub const SETCT_CREDREQTBEX: Nid = Nid(ffi::NID_setct_CredReqTBEX); - pub const SETCT_CREDRESTBE: Nid = Nid(ffi::NID_setct_CredResTBE); - pub const SETCT_CREDREVREQTBE: Nid = Nid(ffi::NID_setct_CredRevReqTBE); - pub const SETCT_CREDREVREQTBEX: Nid = Nid(ffi::NID_setct_CredRevReqTBEX); - pub const SETCT_CREDREVRESTBE: Nid = Nid(ffi::NID_setct_CredRevResTBE); - pub const SETCT_BATCHADMINREQTBE: Nid = Nid(ffi::NID_setct_BatchAdminReqTBE); - pub const SETCT_BATCHADMINRESTBE: Nid = Nid(ffi::NID_setct_BatchAdminResTBE); - pub const SETCT_REGFORMREQTBE: Nid = Nid(ffi::NID_setct_RegFormReqTBE); - pub const SETCT_CERTREQTBE: Nid = Nid(ffi::NID_setct_CertReqTBE); - pub const SETCT_CERTREQTBEX: Nid = Nid(ffi::NID_setct_CertReqTBEX); - pub const SETCT_CERTRESTBE: Nid = Nid(ffi::NID_setct_CertResTBE); - pub const SETCT_CRLNOTIFICATIONTBS: Nid = Nid(ffi::NID_setct_CRLNotificationTBS); - pub const SETCT_CRLNOTIFICATIONRESTBS: Nid = Nid(ffi::NID_setct_CRLNotificationResTBS); - pub const SETCT_BCIDISTRIBUTIONTBS: Nid = Nid(ffi::NID_setct_BCIDistributionTBS); - pub const SETEXT_GENCRYPT: Nid = Nid(ffi::NID_setext_genCrypt); - pub const SETEXT_MIAUTH: Nid = Nid(ffi::NID_setext_miAuth); - pub const SETEXT_PINSECURE: Nid = Nid(ffi::NID_setext_pinSecure); - pub const SETEXT_PINANY: Nid = Nid(ffi::NID_setext_pinAny); - pub const SETEXT_TRACK2: Nid = Nid(ffi::NID_setext_track2); - pub const SETEXT_CV: Nid = Nid(ffi::NID_setext_cv); - pub const SET_POLICY_ROOT: Nid = Nid(ffi::NID_set_policy_root); - pub const SETCEXT_HASHEDROOT: Nid = Nid(ffi::NID_setCext_hashedRoot); - pub const SETCEXT_CERTTYPE: Nid = Nid(ffi::NID_setCext_certType); - pub const SETCEXT_MERCHDATA: Nid = Nid(ffi::NID_setCext_merchData); - pub const SETCEXT_CCERTREQUIRED: Nid = Nid(ffi::NID_setCext_cCertRequired); - pub const SETCEXT_TUNNELING: Nid = Nid(ffi::NID_setCext_tunneling); - pub const SETCEXT_SETEXT: Nid = Nid(ffi::NID_setCext_setExt); - pub const SETCEXT_SETQUALF: Nid = Nid(ffi::NID_setCext_setQualf); - pub const SETCEXT_PGWYCAPABILITIES: Nid = Nid(ffi::NID_setCext_PGWYcapabilities); - pub const SETCEXT_TOKENIDENTIFIER: Nid = Nid(ffi::NID_setCext_TokenIdentifier); - pub const SETCEXT_TRACK2DATA: Nid = Nid(ffi::NID_setCext_Track2Data); - pub const SETCEXT_TOKENTYPE: Nid = Nid(ffi::NID_setCext_TokenType); - pub const SETCEXT_ISSUERCAPABILITIES: Nid = Nid(ffi::NID_setCext_IssuerCapabilities); - pub const SETATTR_CERT: Nid = Nid(ffi::NID_setAttr_Cert); - pub const SETATTR_PGWYCAP: Nid = Nid(ffi::NID_setAttr_PGWYcap); - pub const SETATTR_TOKENTYPE: Nid = Nid(ffi::NID_setAttr_TokenType); - pub const SETATTR_ISSCAP: Nid = Nid(ffi::NID_setAttr_IssCap); - pub const SET_ROOTKEYTHUMB: Nid = Nid(ffi::NID_set_rootKeyThumb); - pub const SET_ADDPOLICY: Nid = Nid(ffi::NID_set_addPolicy); - pub const SETATTR_TOKEN_EMV: Nid = Nid(ffi::NID_setAttr_Token_EMV); - pub const SETATTR_TOKEN_B0PRIME: Nid = Nid(ffi::NID_setAttr_Token_B0Prime); - pub const SETATTR_ISSCAP_CVM: Nid = Nid(ffi::NID_setAttr_IssCap_CVM); - pub const SETATTR_ISSCAP_T2: Nid = Nid(ffi::NID_setAttr_IssCap_T2); - pub const SETATTR_ISSCAP_SIG: Nid = Nid(ffi::NID_setAttr_IssCap_Sig); - pub const SETATTR_GENCRYPTGRM: Nid = Nid(ffi::NID_setAttr_GenCryptgrm); - pub const SETATTR_T2ENC: Nid = Nid(ffi::NID_setAttr_T2Enc); - pub const SETATTR_T2CLEARTXT: Nid = Nid(ffi::NID_setAttr_T2cleartxt); - pub const SETATTR_TOKICCSIG: Nid = Nid(ffi::NID_setAttr_TokICCsig); - pub const SETATTR_SECDEVSIG: Nid = Nid(ffi::NID_setAttr_SecDevSig); - pub const SET_BRAND_IATA_ATA: Nid = Nid(ffi::NID_set_brand_IATA_ATA); - pub const SET_BRAND_DINERS: Nid = Nid(ffi::NID_set_brand_Diners); - pub const SET_BRAND_AMERICANEXPRESS: Nid = Nid(ffi::NID_set_brand_AmericanExpress); - pub const SET_BRAND_JCB: Nid = Nid(ffi::NID_set_brand_JCB); - pub const SET_BRAND_VISA: Nid = Nid(ffi::NID_set_brand_Visa); - pub const SET_BRAND_MASTERCARD: Nid = Nid(ffi::NID_set_brand_MasterCard); - pub const SET_BRAND_NOVUS: Nid = Nid(ffi::NID_set_brand_Novus); - pub const DES_CDMF: Nid = Nid(ffi::NID_des_cdmf); - pub const RSAOAEPENCRYPTIONSET: Nid = Nid(ffi::NID_rsaOAEPEncryptionSET); - pub const IPSEC3: Nid = Nid(ffi::NID_ipsec3); - pub const IPSEC4: Nid = Nid(ffi::NID_ipsec4); - pub const WHIRLPOOL: Nid = Nid(ffi::NID_whirlpool); - pub const CRYPTOPRO: Nid = Nid(ffi::NID_cryptopro); - pub const CRYPTOCOM: Nid = Nid(ffi::NID_cryptocom); - pub const ID_GOSTR3411_94_WITH_GOSTR3410_2001: Nid = - Nid(ffi::NID_id_GostR3411_94_with_GostR3410_2001); - pub const ID_GOSTR3411_94_WITH_GOSTR3410_94: Nid = - Nid(ffi::NID_id_GostR3411_94_with_GostR3410_94); - pub const ID_GOSTR3411_94: Nid = Nid(ffi::NID_id_GostR3411_94); - pub const ID_HMACGOSTR3411_94: Nid = Nid(ffi::NID_id_HMACGostR3411_94); - pub const ID_GOSTR3410_2001: Nid = Nid(ffi::NID_id_GostR3410_2001); - pub const ID_GOSTR3410_94: Nid = Nid(ffi::NID_id_GostR3410_94); - pub const ID_GOST28147_89: Nid = Nid(ffi::NID_id_Gost28147_89); - pub const GOST89_CNT: Nid = Nid(ffi::NID_gost89_cnt); - pub const ID_GOST28147_89_MAC: Nid = Nid(ffi::NID_id_Gost28147_89_MAC); - pub const ID_GOSTR3411_94_PRF: Nid = Nid(ffi::NID_id_GostR3411_94_prf); - pub const ID_GOSTR3410_2001DH: Nid = Nid(ffi::NID_id_GostR3410_2001DH); - pub const ID_GOSTR3410_94DH: Nid = Nid(ffi::NID_id_GostR3410_94DH); - pub const ID_GOST28147_89_CRYPTOPRO_KEYMESHING: Nid = - Nid(ffi::NID_id_Gost28147_89_CryptoPro_KeyMeshing); - pub const ID_GOST28147_89_NONE_KEYMESHING: Nid = Nid(ffi::NID_id_Gost28147_89_None_KeyMeshing); - pub const ID_GOSTR3411_94_TESTPARAMSET: Nid = Nid(ffi::NID_id_GostR3411_94_TestParamSet); - pub const ID_GOSTR3411_94_CRYPTOPROPARAMSET: Nid = - Nid(ffi::NID_id_GostR3411_94_CryptoProParamSet); - pub const ID_GOST28147_89_TESTPARAMSET: Nid = Nid(ffi::NID_id_Gost28147_89_TestParamSet); - pub const ID_GOST28147_89_CRYPTOPRO_A_PARAMSET: Nid = - Nid(ffi::NID_id_Gost28147_89_CryptoPro_A_ParamSet); - pub const ID_GOST28147_89_CRYPTOPRO_B_PARAMSET: Nid = - Nid(ffi::NID_id_Gost28147_89_CryptoPro_B_ParamSet); - pub const ID_GOST28147_89_CRYPTOPRO_C_PARAMSET: Nid = - Nid(ffi::NID_id_Gost28147_89_CryptoPro_C_ParamSet); - pub const ID_GOST28147_89_CRYPTOPRO_D_PARAMSET: Nid = - Nid(ffi::NID_id_Gost28147_89_CryptoPro_D_ParamSet); - pub const ID_GOST28147_89_CRYPTOPRO_OSCAR_1_1_PARAMSET: Nid = - Nid(ffi::NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet); - pub const ID_GOST28147_89_CRYPTOPRO_OSCAR_1_0_PARAMSET: Nid = - Nid(ffi::NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet); - pub const ID_GOST28147_89_CRYPTOPRO_RIC_1_PARAMSET: Nid = - Nid(ffi::NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet); - pub const ID_GOSTR3410_94_TESTPARAMSET: Nid = Nid(ffi::NID_id_GostR3410_94_TestParamSet); - pub const ID_GOSTR3410_94_CRYPTOPRO_A_PARAMSET: Nid = - Nid(ffi::NID_id_GostR3410_94_CryptoPro_A_ParamSet); - pub const ID_GOSTR3410_94_CRYPTOPRO_B_PARAMSET: Nid = - Nid(ffi::NID_id_GostR3410_94_CryptoPro_B_ParamSet); - pub const ID_GOSTR3410_94_CRYPTOPRO_C_PARAMSET: Nid = - Nid(ffi::NID_id_GostR3410_94_CryptoPro_C_ParamSet); - pub const ID_GOSTR3410_94_CRYPTOPRO_D_PARAMSET: Nid = - Nid(ffi::NID_id_GostR3410_94_CryptoPro_D_ParamSet); - pub const ID_GOSTR3410_94_CRYPTOPRO_XCHA_PARAMSET: Nid = - Nid(ffi::NID_id_GostR3410_94_CryptoPro_XchA_ParamSet); - pub const ID_GOSTR3410_94_CRYPTOPRO_XCHB_PARAMSET: Nid = - Nid(ffi::NID_id_GostR3410_94_CryptoPro_XchB_ParamSet); - pub const ID_GOSTR3410_94_CRYPTOPRO_XCHC_PARAMSET: Nid = - Nid(ffi::NID_id_GostR3410_94_CryptoPro_XchC_ParamSet); - pub const ID_GOSTR3410_2001_TESTPARAMSET: Nid = Nid(ffi::NID_id_GostR3410_2001_TestParamSet); - pub const ID_GOSTR3410_2001_CRYPTOPRO_A_PARAMSET: Nid = - Nid(ffi::NID_id_GostR3410_2001_CryptoPro_A_ParamSet); - pub const ID_GOSTR3410_2001_CRYPTOPRO_B_PARAMSET: Nid = - Nid(ffi::NID_id_GostR3410_2001_CryptoPro_B_ParamSet); - pub const ID_GOSTR3410_2001_CRYPTOPRO_C_PARAMSET: Nid = - Nid(ffi::NID_id_GostR3410_2001_CryptoPro_C_ParamSet); - pub const ID_GOSTR3410_2001_CRYPTOPRO_XCHA_PARAMSET: Nid = - Nid(ffi::NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet); - pub const ID_GOSTR3410_2001_CRYPTOPRO_XCHB_PARAMSET: Nid = - Nid(ffi::NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet); - pub const ID_GOSTR3410_94_A: Nid = Nid(ffi::NID_id_GostR3410_94_a); - pub const ID_GOSTR3410_94_ABIS: Nid = Nid(ffi::NID_id_GostR3410_94_aBis); - pub const ID_GOSTR3410_94_B: Nid = Nid(ffi::NID_id_GostR3410_94_b); - pub const ID_GOSTR3410_94_BBIS: Nid = Nid(ffi::NID_id_GostR3410_94_bBis); - pub const ID_GOST28147_89_CC: Nid = Nid(ffi::NID_id_Gost28147_89_cc); - pub const ID_GOSTR3410_94_CC: Nid = Nid(ffi::NID_id_GostR3410_94_cc); - pub const ID_GOSTR3410_2001_CC: Nid = Nid(ffi::NID_id_GostR3410_2001_cc); - pub const ID_GOSTR3411_94_WITH_GOSTR3410_94_CC: Nid = - Nid(ffi::NID_id_GostR3411_94_with_GostR3410_94_cc); - pub const ID_GOSTR3411_94_WITH_GOSTR3410_2001_CC: Nid = - Nid(ffi::NID_id_GostR3411_94_with_GostR3410_2001_cc); - pub const ID_GOSTR3410_2001_PARAMSET_CC: Nid = Nid(ffi::NID_id_GostR3410_2001_ParamSet_cc); - pub const CAMELLIA_128_CBC: Nid = Nid(ffi::NID_camellia_128_cbc); - pub const CAMELLIA_192_CBC: Nid = Nid(ffi::NID_camellia_192_cbc); - pub const CAMELLIA_256_CBC: Nid = Nid(ffi::NID_camellia_256_cbc); - pub const ID_CAMELLIA128_WRAP: Nid = Nid(ffi::NID_id_camellia128_wrap); - pub const ID_CAMELLIA192_WRAP: Nid = Nid(ffi::NID_id_camellia192_wrap); - pub const ID_CAMELLIA256_WRAP: Nid = Nid(ffi::NID_id_camellia256_wrap); - pub const CAMELLIA_128_ECB: Nid = Nid(ffi::NID_camellia_128_ecb); - pub const CAMELLIA_128_OFB128: Nid = Nid(ffi::NID_camellia_128_ofb128); - pub const CAMELLIA_128_CFB128: Nid = Nid(ffi::NID_camellia_128_cfb128); - pub const CAMELLIA_192_ECB: Nid = Nid(ffi::NID_camellia_192_ecb); - pub const CAMELLIA_192_OFB128: Nid = Nid(ffi::NID_camellia_192_ofb128); - pub const CAMELLIA_192_CFB128: Nid = Nid(ffi::NID_camellia_192_cfb128); - pub const CAMELLIA_256_ECB: Nid = Nid(ffi::NID_camellia_256_ecb); - pub const CAMELLIA_256_OFB128: Nid = Nid(ffi::NID_camellia_256_ofb128); - pub const CAMELLIA_256_CFB128: Nid = Nid(ffi::NID_camellia_256_cfb128); - pub const CAMELLIA_128_CFB1: Nid = Nid(ffi::NID_camellia_128_cfb1); - pub const CAMELLIA_192_CFB1: Nid = Nid(ffi::NID_camellia_192_cfb1); - pub const CAMELLIA_256_CFB1: Nid = Nid(ffi::NID_camellia_256_cfb1); - pub const CAMELLIA_128_CFB8: Nid = Nid(ffi::NID_camellia_128_cfb8); - pub const CAMELLIA_192_CFB8: Nid = Nid(ffi::NID_camellia_192_cfb8); - pub const CAMELLIA_256_CFB8: Nid = Nid(ffi::NID_camellia_256_cfb8); - pub const KISA: Nid = Nid(ffi::NID_kisa); - pub const SEED_ECB: Nid = Nid(ffi::NID_seed_ecb); - pub const SEED_CBC: Nid = Nid(ffi::NID_seed_cbc); - pub const SEED_CFB128: Nid = Nid(ffi::NID_seed_cfb128); - pub const SEED_OFB128: Nid = Nid(ffi::NID_seed_ofb128); - pub const HMAC: Nid = Nid(ffi::NID_hmac); - pub const CMAC: Nid = Nid(ffi::NID_cmac); - pub const RC4_HMAC_MD5: Nid = Nid(ffi::NID_rc4_hmac_md5); - pub const AES_128_CBC_HMAC_SHA1: Nid = Nid(ffi::NID_aes_128_cbc_hmac_sha1); - pub const AES_192_CBC_HMAC_SHA1: Nid = Nid(ffi::NID_aes_192_cbc_hmac_sha1); - pub const AES_256_CBC_HMAC_SHA1: Nid = Nid(ffi::NID_aes_256_cbc_hmac_sha1); - #[cfg(ossl111)] - pub const SM2: Nid = Nid(ffi::NID_sm2); - #[cfg(any(ossl111, libressl))] - pub const SM3: Nid = Nid(ffi::NID_sm3); - #[cfg(any(ossl111, libressl380, awslc))] - pub const SHA3_224: Nid = Nid(ffi::NID_sha3_224); - #[cfg(any(ossl111, libressl380, awslc))] - pub const SHA3_256: Nid = Nid(ffi::NID_sha3_256); - #[cfg(any(ossl111, libressl380, awslc))] - pub const SHA3_384: Nid = Nid(ffi::NID_sha3_384); - #[cfg(any(ossl111, libressl380, awslc))] - pub const SHA3_512: Nid = Nid(ffi::NID_sha3_512); - #[cfg(any(ossl111, awslc))] - pub const SHAKE128: Nid = Nid(ffi::NID_shake128); - #[cfg(any(ossl111, awslc))] - pub const SHAKE256: Nid = Nid(ffi::NID_shake256); - #[cfg(any(ossl110, libressl, awslc))] - pub const CHACHA20_POLY1305: Nid = Nid(ffi::NID_chacha20_poly1305); -} - -#[cfg(test)] -mod test { - use super::Nid; - - #[test] - fn signature_digest() { - let algs = Nid::SHA256WITHRSAENCRYPTION.signature_algorithms().unwrap(); - assert_eq!(algs.digest, Nid::SHA256); - assert_eq!(algs.pkey, Nid::RSAENCRYPTION); - } - - #[test] - fn test_long_name_conversion() { - let common_name = Nid::COMMONNAME; - let organizational_unit_name = Nid::ORGANIZATIONALUNITNAME; - let aes256_cbc_hmac_sha1 = Nid::AES_256_CBC_HMAC_SHA1; - let id_cmc_lrapopwitness = Nid::ID_CMC_LRAPOPWITNESS; - let ms_ctl_sign = Nid::MS_CTL_SIGN; - let undefined_nid = Nid::from_raw(118); - - assert_eq!(common_name.long_name().unwrap(), "commonName"); - assert_eq!( - organizational_unit_name.long_name().unwrap(), - "organizationalUnitName" - ); - assert_eq!( - aes256_cbc_hmac_sha1.long_name().unwrap(), - "aes-256-cbc-hmac-sha1" - ); - assert_eq!( - id_cmc_lrapopwitness.long_name().unwrap(), - "id-cmc-lraPOPWitness" - ); - assert_eq!( - ms_ctl_sign.long_name().unwrap(), - "Microsoft Trust List Signing" - ); - assert!( - undefined_nid.long_name().is_err(), - "undefined_nid should not return a valid value" - ); - } - - #[test] - fn test_short_name_conversion() { - let common_name = Nid::COMMONNAME; - let organizational_unit_name = Nid::ORGANIZATIONALUNITNAME; - let aes256_cbc_hmac_sha1 = Nid::AES_256_CBC_HMAC_SHA1; - let id_cmc_lrapopwitness = Nid::ID_CMC_LRAPOPWITNESS; - let ms_ctl_sign = Nid::MS_CTL_SIGN; - let undefined_nid = Nid::from_raw(118); - - assert_eq!(common_name.short_name().unwrap(), "CN"); - assert_eq!(organizational_unit_name.short_name().unwrap(), "OU"); - assert_eq!( - aes256_cbc_hmac_sha1.short_name().unwrap(), - "AES-256-CBC-HMAC-SHA1" - ); - assert_eq!( - id_cmc_lrapopwitness.short_name().unwrap(), - "id-cmc-lraPOPWitness" - ); - assert_eq!(ms_ctl_sign.short_name().unwrap(), "msCTLSign"); - assert!( - undefined_nid.short_name().is_err(), - "undefined_nid should not return a valid value" - ); - } - - #[test] - fn test_create() { - let nid = Nid::create("1.2.3.4", "foo", "foobar").unwrap(); - assert_eq!(nid.short_name().unwrap(), "foo"); - assert_eq!(nid.long_name().unwrap(), "foobar"); - - // Due to a bug in OpenSSL 3.1.0, this test crashes on Windows - if !cfg!(ossl310) { - let invalid_oid = Nid::create("invalid_oid", "invalid", "invalid"); - assert!( - invalid_oid.is_err(), - "invalid_oid should not return a valid value" - ); - } - } -} diff --git a/patch/openssl/src/ocsp.rs b/patch/openssl/src/ocsp.rs deleted file mode 100644 index 8ea5689c6fefe..0000000000000 --- a/patch/openssl/src/ocsp.rs +++ /dev/null @@ -1,433 +0,0 @@ -use bitflags::bitflags; -use foreign_types::{ForeignType, ForeignTypeRef}; -use libc::{c_int, c_long, c_ulong}; -use std::mem; -use std::ptr; -use std::sync::OnceLock; - -use crate::asn1::{Asn1GeneralizedTime, 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; - -// Sentinel value used when next_update is not present in OCSP response -// This represents the maximum possible time (9999-12-31 23:59:59 UTC) -static SENTINEL_MAX_TIME: OnceLock = OnceLock::new(); - -fn get_sentinel_max_time() -> &'static Asn1GeneralizedTimeRef { - SENTINEL_MAX_TIME - .get_or_init(|| { - Asn1GeneralizedTime::from_str("99991231235959Z") - .expect("Failed to create sentinel time") - }) - .as_ref() -} - -bitflags! { - #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - #[repr(transparent)] - pub struct OcspFlag: c_ulong { - const NO_CERTS = ffi::OCSP_NOCERTS as c_ulong; - const NO_INTERN = ffi::OCSP_NOINTERN as c_ulong; - const NO_CHAIN = ffi::OCSP_NOCHAIN as c_ulong; - const NO_VERIFY = ffi::OCSP_NOVERIFY as c_ulong; - const NO_EXPLICIT = ffi::OCSP_NOEXPLICIT as c_ulong; - const NO_CA_SIGN = ffi::OCSP_NOCASIGN as c_ulong; - const NO_DELEGATED = ffi::OCSP_NODELEGATED as c_ulong; - const NO_CHECKS = ffi::OCSP_NOCHECKS as c_ulong; - const TRUST_OTHER = ffi::OCSP_TRUSTOTHER as c_ulong; - const RESPID_KEY = ffi::OCSP_RESPID_KEY as c_ulong; - const NO_TIME = ffi::OCSP_NOTIME as c_ulong; - } -} - -#[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. - /// - /// # Deprecated - /// Contains a sentinel maximum time (99991231235959Z) when the field is - /// not present in the response. - /// Use [`next_update()`](Self::next_update) instead. - #[deprecated(since = "0.10.75", note = "Use the next_update() method instead")] - pub next_update: &'a Asn1GeneralizedTimeRef, - // The actual optional next_update value from the OCSP response. - next_update_opt: Option<&'a Asn1GeneralizedTimeRef>, -} - -impl OcspStatus<'_> { - /// Returns the time at which this revocation check expires. - /// - /// Returns `None` if the OCSP response does not include a `next_update` - /// field. - pub fn next_update(&self) -> Option<&Asn1GeneralizedTimeRef> { - self.next_update_opt - } - - /// 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) -> Result<(), ErrorStack> { - let next_update_ptr = self - .next_update_opt - .map(|t| t.as_ptr()) - .unwrap_or(ptr::null_mut()); - unsafe { - cvt(ffi::OCSP_check_validity( - self.this_update.as_ptr(), - next_update_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, - 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> { - 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); - let next_update_opt = Asn1GeneralizedTimeRef::from_const_ptr_opt(next_update); - // For backwards compatibility, use sentinel max time if next_update is not present - let next_update_compat = next_update_opt.unwrap_or_else(|| get_sentinel_max_time()); - - #[allow(deprecated)] - Some(OcspStatus { - status: OcspCertStatus(status), - reason: OcspRevokedStatus(status), - revocation_time, - this_update: Asn1GeneralizedTimeRef::from_ptr(this_update), - next_update: next_update_compat, - next_update_opt, - }) - } 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 { - 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 { - 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 { - 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 { - 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; -} - -#[cfg(test)] -mod tests { - use super::{ - get_sentinel_max_time, OcspCertId, OcspCertStatus, OcspResponse, OcspResponseStatus, - }; - use crate::hash::MessageDigest; - use crate::x509::X509; - - // Test vectors: OCSP response with next_update=NULL and associated certificates - const OCSP_RESPONSE_NO_NEXTUPDATE: &[u8] = - include_bytes!("../test/ocsp_resp_no_nextupdate.der"); - const OCSP_CA_CERT: &[u8] = include_bytes!("../test/ocsp_ca_cert.der"); - const OCSP_SUBJECT_CERT: &[u8] = include_bytes!("../test/ocsp_subject_cert.der"); - - #[test] - fn test_ocsp_no_next_update() { - // Verify find_status correctly handles OCSP responses with next_update=NULL - let response = OcspResponse::from_der(OCSP_RESPONSE_NO_NEXTUPDATE).unwrap(); - assert_eq!(response.status(), OcspResponseStatus::SUCCESSFUL); - - let ca_cert = X509::from_der(OCSP_CA_CERT).unwrap(); - let subject_cert = X509::from_der(OCSP_SUBJECT_CERT).unwrap(); - let basic = response.basic().unwrap(); - - let cert_id = - OcspCertId::from_cert(MessageDigest::sha256(), &subject_cert, &ca_cert).unwrap(); - - let status = basic - .find_status(&cert_id) - .expect("find_status should find the status"); - - assert!(status.next_update().is_none()); - - #[allow(deprecated)] - let deprecated_next = status.next_update; - let sentinel = get_sentinel_max_time(); - assert_eq!(format!("{}", deprecated_next), format!("{}", sentinel)); - - assert_eq!(status.status, OcspCertStatus::GOOD); - } -} diff --git a/patch/openssl/src/ossl_param.rs b/patch/openssl/src/ossl_param.rs deleted file mode 100644 index 702770aff6604..0000000000000 --- a/patch/openssl/src/ossl_param.rs +++ /dev/null @@ -1,169 +0,0 @@ -//! OSSL_PARAM management for OpenSSL 3.* -//! -//! The OSSL_PARAM structure represents an array of generic -//! attributes that can represent various -//! properties in OpenSSL, including keys and operations. -//! -//! This is always represented as an array of OSSL_PARAM -//! structures, terminated by an entry with a NULL key. -//! -//! For convenience, the OSSL_PARAM_BLD builder can be used to -//! dynamically construct these structures. -//! -//! Note, that this module is available only in OpenSSL 3.* and -//! only internally for this crate. - -use crate::error::ErrorStack; -use crate::util; -use crate::{cvt, cvt_p}; -use foreign_types::ForeignType; -use libc::{c_uint, c_void}; -use openssl_macros::corresponds; -use std::ffi::CStr; -use std::marker::PhantomData; -use std::ptr; - -foreign_type_and_impl_send_sync! { - // This is the singular type, but it is always allocated - // and used as an array of such types. - type CType = ffi::OSSL_PARAM; - // OSSL_PARMA_free correctly frees the entire array. - fn drop = ffi::OSSL_PARAM_free; - - /// `OsslParamArray` constructed using `OsslParamBuilder`. - /// Internally this is a pointer to an array of the OSSL_PARAM - /// structures. - pub struct OsslParamArray; - /// Reference to `OsslParamArray`. - pub struct OsslParamArrayRef; -} - -impl OsslParamArray { - /// Locates the individual `OSSL_PARAM` element representing an - /// octet string identified by the key in the `OsslParamArray` - /// array and returns a reference to it. - /// - /// Combines OSSL_PARAM_locate and OSSL_PARAM_get_octet_string. - #[corresponds(OSSL_PARAM_get_octet_string)] - #[allow(dead_code)] // TODO: remove when when used by ML-DSA / ML-KEM - pub(crate) fn locate_octet_string<'a>(&'a self, key: &CStr) -> Result<&'a [u8], ErrorStack> { - unsafe { - let param = cvt_p(ffi::OSSL_PARAM_locate(self.as_ptr(), key.as_ptr()))?; - let mut val: *const c_void = ptr::null_mut(); - let mut val_len: usize = 0; - cvt(ffi::OSSL_PARAM_get_octet_string_ptr( - param, - &mut val, - &mut val_len, - ))?; - Ok(util::from_raw_parts(val as *const u8, val_len)) - } - } -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::OSSL_PARAM_BLD; - fn drop = ffi::OSSL_PARAM_BLD_free; - - /// Builder used to construct `OsslParamArray`. - pub struct OsslParamBuilderInternal; - /// Reference to `OsslParamBuilderInternal`. - pub struct OsslParamBuilderRefInternal; -} - -/// Wrapper around the internal OsslParamBuilderInternal that adds lifetime management -/// since the builder does not own the key and value data that is added to it. -pub struct OsslParamBuilder<'a> { - builder: OsslParamBuilderInternal, - _marker: PhantomData<&'a ()>, -} - -impl<'a> OsslParamBuilder<'a> { - /// Returns a builder for an OsslParamArray. - /// - /// The array is initially empty. - #[corresponds(OSSL_PARAM_BLD_new)] - #[cfg_attr(any(not(ossl320), osslconf = "OPENSSL_NO_ARGON2"), allow(dead_code))] - pub(crate) fn new() -> Result, ErrorStack> { - unsafe { - ffi::init(); - - cvt_p(ffi::OSSL_PARAM_BLD_new()).map(|builder| OsslParamBuilder { - builder: OsslParamBuilderInternal(builder), - _marker: PhantomData, - }) - } - } - - /// Constructs the `OsslParamArray` and clears this builder. - #[corresponds(OSSL_PARAM_BLD_to_param)] - #[cfg_attr(any(not(ossl320), osslconf = "OPENSSL_NO_ARGON2"), allow(dead_code))] - #[allow(clippy::wrong_self_convention)] - pub(crate) fn to_param(&'a mut self) -> Result { - unsafe { - let params = cvt_p(ffi::OSSL_PARAM_BLD_to_param(self.as_ptr()))?; - Ok(OsslParamArray::from_ptr(params)) - } - } - - /// Adds a octet string to `OsslParamBuilder`. - #[corresponds(OSSL_PARAM_BLD_push_octet_string)] - #[cfg_attr(any(not(ossl320), osslconf = "OPENSSL_NO_ARGON2"), allow(dead_code))] - pub(crate) fn add_octet_string( - &mut self, - key: &'a CStr, - buf: &'a [u8], - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::OSSL_PARAM_BLD_push_octet_string( - self.as_ptr(), - key.as_ptr(), - buf.as_ptr() as *const c_void, - buf.len(), - )) - .map(|_| ()) - } - } - - /// Adds a unsigned int to `OsslParamBuilder`. - #[corresponds(OSSL_PARAM_BLD_push_uint)] - #[cfg_attr(any(not(ossl320), osslconf = "OPENSSL_NO_ARGON2"), allow(dead_code))] - pub(crate) fn add_uint(&mut self, key: &'a CStr, val: u32) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::OSSL_PARAM_BLD_push_uint( - self.as_ptr(), - key.as_ptr(), - val as c_uint, - )) - .map(|_| ()) - } - } - - /// Returns a raw pointer to the underlying `OSSL_PARAM_BLD` structure. - pub(crate) unsafe fn as_ptr(&mut self) -> *mut ffi::OSSL_PARAM_BLD { - self.builder.as_ptr() - } -} - -#[cfg(test)] -mod tests { - use super::*; - #[test] - fn test_builder_locate_octet_string() { - let mut builder = OsslParamBuilder::new().unwrap(); - builder - .add_octet_string(CStr::from_bytes_with_nul(b"key1\0").unwrap(), b"value1") - .unwrap(); - let params = builder.to_param().unwrap(); - - assert!(params - .locate_octet_string(CStr::from_bytes_with_nul(b"invalid\0").unwrap()) - .is_err()); - assert_eq!( - params - .locate_octet_string(CStr::from_bytes_with_nul(b"key1\0").unwrap()) - .unwrap(), - b"value1" - ); - } -} diff --git a/patch/openssl/src/pkcs12.rs b/patch/openssl/src/pkcs12.rs deleted file mode 100644 index 1a2b9660bfa43..0000000000000 --- a/patch/openssl/src/pkcs12.rs +++ /dev/null @@ -1,405 +0,0 @@ -//! PKCS #12 archives. - -use foreign_types::{ForeignType, ForeignTypeRef}; -use libc::c_int; -use std::ffi::CString; -use std::ptr; - -use crate::error::ErrorStack; -#[cfg(not(boringssl))] -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 - } - - /// Deprecated. - #[deprecated(note = "Use parse2 instead", since = "0.10.46")] - #[allow(deprecated)] - pub fn parse(&self, pass: &str) -> Result { - let parsed = self.parse2(pass)?; - - Ok(ParsedPkcs12 { - pkey: parsed.pkey.unwrap(), - cert: parsed.cert.unwrap(), - chain: parsed.ca, - }) - } - - /// Extracts the contents of the `Pkcs12`. - #[corresponds(PKCS12_parse)] - pub fn parse2(&self, pass: &str) -> Result { - unsafe { - let pass = CString::new(pass.as_bytes()).unwrap(); - - let mut pkey = ptr::null_mut(); - let mut cert = ptr::null_mut(); - let mut ca = ptr::null_mut(); - - cvt(ffi::PKCS12_parse( - self.as_ptr(), - pass.as_ptr(), - &mut pkey, - &mut cert, - &mut ca, - ))?; - - let pkey = PKey::from_ptr_opt(pkey); - let cert = X509::from_ptr_opt(cert); - let ca = Stack::from_ptr_opt(ca); - - Ok(ParsedPkcs12_2 { pkey, cert, ca }) - } - } -} - -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` (`SHA-1` only for BoringSSL) - pub fn builder() -> Pkcs12Builder { - ffi::init(); - - Pkcs12Builder { - name: None, - pkey: None, - cert: None, - ca: None, - nid_key: Nid::UNDEF, - nid_cert: Nid::UNDEF, - iter: ffi::PKCS12_DEFAULT_ITER, - mac_iter: ffi::PKCS12_DEFAULT_ITER, - #[cfg(not(boringssl))] - mac_md: None, - } - } -} - -#[deprecated(note = "Use ParsedPkcs12_2 instead", since = "0.10.46")] -pub struct ParsedPkcs12 { - pub pkey: PKey, - pub cert: X509, - pub chain: Option>, -} - -pub struct ParsedPkcs12_2 { - pub pkey: Option>, - pub cert: Option, - pub ca: Option>, -} - -pub struct Pkcs12Builder { - // FIXME borrow - name: Option, - pkey: Option>, - cert: Option, - ca: Option>, - nid_key: Nid, - nid_cert: Nid, - iter: c_int, - mac_iter: c_int, - // FIXME remove - #[cfg(not(boringssl))] - mac_md: Option, -} - -impl Pkcs12Builder { - /// The `friendlyName` used for the certificate and private key. - pub fn name(&mut self, name: &str) -> &mut Self { - self.name = Some(CString::new(name).unwrap()); - self - } - - /// The private key. - pub fn pkey(&mut self, pkey: &PKeyRef) -> &mut Self - where - T: HasPrivate, - { - let new_pkey = unsafe { PKeyRef::from_ptr(pkey.as_ptr()) }; - self.pkey = Some(new_pkey.to_owned()); - self - } - - /// The certificate. - pub fn cert(&mut self, cert: &X509Ref) -> &mut Self { - self.cert = Some(cert.to_owned()); - self - } - - /// An additional set of certificates to include in the archive beyond the one provided to - /// `build`. - pub fn ca(&mut self, ca: Stack) -> &mut Self { - self.ca = Some(ca); - self - } - - /// 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 - #[cfg(not(boringssl))] - pub fn mac_md(&mut self, md: MessageDigest) -> &mut Self { - self.mac_md = Some(md); - self - } - - /// Deprecated. - #[deprecated( - note = "Use Self::{name, pkey, cert, build2} instead.", - since = "0.10.46" - )] - pub fn build( - mut self, - password: &str, - friendly_name: &str, - pkey: &PKeyRef, - cert: &X509Ref, - ) -> Result - where - T: HasPrivate, - { - self.name(friendly_name) - .pkey(pkey) - .cert(cert) - .build2(password) - } - - /// Builds the PKCS#12 object. - #[corresponds(PKCS12_create)] - pub fn build2(&self, password: &str) -> Result { - unsafe { - let pass = CString::new(password).unwrap(); - #[cfg(not(any(boringssl, awslc_fips)))] - let pass_len = pass.as_bytes().len(); - let pass = pass.as_ptr(); - let friendly_name = self.name.as_ref().map_or(ptr::null(), |p| p.as_ptr()); - let pkey = self.pkey.as_ref().map_or(ptr::null(), |p| p.as_ptr()); - let cert = self.cert.as_ref().map_or(ptr::null(), |p| p.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(); - - // 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://docs.openssl.org/master/man3/PKCS12_create/ - let keytype = 0; - - let pkcs12 = cvt_p(ffi::PKCS12_create( - pass as *mut _, - friendly_name as *mut _, - pkey as *mut _, - cert as *mut _, - ca, - nid_key, - nid_cert, - self.iter, - self.mac_iter, - keytype, - )) - .map(Pkcs12)?; - - #[cfg(not(any(boringssl, awslc_fips)))] - // BoringSSL does not support overriding the MAC and will always - // use SHA-1. - { - let md_type = self - .mac_md - .map(|md_type| md_type.as_ptr()) - .unwrap_or(ptr::null()); - - cvt(ffi::PKCS12_set_mac( - pkcs12.as_ptr(), - pass, - pass_len.try_into().unwrap(), - 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.parse2("mypass").unwrap(); - - assert_eq!( - hex::encode( - parsed - .cert - .as_ref() - .unwrap() - .digest(MessageDigest::sha1()) - .unwrap() - ), - "59172d9313e84459bcff27f967e79e6e9217e584" - ); - assert_eq!( - parsed.cert.as_ref().unwrap().alias(), - Some(b"foobar.com" as &[u8]) - ); - - let chain = parsed.ca.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.parse2("cassandra").unwrap(); - if let Some(stack) = parsed.ca { - assert_eq!(stack.len(), 0); - } - } - - #[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 = Pkcs12::builder() - .name(subject_name) - .pkey(&pkey) - .cert(&cert) - .build2("mypass") - .unwrap(); - let der = pkcs12.to_der().unwrap(); - - let pkcs12 = Pkcs12::from_der(&der).unwrap(); - let parsed = pkcs12.parse2("mypass").unwrap(); - - assert_eq!( - &*parsed.cert.unwrap().digest(MessageDigest::sha1()).unwrap(), - &*cert.digest(MessageDigest::sha1()).unwrap() - ); - assert!(parsed.pkey.unwrap().public_eq(&pkey)); - } - - #[test] - fn create_only_ca() { - let ca = include_bytes!("../test/root-ca.pem"); - let ca = X509::from_pem(ca).unwrap(); - let mut chain = Stack::new().unwrap(); - chain.push(ca).unwrap(); - - let pkcs12 = Pkcs12::builder().ca(chain).build2("hunter2").unwrap(); - let parsed = pkcs12.parse2("hunter2").unwrap(); - - assert!(parsed.cert.is_none()); - assert!(parsed.pkey.is_none()); - assert_eq!(parsed.ca.unwrap().len(), 1); - } -} diff --git a/patch/openssl/src/pkcs5.rs b/patch/openssl/src/pkcs5.rs deleted file mode 100644 index a72e0b1a1d1b9..0000000000000 --- a/patch/openssl/src/pkcs5.rs +++ /dev/null @@ -1,310 +0,0 @@ -#[cfg(not(any(boringssl, awslc)))] -use libc::c_int; -use std::convert::TryInto; -#[cfg(not(any(boringssl, awslc)))] -use std::ptr; - -use crate::cvt; -use crate::error::ErrorStack; -use crate::hash::MessageDigest; -#[cfg(not(any(boringssl, awslc)))] -use crate::symm::Cipher; -use openssl_macros::corresponds; - -#[derive(Clone, Eq, PartialEq, Hash, Debug)] -pub struct KeyIvPair { - pub key: Vec, - pub iv: Option>, -} - -/// 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)] -#[cfg(not(any(boringssl, awslc)))] -pub fn bytes_to_key( - cipher: Cipher, - digest: MessageDigest, - data: &[u8], - salt: Option<&[u8]>, - count: i32, -) -> Result { - unsafe { - assert!(data.len() <= c_int::MAX 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 { - ffi::init(); - cvt(ffi::PKCS5_PBKDF2_HMAC( - pass.as_ptr() as *const _, - pass.len().try_into().unwrap(), - salt.as_ptr(), - salt.len().try_into().unwrap(), - iter.try_into().unwrap(), - hash.as_ptr(), - key.len().try_into().unwrap(), - 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(all(any(ossl110, boringssl, awslc), not(osslconf = "OPENSSL_NO_SCRYPT")))] -#[allow(clippy::useless_conversion)] -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.try_into().unwrap(), - key.as_mut_ptr() as *mut _, - key.len(), - )) - .map(|_| ()) - } -} - -#[cfg(test)] -mod tests { - use crate::hash::MessageDigest; - #[cfg(not(any(boringssl, awslc)))] - 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] - #[cfg(not(any(boringssl, awslc)))] - 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, boringssl, awslc))] - 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); - } -} diff --git a/patch/openssl/src/pkcs7.rs b/patch/openssl/src/pkcs7.rs deleted file mode 100644 index 9b991d473bd2b..0000000000000 --- a/patch/openssl/src/pkcs7.rs +++ /dev/null @@ -1,573 +0,0 @@ -use bitflags::bitflags; -use foreign_types::{ForeignType, ForeignTypeRef}; -use libc::c_int; -use std::mem; -use std::ptr; - -use crate::asn1::Asn1ObjectRef; -use crate::bio::{MemBio, MemBioSlice}; -use crate::error::ErrorStack; -use crate::nid::Nid; -use crate::pkey::{HasPrivate, PKeyRef}; -use crate::stack::{Stack, StackRef, Stackable}; -use crate::symm::Cipher; -use crate::util::ForeignTypeRefExt; -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_SIGNER_INFO; - fn drop = ffi::PKCS7_SIGNER_INFO_free; - - pub struct Pkcs7SignerInfo; - pub struct Pkcs7SignerInfoRef; -} - -impl Stackable for Pkcs7SignerInfo { - type StackType = ffi::stack_st_PKCS7_SIGNER_INFO; -} - -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; -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::PKCS7_SIGNED; - fn drop = ffi::PKCS7_SIGNED_free; - - /// A PKCS#7 signed data structure. - /// - /// Contains signed data. - pub struct Pkcs7Signed; - - /// Reference to `Pkcs7Signed` - pub struct Pkcs7SignedRef; -} - -bitflags! { - #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - #[repr(transparent)] - 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(ossl110)] - 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>), 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, - input: &[u8], - cipher: Cipher, - flags: Pkcs7Flags, - ) -> Result { - 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( - signcert: &X509Ref, - pkey: &PKeyRef, - certs: &StackRef, - input: &[u8], - flags: Pkcs7Flags, - ) -> Result - 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, 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( - &self, - pkey: &PKeyRef, - cert: &X509Ref, - flags: Pkcs7Flags, - ) -> Result, 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, - store: &X509StoreRef, - indata: Option<&[u8]>, - out: Option<&mut Vec>, - 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, - flags: Pkcs7Flags, - ) -> Result, 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::::from_ptr(ptr); - for cert in &stack { - mem::forget(cert.to_owned()); - } - - Ok(stack) - } - } - - /// Return the type of a PKCS#7 structure as an Asn1Object - pub fn type_(&self) -> Option<&Asn1ObjectRef> { - unsafe { - let ptr = (*self.as_ptr()).type_; - Asn1ObjectRef::from_const_ptr_opt(ptr) - } - } - - /// Get the signed data of a PKCS#7 structure of type PKCS7_SIGNED - pub fn signed(&self) -> Option<&Pkcs7SignedRef> { - unsafe { - if self.type_().map(|x| x.nid()) != Some(Nid::PKCS7_SIGNED) { - return None; - } - let signed_data = (*self.as_ptr()).d.sign; - Pkcs7SignedRef::from_const_ptr_opt(signed_data) - } - } -} - -impl Pkcs7SignedRef { - /// Get the stack of certificates from the PKCS7_SIGNED object - pub fn certificates(&self) -> Option<&StackRef> { - unsafe { - self.as_ptr() - .as_ref() - .and_then(|x| x.cert.as_mut()) - .and_then(|x| StackRef::::from_const_ptr_opt(x)) - } - } -} - -#[cfg(test)] -mod tests { - use crate::hash::MessageDigest; - use crate::nid::Nid; - 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"); - assert_eq!( - pkcs7.type_().expect("PKCS7 should have a type").nid(), - Nid::PKCS7_ENVELOPED - ); - - 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"); - assert_eq!( - pkcs7.type_().expect("PKCS7 should have a type").nid(), - Nid::PKCS7_SIGNED - ); - - 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()); - } - - /// https://marc.info/?l=openbsd-cvs&m=166602943014106&w=2 - #[test] - #[cfg_attr(all(libressl360, not(libressl361)), ignore)] - 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"); - assert_eq!( - pkcs7.type_().expect("PKCS7 should have a type").nid(), - Nid::PKCS7_SIGNED - ); - - 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()); - } - - /// https://marc.info/?l=openbsd-cvs&m=166602943014106&w=2 - #[test] - #[cfg_attr(all(libressl360, not(libressl361)), ignore)] - 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"); - assert_eq!( - pkcs7.type_().expect("PKCS7 should have a type").nid(), - Nid::PKCS7_SIGNED - ); - - 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()); - } - - #[test] - fn signed_data_certificates() { - let cert = include_bytes!("../test/cert.pem"); - let cert = X509::from_pem(cert).unwrap(); - let mut extra_certs = Stack::::new().unwrap(); - for cert in - X509::stack_from_pem(include_bytes!("../test/certs.pem")).expect("should succeed") - { - extra_certs.push(cert).expect("should succeed"); - } - - let message = "foo"; - let flags = Pkcs7Flags::STREAM; - let pkey = include_bytes!("../test/key.pem"); - let pkey = PKey::private_key_from_pem(pkey).unwrap(); - - let pkcs7 = Pkcs7::sign(&cert, &pkey, &extra_certs, message.as_bytes(), flags) - .expect("should succeed"); - assert_eq!( - pkcs7.type_().expect("PKCS7 should have a type").nid(), - Nid::PKCS7_SIGNED - ); - let signed_data_certs = pkcs7.signed().and_then(|x| x.certificates()); - assert_eq!(signed_data_certs.expect("should succeed").len(), 3); - } - - #[test] - fn signed_data_certificates_no_signed_data() { - let cert = include_bytes!("../test/certs.pem"); - let cert = X509::from_pem(cert).unwrap(); - let mut certs = Stack::new().unwrap(); - certs.push(cert).unwrap(); - let message: String = String::from("foo"); - let cipher = Cipher::des_ede3_cbc(); - let flags = Pkcs7Flags::STREAM; - - // Use `Pkcs7::encrypt` since it populates the PKCS7_ENVELOPE struct rather than - // PKCS7_SIGNED - let pkcs7 = - Pkcs7::encrypt(&certs, message.as_bytes(), cipher, flags).expect("should succeed"); - assert_eq!( - pkcs7.type_().expect("PKCS7 should have a type").nid(), - Nid::PKCS7_ENVELOPED - ); - - let signed_data_certs = pkcs7.signed().and_then(|x| x.certificates()); - assert!(signed_data_certs.is_none()) - } -} diff --git a/patch/openssl/src/pkey.rs b/patch/openssl/src/pkey.rs deleted file mode 100644 index f55440ffbdff6..0000000000000 --- a/patch/openssl/src/pkey.rs +++ /dev/null @@ -1,1222 +0,0 @@ -//! Public/private key processing. -//! -//! Asymmetric public key algorithms solve the problem of establishing and sharing -//! secret keys to securely send and receive messages. -//! This system uses a pair of keys: a public key, which can be freely -//! distributed, and a private key, which is kept to oneself. An entity may -//! encrypt information using a user's public key. The encrypted information can -//! only be deciphered using that user's private key. -//! -//! This module offers support for five popular algorithms: -//! -//! * RSA -//! -//! * DSA -//! -//! * Diffie-Hellman -//! -//! * Elliptic Curves -//! -//! * HMAC -//! -//! These algorithms rely on hard mathematical problems - namely integer factorization, -//! discrete logarithms, and elliptic curve relationships - that currently do not -//! yield efficient solutions. This property ensures the security of these -//! cryptographic algorithms. -//! -//! # Example -//! -//! Generate a 2048-bit RSA public/private key pair and print the public key. -//! -//! ```rust -//! use openssl::rsa::Rsa; -//! use openssl::pkey::PKey; -//! use std::str; -//! -//! let rsa = Rsa::generate(2048).unwrap(); -//! let pkey = PKey::from_rsa(rsa).unwrap(); -//! -//! let pub_key: Vec = pkey.public_key_to_pem().unwrap(); -//! println!("{:?}", str::from_utf8(pub_key.as_slice()).unwrap()); -//! ``` -#![allow(clippy::missing_safety_doc)] -use crate::bio::{MemBio, MemBioSlice}; -#[cfg(ossl110)] -use crate::cipher::CipherRef; -use crate::dh::Dh; -use crate::dsa::Dsa; -use crate::ec::EcKey; -use crate::error::ErrorStack; -#[cfg(any(ossl110, boringssl, libressl370, awslc))] -use crate::pkey_ctx::PkeyCtx; -use crate::rsa::Rsa; -use crate::symm::Cipher; -use crate::util::{invoke_passwd_cb, CallbackState}; -use crate::{cvt, cvt_p}; -use cfg_if::cfg_if; -use foreign_types::{ForeignType, ForeignTypeRef}; -use libc::{c_int, c_long}; -use openssl_macros::corresponds; -use std::convert::{TryFrom, TryInto}; -use std::ffi::CString; -use std::fmt; -#[cfg(all(not(any(boringssl, awslc)), ossl110))] -use std::mem; -use std::ptr; - -/// A tag type indicating that a key only has parameters. -pub enum Params {} - -/// A tag type indicating that a key only has public components. -pub enum Public {} - -/// A tag type indicating that a key has private components. -pub enum Private {} - -/// An identifier of a kind of key. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct Id(c_int); - -impl Id { - pub const RSA: Id = Id(ffi::EVP_PKEY_RSA); - #[cfg(any(ossl111, libressl, boringssl, awslc))] - pub const RSA_PSS: Id = Id(ffi::EVP_PKEY_RSA_PSS); - #[cfg(not(boringssl))] - pub const HMAC: Id = Id(ffi::EVP_PKEY_HMAC); - #[cfg(not(any(boringssl, awslc)))] - pub const CMAC: Id = Id(ffi::EVP_PKEY_CMAC); - pub const DSA: Id = Id(ffi::EVP_PKEY_DSA); - pub const DH: Id = Id(ffi::EVP_PKEY_DH); - #[cfg(ossl110)] - pub const DHX: Id = Id(ffi::EVP_PKEY_DHX); - pub const EC: Id = Id(ffi::EVP_PKEY_EC); - #[cfg(ossl111)] - pub const SM2: Id = Id(ffi::EVP_PKEY_SM2); - - #[cfg(any(ossl110, boringssl, libressl360, awslc))] - pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF); - - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519); - #[cfg(ossl111)] - pub const ED448: Id = Id(ffi::EVP_PKEY_ED448); - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - pub const X25519: Id = Id(ffi::EVP_PKEY_X25519); - #[cfg(ossl111)] - pub const X448: Id = Id(ffi::EVP_PKEY_X448); - #[cfg(ossl111)] - pub const POLY1305: Id = Id(ffi::EVP_PKEY_POLY1305); - - /// Creates a `Id` from an integer representation. - pub fn from_raw(value: c_int) -> Id { - Id(value) - } - - /// Returns the integer representation of the `Id`. - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn as_raw(&self) -> c_int { - self.0 - } -} - -/// A trait indicating that a key has parameters. -pub unsafe trait HasParams {} - -unsafe impl HasParams for Params {} - -unsafe impl HasParams for T where T: HasPublic {} - -/// A trait indicating that a key has public components. -pub unsafe trait HasPublic {} - -unsafe impl HasPublic for Public {} - -unsafe impl HasPublic for T where T: HasPrivate {} - -/// A trait indicating that a key has private components. -pub unsafe trait HasPrivate {} - -unsafe impl HasPrivate for Private {} - -generic_foreign_type_and_impl_send_sync! { - type CType = ffi::EVP_PKEY; - fn drop = ffi::EVP_PKEY_free; - - /// A public or private key. - pub struct PKey; - /// Reference to `PKey`. - pub struct PKeyRef; -} - -impl ToOwned for PKeyRef { - type Owned = PKey; - - fn to_owned(&self) -> PKey { - unsafe { - EVP_PKEY_up_ref(self.as_ptr()); - PKey::from_ptr(self.as_ptr()) - } - } -} - -impl PKeyRef { - /// Returns a copy of the internal RSA key. - #[corresponds(EVP_PKEY_get1_RSA)] - pub fn rsa(&self) -> Result, ErrorStack> { - unsafe { - let rsa = cvt_p(ffi::EVP_PKEY_get1_RSA(self.as_ptr()))?; - Ok(Rsa::from_ptr(rsa)) - } - } - - /// Returns a copy of the internal DSA key. - #[corresponds(EVP_PKEY_get1_DSA)] - pub fn dsa(&self) -> Result, ErrorStack> { - unsafe { - let dsa = cvt_p(ffi::EVP_PKEY_get1_DSA(self.as_ptr()))?; - Ok(Dsa::from_ptr(dsa)) - } - } - - /// Returns a copy of the internal DH key. - #[corresponds(EVP_PKEY_get1_DH)] - pub fn dh(&self) -> Result, ErrorStack> { - unsafe { - let dh = cvt_p(ffi::EVP_PKEY_get1_DH(self.as_ptr()))?; - Ok(Dh::from_ptr(dh)) - } - } - - /// Returns a copy of the internal elliptic curve key. - #[corresponds(EVP_PKEY_get1_EC_KEY)] - pub fn ec_key(&self) -> Result, ErrorStack> { - unsafe { - let ec_key = cvt_p(ffi::EVP_PKEY_get1_EC_KEY(self.as_ptr()))?; - Ok(EcKey::from_ptr(ec_key)) - } - } - - /// Returns the `Id` that represents the type of this key. - #[corresponds(EVP_PKEY_id)] - pub fn id(&self) -> Id { - unsafe { Id::from_raw(ffi::EVP_PKEY_id(self.as_ptr())) } - } - - /// Returns the maximum size of a signature in bytes. - #[corresponds(EVP_PKEY_size)] - pub fn size(&self) -> usize { - unsafe { ffi::EVP_PKEY_size(self.as_ptr()) as usize } - } -} - -impl PKeyRef -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_PUBKEY)] - public_key_to_pem, - ffi::PEM_write_bio_PUBKEY - } - - to_der! { - /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure. - #[corresponds(i2d_PUBKEY)] - public_key_to_der, - ffi::i2d_PUBKEY - } - - /// Returns the size of the key. - /// - /// This corresponds to the bit length of the modulus of an RSA key, and the bit length of the - /// group order for an elliptic curve key, for example. - #[corresponds(EVP_PKEY_bits)] - pub fn bits(&self) -> u32 { - unsafe { ffi::EVP_PKEY_bits(self.as_ptr()) as u32 } - } - - ///Returns the number of security bits. - /// - ///Bits of security is defined in NIST SP800-57. - #[corresponds(EVP_PKEY_security_bits)] - #[cfg(any(ossl110, libressl360))] - pub fn security_bits(&self) -> u32 { - unsafe { ffi::EVP_PKEY_security_bits(self.as_ptr()) as u32 } - } - - /// Compares the public component of this key with another. - #[corresponds(EVP_PKEY_cmp)] - pub fn public_eq(&self, other: &PKeyRef) -> bool - where - U: HasPublic, - { - let res = unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 }; - // Clear the stack. OpenSSL will put an error on the stack when the - // keys are different types in some situations. - let _ = ErrorStack::get(); - res - } - - /// Raw byte representation of a public key. - /// - /// This function only works for algorithms that support raw public keys. - /// Currently this is: [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`]. - #[corresponds(EVP_PKEY_get_raw_public_key)] - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - pub fn raw_public_key(&self) -> Result, ErrorStack> { - unsafe { - let mut len = 0; - cvt(ffi::EVP_PKEY_get_raw_public_key( - self.as_ptr(), - ptr::null_mut(), - &mut len, - ))?; - let mut buf = vec![0u8; len]; - cvt(ffi::EVP_PKEY_get_raw_public_key( - self.as_ptr(), - buf.as_mut_ptr(), - &mut len, - ))?; - buf.truncate(len); - Ok(buf) - } - } -} - -impl PKeyRef -where - T: HasPrivate, -{ - private_key_to_pem! { - /// Serializes the private key to a PEM-encoded PKCS#8 PrivateKeyInfo structure. - /// - /// The output will have a header of `-----BEGIN PRIVATE KEY-----`. - #[corresponds(PEM_write_bio_PKCS8PrivateKey)] - private_key_to_pem_pkcs8, - /// Serializes the private key to a PEM-encoded PKCS#8 EncryptedPrivateKeyInfo structure. - /// - /// The output will have a header of `-----BEGIN ENCRYPTED PRIVATE KEY-----`. - #[corresponds(PEM_write_bio_PKCS8PrivateKey)] - private_key_to_pem_pkcs8_passphrase, - ffi::PEM_write_bio_PKCS8PrivateKey - } - - to_der! { - /// Serializes the private key to a DER-encoded key type specific format. - #[corresponds(i2d_PrivateKey)] - private_key_to_der, - ffi::i2d_PrivateKey - } - - /// Raw byte representation of a private key. - /// - /// This function only works for algorithms that support raw private keys. - /// Currently this is: [`Id::HMAC`], [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`]. - #[corresponds(EVP_PKEY_get_raw_private_key)] - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - pub fn raw_private_key(&self) -> Result, ErrorStack> { - unsafe { - let mut len = 0; - cvt(ffi::EVP_PKEY_get_raw_private_key( - self.as_ptr(), - ptr::null_mut(), - &mut len, - ))?; - let mut buf = vec![0u8; len]; - cvt(ffi::EVP_PKEY_get_raw_private_key( - self.as_ptr(), - buf.as_mut_ptr(), - &mut len, - ))?; - buf.truncate(len); - Ok(buf) - } - } - - /// Serializes a private key into an unencrypted DER-formatted PKCS#8 - #[corresponds(i2d_PKCS8PrivateKey_bio)] - pub fn private_key_to_pkcs8(&self) -> Result, ErrorStack> { - unsafe { - let bio = MemBio::new()?; - cvt(ffi::i2d_PKCS8PrivateKey_bio( - bio.as_ptr(), - self.as_ptr(), - ptr::null(), - ptr::null_mut(), - 0, - None, - ptr::null_mut(), - ))?; - - Ok(bio.get_buf().to_owned()) - } - } - - /// Serializes a private key into a DER-formatted PKCS#8, using the supplied password to - /// encrypt the key. - #[corresponds(i2d_PKCS8PrivateKey_bio)] - pub fn private_key_to_pkcs8_passphrase( - &self, - cipher: Cipher, - passphrase: &[u8], - ) -> Result, ErrorStack> { - unsafe { - let bio = MemBio::new()?; - cvt(ffi::i2d_PKCS8PrivateKey_bio( - bio.as_ptr(), - self.as_ptr(), - cipher.as_ptr(), - passphrase.as_ptr() as *const _ as *mut _, - passphrase.len().try_into().unwrap(), - None, - ptr::null_mut(), - ))?; - - Ok(bio.get_buf().to_owned()) - } - } -} - -impl fmt::Debug for PKey { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let alg = match self.id() { - Id::RSA => "RSA", - #[cfg(any(ossl111, libressl, boringssl, awslc))] - Id::RSA_PSS => "RSA-PSS", - #[cfg(not(boringssl))] - Id::HMAC => "HMAC", - #[cfg(not(any(boringssl, awslc)))] - Id::CMAC => "CMAC", - Id::DSA => "DSA", - Id::DH => "DH", - #[cfg(ossl110)] - Id::DHX => "DHX", - Id::EC => "EC", - #[cfg(ossl111)] - Id::SM2 => "SM2", - #[cfg(any(ossl110, boringssl, libressl360, awslc))] - Id::HKDF => "HKDF", - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - Id::ED25519 => "Ed25519", - #[cfg(ossl111)] - Id::ED448 => "Ed448", - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - Id::X25519 => "X25519", - #[cfg(ossl111)] - Id::X448 => "X448", - #[cfg(ossl111)] - Id::POLY1305 => "POLY1305", - _ => "unknown", - }; - fmt.debug_struct("PKey").field("algorithm", &alg).finish() - // TODO: Print details for each specific type of key - } -} - -impl Clone for PKey { - fn clone(&self) -> PKey { - PKeyRef::to_owned(self) - } -} - -impl PKey { - /// Creates a new `PKey` containing an RSA key. - #[corresponds(EVP_PKEY_set1_RSA)] - pub fn from_rsa(rsa: Rsa) -> Result, ErrorStack> { - // TODO: Next time we make backwards incompatible changes, this could - // become an `&RsaRef`. Same for all the other `from_*` methods. - unsafe { - let evp = cvt_p(ffi::EVP_PKEY_new())?; - let pkey = PKey::from_ptr(evp); - cvt(ffi::EVP_PKEY_set1_RSA(pkey.0, rsa.as_ptr()))?; - Ok(pkey) - } - } - - /// Creates a new `PKey` containing a DSA key. - #[corresponds(EVP_PKEY_set1_DSA)] - pub fn from_dsa(dsa: Dsa) -> Result, ErrorStack> { - unsafe { - let evp = cvt_p(ffi::EVP_PKEY_new())?; - let pkey = PKey::from_ptr(evp); - cvt(ffi::EVP_PKEY_set1_DSA(pkey.0, dsa.as_ptr()))?; - Ok(pkey) - } - } - - /// Creates a new `PKey` containing a Diffie-Hellman key. - #[corresponds(EVP_PKEY_set1_DH)] - #[cfg(not(boringssl))] - pub fn from_dh(dh: Dh) -> Result, ErrorStack> { - unsafe { - let evp = cvt_p(ffi::EVP_PKEY_new())?; - let pkey = PKey::from_ptr(evp); - cvt(ffi::EVP_PKEY_set1_DH(pkey.0, dh.as_ptr()))?; - Ok(pkey) - } - } - - /// Creates a new `PKey` containing a Diffie-Hellman key with type DHX. - #[cfg(all(not(any(boringssl, awslc)), ossl110))] - pub fn from_dhx(dh: Dh) -> Result, ErrorStack> { - unsafe { - let evp = cvt_p(ffi::EVP_PKEY_new())?; - let pkey = PKey::from_ptr(evp); - cvt(ffi::EVP_PKEY_assign( - pkey.0, - ffi::EVP_PKEY_DHX, - dh.as_ptr().cast(), - ))?; - mem::forget(dh); - Ok(pkey) - } - } - - /// Creates a new `PKey` containing an elliptic curve key. - #[corresponds(EVP_PKEY_set1_EC_KEY)] - pub fn from_ec_key(ec_key: EcKey) -> Result, ErrorStack> { - unsafe { - let evp = cvt_p(ffi::EVP_PKEY_new())?; - let pkey = PKey::from_ptr(evp); - cvt(ffi::EVP_PKEY_set1_EC_KEY(pkey.0, ec_key.as_ptr()))?; - Ok(pkey) - } - } -} - -impl PKey { - /// Creates a new `PKey` containing an HMAC key. - /// - /// # Note - /// - /// To compute HMAC values, use the `sign` module. - #[corresponds(EVP_PKEY_new_mac_key)] - #[cfg(not(boringssl))] - pub fn hmac(key: &[u8]) -> Result, ErrorStack> { - #[cfg(awslc)] - let key_len = key.len(); - #[cfg(not(awslc))] - let key_len = key.len() as c_int; - unsafe { - assert!(key.len() <= c_int::MAX as usize); - let key = cvt_p(ffi::EVP_PKEY_new_mac_key( - ffi::EVP_PKEY_HMAC, - ptr::null_mut(), - key.as_ptr() as *const _, - key_len, - ))?; - Ok(PKey::from_ptr(key)) - } - } - - /// Creates a new `PKey` containing a CMAC key. - /// - /// Requires OpenSSL 1.1.0 or newer. - /// - /// # Note - /// - /// To compute CMAC values, use the `sign` module. - #[cfg(all(not(any(boringssl, awslc)), ossl110))] - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn cmac(cipher: &Cipher, key: &[u8]) -> Result, ErrorStack> { - let mut ctx = PkeyCtx::new_id(Id::CMAC)?; - ctx.keygen_init()?; - ctx.set_keygen_cipher(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) })?; - ctx.set_keygen_mac_key(key)?; - ctx.keygen() - } - - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - fn generate_eddsa(id: Id) -> Result, ErrorStack> { - let mut ctx = PkeyCtx::new_id(id)?; - ctx.keygen_init()?; - ctx.keygen() - } - - /// Generates a new private X25519 key. - /// - /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`]. - /// - /// # Examples - /// - /// ``` - /// # fn main() -> Result<(), Box> { - /// use openssl::pkey::{PKey, Id}; - /// use openssl::derive::Deriver; - /// - /// let public = // ... - /// # &PKey::generate_x25519()?.raw_public_key()?; - /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X25519)?; - /// - /// let key = PKey::generate_x25519()?; - /// let mut deriver = Deriver::new(&key)?; - /// deriver.set_peer(&public_key)?; - /// - /// let secret = deriver.derive_to_vec()?; - /// assert_eq!(secret.len(), 32); - /// # Ok(()) } - /// ``` - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - pub fn generate_x25519() -> Result, ErrorStack> { - PKey::generate_eddsa(Id::X25519) - } - - /// Generates a new private X448 key. - /// - /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`]. - /// - /// # Examples - /// - /// ``` - /// # fn main() -> Result<(), Box> { - /// use openssl::pkey::{PKey, Id}; - /// use openssl::derive::Deriver; - /// - /// let public = // ... - /// # &PKey::generate_x448()?.raw_public_key()?; - /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X448)?; - /// - /// let key = PKey::generate_x448()?; - /// let mut deriver = Deriver::new(&key)?; - /// deriver.set_peer(&public_key)?; - /// - /// let secret = deriver.derive_to_vec()?; - /// assert_eq!(secret.len(), 56); - /// # Ok(()) } - /// ``` - #[cfg(ossl111)] - pub fn generate_x448() -> Result, ErrorStack> { - PKey::generate_eddsa(Id::X448) - } - - /// Generates a new private Ed25519 key. - /// - /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`]. - /// - /// # Examples - /// - /// ``` - /// # fn main() -> Result<(), Box> { - /// use openssl::pkey::{PKey, Id}; - /// use openssl::sign::Signer; - /// - /// let key = PKey::generate_ed25519()?; - /// let public_key = key.raw_public_key()?; - /// - /// let mut signer = Signer::new_without_digest(&key)?; - /// let digest = // ... - /// # &vec![0; 32]; - /// let signature = signer.sign_oneshot_to_vec(digest)?; - /// assert_eq!(signature.len(), 64); - /// # Ok(()) } - /// ``` - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - pub fn generate_ed25519() -> Result, ErrorStack> { - PKey::generate_eddsa(Id::ED25519) - } - - /// Generates a new private Ed448 key. - /// - /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`]. - /// - /// # Examples - /// - /// ``` - /// # fn main() -> Result<(), Box> { - /// use openssl::pkey::{PKey, Id}; - /// use openssl::sign::Signer; - /// - /// let key = PKey::generate_ed448()?; - /// let public_key = key.raw_public_key()?; - /// - /// let mut signer = Signer::new_without_digest(&key)?; - /// let digest = // ... - /// # &vec![0; 32]; - /// let signature = signer.sign_oneshot_to_vec(digest)?; - /// assert_eq!(signature.len(), 114); - /// # Ok(()) } - /// ``` - #[cfg(ossl111)] - pub fn generate_ed448() -> Result, ErrorStack> { - PKey::generate_eddsa(Id::ED448) - } - - /// Generates a new EC key using the provided curve. - /// - /// Requires OpenSSL 3.0.0 or newer. - #[corresponds(EVP_EC_gen)] - #[cfg(ossl300)] - pub fn ec_gen(curve: &str) -> Result, ErrorStack> { - ffi::init(); - - let curve = CString::new(curve).unwrap(); - unsafe { - let ptr = cvt_p(ffi::EVP_EC_gen(curve.as_ptr()))?; - Ok(PKey::from_ptr(ptr)) - } - } - - private_key_from_pem! { - /// Deserializes a private key from a PEM-encoded key type specific format. - #[corresponds(PEM_read_bio_PrivateKey)] - private_key_from_pem, - - /// Deserializes a private key from a PEM-encoded encrypted key type specific format. - #[corresponds(PEM_read_bio_PrivateKey)] - private_key_from_pem_passphrase, - - /// Deserializes a private key from a PEM-encoded encrypted key type specific format. - /// - /// The callback should fill the password into the provided buffer and return its length. - #[corresponds(PEM_read_bio_PrivateKey)] - private_key_from_pem_callback, - PKey, - ffi::PEM_read_bio_PrivateKey - } - - from_der! { - /// Decodes a DER-encoded private key. - /// - /// This function will attempt to automatically detect the underlying key format, and - /// supports the unencrypted PKCS#8 PrivateKeyInfo structures as well as key type specific - /// formats. - #[corresponds(d2i_AutoPrivateKey)] - private_key_from_der, - PKey, - ffi::d2i_AutoPrivateKey - } - - /// Deserializes a DER-formatted PKCS#8 unencrypted private key. - /// - /// This method is mainly for interoperability reasons. Encrypted keyfiles should be preferred. - pub fn private_key_from_pkcs8(der: &[u8]) -> Result, ErrorStack> { - unsafe { - ffi::init(); - let len = der.len().min(c_long::MAX as usize) as c_long; - let p8inf = cvt_p(ffi::d2i_PKCS8_PRIV_KEY_INFO( - ptr::null_mut(), - &mut der.as_ptr(), - len, - ))?; - let res = cvt_p(ffi::EVP_PKCS82PKEY(p8inf)).map(|p| PKey::from_ptr(p)); - ffi::PKCS8_PRIV_KEY_INFO_free(p8inf); - res - } - } - - /// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password - /// if the key is encrypted. - /// - /// The callback should copy the password into the provided buffer and return the number of - /// bytes written. - #[corresponds(d2i_PKCS8PrivateKey_bio)] - pub fn private_key_from_pkcs8_callback( - der: &[u8], - callback: F, - ) -> Result, ErrorStack> - where - F: FnOnce(&mut [u8]) -> Result, - { - unsafe { - ffi::init(); - let mut cb = CallbackState::new(callback); - let bio = MemBioSlice::new(der)?; - cvt_p(ffi::d2i_PKCS8PrivateKey_bio( - bio.as_ptr(), - ptr::null_mut(), - Some(invoke_passwd_cb::), - &mut cb as *mut _ as *mut _, - )) - .map(|p| PKey::from_ptr(p)) - } - } - - /// Deserializes a DER-formatted PKCS#8 private key, using the supplied password if the key is - /// encrypted. - /// - /// # Panics - /// - /// Panics if `passphrase` contains an embedded null. - #[corresponds(d2i_PKCS8PrivateKey_bio)] - pub fn private_key_from_pkcs8_passphrase( - der: &[u8], - passphrase: &[u8], - ) -> Result, ErrorStack> { - unsafe { - ffi::init(); - let bio = MemBioSlice::new(der)?; - let passphrase = CString::new(passphrase).unwrap(); - cvt_p(ffi::d2i_PKCS8PrivateKey_bio( - bio.as_ptr(), - ptr::null_mut(), - None, - passphrase.as_ptr() as *const _ as *mut _, - )) - .map(|p| PKey::from_ptr(p)) - } - } - - /// Creates a private key from its raw byte representation - /// - /// Algorithm types that support raw private keys are HMAC, X25519, ED25519, X448 or ED448 - #[corresponds(EVP_PKEY_new_raw_private_key)] - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - pub fn private_key_from_raw_bytes( - bytes: &[u8], - key_type: Id, - ) -> Result, ErrorStack> { - unsafe { - ffi::init(); - cvt_p(ffi::EVP_PKEY_new_raw_private_key( - key_type.as_raw(), - ptr::null_mut(), - bytes.as_ptr(), - bytes.len(), - )) - .map(|p| PKey::from_ptr(p)) - } - } -} - -impl PKey { - private_key_from_pem! { - /// Decodes a PEM-encoded SubjectPublicKeyInfo structure. - /// - /// The input should have a header of `-----BEGIN PUBLIC KEY-----`. - #[corresponds(PEM_read_bio_PUBKEY)] - public_key_from_pem, - - /// Decodes a PEM-encoded SubjectPublicKeyInfo structure. - #[corresponds(PEM_read_bio_PUBKEY)] - public_key_from_pem_passphrase, - - /// Decodes a PEM-encoded SubjectPublicKeyInfo structure. - /// - /// The callback should fill the password into the provided buffer and return its length. - #[corresponds(PEM_read_bio_PrivateKey)] - public_key_from_pem_callback, - PKey, - ffi::PEM_read_bio_PUBKEY - } - - from_der! { - /// Decodes a DER-encoded SubjectPublicKeyInfo structure. - #[corresponds(d2i_PUBKEY)] - public_key_from_der, - PKey, - ffi::d2i_PUBKEY - } - - /// Creates a public key from its raw byte representation - /// - /// Algorithm types that support raw public keys are X25519, ED25519, X448 or ED448 - #[corresponds(EVP_PKEY_new_raw_public_key)] - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - pub fn public_key_from_raw_bytes( - bytes: &[u8], - key_type: Id, - ) -> Result, ErrorStack> { - unsafe { - ffi::init(); - cvt_p(ffi::EVP_PKEY_new_raw_public_key( - key_type.as_raw(), - ptr::null_mut(), - bytes.as_ptr(), - bytes.len(), - )) - .map(|p| PKey::from_ptr(p)) - } - } -} - -cfg_if! { - if #[cfg(any(boringssl, ossl110, libressl, awslc))] { - use ffi::EVP_PKEY_up_ref; - } else { - #[allow(bad_style)] - unsafe extern "C" fn EVP_PKEY_up_ref(pkey: *mut ffi::EVP_PKEY) { - ffi::CRYPTO_add_lock( - &mut (*pkey).references, - 1, - ffi::CRYPTO_LOCK_EVP_PKEY, - "pkey.rs\0".as_ptr() as *const _, - line!() as c_int, - ); - } - } -} - -impl TryFrom> for PKey { - type Error = ErrorStack; - - fn try_from(ec_key: EcKey) -> Result, ErrorStack> { - PKey::from_ec_key(ec_key) - } -} - -impl TryFrom> for EcKey { - type Error = ErrorStack; - - fn try_from(pkey: PKey) -> Result, ErrorStack> { - pkey.ec_key() - } -} - -impl TryFrom> for PKey { - type Error = ErrorStack; - - fn try_from(rsa: Rsa) -> Result, ErrorStack> { - PKey::from_rsa(rsa) - } -} - -impl TryFrom> for Rsa { - type Error = ErrorStack; - - fn try_from(pkey: PKey) -> Result, ErrorStack> { - pkey.rsa() - } -} - -impl TryFrom> for PKey { - type Error = ErrorStack; - - fn try_from(dsa: Dsa) -> Result, ErrorStack> { - PKey::from_dsa(dsa) - } -} - -impl TryFrom> for Dsa { - type Error = ErrorStack; - - fn try_from(pkey: PKey) -> Result, ErrorStack> { - pkey.dsa() - } -} - -#[cfg(not(boringssl))] -impl TryFrom> for PKey { - type Error = ErrorStack; - - fn try_from(dh: Dh) -> Result, ErrorStack> { - PKey::from_dh(dh) - } -} - -impl TryFrom> for Dh { - type Error = ErrorStack; - - fn try_from(pkey: PKey) -> Result, ErrorStack> { - pkey.dh() - } -} - -#[cfg(test)] -mod tests { - use std::convert::TryInto; - - #[cfg(not(boringssl))] - use crate::dh::Dh; - use crate::dsa::Dsa; - use crate::ec::EcKey; - use crate::error::Error; - use crate::nid::Nid; - use crate::rsa::Rsa; - use crate::symm::Cipher; - - use super::*; - - #[cfg(any(ossl111, awslc))] - use crate::rand::rand_bytes; - - #[test] - fn test_to_password() { - let rsa = Rsa::generate(2048).unwrap(); - let pkey = PKey::from_rsa(rsa).unwrap(); - let pem = pkey - .private_key_to_pem_pkcs8_passphrase(Cipher::aes_128_cbc(), b"foobar") - .unwrap(); - PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap(); - assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err()); - } - - #[test] - fn test_unencrypted_pkcs8() { - let key = include_bytes!("../test/pkcs8-nocrypt.der"); - let pkey = PKey::private_key_from_pkcs8(key).unwrap(); - let serialized = pkey.private_key_to_pkcs8().unwrap(); - let pkey2 = PKey::private_key_from_pkcs8(&serialized).unwrap(); - - assert_eq!( - pkey2.private_key_to_der().unwrap(), - pkey.private_key_to_der().unwrap() - ); - } - - #[test] - fn test_encrypted_pkcs8_passphrase() { - let key = include_bytes!("../test/pkcs8.der"); - PKey::private_key_from_pkcs8_passphrase(key, b"mypass").unwrap(); - - let rsa = Rsa::generate(2048).unwrap(); - let pkey = PKey::from_rsa(rsa).unwrap(); - let der = pkey - .private_key_to_pkcs8_passphrase(Cipher::aes_128_cbc(), b"mypass") - .unwrap(); - let pkey2 = PKey::private_key_from_pkcs8_passphrase(&der, b"mypass").unwrap(); - assert_eq!( - pkey.private_key_to_der().unwrap(), - pkey2.private_key_to_der().unwrap() - ); - } - - #[test] - fn test_encrypted_pkcs8_callback() { - let mut password_queried = false; - let key = include_bytes!("../test/pkcs8.der"); - PKey::private_key_from_pkcs8_callback(key, |password| { - password_queried = true; - password[..6].copy_from_slice(b"mypass"); - Ok(6) - }) - .unwrap(); - assert!(password_queried); - } - - #[test] - fn test_private_key_from_pem() { - let key = include_bytes!("../test/key.pem"); - PKey::private_key_from_pem(key).unwrap(); - } - - #[test] - fn test_public_key_from_pem() { - let key = include_bytes!("../test/key.pem.pub"); - PKey::public_key_from_pem(key).unwrap(); - } - - #[test] - fn test_public_key_from_der() { - let key = include_bytes!("../test/key.der.pub"); - PKey::public_key_from_der(key).unwrap(); - } - - #[test] - fn test_private_key_from_der() { - let key = include_bytes!("../test/key.der"); - PKey::private_key_from_der(key).unwrap(); - } - - #[test] - fn test_pem() { - let key = include_bytes!("../test/key.pem"); - let key = PKey::private_key_from_pem(key).unwrap(); - - let priv_key = key.private_key_to_pem_pkcs8().unwrap(); - let pub_key = key.public_key_to_pem().unwrap(); - - // As a super-simple verification, just check that the buffers contain - // the `PRIVATE KEY` or `PUBLIC KEY` strings. - assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY")); - assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY")); - } - - #[test] - fn test_rsa_accessor() { - let rsa = Rsa::generate(2048).unwrap(); - let pkey = PKey::from_rsa(rsa).unwrap(); - pkey.rsa().unwrap(); - assert_eq!(pkey.id(), Id::RSA); - assert!(pkey.dsa().is_err()); - } - - #[test] - fn test_dsa_accessor() { - let dsa = Dsa::generate(2048).unwrap(); - let pkey = PKey::from_dsa(dsa).unwrap(); - pkey.dsa().unwrap(); - assert_eq!(pkey.id(), Id::DSA); - assert!(pkey.rsa().is_err()); - } - - #[test] - #[cfg(not(boringssl))] - fn test_dh_accessor() { - let dh = include_bytes!("../test/dhparams.pem"); - let dh = Dh::params_from_pem(dh).unwrap(); - let pkey = PKey::from_dh(dh).unwrap(); - pkey.dh().unwrap(); - assert_eq!(pkey.id(), Id::DH); - assert!(pkey.rsa().is_err()); - } - - #[test] - fn test_ec_key_accessor() { - let ec_key = EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let pkey = PKey::from_ec_key(ec_key).unwrap(); - pkey.ec_key().unwrap(); - assert_eq!(pkey.id(), Id::EC); - assert!(pkey.rsa().is_err()); - } - - #[test] - fn test_rsa_conversion() { - let rsa = Rsa::generate(2048).unwrap(); - let pkey: PKey = rsa.clone().try_into().unwrap(); - let rsa_: Rsa = pkey.try_into().unwrap(); - // Eq is missing - assert_eq!(rsa.p(), rsa_.p()); - assert_eq!(rsa.q(), rsa_.q()); - } - - #[test] - fn test_dsa_conversion() { - let dsa = Dsa::generate(2048).unwrap(); - let pkey: PKey = dsa.clone().try_into().unwrap(); - let dsa_: Dsa = pkey.try_into().unwrap(); - // Eq is missing - assert_eq!(dsa.priv_key(), dsa_.priv_key()); - } - - #[test] - fn test_ec_key_conversion() { - let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::X9_62_PRIME256V1).unwrap(); - let ec_key = EcKey::generate(&group).unwrap(); - let pkey: PKey = ec_key.clone().try_into().unwrap(); - let ec_key_: EcKey = pkey.try_into().unwrap(); - // Eq is missing - assert_eq!(ec_key.private_key(), ec_key_.private_key()); - } - - #[test] - #[cfg(any(ossl110, libressl360))] - fn test_security_bits() { - let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::SECP521R1).unwrap(); - let ec_key = EcKey::generate(&group).unwrap(); - let pkey: PKey = ec_key.try_into().unwrap(); - - assert_eq!(pkey.security_bits(), 256); - } - - #[test] - #[cfg(not(boringssl))] - fn test_dh_conversion() { - let dh_params = include_bytes!("../test/dhparams.pem"); - let dh_params = Dh::params_from_pem(dh_params).unwrap(); - let dh = dh_params.generate_key().unwrap(); - - // Clone is missing for Dh, save the parameters - let p = dh.prime_p().to_owned().unwrap(); - let q = dh.prime_q().map(|q| q.to_owned().unwrap()); - let g = dh.generator().to_owned().unwrap(); - - let pkey: PKey = dh.try_into().unwrap(); - let dh_: Dh = pkey.try_into().unwrap(); - - // Eq is missing - assert_eq!(&p, dh_.prime_p()); - assert_eq!(q, dh_.prime_q().map(|q| q.to_owned().unwrap())); - assert_eq!(&g, dh_.generator()); - } - - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - fn test_raw_public_key(gen: fn() -> Result, ErrorStack>, key_type: Id) { - // Generate a new key - let key = gen().unwrap(); - - // Get the raw bytes, and create a new key from the raw bytes - let raw = key.raw_public_key().unwrap(); - let from_raw = PKey::public_key_from_raw_bytes(&raw, key_type).unwrap(); - - // Compare the der encoding of the original and raw / restored public key - assert_eq!( - key.public_key_to_der().unwrap(), - from_raw.public_key_to_der().unwrap() - ); - } - - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - fn test_raw_private_key(gen: fn() -> Result, ErrorStack>, key_type: Id) { - // Generate a new key - let key = gen().unwrap(); - - // Get the raw bytes, and create a new key from the raw bytes - let raw = key.raw_private_key().unwrap(); - let from_raw = PKey::private_key_from_raw_bytes(&raw, key_type).unwrap(); - - // Compare the der encoding of the original and raw / restored public key - assert_eq!( - key.private_key_to_pkcs8().unwrap(), - from_raw.private_key_to_pkcs8().unwrap() - ); - } - - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - #[test] - fn test_raw_public_key_bytes() { - test_raw_public_key(PKey::generate_x25519, Id::X25519); - test_raw_public_key(PKey::generate_ed25519, Id::ED25519); - #[cfg(not(any(boringssl, libressl370, awslc)))] - test_raw_public_key(PKey::generate_x448, Id::X448); - #[cfg(not(any(boringssl, libressl370, awslc)))] - test_raw_public_key(PKey::generate_ed448, Id::ED448); - } - - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - #[test] - fn test_raw_private_key_bytes() { - test_raw_private_key(PKey::generate_x25519, Id::X25519); - test_raw_private_key(PKey::generate_ed25519, Id::ED25519); - #[cfg(not(any(boringssl, libressl370, awslc)))] - test_raw_private_key(PKey::generate_x448, Id::X448); - #[cfg(not(any(boringssl, libressl370, awslc)))] - test_raw_private_key(PKey::generate_ed448, Id::ED448); - } - - #[cfg(any(ossl111, awslc))] - #[test] - fn test_raw_hmac() { - let mut test_bytes = vec![0u8; 32]; - rand_bytes(&mut test_bytes).unwrap(); - - let hmac_key = PKey::hmac(&test_bytes).unwrap(); - assert!(hmac_key.raw_public_key().is_err()); - - let key_bytes = hmac_key.raw_private_key().unwrap(); - assert_eq!(key_bytes, test_bytes); - } - - #[cfg(any(ossl111, awslc))] - #[test] - fn test_raw_key_fail() { - // Getting a raw byte representation will not work with Nist curves - let group = crate::ec::EcGroup::from_curve_name(Nid::SECP256K1).unwrap(); - let ec_key = EcKey::generate(&group).unwrap(); - let pkey = PKey::from_ec_key(ec_key).unwrap(); - assert!(pkey.raw_private_key().is_err()); - assert!(pkey.raw_public_key().is_err()); - } - - #[cfg(ossl300)] - #[test] - fn test_ec_gen() { - let key = PKey::ec_gen("prime256v1").unwrap(); - assert!(key.ec_key().is_ok()); - } - - #[test] - fn test_public_eq() { - let rsa = Rsa::generate(2048).unwrap(); - let pkey1 = PKey::from_rsa(rsa).unwrap(); - - let group = crate::ec::EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let ec_key = EcKey::generate(&group).unwrap(); - let pkey2 = PKey::from_ec_key(ec_key).unwrap(); - - assert!(!pkey1.public_eq(&pkey2)); - assert!(Error::get().is_none()); - } -} diff --git a/patch/openssl/src/pkey_ctx.rs b/patch/openssl/src/pkey_ctx.rs deleted file mode 100644 index b85876c25fc94..0000000000000 --- a/patch/openssl/src/pkey_ctx.rs +++ /dev/null @@ -1,1300 +0,0 @@ -//! 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(); -//! ``` - -#![cfg_attr( - not(any(boringssl, awslc)), - doc = r#"\ -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::bn::BigNumRef; -#[cfg(not(any(boringssl, awslc)))] -use crate::cipher::CipherRef; -use crate::error::ErrorStack; -use crate::md::MdRef; -use crate::nid::Nid; -use crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Params, Private}; -use crate::rsa::Padding; -use crate::sign::RsaPssSaltlen; -use crate::{cvt, cvt_p}; -use cfg_if::cfg_if; -use foreign_types::{ForeignType, ForeignTypeRef}; -#[cfg(not(any(boringssl, awslc)))] -use libc::c_int; -#[cfg(ossl320)] -use libc::c_uint; -use openssl_macros::corresponds; -use std::convert::TryFrom; -#[cfg(ossl320)] -use std::ffi::CStr; -use std::ptr; - -/// HKDF modes of operation. -#[cfg(any(ossl111, libressl360))] -pub struct HkdfMode(c_int); - -#[cfg(any(ossl111, libressl360))] -impl HkdfMode { - /// This is the default mode. Calling [`derive`][PkeyCtxRef::derive] on a [`PkeyCtxRef`] set up - /// for HKDF will perform an extract followed by an expand operation in one go. The derived key - /// returned will be the result after the expand operation. The intermediate fixed-length - /// pseudorandom key K is not returned. - pub const EXTRACT_THEN_EXPAND: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND); - - /// In this mode calling [`derive`][PkeyCtxRef::derive] will just perform the extract operation. - /// The value returned will be the intermediate fixed-length pseudorandom key K. - /// - /// The digest, key and salt values must be set before a key is derived or an error occurs. - pub const EXTRACT_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY); - - /// In this mode calling [`derive`][PkeyCtxRef::derive] will just perform the expand operation. - /// The input key should be set to the intermediate fixed-length pseudorandom key K returned - /// from a previous extract operation. - /// - /// The digest, key and info values must be set before a key is derived or an error occurs. - pub const EXPAND_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXPAND_ONLY); -} - -/// Nonce type for ECDSA and DSA. -#[cfg(ossl320)] -#[derive(Debug, PartialEq)] -pub struct NonceType(c_uint); - -#[cfg(ossl320)] -impl NonceType { - /// This is the default mode. It uses a random value for the nonce k as defined in FIPS 186-4 Section 6.3 - /// “Secret Number Generation”. - pub const RANDOM_K: Self = NonceType(0); - - /// Uses a deterministic value for the nonce k as defined in RFC #6979 (See Section 3.2 “Generation of k”). - pub const DETERMINISTIC_K: Self = NonceType(1); -} - -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; - /// A reference to a [`PkeyCtx`]. - pub struct PkeyCtxRef; -} - -impl PkeyCtx { - /// Creates a new pkey context using the provided key. - #[corresponds(EVP_PKEY_CTX_new)] - #[inline] - pub fn new(pkey: &PKeyRef) -> Result { - 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_CTX_new_id)] - #[inline] - pub fn new_id(id: Id) -> Result { - unsafe { - let ptr = cvt_p(ffi::EVP_PKEY_CTX_new_id(id.as_raw(), ptr::null_mut()))?; - Ok(PkeyCtx::from_ptr(ptr)) - } - } -} - -impl PkeyCtxRef -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(()) - } - - /// Prepares the context for signature recovery using the public key. - #[corresponds(EVP_PKEY_verify_recover_init)] - #[inline] - pub fn verify_recover_init(&mut self) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EVP_PKEY_verify_recover_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 { - 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) -> Result { - 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 { - unsafe { - let r = ffi::EVP_PKEY_verify( - self.as_ptr(), - sig.as_ptr(), - sig.len(), - data.as_ptr(), - data.len(), - ); - // `EVP_PKEY_verify` is not terribly consistent about how it, - // reports errors. It does not clearly distinguish between 0 and - // -1, and may put errors on the stack in both cases. If there's - // errors on the stack, we return `Err()`, else we return - // `Ok(false)`. - if r <= 0 { - let errors = ErrorStack::get(); - if !errors.errors().is_empty() { - return Err(errors); - } - } - - Ok(r == 1) - } - } - - /// Recovers the original data signed by the private key. You almost - /// always want `verify` instead. - /// - /// Returns the number of bytes written to `to`, or the number of bytes - /// that would be written, if `to` is `None. - #[corresponds(EVP_PKEY_verify_recover)] - #[inline] - pub fn verify_recover( - &mut self, - sig: &[u8], - to: Option<&mut [u8]>, - ) -> Result { - let mut written = to.as_ref().map_or(0, |b| b.len()); - unsafe { - cvt(ffi::EVP_PKEY_verify_recover( - self.as_ptr(), - to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), - &mut written, - sig.as_ptr(), - sig.len(), - ))?; - } - - Ok(written) - } -} - -impl PkeyCtxRef -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(&mut self, key: &PKeyRef) -> 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 { - 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) -> Result { - 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 { - 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) -> Result { - 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 PkeyCtxRef { - /// 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(()) - } - - /// Prepares the context for key parameter generation. - #[corresponds(EVP_PKEY_paramgen_init)] - #[inline] - pub fn paramgen_init(&mut self) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EVP_PKEY_paramgen_init(self.as_ptr()))?; - } - - Ok(()) - } - - /// Sets which algorithm was used to compute the digest used in a - /// signature. With RSA signatures this causes the signature to be wrapped - /// in a `DigestInfo` structure. This is almost always what you want with - /// RSA signatures. - #[corresponds(EVP_PKEY_CTX_set_signature_md)] - #[inline] - pub fn set_signature_md(&self, md: &MdRef) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EVP_PKEY_CTX_set_signature_md( - self.as_ptr(), - md.as_ptr(), - ))?; - } - Ok(()) - } - - /// Sets the DH paramgen prime length. - /// - /// This is only useful for DH keys. - #[corresponds(EVP_PKEY_CTX_set_dh_paramgen_prime_len)] - #[cfg(not(boringssl))] - #[inline] - pub fn set_dh_paramgen_prime_len(&mut self, bits: u32) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EVP_PKEY_CTX_set_dh_paramgen_prime_len( - self.as_ptr(), - bits as i32, - ))?; - } - - Ok(()) - } - - /// Sets the DH paramgen generator. - /// - /// This is only useful for DH keys. - #[corresponds(EVP_PKEY_CTX_set_dh_paramgen_generator)] - #[cfg(not(boringssl))] - #[inline] - pub fn set_dh_paramgen_generator(&mut self, bits: u32) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EVP_PKEY_CTX_set_dh_paramgen_generator( - self.as_ptr(), - bits as i32, - ))?; - } - - Ok(()) - } - - /// Sets the DSA paramgen bits. - /// - /// This is only useful for DSA keys. - #[corresponds(EVP_PKEY_CTX_set_dsa_paramgen_bits)] - #[inline] - pub fn set_dsa_paramgen_bits(&mut self, bits: u32) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EVP_PKEY_CTX_set_dsa_paramgen_bits( - self.as_ptr(), - bits as i32, - ))?; - } - - Ok(()) - } - - /// Sets the EC paramgen curve NID. - /// - /// This is only useful for EC keys. - #[corresponds(EVP_PKEY_CTX_set_ec_paramgen_curve_nid)] - #[inline] - pub fn set_ec_paramgen_curve_nid(&mut self, nid: Nid) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EVP_PKEY_CTX_set_ec_paramgen_curve_nid( - self.as_ptr(), - nid.as_raw(), - ))?; - } - - 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 { - 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 keygen bits. - /// - /// This is only useful for RSA keys. - #[corresponds(EVP_PKEY_CTX_set_rsa_keygen_bits)] - #[inline] - pub fn set_rsa_keygen_bits(&mut self, bits: u32) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EVP_PKEY_CTX_set_rsa_keygen_bits( - self.as_ptr(), - bits as i32, - ))?; - } - - Ok(()) - } - - /// Sets the RSA keygen public exponent. - /// - /// This is only useful for RSA keys. - #[corresponds(EVP_PKEY_CTX_set1_rsa_keygen_pubexp)] - #[inline] - pub fn set_rsa_keygen_pubexp(&mut self, pubexp: &BigNumRef) -> Result<(), ErrorStack> { - unsafe { - cfg_if! { - if #[cfg(ossl300)] { - cvt(ffi::EVP_PKEY_CTX_set1_rsa_keygen_pubexp( - self.as_ptr(), - pubexp.as_ptr(), - ))?; - } else { - cvt(ffi::EVP_PKEY_CTX_set_rsa_keygen_pubexp( - self.as_ptr(), - // Dupe the BN because the EVP_PKEY_CTX takes ownership of it and will free it. - cvt_p(ffi::BN_dup(pubexp.as_ptr()))?, - ))?; - } - } - } - - Ok(()) - } - - /// Sets the RSA PSS salt length. - /// - /// This is only useful for RSA keys. - #[corresponds(EVP_PKEY_CTX_set_rsa_pss_saltlen)] - #[inline] - pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen( - self.as_ptr(), - len.as_raw(), - )) - .map(|_| ()) - } - } - - /// 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)] - #[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)] - pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> { - use crate::LenType; - let len = LenType::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 as *mut _, - len, - )); - if r.is_err() { - ffi::OPENSSL_free(p); - } - r?; - } - - Ok(()) - } - - /// Sets the cipher used during key generation. - #[cfg(not(any(boringssl, awslc)))] - #[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. - #[cfg(not(any(boringssl, awslc)))] - #[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(any(ossl110, boringssl, libressl360, awslc))] - #[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`]. - /// - /// WARNING: Although this API calls it a "mode", HKDF-Extract and HKDF-Expand are distinct - /// operations with distinct inputs and distinct kinds of keys. Callers should not pass input - /// secrets for one operation into the other. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(EVP_PKEY_CTX_set_hkdf_mode)] - #[cfg(any(ossl111, libressl360))] - #[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 material for HKDF generation as the "key". - /// - /// Which input is the key depends on the "mode" (see [`set_hkdf_mode`][Self::set_hkdf_mode]). - /// If [`HkdfMode::EXTRACT_THEN_EXPAND`] or [`HkdfMode::EXTRACT_ONLY`], this function specifies - /// the input keying material (IKM) for HKDF-Extract. If [`HkdfMode::EXPAND_ONLY`], it instead - /// specifies the pseudorandom key (PRK) for HKDF-Expand. - /// - /// Requires OpenSSL 1.1.0 or newer. - #[corresponds(EVP_PKEY_CTX_set1_hkdf_key)] - #[cfg(any(ossl110, boringssl, libressl360, awslc))] - #[inline] - pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> { - #[cfg(not(any(boringssl, awslc)))] - let len = c_int::try_from(key.len()).unwrap(); - #[cfg(any(boringssl, awslc))] - let len = key.len(); - - unsafe { - cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key( - self.as_ptr(), - key.as_ptr(), - len, - ))?; - } - - Ok(()) - } - - /// Sets the salt value for HKDF generation. - /// - /// If performing HKDF-Expand only, this parameter is ignored. - /// - /// Requires OpenSSL 1.1.0 or newer. - #[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)] - #[cfg(any(ossl110, boringssl, libressl360, awslc))] - #[inline] - pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> { - #[cfg(not(any(boringssl, awslc)))] - let len = c_int::try_from(salt.len()).unwrap(); - #[cfg(any(boringssl, awslc))] - let len = salt.len(); - - unsafe { - cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt( - self.as_ptr(), - salt.as_ptr(), - len, - ))?; - } - - Ok(()) - } - - /// Appends info bytes for HKDF generation. - /// - /// If performing HKDF-Extract only, this parameter is ignored. - /// - /// Requires OpenSSL 1.1.0 or newer. - #[corresponds(EVP_PKEY_CTX_add1_hkdf_info)] - #[cfg(any(ossl110, boringssl, libressl360, awslc))] - #[inline] - pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> { - #[cfg(not(any(boringssl, awslc)))] - let len = c_int::try_from(info.len()).unwrap(); - #[cfg(any(boringssl, awslc))] - let len = info.len(); - - 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 { - 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) -> Result { - 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, ErrorStack> { - unsafe { - let mut key = ptr::null_mut(); - cvt(ffi::EVP_PKEY_keygen(self.as_ptr(), &mut key))?; - Ok(PKey::from_ptr(key)) - } - } - - /// Generates a new set of key parameters. - #[corresponds(EVP_PKEY_paramgen)] - #[inline] - pub fn paramgen(&mut self) -> Result, ErrorStack> { - unsafe { - let mut key = ptr::null_mut(); - cvt(ffi::EVP_PKEY_paramgen(self.as_ptr(), &mut key))?; - Ok(PKey::from_ptr(key)) - } - } - - /// Sets the nonce type for a private key context. - /// - /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979). - /// - /// This is only useful for DSA and ECDSA. - /// Requires OpenSSL 3.2.0 or newer. - #[cfg(ossl320)] - #[corresponds(EVP_PKEY_CTX_set_params)] - pub fn set_nonce_type(&mut self, nonce_type: NonceType) -> Result<(), ErrorStack> { - let nonce_field_name = CStr::from_bytes_with_nul(b"nonce-type\0").unwrap(); - let mut nonce_type = nonce_type.0; - unsafe { - let param_nonce = - ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type); - let param_end = ffi::OSSL_PARAM_construct_end(); - - let params = [param_nonce, param_end]; - cvt(ffi::EVP_PKEY_CTX_set_params(self.as_ptr(), params.as_ptr()))?; - } - Ok(()) - } - - /// Gets the nonce type for a private key context. - /// - /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979). - /// - /// This is only useful for DSA and ECDSA. - /// Requires OpenSSL 3.2.0 or newer. - #[cfg(ossl320)] - #[corresponds(EVP_PKEY_CTX_get_params)] - pub fn nonce_type(&mut self) -> Result { - let nonce_field_name = CStr::from_bytes_with_nul(b"nonce-type\0").unwrap(); - let mut nonce_type: c_uint = 0; - unsafe { - let param_nonce = - ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type); - let param_end = ffi::OSSL_PARAM_construct_end(); - - let mut params = [param_nonce, param_end]; - cvt(ffi::EVP_PKEY_CTX_get_params( - self.as_ptr(), - params.as_mut_ptr(), - ))?; - } - Ok(NonceType(nonce_type)) - } -} - -#[cfg(test)] -mod test { - use super::*; - use crate::bn::BigNum; - #[cfg(not(any(boringssl, awslc)))] - use crate::cipher::Cipher; - use crate::ec::{EcGroup, EcKey}; - use crate::hash::{hash, MessageDigest}; - use crate::md::Md; - use crate::nid::Nid; - use crate::pkey::PKey; - use crate::rsa::Rsa; - use crate::sign::Verifier; - #[cfg(not(boringssl))] - use cfg_if::cfg_if; - - #[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] - 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 rsa_sign() { - 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.sign_init().unwrap(); - ctx.set_rsa_padding(Padding::PKCS1).unwrap(); - ctx.set_signature_md(Md::sha384()).unwrap(); - - let msg = b"hello world"; - let digest = hash(MessageDigest::sha384(), msg).unwrap(); - let mut signature = vec![]; - ctx.sign_to_vec(&digest, &mut signature).unwrap(); - - let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap(); - verifier.update(msg).unwrap(); - assert!(matches!(verifier.verify(&signature), Ok(true))); - } - - #[test] - fn rsa_sign_pss() { - 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.sign_init().unwrap(); - ctx.set_rsa_padding(Padding::PKCS1_PSS).unwrap(); - ctx.set_signature_md(Md::sha384()).unwrap(); - ctx.set_rsa_pss_saltlen(RsaPssSaltlen::custom(14)).unwrap(); - - let msg = b"hello world"; - let digest = hash(MessageDigest::sha384(), msg).unwrap(); - let mut signature = vec![]; - ctx.sign_to_vec(&digest, &mut signature).unwrap(); - - let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap(); - verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap(); - verifier - .set_rsa_pss_saltlen(RsaPssSaltlen::custom(14)) - .unwrap(); - verifier.update(msg).unwrap(); - assert!(matches!(verifier.verify(&signature), Ok(true))); - } - - #[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] - #[cfg(not(any(boringssl, awslc)))] - 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(not(boringssl))] - fn dh_paramgen() { - let mut ctx = PkeyCtx::new_id(Id::DH).unwrap(); - ctx.paramgen_init().unwrap(); - ctx.set_dh_paramgen_prime_len(512).unwrap(); - ctx.set_dh_paramgen_generator(2).unwrap(); - let params = ctx.paramgen().unwrap(); - - assert_eq!(params.size(), 64); - } - - #[test] - #[cfg(not(boringssl))] - fn dsa_paramgen() { - let mut ctx = PkeyCtx::new_id(Id::DSA).unwrap(); - ctx.paramgen_init().unwrap(); - ctx.set_dsa_paramgen_bits(2048).unwrap(); - let params = ctx.paramgen().unwrap(); - - let size = { - cfg_if! { - if #[cfg(awslc)] { - 72 - } else if #[cfg(libressl)] { - 48 - } else { - 64 - } - } - }; - assert_eq!(params.size(), size); - } - - #[test] - fn ec_keygen() { - let mut ctx = PkeyCtx::new_id(Id::EC).unwrap(); - ctx.paramgen_init().unwrap(); - ctx.set_ec_paramgen_curve_nid(Nid::X9_62_PRIME256V1) - .unwrap(); - let params = ctx.paramgen().unwrap(); - - assert_eq!(params.size(), 72); - } - - #[test] - fn rsa_keygen() { - let pubexp = BigNum::from_u32(65537).unwrap(); - let mut ctx = PkeyCtx::new_id(Id::RSA).unwrap(); - ctx.keygen_init().unwrap(); - ctx.set_rsa_keygen_pubexp(&pubexp).unwrap(); - ctx.set_rsa_keygen_bits(2048).unwrap(); - let key = ctx.keygen().unwrap(); - - assert_eq!(key.bits(), 2048); - } - - #[test] - #[cfg(any(ossl110, boringssl, libressl360, awslc))] - 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(any(ossl111, libressl360))] - 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(any(ossl111, libressl360))] - 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); - assert!(matches!(valid, Ok(false) | Err(_))); - assert!(ErrorStack::get().errors().is_empty()); - } - - #[test] - fn verify_fail_ec() { - let key1 = - EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap(); - let key1 = PKey::from_ec_key(key1).unwrap(); - - let data = b"Some Crypto Text"; - let mut ctx = PkeyCtx::new(&key1).unwrap(); - ctx.verify_init().unwrap(); - assert!(matches!(ctx.verify(data, &[0; 64]), Ok(false) | Err(_))); - assert!(ErrorStack::get().errors().is_empty()); - } - - #[test] - fn test_verify_recover() { - let key = Rsa::generate(2048).unwrap(); - let key = PKey::from_rsa(key).unwrap(); - - let digest = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - ]; - - let mut ctx = PkeyCtx::new(&key).unwrap(); - ctx.sign_init().unwrap(); - ctx.set_rsa_padding(Padding::PKCS1).unwrap(); - ctx.set_signature_md(Md::sha256()).unwrap(); - let mut signature = vec![]; - ctx.sign_to_vec(&digest, &mut signature).unwrap(); - - // Attempt recovery of just the digest. - let mut ctx = PkeyCtx::new(&key).unwrap(); - ctx.verify_recover_init().unwrap(); - ctx.set_rsa_padding(Padding::PKCS1).unwrap(); - ctx.set_signature_md(Md::sha256()).unwrap(); - let length = ctx.verify_recover(&signature, None).unwrap(); - let mut result_buf = vec![0; length]; - let length = ctx - .verify_recover(&signature, Some(&mut result_buf)) - .unwrap(); - assert_eq!(length, digest.len()); - // result_buf contains the digest - assert_eq!(result_buf[..length], digest); - - // Attempt recovery of the entire DigestInfo - let mut ctx = PkeyCtx::new(&key).unwrap(); - ctx.verify_recover_init().unwrap(); - ctx.set_rsa_padding(Padding::PKCS1).unwrap(); - let length = ctx.verify_recover(&signature, None).unwrap(); - let mut result_buf = vec![0; length]; - let length = ctx - .verify_recover(&signature, Some(&mut result_buf)) - .unwrap(); - // 32-bytes of SHA256 digest + the ASN.1 DigestInfo structure == 51 bytes - assert_eq!(length, 51); - // The digest is the end of the DigestInfo structure. - assert_eq!(result_buf[length - digest.len()..length], digest); - } - - #[test] - #[cfg(ossl320)] - fn set_nonce_type() { - let key1 = - EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap(); - let key1 = PKey::from_ec_key(key1).unwrap(); - - let mut ctx = PkeyCtx::new(&key1).unwrap(); - ctx.sign_init().unwrap(); - ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap(); - let nonce_type = ctx.nonce_type().unwrap(); - assert_eq!(nonce_type, NonceType::DETERMINISTIC_K); - assert!(ErrorStack::get().errors().is_empty()); - } - - // Test vector from - // https://github.com/openssl/openssl/blob/openssl-3.2.0/test/recipes/30-test_evp_data/evppkey_ecdsa_rfc6979.txt - #[test] - #[cfg(ossl320)] - fn ecdsa_deterministic_signature() { - let private_key_pem = "-----BEGIN PRIVATE KEY----- -MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCDJr6nYRbp1FmtcIVdnsdaTTlDD2zbo -mxJ7imIrEg9nIQ== ------END PRIVATE KEY-----"; - - let key1 = EcKey::private_key_from_pem(private_key_pem.as_bytes()).unwrap(); - let key1 = PKey::from_ec_key(key1).unwrap(); - let input = "sample"; - let expected_output = hex::decode("3046022100EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716022100F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8").unwrap(); - - let hashed_input = hash(MessageDigest::sha256(), input.as_bytes()).unwrap(); - let mut ctx = PkeyCtx::new(&key1).unwrap(); - ctx.sign_init().unwrap(); - ctx.set_signature_md(Md::sha256()).unwrap(); - ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap(); - - let mut output = vec![]; - ctx.sign_to_vec(&hashed_input, &mut output).unwrap(); - assert_eq!(output, expected_output); - assert!(ErrorStack::get().errors().is_empty()); - } -} diff --git a/patch/openssl/src/provider.rs b/patch/openssl/src/provider.rs deleted file mode 100644 index 01b5820af5fca..0000000000000 --- a/patch/openssl/src/provider.rs +++ /dev/null @@ -1,81 +0,0 @@ -use crate::error::ErrorStack; -use crate::lib_ctx::LibCtxRef; -use crate::{cvt, cvt_p}; -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 { - 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 { - 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 _, - ))?; - - // OSSL_PROVIDER_try_load seems to leave errors on the stack, even - // when it succeeds. - let _ = ErrorStack::get(); - - Ok(Provider::from_ptr(p)) - } - } - - /// Specifies the default search path that is to be used for looking for providers in the specified library context. - /// If left unspecified, an environment variable and a fall back default value will be used instead - /// - /// If `ctx` is `None`, the provider will be loaded into the default library context. - #[corresponds(OSSL_PROVIDER_set_default_search_path)] - pub fn set_default_search_path(ctx: Option<&LibCtxRef>, path: &str) -> Result<(), ErrorStack> { - let path = CString::new(path).unwrap(); - unsafe { - cvt(ffi::OSSL_PROVIDER_set_default_search_path( - ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr), - path.as_ptr(), - )) - .map(|_| ()) - } - } -} diff --git a/patch/openssl/src/rand.rs b/patch/openssl/src/rand.rs deleted file mode 100644 index fe8423b99a35f..0000000000000 --- a/patch/openssl/src/rand.rs +++ /dev/null @@ -1,90 +0,0 @@ -//! 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::error::ErrorStack; -use crate::{cvt, LenType}; -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 as usize); - cvt(ffi::RAND_bytes(buf.as_mut_ptr(), buf.len() as LenType)).map(|_| ()) - } -} - -/// Fill buffer with cryptographically strong pseudo-random bytes. It is -/// intended to be used for generating values that should remain private. -/// -/// # Examples -/// -/// To generate a buffer with cryptographically strong random bytes: -/// -/// ``` -/// use openssl::rand::rand_priv_bytes; -/// -/// let mut buf = [0; 256]; -/// rand_priv_bytes(&mut buf).unwrap(); -/// ``` -/// -/// Requires OpenSSL 1.1.1 or newer. -#[corresponds(RAND_priv_bytes)] -#[cfg(ossl111)] -pub fn rand_priv_bytes(buf: &mut [u8]) -> Result<(), ErrorStack> { - unsafe { - ffi::init(); - assert!(buf.len() <= c_int::MAX as usize); - cvt(ffi::RAND_priv_bytes(buf.as_mut_ptr(), buf.len() as LenType)).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 LenType); - } -} - -#[cfg(test)] -mod tests { - #[test] - fn test_rand_bytes() { - let mut buf = [0; 32]; - super::rand_bytes(&mut buf).unwrap(); - } - - #[test] - #[cfg(ossl111)] - fn test_rand_priv_bytes() { - let mut buf = [0; 32]; - super::rand_priv_bytes(&mut buf).unwrap(); - } -} diff --git a/patch/openssl/src/rsa.rs b/patch/openssl/src/rsa.rs deleted file mode 100644 index 5a5f4ba00899c..0000000000000 --- a/patch/openssl/src/rsa.rs +++ /dev/null @@ -1,873 +0,0 @@ -//! Rivest–Shamir–Adleman cryptosystem -//! -//! RSA is one of the earliest asymmetric public key encryption schemes. -//! Like many other cryptosystems, RSA relies on the presumed difficulty of a hard -//! mathematical problem, namely factorization of the product of two large prime -//! numbers. At the moment there does not exist an algorithm that can factor such -//! large numbers in reasonable time. RSA is used in a wide variety of -//! applications including digital signatures and key exchanges such as -//! establishing a TLS/SSL connection. -//! -//! The RSA acronym is derived from the first letters of the surnames of the -//! algorithm's founding trio. -//! -//! # Example -//! -//! Generate a 2048-bit RSA key pair and use the public key to encrypt some data. -//! -//! ```rust -//! use openssl::rsa::{Rsa, Padding}; -//! -//! let rsa = Rsa::generate(2048).unwrap(); -//! let data = b"foobar"; -//! let mut buf = vec![0; rsa.size() as usize]; -//! let encrypted_len = rsa.public_encrypt(data, &mut buf, Padding::PKCS1).unwrap(); -//! ``` -use cfg_if::cfg_if; -use foreign_types::{ForeignType, ForeignTypeRef}; -use libc::c_int; -use std::fmt; -use std::mem; -use std::ptr; - -use crate::bn::{BigNum, BigNumRef}; -use crate::error::ErrorStack; -use crate::pkey::{HasPrivate, HasPublic, Private, Public}; -use crate::util::ForeignTypeRefExt; -use crate::{cvt, cvt_n, cvt_p, LenType}; -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; - - /// Reference to `RSA` - pub struct RsaRef; -} - -impl Clone for Rsa { - fn clone(&self) -> Rsa { - (**self).to_owned() - } -} - -impl ToOwned for RsaRef { - type Owned = Rsa; - - fn to_owned(&self) -> Rsa { - unsafe { - ffi::RSA_up_ref(self.as_ptr()); - Rsa::from_ptr(self.as_ptr()) - } - } -} - -impl RsaRef -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 { - assert!(from.len() <= i32::MAX as usize); - assert!(to.len() >= self.size() as usize); - - unsafe { - let len = cvt_n(ffi::RSA_private_decrypt( - from.len() as LenType, - 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 { - assert!(from.len() <= i32::MAX as usize); - assert!(to.len() >= self.size() as usize); - - unsafe { - let len = cvt_n(ffi::RSA_private_encrypt( - from.len() as LenType, - 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 { - unsafe { - let result = ffi::RSA_check_key(self.as_ptr()); - if result != 1 { - let errors = ErrorStack::get(); - if errors.errors().is_empty() { - Ok(false) - } else { - Err(errors) - } - } else { - Ok(true) - } - } - } -} - -impl RsaRef -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 { - assert!(from.len() <= i32::MAX as usize); - assert!(to.len() >= self.size() as usize); - - unsafe { - let len = cvt_n(ffi::RSA_public_decrypt( - from.len() as LenType, - 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 { - assert!(from.len() <= i32::MAX as usize); - assert!(to.len() >= self.size() as usize); - - unsafe { - let len = cvt_n(ffi::RSA_public_encrypt( - from.len() as LenType, - 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 { - /// 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://docs.openssl.org/master/man3/RSA_new/ - /// [`RSA_set0_key`]: https://docs.openssl.org/master/man3/RSA_set0_key/ - pub fn from_public_components(n: BigNum, e: BigNum) -> Result, 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, - 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, - 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, - ffi::d2i_RSA_PUBKEY - } - - from_der! { - /// Decodes a DER-encoded PKCS#1 RSAPublicKey structure. - #[corresponds(d2i_RSAPublicKey)] - public_key_from_der_pkcs1, - Rsa, - ffi::d2i_RSAPublicKey - } -} - -pub struct RsaPrivateKeyBuilder { - rsa: Rsa, -} - -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://docs.openssl.org/master/man3/RSA_new/ - /// [`RSA_set0_key`]: https://docs.openssl.org/master/man3/RSA_set0_key/ - pub fn new(n: BigNum, e: BigNum, d: BigNum) -> Result { - 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 { - 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 { - 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 { - self.rsa - } -} - -impl Rsa { - /// Creates a new RSA key with private components (public components are assumed). - /// - /// This a convenience method over: - /// ``` - /// # use openssl::rsa::RsaPrivateKeyBuilder; - /// # fn main() -> Result<(), Box> { - /// # let bn = || openssl::bn::BigNum::new().unwrap(); - /// # let (n, e, d, p, q, dmp1, dmq1, iqmp) = (bn(), bn(), bn(), bn(), bn(), bn(), bn(), bn()); - /// RsaPrivateKeyBuilder::new(n, e, d)? - /// .set_factors(p, q)? - /// .set_crt_params(dmp1, dmq1, iqmp)? - /// .build(); - /// # Ok(()) } - /// ``` - #[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, 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, 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, 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, - ffi::PEM_read_bio_RSAPrivateKey - } - - from_der! { - /// Decodes a DER-encoded PKCS#1 RSAPrivateKey structure. - #[corresponds(d2i_RSAPrivateKey)] - private_key_from_der, - Rsa, - ffi::d2i_RSAPrivateKey - } -} - -impl fmt::Debug for Rsa { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Rsa") - } -} - -cfg_if! { - if #[cfg(any(ossl110, libressl, boringssl, awslc))] { - 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(); - } - - #[test] - fn test_check_key() { - let k = Rsa::private_key_from_pem_passphrase( - include_bytes!("../test/rsa-encrypted.pem"), - b"mypass", - ) - .unwrap(); - assert!(matches!(k.check_key(), Ok(true))); - assert!(ErrorStack::get().errors().is_empty()); - - // BoringSSL simply rejects this key, because its corrupted! - if let Ok(k) = Rsa::private_key_from_pem(include_bytes!("../test/corrupted-rsa.pem")) { - assert!(matches!(k.check_key(), Ok(false) | Err(_))); - assert!(ErrorStack::get().errors().is_empty()); - } - } -} diff --git a/patch/openssl/src/sha.rs b/patch/openssl/src/sha.rs deleted file mode 100644 index 24128904a3404..0000000000000 --- a/patch/openssl/src/sha.rs +++ /dev/null @@ -1,463 +0,0 @@ -//! 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(SHA224)] -#[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); - } -} diff --git a/patch/openssl/src/sign.rs b/patch/openssl/src/sign.rs deleted file mode 100644 index 51e6e11695ba5..0000000000000 --- a/patch/openssl/src/sign.rs +++ /dev/null @@ -1,824 +0,0 @@ -//! 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()); -//! ``` - -#![cfg_attr( - not(any(boringssl, awslc)), - doc = r#"\ - -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}; -use openssl_macros::corresponds; - -cfg_if! { - if #[cfg(any(ossl110, libressl382))] { - 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`. - pub(crate) 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 Sync for Signer<'_> {} -unsafe impl Send for Signer<'_> {} - -impl Drop for Signer<'_> { - 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 Signer<'_> { - /// Creates a new `Signer`. - /// - /// This cannot be used with Ed25519 or Ed448 keys. Please refer to - /// `new_without_digest`. - #[corresponds(EVP_DigestSignInit)] - pub fn new<'a, T>(type_: MessageDigest, pkey: &PKeyRef) -> Result, 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. - #[corresponds(EVP_DigestSignInit)] - pub fn new_without_digest<'a, T>(pkey: &PKeyRef) -> Result, ErrorStack> - where - T: HasPrivate, - { - Self::new_intern(None, pkey) - } - - fn new_intern<'a, T>( - type_: Option, - pkey: &PKeyRef, - ) -> Result, 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. - #[corresponds(EVP_PKEY_CTX_get_rsa_padding)] - pub fn rsa_padding(&self) -> Result { - 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. - #[corresponds(EVP_PKEY_CTX_set_rsa_padding)] - 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. - #[corresponds(EVP_PKEY_CTX_set_rsa_pss_saltlen)] - 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. - #[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)] - 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. - #[corresponds(EVP_DigestUpdate)] - 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. - #[corresponds(EVP_DigestSignFinal)] - pub fn len(&self) -> Result { - self.len_intern() - } - - #[cfg(not(any(ossl111, boringssl, libressl370, awslc)))] - fn len_intern(&self) -> Result { - unsafe { - let mut len = 0; - cvt(ffi::EVP_DigestSignFinal( - self.md_ctx, - ptr::null_mut(), - &mut len, - ))?; - Ok(len) - } - } - - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - fn len_intern(&self) -> Result { - 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. - #[corresponds(EVP_DigestSignFinal)] - pub fn sign(&self, buf: &mut [u8]) -> Result { - 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, 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. - #[corresponds(EVP_DigestSign)] - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - pub fn sign_oneshot( - &mut self, - sig_buf: &mut [u8], - data_buf: &[u8], - ) -> Result { - 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(any(ossl111, boringssl, libressl370, awslc))] - pub fn sign_oneshot_to_vec(&mut self, data_buf: &[u8]) -> Result, 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 Write for Signer<'_> { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.update(buf)?; - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -/// A type which can be used to verify the integrity and authenticity -/// of data given the signature. -pub struct Verifier<'a> { - md_ctx: *mut ffi::EVP_MD_CTX, - pctx: *mut ffi::EVP_PKEY_CTX, - pkey_pd: PhantomData<&'a ()>, -} - -unsafe impl Sync for Verifier<'_> {} -unsafe impl Send for Verifier<'_> {} - -impl Drop for Verifier<'_> { - 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 - /// [`Verifier::new_without_digest`]. - #[corresponds(EVP_DigestVerifyInit)] - pub fn new(type_: MessageDigest, pkey: &'a PKeyRef) -> Result, 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. - #[corresponds(EVP_DigestVerifyInit)] - pub fn new_without_digest(pkey: &'a PKeyRef) -> Result, ErrorStack> - where - T: HasPublic, - { - Verifier::new_intern(None, pkey) - } - - fn new_intern( - type_: Option, - pkey: &'a PKeyRef, - ) -> Result, 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. - #[corresponds(EVP_PKEY_CTX_get_rsa_padding)] - pub fn rsa_padding(&self) -> Result { - 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. - #[corresponds(EVP_PKEY_CTX_set_rsa_padding)] - 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. - #[corresponds(EVP_PKEY_CTX_set_rsa_pss_saltlen)] - 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. - #[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)] - 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 [`Verifier::verify_oneshot`] instead. - #[corresponds(EVP_DigestUpdate)] - 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. - #[corresponds(EVP_DigestVerifyFinal)] - pub fn verify(&self, signature: &[u8]) -> Result { - unsafe { - let r = ffi::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. - #[corresponds(EVP_DigestVerify)] - #[cfg(any(ossl111, boringssl, libressl370, awslc))] - pub fn verify_oneshot(&mut self, signature: &[u8], buf: &[u8]) -> Result { - 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 Write for Verifier<'_> { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.update(buf)?; - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -#[cfg(test)] -mod test { - use hex::{self, FromHex}; - #[cfg(not(boringssl))] - 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(any(ossl111, awslc))] - 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()); - } - - #[cfg(not(boringssl))] - fn test_hmac(ty: MessageDigest, tests: &[(Vec, Vec, Vec)]) { - for (key, data, 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] - #[cfg(not(boringssl))] - fn hmac_md5() { - // test vectors from RFC 2202 - let tests: [(Vec, Vec, Vec); 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] - #[cfg(not(boringssl))] - fn hmac_sha1() { - // test vectors from RFC 2202 - let tests: [(Vec, Vec, Vec); 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(any(ossl111, boringssl, libressl370, awslc))] - 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(any(ossl111, awslc))] - 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()); - } -} diff --git a/patch/openssl/src/srtp.rs b/patch/openssl/src/srtp.rs deleted file mode 100644 index 44ef4346590c3..0000000000000 --- a/patch/openssl/src/srtp.rs +++ /dev/null @@ -1,66 +0,0 @@ -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 as c_ulong); - pub const SRTP_AES128_CM_SHA1_32: SrtpProfileId = - SrtpProfileId(ffi::SRTP_AES128_CM_SHA1_32 as c_ulong); - pub const SRTP_AES128_F8_SHA1_80: SrtpProfileId = - SrtpProfileId(ffi::SRTP_AES128_F8_SHA1_80 as c_ulong); - pub const SRTP_AES128_F8_SHA1_32: SrtpProfileId = - SrtpProfileId(ffi::SRTP_AES128_F8_SHA1_32 as c_ulong); - pub const SRTP_NULL_SHA1_80: SrtpProfileId = SrtpProfileId(ffi::SRTP_NULL_SHA1_80 as c_ulong); - pub const SRTP_NULL_SHA1_32: SrtpProfileId = SrtpProfileId(ffi::SRTP_NULL_SHA1_32 as c_ulong); - #[cfg(any(boringssl, ossl110, awslc))] - pub const SRTP_AEAD_AES_128_GCM: SrtpProfileId = - SrtpProfileId(ffi::SRTP_AEAD_AES_128_GCM as c_ulong); - #[cfg(any(boringssl, ossl110, awslc))] - pub const SRTP_AEAD_AES_256_GCM: SrtpProfileId = - SrtpProfileId(ffi::SRTP_AEAD_AES_256_GCM as c_ulong); - - /// 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 - } -} diff --git a/patch/openssl/src/ssl/bio.rs b/patch/openssl/src/ssl/bio.rs deleted file mode 100644 index 4a0b1276ed1a6..0000000000000 --- a/patch/openssl/src/ssl/bio.rs +++ /dev/null @@ -1,308 +0,0 @@ -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 crate::error::ErrorStack; -use crate::{cvt_p, util}; - -pub struct StreamState { - pub stream: S, - pub error: Option, - pub panic: Option>, - pub dtls_mtu_size: c_long, -} - -/// Safe wrapper for `BIO_METHOD` -pub struct BioMethod(BIO_METHOD); - -impl BioMethod { - fn new() -> Result { - BIO_METHOD::new::().map(BioMethod) - } -} - -unsafe impl Sync for BioMethod {} -unsafe impl Send for BioMethod {} - -pub fn new(stream: S) -> Result<(*mut BIO, BioMethod), ErrorStack> { - let method = BioMethod::new::()?; - - 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(bio: *mut BIO) -> Option { - let state = state::(bio); - state.error.take() -} - -pub unsafe fn take_panic(bio: *mut BIO) -> Option> { - let state = state::(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); - &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(bio: *mut BIO, mtu_size: usize) { - if mtu_size as u64 > c_long::MAX as u64 { - panic!( - "Given MTU size {} can't be represented in a positive `c_long` range", - mtu_size - ) - } - state::(bio).dtls_mtu_size = mtu_size as c_long; -} - -unsafe fn state<'a, S: 'a>(bio: *mut BIO) -> &'a mut StreamState { - &mut *(BIO_get_data(bio) as *mut _) -} - -unsafe extern "C" fn bwrite(bio: *mut BIO, buf: *const c_char, len: c_int) -> c_int { - BIO_clear_retry_flags(bio); - - let state = state::(bio); - let buf = util::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(bio: *mut BIO, buf: *mut c_char, len: c_int) -> c_int { - BIO_clear_retry_flags(bio); - - let state = state::(bio); - let buf = util::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(bio: *mut BIO, s: *const c_char) -> c_int { - bwrite::(bio, s, strlen(s) as c_int) -} - -unsafe extern "C" fn ctrl( - bio: *mut BIO, - cmd: c_int, - _num: c_long, - _ptr: *mut c_void, -) -> c_long { - let state = state::(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(bio: *mut BIO) -> c_int { - if bio.is_null() { - return 0; - } - - let data = BIO_get_data(bio); - assert!(!data.is_null()); - let _ = Box::>::from_raw(data as *mut _); - BIO_set_data(bio, ptr::null_mut()); - BIO_set_init(bio, 0); - 1 -} - -cfg_if! { - if #[cfg(any(ossl110, libressl, boringssl))] { - 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() -> Result { - #[cfg(not(boringssl))] - use ffi::{ - BIO_meth_set_write__fixed_rust as BIO_meth_set_write, - BIO_meth_set_read__fixed_rust as BIO_meth_set_read, - BIO_meth_set_puts__fixed_rust as BIO_meth_set_puts, - BIO_meth_set_ctrl__fixed_rust as BIO_meth_set_ctrl, - BIO_meth_set_create__fixed_rust as BIO_meth_set_create, - BIO_meth_set_destroy__fixed_rust as BIO_meth_set_destroy, - }; - #[cfg(boringssl)] - use ffi::{ - BIO_meth_set_write, - BIO_meth_set_read, - BIO_meth_set_puts, - BIO_meth_set_ctrl, - BIO_meth_set_create, - BIO_meth_set_destroy, - }; - - 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(BIO_meth_set_write(method.0, Some(bwrite::)))?; - cvt(BIO_meth_set_read(method.0, Some(bread::)))?; - cvt(BIO_meth_set_puts(method.0, Some(bputs::)))?; - cvt(BIO_meth_set_ctrl(method.0, Some(ctrl::)))?; - cvt(BIO_meth_set_create(method.0, Some(create)))?; - cvt(BIO_meth_set_destroy(method.0, Some(destroy::)))?; - 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() -> Result { - let ptr = Box::new(ffi::BIO_METHOD { - type_: ffi::BIO_TYPE_NONE, - name: b"rust\0".as_ptr() as *const _, - bwrite: Some(bwrite::), - bread: Some(bread::), - bputs: Some(bputs::), - bgets: None, - ctrl: Some(ctrl::), - create: Some(create), - destroy: Some(destroy::), - 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 { - let _ = Box::::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; - } - } -} diff --git a/patch/openssl/src/ssl/callbacks.rs b/patch/openssl/src/ssl/callbacks.rs deleted file mode 100644 index 48ee98749bcd9..0000000000000 --- a/patch/openssl/src/ssl/callbacks.rs +++ /dev/null @@ -1,705 +0,0 @@ -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; -#[cfg(any(ossl111, boringssl, awslc))] -use std::str; -use std::sync::Arc; - -use crate::dh::Dh; -#[cfg(all(ossl102, not(ossl110)))] -use crate::ec::EcKey; -use crate::error::ErrorStack; -use crate::pkey::Params; -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}; -use crate::util; -#[cfg(any(ossl111, boringssl, awslc))] -use crate::util::ForeignTypeRefExt; -#[cfg(ossl111)] -use crate::x509::X509Ref; -use crate::x509::{X509StoreContext, X509StoreContextRef}; - -pub extern "C" fn raw_verify(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::(); - - // 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( - 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 - + 'static - + Sync - + Send, -{ - unsafe { - let ssl = SslRef::from_ptr_mut(ssl); - let callback_idx = SslContext::cached_ex_index::(); - - 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 = util::from_raw_parts_mut(identity as *mut u8, max_identity_len as usize); - #[allow(clippy::unnecessary_cast)] - let psk_sl = util::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( - 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 - + 'static - + Sync - + Send, -{ - unsafe { - let ssl = SslRef::from_ptr_mut(ssl); - let callback_idx = SslContext::cached_ex_index::(); - - 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. - #[allow(clippy::unnecessary_cast)] - let psk_sl = util::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( - 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::>(); - - 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(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, - } - } -} - -pub extern "C" fn raw_alpn_select( - 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::()) - .expect("BUG: alpn callback missing") as *const F; - #[allow(clippy::unnecessary_cast)] - let protos = util::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( - ssl: *mut ffi::SSL, - is_export: c_int, - keylength: c_int, -) -> *mut ffi::DH -where - F: Fn(&mut SslRef, bool, u32) -> Result, ErrorStack> + 'static + Sync + Send, -{ - let ssl = SslRef::from_ptr_mut(ssl); - let callback = ssl - .ssl_context() - .ex_data(SslContext::cached_ex_index::()) - .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(ossl102, not(ossl110)))] -pub unsafe extern "C" fn raw_tmp_ecdh( - ssl: *mut ffi::SSL, - is_export: c_int, - keylength: c_int, -) -> *mut ffi::EC_KEY -where - F: Fn(&mut SslRef, bool, u32) -> Result, ErrorStack> + 'static + Sync + Send, -{ - let ssl = SslRef::from_ptr_mut(ssl); - let callback = ssl - .ssl_context() - .ex_data(SslContext::cached_ex_index::()) - .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( - ssl: *mut ffi::SSL, - is_export: c_int, - keylength: c_int, -) -> *mut ffi::DH -where - F: Fn(&mut SslRef, bool, u32) -> Result, ErrorStack> + 'static + Sync + Send, -{ - let ssl = SslRef::from_ptr_mut(ssl); - let callback = ssl - .ex_data(Ssl::cached_ex_index::>()) - .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(ossl102, not(ossl110)))] -pub unsafe extern "C" fn raw_tmp_ecdh_ssl( - ssl: *mut ffi::SSL, - is_export: c_int, - keylength: c_int, -) -> *mut ffi::EC_KEY -where - F: Fn(&mut SslRef, bool, u32) -> Result, ErrorStack> + 'static + Sync + Send, -{ - let ssl = SslRef::from_ptr_mut(ssl); - let callback = ssl - .ex_data(Ssl::cached_ex_index::>()) - .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(ssl: *mut ffi::SSL, _: *mut c_void) -> c_int -where - F: Fn(&mut SslRef) -> Result + 'static + Sync + Send, -{ - let ssl = SslRef::from_ptr_mut(ssl); - let callback = ssl - .ssl_context() - .ex_data(SslContext::cached_ex_index::()) - .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( - 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::()) - .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( - 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::()) - .expect("BUG: remove session callback missing"); - let session = SslSessionRef::from_ptr(session); - - callback(ctx, session) -} - -cfg_if! { - if #[cfg(any(ossl110, libressl, boringssl, awslc))] { - type DataPtr = *const c_uchar; - } else { - type DataPtr = *mut c_uchar; - } -} - -pub unsafe extern "C" fn raw_get_session( - ssl: *mut ffi::SSL, - data: DataPtr, - len: c_int, - copy: *mut c_int, -) -> *mut ffi::SSL_SESSION -where - F: Fn(&mut SslRef, &[u8]) -> Option + '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::()) - .expect("BUG: get session callback missing") as *const F; - #[allow(clippy::unnecessary_cast)] - let data = util::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(any(ossl111, boringssl, awslc))] -pub unsafe extern "C" fn raw_keylog(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::()) - .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( - ssl: *mut ffi::SSL, - cookie: *mut c_uchar, - cookie_len: *mut size_t, -) -> c_int -where - F: Fn(&mut SslRef, &mut [u8]) -> Result + 'static + Sync + Send, -{ - let ssl = SslRef::from_ptr_mut(ssl); - let callback = ssl - .ssl_context() - .ex_data(SslContext::cached_ex_index::()) - .expect("BUG: stateless cookie generate callback missing") as *const F; - #[allow(clippy::unnecessary_cast)] - let slice = util::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( - 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::()) - .expect("BUG: stateless cookie verify callback missing") as *const F; - #[allow(clippy::unnecessary_cast)] - let slice = util::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len); - (*callback)(ssl, slice) as c_int -} - -#[cfg(not(any(boringssl, awslc)))] -pub extern "C" fn raw_cookie_generate( - ssl: *mut ffi::SSL, - cookie: *mut c_uchar, - cookie_len: *mut c_uint, -) -> c_int -where - F: Fn(&mut SslRef, &mut [u8]) -> Result + 'static + Sync + Send, -{ - unsafe { - let ssl = SslRef::from_ptr_mut(ssl); - let callback = ssl - .ssl_context() - .ex_data(SslContext::cached_ex_index::()) - .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. - #[allow(clippy::unnecessary_cast)] - let slice = - util::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(not(any(boringssl, awslc)))] -cfg_if! { - if #[cfg(any(ossl110, libressl))] { - type CookiePtr = *const c_uchar; - } else { - type CookiePtr = *mut c_uchar; - } -} - -#[cfg(not(any(boringssl, awslc)))] -pub extern "C" fn raw_cookie_verify( - 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::()) - .expect("BUG: cookie verify callback missing") as *const F; - #[allow(clippy::unnecessary_cast)] - let slice = - util::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(Option); - -#[cfg(ossl111)] -pub extern "C" fn raw_custom_ext_add( - 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, 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::()) - .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::>(); - 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( - 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::>(); - if let Some(state) = ssl.ex_data_mut(idx) { - state.0 = None; - } - } -} - -#[cfg(ossl111)] -pub extern "C" fn raw_custom_ext_parse( - 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::()) - .expect("BUG: custom ext parse callback missing") as *const F; - let ectx = ExtensionContext::from_bits_truncate(context); - #[allow(clippy::unnecessary_cast)] - let slice = util::from_raw_parts(input as *const u8, inlen); - 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( - ssl: *mut ffi::SSL, - al: *mut c_int, - arg: *mut c_void, -) -> c_int -where - F: Fn(&mut SslRef, &mut SslAlert) -> Result - + '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 - } - } -} diff --git a/patch/openssl/src/ssl/connector.rs b/patch/openssl/src/ssl/connector.rs deleted file mode 100644 index 14aadfe3e2569..0000000000000 --- a/patch/openssl/src/ssl/connector.rs +++ /dev/null @@ -1,409 +0,0 @@ -use cfg_if::cfg_if; -use std::io::{Read, Write}; -use std::ops::{Deref, DerefMut}; - -use crate::dh::Dh; -use crate::error::ErrorStack; -#[cfg(any(ossl111, libressl))] -use crate::ssl::SslVersion; -use crate::ssl::{ - HandshakeError, Ssl, SslContext, SslContextBuilder, SslContextRef, SslMethod, SslMode, - SslOptions, SslRef, SslStream, SslVerifyMode, -}; -use crate::version; -use std::net::IpAddr; -use super::error::ErrorEx; - -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 { - let mut ctx = SslContextBuilder::new(method)?; - - cfg_if! { - if #[cfg(not(any(boringssl, awslc)))] { - 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. -#[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 { - 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(&self, domain: &str, stream: S) -> Result, HandshakeError> - 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 { - 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 (if it is not an IP address) and hostname verification if enabled. - pub fn into_ssl(mut self, domain: &str) -> Result { - if self.sni && domain.parse::().is_err() { - 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(self, domain: &str, stream: S) -> Result, HandshakeError> - 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 { - 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(any(ossl111, libressl))] - 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 or LibreSSL. - /// - /// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS - #[cfg(any(ossl111, libressl))] - pub fn mozilla_modern_v5(method: SslMethod) -> Result { - let mut ctx = ctx(method)?; - ctx.set_min_proto_version(Some(SslVersion::TLS1_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 { - let mut ctx = ctx(method)?; - ctx.set_options(SslOptions::CIPHER_SERVER_PREFERENCE); - #[cfg(any(ossl111, libressl))] - 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 { - let mut ctx = ctx(method)?; - ctx.set_options( - SslOptions::CIPHER_SERVER_PREFERENCE | SslOptions::NO_TLSV1 | SslOptions::NO_TLSV1_1, - ); - #[cfg(any(ossl111, libressl))] - 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)) - } - - /// Creates a new builder configured with a minimum supported TLS version and a set of ciphersuites - /// - pub fn custom(method: SslMethod, min_tls_version: &Option, ciphersuites: &Option) -> Result { - let mut ctx = ctx(method).map_err(|e| ErrorEx::OpenSslError { error_stack: e })?; - let dh = Dh::params_from_pem(FFDHE_2048.as_bytes()).map_err(|e| ErrorEx::OpenSslError { error_stack: e })?; - ctx.set_tmp_dh(&dh).map_err(|e| ErrorEx::OpenSslError { error_stack: e })?; - setup_curves(&mut ctx).map_err(|e| ErrorEx::OpenSslError { error_stack: e })?; - ctx.set_min_tls_version_and_ciphersuites(min_tls_version, ciphersuites)?; - Ok(SslAcceptorBuilder(ctx)) - } - - /// Initiates a server-side TLS session on a stream. - pub fn accept(&self, stream: S) -> Result, HandshakeError> - 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) - } - } -} - -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), - } -} diff --git a/patch/openssl/src/ssl/error.rs b/patch/openssl/src/ssl/error.rs deleted file mode 100644 index ede4e371df166..0000000000000 --- a/patch/openssl/src/ssl/error.rs +++ /dev/null @@ -1,205 +0,0 @@ -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, -} - -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 { - 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 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 { - /// Setup failed. - SetupFailure(ErrorStack), - /// The handshake failed. - Failure(MidHandshakeSslStream), - /// The handshake encountered a `WouldBlock` error midway through. - /// - /// This error will never be returned for blocking streams. - WouldBlock(MidHandshakeSslStream), -} - -impl StdError for HandshakeError { - 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 fmt::Display for HandshakeError { - 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 From for HandshakeError { - fn from(e: ErrorStack) -> HandshakeError { - HandshakeError::SetupFailure(e) - } -} - -#[derive(Debug)] -pub enum ErrorEx { - OpenSslError { - error_stack: ErrorStack - }, - InvalidTlsVersion, - InvalidCiphersuite, -} - -impl PartialEq for ErrorEx { - fn eq(&self, other: &ErrorEx) -> bool { - match (self, other) { - (ErrorEx::OpenSslError{..}, ErrorEx::OpenSslError{..}) - | (ErrorEx::InvalidTlsVersion, ErrorEx::InvalidTlsVersion) - | (ErrorEx::InvalidCiphersuite, ErrorEx::InvalidCiphersuite) => true, - _ => false, - } - } -} diff --git a/patch/openssl/src/ssl/mod.rs b/patch/openssl/src/ssl/mod.rs deleted file mode 100644 index 419847da342ab..0000000000000 --- a/patch/openssl/src/ssl/mod.rs +++ /dev/null @@ -1,4406 +0,0 @@ -//! SSL/TLS support. -//! -//! `SslConnector` and `SslAcceptor` should be used in most cases - they handle -//! configuration of the OpenSSL primitives for you. -//! -//! # Examples -//! -//! To connect as a client to a remote server: -//! -//! ```no_run -//! use openssl::ssl::{SslMethod, SslConnector}; -//! use std::io::{Read, Write}; -//! use std::net::TcpStream; -//! -//! let connector = SslConnector::builder(SslMethod::tls()).unwrap().build(); -//! -//! let stream = TcpStream::connect("google.com:443").unwrap(); -//! let mut stream = connector.connect("google.com", stream).unwrap(); -//! -//! stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap(); -//! let mut res = vec![]; -//! stream.read_to_end(&mut res).unwrap(); -//! println!("{}", String::from_utf8_lossy(&res)); -//! ``` -//! -//! To accept connections as a server from remote clients: -//! -//! ```no_run -//! use openssl::ssl::{SslMethod, SslAcceptor, SslStream, SslFiletype}; -//! use std::net::{TcpListener, TcpStream}; -//! use std::sync::Arc; -//! use std::thread; -//! -//! -//! let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); -//! acceptor.set_private_key_file("key.pem", SslFiletype::PEM).unwrap(); -//! acceptor.set_certificate_chain_file("certs.pem").unwrap(); -//! acceptor.check_private_key().unwrap(); -//! let acceptor = Arc::new(acceptor.build()); -//! -//! let listener = TcpListener::bind("0.0.0.0:8443").unwrap(); -//! -//! fn handle_client(stream: SslStream) { -//! // ... -//! } -//! -//! for stream in listener.incoming() { -//! match stream { -//! Ok(stream) => { -//! let acceptor = acceptor.clone(); -//! thread::spawn(move || { -//! let stream = acceptor.accept(stream).unwrap(); -//! handle_client(stream); -//! }); -//! } -//! Err(e) => { /* connection failed */ } -//! } -//! } -//! ``` -#[cfg(ossl300)] -use crate::cvt_long; -use crate::dh::{Dh, DhRef}; -#[cfg(all(ossl102, not(ossl110)))] -use crate::ec::EcKey; -use crate::ec::EcKeyRef; -use crate::error::ErrorStack; -use crate::ex_data::Index; -#[cfg(ossl111)] -use crate::hash::MessageDigest; -#[cfg(any(ossl110, libressl))] -use crate::nid::Nid; -use crate::pkey::{HasPrivate, PKeyRef, Params, Private}; -#[cfg(ossl300)] -use crate::pkey::{PKey, Public}; -#[cfg(not(osslconf = "OPENSSL_NO_SRTP"))] -use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef}; -use crate::ssl::bio::BioMethod; -use crate::ssl::callbacks::*; -use crate::ssl::error::InnerError; -use crate::stack::{Stack, StackRef, Stackable}; -use crate::util; -use crate::util::{ForeignTypeExt, ForeignTypeRefExt}; -use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef}; -use crate::x509::verify::X509VerifyParamRef; -use crate::x509::{X509Name, X509Ref, X509StoreContextRef, X509VerifyResult, X509}; -use crate::{cvt, cvt_n, cvt_p, init}; -use bitflags::bitflags; -use cfg_if::cfg_if; -use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; -use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void}; -use once_cell::sync::{Lazy, OnceCell}; -use openssl_macros::corresponds; -use std::any::TypeId; -use std::collections::HashMap; -use std::ffi::{CStr, CString}; -use std::fmt; -use std::io; -use std::io::prelude::*; -use std::marker::PhantomData; -use std::mem::{self, ManuallyDrop, MaybeUninit}; -use std::ops::{Deref, DerefMut}; -use std::panic::resume_unwind; -use std::path::Path; -use std::ptr; -use std::str; -use std::sync::{Arc, Mutex}; - -pub use crate::ssl::connector::{ - ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder, -}; -pub use crate::ssl::error::{Error, ErrorCode, HandshakeError, ErrorEx}; - -mod bio; -mod callbacks; -mod connector; -mod error; -#[cfg(test)] -mod test; - -/// Returns the OpenSSL name of a cipher corresponding to an RFC-standard cipher name. -/// -/// If the cipher has no corresponding OpenSSL name, the string `(NONE)` is returned. -/// -/// Requires OpenSSL 1.1.1 or newer. -#[corresponds(OPENSSL_cipher_name)] -#[cfg(ossl111)] -pub fn cipher_name(std_name: &str) -> &'static str { - unsafe { - ffi::init(); - - let s = CString::new(std_name).unwrap(); - let ptr = ffi::OPENSSL_cipher_name(s.as_ptr()); - CStr::from_ptr(ptr).to_str().unwrap() - } -} - -cfg_if! { - if #[cfg(ossl300)] { - type SslOptionsRepr = u64; - } else if #[cfg(any(boringssl, awslc))] { - type SslOptionsRepr = u32; - } else { - type SslOptionsRepr = libc::c_ulong; - } -} - -bitflags! { - /// Options controlling the behavior of an `SslContext`. - #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - #[repr(transparent)] - pub struct SslOptions: SslOptionsRepr { - /// Disables a countermeasure against an SSLv3/TLSv1.0 vulnerability affecting CBC ciphers. - const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr; - - /// A "reasonable default" set of options which enables compatibility flags. - #[cfg(not(any(boringssl, awslc)))] - const ALL = ffi::SSL_OP_ALL as SslOptionsRepr; - - /// Do not query the MTU. - /// - /// Only affects DTLS connections. - const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr; - - /// Enables Cookie Exchange as described in [RFC 4347 Section 4.2.1]. - /// - /// Only affects DTLS connections. - /// - /// [RFC 4347 Section 4.2.1]: https://tools.ietf.org/html/rfc4347#section-4.2.1 - #[cfg(not(any(boringssl, awslc)))] - const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr; - - /// Disables the use of session tickets for session resumption. - const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr; - - /// Always start a new session when performing a renegotiation on the server side. - #[cfg(not(any(boringssl, awslc)))] - const NO_SESSION_RESUMPTION_ON_RENEGOTIATION = - ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr; - - /// Disables the use of TLS compression. - #[cfg(not(any(boringssl, awslc)))] - const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr; - - /// Allow legacy insecure renegotiation with servers or clients that do not support secure - /// renegotiation. - const ALLOW_UNSAFE_LEGACY_RENEGOTIATION = - ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr; - - /// Creates a new key for each session when using ECDHE. - /// - /// This is always enabled in OpenSSL 1.1.0. - const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr; - - /// Creates a new key for each session when using DHE. - /// - /// This is always enabled in OpenSSL 1.1.0. - const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr; - - /// Use the server's preferences rather than the client's when selecting a cipher. - /// - /// This has no effect on the client side. - const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr; - - /// Disables version rollback attach detection. - const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr; - - /// Disables the use of SSLv2. - const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr; - - /// Disables the use of SSLv3. - const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr; - - /// Disables the use of TLSv1.0. - const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr; - - /// Disables the use of TLSv1.1. - const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr; - - /// Disables the use of TLSv1.2. - const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr; - - /// Disables the use of TLSv1.3. - /// - /// Requires AWS-LC or BoringSSL or OpenSSL 1.1.1 or newer or LibreSSL. - #[cfg(any(boringssl, ossl111, libressl, awslc))] - const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr; - - /// Disables the use of DTLSv1.0 - const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr; - - /// Disables the use of DTLSv1.2. - const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr; - - /// Disables the use of all (D)TLS protocol versions. - /// - /// This can be used as a mask when whitelisting protocol versions. - /// - /// Requires OpenSSL 1.0.2 or newer. - /// - /// # Examples - /// - /// Only support TLSv1.2: - /// - /// ```rust - /// use openssl::ssl::SslOptions; - /// - /// let options = SslOptions::NO_SSL_MASK & !SslOptions::NO_TLSV1_2; - /// ``` - #[cfg(ossl102)] - const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr; - - /// Disallow all renegotiation in TLSv1.2 and earlier. - /// - /// Requires OpenSSL 1.1.0h or newer. - #[cfg(any(boringssl, ossl110h, awslc))] - const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr; - - /// Enable TLSv1.3 Compatibility mode. - /// - /// Requires OpenSSL 1.1.1 or newer. This is on by default in 1.1.1, but a future version - /// may have this disabled by default. - #[cfg(ossl111)] - const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr; - - /// Prioritize ChaCha ciphers when preferred by clients. - /// - /// Temporarily reprioritize ChaCha20-Poly1305 ciphers to the top of the server cipher list - /// if a ChaCha20-Poly1305 cipher is at the top of the client cipher list. This helps those - /// clients (e.g. mobile) use ChaCha20-Poly1305 if that cipher is anywhere in the server - /// cipher list; but still allows other clients to use AES and other ciphers. - /// - /// Requires enable [`SslOptions::CIPHER_SERVER_PREFERENCE`]. - /// Requires OpenSSL 1.1.1 or newer. - /// - /// [`SslOptions::CIPHER_SERVER_PREFERENCE`]: struct.SslOptions.html#associatedconstant.CIPHER_SERVER_PREFERENCE - #[cfg(ossl111)] - const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr; - } -} - -bitflags! { - /// Options controlling the behavior of an `SslContext`. - #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - #[repr(transparent)] - pub struct SslMode: SslBitType { - /// Enables "short writes". - /// - /// Normally, a write in OpenSSL will always write out all of the requested data, even if it - /// requires more than one TLS record or write to the underlying stream. This option will - /// cause a write to return after writing a single TLS record instead. - const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE; - - /// Disables a check that the data buffer has not moved between calls when operating in a - /// non-blocking context. - const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; - - /// Enables automatic retries after TLS session events such as renegotiations or heartbeats. - /// - /// By default, OpenSSL will return a `WantRead` error after a renegotiation or heartbeat. - /// This option will cause OpenSSL to automatically continue processing the requested - /// operation instead. - /// - /// Note that `SslStream::read` and `SslStream::write` will automatically retry regardless - /// of the state of this option. It only affects `SslStream::ssl_read` and - /// `SslStream::ssl_write`. - const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY; - - /// Disables automatic chain building when verifying a peer's certificate. - /// - /// TLS peers are responsible for sending the entire certificate chain from the leaf to a - /// trusted root, but some will incorrectly not do so. OpenSSL will try to build the chain - /// out of certificates it knows of, and this option will disable that behavior. - const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN; - - /// Release memory buffers when the session does not need them. - /// - /// This saves ~34 KiB of memory for idle streams. - const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS; - - /// Sends the fake `TLS_FALLBACK_SCSV` cipher suite in the ClientHello message of a - /// handshake. - /// - /// This should only be enabled if a client has failed to connect to a server which - /// attempted to downgrade the protocol version of the session. - /// - /// Do not use this unless you know what you're doing! - #[cfg(not(libressl))] - const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV; - } -} - -/// A type specifying the kind of protocol an `SslContext` will speak. -#[derive(Copy, Clone)] -pub struct SslMethod(*const ffi::SSL_METHOD); - -impl SslMethod { - /// Support all versions of the TLS protocol. - #[corresponds(TLS_method)] - pub fn tls() -> SslMethod { - unsafe { SslMethod(TLS_method()) } - } - - /// Support all versions of the DTLS protocol. - #[corresponds(DTLS_method)] - pub fn dtls() -> SslMethod { - unsafe { SslMethod(DTLS_method()) } - } - - /// Support all versions of the TLS protocol, explicitly as a client. - #[corresponds(TLS_client_method)] - pub fn tls_client() -> SslMethod { - unsafe { SslMethod(TLS_client_method()) } - } - - /// Support all versions of the TLS protocol, explicitly as a server. - #[corresponds(TLS_server_method)] - pub fn tls_server() -> SslMethod { - unsafe { SslMethod(TLS_server_method()) } - } - - /// Support all versions of the DTLS protocol, explicitly as a client. - #[corresponds(DTLS_client_method)] - #[cfg(any(boringssl, ossl110, libressl, awslc))] - pub fn dtls_client() -> SslMethod { - unsafe { SslMethod(DTLS_client_method()) } - } - - /// Support all versions of the DTLS protocol, explicitly as a server. - #[corresponds(DTLS_server_method)] - #[cfg(any(boringssl, ossl110, libressl, awslc))] - pub fn dtls_server() -> SslMethod { - unsafe { SslMethod(DTLS_server_method()) } - } - - /// Constructs an `SslMethod` from a pointer to the underlying OpenSSL value. - /// - /// # Safety - /// - /// The caller must ensure the pointer is valid. - pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod { - SslMethod(ptr) - } - - /// Returns a pointer to the underlying OpenSSL value. - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn as_ptr(&self) -> *const ffi::SSL_METHOD { - self.0 - } -} - -unsafe impl Sync for SslMethod {} -unsafe impl Send for SslMethod {} - -bitflags! { - /// Options controlling the behavior of certificate verification. - #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - #[repr(transparent)] - pub struct SslVerifyMode: i32 { - /// Verifies that the peer's certificate is trusted. - /// - /// On the server side, this will cause OpenSSL to request a certificate from the client. - const PEER = ffi::SSL_VERIFY_PEER; - - /// Disables verification of the peer's certificate. - /// - /// On the server side, this will cause OpenSSL to not request a certificate from the - /// client. On the client side, the certificate will be checked for validity, but the - /// negotiation will continue regardless of the result of that check. - const NONE = ffi::SSL_VERIFY_NONE; - - /// On the server side, abort the handshake if the client did not send a certificate. - /// - /// This should be paired with `SSL_VERIFY_PEER`. It has no effect on the client side. - const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT; - } -} - -#[cfg(any(boringssl, awslc))] -type SslBitType = c_int; -#[cfg(not(any(boringssl, awslc)))] -type SslBitType = c_long; - -#[cfg(any(boringssl, awslc))] -type SslTimeTy = u64; -#[cfg(not(any(boringssl, awslc)))] -type SslTimeTy = c_long; - -bitflags! { - /// Options controlling the behavior of session caching. - #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - #[repr(transparent)] - pub struct SslSessionCacheMode: SslBitType { - /// No session caching for the client or server takes place. - const OFF = ffi::SSL_SESS_CACHE_OFF; - - /// Enable session caching on the client side. - /// - /// OpenSSL has no way of identifying the proper session to reuse automatically, so the - /// application is responsible for setting it explicitly via [`SslRef::set_session`]. - /// - /// [`SslRef::set_session`]: struct.SslRef.html#method.set_session - const CLIENT = ffi::SSL_SESS_CACHE_CLIENT; - - /// Enable session caching on the server side. - /// - /// This is the default mode. - const SERVER = ffi::SSL_SESS_CACHE_SERVER; - - /// Enable session caching on both the client and server side. - const BOTH = ffi::SSL_SESS_CACHE_BOTH; - - /// Disable automatic removal of expired sessions from the session cache. - const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR; - - /// Disable use of the internal session cache for session lookups. - const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP; - - /// Disable use of the internal session cache for session storage. - const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE; - - /// Disable use of the internal session cache for storage and lookup. - const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL; - } -} - -#[cfg(ossl111)] -bitflags! { - /// Which messages and under which conditions an extension should be added or expected. - #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - #[repr(transparent)] - pub struct ExtensionContext: c_uint { - /// This extension is only allowed in TLS - const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY; - /// This extension is only allowed in DTLS - const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY; - /// Some extensions may be allowed in DTLS but we don't implement them for it - const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY; - /// Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is - const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED; - /// Extension is only defined for TLS1.2 and below - const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY; - /// Extension is only defined for TLS1.3 and above - const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY; - /// Ignore this extension during parsing if we are resuming - const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION; - const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO; - /// Really means TLS1.2 or below - const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO; - const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO; - const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS; - const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST; - const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE; - const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET; - const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST; - } -} - -/// An identifier of the format of a certificate or key file. -#[derive(Copy, Clone)] -pub struct SslFiletype(c_int); - -impl SslFiletype { - /// The PEM format. - /// - /// This corresponds to `SSL_FILETYPE_PEM`. - pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM); - - /// The ASN1 format. - /// - /// This corresponds to `SSL_FILETYPE_ASN1`. - pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1); - - /// Constructs an `SslFiletype` from a raw OpenSSL value. - pub fn from_raw(raw: c_int) -> SslFiletype { - SslFiletype(raw) - } - - /// Returns the raw OpenSSL value represented by this type. - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn as_raw(&self) -> c_int { - self.0 - } -} - -/// An identifier of a certificate status type. -#[derive(Copy, Clone)] -pub struct StatusType(c_int); - -impl StatusType { - /// An OSCP status. - pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp); - - /// Constructs a `StatusType` from a raw OpenSSL value. - pub fn from_raw(raw: c_int) -> StatusType { - StatusType(raw) - } - - /// Returns the raw OpenSSL value represented by this type. - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn as_raw(&self) -> c_int { - self.0 - } -} - -/// An identifier of a session name type. -#[derive(Copy, Clone)] -pub struct NameType(c_int); - -impl NameType { - /// A host name. - pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name); - - /// Constructs a `StatusType` from a raw OpenSSL value. - pub fn from_raw(raw: c_int) -> StatusType { - StatusType(raw) - } - - /// Returns the raw OpenSSL value represented by this type. - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn as_raw(&self) -> c_int { - self.0 - } -} - -static INDEXES: Lazy>> = Lazy::new(|| Mutex::new(HashMap::new())); -static SSL_INDEXES: Lazy>> = Lazy::new(|| Mutex::new(HashMap::new())); -static SESSION_CTX_INDEX: OnceCell> = OnceCell::new(); - -fn try_get_session_ctx_index() -> Result<&'static Index, ErrorStack> { - SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index) -} - -unsafe extern "C" fn free_data_box( - _parent: *mut c_void, - ptr: *mut c_void, - _ad: *mut ffi::CRYPTO_EX_DATA, - _idx: c_int, - _argl: c_long, - _argp: *mut c_void, -) { - if !ptr.is_null() { - let _ = Box::::from_raw(ptr as *mut T); - } -} - -/// An error returned from the SNI callback. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct SniError(c_int); - -impl SniError { - /// Abort the handshake with a fatal alert. - pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL); - - /// Send a warning alert to the client and continue the handshake. - pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING); - - pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK); -} - -/// An SSL/TLS alert. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct SslAlert(c_int); - -impl SslAlert { - /// Alert 112 - `unrecognized_name`. - pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME); - pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER); - pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR); -} - -/// An error returned from an ALPN selection callback. -/// -/// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct AlpnError(c_int); - -impl AlpnError { - /// Terminate the handshake with a fatal alert. - /// - /// Requires AWS-LC or BoringSSL or OpenSSL 1.1.0 or newer. - #[cfg(any(ossl110, libressl, boringssl, awslc))] - pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL); - - /// Do not select a protocol, but continue the handshake. - pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK); -} - -/// The result of a client hello callback. -/// -/// Requires OpenSSL 1.1.1 or newer. -#[cfg(ossl111)] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct ClientHelloResponse(c_int); - -#[cfg(ossl111)] -impl ClientHelloResponse { - /// Continue the handshake. - pub const SUCCESS: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_SUCCESS); - - /// Return from the handshake with an `ErrorCode::WANT_CLIENT_HELLO_CB` error. - pub const RETRY: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_RETRY); -} - -/// An SSL/TLS protocol version. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct SslVersion(c_int); - -impl SslVersion { - /// SSLv3 - pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION); - - /// TLSv1.0 - pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION); - - /// TLSv1.1 - pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION); - - /// TLSv1.2 - pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION); - - /// TLSv1.3 - /// - /// Requires AWS-LC or BoringSSL or OpenSSL 1.1.1 or newer or LibreSSL. - #[cfg(any(ossl111, libressl, boringssl, awslc))] - pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION); - - /// DTLSv1.0 - /// - /// DTLS 1.0 corresponds to TLS 1.1. - pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION); - - /// DTLSv1.2 - /// - /// DTLS 1.2 corresponds to TLS 1.2 to harmonize versions. There was never a DTLS 1.1. - pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION); -} - -cfg_if! { - if #[cfg(any(boringssl, awslc))] { - type SslCacheTy = i64; - type SslCacheSize = libc::c_ulong; - type MtuTy = u32; - type SizeTy = usize; - } else { - type SslCacheTy = i64; - type SslCacheSize = c_long; - type MtuTy = c_long; - type SizeTy = u32; - } -} - -/// A standard implementation of protocol selection for Application Layer Protocol Negotiation -/// (ALPN). -/// -/// `server` should contain the server's list of supported protocols and `client` the client's. They -/// must both be in the ALPN wire format. See the documentation for -/// [`SslContextBuilder::set_alpn_protos`] for details. -/// -/// It will select the first protocol supported by the server which is also supported by the client. -/// -/// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos -#[corresponds(SSL_select_next_proto)] -pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> { - unsafe { - let mut out = ptr::null_mut(); - let mut outlen = 0; - let r = ffi::SSL_select_next_proto( - &mut out, - &mut outlen, - server.as_ptr(), - server.len() as c_uint, - client.as_ptr(), - client.len() as c_uint, - ); - if r == ffi::OPENSSL_NPN_NEGOTIATED { - Some(util::from_raw_parts(out as *const u8, outlen as usize)) - } else { - None - } - } -} - -/// A builder for `SslContext`s. -pub struct SslContextBuilder(SslContext); - -impl SslContextBuilder { - /// Creates a new `SslContextBuilder`. - #[corresponds(SSL_CTX_new)] - pub fn new(method: SslMethod) -> Result { - unsafe { - init(); - let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?; - - Ok(SslContextBuilder::from_ptr(ctx)) - } - } - - /// Creates an `SslContextBuilder` from a pointer to a raw OpenSSL value. - /// - /// # Safety - /// - /// The caller must ensure that the pointer is valid and uniquely owned by the builder. - pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder { - SslContextBuilder(SslContext::from_ptr(ctx)) - } - - /// Returns a pointer to the raw OpenSSL value. - pub fn as_ptr(&self) -> *mut ffi::SSL_CTX { - self.0.as_ptr() - } - - /// Configures the certificate verification method for new connections. - #[corresponds(SSL_CTX_set_verify)] - pub fn set_verify(&mut self, mode: SslVerifyMode) { - unsafe { - ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None); - } - } - - /// Configures the certificate verification method for new connections and - /// registers a verification callback. - /// - /// The callback is passed a boolean indicating if OpenSSL's internal verification succeeded as - /// well as a reference to the `X509StoreContext` which can be used to examine the certificate - /// chain. It should return a boolean indicating if verification succeeded. - #[corresponds(SSL_CTX_set_verify)] - pub fn set_verify_callback(&mut self, mode: SslVerifyMode, verify: F) - where - F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send, - { - unsafe { - self.set_ex_data(SslContext::cached_ex_index::(), verify); - ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::)); - } - } - - /// Configures the server name indication (SNI) callback for new connections. - /// - /// SNI is used to allow a single server to handle requests for multiple domains, each of which - /// has its own certificate chain and configuration. - /// - /// Obtain the server name with the `servername` method and then set the corresponding context - /// with `set_ssl_context` - #[corresponds(SSL_CTX_set_tlsext_servername_callback)] - // FIXME tlsext prefix? - pub fn set_servername_callback(&mut self, callback: F) - where - F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send, - { - unsafe { - // The SNI callback is somewhat unique in that the callback associated with the original - // context associated with an SSL can be used even if the SSL's context has been swapped - // out. When that happens, we wouldn't be able to look up the callback's state in the - // context's ex data. Instead, pass the pointer directly as the servername arg. It's - // still stored in ex data to manage the lifetime. - let arg = self.set_ex_data_inner(SslContext::cached_ex_index::(), callback); - ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg); - #[cfg(any(boringssl, awslc))] - ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::)); - #[cfg(not(any(boringssl, awslc)))] - ffi::SSL_CTX_set_tlsext_servername_callback__fixed_rust( - self.as_ptr(), - Some(raw_sni::), - ); - } - } - - /// Sets the certificate verification depth. - /// - /// If the peer's certificate chain is longer than this value, verification will fail. - #[corresponds(SSL_CTX_set_verify_depth)] - pub fn set_verify_depth(&mut self, depth: u32) { - unsafe { - ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int); - } - } - - /// Sets a custom certificate store for verifying peer certificates. - /// - /// Requires OpenSSL 1.0.2 or newer. - #[corresponds(SSL_CTX_set0_verify_cert_store)] - #[cfg(ossl102)] - pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> { - unsafe { - let ptr = cert_store.as_ptr(); - cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?; - mem::forget(cert_store); - - Ok(()) - } - } - - /// Replaces the context's certificate store. - #[corresponds(SSL_CTX_set_cert_store)] - pub fn set_cert_store(&mut self, cert_store: X509Store) { - unsafe { - ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr()); - mem::forget(cert_store); - } - } - - /// Controls read ahead behavior. - /// - /// If enabled, OpenSSL will read as much data as is available from the underlying stream, - /// instead of a single record at a time. - /// - /// It has no effect when used with DTLS. - #[corresponds(SSL_CTX_set_read_ahead)] - pub fn set_read_ahead(&mut self, read_ahead: bool) { - unsafe { - ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType); - } - } - - /// Sets the mode used by the context, returning the previous mode. - #[corresponds(SSL_CTX_set_mode)] - pub fn set_mode(&mut self, mode: SslMode) -> SslMode { - unsafe { - let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as MtuTy) as SslBitType; - SslMode::from_bits_retain(bits) - } - } - - /// Sets the parameters to be used during ephemeral Diffie-Hellman key exchange. - #[corresponds(SSL_CTX_set_tmp_dh)] - pub fn set_tmp_dh(&mut self, dh: &DhRef) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) } - } - - /// Sets the callback which will generate parameters to be used during ephemeral Diffie-Hellman - /// key exchange. - /// - /// The callback is provided with a reference to the `Ssl` for the session, as well as a boolean - /// indicating if the selected cipher is export-grade, and the key length. The export and key - /// length options are archaic and should be ignored in almost all cases. - #[corresponds(SSL_CTX_set_tmp_dh_callback)] - pub fn set_tmp_dh_callback(&mut self, callback: F) - where - F: Fn(&mut SslRef, bool, u32) -> Result, ErrorStack> + 'static + Sync + Send, - { - unsafe { - self.set_ex_data(SslContext::cached_ex_index::(), callback); - - #[cfg(not(any(boringssl, awslc)))] - ffi::SSL_CTX_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh::)); - #[cfg(any(boringssl, awslc))] - ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::)); - } - } - - /// Sets the parameters to be used during ephemeral elliptic curve Diffie-Hellman key exchange. - #[corresponds(SSL_CTX_set_tmp_ecdh)] - pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) } - } - - /// Sets the callback which will generate parameters to be used during ephemeral elliptic curve - /// Diffie-Hellman key exchange. - /// - /// The callback is provided with a reference to the `Ssl` for the session, as well as a boolean - /// indicating if the selected cipher is export-grade, and the key length. The export and key - /// length options are archaic and should be ignored in almost all cases. - /// - /// Requires OpenSSL 1.0.2. - #[corresponds(SSL_CTX_set_tmp_ecdh_callback)] - #[cfg(all(ossl102, not(ossl110)))] - #[deprecated(note = "this function leaks memory and does not exist on newer OpenSSL versions")] - pub fn set_tmp_ecdh_callback(&mut self, callback: F) - where - F: Fn(&mut SslRef, bool, u32) -> Result, ErrorStack> + 'static + Sync + Send, - { - unsafe { - self.set_ex_data(SslContext::cached_ex_index::(), callback); - ffi::SSL_CTX_set_tmp_ecdh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_ecdh::)); - } - } - - /// Use the default locations of trusted certificates for verification. - /// - /// 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(SSL_CTX_set_default_verify_paths)] - pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) } - } - - /// Loads trusted root certificates from a file. - /// - /// The file should contain a sequence of PEM-formatted CA certificates. - #[corresponds(SSL_CTX_load_verify_locations)] - pub fn set_ca_file>(&mut self, file: P) -> Result<(), ErrorStack> { - self.load_verify_locations(Some(file.as_ref()), None) - } - - /// Loads trusted root certificates from a file and/or a directory. - #[corresponds(SSL_CTX_load_verify_locations)] - pub fn load_verify_locations( - &mut self, - ca_file: Option<&Path>, - ca_path: Option<&Path>, - ) -> Result<(), ErrorStack> { - let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap()); - let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap()); - unsafe { - cvt(ffi::SSL_CTX_load_verify_locations( - self.as_ptr(), - ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()), - ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), - )) - .map(|_| ()) - } - } - - /// Sets the list of CA names sent to the client. - /// - /// The CA certificates must still be added to the trust root - they are not automatically set - /// as trusted by this method. - #[corresponds(SSL_CTX_set_client_CA_list)] - pub fn set_client_ca_list(&mut self, list: Stack) { - unsafe { - ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr()); - mem::forget(list); - } - } - - /// Add the provided CA certificate to the list sent by the server to the client when - /// requesting client-side TLS authentication. - #[corresponds(SSL_CTX_add_client_CA)] - pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) } - } - - /// Set the context identifier for sessions. - /// - /// This value identifies the server's session cache to clients, telling them when they're - /// able to reuse sessions. It should be set to a unique value per server, unless multiple - /// servers share a session cache. - /// - /// This value should be set when using client certificates, or each request will fail its - /// handshake and need to be restarted. - #[corresponds(SSL_CTX_set_session_id_context)] - pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> { - unsafe { - assert!(sid_ctx.len() <= c_uint::MAX as usize); - cvt(ffi::SSL_CTX_set_session_id_context( - self.as_ptr(), - sid_ctx.as_ptr(), - sid_ctx.len() as SizeTy, - )) - .map(|_| ()) - } - } - - /// Loads a leaf certificate from a file. - /// - /// Only a single certificate will be loaded - use `add_extra_chain_cert` to add the remainder - /// of the certificate chain, or `set_certificate_chain_file` to load the entire chain from a - /// single file. - #[corresponds(SSL_CTX_use_certificate_file)] - pub fn set_certificate_file>( - &mut self, - file: P, - file_type: SslFiletype, - ) -> Result<(), ErrorStack> { - let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); - unsafe { - cvt(ffi::SSL_CTX_use_certificate_file( - self.as_ptr(), - file.as_ptr() as *const _, - file_type.as_raw(), - )) - .map(|_| ()) - } - } - - /// Loads a certificate chain from a file. - /// - /// The file should contain a sequence of PEM-formatted certificates, the first being the leaf - /// certificate, and the remainder forming the chain of certificates up to and including the - /// trusted root certificate. - #[corresponds(SSL_CTX_use_certificate_chain_file)] - pub fn set_certificate_chain_file>( - &mut self, - file: P, - ) -> Result<(), ErrorStack> { - let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); - unsafe { - cvt(ffi::SSL_CTX_use_certificate_chain_file( - self.as_ptr(), - file.as_ptr() as *const _, - )) - .map(|_| ()) - } - } - - /// Sets the leaf certificate. - /// - /// Use `add_extra_chain_cert` to add the remainder of the certificate chain. - #[corresponds(SSL_CTX_use_certificate)] - pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) } - } - - /// Appends a certificate to the certificate chain. - /// - /// This chain should contain all certificates necessary to go from the certificate specified by - /// `set_certificate` to a trusted root. - #[corresponds(SSL_CTX_add_extra_chain_cert)] - pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?; - mem::forget(cert); - Ok(()) - } - } - - /// Loads the private key from a file. - #[corresponds(SSL_CTX_use_PrivateKey_file)] - pub fn set_private_key_file>( - &mut self, - file: P, - file_type: SslFiletype, - ) -> Result<(), ErrorStack> { - let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); - unsafe { - cvt(ffi::SSL_CTX_use_PrivateKey_file( - self.as_ptr(), - file.as_ptr() as *const _, - file_type.as_raw(), - )) - .map(|_| ()) - } - } - - /// Sets the private key. - #[corresponds(SSL_CTX_use_PrivateKey)] - pub fn set_private_key(&mut self, key: &PKeyRef) -> Result<(), ErrorStack> - where - T: HasPrivate, - { - unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) } - } - - /// Sets the list of supported ciphers for protocols before TLSv1.3. - /// - /// The `set_ciphersuites` method controls the cipher suites for TLSv1.3. - /// - /// See [`ciphers`] for details on the format. - /// - /// [`ciphers`]: https://docs.openssl.org/master/man1/ciphers/ - #[corresponds(SSL_CTX_set_cipher_list)] - pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { - let cipher_list = CString::new(cipher_list).unwrap(); - unsafe { - cvt(ffi::SSL_CTX_set_cipher_list( - self.as_ptr(), - cipher_list.as_ptr() as *const _, - )) - .map(|_| ()) - } - } - - /// Sets the list of supported ciphers for the TLSv1.3 protocol. - /// - /// The `set_cipher_list` method controls the cipher suites for protocols before TLSv1.3. - /// - /// The format consists of TLSv1.3 cipher suite names separated by `:` characters in order of - /// preference. - /// - /// Requires OpenSSL 1.1.1 or newer or LibreSSL. - #[corresponds(SSL_CTX_set_ciphersuites)] - #[cfg(any(ossl111, libressl))] - pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { - let cipher_list = CString::new(cipher_list).unwrap(); - unsafe { - cvt(ffi::SSL_CTX_set_ciphersuites( - self.as_ptr(), - cipher_list.as_ptr() as *const _, - )) - .map(|_| ()) - } - } - - /// Enables ECDHE key exchange with an automatically chosen curve list. - /// - /// Requires OpenSSL 1.0.2. - #[corresponds(SSL_CTX_set_ecdh_auto)] - #[cfg(any(libressl, all(ossl102, not(ossl110))))] - pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) } - } - - /// Sets the options used by the context, returning the old set. - /// - /// # Note - /// - /// This *enables* the specified options, but does not disable unspecified options. Use - /// `clear_options` for that. - #[corresponds(SSL_CTX_set_options)] - pub fn set_options(&mut self, option: SslOptions) -> SslOptions { - let bits = - unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr; - SslOptions::from_bits_retain(bits) - } - - /// Returns the options used by the context. - #[corresponds(SSL_CTX_get_options)] - pub fn options(&self) -> SslOptions { - let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr; - SslOptions::from_bits_retain(bits) - } - - /// Clears the options used by the context, returning the old set. - #[corresponds(SSL_CTX_clear_options)] - pub fn clear_options(&mut self, option: SslOptions) -> SslOptions { - let bits = - unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr; - SslOptions::from_bits_retain(bits) - } - - /// Sets the minimum supported protocol version. - /// - /// A value of `None` will enable protocol versions down to the lowest version supported by - /// OpenSSL. - /// - /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.1.0 or newer. - #[corresponds(SSL_CTX_set_min_proto_version)] - #[cfg(any(ossl110, libressl, boringssl, awslc))] - pub fn set_min_proto_version(&mut self, version: Option) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::SSL_CTX_set_min_proto_version( - self.as_ptr(), - version.map_or(0, |v| v.0 as _), - )) - .map(|_| ()) - } - } - - /// Sets the maximum supported protocol version. - /// - /// A value of `None` will enable protocol versions up to the highest version supported by - /// OpenSSL. - /// - /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.1.0 or newer. - #[corresponds(SSL_CTX_set_max_proto_version)] - #[cfg(any(ossl110, libressl, boringssl, awslc))] - pub fn set_max_proto_version(&mut self, version: Option) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::SSL_CTX_set_max_proto_version( - self.as_ptr(), - version.map_or(0, |v| v.0 as _), - )) - .map(|_| ()) - } - } - - /// Gets the minimum supported protocol version. - /// - /// A value of `None` indicates that all versions down to the lowest version supported by - /// OpenSSL are enabled. - /// - /// Requires LibreSSL or OpenSSL 1.1.0g or newer. - #[corresponds(SSL_CTX_get_min_proto_version)] - #[cfg(any(ossl110g, libressl))] - pub fn min_proto_version(&mut self) -> Option { - unsafe { - let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr()); - if r == 0 { - None - } else { - Some(SslVersion(r)) - } - } - } - - /// Gets the maximum supported protocol version. - /// - /// A value of `None` indicates that all versions up to the highest version supported by - /// OpenSSL are enabled. - /// - /// Requires LibreSSL or OpenSSL 1.1.0g or newer. - #[corresponds(SSL_CTX_get_max_proto_version)] - #[cfg(any(ossl110g, libressl))] - pub fn max_proto_version(&mut self) -> Option { - unsafe { - let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr()); - if r == 0 { - None - } else { - Some(SslVersion(r)) - } - } - } - - /// Sets the protocols to sent to the server for Application Layer Protocol Negotiation (ALPN). - /// - /// The input must be in ALPN "wire format". It consists of a sequence of supported protocol - /// names prefixed by their byte length. For example, the protocol list consisting of `spdy/1` - /// and `http/1.1` is encoded as `b"\x06spdy/1\x08http/1.1"`. The protocols are ordered by - /// preference. - /// - /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer. - #[corresponds(SSL_CTX_set_alpn_protos)] - pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> { - unsafe { - assert!(protocols.len() <= c_uint::MAX as usize); - let r = ffi::SSL_CTX_set_alpn_protos( - self.as_ptr(), - protocols.as_ptr(), - protocols.len() as _, - ); - // fun fact, SSL_CTX_set_alpn_protos has a reversed return code D: - if r == 0 { - Ok(()) - } else { - Err(ErrorStack::get()) - } - } - } - - /// Enables the DTLS extension "use_srtp" as defined in RFC5764. - #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))] - #[corresponds(SSL_CTX_set_tlsext_use_srtp)] - pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> { - unsafe { - let cstr = CString::new(protocols).unwrap(); - - let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr()); - // fun fact, set_tlsext_use_srtp has a reversed return code D: - if r == 0 { - Ok(()) - } else { - Err(ErrorStack::get()) - } - } - } - - /// Sets the callback used by a server to select a protocol for Application Layer Protocol - /// Negotiation (ALPN). - /// - /// The callback is provided with the client's protocol list in ALPN wire format. See the - /// documentation for [`SslContextBuilder::set_alpn_protos`] for details. It should return one - /// of those protocols on success. The [`select_next_proto`] function implements the standard - /// protocol selection algorithm. - /// - /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer. - /// - /// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos - /// [`select_next_proto`]: fn.select_next_proto.html - #[corresponds(SSL_CTX_set_alpn_select_cb)] - pub fn set_alpn_select_callback(&mut self, callback: F) - where - F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send, - { - unsafe { - self.set_ex_data(SslContext::cached_ex_index::(), callback); - #[cfg(not(any(boringssl, awslc)))] - ffi::SSL_CTX_set_alpn_select_cb__fixed_rust( - self.as_ptr(), - Some(callbacks::raw_alpn_select::), - ptr::null_mut(), - ); - #[cfg(any(boringssl, awslc))] - ffi::SSL_CTX_set_alpn_select_cb( - self.as_ptr(), - Some(callbacks::raw_alpn_select::), - ptr::null_mut(), - ); - } - } - - /// Checks for consistency between the private key and certificate. - #[corresponds(SSL_CTX_check_private_key)] - pub fn check_private_key(&self) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) } - } - - /// Returns a shared reference to the context's certificate store. - #[corresponds(SSL_CTX_get_cert_store)] - pub fn cert_store(&self) -> &X509StoreBuilderRef { - unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) } - } - - /// Returns a mutable reference to the context's certificate store. - #[corresponds(SSL_CTX_get_cert_store)] - pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef { - unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) } - } - - /// Returns a reference to the X509 verification configuration. - /// - /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer. - #[corresponds(SSL_CTX_get0_param)] - pub fn verify_param(&self) -> &X509VerifyParamRef { - unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) } - } - - /// Returns a mutable reference to the X509 verification configuration. - /// - /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer. - #[corresponds(SSL_CTX_get0_param)] - pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef { - unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) } - } - - /// Sets the callback dealing with OCSP stapling. - /// - /// On the client side, this callback is responsible for validating the OCSP status response - /// returned by the server. The status may be retrieved with the `SslRef::ocsp_status` method. - /// A response of `Ok(true)` indicates that the OCSP status is valid, and a response of - /// `Ok(false)` indicates that the OCSP status is invalid and the handshake should be - /// terminated. - /// - /// On the server side, this callback is responsible for setting the OCSP status response to be - /// returned to clients. The status may be set with the `SslRef::set_ocsp_status` method. A - /// response of `Ok(true)` indicates that the OCSP status should be returned to the client, and - /// `Ok(false)` indicates that the status should not be returned to the client. - #[corresponds(SSL_CTX_set_tlsext_status_cb)] - pub fn set_status_callback(&mut self, callback: F) -> Result<(), ErrorStack> - where - F: Fn(&mut SslRef) -> Result + 'static + Sync + Send, - { - unsafe { - self.set_ex_data(SslContext::cached_ex_index::(), callback); - cvt( - ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::)) - as c_int, - ) - .map(|_| ()) - } - } - - /// Sets the callback for providing an identity and pre-shared key for a TLS-PSK client. - /// - /// The callback will be called with the SSL context, an identity hint if one was provided - /// by the server, a mutable slice for each of the identity and pre-shared key bytes. The - /// identity must be written as a null-terminated C string. - #[corresponds(SSL_CTX_set_psk_client_callback)] - #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] - pub fn set_psk_client_callback(&mut self, callback: F) - where - F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result - + 'static - + Sync - + Send, - { - unsafe { - self.set_ex_data(SslContext::cached_ex_index::(), callback); - ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::)); - } - } - - #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")] - #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] - pub fn set_psk_callback(&mut self, callback: F) - where - F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result - + 'static - + Sync - + Send, - { - self.set_psk_client_callback(callback) - } - - /// Sets the callback for providing an identity and pre-shared key for a TLS-PSK server. - /// - /// The callback will be called with the SSL context, an identity provided by the client, - /// and, a mutable slice for the pre-shared key bytes. The callback returns the number of - /// bytes in the pre-shared key. - #[corresponds(SSL_CTX_set_psk_server_callback)] - #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] - pub fn set_psk_server_callback(&mut self, callback: F) - where - F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result - + 'static - + Sync - + Send, - { - unsafe { - self.set_ex_data(SslContext::cached_ex_index::(), callback); - ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::)); - } - } - - /// Sets the callback which is called when new sessions are negotiated. - /// - /// This can be used by clients to implement session caching. While in TLSv1.2 the session is - /// available to access via [`SslRef::session`] immediately after the handshake completes, this - /// is not the case for TLSv1.3. There, a session is not generally available immediately, and - /// the server may provide multiple session tokens to the client over a single session. The new - /// session callback is a portable way to deal with both cases. - /// - /// Note that session caching must be enabled for the callback to be invoked, and it defaults - /// off for clients. [`set_session_cache_mode`] controls that behavior. - /// - /// [`SslRef::session`]: struct.SslRef.html#method.session - /// [`set_session_cache_mode`]: #method.set_session_cache_mode - #[corresponds(SSL_CTX_sess_set_new_cb)] - pub fn set_new_session_callback(&mut self, callback: F) - where - F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send, - { - unsafe { - self.set_ex_data(SslContext::cached_ex_index::(), callback); - ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::)); - } - } - - /// Sets the callback which is called when sessions are removed from the context. - /// - /// Sessions can be removed because they have timed out or because they are considered faulty. - #[corresponds(SSL_CTX_sess_set_remove_cb)] - pub fn set_remove_session_callback(&mut self, callback: F) - where - F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send, - { - unsafe { - self.set_ex_data(SslContext::cached_ex_index::(), callback); - ffi::SSL_CTX_sess_set_remove_cb( - self.as_ptr(), - Some(callbacks::raw_remove_session::), - ); - } - } - - /// Sets the callback which is called when a client proposed to resume a session but it was not - /// found in the internal cache. - /// - /// The callback is passed a reference to the session ID provided by the client. It should - /// return the session corresponding to that ID if available. This is only used for servers, not - /// clients. - /// - /// # Safety - /// - /// The returned `SslSession` must not be associated with a different `SslContext`. - #[corresponds(SSL_CTX_sess_set_get_cb)] - pub unsafe fn set_get_session_callback(&mut self, callback: F) - where - F: Fn(&mut SslRef, &[u8]) -> Option + 'static + Sync + Send, - { - self.set_ex_data(SslContext::cached_ex_index::(), callback); - ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::)); - } - - /// Sets the TLS key logging callback. - /// - /// The callback is invoked whenever TLS key material is generated, and is passed a line of NSS - /// SSLKEYLOGFILE-formatted text. This can be used by tools like Wireshark to decrypt message - /// traffic. The line does not contain a trailing newline. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_CTX_set_keylog_callback)] - #[cfg(any(ossl111, boringssl, awslc))] - pub fn set_keylog_callback(&mut self, callback: F) - where - F: Fn(&SslRef, &str) + 'static + Sync + Send, - { - unsafe { - self.set_ex_data(SslContext::cached_ex_index::(), callback); - ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::)); - } - } - - /// Sets the session caching mode use for connections made with the context. - /// - /// Returns the previous session caching mode. - #[corresponds(SSL_CTX_set_session_cache_mode)] - pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode { - unsafe { - let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits()); - SslSessionCacheMode::from_bits_retain(bits) - } - } - - /// Sets the callback for generating an application cookie for TLS1.3 - /// stateless handshakes. - /// - /// The callback will be called with the SSL context and a slice into which the cookie - /// should be written. The callback should return the number of bytes written. - #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)] - #[cfg(ossl111)] - pub fn set_stateless_cookie_generate_cb(&mut self, callback: F) - where - F: Fn(&mut SslRef, &mut [u8]) -> Result + 'static + Sync + Send, - { - unsafe { - self.set_ex_data(SslContext::cached_ex_index::(), callback); - ffi::SSL_CTX_set_stateless_cookie_generate_cb( - self.as_ptr(), - Some(raw_stateless_cookie_generate::), - ); - } - } - - /// Sets the callback for verifying an application cookie for TLS1.3 - /// stateless handshakes. - /// - /// The callback will be called with the SSL context and the cookie supplied by the - /// client. It should return true if and only if the cookie is valid. - /// - /// Note that the OpenSSL implementation independently verifies the integrity of - /// application cookies using an HMAC before invoking the supplied callback. - #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)] - #[cfg(ossl111)] - pub fn set_stateless_cookie_verify_cb(&mut self, callback: F) - where - F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send, - { - unsafe { - self.set_ex_data(SslContext::cached_ex_index::(), callback); - ffi::SSL_CTX_set_stateless_cookie_verify_cb( - self.as_ptr(), - Some(raw_stateless_cookie_verify::), - ) - } - } - - /// Sets the callback for generating a DTLSv1 cookie - /// - /// The callback will be called with the SSL context and a slice into which the cookie - /// should be written. The callback should return the number of bytes written. - #[corresponds(SSL_CTX_set_cookie_generate_cb)] - #[cfg(not(any(boringssl, awslc)))] - pub fn set_cookie_generate_cb(&mut self, callback: F) - where - F: Fn(&mut SslRef, &mut [u8]) -> Result + 'static + Sync + Send, - { - unsafe { - self.set_ex_data(SslContext::cached_ex_index::(), callback); - ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::)); - } - } - - /// Sets the callback for verifying a DTLSv1 cookie - /// - /// The callback will be called with the SSL context and the cookie supplied by the - /// client. It should return true if and only if the cookie is valid. - #[corresponds(SSL_CTX_set_cookie_verify_cb)] - #[cfg(not(any(boringssl, awslc)))] - pub fn set_cookie_verify_cb(&mut self, callback: F) - where - F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send, - { - unsafe { - self.set_ex_data(SslContext::cached_ex_index::(), callback); - ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::)); - } - } - - /// Sets the extra data at the specified index. - /// - /// This can be used to provide data to callbacks registered with the context. Use the - /// `SslContext::new_ex_index` method to create an `Index`. - // FIXME should return a result - #[corresponds(SSL_CTX_set_ex_data)] - pub fn set_ex_data(&mut self, index: Index, data: T) { - self.set_ex_data_inner(index, data); - } - - fn set_ex_data_inner(&mut self, index: Index, data: T) -> *mut c_void { - match self.ex_data_mut(index) { - Some(v) => { - *v = data; - (v as *mut T).cast() - } - _ => unsafe { - let data = Box::into_raw(Box::new(data)) as *mut c_void; - ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data); - data - }, - } - } - - fn ex_data_mut(&mut self, index: Index) -> Option<&mut T> { - unsafe { - let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw()); - if data.is_null() { - None - } else { - Some(&mut *data.cast()) - } - } - } - - /// Adds a custom extension for a TLS/DTLS client or server for all supported protocol versions. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_CTX_add_custom_ext)] - #[cfg(ossl111)] - pub fn add_custom_ext( - &mut self, - ext_type: u16, - context: ExtensionContext, - add_cb: AddFn, - parse_cb: ParseFn, - ) -> Result<(), ErrorStack> - where - AddFn: Fn( - &mut SslRef, - ExtensionContext, - Option<(usize, &X509Ref)>, - ) -> Result, SslAlert> - + 'static - + Sync - + Send, - T: AsRef<[u8]> + 'static + Sync + Send, - ParseFn: Fn( - &mut SslRef, - ExtensionContext, - &[u8], - Option<(usize, &X509Ref)>, - ) -> Result<(), SslAlert> - + 'static - + Sync - + Send, - { - let ret = unsafe { - self.set_ex_data(SslContext::cached_ex_index::(), add_cb); - self.set_ex_data(SslContext::cached_ex_index::(), parse_cb); - - ffi::SSL_CTX_add_custom_ext( - self.as_ptr(), - ext_type as c_uint, - context.bits(), - Some(raw_custom_ext_add::), - Some(raw_custom_ext_free::), - ptr::null_mut(), - Some(raw_custom_ext_parse::), - ptr::null_mut(), - ) - }; - if ret == 1 { - Ok(()) - } else { - Err(ErrorStack::get()) - } - } - - /// Sets the maximum amount of early data that will be accepted on incoming connections. - /// - /// Defaults to 0. - /// - /// Requires OpenSSL 1.1.1 or newer or LibreSSL. - #[corresponds(SSL_CTX_set_max_early_data)] - #[cfg(any(ossl111, libressl))] - pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> { - if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 { - Ok(()) - } else { - Err(ErrorStack::get()) - } - } - - /// Sets a callback which will be invoked just after the client's hello message is received. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_CTX_set_client_hello_cb)] - #[cfg(ossl111)] - pub fn set_client_hello_callback(&mut self, callback: F) - where - F: Fn(&mut SslRef, &mut SslAlert) -> Result - + 'static - + Sync - + Send, - { - unsafe { - let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::(), callback); - ffi::SSL_CTX_set_client_hello_cb( - self.as_ptr(), - Some(callbacks::raw_client_hello::), - ptr, - ); - } - } - - /// Sets the context's session cache size limit, returning the previous limit. - /// - /// A value of 0 means that the cache size is unbounded. - #[corresponds(SSL_CTX_sess_set_cache_size)] - #[allow(clippy::useless_conversion)] - pub fn set_session_cache_size(&mut self, size: i32) -> i64 { - unsafe { - ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy - } - } - - /// Sets the context's supported signature algorithms. - /// - /// Requires OpenSSL 1.0.2 or newer. - #[corresponds(SSL_CTX_set1_sigalgs_list)] - #[cfg(ossl102)] - pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> { - let sigalgs = CString::new(sigalgs).unwrap(); - unsafe { - cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int) - .map(|_| ()) - } - } - - /// Sets the context's supported elliptic curve groups. - /// - /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.1.1 or newer. - #[corresponds(SSL_CTX_set1_groups_list)] - #[cfg(any(ossl111, boringssl, libressl, awslc))] - pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> { - let groups = CString::new(groups).unwrap(); - unsafe { - cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ()) - } - } - - /// Sets the number of TLS 1.3 session tickets that will be sent to a client after a full - /// handshake. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_CTX_set_num_tickets)] - #[cfg(ossl111)] - pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) } - } - - /// Set the context's security level to a value between 0 and 5, inclusive. - /// A security value of 0 allows allows all parameters and algorithms. - /// - /// Requires OpenSSL 1.1.0 or newer. - #[corresponds(SSL_CTX_set_security_level)] - #[cfg(any(ossl110, libressl360))] - pub fn set_security_level(&mut self, level: u32) { - unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) } - } - - /// Consumes the builder, returning a new `SslContext`. - pub fn build(self) -> SslContext { - self.0 - } - - /// Sets the context's minimal TLS version, specified as "VersionTLS1[0..3]", and a comma-separated list of ciphersuites. - /// - pub fn set_min_tls_version_and_ciphersuites(&mut self, min_tls_version: &Option, ciphersuites: &Option) -> Result<(), ErrorEx>{ - let mut min_proto_version = SslVersion::TLS1; - if let Some(min_tls_version) = min_tls_version { - min_proto_version = match min_tls_version.as_str() { - "VersionTLS10" => SslVersion::TLS1, - "VersionTLS11" => SslVersion::TLS1_1, - "VersionTLS12" => SslVersion::TLS1_2, - "VersionTLS13" => SslVersion::TLS1_3, - _ => return Err(ErrorEx::InvalidTlsVersion), - }; - self.set_min_proto_version(Some(min_proto_version)).map_err(|e| ErrorEx::OpenSslError { error_stack: e })?; - } - if let Some(ciphersuites) = ciphersuites { - if !ciphersuites.is_empty() { - let ciphersuites = &ciphersuites.replace(",", ":"); - if min_proto_version == SslVersion::TLS1_3 { - self.set_ciphersuites(&ciphersuites).map_err(|e| ErrorEx::OpenSslError { error_stack: e })?; - } else { - self.set_cipher_list(&ciphersuites).map_err(|e| ErrorEx::OpenSslError { error_stack: e })?; - } - } else { - return Err(ErrorEx::InvalidCiphersuite); - } - } - Ok(()) - } -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::SSL_CTX; - fn drop = ffi::SSL_CTX_free; - - /// A context object for TLS streams. - /// - /// Applications commonly configure a single `SslContext` that is shared by all of its - /// `SslStreams`. - pub struct SslContext; - - /// Reference to [`SslContext`] - /// - /// [`SslContext`]: struct.SslContext.html - pub struct SslContextRef; -} - -impl Clone for SslContext { - fn clone(&self) -> Self { - (**self).to_owned() - } -} - -impl ToOwned for SslContextRef { - type Owned = SslContext; - - fn to_owned(&self) -> Self::Owned { - unsafe { - SSL_CTX_up_ref(self.as_ptr()); - SslContext::from_ptr(self.as_ptr()) - } - } -} - -// TODO: add useful info here -impl fmt::Debug for SslContext { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "SslContext") - } -} - -impl SslContext { - /// Creates a new builder object for an `SslContext`. - pub fn builder(method: SslMethod) -> Result { - SslContextBuilder::new(method) - } - - /// Returns a new extra data index. - /// - /// Each invocation of this function is guaranteed to return a distinct index. These can be used - /// to store data in the context that can be retrieved later by callbacks, for example. - #[corresponds(SSL_CTX_get_ex_new_index)] - pub fn new_ex_index() -> Result, ErrorStack> - where - T: 'static + Sync + Send, - { - unsafe { - ffi::init(); - #[cfg(any(boringssl, awslc))] - let idx = cvt_n(get_new_idx(Some(free_data_box::)))?; - #[cfg(not(any(boringssl, awslc)))] - let idx = cvt_n(get_new_idx(free_data_box::))?; - Ok(Index::from_raw(idx)) - } - } - - // FIXME should return a result? - fn cached_ex_index() -> Index - where - T: 'static + Sync + Send, - { - unsafe { - let idx = *INDEXES - .lock() - .unwrap_or_else(|e| e.into_inner()) - .entry(TypeId::of::()) - .or_insert_with(|| SslContext::new_ex_index::().unwrap().as_raw()); - Index::from_raw(idx) - } - } -} - -impl SslContextRef { - /// Returns the certificate associated with this `SslContext`, if present. - /// - /// Requires LibreSSL or OpenSSL 1.0.2 or newer. - #[corresponds(SSL_CTX_get0_certificate)] - #[cfg(any(ossl102, libressl))] - pub fn certificate(&self) -> Option<&X509Ref> { - unsafe { - let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr()); - X509Ref::from_const_ptr_opt(ptr) - } - } - - /// Returns the private key associated with this `SslContext`, if present. - /// - /// Requires OpenSSL 1.0.2 or newer or LibreSSL. - #[corresponds(SSL_CTX_get0_privatekey)] - #[cfg(any(ossl102, libressl))] - pub fn private_key(&self) -> Option<&PKeyRef> { - unsafe { - let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr()); - PKeyRef::from_const_ptr_opt(ptr) - } - } - - /// Returns a shared reference to the certificate store used for verification. - #[corresponds(SSL_CTX_get_cert_store)] - pub fn cert_store(&self) -> &X509StoreRef { - unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) } - } - - /// Returns a shared reference to the stack of certificates making up the chain from the leaf. - #[corresponds(SSL_CTX_get_extra_chain_certs)] - pub fn extra_chain_certs(&self) -> &StackRef { - unsafe { - let mut chain = ptr::null_mut(); - ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain); - StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null") - } - } - - /// Returns a reference to the extra data at the specified index. - #[corresponds(SSL_CTX_get_ex_data)] - pub fn ex_data(&self, index: Index) -> Option<&T> { - unsafe { - let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw()); - if data.is_null() { - None - } else { - Some(&*(data as *const T)) - } - } - } - - /// Gets the maximum amount of early data that will be accepted on incoming connections. - /// - /// Requires OpenSSL 1.1.1 or newer or LibreSSL. - #[corresponds(SSL_CTX_get_max_early_data)] - #[cfg(any(ossl111, libressl))] - pub fn max_early_data(&self) -> u32 { - unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) } - } - - /// Adds a session to the context's cache. - /// - /// Returns `true` if the session was successfully added to the cache, and `false` if it was already present. - /// - /// # Safety - /// - /// The caller of this method is responsible for ensuring that the session has never been used with another - /// `SslContext` than this one. - #[corresponds(SSL_CTX_add_session)] - pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool { - ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0 - } - - /// Removes a session from the context's cache and marks it as non-resumable. - /// - /// Returns `true` if the session was successfully found and removed, and `false` otherwise. - /// - /// # Safety - /// - /// The caller of this method is responsible for ensuring that the session has never been used with another - /// `SslContext` than this one. - #[corresponds(SSL_CTX_remove_session)] - pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool { - ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0 - } - - /// Returns the context's session cache size limit. - /// - /// A value of 0 means that the cache size is unbounded. - #[corresponds(SSL_CTX_sess_get_cache_size)] - #[allow(clippy::unnecessary_cast)] - pub fn session_cache_size(&self) -> i64 { - unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 } - } - - /// Returns the verify mode that was set on this context from [`SslContextBuilder::set_verify`]. - /// - /// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify - #[corresponds(SSL_CTX_get_verify_mode)] - pub fn verify_mode(&self) -> SslVerifyMode { - let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) }; - SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode") - } - - /// Gets the number of TLS 1.3 session tickets that will be sent to a client after a full - /// handshake. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_CTX_get_num_tickets)] - #[cfg(ossl111)] - pub fn num_tickets(&self) -> usize { - unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) } - } - - /// Get the context's security level, which controls the allowed parameters - /// and algorithms. - /// - /// Requires OpenSSL 1.1.0 or newer. - #[corresponds(SSL_CTX_get_security_level)] - #[cfg(any(ossl110, libressl360))] - pub fn security_level(&self) -> u32 { - unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 } - } -} - -/// Information about the state of a cipher. -pub struct CipherBits { - /// The number of secret bits used for the cipher. - pub secret: i32, - - /// The number of bits processed by the chosen algorithm. - pub algorithm: i32, -} - -/// Information about a cipher. -pub struct SslCipher(*mut ffi::SSL_CIPHER); - -impl ForeignType for SslCipher { - type CType = ffi::SSL_CIPHER; - type Ref = SslCipherRef; - - #[inline] - unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher { - SslCipher(ptr) - } - - #[inline] - fn as_ptr(&self) -> *mut ffi::SSL_CIPHER { - self.0 - } -} - -impl Stackable for SslCipher { - type StackType = ffi::stack_st_SSL_CIPHER; -} - -impl Deref for SslCipher { - type Target = SslCipherRef; - - fn deref(&self) -> &SslCipherRef { - unsafe { SslCipherRef::from_ptr(self.0) } - } -} - -impl DerefMut for SslCipher { - fn deref_mut(&mut self) -> &mut SslCipherRef { - unsafe { SslCipherRef::from_ptr_mut(self.0) } - } -} - -/// Reference to an [`SslCipher`]. -/// -/// [`SslCipher`]: struct.SslCipher.html -pub struct SslCipherRef(Opaque); - -impl ForeignTypeRef for SslCipherRef { - type CType = ffi::SSL_CIPHER; -} - -impl SslCipherRef { - /// Returns the name of the cipher. - #[corresponds(SSL_CIPHER_get_name)] - pub fn name(&self) -> &'static str { - unsafe { - let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr()); - CStr::from_ptr(ptr).to_str().unwrap() - } - } - - /// Returns the RFC-standard name of the cipher, if one exists. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_CIPHER_standard_name)] - #[cfg(ossl111)] - pub fn standard_name(&self) -> Option<&'static str> { - unsafe { - let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr()); - if ptr.is_null() { - None - } else { - Some(CStr::from_ptr(ptr).to_str().unwrap()) - } - } - } - - /// Returns the SSL/TLS protocol version that first defined the cipher. - #[corresponds(SSL_CIPHER_get_version)] - pub fn version(&self) -> &'static str { - let version = unsafe { - let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr()); - CStr::from_ptr(ptr as *const _) - }; - - str::from_utf8(version.to_bytes()).unwrap() - } - - /// Returns the number of bits used for the cipher. - #[corresponds(SSL_CIPHER_get_bits)] - #[allow(clippy::useless_conversion)] - pub fn bits(&self) -> CipherBits { - unsafe { - let mut algo_bits = 0; - let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits); - CipherBits { - secret: secret_bits.into(), - algorithm: algo_bits.into(), - } - } - } - - /// Returns a textual description of the cipher. - #[corresponds(SSL_CIPHER_description)] - pub fn description(&self) -> String { - unsafe { - // SSL_CIPHER_description requires a buffer of at least 128 bytes. - let mut buf = [0; 128]; - let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128); - String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap() - } - } - - /// Returns the handshake digest of the cipher. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_CIPHER_get_handshake_digest)] - #[cfg(ossl111)] - pub fn handshake_digest(&self) -> Option { - unsafe { - let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr()); - if ptr.is_null() { - None - } else { - Some(MessageDigest::from_ptr(ptr)) - } - } - } - - /// Returns the NID corresponding to the cipher. - /// - /// Requires LibreSSL or OpenSSL 1.1.0 or newer. - #[corresponds(SSL_CIPHER_get_cipher_nid)] - #[cfg(any(ossl110, libressl))] - pub fn cipher_nid(&self) -> Option { - let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) }; - if n == 0 { - None - } else { - Some(Nid::from_raw(n)) - } - } - - /// Returns the two-byte ID of the cipher - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_CIPHER_get_protocol_id)] - #[cfg(ossl111)] - pub fn protocol_id(&self) -> [u8; 2] { - unsafe { - let id = ffi::SSL_CIPHER_get_protocol_id(self.as_ptr()); - id.to_be_bytes() - } - } -} - -impl fmt::Debug for SslCipherRef { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "{}", self.name()) - } -} - -/// A stack of selected ciphers, and a stack of selected signalling cipher suites -#[derive(Debug)] -pub struct CipherLists { - pub suites: Stack, - pub signalling_suites: Stack, -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::SSL_SESSION; - fn drop = ffi::SSL_SESSION_free; - - /// An encoded SSL session. - /// - /// These can be cached to share sessions across connections. - pub struct SslSession; - - /// Reference to [`SslSession`]. - /// - /// [`SslSession`]: struct.SslSession.html - pub struct SslSessionRef; -} - -impl Clone for SslSession { - fn clone(&self) -> SslSession { - SslSessionRef::to_owned(self) - } -} - -impl SslSession { - from_der! { - /// Deserializes a DER-encoded session structure. - #[corresponds(d2i_SSL_SESSION)] - from_der, - SslSession, - ffi::d2i_SSL_SESSION - } -} - -impl ToOwned for SslSessionRef { - type Owned = SslSession; - - fn to_owned(&self) -> SslSession { - unsafe { - SSL_SESSION_up_ref(self.as_ptr()); - SslSession(self.as_ptr()) - } - } -} - -impl SslSessionRef { - /// Returns the SSL session ID. - #[corresponds(SSL_SESSION_get_id)] - pub fn id(&self) -> &[u8] { - unsafe { - let mut len = 0; - let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len); - #[allow(clippy::unnecessary_cast)] - util::from_raw_parts(p as *const u8, len as usize) - } - } - - /// Returns the length of the master key. - #[corresponds(SSL_SESSION_get_master_key)] - pub fn master_key_len(&self) -> usize { - unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) } - } - - /// Copies the master key into the provided buffer. - /// - /// Returns the number of bytes written, or the size of the master key if the buffer is empty. - #[corresponds(SSL_SESSION_get_master_key)] - pub fn master_key(&self, buf: &mut [u8]) -> usize { - unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) } - } - - /// Gets the maximum amount of early data that can be sent on this session. - /// - /// Requires OpenSSL 1.1.1 or newer or LibreSSL. - #[corresponds(SSL_SESSION_get_max_early_data)] - #[cfg(any(ossl111, libressl))] - pub fn max_early_data(&self) -> u32 { - unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) } - } - - /// Returns the time at which the session was established, in seconds since the Unix epoch. - #[corresponds(SSL_SESSION_get_time)] - #[allow(clippy::useless_conversion)] - pub fn time(&self) -> SslTimeTy { - unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) } - } - - /// Returns the sessions timeout, in seconds. - /// - /// A session older than this time should not be used for session resumption. - #[corresponds(SSL_SESSION_get_timeout)] - #[allow(clippy::useless_conversion)] - pub fn timeout(&self) -> i64 { - unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() } - } - - /// Returns the session's TLS protocol version. - /// - /// Requires LibreSSL or OpenSSL 1.1.0 or newer. - #[corresponds(SSL_SESSION_get_protocol_version)] - #[cfg(any(ossl110, libressl))] - pub fn protocol_version(&self) -> SslVersion { - unsafe { - let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr()); - SslVersion(version) - } - } - - to_der! { - /// Serializes the session into a DER-encoded structure. - #[corresponds(i2d_SSL_SESSION)] - to_der, - ffi::i2d_SSL_SESSION - } -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::SSL; - fn drop = ffi::SSL_free; - - /// The state of an SSL/TLS session. - /// - /// `Ssl` objects are created from an [`SslContext`], which provides configuration defaults. - /// These defaults can be overridden on a per-`Ssl` basis, however. - /// - /// [`SslContext`]: struct.SslContext.html - pub struct Ssl; - - /// Reference to an [`Ssl`]. - /// - /// [`Ssl`]: struct.Ssl.html - pub struct SslRef; -} - -impl fmt::Debug for Ssl { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, fmt) - } -} - -impl Ssl { - /// Returns a new extra data index. - /// - /// Each invocation of this function is guaranteed to return a distinct index. These can be used - /// to store data in the context that can be retrieved later by callbacks, for example. - #[corresponds(SSL_get_ex_new_index)] - pub fn new_ex_index() -> Result, ErrorStack> - where - T: 'static + Sync + Send, - { - unsafe { - ffi::init(); - #[cfg(any(boringssl, awslc))] - let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::)))?; - #[cfg(not(any(boringssl, awslc)))] - let idx = cvt_n(get_new_ssl_idx(free_data_box::))?; - Ok(Index::from_raw(idx)) - } - } - - // FIXME should return a result? - fn cached_ex_index() -> Index - where - T: 'static + Sync + Send, - { - unsafe { - let idx = *SSL_INDEXES - .lock() - .unwrap_or_else(|e| e.into_inner()) - .entry(TypeId::of::()) - .or_insert_with(|| Ssl::new_ex_index::().unwrap().as_raw()); - Index::from_raw(idx) - } - } - - /// Creates a new `Ssl`. - #[corresponds(SSL_new)] - pub fn new(ctx: &SslContextRef) -> Result { - let session_ctx_index = try_get_session_ctx_index()?; - unsafe { - let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?; - let mut ssl = Ssl::from_ptr(ptr); - ssl.set_ex_data(*session_ctx_index, ctx.to_owned()); - - Ok(ssl) - } - } - - /// Initiates a client-side TLS handshake. - /// # Warning - /// - /// OpenSSL's default configuration is insecure. It is highly recommended to use - /// `SslConnector` rather than `Ssl` directly, as it manages that configuration. - #[corresponds(SSL_connect)] - #[allow(deprecated)] - pub fn connect(self, stream: S) -> Result, HandshakeError> - where - S: Read + Write, - { - SslStreamBuilder::new(self, stream).connect() - } - - /// Initiates a server-side TLS handshake. - /// - /// # Warning - /// - /// OpenSSL's default configuration is insecure. It is highly recommended to use - /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration. - #[corresponds(SSL_accept)] - #[allow(deprecated)] - pub fn accept(self, stream: S) -> Result, HandshakeError> - where - S: Read + Write, - { - SslStreamBuilder::new(self, stream).accept() - } -} - -impl fmt::Debug for SslRef { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_struct("Ssl") - .field("state", &self.state_string_long()) - .field("verify_result", &self.verify_result()) - .finish() - } -} - -impl SslRef { - fn get_raw_rbio(&self) -> *mut ffi::BIO { - unsafe { ffi::SSL_get_rbio(self.as_ptr()) } - } - - fn get_error(&self, ret: c_int) -> ErrorCode { - unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) } - } - - /// Configure as an outgoing stream from a client. - #[corresponds(SSL_set_connect_state)] - pub fn set_connect_state(&mut self) { - unsafe { ffi::SSL_set_connect_state(self.as_ptr()) } - } - - /// Configure as an incoming stream to a server. - #[corresponds(SSL_set_accept_state)] - pub fn set_accept_state(&mut self) { - unsafe { ffi::SSL_set_accept_state(self.as_ptr()) } - } - - /// Like [`SslContextBuilder::set_verify`]. - /// - /// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify - #[corresponds(SSL_set_verify)] - pub fn set_verify(&mut self, mode: SslVerifyMode) { - unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) } - } - - /// Returns the verify mode that was set using `set_verify`. - #[corresponds(SSL_set_verify_mode)] - pub fn verify_mode(&self) -> SslVerifyMode { - let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) }; - SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode") - } - - /// Like [`SslContextBuilder::set_verify_callback`]. - /// - /// [`SslContextBuilder::set_verify_callback`]: struct.SslContextBuilder.html#method.set_verify_callback - #[corresponds(SSL_set_verify)] - pub fn set_verify_callback(&mut self, mode: SslVerifyMode, verify: F) - where - F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send, - { - unsafe { - // this needs to be in an Arc since the callback can register a new callback! - self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify)); - ffi::SSL_set_verify( - self.as_ptr(), - mode.bits() as c_int, - Some(ssl_raw_verify::), - ); - } - } - - /// Like [`SslContextBuilder::set_tmp_dh`]. - /// - /// [`SslContextBuilder::set_tmp_dh`]: struct.SslContextBuilder.html#method.set_tmp_dh - #[corresponds(SSL_set_tmp_dh)] - pub fn set_tmp_dh(&mut self, dh: &DhRef) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) } - } - - /// Like [`SslContextBuilder::set_tmp_dh_callback`]. - /// - /// [`SslContextBuilder::set_tmp_dh_callback`]: struct.SslContextBuilder.html#method.set_tmp_dh_callback - #[corresponds(SSL_set_tmp_dh_callback)] - pub fn set_tmp_dh_callback(&mut self, callback: F) - where - F: Fn(&mut SslRef, bool, u32) -> Result, ErrorStack> + 'static + Sync + Send, - { - unsafe { - // this needs to be in an Arc since the callback can register a new callback! - self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback)); - #[cfg(any(boringssl, awslc))] - ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::)); - #[cfg(not(any(boringssl, awslc)))] - ffi::SSL_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh_ssl::)); - } - } - - /// Like [`SslContextBuilder::set_tmp_ecdh`]. - /// - /// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.set_tmp_ecdh - #[corresponds(SSL_set_tmp_ecdh)] - pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) } - } - - /// Like [`SslContextBuilder::set_tmp_ecdh_callback`]. - /// - /// Requires OpenSSL 1.0.2. - #[corresponds(SSL_set_tmp_ecdh_callback)] - #[cfg(all(ossl102, not(ossl110)))] - #[deprecated(note = "this function leaks memory and does not exist on newer OpenSSL versions")] - pub fn set_tmp_ecdh_callback(&mut self, callback: F) - where - F: Fn(&mut SslRef, bool, u32) -> Result, ErrorStack> + 'static + Sync + Send, - { - unsafe { - // this needs to be in an Arc since the callback can register a new callback! - self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback)); - ffi::SSL_set_tmp_ecdh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_ecdh_ssl::)); - } - } - - /// Like [`SslContextBuilder::set_ecdh_auto`]. - /// - /// Requires OpenSSL 1.0.2 or LibreSSL. - /// - /// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.set_tmp_ecdh - #[corresponds(SSL_set_ecdh_auto)] - #[cfg(any(all(ossl102, not(ossl110)), libressl))] - pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) } - } - - /// Like [`SslContextBuilder::set_alpn_protos`]. - /// - /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer. - /// - /// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos - #[corresponds(SSL_set_alpn_protos)] - pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> { - unsafe { - assert!(protocols.len() <= c_uint::MAX as usize); - let r = - ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _); - // fun fact, SSL_set_alpn_protos has a reversed return code D: - if r == 0 { - Ok(()) - } else { - Err(ErrorStack::get()) - } - } - } - - /// Returns the current cipher if the session is active. - #[corresponds(SSL_get_current_cipher)] - pub fn current_cipher(&self) -> Option<&SslCipherRef> { - unsafe { - let ptr = ffi::SSL_get_current_cipher(self.as_ptr()); - - SslCipherRef::from_const_ptr_opt(ptr) - } - } - - /// Returns a short string describing the state of the session. - #[corresponds(SSL_state_string)] - pub fn state_string(&self) -> &'static str { - let state = unsafe { - let ptr = ffi::SSL_state_string(self.as_ptr()); - CStr::from_ptr(ptr as *const _) - }; - - str::from_utf8(state.to_bytes()).unwrap() - } - - /// Returns a longer string describing the state of the session. - #[corresponds(SSL_state_string_long)] - pub fn state_string_long(&self) -> &'static str { - let state = unsafe { - let ptr = ffi::SSL_state_string_long(self.as_ptr()); - CStr::from_ptr(ptr as *const _) - }; - - str::from_utf8(state.to_bytes()).unwrap() - } - - /// Sets the host name to be sent to the server for Server Name Indication (SNI). - /// - /// It has no effect for a server-side connection. - #[corresponds(SSL_set_tlsext_host_name)] - pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> { - let cstr = CString::new(hostname).unwrap(); - unsafe { - cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int) - .map(|_| ()) - } - } - - /// Returns the peer's certificate, if present. - #[corresponds(SSL_get_peer_certificate)] - pub fn peer_certificate(&self) -> Option { - unsafe { - let ptr = SSL_get1_peer_certificate(self.as_ptr()); - X509::from_ptr_opt(ptr) - } - } - - /// Returns the certificate chain of the peer, if present. - /// - /// On the client side, the chain includes the leaf certificate, but on the server side it does - /// not. Fun! - #[corresponds(SSL_get_peer_cert_chain)] - pub fn peer_cert_chain(&self) -> Option<&StackRef> { - unsafe { - let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr()); - StackRef::from_const_ptr_opt(ptr) - } - } - - /// Returns the verified certificate chain of the peer, including the leaf certificate. - /// - /// If verification was not successful (i.e. [`verify_result`] does not return - /// [`X509VerifyResult::OK`]), this chain may be incomplete or invalid. - /// - /// Requires OpenSSL 1.1.0 or newer. - /// - /// [`verify_result`]: #method.verify_result - /// [`X509VerifyResult::OK`]: ../x509/struct.X509VerifyResult.html#associatedconstant.OK - #[corresponds(SSL_get0_verified_chain)] - #[cfg(ossl110)] - pub fn verified_chain(&self) -> Option<&StackRef> { - unsafe { - let ptr = ffi::SSL_get0_verified_chain(self.as_ptr()); - StackRef::from_const_ptr_opt(ptr) - } - } - - /// Like [`SslContext::certificate`]. - #[corresponds(SSL_get_certificate)] - pub fn certificate(&self) -> Option<&X509Ref> { - unsafe { - let ptr = ffi::SSL_get_certificate(self.as_ptr()); - X509Ref::from_const_ptr_opt(ptr) - } - } - - /// Like [`SslContext::private_key`]. - /// - /// [`SslContext::private_key`]: struct.SslContext.html#method.private_key - #[corresponds(SSL_get_privatekey)] - pub fn private_key(&self) -> Option<&PKeyRef> { - unsafe { - let ptr = ffi::SSL_get_privatekey(self.as_ptr()); - PKeyRef::from_const_ptr_opt(ptr) - } - } - - #[deprecated(since = "0.10.5", note = "renamed to `version_str`")] - pub fn version(&self) -> &str { - self.version_str() - } - - /// Returns the protocol version of the session. - #[corresponds(SSL_version)] - pub fn version2(&self) -> Option { - unsafe { - let r = ffi::SSL_version(self.as_ptr()); - if r == 0 { - None - } else { - Some(SslVersion(r)) - } - } - } - - /// Returns a string describing the protocol version of the session. - #[corresponds(SSL_get_version)] - pub fn version_str(&self) -> &'static str { - let version = unsafe { - let ptr = ffi::SSL_get_version(self.as_ptr()); - CStr::from_ptr(ptr as *const _) - }; - - str::from_utf8(version.to_bytes()).unwrap() - } - - /// Returns the protocol selected via Application Layer Protocol Negotiation (ALPN). - /// - /// The protocol's name is returned is an opaque sequence of bytes. It is up to the client - /// to interpret it. - /// - /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer. - #[corresponds(SSL_get0_alpn_selected)] - pub fn selected_alpn_protocol(&self) -> Option<&[u8]> { - unsafe { - let mut data: *const c_uchar = ptr::null(); - let mut len: c_uint = 0; - // Get the negotiated protocol from the SSL instance. - // `data` will point at a `c_uchar` array; `len` will contain the length of this array. - ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len); - - if data.is_null() { - None - } else { - Some(util::from_raw_parts(data, len as usize)) - } - } - } - - /// Enables the DTLS extension "use_srtp" as defined in RFC5764. - #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))] - #[corresponds(SSL_set_tlsext_use_srtp)] - pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> { - unsafe { - let cstr = CString::new(protocols).unwrap(); - - let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr()); - // fun fact, set_tlsext_use_srtp has a reversed return code D: - if r == 0 { - Ok(()) - } else { - Err(ErrorStack::get()) - } - } - } - - /// Gets all SRTP profiles that are enabled for handshake via set_tlsext_use_srtp - /// - /// DTLS extension "use_srtp" as defined in RFC5764 has to be enabled. - #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))] - #[corresponds(SSL_get_srtp_profiles)] - pub fn srtp_profiles(&self) -> Option<&StackRef> { - unsafe { - let chain = ffi::SSL_get_srtp_profiles(self.as_ptr()); - - StackRef::from_const_ptr_opt(chain) - } - } - - /// Gets the SRTP profile selected by handshake. - /// - /// DTLS extension "use_srtp" as defined in RFC5764 has to be enabled. - #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))] - #[corresponds(SSL_get_selected_srtp_profile)] - pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> { - unsafe { - let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr()); - - SrtpProtectionProfileRef::from_const_ptr_opt(profile) - } - } - - /// Returns the number of bytes remaining in the currently processed TLS record. - /// - /// If this is greater than 0, the next call to `read` will not call down to the underlying - /// stream. - #[corresponds(SSL_pending)] - pub fn pending(&self) -> usize { - unsafe { ffi::SSL_pending(self.as_ptr()) as usize } - } - - /// Returns the servername sent by the client via Server Name Indication (SNI). - /// - /// It is only useful on the server side. - /// - /// # Note - /// - /// While the SNI specification requires that servernames be valid domain names (and therefore - /// ASCII), OpenSSL does not enforce this restriction. If the servername provided by the client - /// is not valid UTF-8, this function will return `None`. The `servername_raw` method returns - /// the raw bytes and does not have this restriction. - /// - /// [`SSL_get_servername`]: https://docs.openssl.org/master/man3/SSL_get_servername/ - #[corresponds(SSL_get_servername)] - // FIXME maybe rethink in 0.11? - pub fn servername(&self, type_: NameType) -> Option<&str> { - self.servername_raw(type_) - .and_then(|b| str::from_utf8(b).ok()) - } - - /// Returns the servername sent by the client via Server Name Indication (SNI). - /// - /// It is only useful on the server side. - /// - /// # Note - /// - /// Unlike `servername`, this method does not require the name be valid UTF-8. - #[corresponds(SSL_get_servername)] - pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> { - unsafe { - let name = ffi::SSL_get_servername(self.as_ptr(), type_.0); - if name.is_null() { - None - } else { - Some(CStr::from_ptr(name as *const _).to_bytes()) - } - } - } - - /// Changes the context corresponding to the current connection. - /// - /// It is most commonly used in the Server Name Indication (SNI) callback. - #[corresponds(SSL_set_SSL_CTX)] - pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> { - unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) } - } - - /// Returns the context corresponding to the current connection. - #[corresponds(SSL_get_SSL_CTX)] - pub fn ssl_context(&self) -> &SslContextRef { - unsafe { - let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr()); - SslContextRef::from_ptr(ssl_ctx) - } - } - - /// Returns a mutable reference to the X509 verification configuration. - /// - /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer. - #[corresponds(SSL_get0_param)] - pub fn param_mut(&mut self) -> &mut X509VerifyParamRef { - unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) } - } - - /// Returns the certificate verification result. - #[corresponds(SSL_get_verify_result)] - pub fn verify_result(&self) -> X509VerifyResult { - unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) } - } - - /// Returns a shared reference to the SSL session. - #[corresponds(SSL_get_session)] - pub fn session(&self) -> Option<&SslSessionRef> { - unsafe { - let p = ffi::SSL_get_session(self.as_ptr()); - SslSessionRef::from_const_ptr_opt(p) - } - } - - /// Copies the `client_random` value sent by the client in the TLS handshake into a buffer. - /// - /// Returns the number of bytes copied, or if the buffer is empty, the size of the `client_random` - /// value. - /// - /// Requires LibreSSL or OpenSSL 1.1.0 or newer. - #[corresponds(SSL_get_client_random)] - #[cfg(any(ossl110, libressl))] - pub fn client_random(&self, buf: &mut [u8]) -> usize { - unsafe { - ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len()) - } - } - - /// Copies the `server_random` value sent by the server in the TLS handshake into a buffer. - /// - /// Returns the number of bytes copied, or if the buffer is empty, the size of the `server_random` - /// value. - /// - /// Requires LibreSSL or OpenSSL 1.1.0 or newer. - #[corresponds(SSL_get_server_random)] - #[cfg(any(ossl110, libressl))] - pub fn server_random(&self, buf: &mut [u8]) -> usize { - unsafe { - ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len()) - } - } - - /// Derives keying material for application use in accordance to RFC 5705. - #[corresponds(SSL_export_keying_material)] - pub fn export_keying_material( - &self, - out: &mut [u8], - label: &str, - context: Option<&[u8]>, - ) -> Result<(), ErrorStack> { - unsafe { - let (context, contextlen, use_context) = match context { - Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1), - None => (ptr::null(), 0, 0), - }; - cvt(ffi::SSL_export_keying_material( - self.as_ptr(), - out.as_mut_ptr() as *mut c_uchar, - out.len(), - label.as_ptr() as *const c_char, - label.len(), - context, - contextlen, - use_context, - )) - .map(|_| ()) - } - } - - /// Derives keying material for application use in accordance to RFC 5705. - /// - /// This function is only usable with TLSv1.3, wherein there is no distinction between an empty context and no - /// context. Therefore, unlike `export_keying_material`, `context` must always be supplied. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_export_keying_material_early)] - #[cfg(ossl111)] - pub fn export_keying_material_early( - &self, - out: &mut [u8], - label: &str, - context: &[u8], - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::SSL_export_keying_material_early( - self.as_ptr(), - out.as_mut_ptr() as *mut c_uchar, - out.len(), - label.as_ptr() as *const c_char, - label.len(), - context.as_ptr() as *const c_uchar, - context.len(), - )) - .map(|_| ()) - } - } - - /// Sets the session to be used. - /// - /// This should be called before the handshake to attempt to reuse a previously established - /// session. If the server is not willing to reuse the session, a new one will be transparently - /// negotiated. - /// - /// # Safety - /// - /// The caller of this method is responsible for ensuring that the session is associated - /// with the same `SslContext` as this `Ssl`. - #[corresponds(SSL_set_session)] - pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> { - cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ()) - } - - /// Determines if the session provided to `set_session` was successfully reused. - #[corresponds(SSL_session_reused)] - pub fn session_reused(&self) -> bool { - unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 } - } - - /// Sets the status response a client wishes the server to reply with. - #[corresponds(SSL_set_tlsext_status_type)] - pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ()) - } - } - - /// Determines if current session used Extended Master Secret - /// - /// Returns `None` if the handshake is still in-progress. - #[corresponds(SSL_get_extms_support)] - #[cfg(ossl110)] - pub fn extms_support(&self) -> Option { - unsafe { - match ffi::SSL_get_extms_support(self.as_ptr()) { - -1 => None, - ret => Some(ret != 0), - } - } - } - - /// Returns the server's OCSP response, if present. - #[corresponds(SSL_get_tlsext_status_ocsp_resp)] - #[cfg(not(any(boringssl, awslc)))] - pub fn ocsp_status(&self) -> Option<&[u8]> { - unsafe { - let mut p = ptr::null_mut(); - let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p); - - if len < 0 { - None - } else { - Some(util::from_raw_parts(p as *const u8, len as usize)) - } - } - } - - /// Sets the OCSP response to be returned to the client. - #[corresponds(SSL_set_tlsext_status_oscp_resp)] - #[cfg(not(any(boringssl, awslc)))] - pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> { - unsafe { - assert!(response.len() <= c_int::MAX as usize); - let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?; - ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len()); - cvt(ffi::SSL_set_tlsext_status_ocsp_resp( - self.as_ptr(), - p as *mut c_uchar, - response.len() as c_long, - ) as c_int) - .map(|_| ()) - .map_err(|e| { - ffi::OPENSSL_free(p); - e - }) - } - } - - /// Determines if this `Ssl` is configured for server-side or client-side use. - #[corresponds(SSL_is_server)] - pub fn is_server(&self) -> bool { - unsafe { SSL_is_server(self.as_ptr()) != 0 } - } - - /// Sets the extra data at the specified index. - /// - /// This can be used to provide data to callbacks registered with the context. Use the - /// `Ssl::new_ex_index` method to create an `Index`. - // FIXME should return a result - #[corresponds(SSL_set_ex_data)] - pub fn set_ex_data(&mut self, index: Index, data: T) { - match self.ex_data_mut(index) { - Some(v) => *v = data, - None => unsafe { - let data = Box::new(data); - ffi::SSL_set_ex_data( - self.as_ptr(), - index.as_raw(), - Box::into_raw(data) as *mut c_void, - ); - }, - } - } - - /// Returns a reference to the extra data at the specified index. - #[corresponds(SSL_get_ex_data)] - pub fn ex_data(&self, index: Index) -> Option<&T> { - unsafe { - let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw()); - if data.is_null() { - None - } else { - Some(&*(data as *const T)) - } - } - } - - /// Returns a mutable reference to the extra data at the specified index. - #[corresponds(SSL_get_ex_data)] - pub fn ex_data_mut(&mut self, index: Index) -> Option<&mut T> { - unsafe { - let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw()); - if data.is_null() { - None - } else { - Some(&mut *(data as *mut T)) - } - } - } - - /// Sets the maximum amount of early data that will be accepted on this connection. - /// - /// Requires OpenSSL 1.1.1 or newer or LibreSSL. - #[corresponds(SSL_set_max_early_data)] - #[cfg(any(ossl111, libressl))] - pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> { - if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 { - Ok(()) - } else { - Err(ErrorStack::get()) - } - } - - /// Gets the maximum amount of early data that can be sent on this connection. - /// - /// Requires OpenSSL 1.1.1 or newer or LibreSSL. - #[corresponds(SSL_get_max_early_data)] - #[cfg(any(ossl111, libressl))] - pub fn max_early_data(&self) -> u32 { - unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) } - } - - /// Copies the contents of the last Finished message sent to the peer into the provided buffer. - /// - /// The total size of the message is returned, so this can be used to determine the size of the - /// buffer required. - #[corresponds(SSL_get_finished)] - pub fn finished(&self, buf: &mut [u8]) -> usize { - unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) } - } - - /// Copies the contents of the last Finished message received from the peer into the provided - /// buffer. - /// - /// The total size of the message is returned, so this can be used to determine the size of the - /// buffer required. - #[corresponds(SSL_get_peer_finished)] - pub fn peer_finished(&self, buf: &mut [u8]) -> usize { - unsafe { - ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) - } - } - - /// Determines if the initial handshake has been completed. - #[corresponds(SSL_is_init_finished)] - #[cfg(ossl110)] - pub fn is_init_finished(&self) -> bool { - unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 } - } - - /// Determines if the client's hello message is in the SSLv2 format. - /// - /// This can only be used inside of the client hello callback. Otherwise, `false` is returned. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_client_hello_isv2)] - #[cfg(ossl111)] - pub fn client_hello_isv2(&self) -> bool { - unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 } - } - - /// Returns the legacy version field of the client's hello message. - /// - /// This can only be used inside of the client hello callback. Otherwise, `None` is returned. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_client_hello_get0_legacy_version)] - #[cfg(ossl111)] - pub fn client_hello_legacy_version(&self) -> Option { - unsafe { - let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr()); - if version == 0 { - None - } else { - Some(SslVersion(version as c_int)) - } - } - } - - /// Returns the random field of the client's hello message. - /// - /// This can only be used inside of the client hello callback. Otherwise, `None` is returned. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_client_hello_get0_random)] - #[cfg(ossl111)] - pub fn client_hello_random(&self) -> Option<&[u8]> { - unsafe { - let mut ptr = ptr::null(); - let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr); - if len == 0 { - None - } else { - Some(util::from_raw_parts(ptr, len)) - } - } - } - - /// Returns the session ID field of the client's hello message. - /// - /// This can only be used inside of the client hello callback. Otherwise, `None` is returned. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_client_hello_get0_session_id)] - #[cfg(ossl111)] - pub fn client_hello_session_id(&self) -> Option<&[u8]> { - unsafe { - let mut ptr = ptr::null(); - let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr); - if len == 0 { - None - } else { - Some(util::from_raw_parts(ptr, len)) - } - } - } - - /// Returns the ciphers field of the client's hello message. - /// - /// This can only be used inside of the client hello callback. Otherwise, `None` is returned. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_client_hello_get0_ciphers)] - #[cfg(ossl111)] - pub fn client_hello_ciphers(&self) -> Option<&[u8]> { - unsafe { - let mut ptr = ptr::null(); - let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr); - if len == 0 { - None - } else { - Some(util::from_raw_parts(ptr, len)) - } - } - } - - /// Decodes a slice of wire-format cipher suite specification bytes. Unsupported cipher suites - /// are ignored. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_bytes_to_cipher_list)] - #[cfg(ossl111)] - pub fn bytes_to_cipher_list( - &self, - bytes: &[u8], - isv2format: bool, - ) -> Result { - unsafe { - let ptr = bytes.as_ptr(); - let len = bytes.len(); - let mut sk = ptr::null_mut(); - let mut scsvs = ptr::null_mut(); - let res = ffi::SSL_bytes_to_cipher_list( - self.as_ptr(), - ptr, - len, - isv2format as c_int, - &mut sk, - &mut scsvs, - ); - if res == 1 { - Ok(CipherLists { - suites: Stack::from_ptr(sk), - signalling_suites: Stack::from_ptr(scsvs), - }) - } else { - Err(ErrorStack::get()) - } - } - } - - /// Returns the compression methods field of the client's hello message. - /// - /// This can only be used inside of the client hello callback. Otherwise, `None` is returned. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_client_hello_get0_compression_methods)] - #[cfg(ossl111)] - pub fn client_hello_compression_methods(&self) -> Option<&[u8]> { - unsafe { - let mut ptr = ptr::null(); - let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr); - if len == 0 { - None - } else { - Some(util::from_raw_parts(ptr, len)) - } - } - } - - /// Sets the MTU used for DTLS connections. - #[corresponds(SSL_set_mtu)] - pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) } - } - - /// Returns the PSK identity hint used during connection setup. - /// - /// May return `None` if no PSK identity hint was used during the connection setup. - #[corresponds(SSL_get_psk_identity_hint)] - #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] - pub fn psk_identity_hint(&self) -> Option<&[u8]> { - unsafe { - let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr()); - if ptr.is_null() { - None - } else { - Some(CStr::from_ptr(ptr).to_bytes()) - } - } - } - - /// Returns the PSK identity used during connection setup. - #[corresponds(SSL_get_psk_identity)] - #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] - pub fn psk_identity(&self) -> Option<&[u8]> { - unsafe { - let ptr = ffi::SSL_get_psk_identity(self.as_ptr()); - if ptr.is_null() { - None - } else { - Some(CStr::from_ptr(ptr).to_bytes()) - } - } - } - - #[corresponds(SSL_add0_chain_cert)] - #[cfg(ossl102)] - pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?; - mem::forget(chain); - } - Ok(()) - } - - /// Sets a new default TLS/SSL method for SSL objects - #[cfg(not(any(boringssl, awslc)))] - pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?; - }; - Ok(()) - } - - /// Loads the private key from a file. - #[corresponds(SSL_use_Private_Key_file)] - pub fn set_private_key_file>( - &mut self, - path: P, - ssl_file_type: SslFiletype, - ) -> Result<(), ErrorStack> { - let p = path.as_ref().as_os_str().to_str().unwrap(); - let key_file = CString::new(p).unwrap(); - unsafe { - cvt(ffi::SSL_use_PrivateKey_file( - self.as_ptr(), - key_file.as_ptr(), - ssl_file_type.as_raw(), - ))?; - }; - Ok(()) - } - - /// Sets the private key. - #[corresponds(SSL_use_PrivateKey)] - pub fn set_private_key(&mut self, pkey: &PKeyRef) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?; - }; - Ok(()) - } - - /// Sets the certificate - #[corresponds(SSL_use_certificate)] - pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?; - }; - Ok(()) - } - - /// Loads a certificate chain from a file. - /// - /// The file should contain a sequence of PEM-formatted certificates, the first being the leaf - /// certificate, and the remainder forming the chain of certificates up to and including the - /// trusted root certificate. - #[corresponds(SSL_use_certificate_chain_file)] - #[cfg(any(ossl110, libressl))] - pub fn set_certificate_chain_file>( - &mut self, - path: P, - ) -> Result<(), ErrorStack> { - let p = path.as_ref().as_os_str().to_str().unwrap(); - let cert_file = CString::new(p).unwrap(); - unsafe { - cvt(ffi::SSL_use_certificate_chain_file( - self.as_ptr(), - cert_file.as_ptr(), - ))?; - }; - Ok(()) - } - - /// Sets ca certificate that client trusted - #[corresponds(SSL_add_client_CA)] - pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?; - }; - Ok(()) - } - - // Sets the list of CAs sent to the client when requesting a client certificate for the chosen ssl - #[corresponds(SSL_set_client_CA_list)] - pub fn set_client_ca_list(&mut self, list: Stack) { - unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) } - mem::forget(list); - } - - /// Sets the minimum supported protocol version. - /// - /// A value of `None` will enable protocol versions down to the lowest version supported by - /// OpenSSL. - /// - /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.1.0 or newer. - #[corresponds(SSL_set_min_proto_version)] - #[cfg(any(ossl110, libressl, boringssl, awslc))] - pub fn set_min_proto_version(&mut self, version: Option) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::SSL_set_min_proto_version( - self.as_ptr(), - version.map_or(0, |v| v.0 as _), - )) - .map(|_| ()) - } - } - - /// Sets the maximum supported protocol version. - /// - /// A value of `None` will enable protocol versions up to the highest version supported by - /// OpenSSL. - /// - /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.1.0 or newer. - #[corresponds(SSL_set_max_proto_version)] - #[cfg(any(ossl110, libressl, boringssl, awslc))] - pub fn set_max_proto_version(&mut self, version: Option) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::SSL_set_max_proto_version( - self.as_ptr(), - version.map_or(0, |v| v.0 as _), - )) - .map(|_| ()) - } - } - - /// Sets the list of supported ciphers for the TLSv1.3 protocol. - /// - /// The `set_cipher_list` method controls the cipher suites for protocols before TLSv1.3. - /// - /// The format consists of TLSv1.3 cipher suite names separated by `:` characters in order of - /// preference. - /// - /// Requires OpenSSL 1.1.1 or newer or LibreSSL. - #[corresponds(SSL_set_ciphersuites)] - #[cfg(any(ossl111, libressl))] - pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { - let cipher_list = CString::new(cipher_list).unwrap(); - unsafe { - cvt(ffi::SSL_set_ciphersuites( - self.as_ptr(), - cipher_list.as_ptr() as *const _, - )) - .map(|_| ()) - } - } - - /// Sets the list of supported ciphers for protocols before TLSv1.3. - /// - /// The `set_ciphersuites` method controls the cipher suites for TLSv1.3. - /// - /// See [`ciphers`] for details on the format. - /// - /// [`ciphers`]: https://docs.openssl.org/master/man1/ciphers/ - #[corresponds(SSL_set_cipher_list)] - pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { - let cipher_list = CString::new(cipher_list).unwrap(); - unsafe { - cvt(ffi::SSL_set_cipher_list( - self.as_ptr(), - cipher_list.as_ptr() as *const _, - )) - .map(|_| ()) - } - } - - /// Set the certificate store used for certificate verification - #[corresponds(SSL_set_cert_store)] - #[cfg(ossl102)] - pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?; - mem::forget(cert_store); - Ok(()) - } - } - - /// Sets the number of TLS 1.3 session tickets that will be sent to a client after a full - /// handshake. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_set_num_tickets)] - #[cfg(ossl111)] - pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) } - } - - /// Gets the number of TLS 1.3 session tickets that will be sent to a client after a full - /// handshake. - /// - /// Requires OpenSSL 1.1.1 or newer. - #[corresponds(SSL_get_num_tickets)] - #[cfg(ossl111)] - pub fn num_tickets(&self) -> usize { - unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) } - } - - /// Set the context's security level to a value between 0 and 5, inclusive. - /// A security value of 0 allows allows all parameters and algorithms. - /// - /// Requires OpenSSL 1.1.0 or newer. - #[corresponds(SSL_set_security_level)] - #[cfg(any(ossl110, libressl360))] - pub fn set_security_level(&mut self, level: u32) { - unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) } - } - - /// Get the connection's security level, which controls the allowed parameters - /// and algorithms. - /// - /// Requires OpenSSL 1.1.0 or newer. - #[corresponds(SSL_get_security_level)] - #[cfg(any(ossl110, libressl360))] - pub fn security_level(&self) -> u32 { - unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 } - } - - /// Get the temporary key provided by the peer that is used during key - /// exchange. - // We use an owned value because EVP_KEY free need to be called when it is - // dropped - #[corresponds(SSL_get_peer_tmp_key)] - #[cfg(ossl300)] - pub fn peer_tmp_key(&self) -> Result, ErrorStack> { - unsafe { - let mut key = ptr::null_mut(); - match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) { - Ok(_) => Ok(PKey::::from_ptr(key)), - Err(e) => Err(e), - } - } - } - - /// Returns the temporary key from the local end of the connection that is - /// used during key exchange. - // We use an owned value because EVP_KEY free need to be called when it is - // dropped - #[corresponds(SSL_get_tmp_key)] - #[cfg(ossl300)] - pub fn tmp_key(&self) -> Result, ErrorStack> { - unsafe { - let mut key = ptr::null_mut(); - match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) { - Ok(_) => Ok(PKey::::from_ptr(key)), - Err(e) => Err(e), - } - } - } -} - -/// An SSL stream midway through the handshake process. -#[derive(Debug)] -pub struct MidHandshakeSslStream { - stream: SslStream, - error: Error, -} - -impl MidHandshakeSslStream { - /// Returns a shared reference to the inner stream. - pub fn get_ref(&self) -> &S { - self.stream.get_ref() - } - - /// Returns a mutable reference to the inner stream. - pub fn get_mut(&mut self) -> &mut S { - self.stream.get_mut() - } - - /// Returns a shared reference to the `Ssl` of the stream. - pub fn ssl(&self) -> &SslRef { - self.stream.ssl() - } - - /// Returns the underlying error which interrupted this handshake. - pub fn error(&self) -> &Error { - &self.error - } - - /// Consumes `self`, returning its error. - pub fn into_error(self) -> Error { - self.error - } -} - -impl MidHandshakeSslStream -where - S: Read + Write, -{ - /// Restarts the handshake process. - /// - #[corresponds(SSL_do_handshake)] - pub fn handshake(mut self) -> Result, HandshakeError> { - match self.stream.do_handshake() { - Ok(()) => Ok(self.stream), - Err(error) => { - self.error = error; - match self.error.code() { - ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => { - Err(HandshakeError::WouldBlock(self)) - } - _ => Err(HandshakeError::Failure(self)), - } - } - } - } -} - -/// A TLS session over a stream. -pub struct SslStream { - ssl: ManuallyDrop, - method: ManuallyDrop, - _p: PhantomData, -} - -impl Drop for SslStream { - fn drop(&mut self) { - // ssl holds a reference to method internally so it has to drop first - unsafe { - ManuallyDrop::drop(&mut self.ssl); - ManuallyDrop::drop(&mut self.method); - } - } -} - -impl fmt::Debug for SslStream -where - S: fmt::Debug, -{ - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_struct("SslStream") - .field("stream", &self.get_ref()) - .field("ssl", &self.ssl()) - .finish() - } -} - -impl SslStream { - /// Creates a new `SslStream`. - /// - /// This function performs no IO; the stream will not have performed any part of the handshake - /// with the peer. If the `Ssl` was configured with [`SslRef::set_connect_state`] or - /// [`SslRef::set_accept_state`], the handshake can be performed automatically during the first - /// call to read or write. Otherwise the `connect` and `accept` methods can be used to - /// explicitly perform the handshake. - #[corresponds(SSL_set_bio)] - pub fn new(ssl: Ssl, stream: S) -> Result { - let (bio, method) = bio::new(stream)?; - unsafe { - ffi::SSL_set_bio(ssl.as_ptr(), bio, bio); - } - - Ok(SslStream { - ssl: ManuallyDrop::new(ssl), - method: ManuallyDrop::new(method), - _p: PhantomData, - }) - } - - /// Constructs an `SslStream` from a pointer to the underlying OpenSSL `SSL` struct. - /// - /// This is useful if the handshake has already been completed elsewhere. - /// - /// # Safety - /// - /// The caller must ensure the pointer is valid. - #[deprecated( - since = "0.10.32", - note = "use Ssl::from_ptr and SslStream::new instead" - )] - pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self { - let ssl = Ssl::from_ptr(ssl); - Self::new(ssl, stream).unwrap() - } - - /// Read application data transmitted by a client before handshake completion. - /// - /// Useful for reducing latency, but vulnerable to replay attacks. Call - /// [`SslRef::set_accept_state`] first. - /// - /// Returns `Ok(0)` if all early data has been read. - /// - /// Requires OpenSSL 1.1.1 or newer or LibreSSL. - #[corresponds(SSL_read_early_data)] - #[cfg(any(ossl111, libressl))] - pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result { - let mut read = 0; - let ret = unsafe { - ffi::SSL_read_early_data( - self.ssl.as_ptr(), - buf.as_ptr() as *mut c_void, - buf.len(), - &mut read, - ) - }; - match ret { - ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)), - ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read), - ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0), - _ => unreachable!(), - } - } - - /// Send data to the server without blocking on handshake completion. - /// - /// Useful for reducing latency, but vulnerable to replay attacks. Call - /// [`SslRef::set_connect_state`] first. - /// - /// Requires OpenSSL 1.1.1 or newer or LibreSSL. - #[corresponds(SSL_write_early_data)] - #[cfg(any(ossl111, libressl))] - pub fn write_early_data(&mut self, buf: &[u8]) -> Result { - let mut written = 0; - let ret = unsafe { - ffi::SSL_write_early_data( - self.ssl.as_ptr(), - buf.as_ptr() as *const c_void, - buf.len(), - &mut written, - ) - }; - if ret > 0 { - Ok(written) - } else { - Err(self.make_error(ret)) - } - } - - /// Initiates a client-side TLS handshake. - /// - /// # Warning - /// - /// OpenSSL's default configuration is insecure. It is highly recommended to use - /// `SslConnector` rather than `Ssl` directly, as it manages that configuration. - #[corresponds(SSL_connect)] - pub fn connect(&mut self) -> Result<(), Error> { - let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) }; - if ret > 0 { - Ok(()) - } else { - Err(self.make_error(ret)) - } - } - - /// Initiates a server-side TLS handshake. - /// - /// # Warning - /// - /// OpenSSL's default configuration is insecure. It is highly recommended to use - /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration. - #[corresponds(SSL_accept)] - pub fn accept(&mut self) -> Result<(), Error> { - let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) }; - if ret > 0 { - Ok(()) - } else { - Err(self.make_error(ret)) - } - } - - /// Initiates the handshake. - /// - /// This will fail if `set_accept_state` or `set_connect_state` was not called first. - #[corresponds(SSL_do_handshake)] - pub fn do_handshake(&mut self) -> Result<(), Error> { - let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) }; - if ret > 0 { - Ok(()) - } else { - Err(self.make_error(ret)) - } - } - - /// Perform a stateless server-side handshake. - /// - /// Requires that cookie generation and verification callbacks were - /// set on the SSL context. - /// - /// Returns `Ok(true)` if a complete ClientHello containing a valid cookie - /// was read, in which case the handshake should be continued via - /// `accept`. If a HelloRetryRequest containing a fresh cookie was - /// transmitted, `Ok(false)` is returned instead. If the handshake cannot - /// proceed at all, `Err` is returned. - #[corresponds(SSL_stateless)] - #[cfg(ossl111)] - pub fn stateless(&mut self) -> Result { - match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } { - 1 => Ok(true), - 0 => Ok(false), - -1 => Err(ErrorStack::get()), - _ => unreachable!(), - } - } - - /// Like `read`, but takes a possibly-uninitialized slice. - /// - /// # Safety - /// - /// No portion of `buf` will be de-initialized by this method. If the method returns `Ok(n)`, - /// then the first `n` bytes of `buf` are guaranteed to be initialized. - #[corresponds(SSL_read_ex)] - pub fn read_uninit(&mut self, buf: &mut [MaybeUninit]) -> io::Result { - loop { - match self.ssl_read_uninit(buf) { - Ok(n) => return Ok(n), - Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0), - Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => { - return Ok(0); - } - Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {} - Err(e) => { - return Err(e - .into_io_error() - .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e))); - } - } - } - } - - /// Like `read`, but returns an `ssl::Error` rather than an `io::Error`. - /// - /// It is particularly useful with a non-blocking socket, where the error value will identify if - /// OpenSSL is waiting on read or write readiness. - #[corresponds(SSL_read_ex)] - pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result { - // SAFETY: `ssl_read_uninit` does not de-initialize the buffer. - unsafe { - self.ssl_read_uninit(util::from_raw_parts_mut( - buf.as_mut_ptr().cast::>(), - buf.len(), - )) - } - } - - /// Like `read_ssl`, but takes a possibly-uninitialized slice. - /// - /// # Safety - /// - /// No portion of `buf` will be de-initialized by this method. If the method returns `Ok(n)`, - /// then the first `n` bytes of `buf` are guaranteed to be initialized. - #[corresponds(SSL_read_ex)] - pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit]) -> Result { - cfg_if! { - if #[cfg(any(ossl111, libressl))] { - let mut readbytes = 0; - let ret = unsafe { - ffi::SSL_read_ex( - self.ssl().as_ptr(), - buf.as_mut_ptr().cast(), - buf.len(), - &mut readbytes, - ) - }; - - if ret > 0 { - Ok(readbytes) - } else { - Err(self.make_error(ret)) - } - } else { - if buf.is_empty() { - return Ok(0); - } - - let len = usize::min(c_int::MAX as usize, buf.len()) as c_int; - let ret = unsafe { - ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len) - }; - if ret > 0 { - Ok(ret as usize) - } else { - Err(self.make_error(ret)) - } - } - } - } - - /// Like `write`, but returns an `ssl::Error` rather than an `io::Error`. - /// - /// It is particularly useful with a non-blocking socket, where the error value will identify if - /// OpenSSL is waiting on read or write readiness. - #[corresponds(SSL_write_ex)] - pub fn ssl_write(&mut self, buf: &[u8]) -> Result { - cfg_if! { - if #[cfg(any(ossl111, libressl))] { - let mut written = 0; - let ret = unsafe { - ffi::SSL_write_ex( - self.ssl().as_ptr(), - buf.as_ptr().cast(), - buf.len(), - &mut written, - ) - }; - - if ret > 0 { - Ok(written) - } else { - Err(self.make_error(ret)) - } - } else { - if buf.is_empty() { - return Ok(0); - } - - let len = usize::min(c_int::MAX as usize, buf.len()) as c_int; - let ret = unsafe { - ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len) - }; - if ret > 0 { - Ok(ret as usize) - } else { - Err(self.make_error(ret)) - } - } - } - } - - /// Reads data from the stream, without removing it from the queue. - #[corresponds(SSL_peek_ex)] - pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result { - cfg_if! { - if #[cfg(any(ossl111, libressl))] { - let mut readbytes = 0; - let ret = unsafe { - ffi::SSL_peek_ex( - self.ssl().as_ptr(), - buf.as_mut_ptr().cast(), - buf.len(), - &mut readbytes, - ) - }; - - if ret > 0 { - Ok(readbytes) - } else { - Err(self.make_error(ret)) - } - } else { - if buf.is_empty() { - return Ok(0); - } - - let len = usize::min(c_int::MAX as usize, buf.len()) as c_int; - let ret = unsafe { - ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len) - }; - if ret > 0 { - Ok(ret as usize) - } else { - Err(self.make_error(ret)) - } - } - } - } - - /// Shuts down the session. - /// - /// The shutdown process consists of two steps. The first step sends a close notify message to - /// the peer, after which `ShutdownResult::Sent` is returned. The second step awaits the receipt - /// of a close notify message from the peer, after which `ShutdownResult::Received` is returned. - /// - /// While the connection may be closed after the first step, it is recommended to fully shut the - /// session down. In particular, it must be fully shut down if the connection is to be used for - /// further communication in the future. - #[corresponds(SSL_shutdown)] - pub fn shutdown(&mut self) -> Result { - match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } { - 0 => Ok(ShutdownResult::Sent), - 1 => Ok(ShutdownResult::Received), - n => Err(self.make_error(n)), - } - } - - /// Returns the session's shutdown state. - #[corresponds(SSL_get_shutdown)] - pub fn get_shutdown(&mut self) -> ShutdownState { - unsafe { - let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr()); - ShutdownState::from_bits_retain(bits) - } - } - - /// Sets the session's shutdown state. - /// - /// This can be used to tell OpenSSL that the session should be cached even if a full two-way - /// shutdown was not completed. - #[corresponds(SSL_set_shutdown)] - pub fn set_shutdown(&mut self, state: ShutdownState) { - unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) } - } -} - -impl SslStream { - fn make_error(&mut self, ret: c_int) -> Error { - self.check_panic(); - - let code = self.ssl.get_error(ret); - - let cause = match code { - ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())), - ErrorCode::SYSCALL => { - let errs = ErrorStack::get(); - if errs.errors().is_empty() { - self.get_bio_error().map(InnerError::Io) - } else { - Some(InnerError::Ssl(errs)) - } - } - ErrorCode::ZERO_RETURN => None, - ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => { - self.get_bio_error().map(InnerError::Io) - } - _ => None, - }; - - Error { code, cause } - } - - fn check_panic(&mut self) { - if let Some(err) = unsafe { bio::take_panic::(self.ssl.get_raw_rbio()) } { - resume_unwind(err) - } - } - - fn get_bio_error(&mut self) -> Option { - unsafe { bio::take_error::(self.ssl.get_raw_rbio()) } - } - - /// Returns a shared reference to the underlying stream. - pub fn get_ref(&self) -> &S { - unsafe { - let bio = self.ssl.get_raw_rbio(); - bio::get_ref(bio) - } - } - - /// Returns a mutable reference to the underlying stream. - /// - /// # Warning - /// - /// It is inadvisable to read from or write to the underlying stream as it - /// will most likely corrupt the SSL session. - pub fn get_mut(&mut self) -> &mut S { - unsafe { - let bio = self.ssl.get_raw_rbio(); - bio::get_mut(bio) - } - } - - /// Returns a shared reference to the `Ssl` object associated with this stream. - pub fn ssl(&self) -> &SslRef { - &self.ssl - } -} - -impl Read for SslStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - // SAFETY: `read_uninit` does not de-initialize the buffer - unsafe { - self.read_uninit(util::from_raw_parts_mut( - buf.as_mut_ptr().cast::>(), - buf.len(), - )) - } - } -} - -impl Write for SslStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - loop { - match self.ssl_write(buf) { - Ok(n) => return Ok(n), - Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {} - Err(e) => { - return Err(e - .into_io_error() - .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e))); - } - } - } - } - - fn flush(&mut self) -> io::Result<()> { - self.get_mut().flush() - } -} - -/// A partially constructed `SslStream`, useful for unusual handshakes. -#[deprecated( - since = "0.10.32", - note = "use the methods directly on Ssl/SslStream instead" -)] -pub struct SslStreamBuilder { - inner: SslStream, -} - -#[allow(deprecated)] -impl SslStreamBuilder -where - S: Read + Write, -{ - /// Begin creating an `SslStream` atop `stream` - pub fn new(ssl: Ssl, stream: S) -> Self { - Self { - inner: SslStream::new(ssl, stream).unwrap(), - } - } - - /// Perform a stateless server-side handshake - /// - /// Requires that cookie generation and verification callbacks were - /// set on the SSL context. - /// - /// Returns `Ok(true)` if a complete ClientHello containing a valid cookie - /// was read, in which case the handshake should be continued via - /// `accept`. If a HelloRetryRequest containing a fresh cookie was - /// transmitted, `Ok(false)` is returned instead. If the handshake cannot - /// proceed at all, `Err` is returned. - #[corresponds(SSL_stateless)] - #[cfg(ossl111)] - pub fn stateless(&mut self) -> Result { - match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } { - 1 => Ok(true), - 0 => Ok(false), - -1 => Err(ErrorStack::get()), - _ => unreachable!(), - } - } - - /// Configure as an outgoing stream from a client. - #[corresponds(SSL_set_connect_state)] - pub fn set_connect_state(&mut self) { - unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) } - } - - /// Configure as an incoming stream to a server. - #[corresponds(SSL_set_accept_state)] - pub fn set_accept_state(&mut self) { - unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) } - } - - /// See `Ssl::connect` - pub fn connect(mut self) -> Result, HandshakeError> { - match self.inner.connect() { - Ok(()) => Ok(self.inner), - Err(error) => match error.code() { - ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => { - Err(HandshakeError::WouldBlock(MidHandshakeSslStream { - stream: self.inner, - error, - })) - } - _ => Err(HandshakeError::Failure(MidHandshakeSslStream { - stream: self.inner, - error, - })), - }, - } - } - - /// See `Ssl::accept` - pub fn accept(mut self) -> Result, HandshakeError> { - match self.inner.accept() { - Ok(()) => Ok(self.inner), - Err(error) => match error.code() { - ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => { - Err(HandshakeError::WouldBlock(MidHandshakeSslStream { - stream: self.inner, - error, - })) - } - _ => Err(HandshakeError::Failure(MidHandshakeSslStream { - stream: self.inner, - error, - })), - }, - } - } - - /// Initiates the handshake. - /// - /// This will fail if `set_accept_state` or `set_connect_state` was not called first. - #[corresponds(SSL_do_handshake)] - pub fn handshake(mut self) -> Result, HandshakeError> { - match self.inner.do_handshake() { - Ok(()) => Ok(self.inner), - Err(error) => match error.code() { - ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => { - Err(HandshakeError::WouldBlock(MidHandshakeSslStream { - stream: self.inner, - error, - })) - } - _ => Err(HandshakeError::Failure(MidHandshakeSslStream { - stream: self.inner, - error, - })), - }, - } - } - - /// Read application data transmitted by a client before handshake - /// completion. - /// - /// Useful for reducing latency, but vulnerable to replay attacks. Call - /// `set_accept_state` first. - /// - /// Returns `Ok(0)` if all early data has been read. - /// - /// Requires OpenSSL 1.1.1 or newer or LibreSSL. - #[corresponds(SSL_read_early_data)] - #[cfg(any(ossl111, libressl))] - pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result { - self.inner.read_early_data(buf) - } - - /// Send data to the server without blocking on handshake completion. - /// - /// Useful for reducing latency, but vulnerable to replay attacks. Call - /// `set_connect_state` first. - /// - /// Requires OpenSSL 1.1.1 or newer or LibreSSL. - #[corresponds(SSL_write_early_data)] - #[cfg(any(ossl111, libressl))] - pub fn write_early_data(&mut self, buf: &[u8]) -> Result { - self.inner.write_early_data(buf) - } -} - -#[allow(deprecated)] -impl SslStreamBuilder { - /// Returns a shared reference to the underlying stream. - pub fn get_ref(&self) -> &S { - unsafe { - let bio = self.inner.ssl.get_raw_rbio(); - bio::get_ref(bio) - } - } - - /// Returns a mutable reference to the underlying stream. - /// - /// # Warning - /// - /// It is inadvisable to read from or write to the underlying stream as it - /// will most likely corrupt the SSL session. - pub fn get_mut(&mut self) -> &mut S { - unsafe { - let bio = self.inner.ssl.get_raw_rbio(); - bio::get_mut(bio) - } - } - - /// Returns a shared reference to the `Ssl` object associated with this builder. - pub fn ssl(&self) -> &SslRef { - &self.inner.ssl - } - - /// Set the DTLS MTU size. - /// - /// It will be ignored if the value is smaller than the minimum packet size - /// the DTLS protocol requires. - /// - /// # Panics - /// This function panics if the given mtu size can't be represented in a positive `c_long` range - #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")] - pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) { - unsafe { - let bio = self.inner.ssl.get_raw_rbio(); - bio::set_dtls_mtu_size::(bio, mtu_size); - } - } -} - -/// The result of a shutdown request. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum ShutdownResult { - /// A close notify message has been sent to the peer. - Sent, - - /// A close notify response message has been received from the peer. - Received, -} - -bitflags! { - /// The shutdown state of a session. - #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - #[repr(transparent)] - pub struct ShutdownState: c_int { - /// A close notify message has been sent to the peer. - const SENT = ffi::SSL_SENT_SHUTDOWN; - /// A close notify message has been received from the peer. - const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN; - } -} - -cfg_if! { - if #[cfg(any(boringssl, ossl110, libressl, awslc))] { - use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server}; - } else { - #[allow(bad_style)] - pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int { - ffi::CRYPTO_add_lock( - &mut (*ssl).references, - 1, - ffi::CRYPTO_LOCK_SSL_CTX, - "mod.rs\0".as_ptr() as *const _, - line!() as c_int, - ); - 0 - } - - #[allow(bad_style)] - pub unsafe fn SSL_SESSION_get_master_key( - session: *const ffi::SSL_SESSION, - out: *mut c_uchar, - mut outlen: usize, - ) -> usize { - if outlen == 0 { - return (*session).master_key_length as usize; - } - if outlen > (*session).master_key_length as usize { - outlen = (*session).master_key_length as usize; - } - ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen); - outlen - } - - #[allow(bad_style)] - pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int { - (*s).server - } - - #[allow(bad_style)] - pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int { - ffi::CRYPTO_add_lock( - &mut (*ses).references, - 1, - ffi::CRYPTO_LOCK_SSL_CTX, - "mod.rs\0".as_ptr() as *const _, - line!() as c_int, - ); - 0 - } - } -} - -cfg_if! { - if #[cfg(ossl300)] { - use ffi::SSL_get1_peer_certificate; - } else { - use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate; - } -} -cfg_if! { - if #[cfg(any(boringssl, ossl110, libressl, awslc))] { - use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method, DTLS_server_method, DTLS_client_method}; - } else { - use ffi::{ - SSLv23_method as TLS_method, DTLSv1_method as DTLS_method, SSLv23_client_method as TLS_client_method, - SSLv23_server_method as TLS_server_method, - }; - } -} -cfg_if! { - if #[cfg(ossl110)] { - unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int { - ffi::CRYPTO_get_ex_new_index( - ffi::CRYPTO_EX_INDEX_SSL_CTX, - 0, - ptr::null_mut(), - None, - None, - Some(f), - ) - } - - unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int { - ffi::CRYPTO_get_ex_new_index( - ffi::CRYPTO_EX_INDEX_SSL, - 0, - ptr::null_mut(), - None, - None, - Some(f), - ) - } - } else { - use std::sync::Once; - - unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int { - // hack around https://rt.openssl.org/Ticket/Display.html?id=3710&user=guest&pass=guest - static ONCE: Once = Once::new(); - ONCE.call_once(|| { - cfg_if! { - if #[cfg(not(any(boringssl, awslc)))] { - ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None); - } else { - ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None); - } - } - }); - - cfg_if! { - if #[cfg(not(any(boringssl, awslc)))] { - ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f)) - } else { - ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f) - } - } - } - - unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int { - // hack around https://rt.openssl.org/Ticket/Display.html?id=3710&user=guest&pass=guest - static ONCE: Once = Once::new(); - ONCE.call_once(|| { - #[cfg(not(any(boringssl, awslc)))] - ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None); - #[cfg(any(boringssl, awslc))] - ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None); - }); - - #[cfg(not(any(boringssl, awslc)))] - return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f)); - #[cfg(any(boringssl, awslc))] - return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f); - } - } -} diff --git a/patch/openssl/src/ssl/test/mod.rs b/patch/openssl/src/ssl/test/mod.rs deleted file mode 100644 index 9c83728a1d0b3..0000000000000 --- a/patch/openssl/src/ssl/test/mod.rs +++ /dev/null @@ -1,1703 +0,0 @@ -#![allow(unused_imports)] - -use std::env; -use std::fs::File; -use std::io::prelude::*; -use std::io::{self, BufReader}; -use std::iter; -use std::mem; -use std::net::UdpSocket; -use std::net::{SocketAddr, TcpListener, TcpStream}; -use std::path::Path; -use std::process::{Child, ChildStdin, Command, Stdio}; -use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; -use std::thread; -use std::time::Duration; - -use crate::dh::Dh; -use crate::error::ErrorStack; -use crate::hash::MessageDigest; -#[cfg(not(any(boringssl, awslc)))] -use crate::ocsp::{OcspResponse, OcspResponseStatus}; -use crate::pkey::{Id, PKey}; -use crate::srtp::SrtpProfileId; -use crate::ssl::test::server::Server; -#[cfg(any(ossl110, ossl111, libressl))] -use crate::ssl::SslVersion; -use crate::ssl::{self, NameType, SslConnectorBuilder}; -#[cfg(ossl111)] -use crate::ssl::{ClientHelloResponse, ExtensionContext}; -use crate::ssl::{ - Error, HandshakeError, MidHandshakeSslStream, ShutdownResult, ShutdownState, Ssl, SslAcceptor, - SslAcceptorBuilder, SslConnector, SslContext, SslContextBuilder, SslFiletype, SslMethod, - SslOptions, SslSessionCacheMode, SslStream, SslVerifyMode, StatusType, -}; -#[cfg(ossl102)] -use crate::x509::store::X509StoreBuilder; -#[cfg(ossl102)] -use crate::x509::verify::X509CheckFlags; -use crate::x509::{X509Name, X509StoreContext, X509VerifyResult, X509}; - -mod server; - -static ROOT_CERT: &[u8] = include_bytes!("../../../test/root-ca.pem"); -static CERT: &[u8] = include_bytes!("../../../test/cert.pem"); -static KEY: &[u8] = include_bytes!("../../../test/key.pem"); - -#[test] -fn verify_untrusted() { - let mut server = Server::builder(); - server.should_error(); - let server = server.build(); - - let mut client = server.client(); - client.ctx().set_verify(SslVerifyMode::PEER); - - client.connect_err(); -} - -#[test] -fn verify_trusted() { - let server = Server::builder().build(); - - let mut client = server.client(); - client.ctx().set_ca_file("test/root-ca.pem").unwrap(); - - client.connect(); -} - -#[test] -#[cfg(ossl102)] -fn verify_trusted_with_set_cert() { - let server = Server::builder().build(); - - let mut store = X509StoreBuilder::new().unwrap(); - let x509 = X509::from_pem(ROOT_CERT).unwrap(); - store.add_cert(x509).unwrap(); - - let mut client = server.client(); - client.ctx().set_verify(SslVerifyMode::PEER); - client.ctx().set_verify_cert_store(store.build()).unwrap(); - - client.connect(); -} - -#[test] -fn verify_untrusted_callback_override_ok() { - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let server = Server::builder().build(); - - let mut client = server.client(); - client - .ctx() - .set_verify_callback(SslVerifyMode::PEER, |_, x509| { - CALLED_BACK.store(true, Ordering::SeqCst); - assert!(x509.current_cert().is_some()); - true - }); - - client.connect(); - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -#[test] -fn verify_untrusted_callback_override_bad() { - let mut server = Server::builder(); - server.should_error(); - let server = server.build(); - - let mut client = server.client(); - client - .ctx() - .set_verify_callback(SslVerifyMode::PEER, |_, _| false); - - client.connect_err(); -} - -#[test] -fn verify_trusted_callback_override_ok() { - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let server = Server::builder().build(); - - let mut client = server.client(); - client.ctx().set_ca_file("test/root-ca.pem").unwrap(); - client - .ctx() - .set_verify_callback(SslVerifyMode::PEER, |_, x509| { - CALLED_BACK.store(true, Ordering::SeqCst); - assert!(x509.current_cert().is_some()); - true - }); - - client.connect(); - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -#[test] -fn verify_trusted_callback_override_bad() { - let mut server = Server::builder(); - server.should_error(); - let server = server.build(); - - let mut client = server.client(); - client.ctx().set_ca_file("test/root-ca.pem").unwrap(); - client - .ctx() - .set_verify_callback(SslVerifyMode::PEER, |_, _| false); - - client.connect_err(); -} - -#[test] -fn verify_callback_load_certs() { - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let server = Server::builder().build(); - - let mut client = server.client(); - client - .ctx() - .set_verify_callback(SslVerifyMode::PEER, |_, x509| { - CALLED_BACK.store(true, Ordering::SeqCst); - assert!(x509.current_cert().is_some()); - true - }); - - client.connect(); - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -#[test] -fn verify_trusted_get_error_ok() { - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let server = Server::builder().build(); - - let mut client = server.client(); - client.ctx().set_ca_file("test/root-ca.pem").unwrap(); - client - .ctx() - .set_verify_callback(SslVerifyMode::PEER, |_, x509| { - CALLED_BACK.store(true, Ordering::SeqCst); - assert_eq!(x509.error(), X509VerifyResult::OK); - true - }); - - client.connect(); - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -#[test] -fn verify_trusted_get_error_err() { - let mut server = Server::builder(); - server.should_error(); - let server = server.build(); - - let mut client = server.client(); - client - .ctx() - .set_verify_callback(SslVerifyMode::PEER, |_, x509| { - assert_ne!(x509.error(), X509VerifyResult::OK); - false - }); - - client.connect_err(); -} - -#[test] -fn verify_callback() { - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let server = Server::builder().build(); - - let mut client = server.client(); - let expected = "59172d9313e84459bcff27f967e79e6e9217e584"; - client - .ctx() - .set_verify_callback(SslVerifyMode::PEER, move |_, x509| { - CALLED_BACK.store(true, Ordering::SeqCst); - let cert = x509.current_cert().unwrap(); - let digest = cert.digest(MessageDigest::sha1()).unwrap(); - assert_eq!(hex::encode(digest), expected); - true - }); - - client.connect(); - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -#[test] -fn ssl_verify_callback() { - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let server = Server::builder().build(); - - let mut client = server.client().build().builder(); - let expected = "59172d9313e84459bcff27f967e79e6e9217e584"; - client - .ssl() - .set_verify_callback(SslVerifyMode::PEER, move |_, x509| { - CALLED_BACK.store(true, Ordering::SeqCst); - let cert = x509.current_cert().unwrap(); - let digest = cert.digest(MessageDigest::sha1()).unwrap(); - assert_eq!(hex::encode(digest), expected); - true - }); - - client.connect(); - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -#[test] -fn get_ctx_options() { - let ctx = SslContext::builder(SslMethod::tls()).unwrap(); - ctx.options(); -} - -#[test] -fn set_ctx_options() { - let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); - let opts = ctx.set_options(SslOptions::NO_TICKET); - assert!(opts.contains(SslOptions::NO_TICKET)); -} - -#[test] -#[cfg(not(any(boringssl, awslc)))] -fn clear_ctx_options() { - let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); - ctx.set_options(SslOptions::ALL); - let opts = ctx.clear_options(SslOptions::ALL); - assert!(!opts.contains(SslOptions::ALL)); -} - -#[test] -fn zero_length_buffers() { - let server = Server::builder().build(); - - let mut s = server.client().connect(); - assert_eq!(s.write(&[]).unwrap(), 0); - assert_eq!(s.read(&mut []).unwrap(), 0); -} - -#[test] -fn peer_certificate() { - let server = Server::builder().build(); - - let s = server.client().connect(); - let cert = s.ssl().peer_certificate().unwrap(); - let fingerprint = cert.digest(MessageDigest::sha1()).unwrap(); - assert_eq!( - hex::encode(fingerprint), - "59172d9313e84459bcff27f967e79e6e9217e584" - ); -} - -#[test] -fn pending() { - let mut server = Server::builder(); - server.io_cb(|mut s| s.write_all(&[0; 10]).unwrap()); - let server = server.build(); - - let mut s = server.client().connect(); - s.read_exact(&mut [0]).unwrap(); - - assert_eq!(s.ssl().pending(), 9); - assert_eq!(s.read(&mut [0; 10]).unwrap(), 9); -} - -#[test] -fn state() { - const EXPECTED_STATE_STRING_LONG: &str = "SSL negotiation finished successfully"; - - let server = Server::builder().build(); - - let s = server.client().connect(); - #[cfg(not(any(boringssl, awslc)))] - assert_eq!(s.ssl().state_string().trim(), "SSLOK"); - #[cfg(boringssl)] - assert_eq!(s.ssl().state_string(), "!!!!!!"); - #[cfg(awslc)] - assert_eq!(s.ssl().state_string(), EXPECTED_STATE_STRING_LONG); - - assert_eq!(s.ssl().state_string_long(), EXPECTED_STATE_STRING_LONG); -} - -// when a connection uses ECDHE P-384 key exchange, then the temp key APIs -// return P-384 keys, and the peer and local keys are different. -#[test] -#[cfg(ossl300)] -fn peer_tmp_key_p384() { - let mut server = Server::builder(); - server.ctx().set_groups_list("P-384").unwrap(); - let server = server.build(); - let s = server.client().connect(); - let peer_temp = s.ssl().peer_tmp_key().unwrap(); - assert_eq!(peer_temp.id(), Id::EC); - assert_eq!(peer_temp.bits(), 384); - - let local_temp = s.ssl().tmp_key().unwrap(); - assert_eq!(local_temp.id(), Id::EC); - assert_eq!(local_temp.bits(), 384); - - assert_ne!( - peer_temp.ec_key().unwrap().public_key_to_der().unwrap(), - local_temp.ec_key().unwrap().public_key_to_der().unwrap(), - ); -} - -// when a connection uses RSA key exchange, then the peer (server) temp key is -// an Error because there is no temp key, and the local (client) temp key is the -// temp key sent in the initial key share. -#[test] -#[cfg(ossl300)] -fn peer_tmp_key_rsa() { - let mut server = Server::builder(); - server.ctx().set_cipher_list("RSA").unwrap(); - // RSA key exchange is not allowed in TLS 1.3, so force the connection - // to negotiate TLS 1.2 - server - .ctx() - .set_max_proto_version(Some(SslVersion::TLS1_2)) - .unwrap(); - let server = server.build(); - let mut client = server.client(); - client.ctx().set_groups_list("P-521").unwrap(); - let s = client.connect(); - let peer_temp = s.ssl().peer_tmp_key(); - assert!(peer_temp.is_err()); - - // this is the temp key that the client sent in the initial key share - let local_temp = s.ssl().tmp_key().unwrap(); - assert_eq!(local_temp.id(), Id::EC); - assert_eq!(local_temp.bits(), 521); -} - -/// Tests that when both the client as well as the server use SRTP and their -/// lists of supported protocols have an overlap -- with only ONE protocol -/// being valid for both. -#[test] -fn test_connect_with_srtp_ctx() { - let listener = TcpListener::bind("127.0.0.1:0").unwrap(); - let addr = listener.local_addr().unwrap(); - - let guard = thread::spawn(move || { - let stream = listener.accept().unwrap().0; - let mut ctx = SslContext::builder(SslMethod::dtls()).unwrap(); - ctx.set_tlsext_use_srtp("SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32") - .unwrap(); - ctx.set_certificate_file(Path::new("test/cert.pem"), SslFiletype::PEM) - .unwrap(); - ctx.set_private_key_file(Path::new("test/key.pem"), SslFiletype::PEM) - .unwrap(); - let mut ssl = Ssl::new(&ctx.build()).unwrap(); - ssl.set_mtu(1500).unwrap(); - let mut stream = ssl.accept(stream).unwrap(); - - let mut buf = [0; 60]; - stream - .ssl() - .export_keying_material(&mut buf, "EXTRACTOR-dtls_srtp", None) - .unwrap(); - - stream.write_all(&[0]).unwrap(); - - buf - }); - - let stream = TcpStream::connect(addr).unwrap(); - let mut ctx = SslContext::builder(SslMethod::dtls()).unwrap(); - ctx.set_tlsext_use_srtp("SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32") - .unwrap(); - let mut ssl = Ssl::new(&ctx.build()).unwrap(); - ssl.set_mtu(1500).unwrap(); - let mut stream = ssl.connect(stream).unwrap(); - - let mut buf = [1; 60]; - { - let srtp_profile = stream.ssl().selected_srtp_profile().unwrap(); - assert_eq!("SRTP_AES128_CM_SHA1_80", srtp_profile.name()); - assert_eq!(SrtpProfileId::SRTP_AES128_CM_SHA1_80, srtp_profile.id()); - } - stream - .ssl() - .export_keying_material(&mut buf, "EXTRACTOR-dtls_srtp", None) - .expect("extract"); - - stream.read_exact(&mut [0]).unwrap(); - - let buf2 = guard.join().unwrap(); - - assert_eq!(buf[..], buf2[..]); -} - -/// Tests that when both the client as well as the server use SRTP and their -/// lists of supported protocols have an overlap -- with only ONE protocol -/// being valid for both. -#[test] -fn test_connect_with_srtp_ssl() { - let listener = TcpListener::bind("127.0.0.1:0").unwrap(); - let addr = listener.local_addr().unwrap(); - - let guard = thread::spawn(move || { - let stream = listener.accept().unwrap().0; - let mut ctx = SslContext::builder(SslMethod::dtls()).unwrap(); - ctx.set_certificate_file(Path::new("test/cert.pem"), SslFiletype::PEM) - .unwrap(); - ctx.set_private_key_file(Path::new("test/key.pem"), SslFiletype::PEM) - .unwrap(); - let mut ssl = Ssl::new(&ctx.build()).unwrap(); - ssl.set_tlsext_use_srtp("SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32") - .unwrap(); - let mut profilenames = String::new(); - for profile in ssl.srtp_profiles().unwrap() { - if !profilenames.is_empty() { - profilenames.push(':'); - } - profilenames += profile.name(); - } - assert_eq!( - "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32", - profilenames - ); - ssl.set_mtu(1500).unwrap(); - let mut stream = ssl.accept(stream).unwrap(); - - let mut buf = [0; 60]; - stream - .ssl() - .export_keying_material(&mut buf, "EXTRACTOR-dtls_srtp", None) - .unwrap(); - - stream.write_all(&[0]).unwrap(); - - buf - }); - - let stream = TcpStream::connect(addr).unwrap(); - let ctx = SslContext::builder(SslMethod::dtls()).unwrap(); - let mut ssl = Ssl::new(&ctx.build()).unwrap(); - ssl.set_tlsext_use_srtp("SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32") - .unwrap(); - ssl.set_mtu(1500).unwrap(); - let mut stream = ssl.connect(stream).unwrap(); - - let mut buf = [1; 60]; - { - let srtp_profile = stream.ssl().selected_srtp_profile().unwrap(); - assert_eq!("SRTP_AES128_CM_SHA1_80", srtp_profile.name()); - assert_eq!(SrtpProfileId::SRTP_AES128_CM_SHA1_80, srtp_profile.id()); - } - stream - .ssl() - .export_keying_material(&mut buf, "EXTRACTOR-dtls_srtp", None) - .expect("extract"); - - stream.read_exact(&mut [0]).unwrap(); - - let buf2 = guard.join().unwrap(); - - assert_eq!(buf[..], buf2[..]); -} - -/// Tests that when the `SslStream` is created as a server stream, the protocols -/// are correctly advertised to the client. -#[test] -fn test_alpn_server_advertise_multiple() { - let mut server = Server::builder(); - server.ctx().set_alpn_select_callback(|_, client| { - ssl::select_next_proto(b"\x08http/1.1\x08spdy/3.1", client).ok_or(ssl::AlpnError::NOACK) - }); - let server = server.build(); - - let mut client = server.client(); - client.ctx().set_alpn_protos(b"\x08spdy/3.1").unwrap(); - let s = client.connect(); - assert_eq!(s.ssl().selected_alpn_protocol(), Some(&b"spdy/3.1"[..])); -} - -#[test] -#[cfg(any(ossl110, boringssl, awslc))] -fn test_alpn_server_select_none_fatal() { - let mut server = Server::builder(); - server.ctx().set_alpn_select_callback(|_, client| { - ssl::select_next_proto(b"\x08http/1.1\x08spdy/3.1", client) - .ok_or(ssl::AlpnError::ALERT_FATAL) - }); - server.should_error(); - let server = server.build(); - - let mut client = server.client(); - client.ctx().set_alpn_protos(b"\x06http/2").unwrap(); - client.connect_err(); -} - -#[test] -fn test_alpn_server_select_none() { - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let mut server = Server::builder(); - server.ctx().set_alpn_select_callback(|_, client| { - CALLED_BACK.store(true, Ordering::SeqCst); - ssl::select_next_proto(b"\x08http/1.1\x08spdy/3.1", client).ok_or(ssl::AlpnError::NOACK) - }); - let server = server.build(); - - let mut client = server.client(); - client.ctx().set_alpn_protos(b"\x06http/2").unwrap(); - let s = client.connect(); - assert_eq!(None, s.ssl().selected_alpn_protocol()); - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -#[test] -fn test_alpn_server_unilateral() { - let server = Server::builder().build(); - - let mut client = server.client(); - client.ctx().set_alpn_protos(b"\x06http/2").unwrap(); - let s = client.connect(); - assert_eq!(None, s.ssl().selected_alpn_protocol()); -} - -#[test] -#[should_panic(expected = "blammo")] -fn write_panic() { - struct ExplodingStream(TcpStream); - - impl Read for ExplodingStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - } - - impl Write for ExplodingStream { - fn write(&mut self, _: &[u8]) -> io::Result { - panic!("blammo"); - } - - fn flush(&mut self) -> io::Result<()> { - self.0.flush() - } - } - - let mut server = Server::builder(); - server.should_error(); - let server = server.build(); - - let stream = ExplodingStream(server.connect_tcp()); - - let ctx = SslContext::builder(SslMethod::tls()).unwrap(); - let _ = Ssl::new(&ctx.build()).unwrap().connect(stream); -} - -#[test] -#[should_panic(expected = "blammo")] -fn read_panic() { - struct ExplodingStream(TcpStream); - - impl Read for ExplodingStream { - fn read(&mut self, _: &mut [u8]) -> io::Result { - panic!("blammo"); - } - } - - impl Write for ExplodingStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.0.write(buf) - } - - fn flush(&mut self) -> io::Result<()> { - self.0.flush() - } - } - - let mut server = Server::builder(); - server.should_error(); - let server = server.build(); - - let stream = ExplodingStream(server.connect_tcp()); - - let ctx = SslContext::builder(SslMethod::tls()).unwrap(); - let _ = Ssl::new(&ctx.build()).unwrap().connect(stream); -} - -#[test] -#[should_panic(expected = "blammo")] -fn flush_panic() { - struct ExplodingStream(TcpStream); - - impl Read for ExplodingStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - } - - impl Write for ExplodingStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.0.write(buf) - } - - fn flush(&mut self) -> io::Result<()> { - panic!("blammo"); - } - } - - let mut server = Server::builder(); - server.should_error(); - let server = server.build(); - - let stream = ExplodingStream(server.connect_tcp()); - - let ctx = SslContext::builder(SslMethod::tls()).unwrap(); - let _ = Ssl::new(&ctx.build()).unwrap().connect(stream); -} - -#[test] -fn refcount_ssl_context() { - let mut ssl = { - let ctx = SslContext::builder(SslMethod::tls()).unwrap(); - ssl::Ssl::new(&ctx.build()).unwrap() - }; - - { - let new_ctx_a = SslContext::builder(SslMethod::tls()).unwrap().build(); - ssl.set_ssl_context(&new_ctx_a).unwrap(); - } -} - -#[test] -#[cfg_attr(libressl, ignore)] -#[cfg_attr(target_os = "windows", ignore)] -#[cfg_attr(all(target_os = "macos", feature = "vendored"), ignore)] -fn default_verify_paths() { - let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); - ctx.set_default_verify_paths().unwrap(); - ctx.set_verify(SslVerifyMode::PEER); - let ctx = ctx.build(); - let s = match TcpStream::connect("google.com:443") { - Ok(s) => s, - Err(_) => return, - }; - let mut ssl = Ssl::new(&ctx).unwrap(); - ssl.set_hostname("google.com").unwrap(); - let mut socket = ssl.connect(s).unwrap(); - - socket.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap(); - let mut result = vec![]; - socket.read_to_end(&mut result).unwrap(); - - println!("{}", String::from_utf8_lossy(&result)); - assert!(result.starts_with(b"HTTP/1.0")); - assert!(result.ends_with(b"\r\n") || result.ends_with(b"")); -} - -#[test] -fn add_extra_chain_cert() { - let cert = X509::from_pem(CERT).unwrap(); - let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); - ctx.add_extra_chain_cert(cert).unwrap(); -} - -#[test] -#[cfg(ossl102)] -fn verify_valid_hostname() { - let server = Server::builder().build(); - - let mut client = server.client(); - client.ctx().set_ca_file("test/root-ca.pem").unwrap(); - client.ctx().set_verify(SslVerifyMode::PEER); - - let mut client = client.build().builder(); - client - .ssl() - .param_mut() - .set_hostflags(X509CheckFlags::NO_PARTIAL_WILDCARDS); - client.ssl().param_mut().set_host("foobar.com").unwrap(); - client.connect(); -} - -#[test] -#[cfg(ossl102)] -fn verify_invalid_hostname() { - let mut server = Server::builder(); - server.should_error(); - let server = server.build(); - - let mut client = server.client(); - client.ctx().set_ca_file("test/root-ca.pem").unwrap(); - client.ctx().set_verify(SslVerifyMode::PEER); - - let mut client = client.build().builder(); - client - .ssl() - .param_mut() - .set_hostflags(X509CheckFlags::NO_PARTIAL_WILDCARDS); - client.ssl().param_mut().set_host("bogus.com").unwrap(); - client.connect_err(); -} - -#[test] -fn connector_valid_hostname() { - let server = Server::builder().build(); - - let mut connector = SslConnector::builder(SslMethod::tls()).unwrap(); - connector.set_ca_file("test/root-ca.pem").unwrap(); - - let s = server.connect_tcp(); - let mut s = connector.build().connect("foobar.com", s).unwrap(); - s.read_exact(&mut [0]).unwrap(); -} - -#[test] -fn connector_invalid_hostname() { - let mut server = Server::builder(); - server.should_error(); - let server = server.build(); - - let mut connector = SslConnector::builder(SslMethod::tls()).unwrap(); - connector.set_ca_file("test/root-ca.pem").unwrap(); - - let s = server.connect_tcp(); - connector.build().connect("bogus.com", s).unwrap_err(); -} - -#[test] -fn connector_invalid_no_hostname_verification() { - let server = Server::builder().build(); - - let mut connector = SslConnector::builder(SslMethod::tls()).unwrap(); - connector.set_ca_file("test/root-ca.pem").unwrap(); - - let s = server.connect_tcp(); - let mut s = connector - .build() - .configure() - .unwrap() - .verify_hostname(false) - .connect("bogus.com", s) - .unwrap(); - s.read_exact(&mut [0]).unwrap(); -} - -#[test] -fn connector_no_hostname_still_verifies() { - let mut server = Server::builder(); - server.should_error(); - let server = server.build(); - - let connector = SslConnector::builder(SslMethod::tls()).unwrap().build(); - - let s = server.connect_tcp(); - assert!(connector - .configure() - .unwrap() - .verify_hostname(false) - .connect("fizzbuzz.com", s) - .is_err()); -} - -#[test] -fn connector_can_disable_verify() { - let server = Server::builder().build(); - - let mut connector = SslConnector::builder(SslMethod::tls()).unwrap(); - connector.set_verify(SslVerifyMode::NONE); - let connector = connector.build(); - - let s = server.connect_tcp(); - let mut s = connector - .configure() - .unwrap() - .connect("fizzbuzz.com", s) - .unwrap(); - s.read_exact(&mut [0]).unwrap(); -} - -#[test] -fn connector_does_use_sni_with_dnsnames() { - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let mut builder = Server::builder(); - builder.ctx().set_servername_callback(|ssl, _| { - assert_eq!(ssl.servername(NameType::HOST_NAME), Some("foobar.com")); - CALLED_BACK.store(true, Ordering::SeqCst); - Ok(()) - }); - let server = builder.build(); - - let mut connector = SslConnector::builder(SslMethod::tls()).unwrap(); - connector.set_ca_file("test/root-ca.pem").unwrap(); - - let s = server.connect_tcp(); - let mut s = connector - .build() - .configure() - .unwrap() - .connect("foobar.com", s) - .unwrap(); - s.read_exact(&mut [0]).unwrap(); - - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -#[test] -fn connector_doesnt_use_sni_with_ips() { - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let mut builder = Server::builder(); - builder.ctx().set_servername_callback(|ssl, _| { - assert_eq!(ssl.servername(NameType::HOST_NAME), None); - CALLED_BACK.store(true, Ordering::SeqCst); - Ok(()) - }); - let server = builder.build(); - - let mut connector = SslConnector::builder(SslMethod::tls()).unwrap(); - // The server's cert isn't issued for 127.0.0.1 but we don't care for this test. - connector.set_verify(SslVerifyMode::NONE); - - let s = server.connect_tcp(); - let mut s = connector - .build() - .configure() - .unwrap() - .connect("127.0.0.1", s) - .unwrap(); - s.read_exact(&mut [0]).unwrap(); - - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -fn test_mozilla_server(new: fn(SslMethod) -> Result) { - let listener = TcpListener::bind("127.0.0.1:0").unwrap(); - let port = listener.local_addr().unwrap().port(); - - let t = thread::spawn(move || { - let key = PKey::private_key_from_pem(KEY).unwrap(); - let cert = X509::from_pem(CERT).unwrap(); - let mut acceptor = new(SslMethod::tls()).unwrap(); - acceptor.set_private_key(&key).unwrap(); - acceptor.set_certificate(&cert).unwrap(); - let acceptor = acceptor.build(); - let stream = listener.accept().unwrap().0; - let mut stream = acceptor.accept(stream).unwrap(); - - stream.write_all(b"hello").unwrap(); - }); - - let mut connector = SslConnector::builder(SslMethod::tls()).unwrap(); - connector.set_ca_file("test/root-ca.pem").unwrap(); - let connector = connector.build(); - - let stream = TcpStream::connect(("127.0.0.1", port)).unwrap(); - let mut stream = connector.connect("foobar.com", stream).unwrap(); - - let mut buf = [0; 5]; - stream.read_exact(&mut buf).unwrap(); - assert_eq!(b"hello", &buf); - - t.join().unwrap(); -} - -#[test] -fn connector_client_server_mozilla_intermediate() { - test_mozilla_server(SslAcceptor::mozilla_intermediate); -} - -#[test] -fn connector_client_server_mozilla_modern() { - test_mozilla_server(SslAcceptor::mozilla_modern); -} - -#[test] -fn connector_client_server_mozilla_intermediate_v5() { - test_mozilla_server(SslAcceptor::mozilla_intermediate_v5); -} - -#[test] -#[cfg(any(ossl111, libressl))] -fn connector_client_server_mozilla_modern_v5() { - test_mozilla_server(SslAcceptor::mozilla_modern_v5); -} - -#[test] -fn shutdown() { - let mut server = Server::builder(); - server.io_cb(|mut s| { - assert_eq!(s.read(&mut [0]).unwrap(), 0); - assert_eq!(s.shutdown().unwrap(), ShutdownResult::Received); - }); - let server = server.build(); - - let mut s = server.client().connect(); - - assert_eq!(s.get_shutdown(), ShutdownState::empty()); - assert_eq!(s.shutdown().unwrap(), ShutdownResult::Sent); - assert_eq!(s.get_shutdown(), ShutdownState::SENT); - assert_eq!(s.shutdown().unwrap(), ShutdownResult::Received); - assert_eq!( - s.get_shutdown(), - ShutdownState::SENT | ShutdownState::RECEIVED - ); -} - -#[test] -fn client_ca_list() { - let names = X509Name::load_client_ca_file("test/root-ca.pem").unwrap(); - assert_eq!(names.len(), 1); - - let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); - ctx.set_client_ca_list(names); -} - -#[test] -fn cert_store() { - let server = Server::builder().build(); - - let mut client = server.client(); - let cert = X509::from_pem(ROOT_CERT).unwrap(); - client.ctx().cert_store_mut().add_cert(cert).unwrap(); - client.ctx().set_verify(SslVerifyMode::PEER); - - client.connect(); -} - -#[test] -#[cfg_attr(any(boringssl, awslc), ignore)] -fn tmp_dh_callback() { - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let mut server = Server::builder(); - server.ctx().set_tmp_dh_callback(|_, _, _| { - CALLED_BACK.store(true, Ordering::SeqCst); - let dh = include_bytes!("../../../test/dhparams.pem"); - Dh::params_from_pem(dh) - }); - - let server = server.build(); - - let mut client = server.client(); - // TLS 1.3 has no DH suites, so make sure we don't pick that version - #[cfg(any(ossl111, libressl))] - client.ctx().set_options(super::SslOptions::NO_TLSV1_3); - client.ctx().set_cipher_list("EDH").unwrap(); - client.connect(); - - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -#[test] -#[cfg(all(ossl102, not(ossl110)))] -#[allow(deprecated)] -fn tmp_ecdh_callback() { - use crate::ec::EcKey; - use crate::nid::Nid; - - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let mut server = Server::builder(); - server.ctx().set_tmp_ecdh_callback(|_, _, _| { - CALLED_BACK.store(true, Ordering::SeqCst); - EcKey::from_curve_name(Nid::X9_62_PRIME256V1) - }); - - let server = server.build(); - - let mut client = server.client(); - client.ctx().set_cipher_list("ECDH").unwrap(); - client.connect(); - - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -#[test] -#[cfg_attr(any(boringssl, awslc), ignore)] -fn tmp_dh_callback_ssl() { - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let mut server = Server::builder(); - server.ssl_cb(|ssl| { - ssl.set_tmp_dh_callback(|_, _, _| { - CALLED_BACK.store(true, Ordering::SeqCst); - let dh = include_bytes!("../../../test/dhparams.pem"); - Dh::params_from_pem(dh) - }); - }); - - let server = server.build(); - - let mut client = server.client(); - // TLS 1.3 has no DH suites, so make sure we don't pick that version - #[cfg(any(ossl111, libressl))] - client.ctx().set_options(super::SslOptions::NO_TLSV1_3); - client.ctx().set_cipher_list("EDH").unwrap(); - client.connect(); - - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -#[test] -#[cfg(all(ossl102, not(ossl110)))] -#[allow(deprecated)] -fn tmp_ecdh_callback_ssl() { - use crate::ec::EcKey; - use crate::nid::Nid; - - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let mut server = Server::builder(); - server.ssl_cb(|ssl| { - ssl.set_tmp_ecdh_callback(|_, _, _| { - CALLED_BACK.store(true, Ordering::SeqCst); - EcKey::from_curve_name(Nid::X9_62_PRIME256V1) - }); - }); - - let server = server.build(); - - let mut client = server.client(); - client.ctx().set_cipher_list("ECDH").unwrap(); - client.connect(); - - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -#[test] -fn idle_session() { - let ctx = SslContext::builder(SslMethod::tls()).unwrap().build(); - let ssl = Ssl::new(&ctx).unwrap(); - assert!(ssl.session().is_none()); -} - -/// LibreSSL 3.2.1 enabled TLSv1.3 by default for clients and sessions do -/// not work due to lack of PSK support. The test passes with NO_TLSV1_3, -/// but let's ignore it until LibreSSL supports it out of the box. -#[test] -#[cfg_attr(libressl, ignore)] -fn active_session() { - let server = Server::builder().build(); - - let s = server.client().connect(); - - let session = s.ssl().session().unwrap(); - let len = session.master_key_len(); - let mut buf = vec![0; len - 1]; - let copied = session.master_key(&mut buf); - assert_eq!(copied, buf.len()); - let mut buf = vec![0; len + 1]; - let copied = session.master_key(&mut buf); - assert_eq!(copied, len); -} - -#[test] -#[cfg(not(any(boringssl, awslc)))] -fn status_callbacks() { - static CALLED_BACK_SERVER: AtomicBool = AtomicBool::new(false); - static CALLED_BACK_CLIENT: AtomicBool = AtomicBool::new(false); - - let mut server = Server::builder(); - server - .ctx() - .set_status_callback(|ssl| { - CALLED_BACK_SERVER.store(true, Ordering::SeqCst); - let response = OcspResponse::create(OcspResponseStatus::UNAUTHORIZED, None).unwrap(); - let response = response.to_der().unwrap(); - ssl.set_ocsp_status(&response).unwrap(); - Ok(true) - }) - .unwrap(); - - let server = server.build(); - - let mut client = server.client(); - client - .ctx() - .set_status_callback(|ssl| { - CALLED_BACK_CLIENT.store(true, Ordering::SeqCst); - let response = OcspResponse::from_der(ssl.ocsp_status().unwrap()).unwrap(); - assert_eq!(response.status(), OcspResponseStatus::UNAUTHORIZED); - Ok(true) - }) - .unwrap(); - - let mut client = client.build().builder(); - client.ssl().set_status_type(StatusType::OCSP).unwrap(); - - client.connect(); - - assert!(CALLED_BACK_SERVER.load(Ordering::SeqCst)); - assert!(CALLED_BACK_CLIENT.load(Ordering::SeqCst)); -} - -/// LibreSSL 3.2.1 enabled TLSv1.3 by default for clients and sessions do -/// not work due to lack of PSK support. The test passes with NO_TLSV1_3, -/// but let's ignore it until LibreSSL supports it out of the box. -#[test] -#[cfg_attr(libressl, ignore)] -fn new_session_callback() { - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let mut server = Server::builder(); - server.ctx().set_session_id_context(b"foo").unwrap(); - - let server = server.build(); - - let mut client = server.client(); - - client - .ctx() - .set_session_cache_mode(SslSessionCacheMode::CLIENT | SslSessionCacheMode::NO_INTERNAL); - client - .ctx() - .set_new_session_callback(|_, _| CALLED_BACK.store(true, Ordering::SeqCst)); - - client.connect(); - - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -/// LibreSSL 3.2.1 enabled TLSv1.3 by default for clients and sessions do -/// not work due to lack of PSK support. The test passes with NO_TLSV1_3, -/// but let's ignore it until LibreSSL supports it out of the box. -#[test] -#[cfg_attr(libressl, ignore)] -fn new_session_callback_swapped_ctx() { - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let mut server = Server::builder(); - server.ctx().set_session_id_context(b"foo").unwrap(); - - let server = server.build(); - - let mut client = server.client(); - - client - .ctx() - .set_session_cache_mode(SslSessionCacheMode::CLIENT | SslSessionCacheMode::NO_INTERNAL); - client - .ctx() - .set_new_session_callback(|_, _| CALLED_BACK.store(true, Ordering::SeqCst)); - - let mut client = client.build().builder(); - - let ctx = SslContextBuilder::new(SslMethod::tls()).unwrap().build(); - client.ssl().set_ssl_context(&ctx).unwrap(); - - client.connect(); - - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -#[test] -fn keying_export() { - let listener = TcpListener::bind("127.0.0.1:0").unwrap(); - let addr = listener.local_addr().unwrap(); - - let label = "EXPERIMENTAL test"; - let context = b"my context"; - - let guard = thread::spawn(move || { - let stream = listener.accept().unwrap().0; - let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); - ctx.set_certificate_file(Path::new("test/cert.pem"), SslFiletype::PEM) - .unwrap(); - ctx.set_private_key_file(Path::new("test/key.pem"), SslFiletype::PEM) - .unwrap(); - let ssl = Ssl::new(&ctx.build()).unwrap(); - let mut stream = ssl.accept(stream).unwrap(); - - let mut buf = [0; 32]; - stream - .ssl() - .export_keying_material(&mut buf, label, Some(context)) - .unwrap(); - - stream.write_all(&[0]).unwrap(); - - buf - }); - - let stream = TcpStream::connect(addr).unwrap(); - let ctx = SslContext::builder(SslMethod::tls()).unwrap(); - let ssl = Ssl::new(&ctx.build()).unwrap(); - let mut stream = ssl.connect(stream).unwrap(); - - let mut buf = [1; 32]; - stream - .ssl() - .export_keying_material(&mut buf, label, Some(context)) - .unwrap(); - - stream.read_exact(&mut [0]).unwrap(); - - let buf2 = guard.join().unwrap(); - - assert_eq!(buf, buf2); -} - -#[test] -#[cfg(any(ossl110, libressl))] -fn no_version_overlap() { - let mut server = Server::builder(); - server.ctx().set_min_proto_version(None).unwrap(); - server - .ctx() - .set_max_proto_version(Some(SslVersion::TLS1_1)) - .unwrap(); - #[cfg(any(ossl110g, libressl))] - assert_eq!(server.ctx().max_proto_version(), Some(SslVersion::TLS1_1)); - server.should_error(); - let server = server.build(); - - let mut client = server.client(); - client - .ctx() - .set_min_proto_version(Some(SslVersion::TLS1_2)) - .unwrap(); - #[cfg(ossl110g)] - assert_eq!(client.ctx().min_proto_version(), Some(SslVersion::TLS1_2)); - client.ctx().set_max_proto_version(None).unwrap(); - - client.connect_err(); -} - -#[test] -#[cfg(ossl111)] -fn custom_extensions() { - static FOUND_EXTENSION: AtomicBool = AtomicBool::new(false); - - let mut server = Server::builder(); - server - .ctx() - .add_custom_ext( - 12345, - ExtensionContext::CLIENT_HELLO, - |_, _, _| -> Result, _> { unreachable!() }, - |_, _, data, _| { - FOUND_EXTENSION.store(data == b"hello", Ordering::SeqCst); - Ok(()) - }, - ) - .unwrap(); - - let server = server.build(); - - let mut client = server.client(); - client - .ctx() - .add_custom_ext( - 12345, - ssl::ExtensionContext::CLIENT_HELLO, - |_, _, _| Ok(Some(b"hello")), - |_, _, _, _| unreachable!(), - ) - .unwrap(); - - client.connect(); - - assert!(FOUND_EXTENSION.load(Ordering::SeqCst)); -} - -fn _check_kinds() { - fn is_send() {} - fn is_sync() {} - - is_send::>(); - is_sync::>(); -} - -#[test] -#[cfg(ossl111)] -fn stateless() { - use super::SslOptions; - - #[derive(Debug)] - struct MemoryStream { - incoming: io::Cursor>, - outgoing: Vec, - } - - impl MemoryStream { - pub fn new() -> Self { - Self { - incoming: io::Cursor::new(Vec::new()), - outgoing: Vec::new(), - } - } - - pub fn extend_incoming(&mut self, data: &[u8]) { - self.incoming.get_mut().extend_from_slice(data); - } - - pub fn take_outgoing(&mut self) -> Outgoing<'_> { - Outgoing(&mut self.outgoing) - } - } - - impl Read for MemoryStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let n = self.incoming.read(buf)?; - if self.incoming.position() == self.incoming.get_ref().len() as u64 { - self.incoming.set_position(0); - self.incoming.get_mut().clear(); - } - if n == 0 { - return Err(io::Error::new( - io::ErrorKind::WouldBlock, - "no data available", - )); - } - Ok(n) - } - } - - impl Write for MemoryStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.outgoing.write(buf) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } - } - - pub struct Outgoing<'a>(&'a mut Vec); - - impl Drop for Outgoing<'_> { - fn drop(&mut self) { - self.0.clear(); - } - } - - impl ::std::ops::Deref for Outgoing<'_> { - type Target = [u8]; - fn deref(&self) -> &[u8] { - self.0 - } - } - - impl AsRef<[u8]> for Outgoing<'_> { - fn as_ref(&self) -> &[u8] { - self.0 - } - } - - fn send(from: &mut MemoryStream, to: &mut MemoryStream) { - to.extend_incoming(&from.take_outgoing()); - } - - // - // Setup - // - - let mut client_ctx = SslContext::builder(SslMethod::tls()).unwrap(); - client_ctx.clear_options(SslOptions::ENABLE_MIDDLEBOX_COMPAT); - let mut client_stream = - SslStream::new(Ssl::new(&client_ctx.build()).unwrap(), MemoryStream::new()).unwrap(); - - let mut server_ctx = SslContext::builder(SslMethod::tls()).unwrap(); - server_ctx - .set_certificate_file(Path::new("test/cert.pem"), SslFiletype::PEM) - .unwrap(); - server_ctx - .set_private_key_file(Path::new("test/key.pem"), SslFiletype::PEM) - .unwrap(); - const COOKIE: &[u8] = b"chocolate chip"; - server_ctx.set_stateless_cookie_generate_cb(|_tls, buf| { - buf[0..COOKIE.len()].copy_from_slice(COOKIE); - Ok(COOKIE.len()) - }); - server_ctx.set_stateless_cookie_verify_cb(|_tls, buf| buf == COOKIE); - let mut server_stream = - SslStream::new(Ssl::new(&server_ctx.build()).unwrap(), MemoryStream::new()).unwrap(); - - // - // Handshake - // - - // Initial ClientHello - client_stream.connect().unwrap_err(); - send(client_stream.get_mut(), server_stream.get_mut()); - // HelloRetryRequest - assert!(!server_stream.stateless().unwrap()); - send(server_stream.get_mut(), client_stream.get_mut()); - // Second ClientHello - client_stream.do_handshake().unwrap_err(); - send(client_stream.get_mut(), server_stream.get_mut()); - // OldServerHello - assert!(server_stream.stateless().unwrap()); - server_stream.accept().unwrap_err(); - send(server_stream.get_mut(), client_stream.get_mut()); - // Finished - client_stream.do_handshake().unwrap(); - send(client_stream.get_mut(), server_stream.get_mut()); - server_stream.do_handshake().unwrap(); -} - -#[cfg(not(osslconf = "OPENSSL_NO_PSK"))] -#[test] -fn psk_ciphers() { - const CIPHER: &str = "PSK-AES256-CBC-SHA"; - const PSK: &[u8] = b"thisisaverysecurekey"; - const CLIENT_IDENT: &[u8] = b"thisisaclient"; - static CLIENT_CALLED: AtomicBool = AtomicBool::new(false); - static SERVER_CALLED: AtomicBool = AtomicBool::new(false); - - let mut server = Server::builder(); - server.ctx().set_cipher_list(CIPHER).unwrap(); - server.ctx().set_psk_server_callback(|_, identity, psk| { - assert!(identity.unwrap_or(&[]) == CLIENT_IDENT); - psk[..PSK.len()].copy_from_slice(PSK); - SERVER_CALLED.store(true, Ordering::SeqCst); - Ok(PSK.len()) - }); - - let server = server.build(); - - let mut client = server.client(); - // This test relies on TLS 1.2 suites - #[cfg(any(boringssl, ossl111, awslc))] - client.ctx().set_options(super::SslOptions::NO_TLSV1_3); - client.ctx().set_cipher_list(CIPHER).unwrap(); - client - .ctx() - .set_psk_client_callback(move |_, _, identity, psk| { - identity[..CLIENT_IDENT.len()].copy_from_slice(CLIENT_IDENT); - identity[CLIENT_IDENT.len()] = 0; - psk[..PSK.len()].copy_from_slice(PSK); - CLIENT_CALLED.store(true, Ordering::SeqCst); - Ok(PSK.len()) - }); - - client.connect(); - - assert!(SERVER_CALLED.load(Ordering::SeqCst)); - assert!(CLIENT_CALLED.load(Ordering::SeqCst)); -} - -#[test] -fn sni_callback_swapped_ctx() { - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let mut server = Server::builder(); - - let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); - ctx.set_servername_callback(|_, _| { - CALLED_BACK.store(true, Ordering::SeqCst); - Ok(()) - }); - - let keyed_ctx = mem::replace(server.ctx(), ctx).build(); - server.ssl_cb(move |ssl| ssl.set_ssl_context(&keyed_ctx).unwrap()); - - let server = server.build(); - - server.client().connect(); - - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -#[test] -#[cfg(ossl111)] -fn client_hello() { - static CALLED_BACK: AtomicBool = AtomicBool::new(false); - - let mut server = Server::builder(); - server.ctx().set_client_hello_callback(|ssl, _| { - assert!(!ssl.client_hello_isv2()); - assert_eq!(ssl.client_hello_legacy_version(), Some(SslVersion::TLS1_2)); - assert!(ssl.client_hello_random().is_some()); - assert!(ssl.client_hello_session_id().is_some()); - assert!(ssl.client_hello_ciphers().is_some()); - assert!(ssl.client_hello_compression_methods().is_some()); - assert!(ssl - .bytes_to_cipher_list(ssl.client_hello_ciphers().unwrap(), ssl.client_hello_isv2()) - .is_ok()); - - CALLED_BACK.store(true, Ordering::SeqCst); - Ok(ClientHelloResponse::SUCCESS) - }); - - let server = server.build(); - server.client().connect(); - - assert!(CALLED_BACK.load(Ordering::SeqCst)); -} - -#[test] -#[cfg(ossl111)] -fn openssl_cipher_name() { - assert_eq!( - super::cipher_name("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"), - "ECDHE-RSA-AES256-SHA384", - ); - - assert_eq!(super::cipher_name("asdf"), "(NONE)"); -} - -#[test] -fn session_cache_size() { - let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); - ctx.set_session_cache_size(1234); - let ctx = ctx.build(); - assert_eq!(ctx.session_cache_size(), 1234); -} - -#[test] -#[cfg(ossl102)] -fn add_chain_cert() { - let ctx = SslContext::builder(SslMethod::tls()).unwrap().build(); - let cert = X509::from_pem(CERT).unwrap(); - let mut ssl = Ssl::new(&ctx).unwrap(); - assert!(ssl.add_chain_cert(cert).is_ok()); -} -#[test] -#[cfg(ossl111)] -fn set_ssl_certificate_key_related_api() { - let cert_str: &str = include_str!("../../../test/cert.pem"); - let key_str: &str = include_str!("../../../test/key.pem"); - let ctx = SslContext::builder(SslMethod::tls()).unwrap().build(); - let cert_x509 = X509::from_pem(CERT).unwrap(); - let mut ssl = Ssl::new(&ctx).unwrap(); - assert!(ssl.set_method(SslMethod::tls()).is_ok()); - ssl.set_private_key_file("test/key.pem", SslFiletype::PEM) - .unwrap(); - { - let pkey = String::from_utf8( - ssl.private_key() - .unwrap() - .private_key_to_pem_pkcs8() - .unwrap(), - ) - .unwrap(); - assert!(pkey.lines().eq(key_str.lines())); - } - let pkey = PKey::private_key_from_pem(KEY).unwrap(); - ssl.set_private_key(pkey.as_ref()).unwrap(); - { - let pkey = String::from_utf8( - ssl.private_key() - .unwrap() - .private_key_to_pem_pkcs8() - .unwrap(), - ) - .unwrap(); - assert!(pkey.lines().eq(key_str.lines())); - } - ssl.set_certificate(cert_x509.as_ref()).unwrap(); - let cert = String::from_utf8(ssl.certificate().unwrap().to_pem().unwrap()).unwrap(); - assert!(cert.lines().eq(cert_str.lines())); - ssl.add_client_ca(cert_x509.as_ref()).unwrap(); - ssl.set_min_proto_version(Some(SslVersion::TLS1_2)).unwrap(); - ssl.set_max_proto_version(Some(SslVersion::TLS1_3)).unwrap(); - ssl.set_cipher_list("HIGH:!aNULL:!MD5").unwrap(); - ssl.set_ciphersuites("TLS_AES_128_GCM_SHA256").unwrap(); - let x509 = X509::from_pem(ROOT_CERT).unwrap(); - let mut builder = X509StoreBuilder::new().unwrap(); - builder.add_cert(x509).unwrap(); - let store = builder.build(); - ssl.set_verify_cert_store(store).unwrap(); -} - -#[test] -#[cfg(ossl110)] -fn test_ssl_set_cert_chain_file() { - let ctx = SslContext::builder(SslMethod::tls()).unwrap().build(); - let mut ssl = Ssl::new(&ctx).unwrap(); - ssl.set_certificate_chain_file("test/cert.pem").unwrap(); -} - -#[test] -#[cfg(ossl111)] -fn set_num_tickets() { - let mut ctx = SslContext::builder(SslMethod::tls_server()).unwrap(); - ctx.set_num_tickets(3).unwrap(); - let ctx = ctx.build(); - assert_eq!(3, ctx.num_tickets()); - - let mut ssl = Ssl::new(&ctx).unwrap(); - ssl.set_num_tickets(5).unwrap(); - let ssl = ssl; - assert_eq!(5, ssl.num_tickets()); -} - -#[test] -#[cfg(ossl110)] -fn set_security_level() { - let mut ctx = SslContext::builder(SslMethod::tls_server()).unwrap(); - ctx.set_security_level(3); - let ctx = ctx.build(); - assert_eq!(3, ctx.security_level()); - - let mut ssl = Ssl::new(&ctx).unwrap(); - ssl.set_security_level(4); - let ssl = ssl; - assert_eq!(4, ssl.security_level()); -} - -#[test] -fn ssl_ctx_ex_data_leak() { - static DROPS: AtomicUsize = AtomicUsize::new(0); - - struct DropTest; - - impl Drop for DropTest { - fn drop(&mut self) { - DROPS.fetch_add(1, Ordering::Relaxed); - } - } - - let idx = SslContext::new_ex_index().unwrap(); - - let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); - ctx.set_ex_data(idx, DropTest); - ctx.set_ex_data(idx, DropTest); - assert_eq!(DROPS.load(Ordering::Relaxed), 1); - - drop(ctx); - assert_eq!(DROPS.load(Ordering::Relaxed), 2); -} - -#[test] -fn ssl_ex_data_leak() { - static DROPS: AtomicUsize = AtomicUsize::new(0); - - struct DropTest; - - impl Drop for DropTest { - fn drop(&mut self) { - DROPS.fetch_add(1, Ordering::Relaxed); - } - } - - let idx = Ssl::new_ex_index().unwrap(); - - let ctx = SslContext::builder(SslMethod::tls()).unwrap().build(); - let mut ssl = Ssl::new(&ctx).unwrap(); - ssl.set_ex_data(idx, DropTest); - ssl.set_ex_data(idx, DropTest); - assert_eq!(DROPS.load(Ordering::Relaxed), 1); - - drop(ssl); - assert_eq!(DROPS.load(Ordering::Relaxed), 2); -} - -#[test] -#[cfg(ossl111)] -fn cipher_id() { - let mut server = Server::builder(); - server - .ctx() - .set_ciphersuites("TLS_AES_256_GCM_SHA384") - .unwrap(); - let server = server.build(); - - let client = server.client(); - let s = client.connect(); - let ssl = s.ssl(); - let cipher = ssl.current_cipher().unwrap(); - let cipher_id = cipher.protocol_id(); - assert_eq!(cipher_id, [0x13, 0x02]); -} diff --git a/patch/openssl/src/ssl/test/server.rs b/patch/openssl/src/ssl/test/server.rs deleted file mode 100644 index 41677e5768062..0000000000000 --- a/patch/openssl/src/ssl/test/server.rs +++ /dev/null @@ -1,167 +0,0 @@ -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>, - 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, - io_cb: Box) + Send>, - should_error: bool, -} - -impl Builder { - pub fn ctx(&mut self) -> &mut SslContextBuilder { - &mut self.ctx - } - - pub fn ssl_cb(&mut self, cb: F) - where - F: 'static + FnMut(&mut SslRef) + Send, - { - self.ssl_cb = Box::new(cb); - } - - pub fn io_cb(&mut self, cb: F) - where - F: 'static + FnMut(SslStream) + 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 { - 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 { - 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(); - } -} diff --git a/patch/openssl/src/stack.rs b/patch/openssl/src/stack.rs deleted file mode 100644 index 9861f87c48f3c..0000000000000 --- a/patch/openssl/src/stack.rs +++ /dev/null @@ -1,380 +0,0 @@ -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, LenType}; - -cfg_if! { - if #[cfg(any(ossl110, boringssl, awslc))] { - 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(*mut T::StackType); - -unsafe impl Send for Stack {} -unsafe impl Sync for Stack {} - -impl fmt::Debug for Stack -where - T: Stackable, - T::Ref: fmt::Debug, -{ - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_list().entries(self).finish() - } -} -impl Drop for Stack { - fn drop(&mut self) { - unsafe { - while self.pop().is_some() {} - OPENSSL_sk_free(self.0 as *mut _); - } - } -} - -impl Stack { - pub fn new() -> Result, ErrorStack> { - unsafe { - ffi::init(); - let ptr = cvt_p(OPENSSL_sk_new_null())?; - Ok(Stack(ptr as *mut _)) - } - } -} - -impl iter::IntoIterator for Stack { - type IntoIter = IntoIter; - type Item = T; - - fn into_iter(self) -> IntoIter { - let it = IntoIter { - stack: self.0, - idxs: 0..self.len() as LenType, - }; - mem::forget(self); - it - } -} - -impl AsRef> for Stack { - fn as_ref(&self) -> &StackRef { - self - } -} - -impl Borrow> for Stack { - fn borrow(&self) -> &StackRef { - self - } -} - -impl ForeignType for Stack { - type CType = T::StackType; - type Ref = StackRef; - - #[inline] - unsafe fn from_ptr(ptr: *mut T::StackType) -> Stack { - 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 Deref for Stack { - type Target = StackRef; - - fn deref(&self) -> &StackRef { - unsafe { StackRef::from_ptr(self.0) } - } -} - -impl DerefMut for Stack { - fn deref_mut(&mut self) -> &mut StackRef { - unsafe { StackRef::from_ptr_mut(self.0) } - } -} - -pub struct IntoIter { - stack: *mut T::StackType, - idxs: Range, -} - -impl Drop for IntoIter { - 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 Iterator for IntoIter { - type Item = T; - - fn next(&mut self) -> Option { - 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) { - self.idxs.size_hint() - } -} - -impl DoubleEndedIterator for IntoIter { - fn next_back(&mut self) -> Option { - unsafe { - self.idxs - .next_back() - .map(|i| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, i) as *mut _)) - } - } -} - -impl ExactSizeIterator for IntoIter {} - -pub struct StackRef(Opaque, PhantomData); - -unsafe impl Send for StackRef {} -unsafe impl Sync for StackRef {} - -impl ForeignTypeRef for StackRef { - type CType = T::StackType; -} - -impl StackRef { - 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 LenType, - } - } - - pub fn iter_mut(&mut self) -> IterMut<'_, T> { - IterMut { - idxs: 0..self.len() as LenType, - 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 _) as c_int)?; - mem::forget(data); - Ok(()) - } - } - - /// Removes the last element from the stack and returns it. - pub fn pop(&mut self) -> Option { - 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 LenType) as *mut _ - } -} - -impl Index for StackRef { - type Output = T::Ref; - - fn index(&self, index: usize) -> &T::Ref { - self.get(index).unwrap() - } -} - -impl IndexMut for StackRef { - fn index_mut(&mut self, index: usize) -> &mut T::Ref { - self.get_mut(index).unwrap() - } -} - -impl<'a, T: Stackable> iter::IntoIterator for &'a StackRef { - 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 { - 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 { - 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 { - 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, - idxs: Range, -} - -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) { - 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 ExactSizeIterator for Iter<'_, T> {} - -/// A mutable iterator over the stack's contents. -pub struct IterMut<'a, T: Stackable> { - stack: &'a mut StackRef, - idxs: Range, -} - -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) { - 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 ExactSizeIterator for IterMut<'_, T> {} diff --git a/patch/openssl/src/string.rs b/patch/openssl/src/string.rs deleted file mode 100644 index 55b33623fe580..0000000000000 --- a/patch/openssl/src/string.rs +++ /dev/null @@ -1,96 +0,0 @@ -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 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 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] -#[cfg(not(any(boringssl, awslc)))] -unsafe fn free(buf: *mut c_char) { - ffi::OPENSSL_free(buf as *mut c_void); -} - -#[inline] -#[cfg(any(boringssl, awslc))] -unsafe fn free(buf: *mut c_char) { - ffi::CRYPTO_free( - buf as *mut c_void, - concat!(file!(), "\0").as_ptr() as *const c_char, - line!() as ::libc::c_int, - ); -} diff --git a/patch/openssl/src/symm.rs b/patch/openssl/src/symm.rs deleted file mode 100644 index 1ff95966a19d3..0000000000000 --- a/patch/openssl/src/symm.rs +++ /dev/null @@ -1,1776 +0,0 @@ -//! High level interface to certain symmetric ciphers. -//! -//! # Examples -//! -//! Encrypt data in AES128 CBC mode -//! -//! ``` -//! use openssl::symm::{encrypt, Cipher}; -//! -//! 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 ciphertext = encrypt( -//! cipher, -//! key, -//! Some(iv), -//! data).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[..]); -//! ``` -//! -//! Encrypting an asymmetric key with a symmetric cipher -//! -//! ``` -//! use openssl::rsa::{Padding, Rsa}; -//! use openssl::symm::Cipher; -//! -//! // Generate keypair and encrypt private key: -//! let keypair = Rsa::generate(2048).unwrap(); -//! let cipher = Cipher::aes_256_cbc(); -//! let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap(); -//! let privkey_pem = keypair.private_key_to_pem_passphrase(cipher, b"Rust").unwrap(); -//! // pubkey_pem and privkey_pem could be written to file here. -//! -//! // Load private and public key from string: -//! let pubkey = Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap(); -//! let privkey = Rsa::private_key_from_pem_passphrase(&privkey_pem, b"Rust").unwrap(); -//! -//! // Use the asymmetric keys to encrypt and decrypt a short message: -//! let msg = b"Foo bar"; -//! let mut encrypted = vec![0; pubkey.size() as usize]; -//! let mut decrypted = vec![0; privkey.size() as usize]; -//! let len = pubkey.public_encrypt(msg, &mut encrypted, Padding::PKCS1).unwrap(); -//! assert!(len > msg.len()); -//! let len = privkey.private_decrypt(&encrypted, &mut decrypted, Padding::PKCS1).unwrap(); -//! let output_string = String::from_utf8(decrypted[..len].to_vec()).unwrap(); -//! assert_eq!("Foo bar", output_string); -//! println!("Decrypted: '{}'", output_string); -//! ``` -use crate::cipher::CipherRef; -use crate::cipher_ctx::{CipherCtx, CipherCtxRef}; -use crate::error::ErrorStack; -use crate::nid::Nid; -use cfg_if::cfg_if; -use foreign_types::ForeignTypeRef; -use openssl_macros::corresponds; - -#[derive(Copy, Clone)] -pub enum Mode { - Encrypt, - Decrypt, -} - -/// Represents a particular cipher algorithm. -/// -/// See OpenSSL doc at [`EVP_EncryptInit`] for more information on each algorithms. -/// -/// [`EVP_EncryptInit`]: https://docs.openssl.org/master/man3/EVP_EncryptInit/ -#[derive(Copy, Clone, PartialEq, Eq)] -pub struct Cipher(*const ffi::EVP_CIPHER); - -impl Cipher { - /// Looks up the cipher for a certain nid. - #[corresponds(EVP_get_cipherbynid)] - pub fn from_nid(nid: Nid) -> Option { - let ptr = unsafe { ffi::EVP_get_cipherbyname(ffi::OBJ_nid2sn(nid.as_raw())) }; - if ptr.is_null() { - None - } else { - Some(Cipher(ptr)) - } - } - - /// Returns the cipher's Nid. - #[corresponds(EVP_CIPHER_nid)] - pub fn nid(&self) -> Nid { - let nid = unsafe { ffi::EVP_CIPHER_nid(self.0) }; - Nid::from_raw(nid) - } - - pub fn aes_128_ecb() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_128_ecb()) } - } - - pub fn aes_128_cbc() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_128_cbc()) } - } - - #[cfg(not(any(boringssl, awslc)))] - pub fn aes_128_xts() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_128_xts()) } - } - - pub fn aes_128_ctr() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_128_ctr()) } - } - - #[cfg(not(boringssl))] - pub fn aes_128_cfb1() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_128_cfb1()) } - } - - #[cfg(not(boringssl))] - pub fn aes_128_cfb128() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_128_cfb128()) } - } - - #[cfg(not(boringssl))] - pub fn aes_128_cfb8() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_128_cfb8()) } - } - - pub fn aes_128_gcm() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_128_gcm()) } - } - - #[cfg(not(boringssl))] - pub fn aes_128_ccm() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_128_ccm()) } - } - - pub fn aes_128_ofb() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_128_ofb()) } - } - - /// Requires OpenSSL 1.1.0 or newer. - #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))] - pub fn aes_128_ocb() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_128_ocb()) } - } - - pub fn aes_192_ecb() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_192_ecb()) } - } - - pub fn aes_192_cbc() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_192_cbc()) } - } - - pub fn aes_192_ctr() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_192_ctr()) } - } - - #[cfg(not(boringssl))] - pub fn aes_192_cfb1() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_192_cfb1()) } - } - - #[cfg(not(boringssl))] - pub fn aes_192_cfb128() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_192_cfb128()) } - } - - #[cfg(not(boringssl))] - pub fn aes_192_cfb8() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_192_cfb8()) } - } - - pub fn aes_192_gcm() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_192_gcm()) } - } - - #[cfg(not(any(boringssl, awslc)))] - pub fn aes_192_ccm() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_192_ccm()) } - } - - pub fn aes_192_ofb() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_192_ofb()) } - } - - /// Requires OpenSSL 1.1.0 or newer. - #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))] - pub fn aes_192_ocb() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_192_ocb()) } - } - - pub fn aes_256_ecb() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_256_ecb()) } - } - - pub fn aes_256_cbc() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_256_cbc()) } - } - - #[cfg(not(boringssl))] - pub fn aes_256_xts() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_256_xts()) } - } - - pub fn aes_256_ctr() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_256_ctr()) } - } - - #[cfg(not(boringssl))] - pub fn aes_256_cfb1() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_256_cfb1()) } - } - - #[cfg(not(boringssl))] - pub fn aes_256_cfb128() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_256_cfb128()) } - } - - #[cfg(not(boringssl))] - pub fn aes_256_cfb8() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_256_cfb8()) } - } - - pub fn aes_256_gcm() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_256_gcm()) } - } - - #[cfg(not(boringssl))] - pub fn aes_256_ccm() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_256_ccm()) } - } - - pub fn aes_256_ofb() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_256_ofb()) } - } - - /// Requires OpenSSL 1.1.0 or newer. - #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))] - pub fn aes_256_ocb() -> Cipher { - unsafe { Cipher(ffi::EVP_aes_256_ocb()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_BF"))] - pub fn bf_cbc() -> Cipher { - unsafe { Cipher(ffi::EVP_bf_cbc()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_BF"))] - pub fn bf_ecb() -> Cipher { - unsafe { Cipher(ffi::EVP_bf_ecb()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_BF"))] - pub fn bf_cfb64() -> Cipher { - unsafe { Cipher(ffi::EVP_bf_cfb64()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_BF"))] - pub fn bf_ofb() -> Cipher { - unsafe { Cipher(ffi::EVP_bf_ofb()) } - } - - pub fn des_cbc() -> Cipher { - unsafe { Cipher(ffi::EVP_des_cbc()) } - } - - pub fn des_ecb() -> Cipher { - unsafe { Cipher(ffi::EVP_des_ecb()) } - } - - pub fn des_ede3() -> Cipher { - unsafe { Cipher(ffi::EVP_des_ede3()) } - } - - pub fn des_ede3_cbc() -> Cipher { - unsafe { Cipher(ffi::EVP_des_ede3_cbc()) } - } - - pub fn des_ede3_ecb() -> Cipher { - unsafe { Cipher(ffi::EVP_des_ede3_ecb()) } - } - - #[cfg(not(any(boringssl, awslc)))] - pub fn des_ede3_cfb64() -> Cipher { - unsafe { Cipher(ffi::EVP_des_ede3_cfb64()) } - } - - #[cfg(not(any(boringssl, awslc)))] - pub fn des_ede3_cfb8() -> Cipher { - unsafe { Cipher(ffi::EVP_des_ede3_cfb8()) } - } - - #[cfg(not(any(boringssl, awslc)))] - pub fn des_ede3_ofb() -> Cipher { - unsafe { Cipher(ffi::EVP_des_ede3_ofb()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_RC4"))] - pub fn rc4() -> Cipher { - unsafe { Cipher(ffi::EVP_rc4()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia_128_cbc() -> Cipher { - unsafe { Cipher(ffi::EVP_camellia_128_cbc()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia_128_ecb() -> Cipher { - unsafe { Cipher(ffi::EVP_camellia_128_ecb()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia_128_ofb() -> Cipher { - unsafe { Cipher(ffi::EVP_camellia_128_ofb()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia_128_cfb128() -> Cipher { - unsafe { Cipher(ffi::EVP_camellia_128_cfb128()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia_192_cbc() -> Cipher { - unsafe { Cipher(ffi::EVP_camellia_192_cbc()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia_192_ecb() -> Cipher { - unsafe { Cipher(ffi::EVP_camellia_192_ecb()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia_192_ofb() -> Cipher { - unsafe { Cipher(ffi::EVP_camellia_192_ofb()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia_192_cfb128() -> Cipher { - unsafe { Cipher(ffi::EVP_camellia_192_cfb128()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia_256_cbc() -> Cipher { - unsafe { Cipher(ffi::EVP_camellia_256_cbc()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia_256_ecb() -> Cipher { - unsafe { Cipher(ffi::EVP_camellia_256_ecb()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia_256_ofb() -> Cipher { - unsafe { Cipher(ffi::EVP_camellia_256_ofb()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))] - pub fn camellia_256_cfb128() -> Cipher { - unsafe { Cipher(ffi::EVP_camellia_256_cfb128()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAST"))] - pub fn cast5_cbc() -> Cipher { - unsafe { Cipher(ffi::EVP_cast5_cbc()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAST"))] - pub fn cast5_ecb() -> Cipher { - unsafe { Cipher(ffi::EVP_cast5_ecb()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAST"))] - pub fn cast5_ofb() -> Cipher { - unsafe { Cipher(ffi::EVP_cast5_ofb()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_CAST"))] - pub fn cast5_cfb64() -> Cipher { - unsafe { Cipher(ffi::EVP_cast5_cfb64()) } - } - - /// Requires OpenSSL 1.1.0 or newer. - #[cfg(all(any(ossl110, libressl), not(osslconf = "OPENSSL_NO_CHACHA")))] - pub fn chacha20() -> Cipher { - unsafe { Cipher(ffi::EVP_chacha20()) } - } - - /// Requires OpenSSL 1.1.0 or newer. - #[cfg(all(any(ossl110, libressl360, awslc), not(osslconf = "OPENSSL_NO_CHACHA")))] - pub fn chacha20_poly1305() -> Cipher { - unsafe { Cipher(ffi::EVP_chacha20_poly1305()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))] - pub fn idea_cbc() -> Cipher { - unsafe { Cipher(ffi::EVP_idea_cbc()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))] - pub fn idea_ecb() -> Cipher { - unsafe { Cipher(ffi::EVP_idea_ecb()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))] - pub fn idea_ofb() -> Cipher { - unsafe { Cipher(ffi::EVP_idea_ofb()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))] - pub fn idea_cfb64() -> Cipher { - unsafe { Cipher(ffi::EVP_idea_cfb64()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] - pub fn seed_cbc() -> Cipher { - unsafe { Cipher(ffi::EVP_seed_cbc()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] - pub fn seed_cfb128() -> Cipher { - unsafe { Cipher(ffi::EVP_seed_cfb128()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] - pub fn seed_ecb() -> Cipher { - unsafe { Cipher(ffi::EVP_seed_ecb()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] - pub fn seed_ofb() -> Cipher { - unsafe { Cipher(ffi::EVP_seed_ofb()) } - } - - #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))] - pub fn sm4_ecb() -> Cipher { - unsafe { Cipher(ffi::EVP_sm4_ecb()) } - } - - #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))] - pub fn sm4_cbc() -> Cipher { - unsafe { Cipher(ffi::EVP_sm4_cbc()) } - } - - #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))] - pub fn sm4_ctr() -> Cipher { - unsafe { Cipher(ffi::EVP_sm4_ctr()) } - } - - #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))] - pub fn sm4_cfb128() -> Cipher { - unsafe { Cipher(ffi::EVP_sm4_cfb128()) } - } - - #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))] - pub fn sm4_ofb() -> Cipher { - unsafe { Cipher(ffi::EVP_sm4_ofb()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_RC2"))] - pub fn rc2_cbc() -> Cipher { - unsafe { Cipher(ffi::EVP_rc2_cbc()) } - } - - #[cfg(not(osslconf = "OPENSSL_NO_RC2"))] - pub fn rc2_40_cbc() -> Cipher { - unsafe { Cipher(ffi::EVP_rc2_40_cbc()) } - } - - /// Creates a `Cipher` from a raw pointer to its OpenSSL type. - /// - /// # Safety - /// - /// The caller must ensure the pointer is valid for the `'static` lifetime. - pub unsafe fn from_ptr(ptr: *const ffi::EVP_CIPHER) -> Cipher { - Cipher(ptr) - } - - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn as_ptr(&self) -> *const ffi::EVP_CIPHER { - self.0 - } - - /// Returns the length of keys used with this cipher. - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn key_len(&self) -> usize { - unsafe { EVP_CIPHER_key_length(self.0) as usize } - } - - /// Returns the length of the IV used with this cipher, or `None` if the - /// cipher does not use an IV. - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn iv_len(&self) -> Option { - unsafe { - let len = EVP_CIPHER_iv_length(self.0) as usize; - if len == 0 { - None - } else { - Some(len) - } - } - } - - /// Returns the block size of the cipher. - /// - /// # Note - /// - /// Stream ciphers such as RC4 have a block size of 1. - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn block_size(&self) -> usize { - unsafe { EVP_CIPHER_block_size(self.0) as usize } - } - - /// Determines whether the cipher is using CCM mode - #[cfg(not(any(boringssl, awslc)))] - fn is_ccm(self) -> bool { - // NOTE: OpenSSL returns pointers to static structs, which makes this work as expected - self == Cipher::aes_128_ccm() || self == Cipher::aes_256_ccm() - } - - #[cfg(any(boringssl, awslc))] - fn is_ccm(self) -> bool { - false - } - - /// Determines whether the cipher is using OCB mode - #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))] - fn is_ocb(self) -> bool { - self == Cipher::aes_128_ocb() - || self == Cipher::aes_192_ocb() - || self == Cipher::aes_256_ocb() - } - - #[cfg(any(not(ossl110), osslconf = "OPENSSL_NO_OCB"))] - const fn is_ocb(self) -> bool { - false - } -} - -unsafe impl Sync for Cipher {} -unsafe impl Send for Cipher {} - -/// Represents a symmetric cipher context. -/// -/// Padding is enabled by default. -/// -/// # Examples -/// -/// Encrypt some plaintext in chunks, then decrypt the ciphertext back into plaintext, in AES 128 -/// CBC mode. -/// -/// ``` -/// use openssl::symm::{Cipher, Mode, Crypter}; -/// -/// let plaintexts: [&[u8]; 2] = [b"Some Stream of", b" 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 data_len = plaintexts.iter().fold(0, |sum, x| sum + x.len()); -/// -/// // Create a cipher context for encryption. -/// let mut encrypter = Crypter::new( -/// Cipher::aes_128_cbc(), -/// Mode::Encrypt, -/// key, -/// Some(iv)).unwrap(); -/// -/// let block_size = Cipher::aes_128_cbc().block_size(); -/// let mut ciphertext = vec![0; data_len + block_size]; -/// -/// // Encrypt 2 chunks of plaintexts successively. -/// let mut count = encrypter.update(plaintexts[0], &mut ciphertext).unwrap(); -/// count += encrypter.update(plaintexts[1], &mut ciphertext[count..]).unwrap(); -/// count += encrypter.finalize(&mut ciphertext[count..]).unwrap(); -/// ciphertext.truncate(count); -/// -/// assert_eq!( -/// b"\x0F\x21\x83\x7E\xB2\x88\x04\xAF\xD9\xCC\xE2\x03\x49\xB4\x88\xF6\xC4\x61\x0E\x32\x1C\xF9\ -/// \x0D\x66\xB1\xE6\x2C\x77\x76\x18\x8D\x99", -/// &ciphertext[..] -/// ); -/// -/// -/// // Let's pretend we don't know the plaintext, and now decrypt the ciphertext. -/// let data_len = ciphertext.len(); -/// let ciphertexts = [&ciphertext[..9], &ciphertext[9..]]; -/// -/// // Create a cipher context for decryption. -/// let mut decrypter = Crypter::new( -/// Cipher::aes_128_cbc(), -/// Mode::Decrypt, -/// key, -/// Some(iv)).unwrap(); -/// let mut plaintext = vec![0; data_len + block_size]; -/// -/// // Decrypt 2 chunks of ciphertexts successively. -/// let mut count = decrypter.update(ciphertexts[0], &mut plaintext).unwrap(); -/// count += decrypter.update(ciphertexts[1], &mut plaintext[count..]).unwrap(); -/// count += decrypter.finalize(&mut plaintext[count..]).unwrap(); -/// plaintext.truncate(count); -/// -/// assert_eq!(b"Some Stream of Crypto Text", &plaintext[..]); -/// ``` -pub struct Crypter { - ctx: CipherCtx, -} - -impl Crypter { - /// Creates a new `Crypter`. The initialisation vector, `iv`, is not necessary for certain - /// types of `Cipher`. - /// - /// # Panics - /// - /// Panics if an IV is required by the cipher but not provided. Also make sure that the key - /// and IV size are appropriate for your cipher. - pub fn new( - t: Cipher, - mode: Mode, - key: &[u8], - iv: Option<&[u8]>, - ) -> Result { - let mut ctx = CipherCtx::new()?; - - let f = match mode { - Mode::Encrypt => CipherCtxRef::encrypt_init, - Mode::Decrypt => CipherCtxRef::decrypt_init, - }; - - f( - &mut ctx, - Some(unsafe { CipherRef::from_ptr(t.as_ptr() as *mut _) }), - None, - None, - )?; - - ctx.set_key_length(key.len())?; - - if let (Some(iv), Some(iv_len)) = (iv, t.iv_len()) { - if iv.len() != iv_len { - ctx.set_iv_length(iv.len())?; - } - } - - f(&mut ctx, None, Some(key), iv)?; - - Ok(Crypter { ctx }) - } - - /// Enables or disables padding. - /// - /// If padding is disabled, total amount of data encrypted/decrypted must - /// be a multiple of the cipher's block size. - pub fn pad(&mut self, padding: bool) { - self.ctx.set_padding(padding) - } - - /// Sets the tag used to authenticate ciphertext in AEAD ciphers such as AES GCM. - /// - /// When decrypting cipher text using an AEAD cipher, this must be called before `finalize`. - pub fn set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack> { - self.ctx.set_tag(tag) - } - - /// Sets the length of the authentication tag to generate in AES CCM. - /// - /// When encrypting with AES CCM, the tag length needs to be explicitly set in order - /// to use a value different than the default 12 bytes. - pub fn set_tag_len(&mut self, tag_len: usize) -> Result<(), ErrorStack> { - self.ctx.set_tag_length(tag_len) - } - - /// Feeds total plaintext length to the cipher. - /// - /// The total plaintext or ciphertext length MUST be passed to the cipher when it operates in - /// CCM mode. - pub fn set_data_len(&mut self, data_len: usize) -> Result<(), ErrorStack> { - self.ctx.set_data_len(data_len) - } - - /// Feeds Additional Authenticated Data (AAD) through the cipher. - /// - /// This can only be used with AEAD ciphers such as AES GCM. Data fed in is not encrypted, but - /// is factored into the authentication tag. It must be called before the first call to - /// `update`. - pub fn aad_update(&mut self, input: &[u8]) -> Result<(), ErrorStack> { - self.ctx.cipher_update(input, None)?; - Ok(()) - } - - /// Feeds data from `input` through the cipher, writing encrypted/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 for stream ciphers if `output.len() < input.len()`. - /// - /// Panics for block ciphers if `output.len() < input.len() + block_size`, - /// where `block_size` is the block size of the cipher (see `Cipher::block_size`). - /// - /// Panics if `output.len() > c_int::MAX`. - pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result { - self.ctx.cipher_update(input, Some(output)) - } - - /// Feeds data from `input` through the cipher, writing encrypted/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`. - /// - /// # Safety - /// - /// The caller must provide an `output` buffer large enough to contain - /// correct number of bytes. For streaming ciphers the output buffer size - /// should be at least as big as the input buffer. For block ciphers the - /// size of the output buffer depends on the state of partially updated - /// blocks. - pub unsafe fn update_unchecked( - &mut self, - input: &[u8], - output: &mut [u8], - ) -> Result { - self.ctx.cipher_update_unchecked(input, Some(output)) - } - - /// Finishes the encryption/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 for block ciphers if `output.len() < block_size`, - /// where `block_size` is the block size of the cipher (see `Cipher::block_size`). - pub fn finalize(&mut self, output: &mut [u8]) -> Result { - self.ctx.cipher_final(output) - } - - /// Retrieves the authentication tag used to authenticate ciphertext in AEAD ciphers such - /// as AES GCM. - /// - /// When encrypting data with an AEAD cipher, this must be called after `finalize`. - /// - /// The size of the buffer indicates the required size of the tag. While some ciphers support a - /// range of tag sizes, it is recommended to pick the maximum size. For AES GCM, this is 16 - /// bytes, for example. - pub fn get_tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> { - self.ctx.tag(tag) - } -} - -/// Encrypts data in one go, and returns the encrypted data. -/// -/// Data is encrypted using the specified cipher type `t` in encrypt mode with the specified `key` -/// and initialization vector `iv`. Padding is enabled. -/// -/// This is a convenient interface to `Crypter` to encrypt all data in one go. To encrypt a stream -/// of data incrementally , use `Crypter` instead. -/// -/// # Examples -/// -/// Encrypt data in AES128 CBC mode -/// -/// ``` -/// use openssl::symm::{encrypt, Cipher}; -/// -/// 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 ciphertext = encrypt( -/// cipher, -/// key, -/// Some(iv), -/// data).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[..]); -/// ``` -pub fn encrypt( - t: Cipher, - key: &[u8], - iv: Option<&[u8]>, - data: &[u8], -) -> Result, ErrorStack> { - cipher(t, Mode::Encrypt, key, iv, data) -} - -/// Decrypts data in one go, and returns the decrypted data. -/// -/// Data is decrypted using the specified cipher type `t` in decrypt mode with the specified `key` -/// and initialization vector `iv`. Padding is enabled. -/// -/// This is a convenient interface to `Crypter` to decrypt all data in one go. To decrypt a stream -/// of data incrementally , use `Crypter` instead. -/// -/// # Examples -/// -/// Decrypt data in AES128 CBC mode -/// -/// ``` -/// use openssl::symm::{decrypt, Cipher}; -/// -/// 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 ciphertext = decrypt( -/// cipher, -/// key, -/// Some(iv), -/// data).unwrap(); -/// -/// assert_eq!( -/// b"Some Crypto Text", -/// &ciphertext[..]); -/// ``` -pub fn decrypt( - t: Cipher, - key: &[u8], - iv: Option<&[u8]>, - data: &[u8], -) -> Result, ErrorStack> { - cipher(t, Mode::Decrypt, key, iv, data) -} - -fn cipher( - t: Cipher, - mode: Mode, - key: &[u8], - iv: Option<&[u8]>, - data: &[u8], -) -> Result, ErrorStack> { - let mut c = Crypter::new(t, mode, key, iv)?; - let mut out = vec![0; data.len() + t.block_size()]; - let count = c.update(data, &mut out)?; - let rest = c.finalize(&mut out[count..])?; - out.truncate(count + rest); - Ok(out) -} - -/// Like `encrypt`, but for AEAD ciphers such as AES GCM. -/// -/// Additional Authenticated Data can be provided in the `aad` field, and the authentication tag -/// will be copied into the `tag` field. -/// -/// The size of the `tag` buffer indicates the required size of the tag. While some ciphers support -/// a range of tag sizes, it is recommended to pick the maximum size. For AES GCM, this is 16 bytes, -/// for example. -pub fn encrypt_aead( - t: Cipher, - key: &[u8], - iv: Option<&[u8]>, - aad: &[u8], - data: &[u8], - tag: &mut [u8], -) -> Result, ErrorStack> { - let mut c = Crypter::new(t, Mode::Encrypt, key, iv)?; - let mut out = vec![0; data.len() + t.block_size()]; - - let is_ccm = t.is_ccm(); - if is_ccm || t.is_ocb() { - c.set_tag_len(tag.len())?; - if is_ccm { - c.set_data_len(data.len())?; - } - } - - c.aad_update(aad)?; - let count = c.update(data, &mut out)?; - let rest = c.finalize(&mut out[count..])?; - c.get_tag(tag)?; - out.truncate(count + rest); - Ok(out) -} - -/// Like `decrypt`, but for AEAD ciphers such as AES GCM. -/// -/// Additional Authenticated Data can be provided in the `aad` field, and the authentication tag -/// should be provided in the `tag` field. -pub fn decrypt_aead( - t: Cipher, - key: &[u8], - iv: Option<&[u8]>, - aad: &[u8], - data: &[u8], - tag: &[u8], -) -> Result, ErrorStack> { - let mut c = Crypter::new(t, Mode::Decrypt, key, iv)?; - let mut out = vec![0; data.len() + t.block_size()]; - - let is_ccm = t.is_ccm(); - if is_ccm || t.is_ocb() { - c.set_tag(tag)?; - if is_ccm { - c.set_data_len(data.len())?; - } - } - - c.aad_update(aad)?; - let count = c.update(data, &mut out)?; - - let rest = if t.is_ccm() { - 0 - } else { - c.set_tag(tag)?; - c.finalize(&mut out[count..])? - }; - - out.truncate(count + rest); - Ok(out) -} - -cfg_if! { - if #[cfg(any(boringssl, ossl110, libressl, awslc))] { - use ffi::{EVP_CIPHER_block_size, EVP_CIPHER_iv_length, EVP_CIPHER_key_length}; - } else { - use crate::LenType; - - #[allow(bad_style)] - pub unsafe fn EVP_CIPHER_iv_length(ptr: *const ffi::EVP_CIPHER) -> LenType { - (*ptr).iv_len - } - - #[allow(bad_style)] - pub unsafe fn EVP_CIPHER_block_size(ptr: *const ffi::EVP_CIPHER) -> LenType { - (*ptr).block_size - } - - #[allow(bad_style)] - pub unsafe fn EVP_CIPHER_key_length(ptr: *const ffi::EVP_CIPHER) -> LenType { - (*ptr).key_len - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use hex::{self, FromHex}; - - #[test] - fn test_stream_cipher_output() { - let key = [0u8; 16]; - let iv = [0u8; 16]; - let mut c = super::Crypter::new( - super::Cipher::aes_128_ctr(), - super::Mode::Encrypt, - &key, - Some(&iv), - ) - .unwrap(); - - assert_eq!(c.update(&[0u8; 15], &mut [0u8; 15]).unwrap(), 15); - assert_eq!(c.update(&[0u8; 1], &mut [0u8; 1]).unwrap(), 1); - assert_eq!(c.finalize(&mut [0u8; 0]).unwrap(), 0); - } - - // Test vectors from FIPS-197: - // http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf - #[test] - fn test_aes_256_ecb() { - let k0 = [ - 0x00u8, 0x01u8, 0x02u8, 0x03u8, 0x04u8, 0x05u8, 0x06u8, 0x07u8, 0x08u8, 0x09u8, 0x0au8, - 0x0bu8, 0x0cu8, 0x0du8, 0x0eu8, 0x0fu8, 0x10u8, 0x11u8, 0x12u8, 0x13u8, 0x14u8, 0x15u8, - 0x16u8, 0x17u8, 0x18u8, 0x19u8, 0x1au8, 0x1bu8, 0x1cu8, 0x1du8, 0x1eu8, 0x1fu8, - ]; - let p0 = [ - 0x00u8, 0x11u8, 0x22u8, 0x33u8, 0x44u8, 0x55u8, 0x66u8, 0x77u8, 0x88u8, 0x99u8, 0xaau8, - 0xbbu8, 0xccu8, 0xddu8, 0xeeu8, 0xffu8, - ]; - let c0 = [ - 0x8eu8, 0xa2u8, 0xb7u8, 0xcau8, 0x51u8, 0x67u8, 0x45u8, 0xbfu8, 0xeau8, 0xfcu8, 0x49u8, - 0x90u8, 0x4bu8, 0x49u8, 0x60u8, 0x89u8, - ]; - let mut c = super::Crypter::new( - super::Cipher::aes_256_ecb(), - super::Mode::Encrypt, - &k0, - None, - ) - .unwrap(); - c.pad(false); - let mut r0 = vec![0; c0.len() + super::Cipher::aes_256_ecb().block_size()]; - let count = c.update(&p0, &mut r0).unwrap(); - let rest = c.finalize(&mut r0[count..]).unwrap(); - r0.truncate(count + rest); - assert_eq!(hex::encode(&r0), hex::encode(c0)); - - let mut c = super::Crypter::new( - super::Cipher::aes_256_ecb(), - super::Mode::Decrypt, - &k0, - None, - ) - .unwrap(); - c.pad(false); - let mut p1 = vec![0; r0.len() + super::Cipher::aes_256_ecb().block_size()]; - let count = c.update(&r0, &mut p1).unwrap(); - let rest = c.finalize(&mut p1[count..]).unwrap(); - p1.truncate(count + rest); - assert_eq!(hex::encode(p1), hex::encode(p0)); - } - - #[test] - fn test_aes_256_cbc_decrypt() { - let iv = [ - 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, - ]; - 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 ciphered_data = [ - 0x4a_u8, 0x2e_u8, 0xe5_u8, 0x6_u8, 0xbf_u8, 0xcf_u8, 0xf2_u8, 0xd7_u8, 0xea_u8, - 0x2d_u8, 0xb1_u8, 0x85_u8, 0x6c_u8, 0x93_u8, 0x65_u8, 0x6f_u8, - ]; - let mut cr = super::Crypter::new( - super::Cipher::aes_256_cbc(), - super::Mode::Decrypt, - &data, - Some(&iv), - ) - .unwrap(); - cr.pad(false); - let mut unciphered_data = vec![0; data.len() + super::Cipher::aes_256_cbc().block_size()]; - let count = cr.update(&ciphered_data, &mut unciphered_data).unwrap(); - let rest = cr.finalize(&mut unciphered_data[count..]).unwrap(); - unciphered_data.truncate(count + rest); - - let expected_unciphered_data = b"I love turtles.\x01"; - - assert_eq!(&unciphered_data, expected_unciphered_data); - } - - fn cipher_test(ciphertype: super::Cipher, pt: &str, ct: &str, key: &str, iv: &str) { - let pt = Vec::from_hex(pt).unwrap(); - let ct = Vec::from_hex(ct).unwrap(); - let key = Vec::from_hex(key).unwrap(); - let iv = Vec::from_hex(iv).unwrap(); - - let computed = super::decrypt(ciphertype, &key, Some(&iv), &ct).unwrap(); - let expected = pt; - - if computed != expected { - println!("Computed: {}", hex::encode(&computed)); - println!("Expected: {}", hex::encode(&expected)); - if computed.len() != expected.len() { - println!( - "Lengths differ: {} in computed vs {} expected", - computed.len(), - expected.len() - ); - } - panic!("test failure"); - } - } - - #[cfg(not(any(boringssl, awslc)))] - fn cipher_test_nopad(ciphertype: super::Cipher, pt: &str, ct: &str, key: &str, iv: &str) { - let pt = Vec::from_hex(pt).unwrap(); - let ct = Vec::from_hex(ct).unwrap(); - let key = Vec::from_hex(key).unwrap(); - let iv = Vec::from_hex(iv).unwrap(); - - let computed = { - let mut c = Crypter::new(ciphertype, Mode::Decrypt, &key, Some(&iv)).unwrap(); - c.pad(false); - let mut out = vec![0; ct.len() + ciphertype.block_size()]; - let count = c.update(&ct, &mut out).unwrap(); - let rest = c.finalize(&mut out[count..]).unwrap(); - out.truncate(count + rest); - out - }; - let expected = pt; - - if computed != expected { - println!("Computed: {}", hex::encode(&computed)); - println!("Expected: {}", hex::encode(&expected)); - if computed.len() != expected.len() { - println!( - "Lengths differ: {} in computed vs {} expected", - computed.len(), - expected.len() - ); - } - panic!("test failure"); - } - } - - #[test] - fn test_rc4() { - #[cfg(ossl300)] - let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); - - let pt = "0000000000000000000000000000000000000000000000000000000000000000000000000000"; - let ct = "A68686B04D686AA107BD8D4CAB191A3EEC0A6294BC78B60F65C25CB47BD7BB3A48EFC4D26BE4"; - let key = "97CD440324DA5FD1F7955C1C13B6B466"; - let iv = ""; - - cipher_test(super::Cipher::rc4(), pt, ct, key, iv); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn test_aes256_xts() { - // Test case 174 from - // http://csrc.nist.gov/groups/STM/cavp/documents/aes/XTSTestVectors.zip - let pt = "77f4ef63d734ebd028508da66c22cdebdd52ecd6ee2ab0a50bc8ad0cfd692ca5fcd4e6dedc45df7f\ - 6503f462611dc542"; - let ct = "ce7d905a7776ac72f240d22aafed5e4eb7566cdc7211220e970da634ce015f131a5ecb8d400bc9e8\ - 4f0b81d8725dbbc7"; - let key = "b6bfef891f83b5ff073f2231267be51eb084b791fa19a154399c0684c8b2dfcb37de77d28bbda3b\ - 4180026ad640b74243b3133e7b9fae629403f6733423dae28"; - let iv = "db200efb7eaaa737dbdf40babb68953f"; - - cipher_test(super::Cipher::aes_256_xts(), pt, ct, key, iv); - } - - #[test] - fn test_aes128_ctr() { - let pt = "6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411\ - E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710"; - let ct = "874D6191B620E3261BEF6864990DB6CE9806F66B7970FDFF8617187BB9FFFDFF5AE4DF3EDBD5D35E\ - 5B4F09020DB03EAB1E031DDA2FBE03D1792170A0F3009CEE"; - let key = "2B7E151628AED2A6ABF7158809CF4F3C"; - let iv = "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"; - - cipher_test(super::Cipher::aes_128_ctr(), pt, ct, key, iv); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn test_aes128_cfb1() { - // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - - let pt = "6bc1"; - let ct = "68b3"; - let key = "2b7e151628aed2a6abf7158809cf4f3c"; - let iv = "000102030405060708090a0b0c0d0e0f"; - - cipher_test(super::Cipher::aes_128_cfb1(), pt, ct, key, iv); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn test_aes128_cfb128() { - let pt = "6bc1bee22e409f96e93d7e117393172a"; - let ct = "3b3fd92eb72dad20333449f8e83cfb4a"; - let key = "2b7e151628aed2a6abf7158809cf4f3c"; - let iv = "000102030405060708090a0b0c0d0e0f"; - - cipher_test(super::Cipher::aes_128_cfb128(), pt, ct, key, iv); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn test_aes128_cfb8() { - let pt = "6bc1bee22e409f96e93d7e117393172aae2d"; - let ct = "3b79424c9c0dd436bace9e0ed4586a4f32b9"; - let key = "2b7e151628aed2a6abf7158809cf4f3c"; - let iv = "000102030405060708090a0b0c0d0e0f"; - - cipher_test(super::Cipher::aes_128_cfb8(), pt, ct, key, iv); - } - - #[test] - fn test_aes128_ofb() { - // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - - let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"; - let ct = "3b3fd92eb72dad20333449f8e83cfb4a7789508d16918f03f53c52dac54ed8259740051e9c5fecf64344f7a82260edcc304c6528f659c77866a510d9c1d6ae5e"; - let key = "2b7e151628aed2a6abf7158809cf4f3c"; - let iv = "000102030405060708090a0b0c0d0e0f"; - - cipher_test(super::Cipher::aes_128_ofb(), pt, ct, key, iv); - } - - #[test] - fn test_aes192_ctr() { - // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - - let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"; - let ct = "1abc932417521ca24f2b0459fe7e6e0b090339ec0aa6faefd5ccc2c6f4ce8e941e36b26bd1ebc670d1bd1d665620abf74f78a7f6d29809585a97daec58c6b050"; - let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; - let iv = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; - - cipher_test(super::Cipher::aes_192_ctr(), pt, ct, key, iv); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn test_aes192_cfb1() { - // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - - let pt = "6bc1"; - let ct = "9359"; - let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; - let iv = "000102030405060708090a0b0c0d0e0f"; - - cipher_test(super::Cipher::aes_192_cfb1(), pt, ct, key, iv); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn test_aes192_cfb128() { - // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - - let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"; - let ct = "cdc80d6fddf18cab34c25909c99a417467ce7f7f81173621961a2b70171d3d7a2e1e8a1dd59b88b1c8e60fed1efac4c9c05f9f9ca9834fa042ae8fba584b09ff"; - let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; - let iv = "000102030405060708090a0b0c0d0e0f"; - - cipher_test(super::Cipher::aes_192_cfb128(), pt, ct, key, iv); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn test_aes192_cfb8() { - // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - - let pt = "6bc1bee22e409f96e93d7e117393172aae2d"; - let ct = "cda2521ef0a905ca44cd057cbf0d47a0678a"; - let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; - let iv = "000102030405060708090a0b0c0d0e0f"; - - cipher_test(super::Cipher::aes_192_cfb8(), pt, ct, key, iv); - } - - #[test] - fn test_aes192_ofb() { - // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - - let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"; - let ct = "cdc80d6fddf18cab34c25909c99a4174fcc28b8d4c63837c09e81700c11004018d9a9aeac0f6596f559c6d4daf59a5f26d9f200857ca6c3e9cac524bd9acc92a"; - let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; - let iv = "000102030405060708090a0b0c0d0e0f"; - - cipher_test(super::Cipher::aes_192_ofb(), pt, ct, key, iv); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn test_aes256_cfb1() { - let pt = "6bc1"; - let ct = "9029"; - let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; - let iv = "000102030405060708090a0b0c0d0e0f"; - - cipher_test(super::Cipher::aes_256_cfb1(), pt, ct, key, iv); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn test_aes256_cfb128() { - let pt = "6bc1bee22e409f96e93d7e117393172a"; - let ct = "dc7e84bfda79164b7ecd8486985d3860"; - let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; - let iv = "000102030405060708090a0b0c0d0e0f"; - - cipher_test(super::Cipher::aes_256_cfb128(), pt, ct, key, iv); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn test_aes256_cfb8() { - let pt = "6bc1bee22e409f96e93d7e117393172aae2d"; - let ct = "dc1f1a8520a64db55fcc8ac554844e889700"; - let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; - let iv = "000102030405060708090a0b0c0d0e0f"; - - cipher_test(super::Cipher::aes_256_cfb8(), pt, ct, key, iv); - } - - #[test] - fn test_aes256_ofb() { - // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - - let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"; - let ct = "dc7e84bfda79164b7ecd8486985d38604febdc6740d20b3ac88f6ad82a4fb08d71ab47a086e86eedf39d1c5bba97c4080126141d67f37be8538f5a8be740e484"; - let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; - let iv = "000102030405060708090a0b0c0d0e0f"; - - cipher_test(super::Cipher::aes_256_ofb(), pt, ct, key, iv); - } - - #[test] - #[cfg_attr(ossl300, ignore)] - #[cfg(not(any(boringssl, awslc)))] - fn test_bf_cbc() { - #[cfg(ossl300)] - let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); - - // https://www.schneier.com/code/vectors.txt - - let pt = "37363534333231204E6F77206973207468652074696D6520666F722000000000"; - let ct = "6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC"; - let key = "0123456789ABCDEFF0E1D2C3B4A59687"; - let iv = "FEDCBA9876543210"; - - cipher_test_nopad(super::Cipher::bf_cbc(), pt, ct, key, iv); - } - - #[test] - #[cfg_attr(ossl300, ignore)] - #[cfg(not(any(boringssl, awslc)))] - fn test_bf_ecb() { - #[cfg(ossl300)] - let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); - - let pt = "5CD54CA83DEF57DA"; - let ct = "B1B8CC0B250F09A0"; - let key = "0131D9619DC1376E"; - let iv = "0000000000000000"; - - cipher_test_nopad(super::Cipher::bf_ecb(), pt, ct, key, iv); - } - - #[test] - #[cfg_attr(ossl300, ignore)] - #[cfg(not(any(boringssl, awslc)))] - fn test_bf_cfb64() { - #[cfg(ossl300)] - let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); - - let pt = "37363534333231204E6F77206973207468652074696D6520666F722000"; - let ct = "E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3"; - let key = "0123456789ABCDEFF0E1D2C3B4A59687"; - let iv = "FEDCBA9876543210"; - - cipher_test_nopad(super::Cipher::bf_cfb64(), pt, ct, key, iv); - } - - #[test] - #[cfg_attr(ossl300, ignore)] - #[cfg(not(any(boringssl, awslc)))] - fn test_bf_ofb() { - #[cfg(ossl300)] - let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); - - let pt = "37363534333231204E6F77206973207468652074696D6520666F722000"; - let ct = "E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA"; - let key = "0123456789ABCDEFF0E1D2C3B4A59687"; - let iv = "FEDCBA9876543210"; - - cipher_test_nopad(super::Cipher::bf_ofb(), pt, ct, key, iv); - } - - #[test] - fn test_des_cbc() { - #[cfg(ossl300)] - let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); - - let pt = "54686973206973206120746573742e"; - let ct = "6f2867cfefda048a4046ef7e556c7132"; - let key = "7cb66337f3d3c0fe"; - let iv = "0001020304050607"; - - cipher_test(super::Cipher::des_cbc(), pt, ct, key, iv); - } - - #[test] - fn test_des_ecb() { - #[cfg(ossl300)] - let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); - - let pt = "54686973206973206120746573742e"; - let ct = "0050ab8aecec758843fe157b4dde938c"; - let key = "7cb66337f3d3c0fe"; - let iv = "0001020304050607"; - - cipher_test(super::Cipher::des_ecb(), pt, ct, key, iv); - } - - #[test] - fn test_des_ede3() { - let pt = "9994f4c69d40ae4f34ff403b5cf39d4c8207ea5d3e19a5fd"; - let ct = "9e5c4297d60582f81071ac8ab7d0698d4c79de8b94c519858207ea5d3e19a5fd"; - let key = "010203040506070801020304050607080102030405060708"; - let iv = "5cc118306dc702e4"; - - cipher_test(super::Cipher::des_ede3(), pt, ct, key, iv); - } - - #[test] - fn test_des_ede3_cbc() { - let pt = "54686973206973206120746573742e"; - let ct = "6f2867cfefda048a4046ef7e556c7132"; - let key = "7cb66337f3d3c0fe7cb66337f3d3c0fe7cb66337f3d3c0fe"; - let iv = "0001020304050607"; - - cipher_test(super::Cipher::des_ede3_cbc(), pt, ct, key, iv); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn test_des_ede3_cfb64() { - let pt = "2b1773784b5889dc788477367daa98ad"; - let ct = "6f2867cfefda048a4046ef7e556c7132"; - let key = "7cb66337f3d3c0fe7cb66337f3d3c0fe7cb66337f3d3c0fe"; - let iv = "0001020304050607"; - - cipher_test(super::Cipher::des_ede3_cfb64(), pt, ct, key, iv); - } - - #[test] - fn test_aes128_gcm() { - let key = "23dc8d23d95b6fd1251741a64f7d4f41"; - let iv = "f416f48ad44d9efa1179e167"; - let pt = "6cb9b71dd0ccd42cdf87e8e396fc581fd8e0d700e360f590593b748e105390de"; - let aad = "45074844c97d515c65bbe37c210a5a4b08c21c588efe5c5f73c4d9c17d34dacddc0bb6a8a53f7bf477b9780c1c2a928660df87016b2873fe876b2b887fb5886bfd63216b7eaecc046372a82c047eb043f0b063226ee52a12c69b"; - let ct = "8ad20486778e87387efb3f2574e509951c0626816722018129e578b2787969d3"; - let tag = "91e1bc09"; - - // this tag is smaller than you'd normally want, but I pulled this test from the part of - // the NIST test vectors that cover 4 byte tags. - let mut actual_tag = [0; 4]; - let out = encrypt_aead( - Cipher::aes_128_gcm(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(iv).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(pt).unwrap(), - &mut actual_tag, - ) - .unwrap(); - assert_eq!(ct, hex::encode(out)); - assert_eq!(tag, hex::encode(actual_tag)); - - let out = decrypt_aead( - Cipher::aes_128_gcm(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(iv).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(ct).unwrap(), - &Vec::from_hex(tag).unwrap(), - ) - .unwrap(); - assert_eq!(pt, hex::encode(out)); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn test_aes128_ccm() { - let key = "3ee186594f110fb788a8bf8aa8be5d4a"; - let nonce = "44f705d52acf27b7f17196aa9b"; - let aad = "2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57"; - - let pt = "d71864877f2578db092daba2d6a1f9f4698a9c356c7830a1"; - let ct = "b4dd74e7a0cc51aea45dfb401a41d5822c96901a83247ea0"; - let tag = "d6965f5aa6e31302a9cc2b36"; - - let mut actual_tag = [0; 12]; - let out = encrypt_aead( - Cipher::aes_128_ccm(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(nonce).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(pt).unwrap(), - &mut actual_tag, - ) - .unwrap(); - - assert_eq!(ct, hex::encode(out)); - assert_eq!(tag, hex::encode(actual_tag)); - - let out = decrypt_aead( - Cipher::aes_128_ccm(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(nonce).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(ct).unwrap(), - &Vec::from_hex(tag).unwrap(), - ) - .unwrap(); - assert_eq!(pt, hex::encode(out)); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn test_aes128_ccm_verify_fail() { - let key = "3ee186594f110fb788a8bf8aa8be5d4a"; - let nonce = "44f705d52acf27b7f17196aa9b"; - let aad = "2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57"; - - let ct = "b4dd74e7a0cc51aea45dfb401a41d5822c96901a83247ea0"; - let tag = "00005f5aa6e31302a9cc2b36"; - - let out = decrypt_aead( - Cipher::aes_128_ccm(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(nonce).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(ct).unwrap(), - &Vec::from_hex(tag).unwrap(), - ); - assert!(out.is_err()); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn test_aes256_ccm() { - let key = "7f4af6765cad1d511db07e33aaafd57646ec279db629048aa6770af24849aa0d"; - let nonce = "dde2a362ce81b2b6913abc3095"; - let aad = "404f5df97ece7431987bc098cce994fc3c063b519ffa47b0365226a0015ef695"; - - let pt = "7ebef26bf4ecf6f0ebb2eb860edbf900f27b75b4a6340fdb"; - let ct = "353022db9c568bd7183a13c40b1ba30fcc768c54264aa2cd"; - let tag = "2927a053c9244d3217a7ad05"; - - let mut actual_tag = [0; 12]; - let out = encrypt_aead( - Cipher::aes_256_ccm(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(nonce).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(pt).unwrap(), - &mut actual_tag, - ) - .unwrap(); - - assert_eq!(ct, hex::encode(out)); - assert_eq!(tag, hex::encode(actual_tag)); - - let out = decrypt_aead( - Cipher::aes_256_ccm(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(nonce).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(ct).unwrap(), - &Vec::from_hex(tag).unwrap(), - ) - .unwrap(); - assert_eq!(pt, hex::encode(out)); - } - - #[test] - #[cfg(not(any(boringssl, awslc)))] - fn test_aes256_ccm_verify_fail() { - let key = "7f4af6765cad1d511db07e33aaafd57646ec279db629048aa6770af24849aa0d"; - let nonce = "dde2a362ce81b2b6913abc3095"; - let aad = "404f5df97ece7431987bc098cce994fc3c063b519ffa47b0365226a0015ef695"; - - let ct = "353022db9c568bd7183a13c40b1ba30fcc768c54264aa2cd"; - let tag = "0000a053c9244d3217a7ad05"; - - let out = decrypt_aead( - Cipher::aes_256_ccm(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(nonce).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(ct).unwrap(), - &Vec::from_hex(tag).unwrap(), - ); - assert!(out.is_err()); - } - - #[test] - #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))] - fn test_aes_128_ocb() { - let key = "000102030405060708090a0b0c0d0e0f"; - let aad = "0001020304050607"; - let tag = "16dc76a46d47e1ead537209e8a96d14e"; - let iv = "000102030405060708090a0b"; - let pt = "0001020304050607"; - let ct = "92b657130a74b85a"; - - let mut actual_tag = [0; 16]; - let out = encrypt_aead( - Cipher::aes_128_ocb(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(iv).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(pt).unwrap(), - &mut actual_tag, - ) - .unwrap(); - - assert_eq!(ct, hex::encode(out)); - assert_eq!(tag, hex::encode(actual_tag)); - - let out = decrypt_aead( - Cipher::aes_128_ocb(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(iv).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(ct).unwrap(), - &Vec::from_hex(tag).unwrap(), - ) - .unwrap(); - assert_eq!(pt, hex::encode(out)); - } - - #[test] - #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))] - fn test_aes_128_ocb_fail() { - let key = "000102030405060708090a0b0c0d0e0f"; - let aad = "0001020304050607"; - let tag = "16dc76a46d47e1ead537209e8a96d14e"; - let iv = "000000000405060708090a0b"; - let ct = "92b657130a74b85a"; - - let out = decrypt_aead( - Cipher::aes_128_ocb(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(iv).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(ct).unwrap(), - &Vec::from_hex(tag).unwrap(), - ); - assert!(out.is_err()); - } - - #[test] - #[cfg(any(ossl110, libressl))] - fn test_chacha20() { - let key = "0000000000000000000000000000000000000000000000000000000000000000"; - let iv = "00000000000000000000000000000000"; - let pt = - "000000000000000000000000000000000000000000000000000000000000000000000000000000000\ - 00000000000000000000000000000000000000000000000"; - let ct = - "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7\ - 724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586"; - - cipher_test(Cipher::chacha20(), pt, ct, key, iv); - } - - #[test] - #[cfg(any(ossl110, libressl360, awslc))] - fn test_chacha20_poly1305() { - let key = "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f"; - let iv = "070000004041424344454647"; - let aad = "50515253c0c1c2c3c4c5c6c7"; - let pt = - "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393\ - a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f722074\ - 6865206675747572652c2073756e73637265656e20776f756c642062652069742e"; - let ct = - "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca967128\ - 2fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fa\ - b324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116"; - let tag = "1ae10b594f09e26a7e902ecbd0600691"; - - let mut actual_tag = [0; 16]; - let out = encrypt_aead( - Cipher::chacha20_poly1305(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(iv).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(pt).unwrap(), - &mut actual_tag, - ) - .unwrap(); - assert_eq!(ct, hex::encode(out)); - assert_eq!(tag, hex::encode(actual_tag)); - - let out = decrypt_aead( - Cipher::chacha20_poly1305(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(iv).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(ct).unwrap(), - &Vec::from_hex(tag).unwrap(), - ) - .unwrap(); - assert_eq!(pt, hex::encode(out)); - } - - #[test] - #[cfg(not(any(osslconf = "OPENSSL_NO_SEED", ossl300)))] - fn test_seed_cbc() { - #[cfg(ossl300)] - let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); - - let pt = "5363686f6b6f6c6164656e6b756368656e0a"; - let ct = "c2edf0fb2eb11bf7b2f39417a8528896d34b24b6fd79e5923b116dfcd2aba5a4"; - let key = "41414141414141414141414141414141"; - let iv = "41414141414141414141414141414141"; - - cipher_test(super::Cipher::seed_cbc(), pt, ct, key, iv); - } - - #[test] - #[cfg(not(any(osslconf = "OPENSSL_NO_SEED", ossl300)))] - fn test_seed_cfb128() { - #[cfg(ossl300)] - let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); - - let pt = "5363686f6b6f6c6164656e6b756368656e0a"; - let ct = "71d4d25fc1750cb7789259e7f34061939a41"; - let key = "41414141414141414141414141414141"; - let iv = "41414141414141414141414141414141"; - - cipher_test(super::Cipher::seed_cfb128(), pt, ct, key, iv); - } - - #[test] - #[cfg(not(any(osslconf = "OPENSSL_NO_SEED", ossl300)))] - fn test_seed_ecb() { - #[cfg(ossl300)] - let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); - - let pt = "5363686f6b6f6c6164656e6b756368656e0a"; - let ct = "0263a9cd498cf0edb0ef72a3231761d00ce601f7d08ad19ad74f0815f2c77f7e"; - let key = "41414141414141414141414141414141"; - let iv = "41414141414141414141414141414141"; - - cipher_test(super::Cipher::seed_ecb(), pt, ct, key, iv); - } - - #[test] - #[cfg(not(any(osslconf = "OPENSSL_NO_SEED", ossl300)))] - fn test_seed_ofb() { - #[cfg(ossl300)] - let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); - - let pt = "5363686f6b6f6c6164656e6b756368656e0a"; - let ct = "71d4d25fc1750cb7789259e7f34061930afd"; - let key = "41414141414141414141414141414141"; - let iv = "41414141414141414141414141414141"; - - cipher_test(super::Cipher::seed_ofb(), pt, ct, key, iv); - } - - // GB/T 32907-2016 - // http://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=7803DE42D3BC5E80B0C3E5D8E873D56A - #[test] - #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))] - fn test_sm4_ecb() { - use std::mem; - - let key = vec![ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, - 0x32, 0x10, - ]; - let pt = vec![ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, - 0x32, 0x10, - ]; - let ct = vec![ - 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, - 0x42, 0x46, - ]; - let ct1 = vec![ - 0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d, - 0x3f, 0x66, - ]; - - let block_size = Cipher::sm4_ecb().block_size(); - let mut c = Crypter::new(Cipher::sm4_ecb(), Mode::Encrypt, &key, None).unwrap(); - c.pad(false); - - // 1 round - let mut r = vec![0; pt.len() + Cipher::sm4_ecb().block_size()]; - let count = c.update(&pt, &mut r).unwrap(); - assert_eq!(ct, &r[..count]); - - // 1000000 rounds - let mut r1 = vec![0; pt.len() + Cipher::sm4_ecb().block_size()]; - for _ in 0..999999 { - c.update(&r[..block_size], &mut r1).unwrap(); - mem::swap(&mut r, &mut r1); - } - assert_eq!(ct1, &r[..count]); - } -} diff --git a/patch/openssl/src/util.rs b/patch/openssl/src/util.rs deleted file mode 100644 index c903a3209232b..0000000000000 --- a/patch/openssl/src/util.rs +++ /dev/null @@ -1,118 +0,0 @@ -use crate::error::ErrorStack; -use crate::util; -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 { - /// The user callback. Taken out of the `Option` when called. - cb: Option, - /// If the callback panics, we place the panic object here, to be re-thrown once OpenSSL - /// returns. - panic: Option>, -} - -impl CallbackState { - pub fn new(callback: F) -> Self { - CallbackState { - cb: Some(callback), - panic: None, - } - } -} - -impl Drop for CallbackState { - 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( - buf: *mut c_char, - size: c_int, - _rwflag: c_int, - cb_state: *mut c_void, -) -> c_int -where - F: FnOnce(&mut [u8]) -> Result, -{ - let callback = &mut *(cb_state as *mut CallbackState); - - let result = panic::catch_unwind(AssertUnwindSafe(|| { - let pass_slice = util::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 { - if ptr.is_null() { - None - } else { - Some(Self::from_ptr(ptr)) - } - } -} -impl 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 ForeignTypeRefExt for FT {} - -/// The same as `slice::from_raw_parts`, except that `data` may be `NULL` if -/// `len` is 0. -pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { - if len == 0 { - &[] - } else { - // Using this to implement the preferred API - #[allow(clippy::disallowed_methods)] - slice::from_raw_parts(data, len) - } -} - -/// The same as `slice::from_raw_parts_mut`, except that `data` may be `NULL` -/// if `len` is 0. -pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { - if len == 0 { - &mut [] - } else { - // Using this to implement the preferred API - #[allow(clippy::disallowed_methods)] - slice::from_raw_parts_mut(data, len) - } -} diff --git a/patch/openssl/src/version.rs b/patch/openssl/src/version.rs deleted file mode 100644 index dc6f66ad45675..0000000000000 --- a/patch/openssl/src/version.rs +++ /dev/null @@ -1,138 +0,0 @@ -// 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. -// - -//! Build and version information. - -use cfg_if::cfg_if; -use openssl_macros::corresponds; -use std::ffi::CStr; - -cfg_if! { - if #[cfg(any(ossl110, libressl))] { - 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(any(libressl, boringssl, awslc)))] - fn expected_name() -> &'static str { - "OpenSSL" - } - #[cfg(libressl)] - fn expected_name() -> &'static str { - "LibreSSL" - } - #[cfg(boringssl)] - fn expected_name() -> &'static str { - "BoringSSL" - } - #[cfg(awslc)] - fn expected_name() -> &'static str { - "AWS-LC" - } - - 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:")); - } -} diff --git a/patch/openssl/src/x509/extension.rs b/patch/openssl/src/x509/extension.rs deleted file mode 100644 index 11e0151530878..0000000000000 --- a/patch/openssl/src/x509/extension.rs +++ /dev/null @@ -1,562 +0,0 @@ -//! 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::asn1::Asn1Object; -use crate::error::ErrorStack; -use crate::nid::Nid; -use crate::x509::{GeneralName, Stack, X509Extension, X509v3Context}; -use foreign_types::ForeignType; - -/// An extension which indicates whether a certificate is a CA certificate. -pub struct BasicConstraints { - critical: bool, - ca: bool, - pathlen: Option, -} - -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`. - // Temporarily silence the deprecation warning - this should be ported to - // `X509Extension::new_internal`. - #[allow(deprecated)] - pub fn build(&self) -> Result { - 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`. - // Temporarily silence the deprecation warning - this should be ported to - // `X509Extension::new_internal`. - #[allow(deprecated)] - pub fn build(&self) -> Result { - 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, - items: Vec, -} - -impl Default for ExtendedKeyUsage { - fn default() -> ExtendedKeyUsage { - ExtendedKeyUsage::new() - } -} - -impl ExtendedKeyUsage { - /// Construct a new `ExtendedKeyUsage` extension. - pub fn new() -> ExtendedKeyUsage { - ExtendedKeyUsage { - critical: false, - items: 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.other("serverAuth") - } - - /// Sets the `clientAuth` flag to `true`. - pub fn client_auth(&mut self) -> &mut ExtendedKeyUsage { - self.other("clientAuth") - } - - /// Sets the `codeSigning` flag to `true`. - pub fn code_signing(&mut self) -> &mut ExtendedKeyUsage { - self.other("codeSigning") - } - - /// Sets the `emailProtection` flag to `true`. - pub fn email_protection(&mut self) -> &mut ExtendedKeyUsage { - self.other("emailProtection") - } - - /// Sets the `timeStamping` flag to `true`. - pub fn time_stamping(&mut self) -> &mut ExtendedKeyUsage { - self.other("timeStamping") - } - - /// Sets the `msCodeInd` flag to `true`. - pub fn ms_code_ind(&mut self) -> &mut ExtendedKeyUsage { - self.other("msCodeInd") - } - - /// Sets the `msCodeCom` flag to `true`. - pub fn ms_code_com(&mut self) -> &mut ExtendedKeyUsage { - self.other("msCodeCom") - } - - /// Sets the `msCTLSign` flag to `true`. - pub fn ms_ctl_sign(&mut self) -> &mut ExtendedKeyUsage { - self.other("msCTLSign") - } - - /// Sets the `msSGC` flag to `true`. - pub fn ms_sgc(&mut self) -> &mut ExtendedKeyUsage { - self.other("msSGC") - } - - /// Sets the `msEFS` flag to `true`. - pub fn ms_efs(&mut self) -> &mut ExtendedKeyUsage { - self.other("msEFS") - } - - /// Sets the `nsSGC` flag to `true`. - pub fn ns_sgc(&mut self) -> &mut ExtendedKeyUsage { - self.other("nsSGC") - } - - /// Sets a flag not already defined. - pub fn other(&mut self, other: &str) -> &mut ExtendedKeyUsage { - self.items.push(other.to_string()); - self - } - - /// Return the `ExtendedKeyUsage` extension as an `X509Extension`. - pub fn build(&self) -> Result { - let mut stack = Stack::new()?; - for item in &self.items { - stack.push(Asn1Object::from_str(item)?)?; - } - unsafe { - X509Extension::new_internal(Nid::EXT_KEY_USAGE, self.critical, stack.as_ptr().cast()) - } - } -} - -/// 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`. - // Temporarily silence the deprecation warning - this should be ported to - // `X509Extension::new_internal`. - #[allow(deprecated)] - pub fn build(&self, ctx: &X509v3Context<'_>) -> Result { - 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, - issuer: Option, -} - -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`. - // Temporarily silence the deprecation warning - this should be ported to - // `X509Extension::new_internal`. - #[allow(deprecated)] - pub fn build(&self, ctx: &X509v3Context<'_>) -> Result { - 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) - } -} - -enum RustGeneralName { - Dns(String), - Email(String), - Uri(String), - Ip(String), - Rid(String), - OtherName(Asn1Object, Vec), -} - -/// An extension that allows additional identities to be bound to the subject -/// of the certificate. -pub struct SubjectAlternativeName { - critical: bool, - items: Vec, -} - -impl Default for SubjectAlternativeName { - fn default() -> SubjectAlternativeName { - SubjectAlternativeName::new() - } -} - -impl SubjectAlternativeName { - /// Construct a new `SubjectAlternativeName` extension. - pub fn new() -> SubjectAlternativeName { - SubjectAlternativeName { - critical: false, - items: 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.items.push(RustGeneralName::Email(email.to_string())); - self - } - - /// Sets the `uri` flag. - pub fn uri(&mut self, uri: &str) -> &mut SubjectAlternativeName { - self.items.push(RustGeneralName::Uri(uri.to_string())); - self - } - - /// Sets the `dns` flag. - pub fn dns(&mut self, dns: &str) -> &mut SubjectAlternativeName { - self.items.push(RustGeneralName::Dns(dns.to_string())); - self - } - - /// Sets the `rid` flag. - pub fn rid(&mut self, rid: &str) -> &mut SubjectAlternativeName { - self.items.push(RustGeneralName::Rid(rid.to_string())); - self - } - - /// Sets the `ip` flag. - pub fn ip(&mut self, ip: &str) -> &mut SubjectAlternativeName { - self.items.push(RustGeneralName::Ip(ip.to_string())); - self - } - - /// Sets the `dirName` flag. - /// - /// Not currently actually supported, always panics. - #[deprecated = "dir_name is deprecated and always panics. Please file a bug if you have a use case for this."] - pub fn dir_name(&mut self, _dir_name: &str) -> &mut SubjectAlternativeName { - unimplemented!( - "This has not yet been adapted for the new internals. File a bug if you need this." - ); - } - - /// Sets the `otherName` flag. - /// - /// Not currently actually supported, always panics. Please use other_name2 - #[deprecated = "other_name is deprecated and always panics. Please use other_name2."] - pub fn other_name(&mut self, _other_name: &str) -> &mut SubjectAlternativeName { - unimplemented!("This has not yet been adapted for the new internals. Use other_name2."); - } - - /// Sets the `otherName` flag. - /// - /// `content` must be a valid der encoded ASN1_TYPE - /// - /// If you want to add just a ia5string use `other_name_ia5string` - pub fn other_name2(&mut self, oid: Asn1Object, content: &[u8]) -> &mut SubjectAlternativeName { - self.items - .push(RustGeneralName::OtherName(oid, content.into())); - self - } - - /// Return a `SubjectAlternativeName` extension as an `X509Extension`. - pub fn build(&self, _ctx: &X509v3Context<'_>) -> Result { - let mut stack = Stack::new()?; - for item in &self.items { - let gn = match item { - RustGeneralName::Dns(s) => GeneralName::new_dns(s.as_bytes())?, - RustGeneralName::Email(s) => GeneralName::new_email(s.as_bytes())?, - RustGeneralName::Uri(s) => GeneralName::new_uri(s.as_bytes())?, - RustGeneralName::Ip(s) => { - GeneralName::new_ip(s.parse().map_err(|_| ErrorStack::get())?)? - } - RustGeneralName::Rid(s) => GeneralName::new_rid(Asn1Object::from_str(s)?)?, - RustGeneralName::OtherName(oid, content) => { - GeneralName::new_other_name(oid.clone(), content)? - } - }; - stack.push(gn)?; - } - - unsafe { - X509Extension::new_internal(Nid::SUBJECT_ALT_NAME, self.critical, stack.as_ptr().cast()) - } - } -} - -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); -} diff --git a/patch/openssl/src/x509/mod.rs b/patch/openssl/src/x509/mod.rs deleted file mode 100644 index 5fe84fb623463..0000000000000 --- a/patch/openssl/src/x509/mod.rs +++ /dev/null @@ -1,2544 +0,0 @@ -//! The standard defining the format of public key certificates. -//! -//! An `X509` certificate binds an identity to a public key, and is either -//! signed by a certificate authority (CA) or self-signed. An entity that gets -//! a hold of a certificate can both verify your identity (via a CA) and encrypt -//! data with the included public key. `X509` certificates are used in many -//! Internet protocols, including SSL/TLS, which is the basis for HTTPS, -//! the secure protocol for browsing the web. - -use cfg_if::cfg_if; -use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; -use libc::{c_int, c_long, c_uint, c_void}; -use std::cmp::{self, Ordering}; -use std::convert::{TryFrom, TryInto}; -use std::error::Error; -use std::ffi::{CStr, CString}; -use std::fmt; -use std::marker::PhantomData; -use std::mem; -use std::net::IpAddr; -use std::path::Path; -use std::ptr; -use std::str; - -use crate::asn1::{ - Asn1BitStringRef, Asn1Enumerated, Asn1IntegerRef, Asn1Object, Asn1ObjectRef, - Asn1OctetStringRef, Asn1StringRef, Asn1TimeRef, Asn1Type, -}; -use crate::bio::MemBioSlice; -use crate::conf::ConfRef; -use crate::error::ErrorStack; -use crate::ex_data::Index; -use crate::hash::{DigestBytes, MessageDigest}; -use crate::nid::Nid; -use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Public}; -use crate::ssl::SslRef; -use crate::stack::{Stack, StackRef, Stackable}; -use crate::string::OpensslString; -use crate::util::{self, ForeignTypeExt, ForeignTypeRefExt}; -use crate::{cvt, cvt_n, cvt_p, cvt_p_const}; -use openssl_macros::corresponds; - -pub mod verify; - -pub mod extension; -pub mod store; - -#[cfg(test)] -mod tests; - -/// A type of X509 extension. -/// -/// # Safety -/// The value of NID and Output must match those in OpenSSL so that -/// `Output::from_ptr_opt(*_get_ext_d2i(*, NID, ...))` is valid. -pub unsafe trait ExtensionType { - const NID: Nid; - type Output: ForeignType; -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::X509_STORE_CTX; - fn drop = ffi::X509_STORE_CTX_free; - - /// An `X509` certificate store context. - pub struct X509StoreContext; - - /// A reference to an [`X509StoreContext`]. - pub struct X509StoreContextRef; -} - -impl X509StoreContext { - /// Returns the index which can be used to obtain a reference to the `Ssl` associated with a - /// context. - #[corresponds(SSL_get_ex_data_X509_STORE_CTX_idx)] - pub fn ssl_idx() -> Result, ErrorStack> { - unsafe { cvt_n(ffi::SSL_get_ex_data_X509_STORE_CTX_idx()).map(|idx| Index::from_raw(idx)) } - } - - /// Creates a new `X509StoreContext` instance. - #[corresponds(X509_STORE_CTX_new)] - pub fn new() -> Result { - unsafe { - ffi::init(); - cvt_p(ffi::X509_STORE_CTX_new()).map(X509StoreContext) - } - } -} - -impl X509StoreContextRef { - /// Returns application data pertaining to an `X509` store context. - #[corresponds(X509_STORE_CTX_get_ex_data)] - pub fn ex_data(&self, index: Index) -> Option<&T> { - unsafe { - let data = ffi::X509_STORE_CTX_get_ex_data(self.as_ptr(), index.as_raw()); - if data.is_null() { - None - } else { - Some(&*(data as *const T)) - } - } - } - - /// Returns the error code of the context. - #[corresponds(X509_STORE_CTX_get_error)] - pub fn error(&self) -> X509VerifyResult { - unsafe { X509VerifyResult::from_raw(ffi::X509_STORE_CTX_get_error(self.as_ptr())) } - } - - /// Initializes this context with the given certificate, certificates chain and certificate - /// store. After initializing the context, the `with_context` closure is called with the prepared - /// context. As long as the closure is running, the context stays initialized and can be used - /// to e.g. verify a certificate. The context will be cleaned up, after the closure finished. - /// - /// * `trust` - The certificate store with the trusted certificates. - /// * `cert` - The certificate that should be verified. - /// * `cert_chain` - The certificates chain. - /// * `with_context` - The closure that is called with the initialized context. - /// - /// This corresponds to [`X509_STORE_CTX_init`] before calling `with_context` and to - /// [`X509_STORE_CTX_cleanup`] after calling `with_context`. - /// - /// [`X509_STORE_CTX_init`]: https://docs.openssl.org/master/man3/X509_STORE_CTX_init/ - /// [`X509_STORE_CTX_cleanup`]: https://docs.openssl.org/master/man3/X509_STORE_CTX_cleanup/ - pub fn init( - &mut self, - trust: &store::X509StoreRef, - cert: &X509Ref, - cert_chain: &StackRef, - with_context: F, - ) -> Result - where - F: FnOnce(&mut X509StoreContextRef) -> Result, - { - struct Cleanup<'a>(&'a mut X509StoreContextRef); - - impl Drop for Cleanup<'_> { - fn drop(&mut self) { - unsafe { - ffi::X509_STORE_CTX_cleanup(self.0.as_ptr()); - } - } - } - - unsafe { - cvt(ffi::X509_STORE_CTX_init( - self.as_ptr(), - trust.as_ptr(), - cert.as_ptr(), - cert_chain.as_ptr(), - ))?; - - let cleanup = Cleanup(self); - with_context(cleanup.0) - } - } - - /// Verifies the stored certificate. - /// - /// Returns `true` if verification succeeds. The `error` method will return the specific - /// validation error if the certificate was not valid. - /// - /// This will only work inside of a call to `init`. - #[corresponds(X509_verify_cert)] - pub fn verify_cert(&mut self) -> Result { - unsafe { cvt_n(ffi::X509_verify_cert(self.as_ptr())).map(|n| n != 0) } - } - - /// Set the error code of the context. - #[corresponds(X509_STORE_CTX_set_error)] - pub fn set_error(&mut self, result: X509VerifyResult) { - unsafe { - ffi::X509_STORE_CTX_set_error(self.as_ptr(), result.as_raw()); - } - } - - /// Returns a reference to the certificate which caused the error or None if - /// no certificate is relevant to the error. - #[corresponds(X509_STORE_CTX_get_current_cert)] - pub fn current_cert(&self) -> Option<&X509Ref> { - unsafe { - let ptr = ffi::X509_STORE_CTX_get_current_cert(self.as_ptr()); - X509Ref::from_const_ptr_opt(ptr) - } - } - - /// Returns a non-negative integer representing the depth in the certificate - /// chain where the error occurred. If it is zero it occurred in the end - /// entity certificate, one if it is the certificate which signed the end - /// entity certificate and so on. - #[corresponds(X509_STORE_CTX_get_error_depth)] - pub fn error_depth(&self) -> u32 { - unsafe { ffi::X509_STORE_CTX_get_error_depth(self.as_ptr()) as u32 } - } - - /// Returns a reference to a complete valid `X509` certificate chain. - #[corresponds(X509_STORE_CTX_get0_chain)] - pub fn chain(&self) -> Option<&StackRef> { - unsafe { - let chain = X509_STORE_CTX_get0_chain(self.as_ptr()); - - if chain.is_null() { - None - } else { - Some(StackRef::from_ptr(chain)) - } - } - } -} - -/// A builder used to construct an `X509`. -pub struct X509Builder(X509); - -impl X509Builder { - /// Creates a new builder. - #[corresponds(X509_new)] - pub fn new() -> Result { - unsafe { - ffi::init(); - cvt_p(ffi::X509_new()).map(|p| X509Builder(X509(p))) - } - } - - /// Sets the notAfter constraint on the certificate. - #[corresponds(X509_set1_notAfter)] - pub fn set_not_after(&mut self, not_after: &Asn1TimeRef) -> Result<(), ErrorStack> { - unsafe { cvt(X509_set1_notAfter(self.0.as_ptr(), not_after.as_ptr())).map(|_| ()) } - } - - /// Sets the notBefore constraint on the certificate. - #[corresponds(X509_set1_notBefore)] - pub fn set_not_before(&mut self, not_before: &Asn1TimeRef) -> Result<(), ErrorStack> { - unsafe { cvt(X509_set1_notBefore(self.0.as_ptr(), not_before.as_ptr())).map(|_| ()) } - } - - /// Sets the version of the certificate. - /// - /// Note that the version is zero-indexed; that is, a certificate corresponding to version 3 of - /// the X.509 standard should pass `2` to this method. - #[corresponds(X509_set_version)] - #[allow(clippy::useless_conversion)] - pub fn set_version(&mut self, version: i32) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::X509_set_version(self.0.as_ptr(), version as c_long)).map(|_| ()) } - } - - /// Sets the serial number of the certificate. - #[corresponds(X509_set_serialNumber)] - pub fn set_serial_number(&mut self, serial_number: &Asn1IntegerRef) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::X509_set_serialNumber( - self.0.as_ptr(), - serial_number.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Sets the issuer name of the certificate. - #[corresponds(X509_set_issuer_name)] - pub fn set_issuer_name(&mut self, issuer_name: &X509NameRef) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::X509_set_issuer_name( - self.0.as_ptr(), - issuer_name.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Sets the subject name of the certificate. - /// - /// When building certificates, the `C`, `ST`, and `O` options are common when using the openssl command line tools. - /// The `CN` field is used for the common name, such as a DNS name. - /// - /// ``` - /// use openssl::x509::{X509, X509NameBuilder}; - /// - /// let mut x509_name = openssl::x509::X509NameBuilder::new().unwrap(); - /// x509_name.append_entry_by_text("C", "US").unwrap(); - /// x509_name.append_entry_by_text("ST", "CA").unwrap(); - /// x509_name.append_entry_by_text("O", "Some organization").unwrap(); - /// x509_name.append_entry_by_text("CN", "www.example.com").unwrap(); - /// let x509_name = x509_name.build(); - /// - /// let mut x509 = openssl::x509::X509::builder().unwrap(); - /// x509.set_subject_name(&x509_name).unwrap(); - /// ``` - #[corresponds(X509_set_subject_name)] - pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::X509_set_subject_name( - self.0.as_ptr(), - subject_name.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Sets the public key associated with the certificate. - #[corresponds(X509_set_pubkey)] - pub fn set_pubkey(&mut self, key: &PKeyRef) -> Result<(), ErrorStack> - where - T: HasPublic, - { - unsafe { cvt(ffi::X509_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) } - } - - /// Returns a context object which is needed to create certain X509 extension values. - /// - /// Set `issuer` to `None` if the certificate will be self-signed. - #[corresponds(X509V3_set_ctx)] - pub fn x509v3_context<'a>( - &'a self, - issuer: Option<&'a X509Ref>, - conf: Option<&'a ConfRef>, - ) -> X509v3Context<'a> { - unsafe { - let mut ctx = mem::zeroed(); - - let issuer = match issuer { - Some(issuer) => issuer.as_ptr(), - None => self.0.as_ptr(), - }; - let subject = self.0.as_ptr(); - ffi::X509V3_set_ctx( - &mut ctx, - issuer, - subject, - ptr::null_mut(), - ptr::null_mut(), - 0, - ); - - // nodb case taken care of since we zeroed ctx above - if let Some(conf) = conf { - ffi::X509V3_set_nconf(&mut ctx, conf.as_ptr()); - } - - X509v3Context(ctx, PhantomData) - } - } - - /// Adds an X509 extension value to the certificate. - /// - /// This works just as `append_extension` except it takes ownership of the `X509Extension`. - pub fn append_extension(&mut self, extension: X509Extension) -> Result<(), ErrorStack> { - self.append_extension2(&extension) - } - - /// Adds an X509 extension value to the certificate. - #[corresponds(X509_add_ext)] - pub fn append_extension2(&mut self, extension: &X509ExtensionRef) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::X509_add_ext(self.0.as_ptr(), extension.as_ptr(), -1))?; - Ok(()) - } - } - - /// Signs the certificate with a private key. - #[corresponds(X509_sign)] - pub fn sign(&mut self, key: &PKeyRef, hash: MessageDigest) -> Result<(), ErrorStack> - where - T: HasPrivate, - { - unsafe { cvt(ffi::X509_sign(self.0.as_ptr(), key.as_ptr(), hash.as_ptr())).map(|_| ()) } - } - - /// Consumes the builder, returning the certificate. - pub fn build(self) -> X509 { - self.0 - } -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::X509; - fn drop = ffi::X509_free; - - /// An `X509` public key certificate. - pub struct X509; - /// Reference to `X509`. - pub struct X509Ref; -} - -impl X509Ref { - /// Returns this certificate's subject name. - #[corresponds(X509_get_subject_name)] - pub fn subject_name(&self) -> &X509NameRef { - unsafe { - let name = ffi::X509_get_subject_name(self.as_ptr()); - X509NameRef::from_const_ptr_opt(name).expect("subject name must not be null") - } - } - - /// Returns the hash of the certificates subject - #[corresponds(X509_subject_name_hash)] - pub fn subject_name_hash(&self) -> u32 { - #[allow(clippy::unnecessary_cast)] - unsafe { - ffi::X509_subject_name_hash(self.as_ptr()) as u32 - } - } - - /// Returns this certificate's issuer name. - #[corresponds(X509_get_issuer_name)] - pub fn issuer_name(&self) -> &X509NameRef { - unsafe { - let name = ffi::X509_get_issuer_name(self.as_ptr()); - X509NameRef::from_const_ptr_opt(name).expect("issuer name must not be null") - } - } - - /// Returns the hash of the certificates issuer - #[corresponds(X509_issuer_name_hash)] - pub fn issuer_name_hash(&self) -> u32 { - #[allow(clippy::unnecessary_cast)] - unsafe { - ffi::X509_issuer_name_hash(self.as_ptr()) as u32 - } - } - - /// Returns this certificate's subject alternative name entries, if they exist. - #[corresponds(X509_get_ext_d2i)] - pub fn subject_alt_names(&self) -> Option> { - unsafe { - let stack = ffi::X509_get_ext_d2i( - self.as_ptr(), - ffi::NID_subject_alt_name, - ptr::null_mut(), - ptr::null_mut(), - ); - Stack::from_ptr_opt(stack as *mut _) - } - } - - /// Returns this certificate's CRL distribution points, if they exist. - #[corresponds(X509_get_ext_d2i)] - pub fn crl_distribution_points(&self) -> Option> { - unsafe { - let stack = ffi::X509_get_ext_d2i( - self.as_ptr(), - ffi::NID_crl_distribution_points, - ptr::null_mut(), - ptr::null_mut(), - ); - Stack::from_ptr_opt(stack as *mut _) - } - } - - /// Returns this certificate's issuer alternative name entries, if they exist. - #[corresponds(X509_get_ext_d2i)] - pub fn issuer_alt_names(&self) -> Option> { - unsafe { - let stack = ffi::X509_get_ext_d2i( - self.as_ptr(), - ffi::NID_issuer_alt_name, - ptr::null_mut(), - ptr::null_mut(), - ); - Stack::from_ptr_opt(stack as *mut _) - } - } - - /// Returns this certificate's [`authority information access`] entries, if they exist. - /// - /// [`authority information access`]: https://tools.ietf.org/html/rfc5280#section-4.2.2.1 - #[corresponds(X509_get_ext_d2i)] - pub fn authority_info(&self) -> Option> { - unsafe { - let stack = ffi::X509_get_ext_d2i( - self.as_ptr(), - ffi::NID_info_access, - ptr::null_mut(), - ptr::null_mut(), - ); - Stack::from_ptr_opt(stack as *mut _) - } - } - - /// Retrieves the path length extension from a certificate, if it exists. - #[corresponds(X509_get_pathlen)] - #[cfg(any(ossl110, boringssl, awslc))] - pub fn pathlen(&self) -> Option { - let v = unsafe { ffi::X509_get_pathlen(self.as_ptr()) }; - u32::try_from(v).ok() - } - - /// Returns this certificate's subject key id, if it exists. - #[corresponds(X509_get0_subject_key_id)] - #[cfg(any(ossl110, boringssl, awslc))] - pub fn subject_key_id(&self) -> Option<&Asn1OctetStringRef> { - unsafe { - let data = ffi::X509_get0_subject_key_id(self.as_ptr()); - Asn1OctetStringRef::from_const_ptr_opt(data) - } - } - - /// Returns this certificate's authority key id, if it exists. - #[corresponds(X509_get0_authority_key_id)] - #[cfg(any(ossl110, boringssl, awslc))] - pub fn authority_key_id(&self) -> Option<&Asn1OctetStringRef> { - unsafe { - let data = ffi::X509_get0_authority_key_id(self.as_ptr()); - Asn1OctetStringRef::from_const_ptr_opt(data) - } - } - - /// Returns this certificate's authority issuer name entries, if they exist. - #[corresponds(X509_get0_authority_issuer)] - #[cfg(ossl111d)] - pub fn authority_issuer(&self) -> Option<&StackRef> { - unsafe { - let stack = ffi::X509_get0_authority_issuer(self.as_ptr()); - StackRef::from_const_ptr_opt(stack) - } - } - - /// Returns this certificate's authority serial number, if it exists. - #[corresponds(X509_get0_authority_serial)] - #[cfg(ossl111d)] - pub fn authority_serial(&self) -> Option<&Asn1IntegerRef> { - unsafe { - let r = ffi::X509_get0_authority_serial(self.as_ptr()); - Asn1IntegerRef::from_const_ptr_opt(r) - } - } - - #[corresponds(X509_get_pubkey)] - pub fn public_key(&self) -> Result, ErrorStack> { - unsafe { - let pkey = cvt_p(ffi::X509_get_pubkey(self.as_ptr()))?; - Ok(PKey::from_ptr(pkey)) - } - } - - /// Returns a digest of the DER representation of the certificate. - #[corresponds(X509_digest)] - pub fn digest(&self, hash_type: MessageDigest) -> Result { - unsafe { - let mut digest = DigestBytes { - buf: [0; ffi::EVP_MAX_MD_SIZE as usize], - len: ffi::EVP_MAX_MD_SIZE as usize, - }; - let mut len = ffi::EVP_MAX_MD_SIZE as c_uint; - cvt(ffi::X509_digest( - self.as_ptr(), - hash_type.as_ptr(), - digest.buf.as_mut_ptr() as *mut _, - &mut len, - ))?; - digest.len = len as usize; - - Ok(digest) - } - } - - #[deprecated(since = "0.10.9", note = "renamed to digest")] - pub fn fingerprint(&self, hash_type: MessageDigest) -> Result, ErrorStack> { - self.digest(hash_type).map(|b| b.to_vec()) - } - - /// Returns the certificate's Not After validity period. - #[corresponds(X509_getm_notAfter)] - pub fn not_after(&self) -> &Asn1TimeRef { - unsafe { - let date = X509_getm_notAfter(self.as_ptr()); - Asn1TimeRef::from_const_ptr_opt(date).expect("not_after must not be null") - } - } - - /// Returns the certificate's Not Before validity period. - #[corresponds(X509_getm_notBefore)] - pub fn not_before(&self) -> &Asn1TimeRef { - unsafe { - let date = X509_getm_notBefore(self.as_ptr()); - Asn1TimeRef::from_const_ptr_opt(date).expect("not_before must not be null") - } - } - - /// Returns the certificate's signature - #[corresponds(X509_get0_signature)] - pub fn signature(&self) -> &Asn1BitStringRef { - unsafe { - let mut signature = ptr::null(); - X509_get0_signature(&mut signature, ptr::null_mut(), self.as_ptr()); - Asn1BitStringRef::from_const_ptr_opt(signature).expect("signature must not be null") - } - } - - /// Returns the certificate's signature algorithm. - #[corresponds(X509_get0_signature)] - pub fn signature_algorithm(&self) -> &X509AlgorithmRef { - unsafe { - let mut algor = ptr::null(); - X509_get0_signature(ptr::null_mut(), &mut algor, self.as_ptr()); - X509AlgorithmRef::from_const_ptr_opt(algor) - .expect("signature algorithm must not be null") - } - } - - /// Returns the list of OCSP responder URLs specified in the certificate's Authority Information - /// Access field. - #[corresponds(X509_get1_ocsp)] - pub fn ocsp_responders(&self) -> Result, ErrorStack> { - unsafe { cvt_p(ffi::X509_get1_ocsp(self.as_ptr())).map(|p| Stack::from_ptr(p)) } - } - - /// Checks that this certificate issued `subject`. - #[corresponds(X509_check_issued)] - pub fn issued(&self, subject: &X509Ref) -> X509VerifyResult { - unsafe { - let r = ffi::X509_check_issued(self.as_ptr(), subject.as_ptr()); - X509VerifyResult::from_raw(r) - } - } - - /// Returns certificate version. If this certificate has no explicit version set, it defaults to - /// version 1. - /// - /// Note that `0` return value stands for version 1, `1` for version 2 and so on. - #[corresponds(X509_get_version)] - #[cfg(ossl110)] - #[allow(clippy::unnecessary_cast)] - pub fn version(&self) -> i32 { - unsafe { ffi::X509_get_version(self.as_ptr()) as i32 } - } - - /// Check if the certificate is signed using the given public key. - /// - /// Only the signature is checked: no other checks (such as certificate chain validity) - /// are performed. - /// - /// Returns `true` if verification succeeds. - #[corresponds(X509_verify)] - pub fn verify(&self, key: &PKeyRef) -> Result - where - T: HasPublic, - { - unsafe { cvt_n(ffi::X509_verify(self.as_ptr(), key.as_ptr())).map(|n| n != 0) } - } - - /// Returns this certificate's serial number. - #[corresponds(X509_get_serialNumber)] - pub fn serial_number(&self) -> &Asn1IntegerRef { - unsafe { - let r = ffi::X509_get_serialNumber(self.as_ptr()); - Asn1IntegerRef::from_const_ptr_opt(r).expect("serial number must not be null") - } - } - - /// Returns this certificate's "alias". This field is populated by - /// OpenSSL in some situations -- specifically OpenSSL will store a - /// PKCS#12 `friendlyName` in this field. This is not a part of the X.509 - /// certificate itself, OpenSSL merely attaches it to this structure in - /// memory. - #[corresponds(X509_alias_get0)] - pub fn alias(&self) -> Option<&[u8]> { - unsafe { - let mut len = 0; - let ptr = ffi::X509_alias_get0(self.as_ptr(), &mut len); - if ptr.is_null() { - None - } else { - Some(util::from_raw_parts(ptr, len as usize)) - } - } - } - - to_pem! { - /// Serializes the certificate into a PEM-encoded X509 structure. - /// - /// The output will have a header of `-----BEGIN CERTIFICATE-----`. - #[corresponds(PEM_write_bio_X509)] - to_pem, - ffi::PEM_write_bio_X509 - } - - to_der! { - /// Serializes the certificate into a DER-encoded X509 structure. - #[corresponds(i2d_X509)] - to_der, - ffi::i2d_X509 - } - - to_pem! { - /// Converts the certificate to human readable text. - #[corresponds(X509_print)] - to_text, - ffi::X509_print - } -} - -impl ToOwned for X509Ref { - type Owned = X509; - - fn to_owned(&self) -> X509 { - unsafe { - X509_up_ref(self.as_ptr()); - X509::from_ptr(self.as_ptr()) - } - } -} - -impl Ord for X509Ref { - fn cmp(&self, other: &Self) -> cmp::Ordering { - // X509_cmp returns a number <0 for less than, 0 for equal and >0 for greater than. - // It can't fail if both pointers are valid, which we know is true. - let cmp = unsafe { ffi::X509_cmp(self.as_ptr(), other.as_ptr()) }; - cmp.cmp(&0) - } -} - -impl PartialOrd for X509Ref { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl PartialOrd for X509Ref { - fn partial_cmp(&self, other: &X509) -> Option { - >::partial_cmp(self, other) - } -} - -impl PartialEq for X509Ref { - fn eq(&self, other: &Self) -> bool { - self.cmp(other) == cmp::Ordering::Equal - } -} - -impl PartialEq for X509Ref { - fn eq(&self, other: &X509) -> bool { - >::eq(self, other) - } -} - -impl Eq for X509Ref {} - -impl X509 { - /// Returns a new builder. - pub fn builder() -> Result { - X509Builder::new() - } - - from_pem! { - /// Deserializes a PEM-encoded X509 structure. - /// - /// The input should have a header of `-----BEGIN CERTIFICATE-----`. - #[corresponds(PEM_read_bio_X509)] - from_pem, - X509, - ffi::PEM_read_bio_X509 - } - - from_der! { - /// Deserializes a DER-encoded X509 structure. - #[corresponds(d2i_X509)] - from_der, - X509, - ffi::d2i_X509 - } - - /// Deserializes a list of PEM-formatted certificates. - #[corresponds(PEM_read_bio_X509)] - pub fn stack_from_pem(pem: &[u8]) -> Result, ErrorStack> { - unsafe { - ffi::init(); - let bio = MemBioSlice::new(pem)?; - - let mut certs = vec![]; - loop { - let r = - ffi::PEM_read_bio_X509(bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut()); - if r.is_null() { - let e = ErrorStack::get(); - - if let Some(err) = e.errors().last() { - if err.library_code() == ffi::ERR_LIB_PEM as libc::c_int - && err.reason_code() == ffi::PEM_R_NO_START_LINE as libc::c_int - { - break; - } - } - - return Err(e); - } else { - certs.push(X509(r)); - } - } - - Ok(certs) - } - } -} - -impl Clone for X509 { - fn clone(&self) -> X509 { - X509Ref::to_owned(self) - } -} - -impl fmt::Debug for X509 { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - let serial = match &self.serial_number().to_bn() { - Ok(bn) => match bn.to_hex_str() { - Ok(hex) => hex.to_string(), - Err(_) => "".to_string(), - }, - Err(_) => "".to_string(), - }; - let mut debug_struct = formatter.debug_struct("X509"); - debug_struct.field("serial_number", &serial); - debug_struct.field("signature_algorithm", &self.signature_algorithm().object()); - debug_struct.field("issuer", &self.issuer_name()); - debug_struct.field("subject", &self.subject_name()); - if let Some(subject_alt_names) = &self.subject_alt_names() { - debug_struct.field("subject_alt_names", subject_alt_names); - } - debug_struct.field("not_before", &self.not_before()); - debug_struct.field("not_after", &self.not_after()); - - if let Ok(public_key) = &self.public_key() { - debug_struct.field("public_key", public_key); - }; - // TODO: Print extensions once they are supported on the X509 struct. - - debug_struct.finish() - } -} - -impl AsRef for X509Ref { - fn as_ref(&self) -> &X509Ref { - self - } -} - -impl Stackable for X509 { - type StackType = ffi::stack_st_X509; -} - -impl Ord for X509 { - fn cmp(&self, other: &Self) -> cmp::Ordering { - X509Ref::cmp(self, other) - } -} - -impl PartialOrd for X509 { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl PartialOrd for X509 { - fn partial_cmp(&self, other: &X509Ref) -> Option { - X509Ref::partial_cmp(self, other) - } -} - -impl PartialEq for X509 { - fn eq(&self, other: &Self) -> bool { - X509Ref::eq(self, other) - } -} - -impl PartialEq for X509 { - fn eq(&self, other: &X509Ref) -> bool { - X509Ref::eq(self, other) - } -} - -impl Eq for X509 {} - -/// A context object required to construct certain `X509` extension values. -pub struct X509v3Context<'a>(ffi::X509V3_CTX, PhantomData<(&'a X509Ref, &'a ConfRef)>); - -impl X509v3Context<'_> { - pub fn as_ptr(&self) -> *mut ffi::X509V3_CTX { - &self.0 as *const _ as *mut _ - } -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::X509_EXTENSION; - fn drop = ffi::X509_EXTENSION_free; - - /// Permit additional fields to be added to an `X509` v3 certificate. - pub struct X509Extension; - /// Reference to `X509Extension`. - pub struct X509ExtensionRef; -} - -impl Stackable for X509Extension { - type StackType = ffi::stack_st_X509_EXTENSION; -} - -impl X509Extension { - /// Constructs an X509 extension value. See `man x509v3_config` for information on supported - /// names and their value formats. - /// - /// Some extension types, such as `subjectAlternativeName`, require an `X509v3Context` to be - /// provided. - /// - /// DO NOT CALL THIS WITH UNTRUSTED `value`: `value` is an OpenSSL - /// mini-language that can read arbitrary files. - /// - /// See the extension module for builder types which will construct certain common extensions. - /// - /// This function is deprecated, `X509Extension::new_from_der` or the - /// types in `x509::extension` should be used in its place. - #[deprecated( - note = "Use x509::extension types or new_from_der instead", - since = "0.10.51" - )] - pub fn new( - conf: Option<&ConfRef>, - context: Option<&X509v3Context<'_>>, - name: &str, - value: &str, - ) -> Result { - let name = CString::new(name).unwrap(); - let value = CString::new(value).unwrap(); - let mut ctx; - unsafe { - ffi::init(); - let conf = conf.map_or(ptr::null_mut(), ConfRef::as_ptr); - let context_ptr = match context { - Some(c) => c.as_ptr(), - None => { - ctx = mem::zeroed(); - - ffi::X509V3_set_ctx( - &mut ctx, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - 0, - ); - &mut ctx - } - }; - let name = name.as_ptr() as *mut _; - let value = value.as_ptr() as *mut _; - - cvt_p(ffi::X509V3_EXT_nconf(conf, context_ptr, name, value)).map(X509Extension) - } - } - - /// Constructs an X509 extension value. See `man x509v3_config` for information on supported - /// extensions and their value formats. - /// - /// Some extension types, such as `nid::SUBJECT_ALTERNATIVE_NAME`, require an `X509v3Context` to - /// be provided. - /// - /// DO NOT CALL THIS WITH UNTRUSTED `value`: `value` is an OpenSSL - /// mini-language that can read arbitrary files. - /// - /// See the extension module for builder types which will construct certain common extensions. - /// - /// This function is deprecated, `X509Extension::new_from_der` or the - /// types in `x509::extension` should be used in its place. - #[deprecated( - note = "Use x509::extension types or new_from_der instead", - since = "0.10.51" - )] - pub fn new_nid( - conf: Option<&ConfRef>, - context: Option<&X509v3Context<'_>>, - name: Nid, - value: &str, - ) -> Result { - let value = CString::new(value).unwrap(); - let mut ctx; - unsafe { - ffi::init(); - let conf = conf.map_or(ptr::null_mut(), ConfRef::as_ptr); - let context_ptr = match context { - Some(c) => c.as_ptr(), - None => { - ctx = mem::zeroed(); - - ffi::X509V3_set_ctx( - &mut ctx, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - 0, - ); - &mut ctx - } - }; - let name = name.as_raw(); - let value = value.as_ptr() as *mut _; - - cvt_p(ffi::X509V3_EXT_nconf_nid(conf, context_ptr, name, value)).map(X509Extension) - } - } - - /// Constructs a new X509 extension value from its OID, whether it's - /// critical, and its DER contents. - /// - /// The extent structure of the DER value will vary based on the - /// extension type, and can generally be found in the RFC defining the - /// extension. - /// - /// For common extension types, there are Rust APIs provided in - /// `openssl::x509::extensions` which are more ergonomic. - pub fn new_from_der( - oid: &Asn1ObjectRef, - critical: bool, - der_contents: &Asn1OctetStringRef, - ) -> Result { - unsafe { - cvt_p(ffi::X509_EXTENSION_create_by_OBJ( - ptr::null_mut(), - oid.as_ptr(), - critical as _, - der_contents.as_ptr(), - )) - .map(X509Extension) - } - } - - pub(crate) unsafe fn new_internal( - nid: Nid, - critical: bool, - value: *mut c_void, - ) -> Result { - ffi::init(); - cvt_p(ffi::X509V3_EXT_i2d(nid.as_raw(), critical as _, value)).map(X509Extension) - } - - /// Adds an alias for an extension - /// - /// # Safety - /// - /// This method modifies global state without locking and therefore is not thread safe - #[cfg(not(libressl390))] - #[corresponds(X509V3_EXT_add_alias)] - #[deprecated( - note = "Use x509::extension types or new_from_der and then this is not necessary", - since = "0.10.51" - )] - pub unsafe fn add_alias(to: Nid, from: Nid) -> Result<(), ErrorStack> { - ffi::init(); - cvt(ffi::X509V3_EXT_add_alias(to.as_raw(), from.as_raw())).map(|_| ()) - } -} - -impl X509ExtensionRef { - to_der! { - /// Serializes the Extension to its standard DER encoding. - #[corresponds(i2d_X509_EXTENSION)] - to_der, - ffi::i2d_X509_EXTENSION - } -} - -/// A builder used to construct an `X509Name`. -pub struct X509NameBuilder(X509Name); - -impl X509NameBuilder { - /// Creates a new builder. - pub fn new() -> Result { - unsafe { - ffi::init(); - cvt_p(ffi::X509_NAME_new()).map(|p| X509NameBuilder(X509Name(p))) - } - } - - /// Add a name entry - #[corresponds(X509_NAME_add_entry)] - pub fn append_entry(&mut self, ne: &X509NameEntryRef) -> std::result::Result<(), ErrorStack> { - unsafe { - cvt(ffi::X509_NAME_add_entry( - self.0.as_ptr(), - ne.as_ptr(), - -1, - 0, - )) - .map(|_| ()) - } - } - - /// Add a field entry by str. - #[corresponds(X509_NAME_add_entry_by_txt)] - pub fn append_entry_by_text(&mut self, field: &str, value: &str) -> Result<(), ErrorStack> { - unsafe { - let field = CString::new(field).unwrap(); - assert!(value.len() <= crate::SLenType::MAX as usize); - cvt(ffi::X509_NAME_add_entry_by_txt( - self.0.as_ptr(), - field.as_ptr() as *mut _, - ffi::MBSTRING_UTF8, - value.as_ptr(), - value.len() as crate::SLenType, - -1, - 0, - )) - .map(|_| ()) - } - } - - /// Add a field entry by str with a specific type. - #[corresponds(X509_NAME_add_entry_by_txt)] - pub fn append_entry_by_text_with_type( - &mut self, - field: &str, - value: &str, - ty: Asn1Type, - ) -> Result<(), ErrorStack> { - unsafe { - let field = CString::new(field).unwrap(); - assert!(value.len() <= crate::SLenType::MAX as usize); - cvt(ffi::X509_NAME_add_entry_by_txt( - self.0.as_ptr(), - field.as_ptr() as *mut _, - ty.as_raw(), - value.as_ptr(), - value.len() as crate::SLenType, - -1, - 0, - )) - .map(|_| ()) - } - } - - /// Add a field entry by NID. - #[corresponds(X509_NAME_add_entry_by_NID)] - pub fn append_entry_by_nid(&mut self, field: Nid, value: &str) -> Result<(), ErrorStack> { - unsafe { - assert!(value.len() <= crate::SLenType::MAX as usize); - cvt(ffi::X509_NAME_add_entry_by_NID( - self.0.as_ptr(), - field.as_raw(), - ffi::MBSTRING_UTF8, - value.as_ptr() as *mut _, - value.len() as crate::SLenType, - -1, - 0, - )) - .map(|_| ()) - } - } - - /// Add a field entry by NID with a specific type. - #[corresponds(X509_NAME_add_entry_by_NID)] - pub fn append_entry_by_nid_with_type( - &mut self, - field: Nid, - value: &str, - ty: Asn1Type, - ) -> Result<(), ErrorStack> { - unsafe { - assert!(value.len() <= crate::SLenType::MAX as usize); - cvt(ffi::X509_NAME_add_entry_by_NID( - self.0.as_ptr(), - field.as_raw(), - ty.as_raw(), - value.as_ptr() as *mut _, - value.len() as crate::SLenType, - -1, - 0, - )) - .map(|_| ()) - } - } - - /// Return an `X509Name`. - pub fn build(self) -> X509Name { - // Round-trip through bytes because OpenSSL is not const correct and - // names in a "modified" state compute various things lazily. This can - // lead to data-races because OpenSSL doesn't have locks or anything. - X509Name::from_der(&self.0.to_der().unwrap()).unwrap() - } -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::X509_NAME; - fn drop = ffi::X509_NAME_free; - - /// The names of an `X509` certificate. - pub struct X509Name; - /// Reference to `X509Name`. - pub struct X509NameRef; -} - -impl X509Name { - /// Returns a new builder. - pub fn builder() -> Result { - X509NameBuilder::new() - } - - /// Loads subject names from a file containing PEM-formatted certificates. - /// - /// This is commonly used in conjunction with `SslContextBuilder::set_client_ca_list`. - pub fn load_client_ca_file>(file: P) -> Result, ErrorStack> { - let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); - unsafe { cvt_p(ffi::SSL_load_client_CA_file(file.as_ptr())).map(|p| Stack::from_ptr(p)) } - } - - from_der! { - /// Deserializes a DER-encoded X509 name structure. - /// - /// This corresponds to [`d2i_X509_NAME`]. - /// - /// [`d2i_X509_NAME`]: https://docs.openssl.org/master/man3/d2i_X509_NAME/ - from_der, - X509Name, - ffi::d2i_X509_NAME - } -} - -impl Stackable for X509Name { - type StackType = ffi::stack_st_X509_NAME; -} - -impl X509NameRef { - /// Returns the name entries by the nid. - pub fn entries_by_nid(&self, nid: Nid) -> X509NameEntries<'_> { - X509NameEntries { - name: self, - nid: Some(nid), - loc: -1, - } - } - - /// Returns an iterator over all `X509NameEntry` values - pub fn entries(&self) -> X509NameEntries<'_> { - X509NameEntries { - name: self, - nid: None, - loc: -1, - } - } - - /// Compare two names, like [`Ord`] but it may fail. - /// - /// With OpenSSL versions from 3.0.0 this may return an error if the underlying `X509_NAME_cmp` - /// call fails. - /// For OpenSSL versions before 3.0.0 it will never return an error, but due to a bug it may - /// spuriously return `Ordering::Less` if the `X509_NAME_cmp` call fails. - #[corresponds(X509_NAME_cmp)] - pub fn try_cmp(&self, other: &X509NameRef) -> Result { - let cmp = unsafe { ffi::X509_NAME_cmp(self.as_ptr(), other.as_ptr()) }; - if cfg!(ossl300) && cmp == -2 { - return Err(ErrorStack::get()); - } - Ok(cmp.cmp(&0)) - } - - /// Copies the name to a new `X509Name`. - #[corresponds(X509_NAME_dup)] - #[cfg(any(boringssl, ossl110, libressl, awslc))] - pub fn to_owned(&self) -> Result { - unsafe { cvt_p(ffi::X509_NAME_dup(self.as_ptr())).map(|n| X509Name::from_ptr(n)) } - } - - to_der! { - /// Serializes the certificate into a DER-encoded X509 name structure. - /// - /// This corresponds to [`i2d_X509_NAME`]. - /// - /// [`i2d_X509_NAME`]: https://docs.openssl.org/master/man3/i2d_X509_NAME/ - to_der, - ffi::i2d_X509_NAME - } -} - -impl fmt::Debug for X509NameRef { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.debug_list().entries(self.entries()).finish() - } -} - -/// A type to destructure and examine an `X509Name`. -pub struct X509NameEntries<'a> { - name: &'a X509NameRef, - nid: Option, - loc: c_int, -} - -impl<'a> Iterator for X509NameEntries<'a> { - type Item = &'a X509NameEntryRef; - - fn next(&mut self) -> Option<&'a X509NameEntryRef> { - unsafe { - match self.nid { - Some(nid) => { - // There is a `Nid` specified to search for - self.loc = - ffi::X509_NAME_get_index_by_NID(self.name.as_ptr(), nid.as_raw(), self.loc); - if self.loc == -1 { - return None; - } - } - None => { - // Iterate over all `Nid`s - self.loc += 1; - if self.loc >= ffi::X509_NAME_entry_count(self.name.as_ptr()) { - return None; - } - } - } - - let entry = ffi::X509_NAME_get_entry(self.name.as_ptr(), self.loc); - - Some(X509NameEntryRef::from_const_ptr_opt(entry).expect("entry must not be null")) - } - } -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::X509_NAME_ENTRY; - fn drop = ffi::X509_NAME_ENTRY_free; - - /// A name entry associated with a `X509Name`. - pub struct X509NameEntry; - /// Reference to `X509NameEntry`. - pub struct X509NameEntryRef; -} - -impl X509NameEntryRef { - /// Returns the field value of an `X509NameEntry`. - #[corresponds(X509_NAME_ENTRY_get_data)] - pub fn data(&self) -> &Asn1StringRef { - unsafe { - let data = ffi::X509_NAME_ENTRY_get_data(self.as_ptr()); - Asn1StringRef::from_ptr(data) - } - } - - /// Returns the `Asn1Object` value of an `X509NameEntry`. - /// This is useful for finding out about the actual `Nid` when iterating over all `X509NameEntries`. - #[corresponds(X509_NAME_ENTRY_get_object)] - pub fn object(&self) -> &Asn1ObjectRef { - unsafe { - let object = ffi::X509_NAME_ENTRY_get_object(self.as_ptr()); - Asn1ObjectRef::from_ptr(object) - } - } -} - -impl fmt::Debug for X509NameEntryRef { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_fmt(format_args!("{:?} = {:?}", self.object(), self.data())) - } -} - -/// A builder used to construct an `X509Req`. -pub struct X509ReqBuilder(X509Req); - -impl X509ReqBuilder { - /// Returns a builder for a certificate request. - #[corresponds(X509_REQ_new)] - pub fn new() -> Result { - unsafe { - ffi::init(); - cvt_p(ffi::X509_REQ_new()).map(|p| X509ReqBuilder(X509Req(p))) - } - } - - /// Set the numerical value of the version field. - #[corresponds(X509_REQ_set_version)] - #[allow(clippy::useless_conversion)] - pub fn set_version(&mut self, version: i32) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::X509_REQ_set_version( - self.0.as_ptr(), - version as c_long, - )) - .map(|_| ()) - } - } - - /// Set the issuer name. - #[corresponds(X509_REQ_set_subject_name)] - pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::X509_REQ_set_subject_name( - self.0.as_ptr(), - subject_name.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Set the public key. - #[corresponds(X509_REQ_set_pubkey)] - pub fn set_pubkey(&mut self, key: &PKeyRef) -> Result<(), ErrorStack> - where - T: HasPublic, - { - unsafe { cvt(ffi::X509_REQ_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) } - } - - /// Return an `X509v3Context`. This context object can be used to construct - /// certain `X509` extensions. - pub fn x509v3_context<'a>(&'a self, conf: Option<&'a ConfRef>) -> X509v3Context<'a> { - unsafe { - let mut ctx = mem::zeroed(); - - ffi::X509V3_set_ctx( - &mut ctx, - ptr::null_mut(), - ptr::null_mut(), - self.0.as_ptr(), - ptr::null_mut(), - 0, - ); - - // nodb case taken care of since we zeroed ctx above - if let Some(conf) = conf { - ffi::X509V3_set_nconf(&mut ctx, conf.as_ptr()); - } - - X509v3Context(ctx, PhantomData) - } - } - - /// Permits any number of extension fields to be added to the certificate. - pub fn add_extensions( - &mut self, - extensions: &StackRef, - ) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::X509_REQ_add_extensions( - self.0.as_ptr(), - extensions.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Sign the request using a private key. - #[corresponds(X509_REQ_sign)] - pub fn sign(&mut self, key: &PKeyRef, hash: MessageDigest) -> Result<(), ErrorStack> - where - T: HasPrivate, - { - unsafe { - cvt(ffi::X509_REQ_sign( - self.0.as_ptr(), - key.as_ptr(), - hash.as_ptr(), - )) - .map(|_| ()) - } - } - - /// Returns the `X509Req`. - pub fn build(self) -> X509Req { - self.0 - } -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::X509_REQ; - fn drop = ffi::X509_REQ_free; - - /// An `X509` certificate request. - pub struct X509Req; - /// Reference to `X509Req`. - pub struct X509ReqRef; -} - -impl X509Req { - /// A builder for `X509Req`. - pub fn builder() -> Result { - X509ReqBuilder::new() - } - - from_pem! { - /// Deserializes a PEM-encoded PKCS#10 certificate request structure. - /// - /// The input should have a header of `-----BEGIN CERTIFICATE REQUEST-----`. - /// - /// This corresponds to [`PEM_read_bio_X509_REQ`]. - /// - /// [`PEM_read_bio_X509_REQ`]: https://docs.openssl.org/master/man3/PEM_read_bio_X509_REQ/ - from_pem, - X509Req, - ffi::PEM_read_bio_X509_REQ - } - - from_der! { - /// Deserializes a DER-encoded PKCS#10 certificate request structure. - /// - /// This corresponds to [`d2i_X509_REQ`]. - /// - /// [`d2i_X509_REQ`]: https://docs.openssl.org/master/man3/d2i_X509_REQ/ - from_der, - X509Req, - ffi::d2i_X509_REQ - } -} - -impl X509ReqRef { - to_pem! { - /// Serializes the certificate request to a PEM-encoded PKCS#10 structure. - /// - /// The output will have a header of `-----BEGIN CERTIFICATE REQUEST-----`. - /// - /// This corresponds to [`PEM_write_bio_X509_REQ`]. - /// - /// [`PEM_write_bio_X509_REQ`]: https://docs.openssl.org/master/man3/PEM_write_bio_X509_REQ/ - to_pem, - ffi::PEM_write_bio_X509_REQ - } - - to_der! { - /// Serializes the certificate request to a DER-encoded PKCS#10 structure. - /// - /// This corresponds to [`i2d_X509_REQ`]. - /// - /// [`i2d_X509_REQ`]: https://docs.openssl.org/master/man3/i2d_X509_REQ/ - to_der, - ffi::i2d_X509_REQ - } - - to_pem! { - /// Converts the request to human readable text. - #[corresponds(X509_Req_print)] - to_text, - ffi::X509_REQ_print - } - - /// Returns the numerical value of the version field of the certificate request. - #[corresponds(X509_REQ_get_version)] - #[allow(clippy::unnecessary_cast)] - pub fn version(&self) -> i32 { - unsafe { X509_REQ_get_version(self.as_ptr()) as i32 } - } - - /// Returns the subject name of the certificate request. - #[corresponds(X509_REQ_get_subject_name)] - pub fn subject_name(&self) -> &X509NameRef { - unsafe { - let name = X509_REQ_get_subject_name(self.as_ptr()); - X509NameRef::from_const_ptr_opt(name).expect("subject name must not be null") - } - } - - /// Returns the public key of the certificate request. - #[corresponds(X509_REQ_get_pubkey)] - pub fn public_key(&self) -> Result, ErrorStack> { - unsafe { - let key = cvt_p(ffi::X509_REQ_get_pubkey(self.as_ptr()))?; - Ok(PKey::from_ptr(key)) - } - } - - /// Check if the certificate request is signed using the given public key. - /// - /// Returns `true` if verification succeeds. - #[corresponds(X509_REQ_verify)] - pub fn verify(&self, key: &PKeyRef) -> Result - where - T: HasPublic, - { - unsafe { cvt_n(ffi::X509_REQ_verify(self.as_ptr(), key.as_ptr())).map(|n| n != 0) } - } - - /// Returns the extensions of the certificate request. - #[corresponds(X509_REQ_get_extensions)] - pub fn extensions(&self) -> Result, ErrorStack> { - unsafe { - let extensions = cvt_p(ffi::X509_REQ_get_extensions(self.as_ptr()))?; - Ok(Stack::from_ptr(extensions)) - } - } -} - -/// The reason that a certificate was revoked. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct CrlReason(c_int); - -#[allow(missing_docs)] // no need to document the constants -impl CrlReason { - pub const UNSPECIFIED: CrlReason = CrlReason(ffi::CRL_REASON_UNSPECIFIED); - pub const KEY_COMPROMISE: CrlReason = CrlReason(ffi::CRL_REASON_KEY_COMPROMISE); - pub const CA_COMPROMISE: CrlReason = CrlReason(ffi::CRL_REASON_CA_COMPROMISE); - pub const AFFILIATION_CHANGED: CrlReason = CrlReason(ffi::CRL_REASON_AFFILIATION_CHANGED); - pub const SUPERSEDED: CrlReason = CrlReason(ffi::CRL_REASON_SUPERSEDED); - pub const CESSATION_OF_OPERATION: CrlReason = CrlReason(ffi::CRL_REASON_CESSATION_OF_OPERATION); - pub const CERTIFICATE_HOLD: CrlReason = CrlReason(ffi::CRL_REASON_CERTIFICATE_HOLD); - pub const REMOVE_FROM_CRL: CrlReason = CrlReason(ffi::CRL_REASON_REMOVE_FROM_CRL); - pub const PRIVILEGE_WITHDRAWN: CrlReason = CrlReason(ffi::CRL_REASON_PRIVILEGE_WITHDRAWN); - pub const AA_COMPROMISE: CrlReason = CrlReason(ffi::CRL_REASON_AA_COMPROMISE); - - /// Constructs an `CrlReason` from a raw OpenSSL value. - pub const fn from_raw(value: c_int) -> Self { - CrlReason(value) - } - - /// Returns the raw OpenSSL value represented by this type. - pub const fn as_raw(&self) -> c_int { - self.0 - } -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::X509_REVOKED; - fn drop = ffi::X509_REVOKED_free; - - /// An `X509` certificate revocation status. - pub struct X509Revoked; - /// Reference to `X509Revoked`. - pub struct X509RevokedRef; -} - -impl Stackable for X509Revoked { - type StackType = ffi::stack_st_X509_REVOKED; -} - -impl X509Revoked { - from_der! { - /// Deserializes a DER-encoded certificate revocation status - #[corresponds(d2i_X509_REVOKED)] - from_der, - X509Revoked, - ffi::d2i_X509_REVOKED - } -} - -impl X509RevokedRef { - to_der! { - /// Serializes the certificate request to a DER-encoded certificate revocation status - #[corresponds(d2i_X509_REVOKED)] - to_der, - ffi::i2d_X509_REVOKED - } - - /// Copies the entry to a new `X509Revoked`. - #[corresponds(X509_NAME_dup)] - #[cfg(any(boringssl, ossl110, libressl, awslc))] - pub fn to_owned(&self) -> Result { - unsafe { cvt_p(ffi::X509_REVOKED_dup(self.as_ptr())).map(|n| X509Revoked::from_ptr(n)) } - } - - /// Get the date that the certificate was revoked - #[corresponds(X509_REVOKED_get0_revocationDate)] - pub fn revocation_date(&self) -> &Asn1TimeRef { - unsafe { - let r = X509_REVOKED_get0_revocationDate(self.as_ptr() as *const _); - assert!(!r.is_null()); - Asn1TimeRef::from_ptr(r as *mut _) - } - } - - /// Get the serial number of the revoked certificate - #[corresponds(X509_REVOKED_get0_serialNumber)] - pub fn serial_number(&self) -> &Asn1IntegerRef { - unsafe { - let r = X509_REVOKED_get0_serialNumber(self.as_ptr() as *const _); - assert!(!r.is_null()); - Asn1IntegerRef::from_ptr(r as *mut _) - } - } - - /// Get the criticality and value of an extension. - /// - /// This returns None if the extension is not present or occurs multiple times. - #[corresponds(X509_REVOKED_get_ext_d2i)] - pub fn extension(&self) -> Result, ErrorStack> { - let mut critical = -1; - let out = unsafe { - // SAFETY: self.as_ptr() is a valid pointer to an X509_REVOKED. - let ext = ffi::X509_REVOKED_get_ext_d2i( - self.as_ptr(), - T::NID.as_raw(), - &mut critical as *mut _, - ptr::null_mut(), - ); - // SAFETY: Extensions's contract promises that the type returned by - // OpenSSL here is T::Output. - T::Output::from_ptr_opt(ext as *mut _) - }; - match (critical, out) { - (0, Some(out)) => Ok(Some((false, out))), - (1, Some(out)) => Ok(Some((true, out))), - // -1 means the extension wasn't found, -2 means multiple were found. - (-1 | -2, _) => Ok(None), - // A critical value of 0 or 1 suggests success, but a null pointer - // was returned so something went wrong. - (0 | 1, None) => Err(ErrorStack::get()), - (c_int::MIN..=-2 | 2.., _) => panic!("OpenSSL should only return -2, -1, 0, or 1 for an extension's criticality but it returned {}", critical), - } - } -} - -/// The CRL entry extension identifying the reason for revocation see [`CrlReason`], -/// this is as defined in RFC 5280 Section 5.3.1. -pub enum ReasonCode {} - -// SAFETY: CertificateIssuer is defined to be a stack of GeneralName in the RFC -// and in OpenSSL. -unsafe impl ExtensionType for ReasonCode { - const NID: Nid = Nid::from_raw(ffi::NID_crl_reason); - - type Output = Asn1Enumerated; -} - -/// The CRL entry extension identifying the issuer of a certificate used in -/// indirect CRLs, as defined in RFC 5280 Section 5.3.3. -pub enum CertificateIssuer {} - -// SAFETY: CertificateIssuer is defined to be a stack of GeneralName in the RFC -// and in OpenSSL. -unsafe impl ExtensionType for CertificateIssuer { - const NID: Nid = Nid::from_raw(ffi::NID_certificate_issuer); - - type Output = Stack; -} - -/// The CRL extension identifying how to access information and services for the issuer of the CRL -pub enum AuthorityInformationAccess {} - -// SAFETY: AuthorityInformationAccess is defined to be a stack of AccessDescription in the RFC -// and in OpenSSL. -unsafe impl ExtensionType for AuthorityInformationAccess { - const NID: Nid = Nid::from_raw(ffi::NID_info_access); - - type Output = Stack; -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::X509_CRL; - fn drop = ffi::X509_CRL_free; - - /// An `X509` certificate revocation list. - pub struct X509Crl; - /// Reference to `X509Crl`. - pub struct X509CrlRef; -} - -/// The status of a certificate in a revoction list -/// -/// Corresponds to the return value from the [`X509_CRL_get0_by_*`] methods. -/// -/// [`X509_CRL_get0_by_*`]: https://docs.openssl.org/master/man3/X509_CRL_get0_by_serial/ -pub enum CrlStatus<'a> { - /// The certificate is not present in the list - NotRevoked, - /// The certificate is in the list and is revoked - Revoked(&'a X509RevokedRef), - /// The certificate is in the list, but has the "removeFromCrl" status. - /// - /// This can occur if the certificate was revoked with the "CertificateHold" - /// reason, and has since been unrevoked. - RemoveFromCrl(&'a X509RevokedRef), -} - -impl<'a> CrlStatus<'a> { - // Helper used by the X509_CRL_get0_by_* methods to convert their return - // value to the status enum. - // Safety note: the returned CrlStatus must not outlive the owner of the - // revoked_entry pointer. - unsafe fn from_ffi_status( - status: c_int, - revoked_entry: *mut ffi::X509_REVOKED, - ) -> CrlStatus<'a> { - match status { - 0 => CrlStatus::NotRevoked, - 1 => { - assert!(!revoked_entry.is_null()); - CrlStatus::Revoked(X509RevokedRef::from_ptr(revoked_entry)) - } - 2 => { - assert!(!revoked_entry.is_null()); - CrlStatus::RemoveFromCrl(X509RevokedRef::from_ptr(revoked_entry)) - } - _ => unreachable!( - "{}", - "X509_CRL_get0_by_{{serial,cert}} should only return 0, 1, or 2." - ), - } - } -} - -impl X509Crl { - from_pem! { - /// Deserializes a PEM-encoded Certificate Revocation List - /// - /// The input should have a header of `-----BEGIN X509 CRL-----`. - #[corresponds(PEM_read_bio_X509_CRL)] - from_pem, - X509Crl, - ffi::PEM_read_bio_X509_CRL - } - - from_der! { - /// Deserializes a DER-encoded Certificate Revocation List - #[corresponds(d2i_X509_CRL)] - from_der, - X509Crl, - ffi::d2i_X509_CRL - } -} - -impl X509CrlRef { - to_pem! { - /// Serializes the certificate request to a PEM-encoded Certificate Revocation List. - /// - /// The output will have a header of `-----BEGIN X509 CRL-----`. - #[corresponds(PEM_write_bio_X509_CRL)] - to_pem, - ffi::PEM_write_bio_X509_CRL - } - - to_der! { - /// Serializes the certificate request to a DER-encoded Certificate Revocation List. - #[corresponds(i2d_X509_CRL)] - to_der, - ffi::i2d_X509_CRL - } - - /// Get the stack of revocation entries - pub fn get_revoked(&self) -> Option<&StackRef> { - unsafe { - let revoked = X509_CRL_get_REVOKED(self.as_ptr()); - if revoked.is_null() { - None - } else { - Some(StackRef::from_ptr(revoked)) - } - } - } - - /// Returns the CRL's `lastUpdate` time. - #[corresponds(X509_CRL_get0_lastUpdate)] - pub fn last_update(&self) -> &Asn1TimeRef { - unsafe { - let date = X509_CRL_get0_lastUpdate(self.as_ptr()); - assert!(!date.is_null()); - Asn1TimeRef::from_ptr(date as *mut _) - } - } - - /// Returns the CRL's `nextUpdate` time. - /// - /// If the `nextUpdate` field is missing, returns `None`. - #[corresponds(X509_CRL_get0_nextUpdate)] - pub fn next_update(&self) -> Option<&Asn1TimeRef> { - unsafe { - let date = X509_CRL_get0_nextUpdate(self.as_ptr()); - Asn1TimeRef::from_const_ptr_opt(date) - } - } - - /// Get the revocation status of a certificate by its serial number - #[corresponds(X509_CRL_get0_by_serial)] - pub fn get_by_serial<'a>(&'a self, serial: &Asn1IntegerRef) -> CrlStatus<'a> { - unsafe { - let mut ret = ptr::null_mut::(); - let status = - ffi::X509_CRL_get0_by_serial(self.as_ptr(), &mut ret as *mut _, serial.as_ptr()); - CrlStatus::from_ffi_status(status, ret) - } - } - - /// Get the revocation status of a certificate - #[corresponds(X509_CRL_get0_by_cert)] - pub fn get_by_cert<'a>(&'a self, cert: &X509) -> CrlStatus<'a> { - unsafe { - let mut ret = ptr::null_mut::(); - let status = - ffi::X509_CRL_get0_by_cert(self.as_ptr(), &mut ret as *mut _, cert.as_ptr()); - CrlStatus::from_ffi_status(status, ret) - } - } - - /// Get the issuer name from the revocation list. - #[corresponds(X509_CRL_get_issuer)] - pub fn issuer_name(&self) -> &X509NameRef { - unsafe { - let name = X509_CRL_get_issuer(self.as_ptr()); - assert!(!name.is_null()); - X509NameRef::from_ptr(name) - } - } - - /// Check if the CRL is signed using the given public key. - /// - /// Only the signature is checked: no other checks (such as certificate chain validity) - /// are performed. - /// - /// Returns `true` if verification succeeds. - #[corresponds(X509_CRL_verify)] - pub fn verify(&self, key: &PKeyRef) -> Result - where - T: HasPublic, - { - unsafe { cvt_n(ffi::X509_CRL_verify(self.as_ptr(), key.as_ptr())).map(|n| n != 0) } - } - - /// Get the criticality and value of an extension. - /// - /// This returns None if the extension is not present or occurs multiple times. - #[corresponds(X509_CRL_get_ext_d2i)] - pub fn extension(&self) -> Result, ErrorStack> { - let mut critical = -1; - let out = unsafe { - // SAFETY: self.as_ptr() is a valid pointer to an X509_CRL. - let ext = ffi::X509_CRL_get_ext_d2i( - self.as_ptr(), - T::NID.as_raw(), - &mut critical as *mut _, - ptr::null_mut(), - ); - // SAFETY: Extensions's contract promises that the type returned by - // OpenSSL here is T::Output. - T::Output::from_ptr_opt(ext as *mut _) - }; - match (critical, out) { - (0, Some(out)) => Ok(Some((false, out))), - (1, Some(out)) => Ok(Some((true, out))), - // -1 means the extension wasn't found, -2 means multiple were found. - (-1 | -2, _) => Ok(None), - // A critical value of 0 or 1 suggests success, but a null pointer - // was returned so something went wrong. - (0 | 1, None) => Err(ErrorStack::get()), - (c_int::MIN..=-2 | 2.., _) => panic!("OpenSSL should only return -2, -1, 0, or 1 for an extension's criticality but it returned {}", critical), - } - } -} - -/// The result of peer certificate verification. -#[derive(Copy, Clone, PartialEq, Eq)] -pub struct X509VerifyResult(c_int); - -impl fmt::Debug for X509VerifyResult { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_struct("X509VerifyResult") - .field("code", &self.0) - .field("error", &self.error_string()) - .finish() - } -} - -impl fmt::Display for X509VerifyResult { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.write_str(self.error_string()) - } -} - -impl Error for X509VerifyResult {} - -impl X509VerifyResult { - /// Creates an `X509VerifyResult` from a raw error number. - /// - /// # Safety - /// - /// Some methods on `X509VerifyResult` are not thread safe if the error - /// number is invalid. - pub unsafe fn from_raw(err: c_int) -> X509VerifyResult { - X509VerifyResult(err) - } - - /// Return the integer representation of an `X509VerifyResult`. - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn as_raw(&self) -> c_int { - self.0 - } - - /// Return a human readable error string from the verification error. - #[corresponds(X509_verify_cert_error_string)] - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn error_string(&self) -> &'static str { - ffi::init(); - - unsafe { - let s = ffi::X509_verify_cert_error_string(self.0 as c_long); - str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap() - } - } - - /// Successful peer certificate verification. - pub const OK: X509VerifyResult = X509VerifyResult(ffi::X509_V_OK); - /// Application verification failure. - pub const APPLICATION_VERIFICATION: X509VerifyResult = - X509VerifyResult(ffi::X509_V_ERR_APPLICATION_VERIFICATION); -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::GENERAL_NAME; - fn drop = ffi::GENERAL_NAME_free; - - /// An `X509` certificate alternative names. - pub struct GeneralName; - /// Reference to `GeneralName`. - pub struct GeneralNameRef; -} - -impl GeneralName { - unsafe fn new( - type_: c_int, - asn1_type: Asn1Type, - value: &[u8], - ) -> Result { - ffi::init(); - let gn = GeneralName::from_ptr(cvt_p(ffi::GENERAL_NAME_new())?); - (*gn.as_ptr()).type_ = type_; - let s = cvt_p(ffi::ASN1_STRING_type_new(asn1_type.as_raw()))?; - ffi::ASN1_STRING_set(s, value.as_ptr().cast(), value.len().try_into().unwrap()); - - #[cfg(any(boringssl, awslc))] - { - (*gn.as_ptr()).d.ptr = s.cast(); - } - #[cfg(not(any(boringssl, awslc)))] - { - (*gn.as_ptr()).d = s.cast(); - } - - Ok(gn) - } - - pub(crate) fn new_email(email: &[u8]) -> Result { - unsafe { GeneralName::new(ffi::GEN_EMAIL, Asn1Type::IA5STRING, email) } - } - - pub(crate) fn new_dns(dns: &[u8]) -> Result { - unsafe { GeneralName::new(ffi::GEN_DNS, Asn1Type::IA5STRING, dns) } - } - - pub(crate) fn new_uri(uri: &[u8]) -> Result { - unsafe { GeneralName::new(ffi::GEN_URI, Asn1Type::IA5STRING, uri) } - } - - pub(crate) fn new_ip(ip: IpAddr) -> Result { - match ip { - IpAddr::V4(addr) => unsafe { - GeneralName::new(ffi::GEN_IPADD, Asn1Type::OCTET_STRING, &addr.octets()) - }, - IpAddr::V6(addr) => unsafe { - GeneralName::new(ffi::GEN_IPADD, Asn1Type::OCTET_STRING, &addr.octets()) - }, - } - } - - pub(crate) fn new_rid(oid: Asn1Object) -> Result { - unsafe { - ffi::init(); - let gn = cvt_p(ffi::GENERAL_NAME_new())?; - (*gn).type_ = ffi::GEN_RID; - - #[cfg(any(boringssl, awslc))] - { - (*gn).d.registeredID = oid.as_ptr(); - } - #[cfg(not(any(boringssl, awslc)))] - { - (*gn).d = oid.as_ptr().cast(); - } - - mem::forget(oid); - - Ok(GeneralName::from_ptr(gn)) - } - } - - pub(crate) fn new_other_name(oid: Asn1Object, value: &[u8]) -> Result { - unsafe { - ffi::init(); - - let typ = cvt_p(ffi::d2i_ASN1_TYPE( - ptr::null_mut(), - &mut value.as_ptr().cast(), - value.len().try_into().unwrap(), - ))?; - - let gn = cvt_p(ffi::GENERAL_NAME_new())?; - (*gn).type_ = ffi::GEN_OTHERNAME; - - if let Err(e) = cvt(ffi::GENERAL_NAME_set0_othername( - gn, - oid.as_ptr().cast(), - typ, - )) { - ffi::GENERAL_NAME_free(gn); - return Err(e); - } - - mem::forget(oid); - - Ok(GeneralName::from_ptr(gn)) - } - } -} - -impl GeneralNameRef { - fn ia5_string(&self, ffi_type: c_int) -> Option<&str> { - unsafe { - if (*self.as_ptr()).type_ != ffi_type { - return None; - } - - #[cfg(any(boringssl, awslc))] - let d = (*self.as_ptr()).d.ptr; - #[cfg(not(any(boringssl, awslc)))] - let d = (*self.as_ptr()).d; - - let ptr = ASN1_STRING_get0_data(d as *mut _); - let len = ffi::ASN1_STRING_length(d as *mut _); - - #[allow(clippy::unnecessary_cast)] - let slice = util::from_raw_parts(ptr as *const u8, len as usize); - // IA5Strings are stated to be ASCII (specifically IA5). Hopefully - // OpenSSL checks that when loading a certificate but if not we'll - // use this instead of from_utf8_unchecked just in case. - str::from_utf8(slice).ok() - } - } - - /// Returns the contents of this `GeneralName` if it is an `rfc822Name`. - pub fn email(&self) -> Option<&str> { - self.ia5_string(ffi::GEN_EMAIL) - } - - /// Returns the contents of this `GeneralName` if it is a `directoryName`. - pub fn directory_name(&self) -> Option<&X509NameRef> { - unsafe { - if (*self.as_ptr()).type_ != ffi::GEN_DIRNAME { - return None; - } - - #[cfg(any(boringssl, awslc))] - let d = (*self.as_ptr()).d.ptr; - #[cfg(not(any(boringssl, awslc)))] - let d = (*self.as_ptr()).d; - - Some(X509NameRef::from_const_ptr(d as *const _)) - } - } - - /// Returns the contents of this `GeneralName` if it is a `dNSName`. - pub fn dnsname(&self) -> Option<&str> { - self.ia5_string(ffi::GEN_DNS) - } - - /// Returns the contents of this `GeneralName` if it is an `uniformResourceIdentifier`. - pub fn uri(&self) -> Option<&str> { - self.ia5_string(ffi::GEN_URI) - } - - /// Returns the contents of this `GeneralName` if it is an `iPAddress`. - pub fn ipaddress(&self) -> Option<&[u8]> { - unsafe { - if (*self.as_ptr()).type_ != ffi::GEN_IPADD { - return None; - } - #[cfg(any(boringssl, awslc))] - let d: *const ffi::ASN1_STRING = std::mem::transmute((*self.as_ptr()).d); - #[cfg(not(any(boringssl, awslc)))] - let d = (*self.as_ptr()).d; - - let ptr = ASN1_STRING_get0_data(d as *mut _); - let len = ffi::ASN1_STRING_length(d as *mut _); - - #[allow(clippy::unnecessary_cast)] - Some(util::from_raw_parts(ptr as *const u8, len as usize)) - } - } -} - -impl fmt::Debug for GeneralNameRef { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some(email) = self.email() { - formatter.write_str(email) - } else if let Some(dnsname) = self.dnsname() { - formatter.write_str(dnsname) - } else if let Some(uri) = self.uri() { - formatter.write_str(uri) - } else if let Some(ipaddress) = self.ipaddress() { - let address = <[u8; 16]>::try_from(ipaddress) - .map(IpAddr::from) - .or_else(|_| <[u8; 4]>::try_from(ipaddress).map(IpAddr::from)); - match address { - Ok(a) => fmt::Debug::fmt(&a, formatter), - Err(_) => fmt::Debug::fmt(ipaddress, formatter), - } - } else { - formatter.write_str("(empty)") - } - } -} - -impl Stackable for GeneralName { - type StackType = ffi::stack_st_GENERAL_NAME; -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::DIST_POINT; - fn drop = ffi::DIST_POINT_free; - - /// A `X509` distribution point. - pub struct DistPoint; - /// Reference to `DistPoint`. - pub struct DistPointRef; -} - -impl DistPointRef { - /// Returns the name of this distribution point if it exists - pub fn distpoint(&self) -> Option<&DistPointNameRef> { - unsafe { DistPointNameRef::from_const_ptr_opt((*self.as_ptr()).distpoint) } - } -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::DIST_POINT_NAME; - fn drop = ffi::DIST_POINT_NAME_free; - - /// A `X509` distribution point. - pub struct DistPointName; - /// Reference to `DistPointName`. - pub struct DistPointNameRef; -} - -impl DistPointNameRef { - /// Returns the contents of this DistPointName if it is a fullname. - pub fn fullname(&self) -> Option<&StackRef> { - unsafe { - if (*self.as_ptr()).type_ != 0 { - return None; - } - StackRef::from_const_ptr_opt((*self.as_ptr()).name.fullname) - } - } -} - -impl Stackable for DistPoint { - type StackType = ffi::stack_st_DIST_POINT; -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::ACCESS_DESCRIPTION; - fn drop = ffi::ACCESS_DESCRIPTION_free; - - /// `AccessDescription` of certificate authority information. - pub struct AccessDescription; - /// Reference to `AccessDescription`. - pub struct AccessDescriptionRef; -} - -impl AccessDescriptionRef { - /// Returns the access method OID. - pub fn method(&self) -> &Asn1ObjectRef { - unsafe { Asn1ObjectRef::from_ptr((*self.as_ptr()).method) } - } - - // Returns the access location. - pub fn location(&self) -> &GeneralNameRef { - unsafe { GeneralNameRef::from_ptr((*self.as_ptr()).location) } - } -} - -impl Stackable for AccessDescription { - type StackType = ffi::stack_st_ACCESS_DESCRIPTION; -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::X509_ALGOR; - fn drop = ffi::X509_ALGOR_free; - - /// An `X509` certificate signature algorithm. - pub struct X509Algorithm; - /// Reference to `X509Algorithm`. - pub struct X509AlgorithmRef; -} - -impl X509AlgorithmRef { - /// Returns the ASN.1 OID of this algorithm. - pub fn object(&self) -> &Asn1ObjectRef { - unsafe { - let mut oid = ptr::null(); - X509_ALGOR_get0(&mut oid, ptr::null_mut(), ptr::null_mut(), self.as_ptr()); - Asn1ObjectRef::from_const_ptr_opt(oid).expect("algorithm oid must not be null") - } - } -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::X509_OBJECT; - fn drop = X509_OBJECT_free; - - /// An `X509` or an X509 certificate revocation list. - pub struct X509Object; - /// Reference to `X509Object` - pub struct X509ObjectRef; -} - -impl X509ObjectRef { - pub fn x509(&self) -> Option<&X509Ref> { - unsafe { - let ptr = X509_OBJECT_get0_X509(self.as_ptr()); - X509Ref::from_const_ptr_opt(ptr) - } - } -} - -impl Stackable for X509Object { - type StackType = ffi::stack_st_X509_OBJECT; -} - -cfg_if! { - if #[cfg(any(boringssl, ossl110, libressl, awslc))] { - use ffi::{X509_getm_notAfter, X509_getm_notBefore, X509_up_ref, X509_get0_signature}; - } else { - #[allow(bad_style)] - unsafe fn X509_getm_notAfter(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME { - (*(*(*x).cert_info).validity).notAfter - } - - #[allow(bad_style)] - unsafe fn X509_getm_notBefore(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME { - (*(*(*x).cert_info).validity).notBefore - } - - #[allow(bad_style)] - unsafe fn X509_up_ref(x: *mut ffi::X509) { - ffi::CRYPTO_add_lock( - &mut (*x).references, - 1, - ffi::CRYPTO_LOCK_X509, - "mod.rs\0".as_ptr() as *const _, - line!() as c_int, - ); - } - - #[allow(bad_style)] - unsafe fn X509_get0_signature( - psig: *mut *const ffi::ASN1_BIT_STRING, - palg: *mut *const ffi::X509_ALGOR, - x: *const ffi::X509, - ) { - if !psig.is_null() { - *psig = (*x).signature; - } - if !palg.is_null() { - *palg = (*x).sig_alg; - } - } - } -} - -cfg_if! { - if #[cfg(any(boringssl, ossl110, libressl, awslc))] { - use ffi::{ - X509_ALGOR_get0, ASN1_STRING_get0_data, X509_STORE_CTX_get0_chain, X509_set1_notAfter, - X509_set1_notBefore, X509_REQ_get_version, X509_REQ_get_subject_name, - }; - } else { - use ffi::{ - ASN1_STRING_data as ASN1_STRING_get0_data, - X509_STORE_CTX_get_chain as X509_STORE_CTX_get0_chain, - X509_set_notAfter as X509_set1_notAfter, - X509_set_notBefore as X509_set1_notBefore, - }; - - #[allow(bad_style)] - unsafe fn X509_REQ_get_version(x: *mut ffi::X509_REQ) -> ::libc::c_long { - ffi::ASN1_INTEGER_get((*(*x).req_info).version) - } - - #[allow(bad_style)] - unsafe fn X509_REQ_get_subject_name(x: *mut ffi::X509_REQ) -> *mut ::ffi::X509_NAME { - (*(*x).req_info).subject - } - - #[allow(bad_style)] - unsafe fn X509_ALGOR_get0( - paobj: *mut *const ffi::ASN1_OBJECT, - pptype: *mut c_int, - pval: *mut *mut ::libc::c_void, - alg: *const ffi::X509_ALGOR, - ) { - if !paobj.is_null() { - *paobj = (*alg).algorithm; - } - assert!(pptype.is_null()); - assert!(pval.is_null()); - } - } -} - -cfg_if! { - if #[cfg(any(ossl110, boringssl, libressl, awslc))] { - use ffi::X509_OBJECT_get0_X509; - } else { - #[allow(bad_style)] - unsafe fn X509_OBJECT_get0_X509(x: *mut ffi::X509_OBJECT) -> *mut ffi::X509 { - if (*x).type_ == ffi::X509_LU_X509 { - (*x).data.x509 - } else { - ptr::null_mut() - } - } - } -} - -cfg_if! { - if #[cfg(any(ossl110, libressl, boringssl, awslc))] { - use ffi::X509_OBJECT_free; - } else { - #[allow(bad_style)] - unsafe fn X509_OBJECT_free(x: *mut ffi::X509_OBJECT) { - ffi::X509_OBJECT_free_contents(x); - ffi::CRYPTO_free(x as *mut libc::c_void); - } - } -} - -cfg_if! { - if #[cfg(any(ossl110, libressl, boringssl, awslc))] { - use ffi::{ - X509_CRL_get_issuer, X509_CRL_get0_nextUpdate, X509_CRL_get0_lastUpdate, - X509_CRL_get_REVOKED, - X509_REVOKED_get0_revocationDate, X509_REVOKED_get0_serialNumber, - }; - } else { - #[allow(bad_style)] - unsafe fn X509_CRL_get0_lastUpdate(x: *const ffi::X509_CRL) -> *mut ffi::ASN1_TIME { - (*(*x).crl).lastUpdate - } - #[allow(bad_style)] - unsafe fn X509_CRL_get0_nextUpdate(x: *const ffi::X509_CRL) -> *mut ffi::ASN1_TIME { - (*(*x).crl).nextUpdate - } - #[allow(bad_style)] - unsafe fn X509_CRL_get_issuer(x: *const ffi::X509_CRL) -> *mut ffi::X509_NAME { - (*(*x).crl).issuer - } - #[allow(bad_style)] - unsafe fn X509_CRL_get_REVOKED(x: *const ffi::X509_CRL) -> *mut ffi::stack_st_X509_REVOKED { - (*(*x).crl).revoked - } - #[allow(bad_style)] - unsafe fn X509_REVOKED_get0_serialNumber(x: *const ffi::X509_REVOKED) -> *mut ffi::ASN1_INTEGER { - (*x).serialNumber - } - #[allow(bad_style)] - unsafe fn X509_REVOKED_get0_revocationDate(x: *const ffi::X509_REVOKED) -> *mut ffi::ASN1_TIME { - (*x).revocationDate - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq)] -pub struct X509PurposeId(c_int); - -impl X509PurposeId { - pub const SSL_CLIENT: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_SSL_CLIENT); - pub const SSL_SERVER: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_SSL_SERVER); - pub const NS_SSL_SERVER: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_NS_SSL_SERVER); - pub const SMIME_SIGN: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_SMIME_SIGN); - pub const SMIME_ENCRYPT: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_SMIME_ENCRYPT); - pub const CRL_SIGN: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_CRL_SIGN); - pub const ANY: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_ANY); - pub const OCSP_HELPER: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_OCSP_HELPER); - pub const TIMESTAMP_SIGN: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_TIMESTAMP_SIGN); - #[cfg(ossl320)] - pub const CODE_SIGN: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_CODE_SIGN); - - /// Constructs an `X509PurposeId` from a raw OpenSSL value. - pub fn from_raw(id: c_int) -> Self { - X509PurposeId(id) - } - - /// Returns the raw OpenSSL value represented by this type. - pub fn as_raw(&self) -> c_int { - self.0 - } -} - -/// A reference to an [`X509_PURPOSE`]. -pub struct X509PurposeRef(Opaque); - -/// Implements a wrapper type for the static `X509_PURPOSE` table in OpenSSL. -impl ForeignTypeRef for X509PurposeRef { - type CType = ffi::X509_PURPOSE; -} - -impl X509PurposeRef { - /// Get the internal table index of an X509_PURPOSE for a given short name. Valid short - /// names include - /// - "sslclient", - /// - "sslserver", - /// - "nssslserver", - /// - "smimesign", - /// - "smimeencrypt", - /// - "crlsign", - /// - "any", - /// - "ocsphelper", - /// - "timestampsign" - /// - /// The index can be used with `X509PurposeRef::from_idx()` to get the purpose. - #[allow(clippy::unnecessary_cast)] - pub fn get_by_sname(sname: &str) -> Result { - unsafe { - let sname = CString::new(sname).unwrap(); - cfg_if! { - if #[cfg(any(ossl110, libressl, boringssl, awslc))] { - let purpose = cvt_n(ffi::X509_PURPOSE_get_by_sname(sname.as_ptr() as *const _))?; - } else { - let purpose = cvt_n(ffi::X509_PURPOSE_get_by_sname(sname.as_ptr() as *mut _))?; - } - } - Ok(purpose) - } - } - /// Get an `X509PurposeRef` for a given index value. The index can be obtained from e.g. - /// `X509PurposeRef::get_by_sname()`. - #[corresponds(X509_PURPOSE_get0)] - pub fn from_idx(idx: c_int) -> Result<&'static X509PurposeRef, ErrorStack> { - unsafe { - let ptr = cvt_p_const(ffi::X509_PURPOSE_get0(idx))?; - Ok(X509PurposeRef::from_const_ptr(ptr)) - } - } - - /// Get the purpose value from an X509Purpose structure. This value is one of - /// - `X509_PURPOSE_SSL_CLIENT` - /// - `X509_PURPOSE_SSL_SERVER` - /// - `X509_PURPOSE_NS_SSL_SERVER` - /// - `X509_PURPOSE_SMIME_SIGN` - /// - `X509_PURPOSE_SMIME_ENCRYPT` - /// - `X509_PURPOSE_CRL_SIGN` - /// - `X509_PURPOSE_ANY` - /// - `X509_PURPOSE_OCSP_HELPER` - /// - `X509_PURPOSE_TIMESTAMP_SIGN` - pub fn purpose(&self) -> X509PurposeId { - unsafe { - cfg_if! { - if #[cfg(any(ossl110, libressl, boringssl, awslc))] { - let x509_purpose = self.as_ptr() as *const ffi::X509_PURPOSE; - } else { - let x509_purpose = self.as_ptr() as *mut ffi::X509_PURPOSE; - } - } - X509PurposeId::from_raw(ffi::X509_PURPOSE_get_id(x509_purpose)) - } - } -} diff --git a/patch/openssl/src/x509/store.rs b/patch/openssl/src/x509/store.rs deleted file mode 100644 index 116d7effe40c2..0000000000000 --- a/patch/openssl/src/x509/store.rs +++ /dev/null @@ -1,301 +0,0 @@ -//! 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::asn1::Asn1Time; -//! 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(); -//! -//! // Sep 27th, 2016 -//! let sample_time = Asn1Time::from_unix(1474934400).unwrap(); -//! -//! 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.set_not_before(&sample_time); -//! builder.set_not_after(&sample_time); -//! 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::{ForeignType, ForeignTypeRef}; -use std::mem; - -use crate::error::ErrorStack; -#[cfg(not(any(boringssl, awslc)))] -use crate::ssl::SslFiletype; -#[cfg(ossl300)] -use crate::stack::Stack; -use crate::stack::StackRef; -use crate::util::ForeignTypeRefExt; -use crate::x509::verify::{X509VerifyFlags, X509VerifyParamRef}; -use crate::x509::{X509Object, X509PurposeId, X509}; -use crate::{cvt, cvt_p}; -use openssl_macros::corresponds; -#[cfg(not(any(boringssl, awslc)))] -use std::ffi::CString; -#[cfg(not(any(boringssl, awslc)))] -use std::path::Path; - -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 { - 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( - &mut self, - method: &'static X509LookupMethodRef, - ) -> Result<&mut X509LookupRef, 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)] - pub fn set_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::X509_STORE_set_flags(self.as_ptr(), flags.bits())).map(|_| ()) } - } - - /// Sets the certificate purpose. - /// The purpose value can be obtained by `X509PurposeRef::get_by_sname()` - #[corresponds(X509_STORE_set_purpose)] - pub fn set_purpose(&mut self, purpose: X509PurposeId) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::X509_STORE_set_purpose(self.as_ptr(), purpose.as_raw())).map(|_| ()) } - } - - /// Sets certificate chain validation related parameters. - #[corresponds[X509_STORE_set1_param]] - pub fn set_param(&mut self, param: &X509VerifyParamRef) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::X509_STORE_set1_param(self.as_ptr(), param.as_ptr())).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; - /// A reference to an [`X509Lookup`]. - pub struct X509LookupRef; -} - -/// Marker type corresponding to the [`X509_LOOKUP_hash_dir`] lookup method. -/// -/// [`X509_LOOKUP_hash_dir`]: https://docs.openssl.org/master/man3/X509_LOOKUP_hash_dir/ -// FIXME should be an enum -pub struct HashDir; - -impl X509Lookup { - /// 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 { - unsafe { X509LookupMethodRef::from_const_ptr(ffi::X509_LOOKUP_hash_dir()) } - } -} - -#[cfg(not(any(boringssl, awslc)))] -impl X509LookupRef { - /// 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(|_| ()) - } - } -} - -/// Marker type corresponding to the [`X509_LOOKUP_file`] lookup method. -/// -/// [`X509_LOOKUP_file`]: https://docs.openssl.org/master/man3/X509_LOOKUP_file/ -pub struct File; - -impl X509Lookup { - /// Lookup method loads all the certificates or CRLs present in a file - /// into memory at the time the file is added as a lookup source. - #[corresponds(X509_LOOKUP_file)] - pub fn file() -> &'static X509LookupMethodRef { - unsafe { X509LookupMethodRef::from_const_ptr(ffi::X509_LOOKUP_file()) } - } -} - -#[cfg(not(any(boringssl, awslc)))] -impl X509LookupRef { - /// Specifies a file from which certificates will be loaded - #[corresponds(X509_load_cert_file)] - // FIXME should return 'Result>( - &mut self, - file: P, - file_type: SslFiletype, - ) -> Result<(), ErrorStack> { - let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); - unsafe { - cvt(ffi::X509_load_cert_file( - self.as_ptr(), - file.as_ptr(), - file_type.as_raw(), - )) - .map(|_| ()) - } - } - - /// Specifies a file from which certificate revocation lists will be loaded - #[corresponds(X509_load_crl_file)] - pub fn load_crl_file>( - &mut self, - file: P, - file_type: SslFiletype, - ) -> Result { - let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); - unsafe { - cvt(ffi::X509_load_crl_file( - self.as_ptr(), - file.as_ptr(), - file_type.as_raw(), - )) - } - } -} - -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; - /// A reference to an [`X509LookupMethod`]. - pub struct X509LookupMethodRef; -} - -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. - /// - /// This method is deprecated. It is **unsound** and will be removed in a - /// future version of rust-openssl. `X509StoreRef::all_certificates` - /// should be used instead. - #[deprecated( - note = "This method is unsound, and will be removed in a future version of rust-openssl. X509StoreRef::all_certificates should be used instead." - )] - #[corresponds(X509_STORE_get0_objects)] - pub fn objects(&self) -> &StackRef { - unsafe { StackRef::from_ptr(X509_STORE_get0_objects(self.as_ptr())) } - } - - /// Returns a stack of all the certificates in this store. - #[corresponds(X509_STORE_get1_all_certs)] - #[cfg(ossl300)] - pub fn all_certificates(&self) -> Stack { - unsafe { Stack::from_ptr(ffi::X509_STORE_get1_all_certs(self.as_ptr())) } - } -} - -cfg_if! { - if #[cfg(any(boringssl, ossl110, libressl, awslc))] { - 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) {} - } -} diff --git a/patch/openssl/src/x509/tests.rs b/patch/openssl/src/x509/tests.rs deleted file mode 100644 index 760e676384b46..0000000000000 --- a/patch/openssl/src/x509/tests.rs +++ /dev/null @@ -1,1187 +0,0 @@ -use std::cmp::Ordering; - -use crate::asn1::{Asn1Object, Asn1OctetString, Asn1Time}; -use crate::bn::{BigNum, MsbOption}; -use crate::hash::MessageDigest; -use crate::nid::Nid; -use crate::pkey::{PKey, Private}; -use crate::rsa::Rsa; -#[cfg(not(any(boringssl, awslc)))] -use crate::ssl::SslFiletype; -use crate::stack::Stack; -use crate::x509::extension::{ - AuthorityKeyIdentifier, BasicConstraints, ExtendedKeyUsage, KeyUsage, SubjectAlternativeName, - SubjectKeyIdentifier, -}; -#[cfg(not(any(boringssl, awslc)))] -use crate::x509::store::X509Lookup; -use crate::x509::store::X509StoreBuilder; -use crate::x509::verify::{X509VerifyFlags, X509VerifyParam}; -#[cfg(any(ossl102, boringssl, awslc))] -use crate::x509::X509PurposeId; -use crate::x509::X509PurposeRef; -#[cfg(ossl110)] -use crate::x509::{CrlReason, X509Builder}; -use crate::x509::{ - CrlStatus, X509Crl, X509Extension, X509Name, X509Req, X509StoreContext, X509VerifyResult, X509, -}; - -#[cfg(ossl110)] -use foreign_types::ForeignType; -use hex::{self, FromHex}; -use libc::time_t; - -use super::{AuthorityInformationAccess, CertificateIssuer, ReasonCode}; - -fn pkey() -> PKey { - 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""#) - || 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] -#[cfg(any(ossl110, boringssl, awslc))] -fn test_retrieve_pathlen() { - let cert = include_bytes!("../../test/root-ca.pem"); - let cert = X509::from_pem(cert).unwrap(); - assert_eq!(cert.pathlen(), None); - - let cert = include_bytes!("../../test/intermediate-ca.pem"); - let cert = X509::from_pem(cert).unwrap(); - assert_eq!(cert.pathlen(), Some(0)); - - let cert = include_bytes!("../../test/alt_name_cert.pem"); - let cert = X509::from_pem(cert).unwrap(); - assert_eq!(cert.pathlen(), None); -} - -#[test] -#[cfg(any(ossl110, boringssl, awslc))] -fn test_subject_key_id() { - let cert = include_bytes!("../../test/certv3.pem"); - let cert = X509::from_pem(cert).unwrap(); - - let subject_key_id = cert.subject_key_id().unwrap(); - assert_eq!( - subject_key_id.as_slice(), - &b"\xB6\x73\x2F\x61\xA5\x4B\xA1\xEF\x48\x2C\x15\xB1\x9F\xF3\xDC\x34\x2F\xBC\xAC\x30"[..] - ); -} - -#[test] -#[cfg(any(ossl110, boringssl, awslc))] -fn test_authority_key_id() { - let cert = include_bytes!("../../test/certv3.pem"); - let cert = X509::from_pem(cert).unwrap(); - - let authority_key_id = cert.authority_key_id().unwrap(); - assert_eq!( - authority_key_id.as_slice(), - &b"\x6C\xD3\xA5\x03\xAB\x0D\x5F\x2C\xC9\x8D\x8A\x9C\x88\xA7\x88\x77\xB8\x37\xFD\x9A"[..] - ); -} - -#[test] -#[cfg(ossl111d)] -fn test_authority_issuer_and_serial() { - let cert = include_bytes!("../../test/authority_key_identifier.pem"); - let cert = X509::from_pem(cert).unwrap(); - - let authority_issuer = cert.authority_issuer().unwrap(); - assert_eq!(1, authority_issuer.len()); - let dn = authority_issuer[0].directory_name().unwrap(); - let mut o = dn.entries_by_nid(Nid::ORGANIZATIONNAME); - let o = o.next().unwrap().data().as_utf8().unwrap(); - assert_eq!(o.as_bytes(), b"PyCA"); - let mut cn = dn.entries_by_nid(Nid::COMMONNAME); - let cn = cn.next().unwrap().data().as_utf8().unwrap(); - assert_eq!(cn.as_bytes(), b"cryptography.io"); - - let authority_serial = cert.authority_serial().unwrap(); - let serial = authority_serial.to_bn().unwrap(); - let expected = BigNum::from_u32(3).unwrap(); - assert_eq!(serial, expected); -} - -#[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] -// This tests `X509Extension::new`, even though its deprecated. -#[allow(deprecated)] -fn x509_extension_new() { - assert!(X509Extension::new(None, None, "crlDistributionPoints", "section").is_err()); - assert!(X509Extension::new(None, None, "proxyCertInfo", "").is_err()); - assert!(X509Extension::new(None, None, "certificatePolicies", "").is_err()); - assert!(X509Extension::new(None, None, "subjectAltName", "dirName:section").is_err()); -} - -#[test] -fn x509_extension_new_from_der() { - let ext = X509Extension::new_from_der( - &Asn1Object::from_str("2.5.29.19").unwrap(), - true, - &Asn1OctetString::new_from_bytes(b"\x30\x03\x01\x01\xff").unwrap(), - ) - .unwrap(); - assert_eq!( - ext.to_der().unwrap(), - b"0\x0f\x06\x03U\x1d\x13\x01\x01\xff\x04\x050\x03\x01\x01\xff" - ); -} - -#[test] -fn x509_extension_to_der() { - let builder = X509::builder().unwrap(); - - for (ext, expected) in [ - ( - BasicConstraints::new().critical().ca().build().unwrap(), - b"0\x0f\x06\x03U\x1d\x13\x01\x01\xff\x04\x050\x03\x01\x01\xff" as &[u8], - ), - ( - SubjectAlternativeName::new() - .dns("example.com,DNS:example2.com") - .build(&builder.x509v3_context(None, None)) - .unwrap(), - b"0'\x06\x03U\x1d\x11\x04 0\x1e\x82\x1cexample.com,DNS:example2.com", - ), - ( - SubjectAlternativeName::new() - .rid("1.2.3.4") - .uri("https://example.com") - .build(&builder.x509v3_context(None, None)) - .unwrap(), - b"0#\x06\x03U\x1d\x11\x04\x1c0\x1a\x88\x03*\x03\x04\x86\x13https://example.com", - ), - ( - ExtendedKeyUsage::new() - .server_auth() - .other("2.999.1") - .other("clientAuth") - .build() - .unwrap(), - b"0\x22\x06\x03U\x1d%\x04\x1b0\x19\x06\x08+\x06\x01\x05\x05\x07\x03\x01\x06\x03\x887\x01\x06\x08+\x06\x01\x05\x05\x07\x03\x02", - ), - ] { - assert_eq!(&ext.to_der().unwrap(), expected); - } -} - -#[test] -fn eku_invalid_other() { - assert!(ExtendedKeyUsage::new() - .other("1.1.1.1.1,2.2.2.2.2") - .build() - .is_err()); -} - -#[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(0).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] -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" - ) -} - -#[test] -fn test_verify_cert_with_purpose() { - 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(); - let purpose_idx = X509PurposeRef::get_by_sname("sslserver") - .expect("Getting certificate purpose 'sslserver' failed"); - let x509_purposeref = - X509PurposeRef::from_idx(purpose_idx).expect("Getting certificate purpose failed"); - store_bldr - .set_purpose(x509_purposeref.purpose()) - .expect("Setting certificate purpose failed"); - 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] -fn test_verify_cert_with_wrong_purpose_fails() { - 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(); - let purpose_idx = X509PurposeRef::get_by_sname("timestampsign") - .expect("Getting certificate purpose 'timestampsign' failed"); - let x509_purpose = - X509PurposeRef::from_idx(purpose_idx).expect("Getting certificate purpose failed"); - store_bldr - .set_purpose(x509_purpose.purpose()) - .expect("Setting certificate purpose failed"); - store_bldr.add_cert(ca).unwrap(); - - let store = store_bldr.build(); - - let expected_error = ffi::X509_V_ERR_INVALID_PURPOSE; - let mut context = X509StoreContext::new().unwrap(); - assert_eq!( - context - .init(&store, &cert, &chain, |c| { - c.verify_cert()?; - Ok(c.error()) - }) - .unwrap() - .as_raw(), - expected_error - ) -} - -#[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_load_crl() { - let ca = include_bytes!("../../test/crl-ca.crt"); - let ca = X509::from_pem(ca).unwrap(); - - let crl = include_bytes!("../../test/test.crl"); - let crl = X509Crl::from_der(crl).unwrap(); - assert!(crl.verify(&ca.public_key().unwrap()).unwrap()); - - let cert = include_bytes!("../../test/subca.crt"); - let cert = X509::from_pem(cert).unwrap(); - - let revoked = match crl.get_by_cert(&cert) { - CrlStatus::Revoked(revoked) => revoked, - _ => panic!("cert should be revoked"), - }; - - assert_eq!( - revoked.serial_number().to_bn().unwrap(), - cert.serial_number().to_bn().unwrap(), - "revoked and cert serial numbers should match" - ); -} - -#[test] -fn test_crl_entry_extensions() { - let crl = include_bytes!("../../test/entry_extensions.crl"); - let crl = X509Crl::from_pem(crl).unwrap(); - - let (critical, access_info) = crl - .extension::() - .unwrap() - .expect("Authority Information Access extension should be present"); - assert!( - !critical, - "Authority Information Access extension is not critical" - ); - assert_eq!( - access_info.len(), - 1, - "Authority Information Access should have one entry" - ); - assert_eq!(access_info[0].method().to_string(), "CA Issuers"); - assert_eq!( - access_info[0].location().uri(), - Some("http://www.example.com/ca.crt") - ); - let revoked_certs = crl.get_revoked().unwrap(); - let entry = &revoked_certs[0]; - - let (critical, issuer) = entry - .extension::() - .unwrap() - .expect("Certificate issuer extension should be present"); - assert!(critical, "Certificate issuer extension is critical"); - assert_eq!(issuer.len(), 1, "Certificate issuer should have one entry"); - let issuer = issuer[0] - .directory_name() - .expect("Issuer should be a directory name"); - assert_eq!( - format!("{:?}", issuer), - r#"[countryName = "GB", commonName = "Test CA"]"# - ); - - // reason_code can't be inspected without ossl110 - #[allow(unused_variables)] - let (critical, reason_code) = entry - .extension::() - .unwrap() - .expect("Reason code extension should be present"); - assert!(!critical, "Reason code extension is not critical"); - #[cfg(ossl110)] - assert_eq!( - CrlReason::KEY_COMPROMISE, - CrlReason::from_raw(reason_code.get_i64().unwrap() as ffi::c_int) - ); -} - -#[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 - ); - } -} - -#[test] -fn test_convert_req_to_text() { - let csr = include_bytes!("../../test/csr.pem"); - let csr = X509Req::from_pem(csr).unwrap(); - - const SUBSTRINGS: &[&str] = &[ - "Certificate Request:\n", - "Version:", - "Subject: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=foobar.com\n", - "Subject Public Key Info:", - "Signature Algorithm:", - ]; - - let text = String::from_utf8(csr.to_text().unwrap()).unwrap(); - - for substring in SUBSTRINGS { - assert!( - text.contains(substring), - "{:?} not found inside {}", - substring, - text - ); - } -} - -#[test] -fn test_name_cmp() { - let cert = include_bytes!("../../test/cert.pem"); - let cert = X509::from_pem(cert).unwrap(); - - let subject = cert.subject_name(); - let issuer = cert.issuer_name(); - assert_eq!(Ordering::Equal, subject.try_cmp(subject).unwrap()); - assert_eq!(Ordering::Greater, subject.try_cmp(issuer).unwrap()); -} - -#[test] -#[cfg(any(boringssl, ossl110, libressl, awslc))] -fn test_name_to_owned() { - let cert = include_bytes!("../../test/cert.pem"); - let cert = X509::from_pem(cert).unwrap(); - let name = cert.subject_name(); - let copied_name = name.to_owned().unwrap(); - assert_eq!(Ordering::Equal, name.try_cmp(&copied_name).unwrap()); -} - -#[test] -fn test_verify_param_set_time_fails_verification() { - const TEST_T_2030: time_t = 1893456000; - - 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 mut verify_params = X509VerifyParam::new().unwrap(); - verify_params.set_time(TEST_T_2030); - store_bldr.set_param(&verify_params).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(), - "certificate has expired" - ) -} - -#[test] -fn test_verify_param_set_time() { - const TEST_T_2020: time_t = 1577836800; - - 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 mut verify_params = X509VerifyParam::new().unwrap(); - verify_params.set_time(TEST_T_2020); - store_bldr.set_param(&verify_params).unwrap(); - let store = store_bldr.build(); - - let mut context = X509StoreContext::new().unwrap(); - assert!(context - .init(&store, &cert, &chain, |c| c.verify_cert()) - .unwrap()); -} - -#[test] -fn test_verify_param_set_depth() { - let cert = include_bytes!("../../test/leaf.pem"); - let cert = X509::from_pem(cert).unwrap(); - let intermediate_ca = include_bytes!("../../test/intermediate-ca.pem"); - let intermediate_ca = X509::from_pem(intermediate_ca).unwrap(); - let ca = include_bytes!("../../test/root-ca.pem"); - let ca = X509::from_pem(ca).unwrap(); - let mut chain = Stack::new().unwrap(); - chain.push(intermediate_ca).unwrap(); - - let mut store_bldr = X509StoreBuilder::new().unwrap(); - store_bldr.add_cert(ca).unwrap(); - let mut verify_params = X509VerifyParam::new().unwrap(); - // OpenSSL 1.1.0+ considers the root certificate to not be part of the chain, while 1.0.2 and LibreSSL do - let expected_depth = if cfg!(any(ossl110)) { 1 } else { 2 }; - verify_params.set_depth(expected_depth); - store_bldr.set_param(&verify_params).unwrap(); - let store = store_bldr.build(); - - let mut context = X509StoreContext::new().unwrap(); - assert!(context - .init(&store, &cert, &chain, |c| c.verify_cert()) - .unwrap()); -} - -#[test] -#[allow(clippy::bool_to_int_with_if)] -fn test_verify_param_set_depth_fails_verification() { - let cert = include_bytes!("../../test/leaf.pem"); - let cert = X509::from_pem(cert).unwrap(); - let intermediate_ca = include_bytes!("../../test/intermediate-ca.pem"); - let intermediate_ca = X509::from_pem(intermediate_ca).unwrap(); - let ca = include_bytes!("../../test/root-ca.pem"); - let ca = X509::from_pem(ca).unwrap(); - let mut chain = Stack::new().unwrap(); - chain.push(intermediate_ca).unwrap(); - - let mut store_bldr = X509StoreBuilder::new().unwrap(); - store_bldr.add_cert(ca).unwrap(); - let mut verify_params = X509VerifyParam::new().unwrap(); - // OpenSSL 1.1.0+ considers the root certificate to not be part of the chain, while 1.0.2 and LibreSSL do - let expected_depth = if cfg!(any(ossl110, boringssl, awslc)) { - 0 - } else { - 1 - }; - verify_params.set_depth(expected_depth); - store_bldr.set_param(&verify_params).unwrap(); - let store = store_bldr.build(); - - // OpenSSL 1.1.0+ added support for X509_V_ERR_CERT_CHAIN_TOO_LONG, while 1.0.2 simply ignores the intermediate - let expected_error = if cfg!(any(ossl110, libressl)) { - "certificate chain too long" - } else { - "unable to get local issuer certificate" - }; - - let mut context = X509StoreContext::new().unwrap(); - assert_eq!( - context - .init(&store, &cert, &chain, |c| { - c.verify_cert()?; - Ok(c.error()) - }) - .unwrap() - .error_string(), - expected_error - ) -} - -#[test] -#[cfg(not(any(boringssl, awslc)))] -fn test_load_cert_file() { - let cert = include_bytes!("../../test/cert.pem"); - let cert = X509::from_pem(cert).unwrap(); - let chain = Stack::new().unwrap(); - - let mut store_bldr = X509StoreBuilder::new().unwrap(); - let lookup = store_bldr.add_lookup(X509Lookup::file()).unwrap(); - lookup - .load_cert_file("test/root-ca.pem", SslFiletype::PEM) - .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(ossl110)] -fn test_verify_param_auth_level() { - let mut param = X509VerifyParam::new().unwrap(); - let auth_lvl = 2; - let auth_lvl_default = -1; - - assert_eq!(param.auth_level(), auth_lvl_default); - - param.set_auth_level(auth_lvl); - assert_eq!(param.auth_level(), auth_lvl); -} - -#[test] -#[cfg(any(ossl102, boringssl, awslc))] -fn test_set_purpose() { - let cert = include_bytes!("../../test/leaf.pem"); - let cert = X509::from_pem(cert).unwrap(); - let intermediate_ca = include_bytes!("../../test/intermediate-ca.pem"); - let intermediate_ca = X509::from_pem(intermediate_ca).unwrap(); - let ca = include_bytes!("../../test/root-ca.pem"); - let ca = X509::from_pem(ca).unwrap(); - let mut chain = Stack::new().unwrap(); - chain.push(intermediate_ca).unwrap(); - - let mut store_bldr = X509StoreBuilder::new().unwrap(); - store_bldr.add_cert(ca).unwrap(); - let mut verify_params = X509VerifyParam::new().unwrap(); - verify_params.set_purpose(X509PurposeId::ANY).unwrap(); - store_bldr.set_param(&verify_params).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, boringssl, awslc))] -fn test_set_purpose_fails_verification() { - let cert = include_bytes!("../../test/leaf.pem"); - let cert = X509::from_pem(cert).unwrap(); - let intermediate_ca = include_bytes!("../../test/intermediate-ca.pem"); - let intermediate_ca = X509::from_pem(intermediate_ca).unwrap(); - let ca = include_bytes!("../../test/root-ca.pem"); - let ca = X509::from_pem(ca).unwrap(); - let mut chain = Stack::new().unwrap(); - chain.push(intermediate_ca).unwrap(); - - let mut store_bldr = X509StoreBuilder::new().unwrap(); - store_bldr.add_cert(ca).unwrap(); - let mut verify_params = X509VerifyParam::new().unwrap(); - verify_params - .set_purpose(X509PurposeId::TIMESTAMP_SIGN) - .unwrap(); - store_bldr.set_param(&verify_params).unwrap(); - let store = store_bldr.build(); - - let expected_error = ffi::X509_V_ERR_INVALID_PURPOSE; - let mut context = X509StoreContext::new().unwrap(); - assert_eq!( - context - .init(&store, &cert, &chain, |c| { - c.verify_cert()?; - Ok(c.error()) - }) - .unwrap() - .as_raw(), - expected_error - ) -} - -#[test] -fn test_add_name_entry() { - let cert = include_bytes!("../../test/cert.pem"); - let cert = X509::from_pem(cert).unwrap(); - let inp_name = cert.subject_name().entries().next().unwrap(); - - let mut names = X509Name::builder().unwrap(); - names.append_entry(inp_name).unwrap(); - let names = names.build(); - - let mut entries = names.entries(); - let outp_name = entries.next().unwrap(); - assert_eq!(outp_name.object().nid(), inp_name.object().nid()); - assert_eq!(outp_name.data().as_slice(), inp_name.data().as_slice()); - assert!(entries.next().is_none()); -} - -#[test] -#[cfg(not(any(boringssl, awslc)))] -fn test_load_crl_file_fail() { - let mut store_bldr = X509StoreBuilder::new().unwrap(); - let lookup = store_bldr.add_lookup(X509Lookup::file()).unwrap(); - let res = lookup.load_crl_file("test/root-ca.pem", SslFiletype::PEM); - assert!(res.is_err()); -} - -#[cfg(ossl110)] -fn ipaddress_as_subject_alternative_name_is_formatted_in_debug(expected_ip: T) -where - T: Into, -{ - let expected_ip = format!("{:?}", expected_ip.into()); - let mut builder = X509Builder::new().unwrap(); - let san = SubjectAlternativeName::new() - .ip(&expected_ip) - .build(&builder.x509v3_context(None, None)) - .unwrap(); - builder.append_extension(san).unwrap(); - let cert = builder.build(); - let actual_ip = cert - .subject_alt_names() - .into_iter() - .flatten() - .map(|n| format!("{:?}", *n)) - .next() - .unwrap(); - assert_eq!(actual_ip, expected_ip); -} - -#[cfg(ossl110)] -#[test] -fn ipv4_as_subject_alternative_name_is_formatted_in_debug() { - ipaddress_as_subject_alternative_name_is_formatted_in_debug([8u8, 8, 8, 128]); -} - -#[cfg(ossl110)] -#[test] -fn ipv6_as_subject_alternative_name_is_formatted_in_debug() { - ipaddress_as_subject_alternative_name_is_formatted_in_debug([ - 8u8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 128, - ]); -} - -#[cfg(ossl110)] -#[test] -fn other_name_as_subject_alternative_name() { - let oid = Asn1Object::from_str("1.3.6.1.5.5.7.8.11").unwrap(); - // this is the hex representation of "test" encoded as a ia5string - let content = [0x16, 0x04, 0x74, 0x65, 0x73, 0x74]; - - let mut builder = X509Builder::new().unwrap(); - let san = SubjectAlternativeName::new() - .other_name2(oid, &content) - .build(&builder.x509v3_context(None, None)) - .unwrap(); - builder.append_extension(san).unwrap(); - let cert = builder.build(); - let general_name = cert - .subject_alt_names() - .into_iter() - .flatten() - .next() - .unwrap(); - unsafe { - assert_eq!((*general_name.as_ptr()).type_, 0); - } -} - -#[test] -fn test_dist_point() { - let cert = include_bytes!("../../test/certv3.pem"); - let cert = X509::from_pem(cert).unwrap(); - - let dps = cert.crl_distribution_points().unwrap(); - let dp = dps.get(0).unwrap(); - let dp_nm = dp.distpoint().unwrap(); - let dp_gns = dp_nm.fullname().unwrap(); - let dp_gn = dp_gns.get(0).unwrap(); - assert_eq!(dp_gn.uri().unwrap(), "http://example.com/crl.pem"); - - let dp = dps.get(1).unwrap(); - let dp_nm = dp.distpoint().unwrap(); - let dp_gns = dp_nm.fullname().unwrap(); - let dp_gn = dp_gns.get(0).unwrap(); - assert_eq!(dp_gn.uri().unwrap(), "http://example.com/crl2.pem"); - assert!(dps.get(2).is_none()) -} - -#[test] -fn test_dist_point_null() { - let cert = include_bytes!("../../test/cert.pem"); - let cert = X509::from_pem(cert).unwrap(); - assert!(cert.crl_distribution_points().is_none()); -} - -#[test] -#[cfg(ossl300)] -fn test_store_all_certificates() { - let cert = include_bytes!("../../test/cert.pem"); - let cert = X509::from_pem(cert).unwrap(); - - let store = { - let mut b = X509StoreBuilder::new().unwrap(); - b.add_cert(cert).unwrap(); - b.build() - }; - - assert_eq!(store.all_certificates().len(), 1); -} diff --git a/patch/openssl/src/x509/verify.rs b/patch/openssl/src/x509/verify.rs deleted file mode 100644 index 249faf9869ad1..0000000000000 --- a/patch/openssl/src/x509/verify.rs +++ /dev/null @@ -1,211 +0,0 @@ -use bitflags::bitflags; -use foreign_types::ForeignTypeRef; -use libc::{c_int, c_uint, c_ulong, time_t}; -use std::net::IpAddr; - -use crate::error::ErrorStack; -use crate::x509::X509PurposeId; -use crate::{cvt, cvt_p}; -use openssl_macros::corresponds; - -bitflags! { - /// Flags used to check an `X509` certificate. - #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - #[repr(transparent)] - pub struct X509CheckFlags: c_uint { - const ALWAYS_CHECK_SUBJECT = ffi::X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT as _; - const NO_WILDCARDS = ffi::X509_CHECK_FLAG_NO_WILDCARDS as _; - const NO_PARTIAL_WILDCARDS = ffi::X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS as _; - const MULTI_LABEL_WILDCARDS = ffi::X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS as _; - const SINGLE_LABEL_SUBDOMAINS = ffi::X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS as _; - /// 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 as _; - } -} - -bitflags! { - /// Flags used to verify an `X509` certificate chain. - #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - #[repr(transparent)] - pub struct X509VerifyFlags: c_ulong { - const CB_ISSUER_CHECK = ffi::X509_V_FLAG_CB_ISSUER_CHECK as _; - const USE_CHECK_TIME = ffi::X509_V_FLAG_USE_CHECK_TIME as _; - const CRL_CHECK = ffi::X509_V_FLAG_CRL_CHECK as _; - const CRL_CHECK_ALL = ffi::X509_V_FLAG_CRL_CHECK_ALL as _; - const IGNORE_CRITICAL = ffi::X509_V_FLAG_IGNORE_CRITICAL as _; - const X509_STRICT = ffi::X509_V_FLAG_X509_STRICT as _; - const ALLOW_PROXY_CERTS = ffi::X509_V_FLAG_ALLOW_PROXY_CERTS as _; - const POLICY_CHECK = ffi::X509_V_FLAG_POLICY_CHECK as _; - const EXPLICIT_POLICY = ffi::X509_V_FLAG_EXPLICIT_POLICY as _; - const INHIBIT_ANY = ffi::X509_V_FLAG_INHIBIT_ANY as _; - const INHIBIT_MAP = ffi::X509_V_FLAG_INHIBIT_MAP as _; - const NOTIFY_POLICY = ffi::X509_V_FLAG_NOTIFY_POLICY as _; - const EXTENDED_CRL_SUPPORT = ffi::X509_V_FLAG_EXTENDED_CRL_SUPPORT as _; - const USE_DELTAS = ffi::X509_V_FLAG_USE_DELTAS as _; - const CHECK_SS_SIGNATURE = ffi::X509_V_FLAG_CHECK_SS_SIGNATURE as _; - const TRUSTED_FIRST = ffi::X509_V_FLAG_TRUSTED_FIRST as _; - #[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; - const PARTIAL_CHAIN = ffi::X509_V_FLAG_PARTIAL_CHAIN as _; - #[cfg(any(ossl110, boringssl, awslc, libressl))] - const NO_ALT_CHAINS = ffi::X509_V_FLAG_NO_ALT_CHAINS as _; - #[cfg(any(ossl110, boringssl, awslc, libressl))] - const NO_CHECK_TIME = ffi::X509_V_FLAG_NO_CHECK_TIME as _; - } -} - -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 X509VerifyParam { - /// Create an X509VerifyParam - #[corresponds(X509_VERIFY_PARAM_new)] - pub fn new() -> Result { - unsafe { - ffi::init(); - cvt_p(ffi::X509_VERIFY_PARAM_new()).map(X509VerifyParam) - } - } -} - -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::from_bits_retain(bits) - } - - /// Set the expected DNS hostname. - #[corresponds(X509_VERIFY_PARAM_set1_host)] - pub fn set_host(&mut self, host: &str) -> Result<(), ErrorStack> { - unsafe { - // len == 0 means "run strlen" :( - let raw_host = if host.is_empty() { "\0" } else { host }; - cvt(ffi::X509_VERIFY_PARAM_set1_host( - self.as_ptr(), - raw_host.as_ptr() as *const _, - host.len(), - )) - .map(|_| ()) - } - } - - /// Set the expected email address. - #[corresponds(X509_VERIFY_PARAM_set1_email)] - pub fn set_email(&mut self, email: &str) -> Result<(), ErrorStack> { - unsafe { - // len == 0 means "run strlen" :( - let raw_email = if email.is_empty() { "\0" } else { email }; - cvt(ffi::X509_VERIFY_PARAM_set1_email( - self.as_ptr(), - raw_email.as_ptr() as *const _, - email.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(|_| ()) - } - } - - /// Set the verification time, where time is of type time_t, traditionally defined as seconds since the epoch - #[corresponds(X509_VERIFY_PARAM_set_time)] - pub fn set_time(&mut self, time: time_t) { - unsafe { ffi::X509_VERIFY_PARAM_set_time(self.as_ptr(), time) } - } - - /// Set the verification depth - #[corresponds(X509_VERIFY_PARAM_set_depth)] - pub fn set_depth(&mut self, depth: c_int) { - unsafe { ffi::X509_VERIFY_PARAM_set_depth(self.as_ptr(), depth) } - } - - /// Sets the authentication security level to auth_level - #[corresponds(X509_VERIFY_PARAM_set_auth_level)] - #[cfg(ossl110)] - pub fn set_auth_level(&mut self, lvl: c_int) { - unsafe { ffi::X509_VERIFY_PARAM_set_auth_level(self.as_ptr(), lvl) } - } - - /// Gets the current authentication security level - #[corresponds(X509_VERIFY_PARAM_get_auth_level)] - #[cfg(ossl110)] - pub fn auth_level(&self) -> i32 { - unsafe { ffi::X509_VERIFY_PARAM_get_auth_level(self.as_ptr()) } - } - - /// Sets the verification purpose - #[corresponds(X509_VERIFY_PARAM_set_purpose)] - pub fn set_purpose(&mut self, purpose: X509PurposeId) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::X509_VERIFY_PARAM_set_purpose(self.as_ptr(), purpose.0)).map(|_| ()) } - } -} diff --git a/patch/openssl/test/aia_test_cert.pem b/patch/openssl/test/aia_test_cert.pem deleted file mode 100644 index 6cc522ec6fe99..0000000000000 --- a/patch/openssl/test/aia_test_cert.pem +++ /dev/null @@ -1,22 +0,0 @@ ------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----- diff --git a/patch/openssl/test/alt_name_cert.pem b/patch/openssl/test/alt_name_cert.pem deleted file mode 100644 index d9e9f90e19ca8..0000000000000 --- a/patch/openssl/test/alt_name_cert.pem +++ /dev/null @@ -1,22 +0,0 @@ ------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----- diff --git a/patch/openssl/test/authority_key_identifier.pem b/patch/openssl/test/authority_key_identifier.pem deleted file mode 100644 index cbe9169fc992f..0000000000000 --- a/patch/openssl/test/authority_key_identifier.pem +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDIjCCAgqgAwIBAgIBAzANBgkqhkiG9w0BAQUFADApMQ0wCwYDVQQKDARQeUNB -MRgwFgYDVQQDDA9jcnlwdG9ncmFwaHkuaW8wHhcNMTUwNTAzMDk0OTU2WhcNMTYw -NTAyMDk0OTU2WjApMQ0wCwYDVQQKDARQeUNBMRgwFgYDVQQDDA9jcnlwdG9ncmFw -aHkuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCadi1UZioxdnP -ajqlRZHeKsSxvXXhgrWvlt91P3gV0dBThRFhJsLOhjNLz6PO6KeRbjz9GhTA2hdk -xtIpXrjvTv9dEJ1/k0xebsHWgFC43aTlgekw0U4cMwMe5NGeeg1tfzbJwldIN+cK -vabc08ADlkmM6DMnUArkzA2yii0DErRFMSIGrkDr6E9puord3h6Mh8Jfnc3TDAq8 -Qo1DI2XM7oFSWNfecQ9KbIC5wzzT+7Shoyz7QmCk/XhRzt8Xcfc3yAXIwazvLf8b -YP1auaSG11a5E+w6onj91h8UHKKOXu+rdq5YYPZ+qUYpxA7ZJ/VAGadMulYbXaO8 -Syi39HTpAgMBAAGjVTBTMFEGA1UdIwRKMEiAFDlFPso9Yh3qhkn2WqtAt6RwmPHs -oS2kKzApMQ0wCwYDVQQKDARQeUNBMRgwFgYDVQQDDA9jcnlwdG9ncmFwaHkuaW+C -AQMwDQYJKoZIhvcNAQEFBQADggEBAFbZYy6aZJUK/f7nJx2Rs/ht6hMbM32/RoXZ -JGbYapNVqVu/vymcfc/se3FHS5OVmPsnRlo/FIKDn/r5DGl73Sn/FvDJiLJZFucT -msyYuHZ+ZRYWzWmN2fcB3cfxj0s3qps6f5OoCOqoINOSe4HRGlw4X9keZSD+3xAt -vHNwQdlPC7zWbPdrzLT+FqR0e/O81vFJJS6drHJWqPcR3NQVtZw+UF7A/HKwbfeL -Nu2zj6165hzOi9HUxa2/mPr/eLUUV1sTzXp2+TFjt3rVCjW1XnpMLdwNBHzjpyAB -dTOX3iw0+BPy3s2jtnCW1PLpc74kvSTaBwhg74sq39EXfIKax00= ------END CERTIFICATE----- diff --git a/patch/openssl/test/ca.crt b/patch/openssl/test/ca.crt deleted file mode 100644 index b441d6d8e187f..0000000000000 --- a/patch/openssl/test/ca.crt +++ /dev/null @@ -1,88 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: - 13:ae:da:d8:f4:18:d7:73:b8:bd:35:c9:ce:8e:b3:fc - Signature Algorithm: sha256WithRSAEncryption - Issuer: CN=TestCA - Validity - Not Before: Jun 6 19:11:19 2019 GMT - Not After : May 21 19:11:19 2022 GMT - Subject: CN=SubCA - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - RSA Public-Key: (2048 bit) - Modulus: - 00:b0:09:fc:54:e7:6a:9f:0c:bd:ad:5a:8d:ef:94: - 4e:11:a6:87:19:4f:bf:a6:e1:62:a5:2d:b7:17:df: - 67:53:70:da:fe:7d:99:17:ee:13:47:0b:40:0b:a2: - 34:32:a9:d3:bf:20:fc:13:77:a1:d5:26:60:1f:f0: - d4:be:dc:76:7c:1e:6c:b4:4c:01:7c:56:cd:5c:53: - ec:81:b3:81:2a:b2:35:26:06:5a:79:e0:b3:9e:e4: - 57:e1:09:de:ad:7f:c8:cd:87:ee:49:93:30:52:58: - b2:bc:0f:c1:b6:10:44:f8:85:d5:5b:0a:9b:28:fe: - f4:f4:4a:16:a6:f7:25:e9:96:47:69:73:5b:33:77: - 92:7d:61:8d:2a:3d:d5:04:89:40:bf:6b:d2:fd:5d: - e2:1a:80:a9:8e:c8:92:f6:e5:4c:00:84:f9:6e:2a: - 93:a3:23:ee:28:23:81:f4:54:f0:18:2c:ee:32:8e: - 38:9c:a0:c8:33:04:b0:fc:4c:43:1a:5c:04:84:9f: - 73:c6:08:c7:1d:64:39:fe:72:19:3b:cc:a5:fd:0b: - 43:25:0d:2b:a9:88:77:9e:62:e6:ac:c2:9a:60:42: - 4f:4a:54:47:bc:a0:29:72:7c:38:52:c9:ea:27:c5: - 3d:d0:81:4a:3e:b8:78:79:4b:89:b8:4e:6d:1b:24: - 15:bd - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 CRL Distribution Points: - - Full Name: - URI:http://127.0.0.1:8081/pki/test.crl - - X509v3 Basic Constraints: - CA:TRUE - X509v3 Subject Key Identifier: - FD:82:45:39:A1:91:41:F2:66:CC:0D:75:D5:0D:40:D5:81:A7:A1:43 - X509v3 Authority Key Identifier: - keyid:C5:CC:F5:A1:8C:D9:E4:A7:BA:EC:21:F5:D1:84:23:EA:0D:C2:C7:30 - DirName:/CN=TestCA - serial:33:E7:04:87:09:32:87:21:D9:CD:7C:AA:4C:5A:BB:2C:6C:7B:54:28 - - X509v3 Key Usage: - Certificate Sign, CRL Sign - Signature Algorithm: sha256WithRSAEncryption - 96:a0:ff:8a:4b:bd:45:96:c9:72:3c:63:e3:48:c4:ab:ef:7e: - db:76:3f:d9:02:9e:69:c8:d9:36:55:e1:f5:9b:c9:69:d8:69: - 02:ac:50:8c:60:94:2c:2e:b9:a8:65:ac:f5:00:b0:8b:96:25: - 0b:8a:ef:94:21:57:e2:04:c2:c3:86:bf:06:4e:91:5c:e6:bc: - 1b:03:31:8b:64:ea:c5:79:c3:5c:94:e5:aa:67:7e:74:12:07: - 14:fd:cd:32:02:26:26:c9:0a:ed:d4:da:ee:2a:84:e3:f1:60: - b3:09:77:27:a1:3c:ac:ec:61:18:30:b5:6d:1f:16:0a:24:1a: - cf:1c:1b:60:a5:60:e5:2c:8b:cf:37:83:0c:15:e7:79:30:3f: - ee:50:45:7c:4b:c6:2c:cd:2c:81:0a:98:f1:65:44:7a:ca:2a: - 20:1a:de:19:d9:4b:ca:a1:e2:a4:b5:14:47:bf:b4:68:15:03: - c0:55:e5:f4:47:0e:55:9f:fe:85:d8:2c:7d:d0:1a:96:11:b9: - 68:b7:74:1e:61:94:c1:ae:87:52:2d:c6:26:ba:51:ed:f1:91: - c0:e6:4c:f8:ad:02:23:75:51:fc:f8:69:05:ec:cf:31:50:5a: - 41:78:eb:3d:27:4d:9b:68:ef:ba:0e:ba:3a:7d:60:00:9d:53: - a5:08:3d:c6 ------BEGIN CERTIFICATE----- -MIIDbDCCAlSgAwIBAgIQE67a2PQY13O4vTXJzo6z/DANBgkqhkiG9w0BAQsFADAR -MQ8wDQYDVQQDDAZUZXN0Q0EwHhcNMTkwNjA2MTkxMTE5WhcNMjIwNTIxMTkxMTE5 -WjAQMQ4wDAYDVQQDDAVTdWJDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBALAJ/FTnap8Mva1aje+UThGmhxlPv6bhYqUttxffZ1Nw2v59mRfuE0cLQAui -NDKp078g/BN3odUmYB/w1L7cdnwebLRMAXxWzVxT7IGzgSqyNSYGWnngs57kV+EJ -3q1/yM2H7kmTMFJYsrwPwbYQRPiF1VsKmyj+9PRKFqb3JemWR2lzWzN3kn1hjSo9 -1QSJQL9r0v1d4hqAqY7IkvblTACE+W4qk6Mj7igjgfRU8Bgs7jKOOJygyDMEsPxM -QxpcBISfc8YIxx1kOf5yGTvMpf0LQyUNK6mId55i5qzCmmBCT0pUR7ygKXJ8OFLJ -6ifFPdCBSj64eHlLibhObRskFb0CAwEAAaOBwDCBvTAzBgNVHR8ELDAqMCigJqAk -hiJodHRwOi8vMTI3LjAuMC4xOjgwODEvcGtpL3Rlc3QuY3JsMAwGA1UdEwQFMAMB -Af8wHQYDVR0OBBYEFP2CRTmhkUHyZswNddUNQNWBp6FDMEwGA1UdIwRFMEOAFMXM -9aGM2eSnuuwh9dGEI+oNwscwoRWkEzARMQ8wDQYDVQQDDAZUZXN0Q0GCFDPnBIcJ -Moch2c18qkxauyxse1QoMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEA -lqD/iku9RZbJcjxj40jEq+9+23Y/2QKeacjZNlXh9ZvJadhpAqxQjGCULC65qGWs -9QCwi5YlC4rvlCFX4gTCw4a/Bk6RXOa8GwMxi2TqxXnDXJTlqmd+dBIHFP3NMgIm -JskK7dTa7iqE4/Fgswl3J6E8rOxhGDC1bR8WCiQazxwbYKVg5SyLzzeDDBXneTA/ -7lBFfEvGLM0sgQqY8WVEesoqIBreGdlLyqHipLUUR7+0aBUDwFXl9EcOVZ/+hdgs -fdAalhG5aLd0HmGUwa6HUi3GJrpR7fGRwOZM+K0CI3VR/PhpBezPMVBaQXjrPSdN -m2jvug66On1gAJ1TpQg9xg== ------END CERTIFICATE----- diff --git a/patch/openssl/test/cert.pem b/patch/openssl/test/cert.pem deleted file mode 100644 index 032fe60e90b90..0000000000000 --- a/patch/openssl/test/cert.pem +++ /dev/null @@ -1,19 +0,0 @@ ------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----- diff --git a/patch/openssl/test/certs.pem b/patch/openssl/test/certs.pem deleted file mode 100644 index 9d3516620da5d..0000000000000 --- a/patch/openssl/test/certs.pem +++ /dev/null @@ -1,40 +0,0 @@ ------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----- diff --git a/patch/openssl/test/certv3.pem b/patch/openssl/test/certv3.pem deleted file mode 100644 index 819409164d686..0000000000000 --- a/patch/openssl/test/certv3.pem +++ /dev/null @@ -1,23 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDwTCCAqmgAwIBAgIUDeCGNunyJfBd3U/qUtmCcvbMyZwwDQYJKoZIhvcNAQEL -BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM -GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMzAxMjMxMzMzNTJaFw0zMzAx -MjAxMzMzNTJaMFoxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw -HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEzARBgNVBAMMCmZvb2Jh -ci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCo9CWMRLMXo1CF -/iORh9B4NhtJF/8tR9PlG95sNvyWuQQ/8jfev+8zErplxfLkt0pJqcoiZG8g9NU0 -kU6o5T+/1QgZclCAoZaS0Jqxmoo2Yk/1Qsj16pnMBc10uSDk6V9aJSX1vKwONVNS -wiHA1MhX+i7Wf7/K0niq+k7hOkhleFkWgZtUq41gXh1VfOugka7UktYnk9mrBbAM -jmaloZNn2pMMAQxVg4ThiLm3zvuWqvXASWzUZc7IAd1GbN4AtDuhs252eqE9E4iT -Hk7F14wAS1JWqv666hReGHrmZJGx0xQTM9vPD1HN5t2U3KTfhO/mTlAUWVyg9tCt -OzboKgs1AgMBAAGjgZMwgZAwTgYDVR0fBEcwRTAgoB6gHIYaaHR0cDovL2V4YW1w -bGUuY29tL2NybC5wZW0wIaAfoB2GG2h0dHA6Ly9leGFtcGxlLmNvbS9jcmwyLnBl -bTAdBgNVHQ4EFgQUtnMvYaVLoe9ILBWxn/PcNC+8rDAwHwYDVR0jBBgwFoAUbNOl -A6sNXyzJjYqciKeId7g3/ZowDQYJKoZIhvcNAQELBQADggEBAJZyk6Eo4p3JIyOt -7t6ET3K18BKvlRilze+zrGkaQYvKRsP6YzbZWgcIq59hy5VeFCX5O2WP91CPG3MU -I9eRiih66/ry3G4I8QEdpRKnn0N5unbGjb5qPT5wXrhU4IO+vn3sGZGM4uIM1/3K -N/bOh9CTsu9YqrdHSGeDyNzCy/XZ/j5bP4aNm31ZDNCZDFsbjr3/yTLcpHPL0UP3 -mCX8D16BDu1Nep+wK9VRuOEw6Z9tlT/VjTImzoOUoJO/o2UHfSHahX+n2aC5OpI6 -BdhaFBuJ1vn+yTWf3zIjhWUdp9TlzgRyFiyetP2FcKwremVVGdDq/Y6dfXaq8CA1 -6Fr9KTY= ------END CERTIFICATE----- diff --git a/patch/openssl/test/certv3_extfile b/patch/openssl/test/certv3_extfile deleted file mode 100644 index 1b3df49482b95..0000000000000 --- a/patch/openssl/test/certv3_extfile +++ /dev/null @@ -1 +0,0 @@ -crlDistributionPoints=URI:http://example.com/crl.pem,URI:http://example.com/crl2.pem diff --git a/patch/openssl/test/cms.p12 b/patch/openssl/test/cms.p12 deleted file mode 100644 index c4f96b6996e41..0000000000000 Binary files a/patch/openssl/test/cms.p12 and /dev/null differ diff --git a/patch/openssl/test/cms_pubkey.der b/patch/openssl/test/cms_pubkey.der deleted file mode 100644 index e98fb966508ae..0000000000000 Binary files a/patch/openssl/test/cms_pubkey.der and /dev/null differ diff --git a/patch/openssl/test/corrupted-rsa.pem b/patch/openssl/test/corrupted-rsa.pem deleted file mode 100644 index fa2cc3b130124..0000000000000 --- a/patch/openssl/test/corrupted-rsa.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCyiHMQLLOSG6T6 -AYpMTJj9f4WzXQF0+T0Ri/Mk6vcJMQdnLMrlEMIJA/4iCn32zvpQ0raYcuZZoyso -/Svqg7tAeC3aQ/iFopYWfaR+SDMEnpKMl26qwiIxlPcj9J8hAQw/9WA7YneBXq+T -ypONX4EeDn+bsp/mSNSZKYJBmwXevQ9xbnOOxmBrVd5OS07ZwYuQXy8uVsYe4IXX -7/F+BIyULnIlUxRcVRjKp9++PeS53KLJX04H6HeqUiWC8Ntd+DuD3df0a067L38o -sc+CVzwKXqvh75RwlXCR4/B3D9qEqSYmY7lxp9vA3hirWcSJn0xUIbHb7q1hzE0H -rL65mLwnAgMBAAECggEADePYJpKBGBAm35KTcB3ngJWAJp/I92ZVbieNb7peJOzC -btsJIBWT2xVgm2+7NCK5+Tl486xrfTQuLUlhNiTbQof3HUumKr4nCjHqmdlD1YtW -yzG+7kceAkMyOoMThwL+Bn3bPP42CQPVCjJmahyGPvs8H2DK2E+jRr/4KTgxQTki -s/MXmJa4+xhvfF4CmFVj8imkKCyUTFoaqvYevHDMrJ3cohXFONBPv0MT8X/Y0sgw -UVaZ1aw3dbLC2PBpZFotILGxch2rODXgOcer/GBC41aGQTBB8mLPwKb6KMh0xdPd -1E5NwyODA3YJ6W3fGe8WE0MIHoYlOkX+ukf4W4+U0wKBgQDhueBkZwrd1HdhqwhG -QKt1/itCx24Go75G/+5vJUCB4bcdaJP49aH0/H4BiSsKI8r+GVsVJcrKP8h3tgjw -hhuLLPSaWi9TiUsWeDTw0JrAJc7w6hwL1EYbnwcto5mRQdbfugitlkhh17yUmgdj -gczAKLfV3igxslnR67iNOEYrlwKBgQDKejyWNnxhBJoXerpR/hijoXhMaHqV6Z7T -gUy6F0BiJ5CqN+TOTaC17CEnsMmI28o1rWJ6bIKwOUPFXOE9Z5gyxuIJhY9M8n30 -iwm/Ug2oBTFAdZQyyCuCmPiNURnGo+Hhu1EtVwMWLt3Z0L+/DdI6pgPX8mG0NNZm -+pS96Lg9owKBgHOzCslr5638kZSGTh90Vm6McTAxeLv+gjFyTYy6022/fFSenfom -LXWdVhkDbgQshIfqBz23uVIhj2eM7tgaZVPZHydewpNW9B34T2qAAlIrDv99gBKw -I59UzCEgkj5aOQFEId6YAVHlesvQh6kBhymXtWLyFDgk6tUmtdns1krRAoGBAJj0 -pnhDSMpxk4ZRLBdsgGh8PkhaVOCSz2yvrKqXjgeYI+yytKI0ekdzzcgSAOzmPGc4 -R8B74G4HlG6vr2eXrp4NKAxRXOOf/A6UShTBg5d99KrhJ8cE9/l8XadDsNkiTC0e -OECsDqTfWrCExZUqd7neV+D2NWDQ2XaJrXuZJjVJAoGAIGA5ktXIxWIDeXkxo06b -nHeTEmOAgER/5UIikHnoSAnXo5JNZyFxqoylthWuA1fMPQw/UphAeawDwEXVKp1J -NEhLUfVAO/p1RBUsQi8LQVoO9Nql5u5dFjqoCnlRv5tbeAAzZH5magZk7/1rOS5T -Cj7WW2zW+iL20suUmXfCQGU= ------END RSA PRIVATE KEY----- diff --git a/patch/openssl/test/crl-ca.crt b/patch/openssl/test/crl-ca.crt deleted file mode 100644 index a4a9075af48b5..0000000000000 --- a/patch/openssl/test/crl-ca.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDPDCCAiSgAwIBAgIUM+cEhwkyhyHZzXyqTFq7LGx7VCgwDQYJKoZIhvcNAQEL -BQAwETEPMA0GA1UEAwwGVGVzdENBMB4XDTE5MDYwNjE5MTA1NVoXDTI5MDYwMzE5 -MTA1NVowETEPMA0GA1UEAwwGVGVzdENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAtNcFPtD1MHcolhgTHIAx/b9OyawCbVzvgasv8R9+94ZMhoGc/tNc -dVg271pCSmj+zYAFYsIwjxW+iq2e5A/fiBc6uqtNfEbU7+77QzxFG5wIbXtmmqEb -dVbqBT28NeKTR6X+EHlNgbw90CHy7byA7LMewxbTt2q1eY1RnB0ji8zdGZmIUPeC -WxzkxXEd0fg+KwBFN3YHV9CJX2KJ10qv7DvbKHeIVBU7osm6tzvNglNnnT90GFSY -zc59b+zS00axcY3Kn08Vt+1qWB9Sl8tixCTGqR538y/ambDr3NCWsiQYWys9KE1L -g0nEaIjb84R7b+qNmPtOezd9tanx7j9UzQIDAQABo4GLMIGIMB0GA1UdDgQWBBTF -zPWhjNnkp7rsIfXRhCPqDcLHMDBMBgNVHSMERTBDgBTFzPWhjNnkp7rsIfXRhCPq -DcLHMKEVpBMwETEPMA0GA1UEAwwGVGVzdENBghQz5wSHCTKHIdnNfKpMWrssbHtU -KDAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEA -gdyQq6F8DO5rn7rZSLehTFx6tbtfncC/BOXZEGLZO0ciTrQ9Q8xHwRhz0W09QE1A -/GsBzb++PuvAl9i82WvunyPB5KZh+GPiaaqf466MdQrXj+IyqxeC9Lg9wEUjwRgp -ANVd3moKap5IZ9WDvhyEng2Oy8/btP2iqVEmd58rGAodd671eOPD8QkIxSquiIwy -Cu5s3IBZ0BOuSG9fWoyPTGMKAhzQPFiXGvWOabCkMz3TsPYVY5ENpq2K8cWn2D/r -TD1yPPdINg6HrALGD3S0sD+k588oS7U5oj1L8V4KJQTLSbh6/XcBpasa5Jdv7ZZe -lVgt69Gsn5Cf2BkbwhbF2Q== ------END CERTIFICATE----- diff --git a/patch/openssl/test/csr.pem b/patch/openssl/test/csr.pem deleted file mode 100644 index cf9dde2b0abbd..0000000000000 --- a/patch/openssl/test/csr.pem +++ /dev/null @@ -1,62 +0,0 @@ -Certificate Request: - Data: - Version: 1 (0x0) - Subject: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = foobar.com - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - RSA Public-Key: (2048 bit) - Modulus: - 00:a8:f4:25:8c:44:b3:17:a3:50:85:fe:23:91:87: - d0:78:36:1b:49:17:ff:2d:47:d3:e5:1b:de:6c:36: - fc:96:b9:04:3f:f2:37:de:bf:ef:33:12:ba:65:c5: - f2:e4:b7:4a:49:a9:ca:22:64:6f:20:f4:d5:34:91: - 4e:a8:e5:3f:bf:d5:08:19:72:50:80:a1:96:92:d0: - 9a:b1:9a:8a:36:62:4f:f5:42:c8:f5:ea:99:cc:05: - cd:74:b9:20:e4:e9:5f:5a:25:25:f5:bc:ac:0e:35: - 53:52:c2:21:c0:d4:c8:57:fa:2e:d6:7f:bf:ca:d2: - 78:aa:fa:4e:e1:3a:48:65:78:59:16:81:9b:54:ab: - 8d:60:5e:1d:55:7c:eb:a0:91:ae:d4:92:d6:27:93: - d9:ab:05:b0:0c:8e:66:a5:a1:93:67:da:93:0c:01: - 0c:55:83:84:e1:88:b9:b7:ce:fb:96:aa:f5:c0:49: - 6c:d4:65:ce:c8:01:dd:46:6c:de:00:b4:3b:a1:b3: - 6e:76:7a:a1:3d:13:88:93:1e:4e:c5:d7:8c:00:4b: - 52:56:aa:fe:ba:ea:14:5e:18:7a:e6:64:91:b1:d3: - 14:13:33:db:cf:0f:51:cd:e6:dd:94:dc:a4:df:84: - ef:e6:4e:50:14:59:5c:a0:f6:d0:ad:3b:36:e8:2a: - 0b:35 - Exponent: 65537 (0x10001) - Attributes: - a0:00 - Signature Algorithm: sha256WithRSAEncryption - 95:26:e1:84:56:e7:80:da:2c:a4:c0:b5:85:43:61:85:34:84: - 37:83:c0:bc:cf:70:20:89:46:ce:3d:7e:23:8a:40:a4:a5:fa: - c5:e3:3d:ee:e5:05:16:58:93:f9:6c:f3:86:ee:99:cc:e1:04: - 5c:68:99:da:66:72:a1:95:31:cd:13:6f:a5:6f:fc:a9:ec:75: - 6a:f7:e5:cf:0e:7b:5f:2f:db:8d:45:e6:66:52:12:1d:c9:ac: - 3a:86:35:bd:1f:7b:6e:b5:e1:f3:4f:80:6a:06:73:1c:a0:0d: - a3:63:b6:40:76:25:b0:e9:96:33:7a:9d:18:7e:5e:93:c0:47: - d7:0b:da:b3:03:17:94:d0:0c:78:18:f3:0e:cd:3c:f7:e8:25: - 08:c2:13:0a:af:1e:5c:48:5f:17:41:b2:2d:d2:0f:37:2e:b3: - 10:fd:2b:c0:77:e1:17:8a:57:0c:95:5e:c8:03:eb:63:14:2e: - 46:fd:1e:14:13:9f:38:c1:2f:e9:9b:47:c3:60:a9:d7:6e:a3: - d0:af:0b:6f:df:6e:37:f6:d9:a0:1b:dd:1f:a5:a5:33:89:1f: - a5:a3:44:14:91:83:c3:c8:b2:6e:fb:3f:f1:6d:d2:51:21:f7: - 98:20:0a:40:75:a5:60:c3:59:53:08:62:3d:39:e8:83:55:90: - 1a:bf:51:57 ------BEGIN CERTIFICATE REQUEST----- -MIICnzCCAYcCAQAwWjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx -ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKZm9v -YmFyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKj0JYxEsxej -UIX+I5GH0Hg2G0kX/y1H0+Ub3mw2/Ja5BD/yN96/7zMSumXF8uS3SkmpyiJkbyD0 -1TSRTqjlP7/VCBlyUIChlpLQmrGaijZiT/VCyPXqmcwFzXS5IOTpX1olJfW8rA41 -U1LCIcDUyFf6LtZ/v8rSeKr6TuE6SGV4WRaBm1SrjWBeHVV866CRrtSS1ieT2asF -sAyOZqWhk2fakwwBDFWDhOGIubfO+5aq9cBJbNRlzsgB3UZs3gC0O6GzbnZ6oT0T -iJMeTsXXjABLUlaq/rrqFF4YeuZkkbHTFBMz288PUc3m3ZTcpN+E7+ZOUBRZXKD2 -0K07NugqCzUCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQCVJuGEVueA2iykwLWF -Q2GFNIQ3g8C8z3AgiUbOPX4jikCkpfrF4z3u5QUWWJP5bPOG7pnM4QRcaJnaZnKh -lTHNE2+lb/yp7HVq9+XPDntfL9uNReZmUhIdyaw6hjW9H3tuteHzT4BqBnMcoA2j -Y7ZAdiWw6ZYzep0Yfl6TwEfXC9qzAxeU0Ax4GPMOzTz36CUIwhMKrx5cSF8XQbIt -0g83LrMQ/SvAd+EXilcMlV7IA+tjFC5G/R4UE584wS/pm0fDYKnXbqPQrwtv3243 -9tmgG90fpaUziR+lo0QUkYPDyLJu+z/xbdJRIfeYIApAdaVgw1lTCGI9OeiDVZAa -v1FX ------END CERTIFICATE REQUEST----- diff --git a/patch/openssl/test/dhparams.pem b/patch/openssl/test/dhparams.pem deleted file mode 100644 index 6e4d4c68cb283..0000000000000 --- a/patch/openssl/test/dhparams.pem +++ /dev/null @@ -1,8 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIBCAKCAQEAh3Betv+hf5jNsOmGXU8oxuABD2B8r0yU8FVgjnCZBSVo61qJ0A2d -J6r8rYKbjtolnrZN/V4IPSzYvxurHbu8nbiFVyhOySPchI2Fu+YT/HsSe/0MH9bW -gJTNzmutWoy9VxtWLCmXnOSZHep3MZ1ZNimno6Kh2qQ7VJr0+KF8GbxUKOPv4SqK -NBwouIQXFc0pE9kGhcGKbr7TnHhyJFCRLNP1OVDQZbcoKjk1Vh+5sy7vM2VUTQmM -yOToT2LEZVAUJXNumcYMki9MIwfYCwYZbNt0ZEolyHzUEesuyHfU1eJd6+sKEjUz -5GteQIR7AehxZIS+cytu7BXO7B0owLJ2awIBAg== ------END DH PARAMETERS----- diff --git a/patch/openssl/test/dsa.pem b/patch/openssl/test/dsa.pem deleted file mode 100644 index 9b55018486fba..0000000000000 --- a/patch/openssl/test/dsa.pem +++ /dev/null @@ -1,12 +0,0 @@ ------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----- diff --git a/patch/openssl/test/dsa.pem.pub b/patch/openssl/test/dsa.pem.pub deleted file mode 100644 index ae298d093d0fd..0000000000000 --- a/patch/openssl/test/dsa.pem.pub +++ /dev/null @@ -1,12 +0,0 @@ ------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----- diff --git a/patch/openssl/test/dsaparam.pem b/patch/openssl/test/dsaparam.pem deleted file mode 100644 index 53bda543b69da..0000000000000 --- a/patch/openssl/test/dsaparam.pem +++ /dev/null @@ -1,9 +0,0 @@ ------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----- diff --git a/patch/openssl/test/entry_extensions.crl b/patch/openssl/test/entry_extensions.crl deleted file mode 100644 index 5b0ee298ed307..0000000000000 --- a/patch/openssl/test/entry_extensions.crl +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN X509 CRL----- -MIIBojCCAUkCAQEwCgYIKoZIzj0EAwIwHTEbMBkGA1UEAwwSY3J5cHRvZ3JhcGh5 -LmlvIENBFw0yMzA3MjUxNDA1MzlaFw0yMzA4MDExNDA1MzlaMIGAMH4CFE+Y95/1 -pOqa6c9fUEJ8c04kxu2PFw0yMzA3MjUxNDA1MzlaMFcwLwYDVR0dAQH/BCUwI6Qh -MB8xCzAJBgNVBAYTAkdCMRAwDgYDVQQDDAdUZXN0IENBMAoGA1UdFQQDCgEBMBgG -A1UdGAQRGA8yMDIzMDcyNTE0MDUzOVqgeDB2MB8GA1UdIwQYMBaAFK6qKNgsGefh -XexO9WsIwiQ/73R8MAoGA1UdFAQDAgEUMAwGA1UdHAQFMAOEAf8wOQYIKwYBBQUH -AQEELTArMCkGCCsGAQUFBzAChh1odHRwOi8vd3d3LmV4YW1wbGUuY29tL2NhLmNy -dDAKBggqhkjOPQQDAgNHADBEAiB22SXxFnQUB41uxfyCvg2dAs2nFiR0r8jft/cd -G8zcKAIgeYkNOzRn4lyopK6J94rhm8jIIuJRj3Ns9XcH+91N370= ------END X509 CRL----- diff --git a/patch/openssl/test/identity.p12 b/patch/openssl/test/identity.p12 deleted file mode 100644 index d16abb8c70627..0000000000000 Binary files a/patch/openssl/test/identity.p12 and /dev/null differ diff --git a/patch/openssl/test/intermediate-ca.key b/patch/openssl/test/intermediate-ca.key deleted file mode 100644 index 48f449534e578..0000000000000 --- a/patch/openssl/test/intermediate-ca.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEA1HsHFTpgKeWL/y6oKtARZm0Dy6J/08E0CujmdpVp0xnkXi/A -RARnbMEbOPfmBUMOkVtQT3+l5aCgIAX+Kg6K7sQvio8nQUgOxuO1YpGlYu9EMtc7 -5fNxA1T0CuXXx8ClfEqW1ZV7ziQV0J4gzvuI26A7XyUhdk1oP/Al3F/94TmH6dtP -SQ2K901O2zknU+bpPheQy08SE20k/nUOJAsiwtsxqY8hHOL1sXZ4K+I311hl0QpD -OYf7eBcBdo2Mc5Nzjd9LPGLk1lE3itAXpayFMmfuuA0IdH1gNfy18axFEEVnj6CS -2epGpmAckUEWUOse1WBhDEt6ddowT1iw7X4mWwIDAQABAoIBAGMGXzuudAiymTc5 -OFiTlbhlkAJEXkyC201GU7nqUmJ2y651lKZeYxEVQimfpszG/rARnXEfbWKCJH4o -LNbO5kL2na12n/XVrkVU9EDW3fwoxGDpXFoDxaSm4AGAMrs+diFh5b/upb9ho+UQ -/PtZ0OOCXokuFdU7qB08P3jgJ8LhooqWnZ4AC0rhN85CMNIKs/nrUrnmS3FZLVd/ -NWI9Vfjsndd41Gkho0A7tgOSnwRupk/Bv1b0px31h8ucp9/nLuR8vbGSdS/R9Sta -pB9KNYYQ3LrhQGjddnEU0gj8qsuWgnoPf7eaWsLVunPLHQzL2hNNKL1eBADm7Lhh -avIlnrkCgYEA8Q8UhOeIO0sMU8sB4NPTUf2UT9xjURoowGsGgbDEk21eABH6VC33 -VYt5r5xwbZFQvVaTbe+EI1YDpjH1cvpmorEWI47Nm4Vbf9JujW/hoQwuwpzOpdUT -2G4tfMQrmTw/9HJ0l9+1Ib+A93dB8GvR0NE1uueaWanWvXARInwGiscCgYEA4aZ9 -mbhuwx88sSRMXwxSZw+R5BRrjdC0CeoimGg4/P84bKgc0YsjAha5jWaC/h8xN2Pb -w45b3hQ0/FP8xohP0bp/5eeiDbqb6JuO5bI3CnfBrVpu1CAuIrf7lhkar3a0wluB -k03fVHuVLtydACDJBKrZm1F39lpiZiEqlBIp080CgYEAwRwYjwPAEefkHzhQ7+Ah -uNwQtQ1TjsQLA2J5mumWAJirphjA1jDgo+oQ+Iq1UkEIUjWJ85bd30TntXruK0bH -c+uzVZbvxXfGvhZAtBN9x/svdn4R2a1hsY9J51prpt0qStRp7MSsoTV9xkEGVOi6 -87K1fV5OOyggvC+Lunlq8D8CgYAVSCOObPOdWYPa3SaKzFm1OKW00iw2qtlgGgH7 -R9EgI14J+W0GYk4B82y6plFycDSvGa7vaazGbDd3GOC9RLvqduF7KHaDPvdXX9yB -U2aXiSXuGJpdTU+snJeQ13tJ0zNHJWQ6JV0L1cADNHFmQrFSzF5LpMpgpLOlGDmw -z2m8fQKBgQDclFeonyn0zcXqznun9kAKkMij4s6lSdRgi/5Zh1WbJwOso9oWfwz9 -SSTP2KBO8B+/yFvuo5SWrbNaTz9/KuzMTv4HXz5ukLbyN9Jjtk73fdBBRSjL+zF5 -jU56oXHrwBhEqWQ77Ps60r+FmDjUgUhyJl14ZfkzICUK7NLFxKrvMQ== ------END RSA PRIVATE KEY----- diff --git a/patch/openssl/test/intermediate-ca.pem b/patch/openssl/test/intermediate-ca.pem deleted file mode 100644 index 266ef593cb1da..0000000000000 --- a/patch/openssl/test/intermediate-ca.pem +++ /dev/null @@ -1,22 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDszCCApugAwIBAgIEFSQSITANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB -VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMB4XDTIyMTEwMzA3MDc0OVoXDTI2MDgxMTA3MDc0OVowgYkxCzAJ -BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l -dCBXaWRnaXRzIFB0eSBMdGQxIDAeBgNVBAsMF0ludGVybWVkaWF0ZSBEZXBhcnRt -ZW50MSAwHgYDVQQDDBdpbnRlcm1lZGlhdGUuZm9vYmFyLmNvbTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBANR7BxU6YCnli/8uqCrQEWZtA8uif9PBNAro -5naVadMZ5F4vwEQEZ2zBGzj35gVDDpFbUE9/peWgoCAF/ioOiu7EL4qPJ0FIDsbj -tWKRpWLvRDLXO+XzcQNU9Arl18fApXxKltWVe84kFdCeIM77iNugO18lIXZNaD/w -Jdxf/eE5h+nbT0kNivdNTts5J1Pm6T4XkMtPEhNtJP51DiQLIsLbMamPIRzi9bF2 -eCviN9dYZdEKQzmH+3gXAXaNjHOTc43fSzxi5NZRN4rQF6WshTJn7rgNCHR9YDX8 -tfGsRRBFZ4+gktnqRqZgHJFBFlDrHtVgYQxLenXaME9YsO1+JlsCAwEAAaNmMGQw -HQYDVR0OBBYEFAXJImmmxYXx6L1SRRhgP3Tyq2J6MB8GA1UdIwQYMBaAFGzTpQOr -DV8syY2KnIiniHe4N/2aMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQD -AgGGMA0GCSqGSIb3DQEBCwUAA4IBAQCnUh7iNbnFBjVa4sFx02r65syxUhcvM/ya -DcSe1esGUwjZLyKVl9BTfQ6kfNa/6Z/t5cprp0R3etalN31dxka7xSDwzFNdBczB -zYDIVOVlcGLL1Xjozacm6YHo773dqxZS36rVMk3NqNUY6GJJ+CGso2xZShcBg2KG -fPlNPiRz3847E3dwouDYcP1MXf2ql/Y7dRbE+8kb3bWkSusJVb/4EHjpR7yZjKmh -eXHVVx1dKnCGRldn3+dSNhN6mxNaSeBE2hb158+diQvL5u3f//va7SOpCi0f4d8E -UCnLhieyrDlr42XXfz42BqRpqBO1SDjQwzIIc9Fbevwb916OSExp ------END CERTIFICATE----- diff --git a/patch/openssl/test/key.der b/patch/openssl/test/key.der deleted file mode 100644 index 791f740e45a76..0000000000000 Binary files a/patch/openssl/test/key.der and /dev/null differ diff --git a/patch/openssl/test/key.der.pub b/patch/openssl/test/key.der.pub deleted file mode 100644 index 7ed56b0496b88..0000000000000 Binary files a/patch/openssl/test/key.der.pub and /dev/null differ diff --git a/patch/openssl/test/key.pem b/patch/openssl/test/key.pem deleted file mode 100644 index d381795d3ba3c..0000000000000 --- a/patch/openssl/test/key.pem +++ /dev/null @@ -1,28 +0,0 @@ ------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----- diff --git a/patch/openssl/test/key.pem.pub b/patch/openssl/test/key.pem.pub deleted file mode 100644 index 2a82256967ac3..0000000000000 --- a/patch/openssl/test/key.pem.pub +++ /dev/null @@ -1,9 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr1bXMptaIgOL9PVL8a7W -KG/C8+IbxP018eMBQZT0SnPQmXp0Q8Aai/F+AEDE7b5sO5U7WdxU4GRYw0wqkQNF -si78KNfoj2ZMlx6NRfl4UKuzrpGTPgQxuKDYedngPpWcbmW4P3zEL2Y7b18n9NJr -atRUzH1Zh/ReRO525Xadu58aviPw1Mzgse7cKyzb03Gll9noLnYNIIpO8jL+QyrD -8qNmfacmR20U0a6XDTtmsmk7AitGETICbTT0KRf+oAP0yIHoonllPpNLUEPZQjrp -ClS/S/wKdj7gaq9TaMbHULhFMjbCV8cuPu//rUAuWp3riaznZGOVQyn3Dp2CB3ad -yQIDAQAB ------END PUBLIC KEY----- diff --git a/patch/openssl/test/keystore-empty-chain.p12 b/patch/openssl/test/keystore-empty-chain.p12 deleted file mode 100644 index c39930a5cb4f0..0000000000000 Binary files a/patch/openssl/test/keystore-empty-chain.p12 and /dev/null differ diff --git a/patch/openssl/test/leaf.pem b/patch/openssl/test/leaf.pem deleted file mode 100644 index 0f7aa808de823..0000000000000 --- a/patch/openssl/test/leaf.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDejCCAmICBBUkEiQwDQYJKoZIhvcNAQELBQAwgYkxCzAJBgNVBAYTAkFVMRMw -EQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0 -eSBMdGQxIDAeBgNVBAsMF0ludGVybWVkaWF0ZSBEZXBhcnRtZW50MSAwHgYDVQQD -DBdpbnRlcm1lZGlhdGUuZm9vYmFyLmNvbTAeFw0yMjExMDMwNzE3NTJaFw0yNjA4 -MTEwNzE3NTJaMHkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw -HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxGDAWBgNVBAsMD0xlYWYg -RGVwYXJ0bWVudDEYMBYGA1UEAwwPbGVhZi5mb29iYXIuY29tMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs9STUHGIcSOtioK6+02k9Jx4JuYVJ0SB7Ebd -FAhGiOxBSoOljRVmmALti89QMmRiRqlyJnGJch7AloCCRsLJA0MfUYvauqmKHZFk -iqtZ1HocHQ/LGNKfkILcclb4xp2nGYntKAyEqer3Qc6aPWAnQAV/+BshU1vlMfwU -T6vOJRG69mft6dkHEWSzZd7++7HmFQGnDmIs5jBJVCOgKVttkN8Bk2EsTvJi9zl2 -SXLTcVrTAxEvuawv2ZXvdI/Cpt1WW0litXlFLcYBGwt/N93TX/L3Iyw5HcNd/xf9 -QwOr6RR66krQJzKxwcIY934uq6cyTQhexgnffb65qXL4bbV5fwIDAQABMA0GCSqG -SIb3DQEBCwUAA4IBAQAZf0/r04AeKN2QhQ7Z0o2Iu/Yj3OD2tnbxVoltYk8CRfp3 -7VGl/5PUbmXXBSwMc4Udj88JlreU7iNEPAKtBqFczw0pwNfvxKG4Eh3vsfKrP+5g -gtVwDG0mWeKJ7udrmFt8N0uwxVYDKp/gv5+Bw2eMew9Eoyenj6k2yg0nbFKzA3EH -DqngETzX0dhdiYwVcoJFUK5ni3tVl9qi6FpmaTE6C5nTQLyH4CI+vo2x/QHINGaJ -OzY/rx35iyVqXVqxN/gO/hp6g0nT5zLuMg2rfvcAhdDsD7htYcHiNkofrC8s0oQE -W+r01EhxdEVvY1nYWanBCF6tktc5v5qf2WMS4ye5 ------END CERTIFICATE----- diff --git a/patch/openssl/test/nid_test_cert.pem b/patch/openssl/test/nid_test_cert.pem deleted file mode 100644 index 6f17e734cde30..0000000000000 --- a/patch/openssl/test/nid_test_cert.pem +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIB1DCCAX6gAwIBAgIJAMzXWZGWHleWMA0GCSqGSIb3DQEBCwUAMFYxHzAdBgkq -hkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20xFDASBgNVBAMMC2V4YW1wbGUuY29t -MR0wGwYJKoZIhvcNAQkUHg4ARQB4AGEAbQBwAGwAZTAeFw0xNTA3MDEwNjQ3NDRa -Fw0xNTA3MzEwNjQ3NDRaMFYxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5j -b20xFDASBgNVBAMMC2V4YW1wbGUuY29tMR0wGwYJKoZIhvcNAQkUHg4ARQB4AGEA -bQBwAGwAZTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCmejzp4+o35FD0hAnx2trL -08h07X5jZca9DgZH35hWXPh7fMucLt/IPXIRnz2zKEa/Mo6D2V/fx03Mqo0epid7 -AgMBAAGjLzAtMB0GA1UdDgQWBBRQa57tXz3rZNRz+fTbo3w3jQJMBTAMBgNVHRME -BTADAQH/MA0GCSqGSIb3DQEBCwUAA0EAm0iY9cr+gvC+vcQIebdofpQ4GcDW8U6W -Bxs8ZXinLl69P0jYLum3+XITNFRiyQqcivaxdxthxDNOX7P+aKwkJA== ------END CERTIFICATE----- diff --git a/patch/openssl/test/nid_uid_test_cert.pem b/patch/openssl/test/nid_uid_test_cert.pem deleted file mode 100644 index de6722abe0485..0000000000000 --- a/patch/openssl/test/nid_uid_test_cert.pem +++ /dev/null @@ -1,24 +0,0 @@ ------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----- diff --git a/patch/openssl/test/ocsp_ca_cert.der b/patch/openssl/test/ocsp_ca_cert.der deleted file mode 100644 index 7162e6f3b766c..0000000000000 Binary files a/patch/openssl/test/ocsp_ca_cert.der and /dev/null differ diff --git a/patch/openssl/test/ocsp_resp_no_nextupdate.der b/patch/openssl/test/ocsp_resp_no_nextupdate.der deleted file mode 100644 index 7ed4aab02b257..0000000000000 Binary files a/patch/openssl/test/ocsp_resp_no_nextupdate.der and /dev/null differ diff --git a/patch/openssl/test/ocsp_subject_cert.der b/patch/openssl/test/ocsp_subject_cert.der deleted file mode 100644 index 65e097804f749..0000000000000 Binary files a/patch/openssl/test/ocsp_subject_cert.der and /dev/null differ diff --git a/patch/openssl/test/pkcs1.pem.pub b/patch/openssl/test/pkcs1.pem.pub deleted file mode 100644 index 4d557048feace..0000000000000 --- a/patch/openssl/test/pkcs1.pem.pub +++ /dev/null @@ -1,8 +0,0 @@ ------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----- diff --git a/patch/openssl/test/pkcs8-nocrypt.der b/patch/openssl/test/pkcs8-nocrypt.der deleted file mode 100644 index 2820fd1af7034..0000000000000 Binary files a/patch/openssl/test/pkcs8-nocrypt.der and /dev/null differ diff --git a/patch/openssl/test/pkcs8.der b/patch/openssl/test/pkcs8.der deleted file mode 100644 index c8a777c2a9de7..0000000000000 Binary files a/patch/openssl/test/pkcs8.der and /dev/null differ diff --git a/patch/openssl/test/root-ca.key b/patch/openssl/test/root-ca.key deleted file mode 100644 index 746ae2a68c510..0000000000000 --- a/patch/openssl/test/root-ca.key +++ /dev/null @@ -1,27 +0,0 @@ ------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----- diff --git a/patch/openssl/test/root-ca.pem b/patch/openssl/test/root-ca.pem deleted file mode 100644 index 4ec2f5388494b..0000000000000 --- a/patch/openssl/test/root-ca.pem +++ /dev/null @@ -1,21 +0,0 @@ ------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----- diff --git a/patch/openssl/test/rsa-encrypted.pem b/patch/openssl/test/rsa-encrypted.pem deleted file mode 100644 index a6249997268d6..0000000000000 --- a/patch/openssl/test/rsa-encrypted.pem +++ /dev/null @@ -1,30 +0,0 @@ ------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----- diff --git a/patch/openssl/test/rsa.pem b/patch/openssl/test/rsa.pem deleted file mode 100644 index d8185fed6691a..0000000000000 --- a/patch/openssl/test/rsa.pem +++ /dev/null @@ -1,27 +0,0 @@ ------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----- diff --git a/patch/openssl/test/rsa.pem.pub b/patch/openssl/test/rsa.pem.pub deleted file mode 100644 index 093f2ba12a50e..0000000000000 --- a/patch/openssl/test/rsa.pem.pub +++ /dev/null @@ -1,9 +0,0 @@ ------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----- diff --git a/patch/openssl/test/subca.crt b/patch/openssl/test/subca.crt deleted file mode 100644 index b441d6d8e187f..0000000000000 --- a/patch/openssl/test/subca.crt +++ /dev/null @@ -1,88 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: - 13:ae:da:d8:f4:18:d7:73:b8:bd:35:c9:ce:8e:b3:fc - Signature Algorithm: sha256WithRSAEncryption - Issuer: CN=TestCA - Validity - Not Before: Jun 6 19:11:19 2019 GMT - Not After : May 21 19:11:19 2022 GMT - Subject: CN=SubCA - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - RSA Public-Key: (2048 bit) - Modulus: - 00:b0:09:fc:54:e7:6a:9f:0c:bd:ad:5a:8d:ef:94: - 4e:11:a6:87:19:4f:bf:a6:e1:62:a5:2d:b7:17:df: - 67:53:70:da:fe:7d:99:17:ee:13:47:0b:40:0b:a2: - 34:32:a9:d3:bf:20:fc:13:77:a1:d5:26:60:1f:f0: - d4:be:dc:76:7c:1e:6c:b4:4c:01:7c:56:cd:5c:53: - ec:81:b3:81:2a:b2:35:26:06:5a:79:e0:b3:9e:e4: - 57:e1:09:de:ad:7f:c8:cd:87:ee:49:93:30:52:58: - b2:bc:0f:c1:b6:10:44:f8:85:d5:5b:0a:9b:28:fe: - f4:f4:4a:16:a6:f7:25:e9:96:47:69:73:5b:33:77: - 92:7d:61:8d:2a:3d:d5:04:89:40:bf:6b:d2:fd:5d: - e2:1a:80:a9:8e:c8:92:f6:e5:4c:00:84:f9:6e:2a: - 93:a3:23:ee:28:23:81:f4:54:f0:18:2c:ee:32:8e: - 38:9c:a0:c8:33:04:b0:fc:4c:43:1a:5c:04:84:9f: - 73:c6:08:c7:1d:64:39:fe:72:19:3b:cc:a5:fd:0b: - 43:25:0d:2b:a9:88:77:9e:62:e6:ac:c2:9a:60:42: - 4f:4a:54:47:bc:a0:29:72:7c:38:52:c9:ea:27:c5: - 3d:d0:81:4a:3e:b8:78:79:4b:89:b8:4e:6d:1b:24: - 15:bd - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 CRL Distribution Points: - - Full Name: - URI:http://127.0.0.1:8081/pki/test.crl - - X509v3 Basic Constraints: - CA:TRUE - X509v3 Subject Key Identifier: - FD:82:45:39:A1:91:41:F2:66:CC:0D:75:D5:0D:40:D5:81:A7:A1:43 - X509v3 Authority Key Identifier: - keyid:C5:CC:F5:A1:8C:D9:E4:A7:BA:EC:21:F5:D1:84:23:EA:0D:C2:C7:30 - DirName:/CN=TestCA - serial:33:E7:04:87:09:32:87:21:D9:CD:7C:AA:4C:5A:BB:2C:6C:7B:54:28 - - X509v3 Key Usage: - Certificate Sign, CRL Sign - Signature Algorithm: sha256WithRSAEncryption - 96:a0:ff:8a:4b:bd:45:96:c9:72:3c:63:e3:48:c4:ab:ef:7e: - db:76:3f:d9:02:9e:69:c8:d9:36:55:e1:f5:9b:c9:69:d8:69: - 02:ac:50:8c:60:94:2c:2e:b9:a8:65:ac:f5:00:b0:8b:96:25: - 0b:8a:ef:94:21:57:e2:04:c2:c3:86:bf:06:4e:91:5c:e6:bc: - 1b:03:31:8b:64:ea:c5:79:c3:5c:94:e5:aa:67:7e:74:12:07: - 14:fd:cd:32:02:26:26:c9:0a:ed:d4:da:ee:2a:84:e3:f1:60: - b3:09:77:27:a1:3c:ac:ec:61:18:30:b5:6d:1f:16:0a:24:1a: - cf:1c:1b:60:a5:60:e5:2c:8b:cf:37:83:0c:15:e7:79:30:3f: - ee:50:45:7c:4b:c6:2c:cd:2c:81:0a:98:f1:65:44:7a:ca:2a: - 20:1a:de:19:d9:4b:ca:a1:e2:a4:b5:14:47:bf:b4:68:15:03: - c0:55:e5:f4:47:0e:55:9f:fe:85:d8:2c:7d:d0:1a:96:11:b9: - 68:b7:74:1e:61:94:c1:ae:87:52:2d:c6:26:ba:51:ed:f1:91: - c0:e6:4c:f8:ad:02:23:75:51:fc:f8:69:05:ec:cf:31:50:5a: - 41:78:eb:3d:27:4d:9b:68:ef:ba:0e:ba:3a:7d:60:00:9d:53: - a5:08:3d:c6 ------BEGIN CERTIFICATE----- -MIIDbDCCAlSgAwIBAgIQE67a2PQY13O4vTXJzo6z/DANBgkqhkiG9w0BAQsFADAR -MQ8wDQYDVQQDDAZUZXN0Q0EwHhcNMTkwNjA2MTkxMTE5WhcNMjIwNTIxMTkxMTE5 -WjAQMQ4wDAYDVQQDDAVTdWJDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBALAJ/FTnap8Mva1aje+UThGmhxlPv6bhYqUttxffZ1Nw2v59mRfuE0cLQAui -NDKp078g/BN3odUmYB/w1L7cdnwebLRMAXxWzVxT7IGzgSqyNSYGWnngs57kV+EJ -3q1/yM2H7kmTMFJYsrwPwbYQRPiF1VsKmyj+9PRKFqb3JemWR2lzWzN3kn1hjSo9 -1QSJQL9r0v1d4hqAqY7IkvblTACE+W4qk6Mj7igjgfRU8Bgs7jKOOJygyDMEsPxM -QxpcBISfc8YIxx1kOf5yGTvMpf0LQyUNK6mId55i5qzCmmBCT0pUR7ygKXJ8OFLJ -6ifFPdCBSj64eHlLibhObRskFb0CAwEAAaOBwDCBvTAzBgNVHR8ELDAqMCigJqAk -hiJodHRwOi8vMTI3LjAuMC4xOjgwODEvcGtpL3Rlc3QuY3JsMAwGA1UdEwQFMAMB -Af8wHQYDVR0OBBYEFP2CRTmhkUHyZswNddUNQNWBp6FDMEwGA1UdIwRFMEOAFMXM -9aGM2eSnuuwh9dGEI+oNwscwoRWkEzARMQ8wDQYDVQQDDAZUZXN0Q0GCFDPnBIcJ -Moch2c18qkxauyxse1QoMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEA -lqD/iku9RZbJcjxj40jEq+9+23Y/2QKeacjZNlXh9ZvJadhpAqxQjGCULC65qGWs -9QCwi5YlC4rvlCFX4gTCw4a/Bk6RXOa8GwMxi2TqxXnDXJTlqmd+dBIHFP3NMgIm -JskK7dTa7iqE4/Fgswl3J6E8rOxhGDC1bR8WCiQazxwbYKVg5SyLzzeDDBXneTA/ -7lBFfEvGLM0sgQqY8WVEesoqIBreGdlLyqHipLUUR7+0aBUDwFXl9EcOVZ/+hdgs -fdAalhG5aLd0HmGUwa6HUi3GJrpR7fGRwOZM+K0CI3VR/PhpBezPMVBaQXjrPSdN -m2jvug66On1gAJ1TpQg9xg== ------END CERTIFICATE----- diff --git a/patch/openssl/test/test.crl b/patch/openssl/test/test.crl deleted file mode 100644 index cf1677223a563..0000000000000 Binary files a/patch/openssl/test/test.crl and /dev/null differ