From 115364f5727503b308f538416dc64785f816b78c Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Fri, 17 Nov 2023 02:40:11 +0000 Subject: [PATCH] RSA OAEP Support --- .github/workflows/tests.yml | 4 +- aws-lc-rs/Makefile | 9 +- aws-lc-rs/src/bn.rs | 10 +- aws-lc-rs/src/ed25519.rs | 6 +- aws-lc-rs/src/encoding.rs | 6 + aws-lc-rs/src/error.rs | 33 +- aws-lc-rs/src/pkcs8.rs | 2 +- aws-lc-rs/src/ptr.rs | 19 - aws-lc-rs/src/rsa.rs | 9 +- aws-lc-rs/src/rsa/encoding.rs | 102 +++++ aws-lc-rs/src/rsa/encryption.rs | 348 ++++++++++++++ aws-lc-rs/src/rsa/key.rs | 424 +++++++++--------- aws-lc-rs/src/rsa/signature.rs | 49 +- aws-lc-rs/tests/data/rsa_from_pkcs8_tests.txt | 43 +- aws-lc-rs/tests/data/rsa_pkcs1_sign_tests.txt | 12 +- aws-lc-rs/tests/rsa_test.rs | 237 +++++++++- 16 files changed, 985 insertions(+), 328 deletions(-) create mode 100644 aws-lc-rs/src/rsa/encryption.rs diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ec02625c104..62820be1f3a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -128,10 +128,10 @@ jobs: - name: Run coverage working-directory: ./aws-lc-rs - run: cargo llvm-cov --workspace --features unstable --no-fail-fast --ignore-filename-regex "aws-lc-(fips-)?sys/.*" --lcov --output-path ${{ runner.temp }}/lcov.info + run: cargo llvm-cov --workspace --features unstable,ring-sig-verify,ring-io --no-fail-fast --ignore-filename-regex "aws-lc-(fips-)?sys/.*" --lcov --output-path ${{ runner.temp }}/lcov.info - name: Run FIPS coverage working-directory: ./aws-lc-rs - run: cargo llvm-cov --workspace --features unstable,fips --no-fail-fast --ignore-filename-regex "aws-lc-(fips-)?sys/.*" --lcov --output-path ${{ runner.temp }}/lcov-fips.info + run: cargo llvm-cov --workspace --features unstable,ring-sig-verify,ring-io,fips --no-fail-fast --ignore-filename-regex "aws-lc-(fips-)?sys/.*" --lcov --output-path ${{ runner.temp }}/lcov-fips.info - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v3 env: diff --git a/aws-lc-rs/Makefile b/aws-lc-rs/Makefile index 352b15f3d1a..0490f28f89a 100644 --- a/aws-lc-rs/Makefile +++ b/aws-lc-rs/Makefile @@ -2,6 +2,8 @@ include ../Makefile UNAME_S := $(shell uname -s) +AWS_LC_RS_COVERAGE_FEATURES := unstable,ring-sig-verify,ring-io + asan: # TODO: This build target produces linker error on Mac. # Run specific tests: @@ -21,7 +23,10 @@ asan-fips: RUST_BACKTRACE=1 ASAN_OPTIONS=detect_leaks=1 RUSTFLAGS=-Zsanitizer=address RUSTDOCFLAGS=-Zsanitizer=address cargo +nightly test --lib --bins --tests --examples --target `rustc -vV | sed -n 's|host: ||p'` --no-default-features --features fips,asan coverage: - cargo llvm-cov --no-fail-fast --fail-under-lines 95 --ignore-filename-regex "aws-lc-sys/*" --lcov --output-path lcov.info + cargo llvm-cov --features "${AWS_LC_RS_COVERAGE_FEATURES}" --no-fail-fast --fail-under-lines 95 --ignore-filename-regex "aws-lc(-fips|)-sys/*" --lcov --output-path lcov.info + +coverage-fips: + cargo llvm-cov --features "${AWS_LC_RS_COVERAGE_FEATURES},fips" --no-fail-fast --fail-under-lines 95 --ignore-filename-regex "aws-lc(-fips|)-sys/*" --lcov --output-path lcov.info test: cargo test --all-targets --features unstable @@ -44,4 +49,4 @@ clippy: ci: format clippy msrv test coverage api-diff-pub -.PHONY: asan asan-fips asan-release ci clippy coverage test msrv clippy +.PHONY: asan asan-fips asan-release ci clippy coverage coverage-fips test msrv clippy diff --git a/aws-lc-rs/src/bn.rs b/aws-lc-rs/src/bn.rs index 5c90502d087..55828de1921 100644 --- a/aws-lc-rs/src/bn.rs +++ b/aws-lc-rs/src/bn.rs @@ -2,9 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 OR ISC use crate::ptr::{ConstPointer, DetachableLcPtr, LcPtr}; -use aws_lc::{BN_bin2bn, BN_bn2bin, BN_cmp, BN_new, BN_num_bits, BN_num_bytes, BN_set_u64, BIGNUM}; +use aws_lc::{BN_bin2bn, BN_bn2bin, BN_new, BN_num_bits, BN_num_bytes, BN_set_u64, BIGNUM}; use mirai_annotations::unrecoverable; -use std::cmp::Ordering; use std::ptr::null_mut; impl TryFrom<&[u8]> for LcPtr { @@ -65,13 +64,6 @@ impl ConstPointer { } } - pub(crate) fn compare(&self, other: &ConstPointer) -> Ordering { - unsafe { - let result = BN_cmp(**self, **other); - result.cmp(&0) - } - } - pub(crate) fn num_bits(&self) -> u32 { unsafe { BN_num_bits(**self) } } diff --git a/aws-lc-rs/src/ed25519.rs b/aws-lc-rs/src/ed25519.rs index 6d856a1ce04..35b83338e2e 100644 --- a/aws-lc-rs/src/ed25519.rs +++ b/aws-lc-rs/src/ed25519.rs @@ -149,7 +149,7 @@ impl KeyPair for Ed25519KeyPair { } } -pub(crate) unsafe fn generate_key() -> Result, ()> { +pub(crate) fn generate_key() -> Result, ()> { let pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, null_mut()) })?; if 1 != unsafe { EVP_PKEY_keygen_init(*pkey_ctx) } { @@ -191,7 +191,7 @@ impl Ed25519KeyPair { /// # Errors /// `error::Unspecified` if `rng` cannot provide enough bits or if there's an internal error. pub fn generate_pkcs8(_rng: &dyn SecureRandom) -> Result { - let evp_pkey = unsafe { generate_key()? }; + let evp_pkey = generate_key()?; evp_pkey.marshall_private_key(Version::V2) } @@ -228,7 +228,7 @@ impl Ed25519KeyPair { /// # Errors /// `error::Unspecified` if `rng` cannot provide enough bits or if there's an internal error. pub fn generate_pkcs8v1(_rng: &dyn SecureRandom) -> Result { - let evp_pkey = unsafe { generate_key()? }; + let evp_pkey = generate_key()?; evp_pkey.marshall_private_key(Version::V1) } diff --git a/aws-lc-rs/src/encoding.rs b/aws-lc-rs/src/encoding.rs index c06629ef817..b561118dbc4 100644 --- a/aws-lc-rs/src/encoding.rs +++ b/aws-lc-rs/src/encoding.rs @@ -45,6 +45,12 @@ macro_rules! generated_encodings { f.debug_struct(stringify!($name)).finish() } } + + impl<'a> From]>> for $name<'a> { + fn from(value: Buffer<'a, buffer_type::[<$name Type>]>) -> Self { + Self(value) + } + } )* }} } diff --git a/aws-lc-rs/src/error.rs b/aws-lc-rs/src/error.rs index 8645e182e36..d37b0ef8cf4 100644 --- a/aws-lc-rs/src/error.rs +++ b/aws-lc-rs/src/error.rs @@ -126,23 +126,14 @@ impl KeyRejected { KeyRejected("InconsistentComponents") } - //pub(crate) fn invalid_component() -> Self { - // KeyRejected("InvalidComponent") - //} - #[inline] pub(crate) fn invalid_encoding() -> Self { KeyRejected("InvalidEncoding") } - // XXX: See the comment at the call site. - //pub(crate) fn rng_failed() -> Self { - // KeyRejected("RNG failed") - //} - - //pub(crate) fn public_key_is_missing() -> Self { - // KeyRejected("PublicKeyIsMissing") - //} + pub(crate) fn unsupported_size() -> Self { + KeyRejected("UnsupportedSize") + } pub(crate) fn too_small() -> Self { KeyRejected("TooSmall") @@ -152,21 +143,17 @@ impl KeyRejected { KeyRejected("TooLarge") } - //pub(crate) fn version_not_supported() -> Self { - // KeyRejected("VersionNotSupported") - //} - pub(crate) fn wrong_algorithm() -> Self { KeyRejected("WrongAlgorithm") } - pub(crate) fn private_modulus_len_not_multiple_of_512_bits() -> Self { - KeyRejected("PrivateModulusLenNotMultipleOf512Bits") - } - pub(crate) fn unexpected_error() -> Self { KeyRejected("UnexpectedError") } + + pub(crate) fn unspecified() -> Self { + KeyRejected("Unspecified") + } } impl std::error::Error for KeyRejected { @@ -237,6 +224,12 @@ impl From for KeyRejected { } } +impl From for KeyRejected { + fn from(_: Unspecified) -> Self { + Self::unspecified() + } +} + #[allow(deprecated, unused_imports)] #[cfg(test)] mod tests { diff --git a/aws-lc-rs/src/pkcs8.rs b/aws-lc-rs/src/pkcs8.rs index 6c46f6bd7f0..6ee0160fd1d 100644 --- a/aws-lc-rs/src/pkcs8.rs +++ b/aws-lc-rs/src/pkcs8.rs @@ -29,7 +29,7 @@ impl AsRef<[u8]> for Document { impl Drop for Document { fn drop(&mut self) { - self.bytes.zeroize(); + self.bytes.as_mut().zeroize(); } } diff --git a/aws-lc-rs/src/ptr.rs b/aws-lc-rs/src/ptr.rs index 6f8dc6b850a..2885d366c9d 100644 --- a/aws-lc-rs/src/ptr.rs +++ b/aws-lc-rs/src/ptr.rs @@ -101,21 +101,6 @@ impl DetachablePointer

{ } } -impl DetachablePointer

{ - #[inline] - pub fn as_const(&self) -> ConstPointer { - match &self.pointer { - Some(pointer) => ConstPointer { - ptr: pointer.as_const_ptr(), - }, - None => { - // Safety: pointer is only None when DetachableLcPtr is detached or dropped - verify_unreachable!() - } - } - } -} - impl From> for ManagedPointer

{ #[inline] fn from(mut dptr: DetachablePointer

) -> Self { @@ -236,10 +221,6 @@ mod tests { let debug = format!("{detachable_ptr:?}"); assert!(debug.contains("DetachablePointer { pointer: Some(")); - let const_ptr: ConstPointer = detachable_ptr.as_const(); - let debug = format!("{const_ptr:?}"); - assert!(debug.contains("ConstPointer { ptr:")); - let lc_ptr = ManagedPointer::new(detachable_ptr.detach()).unwrap(); let debug = format!("{lc_ptr:?}"); assert!(debug.contains("ManagedPointer { pointer:")); diff --git a/aws-lc-rs/src/rsa.rs b/aws-lc-rs/src/rsa.rs index 82f77b1f4b7..e4c139722b5 100644 --- a/aws-lc-rs/src/rsa.rs +++ b/aws-lc-rs/src/rsa.rs @@ -11,12 +11,19 @@ // components. mod encoding; +mod encryption; pub(crate) mod key; pub(crate) mod signature; -pub use self::key::{KeyPair, KeySize, PublicKey, PublicKeyComponents}; #[allow(clippy::module_name_repetitions)] pub use self::signature::RsaParameters; +pub use self::{ + encryption::{ + EncryptionAlgorithm, EncryptionAlgorithmId, PrivateDecryptingKey, PublicEncryptingKey, + OAEP_SHA1_MGF1SHA1, OAEP_SHA256_MGF1SHA256, OAEP_SHA384_MGF1SHA384, OAEP_SHA512_MGF1SHA512, + }, + key::{KeyPair, KeySize, PublicKey, PublicKeyComponents}, +}; pub(crate) use self::signature::RsaVerificationAlgorithmId; diff --git a/aws-lc-rs/src/rsa/encoding.rs b/aws-lc-rs/src/rsa/encoding.rs index 63902999312..49e481ade79 100644 --- a/aws-lc-rs/src/rsa/encoding.rs +++ b/aws-lc-rs/src/rsa/encoding.rs @@ -37,3 +37,105 @@ pub(in super::super) mod pkcs8 { LcPtr::try_from(pkcs8) } } + +/// [RFC 8017](https://www.rfc-editor.org/rfc/rfc8017.html) +/// +/// PKCS #1: RSA Cryptography Specifications Version 2.2 +pub(in super::super) mod rfc8017 { + use crate::{ + cbs, + error::Unspecified, + ptr::{DetachableLcPtr, LcPtr}, + }; + use aws_lc::{ + EVP_PKEY_assign_RSA, EVP_PKEY_new, RSA_parse_private_key, RSA_parse_public_key, + RSA_public_key_to_bytes, EVP_PKEY, + }; + use std::ptr::null_mut; + + /// DER encode a RSA public key to `RSAPublicKey` structure. + pub(in super::super) unsafe fn encode_public_key_der( + pubkey: &LcPtr, + ) -> Result, ()> { + let mut pubkey_bytes = null_mut::(); + let mut outlen: usize = 0; + if 1 != RSA_public_key_to_bytes( + &mut pubkey_bytes, + &mut outlen, + *pubkey.get_rsa().map_err(|_| Unspecified)?.as_const(), + ) { + return Err(()); + } + let pubkey_bytes = LcPtr::new(pubkey_bytes)?; + let pubkey_slice = pubkey_bytes.as_slice(outlen); + let pubkey_vec = Vec::from(pubkey_slice); + Ok(pubkey_vec.into_boxed_slice()) + } + + /// Decode a DER encoded `RSAPublicKey` structure. + #[inline] + pub(in super::super) fn decode_public_key_der( + public_key: &[u8], + ) -> Result, Unspecified> { + let mut cbs = unsafe { cbs::build_CBS(public_key) }; + + let rsa = DetachableLcPtr::new(unsafe { RSA_parse_public_key(&mut cbs) })?; + + let pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; + + if 1 != unsafe { EVP_PKEY_assign_RSA(*pkey, *rsa) } { + return Err(Unspecified); + } + + rsa.detach(); + + Ok(pkey) + } + + /// Decodes a DER encoded `RSAPrivateKey` structure. + #[inline] + pub(in super::super) fn decode_private_key_der( + private_key: &[u8], + ) -> Result, Unspecified> { + let mut cbs = unsafe { cbs::build_CBS(private_key) }; + + let rsa = DetachableLcPtr::new(unsafe { RSA_parse_private_key(&mut cbs) })?; + + let pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; + + if 1 != unsafe { EVP_PKEY_assign_RSA(*pkey, *rsa) } { + return Err(Unspecified); + } + + rsa.detach(); + + Ok(pkey) + } +} + +/// [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280.html) +/// +/// Encodings that use the `SubjectPublicKeyInfo` structure. +pub(in super::super) mod rfc5280 { + use crate::{cbb::LcCBB, cbs, encoding::PublicKeyX509Der, error::Unspecified, ptr::LcPtr}; + use aws_lc::{EVP_marshal_public_key, EVP_parse_public_key, EVP_PKEY}; + + pub(in super::super) fn encode_public_key_der( + key: &LcPtr, + ) -> Result, Unspecified> { + let mut der = LcCBB::new(1024); + + if 1 != unsafe { EVP_marshal_public_key(der.as_mut_ptr(), **key) } { + return Err(Unspecified); + }; + + Ok(PublicKeyX509Der::from(der.into_buffer()?)) + } + + pub(in super::super) fn decode_public_key_der( + value: &[u8], + ) -> Result, Unspecified> { + let mut der = unsafe { cbs::build_CBS(value) }; + Ok(LcPtr::new(unsafe { EVP_parse_public_key(&mut der) })?) + } +} diff --git a/aws-lc-rs/src/rsa/encryption.rs b/aws-lc-rs/src/rsa/encryption.rs new file mode 100644 index 00000000000..ca5479dd4d6 --- /dev/null +++ b/aws-lc-rs/src/rsa/encryption.rs @@ -0,0 +1,348 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR ISC + +use crate::{ + encoding::{AsDer, Pkcs8V1Der, PublicKeyX509Der}, + error::{KeyRejected, Unspecified}, + fips::indicator_check, + ptr::LcPtr, +}; +#[cfg(feature = "fips")] +use aws_lc::RSA_check_fips; +use aws_lc::{ + EVP_PKEY_CTX_new, EVP_PKEY_CTX_set_rsa_mgf1_md, EVP_PKEY_CTX_set_rsa_oaep_md, + EVP_PKEY_CTX_set_rsa_padding, EVP_PKEY_decrypt, EVP_PKEY_decrypt_init, EVP_PKEY_encrypt, + EVP_PKEY_encrypt_init, EVP_PKEY_up_ref, EVP_sha1, EVP_sha256, EVP_sha384, EVP_sha512, EVP_MD, + EVP_PKEY, EVP_PKEY_CTX, RSA_PKCS1_OAEP_PADDING, +}; +use std::{fmt::Debug, ptr::null_mut}; + +use super::{ + key::{generate_rsa_key, RsaEvpPkey, UsageContext}, + KeySize, +}; + +/// RSA-OAEP with SHA1 Hash and SHA1 MGF1 +pub const OAEP_SHA1_MGF1SHA1: EncryptionAlgorithm = EncryptionAlgorithm::OAEP(OaepAlgorithm { + id: EncryptionAlgorithmId::OaepSha1Mgf1sha1, + oaep_hash_fn: EVP_sha1, + mgf1_hash_fn: EVP_sha1, +}); + +/// RSA-OAEP with SHA256 Hash and SHA256 MGF1 +pub const OAEP_SHA256_MGF1SHA256: EncryptionAlgorithm = EncryptionAlgorithm::OAEP(OaepAlgorithm { + id: EncryptionAlgorithmId::OaepSha256Mgf1sha256, + oaep_hash_fn: EVP_sha256, + mgf1_hash_fn: EVP_sha256, +}); + +/// RSA-OAEP with SHA384 Hash and SHA384 MGF1 +pub const OAEP_SHA384_MGF1SHA384: EncryptionAlgorithm = EncryptionAlgorithm::OAEP(OaepAlgorithm { + id: EncryptionAlgorithmId::OaepSha384Mgf1sha384, + oaep_hash_fn: EVP_sha384, + mgf1_hash_fn: EVP_sha384, +}); + +/// RSA-OAEP with SHA512 Hash and SHA512 MGF1 +pub const OAEP_SHA512_MGF1SHA512: EncryptionAlgorithm = EncryptionAlgorithm::OAEP(OaepAlgorithm { + id: EncryptionAlgorithmId::OaepSha512Mgf1sha512, + oaep_hash_fn: EVP_sha512, + mgf1_hash_fn: EVP_sha512, +}); + +/// RSA Encryption Algorithm Identifier +#[allow(clippy::module_name_repetitions)] +#[derive(Debug, Clone, Copy, PartialEq)] +#[non_exhaustive] +pub enum EncryptionAlgorithmId { + /// RSA-OAEP with SHA1 Hash and SHA1 MGF1 + OaepSha1Mgf1sha1, + + /// RSA-OAEP with SHA256 Hash and SHA256 MGF1 + OaepSha256Mgf1sha256, + + /// RSA-OAEP with SHA384 Hash and SHA384 MGF1 + OaepSha384Mgf1sha384, + + /// RSA-OAEP with SHA512 Hash and SHA512 MGF1 + OaepSha512Mgf1sha512, +} + +type OaepHashFn = unsafe extern "C" fn() -> *const EVP_MD; +type Mgf1HashFn = unsafe extern "C" fn() -> *const EVP_MD; + +pub struct OaepAlgorithm { + id: EncryptionAlgorithmId, + oaep_hash_fn: OaepHashFn, + mgf1_hash_fn: Mgf1HashFn, +} + +impl OaepAlgorithm { + #[must_use] + fn id(&self) -> EncryptionAlgorithmId { + self.id + } + + #[inline] + fn oaep_hash_fn(&self) -> OaepHashFn { + self.oaep_hash_fn + } + + #[inline] + fn mgf1_hash_fn(&self) -> Mgf1HashFn { + self.mgf1_hash_fn + } +} + +impl Debug for OaepAlgorithm { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Debug::fmt(&self.id, f) + } +} + +/// An RSA Encryption Algorithm. +#[allow(clippy::module_name_repetitions)] +#[non_exhaustive] +#[derive(Debug)] +pub enum EncryptionAlgorithm { + /// RSA-OAEP Encryption + OAEP(OaepAlgorithm), +} + +impl EncryptionAlgorithm { + /// Returns the algorithm's associated identifier. + #[must_use] + pub fn id(&self) -> EncryptionAlgorithmId { + match self { + EncryptionAlgorithm::OAEP(a) => a.id(), + } + } +} + +/// An RSA private key used for decrypting ciphertext encrypted by a [`PublicEncryptingKey`]. +pub struct PrivateDecryptingKey(RsaEvpPkey); + +impl PrivateDecryptingKey { + fn new(key: LcPtr) -> Result { + Ok(Self(RsaEvpPkey::new(key, UsageContext::Decryption)?)) + } + + /// Generate a new RSA private key for use with asymmetrical encryption. + /// + /// # Errors + /// * `Unspecified` for any error that occurs during the generation of the RSA keypair. + pub fn generate(size: KeySize) -> Result { + let key = generate_rsa_key(size.bit_len(), false)?; + Self::new(key) + } + + /// Generate a RSA `KeyPair` of the specified key-strength. + /// + /// Supports the following key sizes: + /// * `EncryptionKeySize::Rsa2048` + /// * `EncryptionKeySize::Rsa3072` + /// * `EncryptionKeySize::Rsa4096` + /// + /// # Errors + /// * `Unspecified`: Any key generation failure. + #[cfg(feature = "fips")] + pub fn generate_fips(size: KeySize) -> Result { + let key = generate_rsa_key(size.bit_len(), true)?; + Self::new(key) + } + + /// Construct a `PrivateDecryptingKey` from the provided PKCS#8 (v1) document. + /// + /// Supports RSA key sizes between 2048 and 8192 (inclusive). + /// + /// # Errors + /// * `Unspecified` for any error that occurs during deserialization of this key from PKCS#8. + pub fn from_pkcs8(pkcs8: &[u8]) -> Result { + let evp_pkey = LcPtr::try_from(pkcs8)?; + Self::new(evp_pkey).map_err(|_| KeyRejected::unexpected_error()) + } + + /// Returns a boolean indicator if this RSA key is an approved FIPS 140-3 key. + #[cfg(feature = "fips")] + #[allow(clippy::missing_panics_doc)] + #[must_use] + pub fn is_valid_fips_key(&self) -> bool { + self.0.is_valid_fips_key() + } + + /// Returns the RSA key size in bytes. + #[must_use] + pub fn key_size(&self) -> usize { + self.0.key_size() + } + + /// Retrieves the `PublicEncryptingKey` corresponding with this `PrivateDecryptingKey`. + /// + /// # Errors + /// * `Unspecified` for any error that occurs computing the public key. + pub fn public_key(&self) -> Result { + if 1 != unsafe { EVP_PKEY_up_ref(*self.0.key) } { + return Err(Unspecified); + }; + Ok(PublicEncryptingKey(RsaEvpPkey::new( + LcPtr::new(*self.0.key)?, + UsageContext::Encryption, + )?)) + } + + /// Decrypts the contents in `ciphertext` and writes the corresponding plaintext to `output`. + /// + /// # Errors + /// * `Unspecified` for any error that occurs while decrypting `ciphertext`. + pub fn decrypt<'output>( + &self, + algorithm: &'static EncryptionAlgorithm, + ciphertext: &[u8], + output: &'output mut [u8], + ) -> Result<&'output mut [u8], Unspecified> { + let pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new(*self.0.key, null_mut()) })?; + + if 1 != unsafe { EVP_PKEY_decrypt_init(*pkey_ctx) } { + return Err(Unspecified); + } + + match algorithm { + EncryptionAlgorithm::OAEP(oaep) => { + configure_oaep_crypto_operation( + &pkey_ctx, + oaep.oaep_hash_fn(), + oaep.mgf1_hash_fn(), + )?; + } + } + + let mut out_len = output.len(); + + if 1 != indicator_check!(unsafe { + EVP_PKEY_decrypt( + *pkey_ctx, + output.as_mut_ptr(), + &mut out_len, + ciphertext.as_ptr(), + ciphertext.len(), + ) + }) { + return Err(Unspecified); + }; + + Ok(&mut output[..out_len]) + } +} + +impl Debug for PrivateDecryptingKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("PrivateDecryptingKey").finish() + } +} + +impl AsDer> for PrivateDecryptingKey { + fn as_der(&self) -> Result, Unspecified> { + AsDer::>::as_der(&self.0) + } +} + +/// An RSA public key used for encrypting plaintext that is decrypted by a [`PrivateDecryptingKey`]. +pub struct PublicEncryptingKey(RsaEvpPkey); + +impl PublicEncryptingKey { + /// Construct a `PublicEncryptingKey` from X.509 `SubjectPublicKeyInfo` DER encoded bytes. + /// + /// # Errors + /// * `Unspecified` for any error that occurs deserializing from bytes. + pub fn from_der(value: &[u8]) -> Result { + Ok(Self(RsaEvpPkey::from_rfc5280_public_key_der( + value, + UsageContext::Encryption, + )?)) + } + + /// Returns the RSA key size in bytes. + #[must_use] + pub fn key_size(&self) -> usize { + self.0.key_size() + } + + /// Encrypts the contents in `plaintext` and writes the corresponding ciphertext to `output`. + /// + /// # Errors + /// * `Unspecified` for any error that occurs while decrypting `ciphertext`. + pub fn encrypt<'output>( + &self, + algorithm: &'static EncryptionAlgorithm, + plaintext: &[u8], + output: &'output mut [u8], + ) -> Result<&'output mut [u8], Unspecified> { + let pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new(*self.0.key, null_mut()) })?; + + if 1 != unsafe { EVP_PKEY_encrypt_init(*pkey_ctx) } { + return Err(Unspecified); + } + + match algorithm { + EncryptionAlgorithm::OAEP(oaep) => { + configure_oaep_crypto_operation( + &pkey_ctx, + oaep.oaep_hash_fn(), + oaep.mgf1_hash_fn(), + )?; + } + } + + let mut out_len = output.len(); + + if 1 != indicator_check!(unsafe { + EVP_PKEY_encrypt( + *pkey_ctx, + output.as_mut_ptr(), + &mut out_len, + plaintext.as_ptr(), + plaintext.len(), + ) + }) { + return Err(Unspecified); + }; + + Ok(&mut output[..out_len]) + } +} + +impl Debug for PublicEncryptingKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("PublicEncryptingKey").finish() + } +} + +fn configure_oaep_crypto_operation( + evp_pkey_ctx: &LcPtr, + oaep_hash_fn: OaepHashFn, + mgf1_hash_fn: Mgf1HashFn, +) -> Result<(), Unspecified> { + if 1 != unsafe { EVP_PKEY_CTX_set_rsa_padding(**evp_pkey_ctx, RSA_PKCS1_OAEP_PADDING) } { + return Err(Unspecified); + }; + + if 1 != unsafe { EVP_PKEY_CTX_set_rsa_oaep_md(**evp_pkey_ctx, oaep_hash_fn()) } { + return Err(Unspecified); + }; + + if 1 != unsafe { EVP_PKEY_CTX_set_rsa_mgf1_md(**evp_pkey_ctx, mgf1_hash_fn()) } { + return Err(Unspecified); + }; + + Ok(()) +} + +impl AsDer> for PublicEncryptingKey { + /// Serialize this `PublicEncryptingKey` to a X.509 `SubjectPublicKeyInfo` structure as DER encoded bytes. + /// + /// # Errors + /// * `Unspecified` for any error that occurs serializing to bytes. + fn as_der(&self) -> Result, Unspecified> { + AsDer::>::as_der(&self.0) + } +} diff --git a/aws-lc-rs/src/rsa/key.rs b/aws-lc-rs/src/rsa/key.rs index 8ae4053f2d2..895226c9b7e 100644 --- a/aws-lc-rs/src/rsa/key.rs +++ b/aws-lc-rs/src/rsa/key.rs @@ -3,50 +3,40 @@ // Modifications copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 OR ISC -use core::{ - cmp::Ordering, - fmt::{self, Debug, Formatter}, - mem::MaybeUninit, - ptr::null_mut, -}; - -use crate::{ - encoding::{AsDer, Pkcs8V1Der}, - fips::indicator_check, -}; - -#[cfg(feature = "fips")] -use aws_lc::RSA_check_fips; -use aws_lc::{ - EVP_DigestSignInit, EVP_PKEY_assign_RSA, EVP_PKEY_new, RSA_generate_key_ex, - RSA_generate_key_fips, RSA_get0_e, RSA_get0_n, RSA_get0_p, RSA_get0_q, RSA_new, - RSA_parse_private_key, RSA_parse_public_key, RSA_public_key_to_bytes, RSA_set0_key, RSA_size, - BIGNUM, EVP_PKEY, EVP_PKEY_CTX, RSA, -}; - -use mirai_annotations::verify_unreachable; - -#[cfg(feature = "ring-io")] -use untrusted::Input; - -use zeroize::Zeroize; - use super::{ encoding, signature::{compute_rsa_signature, RsaEncoding, RsaPadding}, RsaParameters, }; - #[cfg(feature = "ring-io")] use crate::io; +#[cfg(feature = "ring-io")] +use crate::ptr::ConstPointer; use crate::{ - cbs, digest, + digest::{self}, + encoding::{AsDer, Pkcs8V1Der, PublicKeyX509Der}, error::{KeyRejected, Unspecified}, + fips::indicator_check, hex, - ptr::{ConstPointer, DetachableLcPtr, LcPtr}, + ptr::{DetachableLcPtr, LcPtr, Pointer}, rand, sealed::Sealed, }; +#[cfg(feature = "fips")] +use aws_lc::RSA_check_fips; +use aws_lc::{ + EVP_DigestSignInit, EVP_PKEY_assign_RSA, EVP_PKEY_bits, EVP_PKEY_id, EVP_PKEY_new, + EVP_PKEY_size, RSA_generate_key_ex, RSA_generate_key_fips, RSA_get0_d, RSA_get0_e, RSA_get0_n, + RSA_new, RSA_set0_key, RSA_size, BIGNUM, EVP_PKEY, EVP_PKEY_CTX, EVP_PKEY_RSA, +}; +use core::{ + fmt::{self, Debug, Formatter}, + ptr::null_mut, +}; +use mirai_annotations::verify_unreachable; +#[cfg(feature = "ring-io")] +use untrusted::Input; +use zeroize::Zeroize; /// RSA key-size. #[allow(clippy::module_name_repetitions)] @@ -82,7 +72,7 @@ impl KeySize { /// Returns the key size in bits. #[inline] - fn bit_len(self) -> i32 { + pub(super) fn bit_len(self) -> i32 { match self { Self::Rsa2048 => 2048, Self::Rsa3072 => 3072, @@ -101,8 +91,8 @@ pub struct KeyPair { // other thread is concurrently calling a mutating function. Unless otherwise // documented, functions which take a |const| pointer are non-mutating and // functions which take a non-|const| pointer are mutating. - evp_pkey: LcPtr, - serialized_public_key: PublicKey, + pub(super) rsa_evp_pkey: RsaEvpPkey, + pub(super) serialized_public_key: PublicKey, } impl Sealed for KeyPair {} @@ -110,15 +100,19 @@ unsafe impl Send for KeyPair {} unsafe impl Sync for KeyPair {} impl KeyPair { - fn new(evp_pkey: LcPtr) -> Result { - unsafe { - let rsa_key = evp_pkey.get_rsa()?; - let serialized_public_key = PublicKey::new(&rsa_key.as_const())?; - Ok(KeyPair { - evp_pkey, - serialized_public_key, - }) - } + unsafe fn new(evp_pkey: LcPtr) -> Result { + Self::from_rsa_evp_pkey(RsaEvpPkey::new( + evp_pkey, + UsageContext::SignatureGeneration, + )?) + } + + fn from_rsa_evp_pkey(rsa_evp_pkey: RsaEvpPkey) -> Result { + let serialized_public_key = unsafe { PublicKey::new(&rsa_evp_pkey)? }; + Ok(KeyPair { + rsa_evp_pkey, + serialized_public_key, + }) } /// Generate a RSA `KeyPair` of the specified key-strength. @@ -127,7 +121,7 @@ impl KeyPair { /// * `Unspecified`: Any key generation failure. pub fn generate(size: KeySize) -> Result { let private_key = generate_rsa_key(size.bit_len(), false)?; - Self::new(private_key).map_err(|_| Unspecified) + unsafe { Self::new(private_key) }.map_err(|_| Unspecified) } /// Generate a RSA `KeyPair` of the specified key-strength. @@ -142,64 +136,27 @@ impl KeyPair { #[cfg(feature = "fips")] pub fn generate_fips(size: KeySize) -> Result { let private_key = generate_rsa_key(size.bit_len(), true)?; - Self::new(private_key).map_err(|_| Unspecified) + unsafe { Self::new(private_key) }.map_err(|_| Unspecified) } - /// Parses an unencrypted PKCS#8-encoded RSA private key. - /// - /// A RSA keypair may be generated using [`KeyPair::generate`]. - /// - /// Only two-prime (not multi-prime) keys are supported. The public modulus - /// (n) must be at least 2047 bits. The public modulus must be no larger - /// than 4096 bits. It is recommended that the public modulus be exactly - /// 2048 or 3072 bits. The public exponent must be at least 65537. - /// - /// The following will generate a 2048-bit RSA private key of the correct form using - /// OpenSSL's command line tool: - /// - /// ```sh - /// openssl genpkey -algorithm RSA \ - /// -pkeyopt rsa_keygen_bits:2048 \ - /// -pkeyopt rsa_keygen_pubexp:65537 | \ - /// openssl pkcs8 -topk8 -nocrypt -outform der > rsa-2048-private-key.pk8 - /// ``` + /// Parses an unencrypted PKCS#8 DER encoded RSA private key. /// - /// The following will generate a 3072-bit RSA private key of the correct form: + /// Keys can be generated using [`KeyPair::generate`]. /// - /// ```sh - /// openssl genpkey -algorithm RSA \ - /// -pkeyopt rsa_keygen_bits:3072 \ - /// -pkeyopt rsa_keygen_pubexp:65537 | \ - /// openssl pkcs8 -topk8 -nocrypt -outform der > rsa-3072-private-key.pk8 - /// ``` + /// # *ring*-compatibility /// - /// Often, keys generated for use in OpenSSL-based software are stored in - /// the Base64 “PEM” format without the PKCS#8 wrapper. Such keys can be - /// converted to binary PKCS#8 form using the OpenSSL command line tool like - /// this: - /// - /// ```sh - /// openssl pkcs8 -topk8 -nocrypt -outform der \ - /// -in rsa-2048-private-key.pem > rsa-2048-private-key.pk8 - /// ``` - /// - /// Base64 (“PEM”) PKCS#8-encoded keys can be converted to the binary PKCS#8 - /// form like this: - /// - /// ```sh - /// openssl pkcs8 -nocrypt -outform der \ - /// -in rsa-2048-private-key.pem > rsa-2048-private-key.pk8 - /// ``` + /// *aws-lc-rs* does not impose the same limitations that *ring* does for + /// RSA keys. Thus signatures may be generated by keys that are not accepted + /// by *ring*. In particular: + /// * RSA keys ranging between 2048-bit keys and 8192-bit keys are supported. + /// * The public exponenet does not have a required minimum size. /// /// # Errors /// `error::KeyRejected` if bytes do not encode an RSA private key or if the key is otherwise /// not acceptable. pub fn from_pkcs8(pkcs8: &[u8]) -> Result { - unsafe { - let evp_pkey = encoding::pkcs8::decode_der(pkcs8)?; - Self::validate_rsa_pkey(&evp_pkey)?; - Self::new(evp_pkey) - } + let key = RsaEvpPkey::from_pkcs8(pkcs8, UsageContext::SignatureGeneration)?; + Self::from_rsa_evp_pkey(key) } /// Parses a DER-encoded `RSAPrivateKey` structure (RFC 8017). @@ -207,60 +164,16 @@ impl KeyPair { /// # Errors /// `error:KeyRejected` on error. pub fn from_der(input: &[u8]) -> Result { - unsafe { - let pkey = build_private_RSA_PKEY(input)?; - Self::validate_rsa_pkey(&pkey)?; - Self::new(pkey) - } + let key = + RsaEvpPkey::from_rfc8017_private_key_der(input, UsageContext::SignatureGeneration)?; + Self::from_rsa_evp_pkey(key) } - const MIN_RSA_PRIME_BITS: u32 = 1024; - const MAX_RSA_PRIME_BITS: u32 = 4096; - - /// ⚠️ Function assumes that `aws_lc::RSA_check_key` / `aws_lc::RSA_validate_key` has already been invoked beforehand. - /// `aws_lc::RSA_validate_key` is already invoked by `aws_lc::EVP_parse_private_key` / `aws_lc::RSA_parse_private_key`. - /// If the `EVP_PKEY` was constructed through another mechanism, then the key should be validated through the use of - /// one those verifier functions first. - unsafe fn validate_rsa_pkey(rsa: &LcPtr) -> Result<(), KeyRejected> { - let rsa = rsa.get_rsa()?.as_const(); - - let p = ConstPointer::new(RSA_get0_p(*rsa))?; - let q = ConstPointer::new(RSA_get0_q(*rsa))?; - let p_bits = p.num_bits(); - let q_bits = q.num_bits(); - - if p_bits != q_bits { - return Err(KeyRejected::inconsistent_components()); - } - - if p_bits < Self::MIN_RSA_PRIME_BITS { - return Err(KeyRejected::too_small()); - } - if p_bits > Self::MAX_RSA_PRIME_BITS { - return Err(KeyRejected::too_large()); - } - - if p_bits % 512 != 0 { - return Err(KeyRejected::private_modulus_len_not_multiple_of_512_bits()); - } - - let e = ConstPointer::new(RSA_get0_e(*rsa))?; - let min_exponent = DetachableLcPtr::try_from(65537)?; - match e.compare(&min_exponent.as_const()) { - Ordering::Less => Err(KeyRejected::too_small()), - Ordering::Equal | Ordering::Greater => Ok(()), - }?; - - // For the FIPS feature this will perform the necessary public-key validaiton steps and pairwise consistency tests. - // TODO: This also result in another call to `aws_lc::RSA_validate_key`, meaning duplicate effort is performed - // even after having already performing this operation during key parsing. Ideally the FIPS specific checks - // could be pulled out and invoked seperatly from the standard checks. - #[cfg(feature = "fips")] - if 1 != RSA_check_fips(*rsa as *mut RSA) { - return Err(KeyRejected::inconsistent_components()); - } - - Ok(()) + /// Returns a boolean indicator if this RSA key is an approved FIPS 140-3 key. + #[cfg(feature = "fips")] + #[must_use] + pub fn is_valid_fips_key(&self) -> bool { + self.rsa_evp_pkey.is_valid_fips_key() } /// Sign `msg`. `msg` is digested using the digest algorithm from @@ -304,7 +217,7 @@ impl KeyPair { &mut pctx, *digest, null_mut(), - *self.evp_pkey, + *self.rsa_evp_pkey.key, ) } { return Err(Unspecified); @@ -333,7 +246,7 @@ impl KeyPair { #[must_use] pub fn public_modulus_len(&self) -> usize { // This was already validated to be an RSA key so this can't fail - match self.evp_pkey.get_rsa() { + match self.rsa_evp_pkey.key.get_rsa() { Ok(rsa) => { // https://github.com/awslabs/aws-lc/blob/main/include/openssl/rsa.h#L99 unsafe { (RSA_size(*rsa)) as usize } @@ -362,48 +275,8 @@ impl crate::signature::KeyPair for KeyPair { impl AsDer> for KeyPair { fn as_der(&self) -> Result, Unspecified> { - Ok(Pkcs8V1Der::new(encoding::pkcs8::encode_v1_der( - &self.evp_pkey, - )?)) - } -} - -#[inline] -#[allow(non_snake_case)] -unsafe fn build_private_RSA_PKEY(private_key: &[u8]) -> Result, KeyRejected> { - let mut cbs = cbs::build_CBS(private_key); - - let rsa = DetachableLcPtr::new(RSA_parse_private_key(&mut cbs))?; - - let pkey = LcPtr::new(EVP_PKEY_new())?; - - if 1 != EVP_PKEY_assign_RSA(*pkey, *rsa) { - return Err(KeyRejected::unexpected_error()); - } - - rsa.detach(); - - Ok(pkey) -} - -#[inline] -#[allow(non_snake_case)] -pub(super) unsafe fn build_public_RSA_PKEY( - public_key: &[u8], -) -> Result, Unspecified> { - let mut cbs = cbs::build_CBS(public_key); - - let rsa = DetachableLcPtr::new(RSA_parse_public_key(&mut cbs))?; - - let pkey = LcPtr::new(EVP_PKEY_new())?; - - if 1 != EVP_PKEY_assign_RSA(*pkey, *rsa) { - return Err(Unspecified); + AsDer::>::as_der(&self.rsa_evp_pkey) } - - rsa.detach(); - - Ok(pkey) } /// A serialized RSA public key. @@ -428,13 +301,14 @@ impl Drop for PublicKey { } impl PublicKey { - pub(super) unsafe fn new(pubkey: &ConstPointer) -> Result { - let key = serialize_RSA_pubkey(pubkey)?; + pub(super) unsafe fn new(rsa_evp_pkey: &RsaEvpPkey) -> Result { + let key = encoding::rfc8017::encode_public_key_der(&rsa_evp_pkey.key)?; #[cfg(feature = "ring-io")] { - let modulus = ConstPointer::new(RSA_get0_n(**pubkey))?; + let pubkey = rsa_evp_pkey.key.get_rsa().map_err(|_| ())?; + let modulus = ConstPointer::new(RSA_get0_n(*pubkey))?; let modulus = modulus.to_be_bytes().into_boxed_slice(); - let exponent = ConstPointer::new(RSA_get0_e(**pubkey))?; + let exponent = ConstPointer::new(RSA_get0_e(*pubkey))?; let exponent = exponent.to_be_bytes().into_boxed_slice(); Ok(PublicKey { key, @@ -513,9 +387,8 @@ impl PublicKeyComponents where B: AsRef<[u8]> + Debug, { - #[allow(non_snake_case)] #[inline] - unsafe fn build_RSA(&self) -> Result, ()> { + unsafe fn build_rsa(&self) -> Result, ()> { let n_bytes = self.n.as_ref(); if n_bytes.is_empty() || n_bytes[0] == 0u8 { return Err(()); @@ -558,8 +431,8 @@ where signature: &[u8], ) -> Result<(), Unspecified> { unsafe { - let rsa = self.build_RSA()?; - super::signature::verify_RSA( + let rsa = self.build_rsa()?; + super::signature::verify_rsa_signature( params.digest_algorithm(), params.padding(), &rsa, @@ -571,20 +444,6 @@ where } } -#[allow(non_snake_case)] -unsafe fn serialize_RSA_pubkey(pubkey: &ConstPointer) -> Result, ()> { - let mut pubkey_bytes = null_mut::(); - let mut outlen = MaybeUninit::::uninit(); - if 1 != RSA_public_key_to_bytes(&mut pubkey_bytes, outlen.as_mut_ptr(), **pubkey) { - return Err(()); - } - let pubkey_bytes = LcPtr::new(pubkey_bytes)?; - let outlen = outlen.assume_init(); - let pubkey_slice = pubkey_bytes.as_slice(outlen); - let pubkey_vec = Vec::from(pubkey_slice); - Ok(pubkey_vec.into_boxed_slice()) -} - pub(super) fn generate_rsa_key( size: std::os::raw::c_int, fips: bool, @@ -616,3 +475,150 @@ pub(super) fn generate_rsa_key( Ok(evp_pkey) } + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[non_exhaustive] +pub(super) enum UsageContext { + SignatureGeneration, + SignatureVerification, + Encryption, + Decryption, +} + +impl UsageContext { + pub(super) fn validate_key_usage( + &self, + key: &LcPtr, + ) -> Result { + if EVP_PKEY_RSA != unsafe { EVP_PKEY_id(**key) } { + return Err(KeyRejected::wrong_algorithm()); + } + + let key_type = get_rsa_evp_pkey_type(key)?; + + // If we only have a public-key EVP_PKEY then the RSA key can't be an operation + // context that requires the private key. + if let ( + UsageContext::SignatureGeneration | UsageContext::Decryption, + RsaEvpPkeyType::Public, + ) = (self, key_type) + { + return Err(KeyRejected::unspecified()); + } + + let key_size = unsafe { EVP_PKEY_bits(**key) }; + + match self { + UsageContext::SignatureVerification => { + // Our API has 1024 as the absolute lower-bound for RSA verification. + // This can be further restricted by the configured signature algorithm. + if !(1024..=8192).contains(&key_size) { + return Err(KeyRejected::unsupported_size()); + } + } + UsageContext::SignatureGeneration + | UsageContext::Encryption + | UsageContext::Decryption => { + // For generation and encryption/decryption limit to keys that are 2048 or higher. + if !(2048..=8192).contains(&key_size) { + return Err(KeyRejected::unsupported_size()); + } + } + } + + Ok(key_type) + } +} + +#[derive(Clone, Copy, PartialEq, Eq)] +pub(super) enum RsaEvpPkeyType { + Private, + Public, +} + +pub(super) struct RsaEvpPkey { + pub(super) key: LcPtr, + typ: RsaEvpPkeyType, +} + +impl RsaEvpPkey { + pub fn new(key: LcPtr, usage: UsageContext) -> Result { + let typ = usage.validate_key_usage(&key)?; + Ok(Self { key, typ }) + } + + pub fn from_pkcs8(pkcs8: &[u8], usage: UsageContext) -> Result { + let evp_pkey = encoding::pkcs8::decode_der(pkcs8)?; + // Safety: Self::new validates that what we parsed a RSA key of a supported size + Self::new(evp_pkey, usage) + } + + pub fn from_rfc8017_private_key_der( + input: &[u8], + usage: UsageContext, + ) -> Result { + let pkey = encoding::rfc8017::decode_private_key_der(input)?; + Self::new(pkey, usage) + } + + pub fn from_rfc8017_public_key_der( + input: &[u8], + usage: UsageContext, + ) -> Result { + let pkey = encoding::rfc8017::decode_public_key_der(input)?; + Self::new(pkey, usage) + } + + pub fn from_rfc5280_public_key_der( + value: &[u8], + usage: UsageContext, + ) -> Result { + let key = encoding::rfc5280::decode_public_key_der(value)?; + // Safety: Self::new validates that what we just parsed is an RSA key of a supported size + Self::new(key, usage) + } + + #[cfg(feature = "fips")] + #[must_use] + pub fn is_valid_fips_key(&self) -> bool { + // This should always be an RSA key and must-never panic. + let rsa_key = self.key.get_rsa().unwrap(); + + 1 == unsafe { RSA_check_fips(*rsa_key) } + } + + pub fn key_size(&self) -> usize { + // Safety: RSA modulous byte sizes supported fit an usize + unsafe { EVP_PKEY_size(self.key.as_const_ptr()) } + .try_into() + .expect("modulous should fit in usize") + } +} + +impl AsDer> for RsaEvpPkey { + /// Serialize this `PublicEncryptingKey` to a X.509 `SubjectPublicKeyInfo` structure as DER encoded bytes. + /// + /// # Errors + /// * `Unspecified` for any error that occurs serializing to bytes. + fn as_der(&self) -> Result, Unspecified> { + encoding::rfc5280::encode_public_key_der(&self.key) + } +} + +impl AsDer> for RsaEvpPkey { + fn as_der(&self) -> Result, crate::error::Unspecified> { + if self.typ != RsaEvpPkeyType::Private { + verify_unreachable!(); + } + Ok(Pkcs8V1Der::new(encoding::pkcs8::encode_v1_der(&self.key)?)) + } +} + +fn get_rsa_evp_pkey_type(key: &LcPtr) -> Result { + let rsa = key.get_rsa()?; + Ok(if unsafe { RSA_get0_d(*rsa) }.is_null() { + RsaEvpPkeyType::Public + } else { + RsaEvpPkeyType::Private + }) +} diff --git a/aws-lc-rs/src/rsa/signature.rs b/aws-lc-rs/src/rsa/signature.rs index f0420232afb..1ed88ae34f8 100644 --- a/aws-lc-rs/src/rsa/signature.rs +++ b/aws-lc-rs/src/rsa/signature.rs @@ -1,7 +1,7 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 OR ISC -use core::{ +use std::{ fmt::{self, Debug, Formatter}, mem::MaybeUninit, ops::RangeInclusive, @@ -10,16 +10,15 @@ use core::{ use aws_lc::{ EVP_DigestSign, EVP_DigestVerify, EVP_DigestVerifyInit, EVP_PKEY_CTX_set_rsa_padding, - EVP_PKEY_CTX_set_rsa_pss_saltlen, EVP_PKEY_get0_RSA, RSA_bits, RSA_get0_n, - RSA_parse_public_key, EVP_PKEY, EVP_PKEY_CTX, RSA_PKCS1_PSS_PADDING, RSA_PSS_SALTLEN_DIGEST, + EVP_PKEY_CTX_set_rsa_pss_saltlen, EVP_PKEY_get0_RSA, RSA_bits, RSA_get0_n, EVP_PKEY, + EVP_PKEY_CTX, RSA_PKCS1_PSS_PADDING, RSA_PSS_SALTLEN_DIGEST, }; use crate::{ - cbs, digest::{self, digest_ctx::DigestContext}, error::Unspecified, fips::indicator_check, - ptr::{ConstPointer, DetachableLcPtr, LcPtr}, + ptr::{ConstPointer, DetachableLcPtr, LcPtr, Pointer}, sealed::Sealed, signature::VerificationAlgorithm, }; @@ -27,6 +26,11 @@ use crate::{ #[cfg(feature = "ring-sig-verify")] use untrusted::Input; +use super::{ + encoding, + key::{RsaEvpPkey, UsageContext}, +}; + #[allow(non_camel_case_types)] #[allow(clippy::module_name_repetitions)] #[derive(Debug)] @@ -81,17 +85,18 @@ impl VerificationAlgorithm for RsaParameters { msg: &[u8], signature: &[u8], ) -> Result<(), Unspecified> { - unsafe { - let rsa = super::key::build_public_RSA_PKEY(public_key)?; - verify_RSA( - self.digest_algorithm(), - self.padding(), - &rsa, - msg, - signature, - self.bit_size_range(), - ) - } + let rsa = RsaEvpPkey::from_rfc8017_public_key_der( + public_key, + UsageContext::SignatureVerification, + )?; + verify_rsa_signature( + self.digest_algorithm(), + self.padding(), + &rsa.key, + msg, + signature, + self.bit_size_range(), + ) } } @@ -118,13 +123,8 @@ impl RsaParameters { /// # Errors /// `error::Unspecified` on parse error. pub fn public_modulus_len(public_key: &[u8]) -> Result { - unsafe { - let mut cbs = cbs::build_CBS(public_key); - let rsa = LcPtr::new(RSA_parse_public_key(&mut cbs))?; - let mod_len = RSA_bits(*rsa); - - Ok(mod_len) - } + let rsa = encoding::rfc8017::decode_public_key_der(public_key)?; + Ok(unsafe { RSA_bits(rsa.get_rsa()?.as_const_ptr()) }) } #[must_use] @@ -252,8 +252,7 @@ pub(crate) fn configure_rsa_pkcs1_pss_padding(pctx: *mut EVP_PKEY_CTX) -> Result } #[inline] -#[allow(non_snake_case)] -pub(crate) fn verify_RSA( +pub(crate) fn verify_rsa_signature( algorithm: &'static digest::Algorithm, padding: &'static RsaPadding, public_key: &LcPtr, diff --git a/aws-lc-rs/tests/data/rsa_from_pkcs8_tests.txt b/aws-lc-rs/tests/data/rsa_from_pkcs8_tests.txt index 42aec17a93c..5483d25771b 100644 --- a/aws-lc-rs/tests/data/rsa_from_pkcs8_tests.txt +++ b/aws-lc-rs/tests/data/rsa_from_pkcs8_tests.txt @@ -22,63 +22,46 @@ Input = 30821242020100300d06092a864886f70d01010105000482122c30821228020100028204 # RSA 512-bit key (too small) Input = 30820154020100300d06092a864886f70d01010105000482013e3082013a02010002410094f95f85cae61920ffca1deeb2135de7bf20fc05523198433178e74bd3090445f5089488a69bed2984425e497e255abe329129f5b166ad8b204768b8e374fbdd020301000102403e65280e088a513212105c731220ac6f190d3ea117e8efc60cdd7fbab15c106e7a9c8d9be4c0e03470742bc2d0e97233656b771be841a00e0957824c6091fc9d022100e7689ca4d01c8f0a190defcf4bd59038f01879605cba34d98a8e8cd04b00974f022100a4ce28ec8938a3012604174433260b8e0ed783fb2720c4c34abe004f7ea9ef13022100c94768d8c25bd4df07a3e3aeff5b27331f436a6fb2b814381418a1ca9b324c69022027f7efa8dde6a471a4dc9d1fe71fb4f1b0dbc7a0636ee9094bd9248e22f3e78d02201d849cc8c96c732c542a5ba82c7a7a474e05aeb5fb5689ee6a461e3ad545bd85 -Error = TooSmall +Error = UnsupportedSize # RSA 16384-bit key (too big) Input = 30822441020100300d06092a864886f70d01010105000482242b308224270201000282080100bc7a0fd84f1ac3616b14ac0d033dba7bdef142d56fe9fa9c5aeb27bfd2009e6b23939f6ce3d7b7fe43ac398c4a1ac8b5da36660bd29bf622356c5c699be7dfe2799709dd1c127ebb509f612ecddd5db8132094e60e2591c9aaa6c8bc6536821fd80f601f446cc4ab8953cab34155261e3dd2c7d428f2d3467a257d667fc6059327213f430c95d94a5aeacf3f36eda0e757ca7651cd1ec3129a15273c60228c9a92c8aa6b8c9926467a2eeb172958d3a9b286507d46857c6be7e6c1ff092fc0f916d4c2e88ba51114c1d59b3f82dd9511360117622b5c53909079e4f3b192c20e12aa49df42781c57ab8662e41a0aa0c438f1b056a0d31bad1fd1c9b4ead8e63c8323f1aed9c6e38aa4e68821637190845f419446fc2fc6317e95a3558eb6d6b603786134d474fd5ea9a7a6b794768c2b18ef6c3c917fb8d5a8fcf8d538235df310486e4ceecb3d60b5cfd879b423c0851371a9f3efadbbb80106678fe2f014d570ae93a1162e5582f81fed0379092ce19c3362b1a1f0526746b344341a90b7254817e10518ec654e62d971bb906ff95652c7cbc95712544ac5e4b5170b8c84ea15abdb3e17dcb084c4e91b3288930cd7da1c4eddfcea190efd0c408cdd3084c722fd1f821a9568d9812da1bda9b40473886a9d4d67bda388c555da9ba78741e3215d8142020e83b7e63378c694e4e3c9714784fe60ec8684d429291e8668eb745a1a28056cba43bb5f7200020723031da321f9150d073e8b07dfd700550761431fb4e93509de2ae93b52a85164a0067b0a91031e39250817a16174c85ca1e78782fcfdd6a4ba21239bda8fc0931445dccb36f583eba9a0a5909a5a208d3d163ae6192745c1ccca46d6167cd7abc02d6ab632d2cae253f00dbef1f7d17bdf1fd676a00a93e3eaaf3dc3ca2aaf597c450ff2696139fe014525fd8bae52b4218ad277a5d03603c0cec0bee47b07ad63cb8536fb02855449b81e2ede281994b5a0367f0e25c9d77fe074395336c52cfcb9bbb15e276fdba024e4f8b8e932fcd36413a49b3bba68bb21701640c345278785a133de997235843f9f000c58ad865e39d87ecf6779d790d0b60329078d526ee067c70c08d70a12323d32d60cbb3963b614babd9cec66541b615bd797c991fea03f1633b1e8c755dafeb920773c8185200c2961a84f978ddb4ba29c456846a560363701dadc104410344876f0940d59d2c89edbe00fd76e8eb0c35884f6e5a9eb67474cf7f7a9e6ed1753d8d224dc87198fae2e7ccd3bebf69ddfc6839a66d1713453713dc420d0999a1c7f4a8e6fbe11f17560213883a52eb4dcd3835cccae7b6b0f96c11dc53b16938276d24384bfe0ad02ccc566c33c5cafae70315aa1cd3d034e3ae75ed962c11b33b684db9d8b1d26545bc158a3b4844085fa59d6095cb42cef25e405925784e23adcbddd57a25603df29a47678b5d82d556405cd0df9dd0532b46376c5f84b36afb40f208e7fee1ad8a56d7de458f968df9821378cf66567f0beb98e805646c77a0dd77e5d61c04e1b40e29bf6fec1c127459db4dc1d24b7d0dd2cf8c4e4dd5fb59a5c538694f42b2f99720f187f43da1348d55f3982c33dd63abf59480ef826fc8af39e5591bf12618751e16d70ecef8c491303e4518c639da188f94b91deab6db170402a578c9f1ac6f8821c5030636d9f462d7d7a1508b272fa8377285a9bff4fb4c89c041f6ec0e0e6552f80122fa1a1b9ce64fff8cac09d3dc5cb8003ea4696ba9691ce133e2bdad17c010aff5da172ba507aecf35cc5144db830cf3b56204959c68c3ccf44a330a3dcde1326bfe8ac738921796b5ebd90c4abe7ba1f342e1219dee84e74aefaee1aae4e6a0d5071dedeb014df501fba8ba8e80b4a20947d8b382306120c9d56007801128c1f98137abe31b72a833c317b86ef56bf6bfd501386f6f0fef37d38dd52572460744d0d8aa7c70d10f4b5d21b5521ca7323f4443d42502c81f893edb0a77d9ba3e9eb7ae3ac4d98708c00c049d32affee5c810288eb538dda9bc67559d293d8b29823ec6d3702fb4e6eeb2014577887134ac1ffcca64bbd63d40f941b4f7fe5e5288fd92795da83b6057e68f5c688a40e16e9ce15a8ba0d9f99d4c8f43f9dbc0a57076dbf4c93ceda254cbbcfb34e62510a069e685c6f04176b96235b44dda37cefddacb04bbf39593284e4a2afbaf6970e546eb8113d44aee2055365c149fbda26aab9f28e39fa1f683e73afacd303febf33acae418448c8aea8f69e58d8580d6a04b7842def0ab12db0718e6cd3a9ba8d2e039b0258748875287ba7f8405184d11f4094b9ded2d3552e10b4094fca3df392d76c1efdae2df212942b65e1071f91f7caad1255c16e1d1b342a8c4d60dc59de68317f79db2ee38dddc10151c03411835a700f04e2ecdec035892b2120bda38727f2f2317c1a31af517141fbb51eadeee414052ee5e72471a6e07a7b0ddc60f3e883aa585e4ed2938eea881532472510bf31db81e3adff6b88bbc40130d459b3c1a8bdf03efcf75ded3ae602b8ba0472d168e2b53f97644646c87ade4283dbc7db6c6ab46ce94cf44dc8a6f44c089419a311fc6837602b26863d61c492f169925edbebc55ce3b22e9d47dd023acb0b8d9a98ce79656b1161982fcb6f5e7f58e3785c78bd24d4e735cfb6f06a42cf20a863f7f1a6f3e23ecacb6268c1c66233f4c46d7070fc2e6bb3225dd203c6901f3f32c072a073e84ba0d68daf4be109c3264e87bb1ad7934bcfc1f874be2328de93a47eb6e6bc39486175c8d624deaed4d088f08913b34571a83785fb86514f6f659c747d0cabb08efc04cd9ba943abde58fb163cd3c41e151e38a19ecb9a9a65d1d8dec58b82f7758c12521b836d6d86ec43ae0cf1177b71410203010001028207ff4a78234a945d3ebbe58685746b936b750614cd79d47e44e09c0bcde8d650e84720077403389ca9bca6b3a5d6220b265c4d9be402e1743e0c2c8f975a5632bb1ccda139847d5304a64b0e47caf672a721d4067ece9a7b8a787db4e881ee155b6e53302671010b5f4367a5a717dfc551d721164dc4c635f85e2064fc80dce1d43876b0b90e382ac9d68a628966e3f3802cb4f68a16481c05ddfa1d14bd397206cf3f7cbd0c74c10e51b0db8c21744197c681e9a997093968163a9765c2858518c6ec31a49e23c2218a6ba58771d0b66f89508d377005984ed2a9764cf3630fbfe9b5f645ed172fde02f902c6900d2072b1e201366b6a6ccbf5db8fe215f34e73438f26e49757f4ca730a34a5ae8b8f604a86bf08fd9cc0aa01cac23b8705cfb85318bf1e0fb4e2516d3c1b5b6a7a7e8fc9dde9eee6ff96377e9aa0264ae5a37a21e959e83afd8569c7bfa81fed299990516ab6f1963090815b3f72d52bab58b0e2a49655d7f67871d10db8c2c6c2e59d2fba7b2cc3b5f864fd1c989e9a2ae4e97844c3f764cc3434d2ea554cf45bf71566f967de5d2263c203fc79bae053563efad8486897f9bc129c62fdeae77fc233f748a9cd1935c84937fc77013d73f4aae836f7b2d4f52bfa01902f3778df549b073e527b54a70253c19036e8b617bb6659e4ae9a23d42c34c5816f54ef87feb501efb378e5a3196b0d2a2d4c6b83300b0b61280e28168db54ef9da84731578666928fee9c55aba0ed5c686b7aca9ec008ede9ea9530b864987c44257bf045ccfcc4dd3b15ae61faed2da9733e6f6b2cebb95df79d2aef6a8d48f66727fb136f7ca058124cd87c2f143466c1cb03fead63755ccb4114f0e5b778805da9ac2e838a34ada16bc5fca4a8257162a6174835aeaa20de6ecd4fa8bc31bbf6bd15cca16b2c321f9a216adb697d8efe49748e1c4b81741798fde055d454af448a8331a2e5cb44fc622681e8561013d45e7a267210ccda6d62ddd51830469086b41fd114484d7cfe8ab89c1fcd1e20dfa7c84826815279b2e3e52a337396bf7ddfc81c84a445a93d95a06e4c6d818d32e69c8072620bdfa1b5baf5d957feea62115c26f8cbb0df759ba03e7130c34c9de5781c8a402732cc4fa6fa74bc3d2793659ae7c1354d9e4130dd9b4ec2c05dff4700089bf7975137a9391c154a467753dc41c25bb9e169de5022804bc958572ac82395dd1115a199fe16f4a4c63a4cb94f0f8b3eaa8bd901f036291686928c4c2a9b44579e0d8319f9e11689d7bdd156c3708b5d1f80133638ddacfc44779ae383a5c05fd90f6c2c4c3e940015ac1b29da7e69e0a3f4fc31aa4357016884baa8d833996ca08c538d6931d77628e3ad166485c59151bf940334486b9a4aca79bb62fa9830ddb0a6036ab28d06a70e0e563b3214ca6174e3350d84920983a315486b047afe9656f2309fba2c944d0e81cec51743e6faeb3d9b3d23db567ca0a9b63fb2ffafc87904c5d3fdfa18c5046838df38a3344e1775dfe9504e5d77827be703f26a188b4bbc4d7e4074618654dad2e1f620cf3d5a7cbb4d07a6cba17572e5d2aea353dd59e7115099341b92fdccf464e6990d74a78ac69f3168abde796baa014bd88bf5a66f3c849ec2ca1f70c7d89cc96a97648af810d652be9e26b7a04745abb88c6e5d2b78f5ae5dfd8096c6ffae8713581a1c2e465ed965184f508c1f51785cccfd49c20fc626c7d16b376446c3279540d35c25c5dbcf4d69fb0297aa536a1549dbc0d2837f1c7bdabdc8eba9e4481e4674253ae3d80f678c440bbebee1ff550fef4c137fc9c856fbf4af67fdc91fddd8b5f4ebb9e1ca3e2c5fbc8a826f55c0febf1239b435759d393e958e1b2f35c3612eb68d8daa45a31304cb488735e2d3b81916cfad272d75f16be5bf06e140050ccd58bf19c99ee9957e1d28a1dcfd913100b05be9b6ed7d1c9046e10f17203b0168fbfda671733ad8ba08f15abf5b58d9e317f31c097dbeb0e9cb0cc3c6998efddbabdd710f7d017181d356a8431d1877937fd75d9365f924a3ca68f68c7de02830be2eddc8c0b276d72a235120df80e0b5da2d3a9a48219a0addd2281cd2fe165c7a0b0ec4f0090014e1c10380b10973d1a2cdecef6055e0d4e67c8473b114a5224470081c20e98265cce480eed4809c684c18429c1c226880250f60f5c89af85f6c30f048806d18d4438a8fb4fdf9dfc241c87d8950fcf80fbbbe5d67307a002f89ff5d330f4b7b293b494fc02110fd1bb6650a4e239c632a8a1b87ade37eca9a32ed22b440c85ce0f550d01708f88b39b00f85e77ac8676dfaec5942b96b0a7b78356937c434fc64f52d4bfd84870dc8b4acb01e43c323392322a81a27607fda83fc26ca60906966ecf9c731d443c3ad6a128380614d1ca1f5dc7221ec2dbba9492d52ae556959bc80c842ce3ffbd90225656910ccbb2425c3ec9b80c424c541b7823342b5849658205354e72715c30c8b1c6ba1e5db1be6a4d02e6faa869b42b58ed6b4453fff0d195ceefb6f1fe9e351cfc7a8f6302d13f50a77daa56e1d25d1e777f58ea0d78c09aede173e00626cabfb9314d44f9a690ae3291df9cee142e1f8aaf5d708b2da24a22c9896be3aa59b888d9578aec4c7e4077d7e90082710ca407f0fe34e41254e03277d5e15a594aef9ec0a3433ae0f117edacb45987c3d0ea56b0fbeafd1db1d6f92dc5895d091720d28c83f005ab13e001074a2cef352a63c794af245d5ae2a67523f6c51872c71864803ce2310bd371cefba83c492ee45baa475adad03f49ef9dba2b03f934ef55524b71b980c8eb8c54d1432c8b53bd3f52e7638efdab99af4e1e22ebe1274f37a2dd6fbe2247a831c01433c94bdef74816177ed4d5331862f88d99082fc50282040100fa9bd9b37e7c8301376b7ea5de7244987dfc648c63400b20b5a6613a590f4dcf9132643069df349f0e158a1c5ed9227569513f7c4ef9468f07109b1a56b1c2e66f66ba8927427e5b9b1cd0fa074ade9bd3155715c801bec2f6af60495e68010f4a43482469084541774d08bcf915f8d985b366dfa554dab5ef3fa6bb773bdb5caf21a8b806efcd93804a7d3ed46fb8e7bafaaec1d75668e914c297a4155c2a18ff3c7f520ffd6b60e6367979900ad508e09c355ca95795709c9f75fb17d692bcfa765bf4fd5c6194eef2c4eb9def6ee30af159e23f5f626db3b03c14b0a8998cabc0e99eddf15bc5e9c0fa64678da93eb00d5cab44121ec961ae6ab109b5bc3fff85892c94be58d12ec4e5912ab239e55920607bddbc5a305de10eb6cf5750ec1710256b5254eb5c4de9376a71c26462b5937ed33ed69bf43eb02237c951fa08b190b6a4b52aa7b96e5ec7a7f71787068247f1596f72af47cb6f55c3d9d0af3298cde29f4d5da94ff87dd8300b97a6d90c3cfb7d4e0905a9750e76eb2f8982919d4ae27fc8ebb81c3c5d7761873ac7a582b15a54779cf88981f318ff5470f19c4d7b4510c832b8b4a1e8a5b53fdcaeca3b85f7a165b0cbd8f176856223285f73d6c0c384bbd4dcd56890e77a1483a8f507861592e194194b3a5b59f4035bcb569a05f81edd6d9ff23f515b9ae060e3b3876597e51a12be4ebf0c20112bf151b0218b25f94f8814467754eea90756e7c0efe6d61623cb41d567e8f5e4f022762816d667a5b9d9d4625b87b198c0ce1357850f0a227b6d1360f70c7fa2fabf08ccb0580c67d5749f1b85aa8e48c65831917b402147ad4247176193a1ca6217273902f9e5e1baab9245805fef76f9ddb8315d908a7dd61c54d3ea922a89e5df74e3771385a80445f5fd677b55ff6c09ee063361a53791f75c0e9f79cab443af7a43d0c53f8e77dcdb48f3c2e803346a570a0781b05313fe0ecb3788ecae27fe501028e2d8f51b5999a5041a06acbdd58256d7ecd34b1281664a7bba4140efaec34bf214d78e956aafe0af573a19b8936a6652d1ee19d5dc0091bfe8d61024f3aa86f79a62c2e70d143c9d8952af49281c31cc67b834bd1d2afd85678f1b29cea20ea7ea9293015cf1b57f49026266cb0d96e458e47fe0f07d3c93e8129844488050d9ce3833c7971889dc0851f31baeb3403b9f88bdd342b05ad06a24409641a9d1220930425ba7f018ed0afdb84cde47d370d05594c8606da8b391dcc60d7f87a32729945aaa741cd8fa971902d656a64dcfd9c52963fbbef73ff6641f687a5a2fa3ac7f8b6e9fd394c2d8e37e131fbd4ab1768d7ecccdb7bd64d7e777fe0c1cf786726b82875da8ee484046b0917bc2897a9cd09237977693bd0977646c151fdef89a7178c9622e6b21facac1992485490af6856d6e18626cf1b00c9818a737850282040100c08809fbdc0ecd41f1dc1b4212240776db9c85e24da340b95a9ddbfdcd43a471dffde96b3f4d4bf3a52663d12a70c22c454005254444ee14c5767b4eaabef5d860dfe8e7399dd5207512715dea05b010950d26f9ee7d1c8c1fcb76aa29c17f369200ff12260d554b9445dc48f1a882e08cdaa63de6d45c57cac5e2f161a6877da3737e492690ed66b93872deaecb4cb96463f0deaf8f37aae897f527505c2ae3c02361d8f71da434d979bf4cfd767772ee4028701c48363c555d206ee94ebe596452006885fae9322b9d27166a9f57d2ad03857d3dfb7a1069fb9bc21979623e8da99c2fa5bb3b91106d18e44aa5bf6bd4a451e58fca53073cf622f9f3ceb0213c992806b23dfac81abb134bfb3e4e9c504e291ac27fd2c25f15becfbd4b7745343a13c3c59fa066fad991ee4c45f629e3c5c3dc57f194569cab5d08e7f6e8f234732d7c17fbc6cbab19b6766fbbeb40d414f0750487e560b1828f37fd4607c23f6955b4edc8625e9c1d74d3fb3068703aa1db3d778f1385e50b899af1cd3d942ec48db9149ed8440d0530b85a3a49d1cb264f0ec56b0fad57008fddb0af28762cbb2631a417708f750b50078f2d781bd5cfee02a620a39a91ee1929c9893f277e9b36e4d6f1339c5800ed0d0e6f8582dce41c454ad69a5d1dbdc75aa511d00772f465071575ef356e7d6bd072a8ddccd6e9f50af8a405372987dbaa4dabb70cc6e1a986c1c753e916cef5840aa92d27b5e91401985527850aca8b2798ef7c0a8c7b35ec5e5d8b9f7661d283710fee07de393fba5365e0bb8b57e18a9e78489cd3e2b9456f578ffbf9970813dbd732a1b1b2838355f750a2c01e90cae6178d9d34277f3aab1d3acdbc8c34379700e436dd43eb152d35e6100b7f8b3a603248945715589b1a2a60f6fa31db36666f50a54a237305f733642a23f8b922f0d6dce42894e15226b265d443bfc16569b9596cc71d855cc71279ddd597a48febe245e8ce86cecc3b80dbf595b2f7752da59879375d4270c6b291e57db3f4e8fdfb77914cb4bbcd1da6a6c4e461c5bfd697942df47f7f1bc08b17a998e6f417931dc44aec06872e7172b7a009db3ebb59e7b95916b5c1bd9caf7d4627c00da13847c6d2aa41f1e55fbc292f8b85057c2d751ecd005db2c79b548624c658c35a608b488b2a240ca1ed683bdd0525d240113f3b2e70bbd64f7a114f0286775812e56a0a06f27c8dc569b3cd8c1e4b0e6c6050bd862568ee4b3683c6d863b2e8b7ed749fd864b5c10b78239654a58ae83f545d6ce2a932c9738bbca7ce5d0b196d4c4612f9799c52c3a360999130c70987be607cd8670a2fcb91a49ec700e77f9b99883d01536acebdc2bcfb6e01f23e38b107df582815d61131d75674bf3cfa7a81e18a177653a7a2855e1f6176f78904b7d79a2e247516d4024c552561c4f4a880d4798d0282040100bc67aab54ce462c0e95f41298620b5fd46ca16f58c303bad6da315f97db709b280e0377e4639ee1f9dc107c1e874a97947a2336e4b1910b8ba80fb7a43af046da556bfea18bfdeab13e4081fd097b2dfc74385e2f4288bb79b29a1e3c6bbbe0036be7a60152e88927d1446fb7aefcfd408b6252301f2d7326c199849db8bfe90a181568c737a993cc8f8374ca2fd132ff3dc3ec1b018606aca96b8d63cd0bb3d6bb599aaa226cd315e219a158ffaf4c9e5c2ca434d7470fee660e39bd0021af34400f3852d6ce457c9846e130cfb528c124ffc5921779e520702f9483cbfa420a387369b9f13b3010989713546bcb37e5370d83851c6a5aa946b41feb2e41410b1133d5b6cbfe599ede54d0963e5f5acbce2a066befeb9771f3cf188f23c1cb4416a7c174120628954717e9de1c4591ff48e5c8c87f363efada951304b83fbcbc962984d1f7e5ff60249f3240d997c83a2325ff9f2d56f7d342e11765a2c8f6a2482b45b3b18ad0f582b93fa1adcfa2cb70ca9ad3c9b7fcc341a99c09a4e7100f415b64e8748df732ad6c1c76a99003b2814196ae339f987b750817c83891dbb7a6cb031bbb096380679170b3a65b86a85716407cca1abbeff593151e44897ea488b46f2651bd4a20428dc3d656acdfcd8992f62eb8021bbf2b576dd022162af4ac02e175634f24876ddbd56a455731a2732738d639aafc417d10fd2990ca5731ae4b7b9c4d6f3173ee3754152293db649256bd1dd3b13d552774b55c04ac835bf65952a7c9c8d151ce6d8d7942bd952b4cfe7b8a0be121195e9a993679b730c1f8f3254659f7576857901db287269618c1d5c67bc93d54a78ab3ab9222171f5648d670bdb00ddc8ae8871492af44b63a189e6f44fa1a10c688f56b7b13fdb6a9ebce880b625ba97b5d27d86b73c87dbd5891562bfb40d5b58fd812d20adade789eea0a784e95f5a6b181ec13a08b042f3fdc607cf41f2f14861023eb406773e8ede6c69691465742faf395168ae397cfc7c292589560b06f819c0b107008606748ac2bb890d5a083b0a02be0f8b943435136a43b609ddcbb551608d669a619b724e78ed3a331501b515e639ad702032380fc9e6ac3e5f7195779398c2477c82342f1fdeb0e9a535e3e989875cec4edd1ff2cc666f3f9d878b52af9815cdc3da04c50a6fb31f9eed15a493a7872a41cc8a869790ce6096a0cf8adc9249e437bce82fac3e5715dc6580e0007b2c1ef834b7dd885980832e2de442468e06dbd7a70aec3182301f770890ec437b649464169faa8295697b7bc7fa284c81685483b4c902082955138747916ce92a814a1d4f28378e8cc37fed20cfcd9951168718c7e625e33990771367809e02070078e079e6da39db933ba583d05c6b8bedcdbbd62f643ce6a7cfce41f09bd10ed70923c31420dd92b570539ebfdcb0bb2fdd96d902820400519b9837c48015aac51cda04f87183247353f640054e9489bc8a3b0c6a6c28910833b533fb620536a223129e3f520a4bff92725be8831b337cbb8aeabe5f310fe588234d97537a5a46a5699e382aef052858a9d3b8ae19629fbb7b72073ef8702614fc09324de680a1b9b6f4c851f81fbc3495d0993e1c622e1610eae5cc539402ab5ab520febf52126285f633bb02ab768d123521cf1ff6769eaa905e74a2cd64ccda95bfb135c01d0a88f6d65cd7a6c4ac3737c61529c00b22ed3375fb259df872f5af585311736d9f3049452a836c4e5fb6be6e7e60b0026c5f0a38080687a33e68709ddc2e148014ee3f1e1101817061b2410ee0e0aea9bd5ef7f9cafb472b4b73f6daa880db3ed15b0d92d24739e4a42cb2260d4e458b4e4951fed7b517855ab4b3ffd978810e0518e11c3d6f69341dc8b66624850eed5b8994d3d609c9584815d88ac5f2eeb378b3a9a214d253e95172d6f6f3af5b7c026e387a47abd43f52a3bc8c29aae09565baf67b7b7a594fd0f9802564650f1515fddeca6d87937efb5b633f0551800ed0cb64e901d9f66e18afdbfffc3069f5fdcbfd58fdf5b599a23e3f3e619d1981b028dcfb687787bcea64e5848b432daa7b74f90c6efb70ff2e45675c6062d2fb4e712c5e9910cb765bce4be4bbf03455fdf2394eccad13eb3b0273ad3a0f09e3ea8fbf8c4a5db18ccb204de53488ed67d2295f178b188cf6e4021a979aa8cb9d1a5e60f8afdaef012169947f8060bef8e2ff76ea51608f8c1a51b1fe11c2b3f5d6e30749ee49a3d623080b2f7c7874a64cbad229f7ac37a56c6dc1abbf3ecdbc6eb342cfa578d5a6df96f51d84360eb6467e7332727b594e190bc9cf6c1557cd7ad44b57db4de09f8b4162f985e61d98f2180ec765a8f40fb1819c44cbffcbd0233fdae03280c97f126597fabf32ced5ee8072fa08e91a60c53278c2e44d5b5ad835de89a0c1f1e4b873a5eecfbb0e37920e73deb54b92b1afdc8a1f12b0a97929a1d06e67c9a85fba4d064682bc6abd0c815c1d03f11b8a9af51bad5ccd4599d483a09c12260210a7d635ea384af05d5a4fce8a524cb8c130c72dfd7275b9055484539f79244c49df02df1f4217649c46c0c03c7dd81dc5832c48607afe2e24025f5fd258d994657a51e45fc7c510636e8e678992a04e34af911735ed3faaa09af672a79cd8b6079ce6eb4b3f78f106142225e84e392fd6aacae109bbe7fd637dc7005317062e8d3edbfacf81add05cfa21c08c8b2991eca649cc55c127e07b46d4c8bb36da877cd685234ff0c864257625f1f9299eb35643d7a50b644fd3860c67d2bcf46316cb1e3b421b5adede5558caf32671e401e2dcdc02fd3f6387ae9582a03f11aa2ed0d6e8a4e32e767c07ef8df04d8b4f2040cc96bac1b332b3fa5c541cc6dc41831b7af2112d64339723c8fb374d5c42a502820400248cc613c63441c0316f34f45ef6a1d64bb2f7e4ea8e806e81c2356ad4c51f8232688cf0778f175e3b86d934d84b3938be70d80a2912ef2e122d6bda3aa9e460ceb0314fed1a1a6b68ac9c007c88cbc3afa8e368dcff343a41e09b69d8a6d34b5f32d4246d5b2393d6df50a7e474a7788e7f4bd0c8b3306156b70c9285eea63ab8e05d7fd91059530b58cd55b33b20235e3ef122aeb8418c0a66c44a0683205092fa0144706549cee68333757454b3e04b317bc073875ad29d1f626915da3a32833bd22159696a89d8ca7275b4adc4f2abd446758bf4c062af0bd31493ae4f3376a152da561be8519e48714afd6896a50bbda921fe780cc76fa7c3154bcf2da5b55d2e8c2eca54ec9930ce95ad1b8f1638092b376fd69ffa748c985e23d023c59679d7fbddacae6a71549b2e60e2181aec80a85bf53684e681cfdc867b83fcac3b44cadcd4d256373dd26eae851a8192074b124de443054a94359f71f4721deb9db4b26ba9c9699b34b2689d7c1798d987a340e88ab82480b5c91e1ff73acda0bc2d822ce9da6930f57810875592e0c703029d0cd61c27c34b2a3a7d44df9fd69b7e85a3e210bdf5c4207dc0df7baac646c6f5d91cc7873aa04c11f8c935e0898abb4372b3fbb733d8a79207f62a8b9cd8f434122730f2f6cab52d9f22392b430bbd570db248d7d55042bfd64231ca179827dc2c23be2b1902cb5753ac9a1ec26916c654e85f018329a34b9e0dd2ea692d115a1cc85e7268bb8cba2206e842343e3258fa336d735f0f77f776e4a8e163384b675be1bd2a813e6422bae94032a084d405dfa92b3ed5402d2e74f00fcea99fb62ef02cb804b4e19fc51e876cc59dc53730e2806441b73371c3f8f573cac1dce796f87b52ee5d8a6c124ec39339c4426cc2d83af1cc5245c361f042c253e223bd1bbb629f0ae9d43de8ffa4639fa3cfe1b0e2467d7575642dd6455df358d158602651ebeec59084a2f0157787b19bdbc2a630f52bd7b40f047f2cfa89f6f38b178cd46148aac88d692f0a3924b0c7a7281c23d4abd23ebcfe01d391f16af679fb362cd7e8bb5e5bd10c0d0577e3153621e63b12a7a3358a956b43bb530ddcda72bd831551c2dc816b8535f69aaa552aaddb5e1aa9de2a42309a829ef995559af42c496661b3179ba35e0ea81a22f20ba07e00f3d8660c716571a8a66200ba7feec4357a00b5624e4686cf2db4c4a8caf5235145460b4ab2c2a7138bc5cd46232a97fff856bc6579d32d21bb93fa837dd71446f156501a1ed3f8907019140cdcae7fc14dee18747e96bc396bc95113c05d16ef97c1fee90b2112ef2720e8c3e1a1232ea5e7025e41791987b9f76fd63736fd7f18b83130df67357f0923affa52f19c8042824642abace197de3890b5455d4ab7594f6f5b5a3d1b9e0d4ba22a30cfa8da2bf9f91b3cd6f30c270fb83b -Error = TooLarge +Error = UnsupportedSize -# RSA 2048-bit key with invalid e == 3. +# RSA 2048-bit key with e == 3. Input = 308204bc020100300d06092a864886f70d0101010500048204a6308204a20201000282010100bbb126534d64a3a60711730846af3c2f4cf4fee28f48e7c9ca2b0b5a6c8ad51e2509d38b87ea6b039ad3a33ac57e78c444d86438b1938eed73219cba33b06454e429330ce0fcd356624630c58f32a7ab3bef8c7cb3f9843b09c3e61dc92329df330f002451b5910cac3e7b513d3ca1cd58e39a5cc277e64da395058805f69f19bb62571f28525c5a7f781055ea82bddcc8d10c7163060e2040aeb390e6cd8cbba216726875d3b2975fae77d9d092a9e65f545f8a1e282c7096b3e8293d47d15e656717b0ea2d9a170d489c2f3b596cb745fd3f587e10cf3ff043a1f42ed9d030d900c02676761e70e2b5a8fd9387dc658cc95b1ac3ca83ce3b352d6e71514025020103028201007d20c43788edc26eaf60f75ad9ca281f88a354970a309a8686c75ce6f30738bec35be25d0546f2026737c2272e545082d89042d076625f48f76bbdd177caed8ded70ccb340a88ce441842083b4cc6fc77d4a5da877fbad7cb12d4413db6cc694ccb4aac2e123b60872d4523628d31688e5ed11932c4feede6d0e03b003f9bf6556ac08bfb5829df7f6baf74772fd3e22ca571851c5a0efe8330ffb45863a804f870f4535da65761c81c22decb3bd8fe55fb250b09fce0f12f1c1a073ab5349a8b9d8e3fb826a04f441479cf3b4ecb7d61aca60f44a3f1ffbe2bd615cb65c29b11beeff13074c06356ece01581b45fcfc2cab27a8777a631b3361763d59b7f26b02818100f6434d514907d7c9f522c84633148b5e2fccf3bc0fc4e6a5c5f7b88b15a062433dae12c53d5e54e2a47427da06b6ff4e2c4635b90aa8887b365b96e6485584f64138c39ef0d9108dc8f569f5cdac877c5d4bfad3a89dbda8f5e88d05277462b2636618c6f21f845ebbca664f1c7d5534c15ff90f5faffd712ecd2f130b8f808d02818100c31cfcae4f06979c983cd5248af2554a6981743aaacfbf9e2e1f021d87d56a0119d177d270dd2c89f8970b1cbc3f52c02382b0c823ca8d58f5b5e09573f55deb0d68fe18b5b5821ae267c6cbde49d179c081b3166614619d263f02e3f5db2ef4cbb428c2f96490c200b640aa4e218bb68868a68eb0e2f1b43f55ccff5f2dd3f902818100a42cde3630afe5314e17302eccb85ce975334d280a83446e83fa7b0763c04182291eb72e28e98dec6da2c53c0479ff8972d97926071b05a779926499858e58a42b7b2d14a090b5b3db4e46a3de7304fd9387fc8d1b13d3c5f945b358c4f841cc42441084a16a583f27dc4434bda8e37880eaa60a3fcaa8f61f3374b75d0a55b3028181008213531edf59ba68657de36db1f6e386f100f8271c8a7fbec96a01690538f15611364fe1a0937306a5ba07687d7f8c8017ac75dac28708e5f923eb0e4d4e3e9cb39b54107923ac11ec452f32943136512b01220eeeb841136ed4ac97f93cc9f887cd7081fb98608155ced5c6dec107cf059b19b475eca122d4e3ddff94c937fb0281805d84a6c335b77a5d2468b81cab4ab69198906454bb499b00c8094456b855987dd20a95a5be48f21067554b86df117cc9abab45dca04265fb589606b2cbc074808f39862cbf39e3efd1df44e04fcd9f778574528fcb52f5b7e16066267cf08d29ce7a29deb3d9c3671634af765916a865646accbdec557d970de3b242e3450167 -Error = TooSmall # RSA 2040-bit key that is valid, but we reject it because it is too small and # or because the private modulus length isn't a multiple of 512 bits. Input = 308204b9020100300d06092a864886f70d0101010500048204a33082049f0201000282010000e978633c731dc49958124170096c8dfd536977a5ad78051520be93de8b3040faeebe61b436d02e6015d78dfa2280a7a1c33b87b16b82b367e352545a6de6ce46f83dc0fc421c2997c7149f9c616cd538a311cdd8c7f5b0959c3a9343090f0ba87b02dd44e7dd0c8a2eeb0d7ad2e49527d5d420b72b52301e7ea2f6f18c86a05c8ee5a20ebac5a78f76d4a1443db1c399375293e008ef34835f873f0ccfbb3005d1efd17ac405db1e86a5b64ecfcf3f02819818802f122d1a889ebfbb6658d3d63355894a4141d1aeb4dfcbfc5bf6d2229532326f73810364a42b7cd1b71f05720698b74c58e5e1fdc364f8403f6ec825dab667f6b26653e76f6f7eb8d98b2702030100010282010000bbb8bfda0019845563fa31c17ae25cfcbe8fc3d3643a67a3c8535424113878570b95ea8b73b34a4699e95ad02fe3d06581cc20dbe83d0c31d117069a3b59e4ac2db7c1af531cbfd8b90afd174942afe2bd43788700a8ad166eaaae73ad19fadeba21e07622149b9b94040d2f9fd88991a11dd23c5549dd44f7bfe2dcef87e3da55d5b0c92e321a992600b6aa2205b90f03cbde204ccbf5e4ae729c6a4d1d38f415f559b865b91996973a05103410842a84c8e19e8b4fdad94d498392dbd521691154381ac6cb5bc6d180daf72cdbc06a7d42a2f503cf44ff804b1b6004b2f4f058c2f20712fccca5866cd107a812390c9b2784d5e199b270bcbc0b2ca3f2410281800f5fd9faeb3fc7a0d6f4011b731482e8ab1d5fac10ed36241d95a28fc298e3bf41e75aa9d0d967d79b857d7156496f073003c45ac8d97136862c103a8e2e3d1548e308b4e50f436b86a236b0c15cbe50d812819294db7cffe6f655bcf50113ef79245fa94886be820ee043d1e4ed9984ad8d8157610c433513a96f86398a7aa10281800f2f85807ba2ee028bdf1902a9940629b8844797d41b922f91b81dad222089079979db61890295bd20e02fdc7d8ccf34c569e328abc83b0127ab6a3ffead18f1e3172206fcf0a1b032dc899d142e64c7e5ef1316992f537bef6963f4304a5064d67e8bffb7a16ae165746cdddef21e531ab19fe2c03940ecc9462da340c138c70281800a3ebd6b4fc8b8a69d970c05d6b21c6a1f5cfb9c15cb7d00a4164ab5b1df6024db2de864b11faeeb265fd62fe86816ec9b3a676677e12e683f10addfd74f48b51e54ec405f43c491aaadfdf3db668a0c25706f97d64a4d09da46dceb85f8a9e832b9e2655447363c44dd7d5429518bb3b6534d9584be3f2ae767494210a60f0102818008bf7d8ee8aa91a651e171cd00d7cf3d1598ce8d7e996b7b8fdc9aebf42efe01acbe704d1ddaa95c4ca619ac517f5e96adeb33fb680a6f435910fca2651a5eb669f6179a22f8948ca6a0397e8df3b4071c44bfa0531ada631926837856a158f2de46046c89e2a969b34280bcc8047ec7ad270a4e5c221f6ec8fc6eaa0f51c05d028180083e0d97571b3ca817e899b3699cb4193d331b4ea9d53e2be2a5c81985f1b609d58c15ee596e736e5647c2a89d05c784836182f2874d83c8648dad4550ab51232e88017c82ec6ce8612e77f5842a5615bea94d116bf4ad1d0a478034a3da7a467522ce292fd30b1c5c0c51e0888dd4397d0708a216456935cb2de88398690320 -Error = TooSmall +Error = UnsupportedSize # RSA 2046-bit key that is valid, but we reject it because it is too small and # because the private modulus length isn't a multiple of 512 bits. Input = 308204b9020100300d06092a864886f70d0101010500048204a33082049f020100028201002d7374f1cd461fb28614fc8f5db38154717c8ec36f61528768ba78910d78042e4655566aa56d81de67247a85a153d14eaa651ff3e4082c6f67b587d7f94d4d2991c59aba31dcac192061811ca39e6cef73169df49283494eeb51d1f28f4438999f7222cf3fcf17955a155ad901c7e058737dda655a17d0a78ba9fb69783e33c208d63c9f9984a2c612994f515d5fd9d71b18439fba6b092d6f8c8562a0e2eea605a218b32e8f84c4dbb8667bd0a5ce88213966429211fe2fbad80f5ece4b70a4ebca26981e5a27d1468d7cfc9c67e6d6eb2c09b62cdceb8e75a4192fe68c15b579d7138ac710e76a63fa0866274c85f94ff5127930c1316def7e7532582bb6fd0203010001028201001e7efa7787b946695d87d5524897b9ee33db545b136fa4955092d574d629b1fc6e9ab1ca0ac7683d16cda61be57c3cd360874ba2345dbb9ae06630089cb0de564705e4648c323992fe640de26e724d3b78e83301b810b8ee67fc55374023912a9a8e5586e3948b895d91388ca4a23d087c2d748d4e9eee148d24779973e1a08e3ee60a3283d203ad4d1d8b92070f180dae0fdd0131735872b1e5a3bd6c25b02cf44c396b4b046ceca986e871d22c60b63f0ff6681b89554309dbc8a03ca1020e64d07e42a4831e326ba17ce44d0ec727c01b6832f07188e6b3c83a999e5d3922987350dfbd994883d3c841412c53eda5b9a131cd981f87a0991e2055749bf06d0281806d352d2ecf4b613356b19186c1d4a110910235213717edd29e1131516e2fce9b59f4ae2a9e2915bbe1a2f5f10c59ddb898ce7ebd1f2a38d7ec52baa3cca0162266a555ac4c8bf4c44a2e5f29449dad674067c37d3e1b84c978947f5ef96761c33d4845a04c2a7106f66868e71982b4c95585ad727e5feb8cbfd479b2c0b5b3630281806a8b553d7d109b1332b2f397bebdcfea592ca801f8abac7da8d3951cffd89615ed588369a16b33bbf256661f68f8397963c33ab3bcea2d2a7ecc7b4cabd0840145a704ea1a7c52eeef57cea22ab7ab4ffd470a6fd0ff6b285f9fa6f0720e10a5a75ebcf1f84cfa20d34db34e245460023ab3b2e1b7aa57dfb9f61c61d1cc6a1f0281805b3a4fdb49a9c3b21a5acda1cfebeafca6d63c41d9ff305980580665eaf11edbe1e2a757ccb5af853af162189263c3f780170802beb50bb53ca2c36d2ff40f697f6be04cc5c928988d0b7dcd4097a3929c57d2139ebd6848d164e39e182447a3cc5ec2632d1d4b3c30bd79dc8c10072c25383d7366a48466189dcb680ad9fed70281805ca34f774a41e1043d45d9856c64afde2cb12657a876e460d2253df6dc01dee5abdc154f07fa251e5ae482a0f6ed3553f5c92f464e9132ba4b4bd23d64fac57c31aaba1c2ef1404ede2e73cd0ee569ffffd200221f0fa685913748b8b202c6b8b2212e9a19721cdde3bc2096660233045d3417ea287ee52ef30b29bc67e59bb302818058ab3d6815ac06d311d3364f8da1ce2ec7616864f90cfd4051668669ceb4ec8e3eed35c83c48ff18595908e6d40f0017d14eb455bdd5c282b21fadb76be331e6bf66d50020775cead697cc62d07cfd14ad1d383afe3b3f7d0dbf181213ccd3df42e7e4481e653333debf7f5523a46722e1231327ba57374c4dc605b04822a7af -Error = TooSmall +Error = UnsupportedSize -# RSA 2047-bit key that is valid, but we reject it because the lengths of the -# private primes aren't equal, because it is too small, because the private -# modulus length isn't a multiple of 512 bits. +# RSA 2047-bit key that is valid, but we reject because it is too small Input = 308204bc020100300d06092a864886f70d0101010500048204a6308204a2020100028201004edbbf2909ee78cc4ef9914eed0bb1ce5267ac3f141c69b288eda901f73e8e68d4184e8e62b23e10e8fe3da44a2ad6826825581b01741d5cee01964e2561d1ede3cf813eeec832b6aa43e31bfbfc9aa3181cf4d729860fa5bf6477d468374640cac16dbe2c82f8d61c1e3cec8e42a18cc1e3cbbaefe21b2c8490bf3f9dad6f90b9297d44a32899fd88fb9914f8843cc1600ce310d69ea52c9bf26bb9ff030b7a5b01e1809227f59e58a3531559f520028e50bf2e21af4fe53ac19685661d03c0ac75774cb518ffd85f778b16b254b83065bcb09dd4ff2e7e908aa1f90e1f99aa94336844ba04ac228b6edba3f1d2e602868ef042a8ad1f6bbc259ed86e5a06ad0203010001028201000c43318ba126bb141227cec7b626be6475fdf713ebfdab15ff22edc807796bcdb3458059b5d13fc383679d9041943dbd1392d30b88035559910d202150c0d0532cbca4bd73862014b58f4eee9815a4ba3dd2aae41669e95efdcf12af2df182742ad33f4c76417b8e57daffe04d12e16a30f04a4aec687d8f43a1fa8b5aea905182928441401bb9dc7946806b7f21aeda027974e32b08c8d31a60283f36b4fdfaac2763625e792b9dddceebb995a379989e39f79a5f07a26d4cb87504df0e4dc283cf44f0bdd7d313d33d0b1813b53e702e34c0788792ad72479563fbe0f7bfffb7033842ef62456d1d087399fb7e425bf92f78b438027f9a8c81305bbfde8fa102818100ced2d7908326a8085b5b05a46c7933c278bd6dc32e941b1fa5cf78db252ffda3bebe5e8a824f667af2c89d40cd299d23bc898926cf40365ce4c4d90c173dc372cf392d1ba6b9f92ec77d69e59aa37462e80afc75ed491a9ec07ae9464a478f4b3593f1e518271925d13cabcec9eb491257323b6500b2f15c3283dc43ca3e45b9028180619bc84ccbe7df0317658039047d6ed73b063946863498120e4bad94654fcf12447e00c4ee2bdb0017e2f62013ca193cd2de66ba69c54024db2e4233658d1cdd35fd98976d291ebc86bf77334871548c16403801380a5afd9ac3be64d177e80583ad4589371308e44c883b93f7711980e389c661e5673c875bb7feb1e010029502818100b1aec3911c8b664a9fa9882465288f462092a52ccce4629502cf46460721bea72164cd35f393a13839420e8f3072f2d453d258e8e59e85d5b29846dbb34fd58cd9e8860f3e62816825ec61c0e6e44c45f8920fa8846d8c981c46bc082e226241bbcad942f74807bbcc91720cdabdef6df949676b7379480fec3a0a4e96fe7ec90281802f38671147fff7b28e2a0b7b0a020892553ab090beb248f34b392f534023f900546444c90093f4d1b9bc91e778cb67a4363b63a541302cd4e7b81c4cb30f2e6c92070a400f8e3a11687ace16e02ffb7ffdefb968558d24f1d56267046d15be0894e8496095653f02fb4758d33f7cd6a2b4f15d28d50b398c1e420814535a4b7502818100cc6fb56fd8b7b3db0a4171c662a0d76efeada4ce0dbf5891b3b51d60efa31bb8f7e176417579bc35a751de444a9e3479307af73ac1ccf0458d81e021d1e4e33a5203c5d01e5e397ca26e62174ded0d310ca0c78685c17738783c9f06acd286f009a623cb4e651776ff9adad81a08299144c9ef4d07fd3ac1408d9c92c98d9379 -Error = InconsistentComponents +Error = UnsupportedSize -# RSA 2049-bit key that is valid, but we reject it because the lengths of the -# private primes aren't equal and because the private modulus length isn't a -# multiple of 512 bits. +# RSA 2049-bit key that is valid Input = 308204be020100300d06092a864886f70d0101010500048204a8308204a402010002820101019129387ed5eafe167c7c575ad391104cdb7ac95d25c2b0e3699a98f477de9729755574b112f552b28204480a061cf6a6360e0959000cb1b175301ee7d7accc82735c2388fb7bbf2673a309e25e2e4b26f046c9dfd858e78de52bd36991e0fc1a28f04b9ebdd6b0ab8da95b6467a7869b4e5a19dc1bc189b666729f7edb24a64965f53382ca45e20bb0a315439f7bead07a0bea88cf25a179e2aba7ee8584c1fa58e731246fcb4778e6f9ef455d0e50fc60c044f7745a4380b9f4c82dd4a64dae636461fd351f2e871477d801833bf44e7e4a7e08691776d263433c19d477290f1b844f0555c2995b22525b57681962332271a3cb522464c27989ab7c943f48e1020301000102820101011c7c6b00279bfa8cdfc31dffdf416499dc9bfae8ffba4dcf3838d677a7fa46a0b400e23c2101b09fbeec625a1973b8c6ae56cdf23bc2c4d0e0163c14963288e58a01b18197366e9c4a2d38f93b69010aa022d34ed71255439f5db11390cc487c14c4341c62ec3965af9486a7718ab03ebb15d278f18612af337fddf40c5cb53e46b99d7da4b7d8d9d586be8add8b0da6756a301155f2472b484c0ed8a23c052dcfe7ce40e99b6cae94edd41cc6a24fb5fda50b5ba3958cd3ccaa6aa2674cb9f492e208c8eb966f1d4d9b1c2a39efc324a41b562ebce4cbea0af06a6bdf19f4c45aed56efd9fd892ceeaa9abd3458c151a83a2b80075e1bab92b388a747baa64102818101aa9f633cbbe8135713302e9b0d22bfb7589c710a6516d25521550d98ee4b827183fe8351285387686d15abb3226813f5ec6367fd9138e2f5e5f248bacb3247219490092620f3660c4d7e091c5e61cbcd4992fc10441261aef9e80d4baa74f1fe9e7eb358c5098693954701a62c0309aecb7a32f0a763988d6b5fb26b5be8a07d02818100f0b8b228a6ef97211d25f0962132ec78ef48f99877d49d3b02e969a34b72eef8e289d0c99b8576d0e704ab27cb908b8c791ae9cba56340ceb9ab13436f6d19b07f1f485d8577b72f6bbc42b6edef6f9fe6dff28bbf790f26dae0c85f76689a440663372cf21f660cd860967b69d6ba491b58b7ad817eecb7f088df4053027b35028180265fd5e655a4a770b2aa27d70c946e984861320dd44ffc356a1d236ef92853a07056096bd86bc30752a09b642e991c0a87ebdd23c2d7521afa4713e1b17b614894fb6bc74139839961b30f90bcb0a14b62edd4bc85d2fd7466c847c1e1a0495034e382b05e70dfe91089658d93f1e602120d78dd8ac0fbace4d6a3cee2628765028181008155fb03348e4e59105c2e23bbbaacab5d858bf58b8cc4ddcbf6b5377376514790101409fe717b214abe8b675a4c536e2a3377a25f3e30b7e1b2352b6a56e812987aaa5af5371949754d355b2c0415a9885692eedaf5a45a70078e211c719f51254d717bc8ab6e1d40b4c4a5927c38a2c6faa7d5a55a18bdcb92fec084d934710281803e411557b7c0e6e6e296a1d0473b7bcf5f7a71d03c70bd6cadc3a9fb3a11cd0294dd02893ad1c28f62c20294d3893d6ac77baabf7772dd47be587893c79c8d66701c3037ceaec38088b500e2197994e048b1b357f8fffbbdbbdc94c0c82a7cac7ef0136cd6f7795355aeb3e4179eb2b363315f6ccb0a26434682adbbe7b6ce6b -Error = InconsistentComponents -# RSA 2050-bit key that is valid, but we reject it because the private modulus -# length isn't a multiple of 512 bits. +# RSA 2050-bit key that is valid Input = 308204c0020100300d06092a864886f70d0101010500048204aa308204a60201000282010102c539e76a413401bebc36a0e09b5acfd299393605da7d25289d085a872fd761b2cf11787287b9c45d285b146e11d8a043c07049947e49f0e89791c99aafa2224d65dd8118067adeb1417e8fd3be306aa6001bdda425c89f691aa1b77ad2c6cdaa890fa764c541e74bf5e1571e7efbee69d1331d5d7544e15d2a7f21de27f268135fb7a4334d45e348d15de362ba649e5bc50cbff86a6775d5d9bdd75441eaaf3a4f4acd1a28cf3d81dd3749a460f87721a73e45adda47134634276c6acbc341fd9c96c4b7b3f6f74b22f93512a39fd4e77f330726d07728f7ae8246a7f2c50cd29625c1365825c8ad257213444ec6dfeef03350bca7091415a3505d5798dd37b7020301000102820101017d721734debcc9f37be725bfa7cebfd7d4f1204d25a609463eaf2f816609c1521a6c9b0b7e543b789f2bdd6115d81cda53b610dcfccf67f2b112880bda4aa98857313b2d60ced4d72112a0e8917218ea0f44ed804b920baacbd80e86d0b67c072c906ec794104e065cc845c2f1292ea15b12d2c8613a1abbb10f8f779ca493b38d5e704ce2644b3798e852d0371214a862b6636fe2d22d5f5c95b794b317438c14ebb28d9c90339f505c90c3fa6ad5430c163c067931df4523490906888f1ba4f55c07fdeb6fe77932b817eaee669f72988a09df346fbcd3abc3b0a6d60546ff52aa28405aa51d1dd83195be0ea21b7995a61a9bcd807d3b0683526b1f79eb8102818101b41a1d8a1fb22acb2f2a827655d9345de5c5c606761d99aa75116d1f50a432079ffce48dcfd9a1c2888b865c92f02a309520291b854759bcca9c4986b85f2c0817e9327bdb69d233f1dae5b52b5cd3f3797c672fcc7fcdf8feb57d2801dc3ca43e4cbac95b919270065a4c617e1e4f11d9a07c7eb87cf9ce7968a9819e79974502818101a05437ace086421b86c6dfc1e7f4ba18e4faeef9ed4d1cc4b6366fb5810ceb5610dc349852b340fea235b0af07adc76ff4ffb91fb73f75bcfd2328d20d6c6c099d4e6b1dd70e75c97e272e3984383657341a8b36978df2bbec2c557357a9bc46cad2703659631dee2df8a61e65841ec80c004adfa169fa0169d476b9253b74cb028181018c3759f53f3ce9a276f4e15950402a52d14af1d2b707c7b055f282393c5421dc49a043ab1057c39ef1de0a321b923652b37a67bec8457e2387d59cfbd891277926f84954bc9195587a798dd01f58947d16384fabded99332918024f8ef4fc08cdcc96bbf3c01b391324462370595d5f2facdd3ae7241a1d8d4f7a161d1b0d91d028181019e24c8b17f33ef0504e0466bd4bb1c787127b19c0ad41f9f0b0741be931e6fe850a34cea8db1e520a7e9b2d59a54e344dab99bc511fbddba5f319f84bc77b34d291f7decd4267d432febf7ce9d5971acf396c80f49599a321830cddc0c433b984c6063e19cafbd715667b7901b39ff88ce6f680be7bccd46a4a906650cc5855b028181009a8f419948a190615b84cd10ea337bfe5fa33b94d2ae506e153a20e6c006c831d025c2fee5a10f67e708631f98532417c2ce89146b279349f9defa5ace677dbf11a9dbffec36a42c0082a912422aa8f641fdc559393276ace5ce985937c3da09220210f381f60eac5cccd0858a8273045c42b96623aeb042d2419be434519dba -Error = PrivateModulusLenNotMultipleOf512Bits -# RSA 2056-bit key that is valid, but we reject it because the private modulus -# length isn't a multiple of 512 bits. +# RSA 2056-bit key that is valid Input = 308204c1020100300d06092a864886f70d0101010500048204ab308204a70201000282010200ba546c668d1f047853f6d70ea45f0e51926bfff13167985f6bf6056b1d6254255458e4d2145dfb8fbcce9ccc1433da1d34804953487cd1b45b6c16c51f9c0d50cd0118684a96c8a2f6bf98b14ff417b1d591a4f125cfe04c6e6ee7472d45fbf791729824f2adac8edb9b7bd1c2540da03337369106a2b40de64d1f8ac5f106a3aeaf5eb05c25bda6f5d0e2aabcb5901b552559cc7f95fe46af048307f6b8ed954d205cb583d526b63914d1b9425ecc90d598d41c97297016130b1e5cd2c384a04132df6919dba22216b6f962cfbe03859ae0923145e1f60a92dc958f0b1bc12af3215659950a0d4cd28450b943244f37c6f5cc38e52aad4acd64ac4c933e737f4f0203010001028201012e4367e6ce833508eb500e75843a55c3cb2725952d3f1b8615b83000387b818903384f181a167baf64a1a82cc3975c408418961c2793563e01b504b24cf6e2177dcf17d04d34c2fc3367bef1c77843a9d3ed2596fa5c72c48766e1e5ba47f617b1f551f15a8fe49853ce771fcdb030f1e5c57fb6e27ee355d028b5fc2ec9796c83da05f851bcd5798b1b5b71c27a888f8203f5c642c59642f96ed30a62e028cd806a974e4ef3be34845feb67bd879e9eb6a8adbf0b8fd1d87df6e091c45e411c82f764a5e6469120345e39dc896b90b3b677d7d82139908437cd7695b29629cdcce2f23d75f6406039196963868d62a4de9c7b3f299393aa88d4221cef342205810281810e3f428717de170fd9a2a11fdd057211dd95ed2d39998986e064833a186f653018f8e5230ba9ee0f1ec40a5f7aaef80ff900ba71f8af297806780f0bf0a2584c95fc1b9e326cdcfd58dde68b9535d87128aff2920f01210ad57de059c673f0b34903276a02df0fe05b3521027e45907838ab4a7cb09a185fe4d80d5e5733aa9f3b0281810d1413d14b7fabc6ad1840d52a00ff6bb9346e3931289de591ee9772668dd12dee8d4ae0a7f6a808fb48ba2405df36d39842f3081cdbfbfa2e9111b2792964cb6c7959dc5a45dff89aa1b90f0f1bc4e4819d64b83e673937fe8a077895c6544e875e62c8ad4b9d2a1d4b1ea526458de103d2c8c9f95e077af2a39b63c4753e46fd02818107c50e2618a921109ed32765f6268b201d252f94d36ddd67b6267abe8b26ed1b3ef3361b57b813c121392ea30588387695888525b4c6ea29aff577d73e237b5e41099d9237d3d0ed45b2b691770d477de6ff959d7c1b5486d10975f9dfd5c8f62da24fb36bdf748c1991aeefea274bf3948c2df23469c5533ebd6905032f8524930281810a440f46436025031fce20ddf249b434e7bcdb24738cf15c498fa23b7f7aa48ecc69063490439224f2b264c2700585b0d41d014e05f13bba6721226618ab405e59786bec06c44089913f8ed6de422aec3f3dbfd8cbcb14e3fa1e78bcd3bc496316e924db67042a8aeb5192ed89bc21215671f7806b08bf106833ba7eb6b05d413502818105d0bd604f192d745e6f88e5194b2ef390dc4fa61c230a4862d3a12edb3db48178aee3ec577b156a3b0b1474d14e6a9c59276c21202c46410945c7ce6bcb72ab9c61e2c4bf97e3dd4ab47574aad5ca7e0f94698970c07b60ca268f11551dca945ffbbda1acba78d42e9616a6c7da464959c94b44918e6d41423a0ac9deb368efd3 -Error = PrivateModulusLenNotMultipleOf512Bits -# RSA 2302-bit key that is valid, but we reject it because the private modulus -# length isn't a multiple of 512 bits. +# RSA 2302-bit key that is valid Input = 30820549020100300d06092a864886f70d0101010500048205333082052f020100028201202e8314b5b60f188172bd5b0eacb60b94c15375e3df7fe733d523c37a8470acc8108ac1130301167dcdb2fd3c87f48cf8d1a597a3401cde1c64cd115be2f4f03d5cb8948137ea895b1558b8c836ca2bbe8c4376103a6c490e76fed580338a5da6230680855e6659354525fd3e91e7b238abdebb0a12bd8c52adb49b2eba187d87b577abfaeded16a26b8f2705313975f5214cdb0033e08f800c8d5baccdbee86c435882bdd599667ead13b59c9703f8d82c9bf122f70e80639d98f1559ef57e61cc63593ff0111fb7fde3cbd80531e351b41f258585e4e74afb4ec7793982de1d253ed1e479f6942c48f0d0d2674d3e65a547c11014ca924bb3b01401a7e507455a9de56bf9f74b0a752dca972b463b9113b6acdb0a1ebb9b297e496fca0a1597020301000102820120047c9c98d2d12df9fec9896926fc00adfee0403515304f6b4e9a3e9729037d8767211b72ec0d44d029f1a4401c9558abfffd4b5d7227d6bd42740dc2a168236ca7ef1e5440c29d316e23badf85798732c0711988833a42e9e44cbce7bb1113eb9ce159b083e4b7a24de356449cea8ee4ac9fb5c748fb83f7cdcde8525f9d512eb030b52465a34355b3ae81831cb6804c6a17f756956d9c674d3882b65996b27301f4f467478617432c2d4ddcdb14c77789f29a6c866a975c8c8128043a07535a05e40bc625ddcce0eb295cc3b3bfed4f5d5f6fa2bb84b5580b5ff54de7d601533909807c6497da7dd8c292d9bd247430a6000d00b7b02c3cf82d8faf9653b16dbc344b3e2a7e72461b26600720acd3baee6a11c381281e322e79a2088f543a01028190795c84579a2a729defe281fe5339696f8750942e49b4fc6809a66b628b17948242aa2afe65cf5044a8fca45c5794696085a6c20365df2d7d1b3458b47504a1baf869c61b16c7ea2433094905cbfe311d330d4da8fa81c8f86f6d756f5324931941095e832e0da7862fabefa9b48e8c58aa815654be07ab8c7ec4b739cb990efdbf5b9575fbcb3baec42df70060688917028190621cd2ca19189990fa6adf8f0b1f35385312c501415425094c58b7b6f8a9cc641c3b4b9053bb831622231f7be8b93895acdbc8caedf924e61727504579d6e1911e1346deaf471134aed767b2f4d9e879bc63813d7a9647496c29e1d0166b2fbfa0dfe9d93e7de982af3de427c342baaf3bd0212c386dc50c32f821ccf2059875c36df4437d74a64c94c7986672e9a78102819056eb7635afcadb1056f0e99d9749b54415ac1695186131ade9cb7179c09900da5298c1f63640c70285ed7c624eaf92d178a7b8a8ea5b6f9efcceff01301643274027b1a55129997e97b6fcbfd41c985c8b65e9cb2eafa99a9563d60a0788587a6be423f6dc13177ab9c5f0fea0bcbfb3f95a6cd480cdc985f47d3ba57f367e502aaf935a4f1e7dfe6baf680ab301ebbd028190104ba34307da0b1f86481beb813864b97f2abde7d076ee53d607623414a6f718a58bbfa8301013dca83cd72cd861732180fd5c2340554228a92dd16a48ab44f9ba5a0f4a4b286d962778057436b0bea9017e316809a54e1fc6c44a0a2abf10c62e2d2284ff992020a18491117d9fe6abd62e62641ad73884272f094625e88203053b8cf76cade43511fcf8b6035e0581028190575f40ae0aa97cf56c9f08f6b9e418caa562f9378a17ab36b8e6d503f3f4f975aeeccc162e8870a5942dd2ca8157a208faad72532a11e8f0d9bdf0ba38f91585f49f8b51927bab2fdd22bd99544897a08181e32fe7993173030a2c9fce6c219f44299c96137f9e060da72637546e6837c81cadeed9137f8f18ea5c24025f85a118404b8bdc86626ba24b05e081197390 -Error = PrivateModulusLenNotMultipleOf512Bits -# RSA 2303-bit key that is valid, but we reject it because the private modulus -# length isn't a multiple of 512 bits and because the private primes aren't -# the same length. +# RSA 2303-bit key that is valid Input = 3082054b020100300d06092a864886f70d010101050004820535308205310201000282012061ca8d93087a5eb0f9a4e5dd47f62651673943ba5f3cfd6aaecbe355e6f37b422d7cbb13fd0675bdb22cf0e5906a224a83701f3256a78f61ba294160cb212dd5a6b42bda1a8bbfb7b21863dcc8a7aaf2a473dc71a9371e8f16e5dc77b2c4025a69fd27c60c7123e33d8c8bd03398566fe99e7601378e4acd97235bdcba08e388107cfab48c0ac6cc713aa09be6eaa4173bebac4141fc8857e09cb136d9e994efdc5a42a2dd2cf0a15a8f67ab8bf2ca5bfe728bbdd06b1d1eaddfa238d28a857e1b376613cd2260bfa7905300af58f8a14e7ecf41fc31cabd45f7f4445bb00d86f15912bcb730216dfdc656b57b94ee5f5c8b3000ca80628713332028b6d48249174fc8a0bd0ec2917b76218764070ae24355c31eaf389d3403d802bf3dc42b7d0203010001028201205268fd0804a4033a871744b3471a93ce13fc392c4d683b73751cd357280ad63bbdd398604ee1ebc551eaf793ae3112f6d26f618aed65c5ba28c4ed98a1763387123651a23aaebc8114afe3304354b1064c3a6b72c9946ec74d17a6c4a4bcf3f2b7d1247c8d2da77daff7ca3749d3be3c0f977f80a50ddfd203e5435beed6e0d0607cc255f6927a57fdafd77baa8ce07caa191b77c5b2b725636fd252f9246c4d26d4734e472e3884a0c205ef9e947b8882f9b27d8b3e305231757826b900aed455252552af86a1cc0f9f405126272d4e86a5b3a4539fa4ec46d1737921ad5a47046a9b2e1fbf9e745e802155b2e8205286b78317d5855494aae4ce94874c527d21027d11979bcef23917eef81bbd3e1fcf7cb04f8b0f61083acb08d94ed990cd02819100e6c1fc3765e9c9eb83316e06bd2e910f04cf23aa7aa5d303001db15f93bfba4fe28f19205499035be6d2c224396c9d669897dedd6a8c4f399dcffdb8181078baddc34d159a10741384db2a1850b4242a8f63b16c5478b72fbc17efef4866a5ae156e4b6222c86c2f4e370a55c9690f20122f6cffb37a1aa71d848bb9b7b84116a511ba76dedf8743751b842fb140ca4f0281906c7d0b982df2ac5d289aa1925f65be3c562373fc8f19171b53d85ffc4989cd30442175e423d4c106cd00e64f3108fe3f8cb3dd8eff6fd380334baa0e4372d98755a82c6d02e63443eb5020dcc2ce6e452bb6c7434a9758f1cb33b9ce6148a4bed5f042da4a14cbe83d161c26450b8c2f0fe4267d7ef0499b4c7b6407aa7e66f2d1ff5724a01ace5d30a3bc0bb2319673028191009c9e73122290b024b2119d8ce36034c24dd04d73caf4bba860aec69189556b1e07367aa64fe4debbc489ad8d2a9086b078c73353729ab2b6f75e90e51f2826d925e5056fb0f693e21f9d251005ce8e71788b0083f73d4b901188e9a7adab45ae470b6a0cbc70edc499c08fba340ea35e70195250a6bf2c51da9df8bbdf6f267639293436b40460e92f15b2fd2fc03acf028190157424f6d31f4a36a1f0f2429fdadee3cfa4f32adea177904fe45a16e9f3f63fb53968b6d4df1dccda7d730df6047142dff031c0358347aff274e40c2e0a6839fb1666b2a8001e15d052e82cbfd952b51b0fea17c488696e6760b33dbcbf40d4fc39a6fec3e798eb34294b27c63fa2592c2b51f13f49054550ba95ed6e29d0f1f3d52ac67362d9ac54120cfdc31f4b410281901ee70df154d97ae00935532cfdb43c4464bfdd0d6f76712fec6ae76f2a08f37f48eb2d54a341c023a1f79b143414f79479f5ace419ebca650a133fd6fa599dc3754851e04a5128bc007cccb1116339844861beacb1ab660ab629fcf0ed70ec41368324848f9fedc296c7104811b85141dfda4e7a51af43483e133d557c906b75590dea5480c2a3b7ad881ae6de3047f3 -Error = InconsistentComponents -# RSA 2304-bit key that is valid, but we reject it because the private modulus -# length isn't a multiple of 512 bits. +# RSA 2304-bit key that is valid Input = 3082054f020100300d06092a864886f70d010101050004820539308205350201000282012100cd1d23382a2db0444fdac845b1645182df1ae59d14830e6e4fa41ffff1c1dbcb63e8cebcbd8e643702ef0ab6953d65d9e3138509d5be4fdd15aaff1ccd7d34619ce713bdac14838d4a25fb561c6521992ed523158b538eb9dccc902a7955c5f568e6652fa6296370d589b5acc0ec1cbd110b2506ab73d2c9180c77be49cc8c27c4b06e4a102c60414129ed8644e613735a1f8f5ef874a50ca7dd6c42cf5f90ae745d59cfd4b47bb3c8d86a0c5aad1d7f306343f8b12fbc3ebfda03a59a638dfaa519e241c0fe728322df643cf20eb85134ea7625b8414029ff89fa44b4d8955c43382dc574bffefe4a5f3de5908a4d220d525e85b5774380b244ecf667014786c14cf53517c5f15179435c81e97e46e83c20c21e5ac8922544f1c39bb20571b302030100010282012100878559f0d10570f221a4d7301cfdc0516ce193964ea82ccfbbb52023767374aa94af8c70edf977c3551fe57f2f69eab2a4b30ff2a893dea69f9b64857e4bdc61264f131efde46beadd73ecf53f3b9e905c7e1c792e9e1dae35f1becb217207a29715ab036990ed0fef36d69f76b44a64ad2f24de9c47a19c96541e85ceb2e4639e34481a8d4714ade8c53017c7cc104ab6b0df5e2100f42af6ee1a8edadd726f3303321b9d697740b9ae11cad24f5a9edd3dfe5eedeb03eb5322c7725dde8162cc1b5c4bd56e07fdbba2b75b414efe84ac12885350928d2f859e2803261a6f449f92810eda199fcf279e780e2c47aa119a7b0d7b7729a0a0067f3d648db50673042a27f2f714d335c9aa022a2f51b9752dbddaffe039f5ba2a9736aed89cb3c902819100f0e35612fbec84c21e07de8f8a7f1c82bc1fe9d4e487929d88c925c352750dd4ef5bfeeae293f44437d3da88cd377a3926f621f1d92ec2f5b56775fc4a234ef1083ce3fc309bf6974758891e3b4d5d790d84d22b839adbe2d538668843d962a9ccb761a2f7d1329643796fdbbffb9d2a3b06f31a62f6ea24ba96e7f827cb66c4ceb763aa036906cfd126547d18b57e5f02819100d9fb446655a1eff75331b259824d3f1e1e845d3d6f385bba360424ae08ac55beef743b6aebc5f4028dc218d5eb5c31bbfc53a0035e7951ba9014c8e4e6ede6d21763272770058cb8ecb7d995f6ec9cb34c8cd63455eb832ca13783ec52bd789ce47010f141d3364fd6230aabb0045596680225fef8f0e7148c1d52ff630be6bca36ca3cf996507ee3e2b6d618a35a52d028190767d8d0067954f34612b43c9ddb96adfd003eeb47ef9452062817726ddefa02f26d25cd15344adf9c4705c65c0745295bc598416ffdae5a1916ae3f986ca59716cb8eef8453ce28e45550295b15bfbe7a8c3b5d21bb95801fb19f42d811a7452cbd5449cb243e01b53f36f176c172b96f35416cedaf153f95f230dd5de554a26f2fbf8754f9a20f4a68fb12d9bb2e307028191008319d431981f252c232528971cff488edcdbcf183be43186f525d8c9b2fdb3347adff53c81413558b3d9a10647dfd329b4c0b6e44fd5b789f54e0ae560de848ca6f443803ca799d33ecbf4597581295dcd14876042acbae004b656e9b379b128eb5b5b553eb9c15892f9d059222bf92dd4b03619fbaf27cbfbd94729c2704dfdf66c48b97b10808c91679d09a50e4ea102819100835e751035519d3a6c0a6cddfa73d928b5ea0c51eb7ba44c34ddf148edb1971e436c1438ba996c114f0a545bdf3cae1be3da1ecbc6859fac3ce04a7b1beac6c19e5f032ecc7cd9e96e8e6fc2241911f90ef0a26b1c8b9df24e324690f6be4d904a7070d9424120b65c8ebd733a97817f943d4c697dd931e66c8a5eb0bf54d813e0df978828897bfe304cdb799728cdc5 -Error = PrivateModulusLenNotMultipleOf512Bits # A valid ECC P-256 key. Input = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b0201010420090460075f15d2a256248000fb02d83ad77593dde4ae59fc5e96142dffb2bd07a14403420004cf0d13a3a7577231ea1b66cf4021cd54f21f4ac4f5f2fdd28e05bc7d2bd099d1374cd08d2ef654d6f04498db462f73e0282058dd661a4c9b0437af3f7af6e724 diff --git a/aws-lc-rs/tests/data/rsa_pkcs1_sign_tests.txt b/aws-lc-rs/tests/data/rsa_pkcs1_sign_tests.txt index 171a2f74b30..ed8287380ee 100644 --- a/aws-lc-rs/tests/data/rsa_pkcs1_sign_tests.txt +++ b/aws-lc-rs/tests/data/rsa_pkcs1_sign_tests.txt @@ -434,19 +434,19 @@ Msg = a7c309d44a57188bbd7b726b98b98ce12582228e1415864870a23961d2afb82cd5bc98bec9 Sig = 72a8d4f11321d8465ba3cf051ecd8e307367014a0ba1677e77a9c500d77e874558e245f3e2f52985e770895827a2cab290b05229168bccd3bfccea7e7128beeae070890de1c1b7f52ac90894ec52403a33187baff155a471f913e8bc2d96e4ff16308838f9f7473bdaa29d0ad5a6dbfb0d8fbc229cc46394c5e25fd19ed6129f28b0c15282793bd288ad491d1324ca431a63212b75ceb510b19d4f635d8fce80ad86e7539b4883c7aefad92cd2de9cecca4e2d7986dea10ca122dd6cf455deb7eb3930937892e713760034c1e9e8b7a0e566bf471845d125d79018f1b3395e2fb4a908ca3c39272a3f2ee733e56bf76930a54efb049fd14cdb67c728ab23f442fb0e8efdbf0389770a086a7451cefbf5b94ffce64ed0430b441897f5a7875420c9df2aa4b3eee7551d0072b021abd579279f8d5b42b129fd13fb4717a23eaa50e0bebbfa64cb973aa249d8095b68ec5944f4f9b73b5f2d6686e9a0d84497d97dde49f8b77a0141a2ea2de47f08d171d16a53fd2e02369c35de96530f5006c35e96857219584053aabe880d246066e225dfc9ac4f59dd295c131796d4b739de118660897c22e9964d7ec8e53272dd2cbbcc2b1342faf9ebbdf4c24cf31b192bdd070eef578ca8cfa02f2c6f29e1643796087cc3867a4a6be8cb35fd63e03f66b9ef2be3fe7975aabe08d7234d116b4c6b41ab5e5de0f93fc60d68b3478ad4ede9 Result = Pass -# Invalid key, size = 2040 +# Invalid key < 2048, size = 2040 Digest = SHA256 Key = 3082049d0201000282010000baff76a0e86f27d7cb0b843454475348f1a7b474d12c3ed1f479d2d8d34c0bc8a7cf9562bc43b3649585a0325e17d30872c19202af95b407fbbe701811a77937a0c866f863f062f1d36724faf5a44724aa8b0901bc61f8632bf6a1bcad8da8c26b38428b88413317f2975019e9a0c0a4c2ad5cacff643dc3092d053f8607bba83310ca90197e4f38f6507d60d3fcff5c42d0d9e2695b72490c0b622d783e22ce0986dce6047410569e869651acf168f59bba02326f5a2a5d1292766a9b5325f7e17c1820a1ec91aa4257483657f8d13fd3ab071b9ff361f8ddbb071b61aeaec3ec7338694ff2f3f7b43d81cfc9900a6b8cc5c426ef5c26559a5348c16b476b02030100010281ff26030c10456f630000ac44a18688412bd0c3b071169c11e107fb439b03c8af948858301bb3fd67180934f28d8a86f944fc5ed0d96eebd57ed1f3b241924522e4e5f016ce6332584aa4189171da411c9d1d75c9ccea8857bf810e4f6e5531389edcc0c0f6302a60c27b73babaa9bd1dabe04ef149d158851d825dfe751d3fb126355980af98fa7d977e573f58e428a309835958ee689242dfa6018c070d39809b8c21632cbe33fe3ee1a862e38ed13b6147115194b48922bb1de56ffd20679146251c8d2fc192c931c7e538299e7bbcecd81d3b8f8ff5ab95887b5bf3c621653810e2e3fb3b00b0817aed965d21b5ebdce84055c15770cef5d7599c79dee9410281800f522a5da7007ca094340bdc9136edd6ee0a80bbf3c6d1eb062c57d58ae69e170ee629fa269fa7bbe3ac78267a7eb260c5fe064a7ee05f78ba8ec0be8f1d0f471d3af0820bd09756110b4d53c6ef83211b10ee0862d879472e030c9ce0862c5b5aaee108d3f1c011a746629d90cd78d8111f1da85896b93d9e088205c314af510281800c3492d56d1ecee6d51bc376436baeab40a1a3eee530a5faad1f8db149cdc2fc01eb809089a36de466a620a4b997d8112b613c68fda78a7237506c90cc890d260974430ede8942e2bb34fb9473e46adc85aafc42ecac2a84f56fb4bf7d7f8469e791111cbfc75a221bf0e3d252957e5bb0dc78fd73509007e973014476c273fb028180072a6ade3a89a3c0871080abbccf701622678f26593218645012d551ef1145c78b146375b832dc04a8cbb5b6697c70798aa0f0d84ed72a5011114b5cd51ac65680795c9bb662ed2537fb8d432dbc401c6fc84f4c64ced28a541ee0fb4e97f28f17aecb5991a77429cd8ec1f8e80cf2043c9dcd053bc9e301cab437fbf1edeec102818000b46865fa4ef5134eeab376789e170fbc4398fb8a302ce53469c5fc9e8e4adbd2208ee3c98eae21a9eb9da6e53067415687debd1128434e24f377d1447e054c54ef698fca3992ab14b4127297de706d1b2aac3611043fd03d7b9dac10caf41249548ef0620258a9ef8311246bb04603754ac5919cbee21212e0990a22f147510281800e6614d7fe3a6c3ce1c1d2cf1d3eab9b7ae046fd78067141dd841726968e8cfebb4171d94754aa4c71ae8cb53d251b06e420f2b7f0f01a6a2e6b386c3554e0e81a74a94b053bd5c062997729801885f3c36b996b2757b76d09116e11af29d604f70e7dd63225234677796095551c64692aa52ba63aaae2dc836f92cab9def128 Msg = 61 Sig = 6041bb20241dd3aaa3eb8175f9642243e1e3cb289e52bad58a4d56bd8a10306bf139ae14d2489fa3575c74f53d851b7dd7c6bb7520718295afbfb5e67ea7b414c332fa0bf3df019c95ca9f6d0389a84c2020ebebeb09ec42a4985f47560c356979a7667937c94de9e16dd26dc4bc4c3a7f34f9b1f5f1166397c6493dab8760e822f41713bb9b1978cd413955a3d356f2d03d973036019a1115e502f65aba3c9b5a3955ba2d6155f106283657541faccce43db657f9aeb93f64e0331f3e71e3f569a26e773e1d103c2c04c59f331ca53bd44c271df15c32279f433359e1b1744fdd587c94e2d42ddbc899ec444718ae6a22e302ebcba861528d08683345e9c3 Result = Fail-Invalid-Key -# Invalid key, size = 4104 +# Valid key, size = 4104 Digest = SHA256 Key = 3082092d0201000282020200da35475cb97abb30a924594d855d9279fecff4bf9b950c5ba8ed23a263429d1e075cc63e2438b34ce5ebf1699ed0ca590c1eec0e93dda1c5a345d01a6aa2b1708c74fefb91cb078b4725996af868ecae9390b836d906288c0d86f3991121f85059b45c24611d97df5d497a56176c3e1b9b83887e8a07f72bc2d45cdc8e5a90439ef77b09ebb1c2e538058dee343004ce2351c6b398f1f4896b165e2ef6ccdb46dadf51db109137e7db57fcbba406c16b4e8c3d741dbac14d1c1a02fbee6a58cd2472737be1c73fadfaf3ab90064bbf1d1b1eeb499283334c9ccaa68a875ce25a025f9cd49c6a64a00a7c065c2693a02cd4c4984879a9b46a7f88274b259ada9d69dcb62dbb9fa5d865841262a76b63018d06cd808659ad4cfa31e022d227a884969346de362697ce192dd839537ef3017f0f73fa080d012a82f596c24eaa9dd01fc10c875020232ffc1635ef094b050a118bf810d8d409df9399f5ccfbb3ebf25a96f438eef72a6b563be8efaa1f5ee5fd2950cacc06f7a208a311f9d5e5e9c97284859cebecd5527f76c7b80dc44f6a5856411fa53148a28ba3025ca02fd9b4f97245fe31fecadf7bf5683a3ebfeebc91695a3910f27f38df143cbf0b9b9553fcef262f16ae5170a1b5018b2f0fdac640afd5c318a9517ca8491bdf231e940e861e4bf3336a0c83a9cf1c1d53d6ba6dc129717f14fdf6261a0cd6c93eab0866c702030100010282020200a9520a6bf3293f33c52c0577d7f30204542bbdf9289b0199e67d0cd7a73a3b7cdfada7cef48062f15ac038f6025c75879f96270a30c71c0ea66137d827c2d2f948a4486fa173f008ad4e89bbadc28d55f1ffac5233194a415305d2e4859cdc784d035d34857f5727e5d56c6e7d826ab735775d65036aa6eb78251d61afbcaa912e3b4f6825522caf7d47221922b9d820b4db71da4ee60120d8cde48b80caf9a40396a287e0552f1264ebe39b1eee770bf349732e351b837f783cdeefead2eed15064d723dbd0a6a33445fc6ca7d603186cc1134665c015006ff1f8452a40730bf1278c2496b3201de7c4d19294049d97ec0a1938b3df71b5e9fc16b1831ea460c6a5813b96b542a809b4e92092d0c850a213936ea8bd48467cb4738e55f79202045a3e58eb46df455f33ab8ed1f798001006f620038b9557d21263dd1b3f849550d7c79d37a816ee6ce8a14bb8b08ce9caee2860815b7ad0c862e40c0639d7d5d129b501405560657a49b99ebfbabc666086a4c9ba394367f29321c7676ffd908b65ca0b5992f6cb65bd5ffe1c5257e584d6f01c04f4a4de223cf39ab3cf1f0e43b933f0f2fdff24dd8f03b0d69ec5d592732c960205e7a94401baaabd7cafc90b972f56a0d096a2ee366f9be53b97b820b9639382cd3508498a7f08543032f8d33fc0968596d4db961e8089ad17be6c1fec0228968e7b21ef164ff8c43479e1d1028201010ee8e72193d6b01c1f603fa872c04d0bbdf690cb4b3dca22a3cec552b788434302390004d118f53532be3774da84c9d2c675b81481d2df4e17abcafdece67250e30e76d7671b145c2accb57a19c1e95029936dd27947af246ec1e522c67f1979575555795cb6637532300f5b1bdf5f55f130d195165eec33522367dcf9331f9a3ac52db8cab35516cb8944f73c1903fb6936820d1430cf6ed6f3c52d2696ba20cc6098dbc91d392d44a0a0d543aa0382998cc4133d3ef3f02a2f563b9c2aede75cb99c40ebb01ad2a622ac376bb72adc2f23a3efb681d6b73e99b68d43ca306f68c42df1d482a490bc01289e2dc81daa76aaf7b4d17456b9d1f4272542be12899d028201010ea29ee81cb4b4ca41b489746ca8ef83675c90bea23224873af5026a01a4f172134f2da20ae520f099b65cb9a6dd7f50f8f0b0db6aecb1cbf3630e975a1f1af37725a8fb88f1a762c3ab790b80d60cdd320582d9b1b6adf8e52ce56d98cccf1770370c3e54cb69100adc2da03a50bb107095e4dd6afa0f8de4c93d6cf27d1a1a11ee21ded0d6fe4da95a3a0df2dc74aecabc5ebc99a30afe4a0efca184c3b4f0f58be76ae282222da06971390d6951f8124bec79a912deae86bf502518d6720e147bd6d74d7ae0e90bb42c420c957bb68498f82e81dfff51c4b9f9725b1553c25c9b49d7181942bed4fc80a1290cda56f2755d1f963b276e152bca36f9ff1286b3028201010e7ad41540fd8bf513e7a68b123e7dd4bc7d1bebc33bd3f6463dc656e9d514f59bcffd9baff25c19791950c45480077d82adcac367bd828ed5e04a78c6bc9b22c110480c339f11ebdcc90829f79fe1d5af3af5ba257c9fb473382d2ed3b595e8c90f1fbe8872bd2e913a297fa31711006707b152e7f1f1d4799dd6fdbcaa90b379060bbc5e674168acecb8249fa1efc317500f876227711cc4f6e37450f8aaf4b567ceac0caa2be031b909d9742845d66d074f591beeea7b408cce637fec1535cf509756594ea30e16b8afa5f71f61298b4242b0c7ff5aa685ce4482f6e6029a00161e44b0ccdbc3904253cf22c9293e6696ed9016a6b49f2c2ec061a86aed97e502820101081f078d07f8e2e5e566186c89ab891562f303c335601bd30acd50e4a03af65c760896eaf79ec4139f4889d5df99c3ff9bd47c5f95caf8b29341a1a42d375b8e44cc9a23d28f3e7258e03b503dd309da68da940cd747e6ec59c7fb1c41114dcdd4d04734037bc8b645407ef50dc724b6efb2ce086c478d001137f6a5113e889074e8aed4e510989761e596978ceff6b3d3fe8997a0adcff8e201c500a01ab5ba8c9770f867ef0ca643009ffaa7cd8cd5dad954c502245d7b7d7c862dbfc5a80ed6210e4bf54bbda8b47ceb9e4f3b582625187987dd3bfe8352665cdcaf5c7b593c6853a64f521d2ea623e4010a357ea786edc79a32946ac1f46f934bc4985da06f028201010d783f2e727336392f1f93272cca34854c0a2afffe94fdf19cbab693c81d17c0f24d3bec537b7be9c0ca6d57450c11cac258332e4d3d0fa82a6d1a2af223dbbb9fa90cd60bc977ead9a5c377ed7123d7b3238b56587780081f29caf322a99e40f982bc6189ce68c959b1106fff19c9aa3ec0a9fbbcfd461de51cb6d3e9b664558124fb88359043162cc144a023c2ff1ef9fdca01f1db3dfad8c4e0aa914f84b42f4bfa9fd4be67c5fe864166d62dfb779aa106f7d99866384f13ed8c6dc34ce9a950f9778d009fa1b8936a67403211d4bc8f99da77f0f82cad1e3e4f594ab7cd377fed95e720dc1acadd0d75d415b0d5bf1257c0c6ee78eb09973cef9773d3ca32 Msg = 61 Sig = 3b06ecdd187c947f9007f0c4bb77b1ea60898bbe426505fc9200e09e2ae7fafd8d563c92b57755a6e62dbd7232ebc59158c267bd965ce39e24bb795f819e92a6a5a1de2a1f164353583908b74878e8042e488041d3c9122e8006452544e1bfd279295ede2cbb02334e9dd818cac7b6561d4123898bddd29e9c59843bec5771827e95541bbb82e9e1e9bc9c5d4da43d756f35ebbba0b31d41ca446b3d1be046e062be0a2f585c9ef7764faa71d178daeb153f35ccc9cda28ca40453ea09e3eb7a0f77cff09fe074903a07856ef24a158786d417593c6e9d6d024da4fd7d9bd5eb6262810093e5bf9d250a84fa431f6a36ec713b7b0c8f7df2a551687129a9f1eb0a034d350c30c715d515099f2ae7094a754220f7403b04641b8a1d1e4c5a0fbb0082ead3620ebc21baa06daa561440f43d53baf6ac8ee413935ba1dc2af63bb34abc87e669ced4bab9bb40e4cb7c4d8c136a70a175e55e022d66ac18b43355faaf55ac73eab3f59019e522c4967c492f11a9e80305fe37bc643e2ef61c583d60d9c2afbd1dca9e40d2e66e077c3b2cb4a574f6b9c73fa6ed6aefc03c0e39632529cacab6c1fa6dbd645a6bc05a5b8e91f90264f404bde99fb538bee7ba15624e3790bc088c2a0a27d5dad111802a167d181ce930bfa2f1f8b90e5643f55bea1e0edd57b0997a5a84b7e36d5b107913a2b503edc2093998ca2fbc2f2a085d341cbf -Result = Fail-Invalid-Key +Result = Pass # Invalid key, halved Digest = SHA256 @@ -464,12 +464,12 @@ Msg = 5af283b1b76ab2a695d794c23b35ca7371fc779e92ebf589e304c7f923d8cf976304c19818 Sig = 6b8be97d9e518a2ede746ff4a7d91a84a1fc665b52f154a927650db6e7348c69f8c8881f7bcf9b1a6d3366eed30c3aed4e93c203c43f5528a45de791895747ade9c5fa5eee81427edee02082147aa311712a6ad5fb1732e93b3d6cd23ffd46a0b3caf62a8b69957cc68ae39f9993c1a779599cdda949bdaababb77f248fcfeaa44059be5459fb9b899278e929528ee130facd53372ecbc42f3e8de2998425860406440f248d817432de687112e504d734028e6c5620fa282ca07647006cf0a2ff83e19a916554cc61810c2e855305db4e5cf893a6a96767365794556ff033359084d7e38a8456e68e21155b76151314a29875feee09557161cbc654541e89e42 Result = Fail-Invalid-Key -# Invalid key, e is too small (e=65535) +# Valid key (e=65535) Digest = SHA512 Key = 308204a40201000282010100d3e94ceebdf732da0040d4ac1b3cc89b81718abfbb5661a516c4395d4d01689db558fe2dd875a36dabafa81b532bcd3edfc126e60d3acadf8505a2e45570c7ed19649de601042e10953d40639614437f7e380919c994bace28e249f9f2e28d3fd170faa7245e6836c97cabddeea0bc0c94c16d64348175043c0cf443d4886c39a9faf025e9f1b385a2188f206b726ad34f3a5707804ce448b42b04a25db31888a8e9903f0f842949109e35c0719dbcc2b5d541ffc7f7270fbf912f149ca47e90a4232ca40a87f0a24c37a299f04979553a0700dcb2618f3ca448dcfb2313dc028ee78b151ca7dc46d997cefe5b62b5a6f82535059cf8550d08ecab04956f12df020300ffff028201002e2e83cc82fe83f97a0b9ae4648bf19ba51f2d85da0f3b32bf5ade832dad3e43acaae37f4d2d601ce4891a419eafa8581e072bcb4a295c237616a288390edf00908b37dc3990ecc2d5e8c112f4e5bb63621b0446bceec06c71e1525464bcb7d8e2336b331be616c8174cdc9927fbfb37111a003ad89416de551c7fcfcffed2e4365ce61ea90836505735c36a087d5675c608806e361cbd02b9b5f9d93087fffef5c17d20475ab164323c1b6069dfc3116b99990ee41f6a7230ecf381e838bfc3265857963f92e09e82a658ad054c4593fbb8832d4e6bd42da4d9a6ef365534469c7c8f14843f3f69bb1ab5dd12b4f2150c3c16fdc9201366c910ad19809110cf02818100eed2c519d13351a714b5473fef7921c6f334a099178fe48404a567bb59c125281e05746e188b8eec0fa2f12cda11f386c11ab460de0b37131d1e3bb8ee6ac5bd8de72939d2d0660ba9871e1c96072c8759b36c938308d4876cc9f7df707939b1c1a3a642929a1d0ea277c4e4b217140164cc34d3360072aa55bb1782759e9a5b02818100e327067c378bd8fe8cb78f119d4a4e2abb42caf13aa0693cbb824ff2b0a71230b94e72f3a9ac2beba21707d7a004a6094a95ac891929609c8cbf1eb7fad204a3811da06fc64747451d1500b20a388b4246c63c309b19acbade72218edb41df4525a27d5381140918ac68153e2d3924f604cac5e0202922e6cf8d6bea7491e8cd02818100ea2f2a601918515b0c9345aea0fa01eedd0d29bf076fa9dc7582be17dd7c57718bd1991a45bfae267b039b4c3c28f259c6d77c52b04ce38feb8f3ed2f6eb3d4cb9dfb2b65bc3a0b37430e7e1a3a63079f098f6422330ddc6a09d336115e4944d3753352c6078ea92f2362f110709d431aa0e3ea2918845f7f8046a73e0d523e30281805a268208642fc360e107662ddac32d02c06e056a7bb7cf1baa6224ceac8c2a9342cdf60acb9c20d6579d4d790f7987c26dbd0e4343209ff92110a66898525baba3547e557a5d1a14f6dca1b04a20b4dd1565979ebddc915a86cc803feb21f296aac344521d2729b7557b7011aa123cce63bb40fcf0a063fb4fd026e92606621302818100cc847aa3a8851bdb581b1fc9926abe2760d1fa47b5993e6ff83a4abf3827252e0bcca53331eaef1eedd83bad6cf10327ac573043bb87d822a91c3c5d35989c82a00bac71f2b879d2f0c7efa582d2b3498bc190386f90f02e4a6b5166010439fd7070aca790b597ead9188e295789ac2bfcfb6ca039f235dcd0d0a7c197bc84a2 Msg = 0123 -Sig = b62bdd9c87f8f409178a5155768b536c1341f52a28c881494baa80b39f4a25a841f664eec49a464adf3cf5c920975cb83de4b06f0c7740685f0174627fcb4d0511bc6a25d473952c33fa5763a8e9bdd00bcdc1e4e5881d061193d77335d7e245987c9333455c9e1a2f0ff45242cff45cbd9ab8859d1c81dda62680ce388caba410be15bb40c0a66ea3a4ef07a3fb1f0f66c656c754dd3b15e694902ea79d1d0496a83408bdc2e94b7bdfef5883fe748ed50027ce0f35380dac8245e042ccdad69cd98440a2f77085a6d02d097f6ef650400b7eb469b9e6ee5284c7c7aee8e6365731114490dffadce428b2d16dd086ae0ef350f8e9dffe22d63203d891394322 -Result = Fail-Invalid-Key +Sig = c417ba19bd45ef2c60f8275c6bbdfa434996064e63c7be8184821f2ceb59485262281b8c6dba824b73a6760a12033264ba7ce6e34adb3c5dc575f791424614c732de3bd635451d36b6d3475ef413624e854ce83cc93cde5e51cc84a6c75e8cf67aea1333ca5f277dbca337b35e5d00b1c9fee561e818c13eee42be83a845e61f9ecf62462aa70f0d12f7559c4dd79cc5d227b8b084f914af50d86f2cabb1ec478509a160d29e2b5b8ef892db7d511b32e3ea64783141ef63748e1a1c1b13814f27e48047cd29b6a742500b8d7a9496cc21a9225f1a5344988d6b1d1b8bd9d974744bbcfd5806d184c99798368428a513b5a8c9c297e2feb5e500cddf2399617a +Result = Pass # TODO: # Invalid key, p & q are too close diff --git a/aws-lc-rs/tests/rsa_test.rs b/aws-lc-rs/tests/rsa_test.rs index 0a6bc491bd9..ba49144ec69 100644 --- a/aws-lc-rs/tests/rsa_test.rs +++ b/aws-lc-rs/tests/rsa_test.rs @@ -4,7 +4,10 @@ // SPDX-License-Identifier: Apache-2.0 OR ISC use aws_lc_rs::encoding::AsDer; -use aws_lc_rs::rsa::KeySize; +use aws_lc_rs::rsa::{ + EncryptionAlgorithmId, KeySize, PrivateDecryptingKey, PublicEncryptingKey, OAEP_SHA1_MGF1SHA1, + OAEP_SHA256_MGF1SHA256, OAEP_SHA384_MGF1SHA384, OAEP_SHA512_MGF1SHA512, +}; use aws_lc_rs::signature::{ KeyPair, RsaKeyPair, RsaParameters, RsaPublicKeyComponents, RsaSubjectPublicKey, }; @@ -55,6 +58,7 @@ fn test_signature_rsa_pkcs1_sign() { let rng = rand::SystemRandom::new(); test::run( test_file!("data/rsa_pkcs1_sign_tests.txt"), + // test_file!("data/debug.txt"), |section, test_case| { assert_eq!(section, ""); let digest_name = test_case.consume_string("Digest"); @@ -309,6 +313,8 @@ macro_rules! generate_fips_encode_decode { fn $name() { let private_key = RsaKeyPair::generate_fips($size).expect("generation"); + assert_eq!(true, private_key.is_valid_fips_key()); + let pkcs8v1 = private_key.as_der().expect("encoded"); let private_key = RsaKeyPair::from_pkcs8(pkcs8v1.as_ref()).expect("decoded"); @@ -332,6 +338,84 @@ generate_fips_encode_decode!(rsa3072_generate_fips_encode_decode, KeySize::Rsa30 generate_fips_encode_decode!(rsa4096_generate_fips_encode_decode, KeySize::Rsa4096); generate_fips_encode_decode!(rsa8192_generate_fips_encode_decode, KeySize::Rsa8192, false); +macro_rules! encryption_generate_encode_decode { + ($name:ident, $size:expr) => { + #[test] + fn $name() { + let private_key = PrivateDecryptingKey::generate($size).expect("generation"); + + let pkcs8v1 = private_key.as_der().expect("encoded"); + + let private_key = PrivateDecryptingKey::from_pkcs8(pkcs8v1.as_ref()).expect("decoded"); + + let public_key = private_key.public_key().expect("public key"); + + drop(private_key); + + let public_key_der = public_key.as_der().expect("encoded"); + + let _public_key = + PublicEncryptingKey::from_der(public_key_der.as_ref()).expect("decoded"); + } + }; +} + +encryption_generate_encode_decode!(rsa2048_encryption_generate_encode_decode, KeySize::Rsa2048); +encryption_generate_encode_decode!(rsa3072_encryption_generate_encode_decode, KeySize::Rsa3072); +encryption_generate_encode_decode!(rsa4096_encryption_generate_encode_decode, KeySize::Rsa4096); +encryption_generate_encode_decode!(rsa8192_encryption_generate_encode_decode, KeySize::Rsa8192); + +macro_rules! encryption_generate_fips_encode_decode { + ($name:ident, $size:expr) => { + #[cfg(feature = "fips")] + #[test] + fn $name() { + let private_key = PrivateDecryptingKey::generate_fips($size).expect("generation"); + + assert_eq!(true, private_key.is_valid_fips_key()); + + let pkcs8v1 = private_key.as_der().expect("encoded"); + + let private_key = PrivateDecryptingKey::from_pkcs8(pkcs8v1.as_ref()).expect("decoded"); + + let public_key = private_key.public_key().expect("public key"); + + drop(private_key); + + let public_key_der = public_key.as_der().expect("encoded"); + + let _public_key = + PublicEncryptingKey::from_der(public_key_der.as_ref()).expect("decoded"); + } + }; + ($name:ident, $size:expr, false) => { + #[cfg(feature = "fips")] + #[test] + fn $name() { + let _ = + PrivateDecryptingKey::generate_fips($size).expect_err("should fail for key size"); + } + }; +} + +encryption_generate_fips_encode_decode!( + rsa2048_encryption_generate_fips_encode_decode, + KeySize::Rsa2048 +); +encryption_generate_fips_encode_decode!( + rsa3072_encryption_generate_fips_encode_decode, + KeySize::Rsa3072 +); +encryption_generate_fips_encode_decode!( + rsa4096_encryption_generate_fips_encode_decode, + KeySize::Rsa4096 +); +encryption_generate_fips_encode_decode!( + rsa8192_encryption_generate_fips_encode_decode, + KeySize::Rsa8192, + false +); + #[test] fn public_key_components_clone_debug() { let pkc = RsaPublicKeyComponents::<&[u8]> { @@ -340,3 +424,154 @@ fn public_key_components_clone_debug() { }; assert_eq!("RsaPublicKeyComponents { n: [99, 97, 109, 101, 108, 111, 116], e: [97, 118, 97, 108, 111, 110] }", format!("{pkc:?}")); } + +#[test] +fn encryption_algorithm_id() { + assert_eq!( + OAEP_SHA1_MGF1SHA1.id(), + EncryptionAlgorithmId::OaepSha1Mgf1sha1 + ); + assert_eq!( + OAEP_SHA256_MGF1SHA256.id(), + EncryptionAlgorithmId::OaepSha256Mgf1sha256 + ); + assert_eq!( + OAEP_SHA384_MGF1SHA384.id(), + EncryptionAlgorithmId::OaepSha384Mgf1sha384 + ); + assert_eq!( + OAEP_SHA512_MGF1SHA512.id(), + EncryptionAlgorithmId::OaepSha512Mgf1sha512 + ); +} + +#[test] +fn encryption_algorithm_debug() { + assert_eq!("OAEP(OaepSha1Mgf1sha1)", format!("{OAEP_SHA1_MGF1SHA1:?}")); +} + +macro_rules! round_trip_algorithm { + ($name:ident, $alg:expr, $keysize:expr) => { + #[test] + fn $name() { + const MESSAGE: &[u8] = b"Hello World!"; + + let private_key = PrivateDecryptingKey::generate($keysize).expect("generation"); + + assert_eq!(private_key.key_size(), $keysize.len()); + + let public_key = private_key.public_key().expect("public key"); + + assert_eq!(public_key.key_size(), $keysize.len()); + + let mut ciphertext = vec![0u8; private_key.key_size()]; + + let ciphertext = public_key + .encrypt($alg, MESSAGE, ciphertext.as_mut()) + .expect("encrypted"); + + let mut plaintext = vec![0u8; private_key.key_size()]; + + let plaintext = private_key + .decrypt($alg, ciphertext, &mut plaintext) + .expect("decryption"); + + assert_eq!(MESSAGE, plaintext); + } + }; +} + +round_trip_algorithm!( + rsa2048_oaep_sha1_mgf1sha1, + &OAEP_SHA1_MGF1SHA1, + KeySize::Rsa2048 +); +round_trip_algorithm!( + rsa3072_oaep_sha1_mgf1sha1, + &OAEP_SHA1_MGF1SHA1, + KeySize::Rsa3072 +); +round_trip_algorithm!( + rsa4096_oaep_sha1_mgf1sha1, + &OAEP_SHA1_MGF1SHA1, + KeySize::Rsa4096 +); +round_trip_algorithm!( + rsa8192_oaep_sha1_mgf1sha1, + &OAEP_SHA1_MGF1SHA1, + KeySize::Rsa8192 +); + +round_trip_algorithm!( + rsa2048_oaep_sha256_mgf1sha256, + &OAEP_SHA256_MGF1SHA256, + KeySize::Rsa2048 +); +round_trip_algorithm!( + rsa3072_oaep_sha256_mgf1sha256, + &OAEP_SHA256_MGF1SHA256, + KeySize::Rsa3072 +); +round_trip_algorithm!( + rsa4096_oaep_sha256_mgf1sha256, + &OAEP_SHA256_MGF1SHA256, + KeySize::Rsa4096 +); +round_trip_algorithm!( + rsa8192_oaep_sha256_mgf1sha256, + &OAEP_SHA256_MGF1SHA256, + KeySize::Rsa8192 +); + +round_trip_algorithm!( + rsa2048_oaep_sha384_mgf1sha384, + &OAEP_SHA384_MGF1SHA384, + KeySize::Rsa2048 +); +round_trip_algorithm!( + rsa3072_oaep_sha384_mgf1sha384, + &OAEP_SHA384_MGF1SHA384, + KeySize::Rsa3072 +); +round_trip_algorithm!( + rsa4096_oaep_sha384_mgf1sha384, + &OAEP_SHA384_MGF1SHA384, + KeySize::Rsa4096 +); +round_trip_algorithm!( + rsa8192_oaep_sha384_mgf1sha384, + &OAEP_SHA384_MGF1SHA384, + KeySize::Rsa8192 +); + +round_trip_algorithm!( + rsa2048_oaep_sha512_mgf1sha512, + &OAEP_SHA512_MGF1SHA512, + KeySize::Rsa2048 +); +round_trip_algorithm!( + rsa3072_oaep_sha512_mgf1sha512, + &OAEP_SHA512_MGF1SHA512, + KeySize::Rsa3072 +); +round_trip_algorithm!( + rsa4096_oaep_sha512_mgf1sha512, + &OAEP_SHA512_MGF1SHA512, + KeySize::Rsa4096 +); +round_trip_algorithm!( + rsa8192_oaep_sha512_mgf1sha512, + &OAEP_SHA512_MGF1SHA512, + KeySize::Rsa8192 +); + +#[test] +fn encrypting_keypair_debug() { + let private_key = PrivateDecryptingKey::generate(KeySize::Rsa2048).expect("generation"); + + assert_eq!("PrivateDecryptingKey", format!("{:?}", &private_key)); + + let public_key = private_key.public_key().expect("public key"); + + assert_eq!("PublicEncryptingKey", format!("{:?}", &public_key)); +}