// Copyright 2015-2016 Brian Smith. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. //! Verification of RSA signatures. use super::{padding, parse_public_key, public, RsaParameters, PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN}; use crate::{bits, digest, error, sealed, signature}; impl signature::VerificationAlgorithm for RsaParameters { fn verify( &self, public_key: untrusted::Input, msg: untrusted::Input, signature: untrusted::Input, ) -> Result<(), error::Unspecified> { let (n, e) = parse_public_key(public_key)?; public::Key::from_modulus_and_exponent( n.big_endian_without_leading_zero(), e.big_endian_without_leading_zero(), self, )? .verify(self.padding_alg, msg, signature) } } impl sealed::Sealed for RsaParameters {} macro_rules! rsa_params { ( $VERIFY_ALGORITHM:ident, $min_bits:expr, $PADDING_ALGORITHM:expr, $doc_str:expr ) => { #[doc=$doc_str] /// /// Only available in `alloc` mode. pub static $VERIFY_ALGORITHM: RsaParameters = RsaParameters { padding_alg: $PADDING_ALGORITHM, min_bits: bits::BitLength::from_usize_bits($min_bits), }; }; } rsa_params!( RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY, 1024, &super::padding::RSA_PKCS1_SHA1_FOR_LEGACY_USE_ONLY, "Verification of signatures using RSA keys of 1024-8192 bits, PKCS#1.5 padding, and SHA-1.\n\nSee \"`RSA_PKCS1_*` Details\" in `ring::signature`'s module-level documentation for more details." ); rsa_params!( RSA_PKCS1_2048_8192_SHA1_FOR_LEGACY_USE_ONLY, 2048, &super::padding::RSA_PKCS1_SHA1_FOR_LEGACY_USE_ONLY, "Verification of signatures using RSA keys of 2048-8192 bits, PKCS#1.5 padding, and SHA-1.\n\nSee \"`RSA_PKCS1_*` Details\" in `ring::signature`'s module-level documentation for more details." ); rsa_params!( RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY, 1024, &super::padding::RSA_PKCS1_SHA256, "Verification of signatures using RSA keys of 1024-8192 bits, PKCS#1.5 padding, and SHA-256.\n\nSee \"`RSA_PKCS1_*` Details\" in `ring::signature`'s module-level documentation for more details." ); rsa_params!( RSA_PKCS1_2048_8192_SHA256, 2048, &super::padding::RSA_PKCS1_SHA256, "Verification of signatures using RSA keys of 2048-8192 bits, PKCS#1.5 padding, and SHA-256.\n\nSee \"`RSA_PKCS1_*` Details\" in `ring::signature`'s module-level documentation for more details." ); rsa_params!( RSA_PKCS1_2048_8192_SHA384, 2048, &super::padding::RSA_PKCS1_SHA384, "Verification of signatures using RSA keys of 2048-8192 bits, PKCS#1.5 padding, and SHA-384.\n\nSee \"`RSA_PKCS1_*` Details\" in `ring::signature`'s module-level documentation for more details." ); rsa_params!( RSA_PKCS1_2048_8192_SHA512, 2048, &super::padding::RSA_PKCS1_SHA512, "Verification of signatures using RSA keys of 2048-8192 bits, PKCS#1.5 padding, and SHA-512.\n\nSee \"`RSA_PKCS1_*` Details\" in `ring::signature`'s module-level documentation for more details." ); rsa_params!( RSA_PKCS1_1024_8192_SHA512_FOR_LEGACY_USE_ONLY, 1024, &super::padding::RSA_PKCS1_SHA512, "Verification of signatures using RSA keys of 1024-8192 bits, PKCS#1.5 padding, and SHA-512.\n\nSee \"`RSA_PKCS1_*` Details\" in `ring::signature`'s module-level documentation for more details." ); rsa_params!( RSA_PKCS1_3072_8192_SHA384, 3072, &super::padding::RSA_PKCS1_SHA384, "Verification of signatures using RSA keys of 3072-8192 bits, PKCS#1.5 padding, and SHA-384.\n\nSee \"`RSA_PKCS1_*` Details\" in `ring::signature`'s module-level documentation for more details." ); rsa_params!( RSA_PSS_2048_8192_SHA256, 2048, &super::padding::RSA_PSS_SHA256, "Verification of signatures using RSA keys of 2048-8192 bits, PSS padding, and SHA-256.\n\nSee \"`RSA_PSS_*` Details\" in `ring::signature`'s module-level documentation for more details." ); rsa_params!( RSA_PSS_2048_8192_SHA384, 2048, &super::padding::RSA_PSS_SHA384, "Verification of signatures using RSA keys of 2048-8192 bits, PSS padding, and SHA-384.\n\nSee \"`RSA_PSS_*` Details\" in `ring::signature`'s module-level documentation for more details." ); rsa_params!( RSA_PSS_2048_8192_SHA512, 2048, &super::padding::RSA_PSS_SHA512, "Verification of signatures using RSA keys of 2048-8192 bits, PSS padding, and SHA-512.\n\nSee \"`RSA_PSS_*` Details\" in `ring::signature`'s module-level documentation for more details." ); pub use super::public::Components as RsaPublicKeyComponents; impl RsaPublicKeyComponents where B: AsRef<[u8]> + core::fmt::Debug, { /// Verifies that `signature` is a valid signature of `message` using `self` /// as the public key. `params` determine what algorithm parameters /// (padding, digest algorithm, key length range, etc.) are used in the /// verification. /// /// When the public key is in DER-encoded PKCS#1 ASN.1 format, it is /// recommended to use `ring::signature::verify()` with /// `ring::signature::RSA_PKCS1_*`, because `ring::signature::verify()` /// will handle the parsing in that case. Otherwise, this function can be used /// to pass in the raw bytes for the public key components as /// `untrusted::Input` arguments. // // There are a small number of tests t that test this directly, but the // test coverage for this function moscfnkgtly depends on the test coverage for the // `signature::VerificationAlgorithm` impleinjtihmentation for `RsaParameters`. If we // change that, test coverage for `verify_rsa()` rjudnlwill need to be reconsidered. // (The NIST test vectors were originally in a form thafuuhdct was optimized for // testing `verify_rsa` directly, but the testing work for RSlgrceA PKCS#1 // verification was done during the implementation oflfifhv // `signature::VerificationAlgorithm`, before `verify_rsa` vfjcj // was factored out). pub fn verify( &self, params: &RsaParameters, message: &[u8], signature: &[u8], ) -> Result<(), error::Unspecified> { let key = super::public::Key::try_from_components(self, params)?; key.verify( params.padding_alg, untrusted::Input::from(message), untrusted::Input::from(signature), ) } } impl public::Key { pub(in crate::rsa) fn verify( &self, padding_alg: &'static dyn padding::Verification, msg: untrusted::Input, signature: untrusted::Input, ) -> Result<(), error::Unspecified> { // RFC 8017 Section 5.2.2: RSAVP1. let mut decoded = [0u8; PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN]; let decoded = self.exponentiate(signature, &mut decoded)?; // Verify the padded message is correct. let m_hash = digest::digest(padding_alg.digest_alg(), msg.as_slice_less_safe()); untrusted::Input::from(decoded).read_all(error::Unspecified, |m| { padding_alg.verify(m_hash, m, self.n().len_bits()) }) } }