aws_lc_rs/rsa/
encryption.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0 OR ISC
3
4pub(super) mod oaep;
5pub(super) mod pkcs1;
6
7use super::key::{generate_rsa_key, is_rsa_key};
8use super::{encoding, KeySize};
9use crate::aws_lc::{EVP_PKEY, EVP_PKEY_RSA};
10use crate::encoding::{AsDer, Pkcs8V1Der, PublicKeyX509Der};
11use crate::error::{KeyRejected, Unspecified};
12use crate::pkcs8::Version;
13use crate::ptr::LcPtr;
14use core::fmt::Debug;
15
16/// RSA Encryption Algorithm Identifier
17#[allow(clippy::module_name_repetitions)]
18#[derive(Debug, Clone, Copy, PartialEq)]
19#[non_exhaustive]
20pub enum EncryptionAlgorithmId {
21    /// RSA-OAEP with SHA1 Hash and SHA1 MGF1
22    OaepSha1Mgf1sha1,
23
24    /// RSA-OAEP with SHA256 Hash and SHA256 MGF1
25    OaepSha256Mgf1sha256,
26
27    /// RSA-OAEP with SHA384 Hash and SHA384 MGF1
28    OaepSha384Mgf1sha384,
29
30    /// RSA-OAEP with SHA512 Hash and SHA512 MGF1
31    OaepSha512Mgf1sha512,
32}
33
34/// An RSA private key used for decrypting ciphertext encrypted by a [`PublicEncryptingKey`].
35pub struct PrivateDecryptingKey(LcPtr<EVP_PKEY>);
36
37impl PrivateDecryptingKey {
38    fn new(evp_pkey: LcPtr<EVP_PKEY>) -> Result<Self, Unspecified> {
39        Self::validate_key(&evp_pkey)?;
40        Ok(Self(evp_pkey))
41    }
42
43    fn validate_key(key: &LcPtr<EVP_PKEY>) -> Result<(), Unspecified> {
44        if !is_rsa_key(key) {
45            return Err(Unspecified);
46        }
47        match key.key_size_bits() {
48            2048..=8192 => Ok(()),
49            _ => Err(Unspecified),
50        }
51    }
52
53    /// Generate a new RSA private key pair for use with asymmetrical encryption.
54    ///
55    /// Supports the following key sizes:
56    /// * `KeySize::Rsa2048`
57    /// * `KeySize::Rsa3072`
58    /// * `KeySize::Rsa4096`
59    /// * `KeySize::Rsa8192`
60    ///
61    /// # Errors
62    /// * `Unspecified` for any error that occurs during the generation of the RSA keypair.
63    pub fn generate(size: KeySize) -> Result<Self, Unspecified> {
64        let key = generate_rsa_key(size.bits())?;
65        Self::new(key)
66    }
67
68    /// Generate a new RSA private key pair for use with asymmetrical encryption.
69    ///
70    /// Supports the following key sizes:
71    /// * `KeySize::Rsa2048`
72    /// * `KeySize::Rsa3072`
73    /// * `KeySize::Rsa4096`
74    /// * `KeySize::Rsa8192`
75    ///
76    /// ## Deprecated
77    /// This is equivalent to `KeyPair::generate`.
78    ///
79    /// # Errors
80    /// * `Unspecified` for any error that occurs during the generation of the RSA keypair.
81    #[cfg(feature = "fips")]
82    #[deprecated]
83    pub fn generate_fips(size: KeySize) -> Result<Self, Unspecified> {
84        Self::generate(size)
85    }
86
87    /// Construct a `PrivateDecryptingKey` from the provided PKCS#8 (v1) document.
88    ///
89    /// Supports RSA key sizes between 2048 and 8192 (inclusive).
90    ///
91    /// # Errors
92    /// * `Unspecified` for any error that occurs during deserialization of this key from PKCS#8.
93    pub fn from_pkcs8(pkcs8: &[u8]) -> Result<Self, KeyRejected> {
94        let key = LcPtr::<EVP_PKEY>::parse_rfc5208_private_key(pkcs8, EVP_PKEY_RSA)?;
95        Ok(Self::new(key)?)
96    }
97
98    /// Returns a boolean indicator if this RSA key is an approved FIPS 140-3 key.
99    #[cfg(feature = "fips")]
100    #[must_use]
101    pub fn is_valid_fips_key(&self) -> bool {
102        super::key::is_valid_fips_key(&self.0)
103    }
104
105    /// Returns the RSA signature size in bytes.
106    #[must_use]
107    pub fn key_size_bytes(&self) -> usize {
108        self.0.signature_size_bytes()
109    }
110
111    /// Returns the RSA key size in bits.
112    #[must_use]
113    pub fn key_size_bits(&self) -> usize {
114        self.0.key_size_bits()
115    }
116
117    /// Retrieves the `PublicEncryptingKey` corresponding with this `PrivateDecryptingKey`.
118    #[must_use]
119    #[allow(clippy::missing_panics_doc)]
120    pub fn public_key(&self) -> PublicEncryptingKey {
121        PublicEncryptingKey::new(self.0.clone()).expect(
122            "PublicEncryptingKey key size to be supported by PrivateDecryptingKey key sizes",
123        )
124    }
125}
126
127impl Debug for PrivateDecryptingKey {
128    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
129        f.debug_tuple("PrivateDecryptingKey").finish()
130    }
131}
132
133impl AsDer<Pkcs8V1Der<'static>> for PrivateDecryptingKey {
134    fn as_der(&self) -> Result<Pkcs8V1Der<'static>, Unspecified> {
135        Ok(Pkcs8V1Der::new(
136            self.0.marshal_rfc5208_private_key(Version::V1)?,
137        ))
138    }
139}
140
141impl Clone for PrivateDecryptingKey {
142    fn clone(&self) -> Self {
143        Self(self.0.clone())
144    }
145}
146
147/// An RSA public key used for encrypting plaintext that is decrypted by a [`PrivateDecryptingKey`].
148pub struct PublicEncryptingKey(LcPtr<EVP_PKEY>);
149
150impl PublicEncryptingKey {
151    pub(crate) fn new(evp_pkey: LcPtr<EVP_PKEY>) -> Result<Self, Unspecified> {
152        Self::validate_key(&evp_pkey)?;
153        Ok(Self(evp_pkey))
154    }
155
156    fn validate_key(key: &LcPtr<EVP_PKEY>) -> Result<(), Unspecified> {
157        if !is_rsa_key(key) {
158            return Err(Unspecified);
159        }
160        match key.key_size_bits() {
161            2048..=8192 => Ok(()),
162            _ => Err(Unspecified),
163        }
164    }
165
166    /// Construct a `PublicEncryptingKey` from X.509 `SubjectPublicKeyInfo` DER encoded bytes.
167    ///
168    /// # Errors
169    /// * `Unspecified` for any error that occurs deserializing from bytes.
170    pub fn from_der(value: &[u8]) -> Result<Self, KeyRejected> {
171        Ok(Self(encoding::rfc5280::decode_public_key_der(value)?))
172    }
173
174    /// Returns the RSA signature size in bytes.
175    #[must_use]
176    pub fn key_size_bytes(&self) -> usize {
177        self.0.signature_size_bytes()
178    }
179
180    /// Returns the RSA key size in bits.
181    #[must_use]
182    pub fn key_size_bits(&self) -> usize {
183        self.0.key_size_bits()
184    }
185}
186
187impl Debug for PublicEncryptingKey {
188    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
189        f.debug_tuple("PublicEncryptingKey").finish()
190    }
191}
192
193impl Clone for PublicEncryptingKey {
194    fn clone(&self) -> Self {
195        Self(self.0.clone())
196    }
197}
198
199impl AsDer<PublicKeyX509Der<'static>> for PublicEncryptingKey {
200    /// Serialize this `PublicEncryptingKey` to a X.509 `SubjectPublicKeyInfo` structure as DER encoded bytes.
201    ///
202    /// # Errors
203    /// * `Unspecified` for any error that occurs serializing to bytes.
204    fn as_der(&self) -> Result<PublicKeyX509Der<'static>, Unspecified> {
205        encoding::rfc5280::encode_public_key_der(&self.0)
206    }
207}