Skip to main content

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, validate_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
37// https://github.com/aws/aws-lc/blob/ebaa07a207fee02bd68fe8d65f6b624afbf29394/include/openssl/evp.h#L295
38// An |EVP_PKEY| object represents a public or private RSA key. A given object may be
39// used concurrently on multiple threads by non-mutating functions, provided no
40// other thread is concurrently calling a mutating function. Unless otherwise
41// documented, functions which take a |const| pointer are non-mutating and
42// functions which take a non-|const| pointer are mutating.
43unsafe impl Send for PrivateDecryptingKey {}
44unsafe impl Sync for PrivateDecryptingKey {}
45
46impl PrivateDecryptingKey {
47    fn new(evp_pkey: LcPtr<EVP_PKEY>) -> Result<Self, KeyRejected> {
48        Self::validate_key(&evp_pkey)?;
49        Ok(Self(evp_pkey))
50    }
51
52    fn validate_key(key: &LcPtr<EVP_PKEY>) -> Result<(), KeyRejected> {
53        validate_rsa_key(key)
54    }
55
56    /// Generate a new RSA private key pair for use with asymmetrical encryption.
57    ///
58    /// Supports the following key sizes:
59    /// * `KeySize::Rsa2048`
60    /// * `KeySize::Rsa3072`
61    /// * `KeySize::Rsa4096`
62    /// * `KeySize::Rsa8192`
63    ///
64    /// # Errors
65    /// * `Unspecified` for any error that occurs during the generation of the RSA keypair.
66    pub fn generate(size: KeySize) -> Result<Self, Unspecified> {
67        let key = generate_rsa_key(size.bits())?;
68        Ok(Self::new(key)?)
69    }
70
71    /// Generate a new RSA private key pair for use with asymmetrical encryption.
72    ///
73    /// Supports the following key sizes:
74    /// * `KeySize::Rsa2048`
75    /// * `KeySize::Rsa3072`
76    /// * `KeySize::Rsa4096`
77    /// * `KeySize::Rsa8192`
78    ///
79    /// ## Deprecated
80    /// This is equivalent to `KeyPair::generate`.
81    ///
82    /// # Errors
83    /// * `Unspecified` for any error that occurs during the generation of the RSA keypair.
84    #[cfg(feature = "fips")]
85    #[deprecated]
86    pub fn generate_fips(size: KeySize) -> Result<Self, Unspecified> {
87        Self::generate(size)
88    }
89
90    /// Construct a `PrivateDecryptingKey` from the provided PKCS#8 (v1) document.
91    ///
92    /// Supports RSA key sizes between 2048 and 8192 (inclusive).
93    ///
94    /// # Errors
95    /// * `KeyRejected` if bytes do not encode an RSA private key or if the key is otherwise not
96    ///   acceptable.
97    pub fn from_pkcs8(pkcs8: &[u8]) -> Result<Self, KeyRejected> {
98        let key = LcPtr::<EVP_PKEY>::parse_rfc5208_private_key(pkcs8, EVP_PKEY_RSA)?;
99        Self::new(key)
100    }
101
102    /// Returns a boolean indicator if this RSA key is an approved FIPS 140-3 key.
103    #[cfg(feature = "fips")]
104    #[must_use]
105    pub fn is_valid_fips_key(&self) -> bool {
106        super::key::is_valid_fips_key(&self.0)
107    }
108
109    /// Returns the RSA signature size in bytes.
110    #[must_use]
111    pub fn key_size_bytes(&self) -> usize {
112        self.0.as_const().signature_size_bytes()
113    }
114
115    /// Returns the RSA key size in bits.
116    #[must_use]
117    pub fn key_size_bits(&self) -> usize {
118        self.0.as_const().key_size_bits()
119    }
120
121    /// Retrieves the `PublicEncryptingKey` corresponding with this `PrivateDecryptingKey`.
122    #[must_use]
123    #[allow(clippy::missing_panics_doc)]
124    pub fn public_key(&self) -> PublicEncryptingKey {
125        PublicEncryptingKey::new(self.0.clone()).expect(
126            "PublicEncryptingKey key size to be supported by PrivateDecryptingKey key sizes",
127        )
128    }
129}
130
131impl Debug for PrivateDecryptingKey {
132    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
133        f.debug_tuple("PrivateDecryptingKey").finish()
134    }
135}
136
137impl AsDer<Pkcs8V1Der<'static>> for PrivateDecryptingKey {
138    fn as_der(&self) -> Result<Pkcs8V1Der<'static>, Unspecified> {
139        Ok(Pkcs8V1Der::new(
140            self.0.as_const().marshal_rfc5208_private_key(Version::V1)?,
141        ))
142    }
143}
144
145impl Clone for PrivateDecryptingKey {
146    fn clone(&self) -> Self {
147        Self(self.0.clone())
148    }
149}
150
151/// An RSA public key used for encrypting plaintext that is decrypted by a [`PrivateDecryptingKey`].
152pub struct PublicEncryptingKey(LcPtr<EVP_PKEY>);
153
154// See thread-safety note on `PrivateDecryptingKey`.
155unsafe impl Send for PublicEncryptingKey {}
156unsafe impl Sync for PublicEncryptingKey {}
157
158impl PublicEncryptingKey {
159    pub(crate) fn new(evp_pkey: LcPtr<EVP_PKEY>) -> Result<Self, KeyRejected> {
160        Self::validate_key(&evp_pkey)?;
161        Ok(Self(evp_pkey))
162    }
163
164    fn validate_key(key: &LcPtr<EVP_PKEY>) -> Result<(), KeyRejected> {
165        validate_rsa_key(key)
166    }
167
168    /// Construct a `PublicEncryptingKey` from X.509 `SubjectPublicKeyInfo` DER encoded bytes.
169    ///
170    /// # Errors
171    /// * `KeyRejected` if bytes do not encode a supported RSA public key or if the key is
172    ///   otherwise not acceptable.
173    pub fn from_der(value: &[u8]) -> Result<Self, KeyRejected> {
174        let key = encoding::rfc5280::decode_public_key_der(value)?;
175        Self::new(key)
176    }
177
178    /// Returns the RSA signature size in bytes.
179    #[must_use]
180    pub fn key_size_bytes(&self) -> usize {
181        self.0.as_const().signature_size_bytes()
182    }
183
184    /// Returns the RSA key size in bits.
185    #[must_use]
186    pub fn key_size_bits(&self) -> usize {
187        self.0.as_const().key_size_bits()
188    }
189}
190
191impl Debug for PublicEncryptingKey {
192    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
193        f.debug_tuple("PublicEncryptingKey").finish()
194    }
195}
196
197impl Clone for PublicEncryptingKey {
198    fn clone(&self) -> Self {
199        Self(self.0.clone())
200    }
201}
202
203impl AsDer<PublicKeyX509Der<'static>> for PublicEncryptingKey {
204    /// Serialize this `PublicEncryptingKey` to a X.509 `SubjectPublicKeyInfo` structure as DER encoded bytes.
205    ///
206    /// # Errors
207    /// * `Unspecified` for any error that occurs serializing to bytes.
208    fn as_der(&self) -> Result<PublicKeyX509Der<'static>, Unspecified> {
209        encoding::rfc5280::encode_public_key_der(&self.0)
210    }
211}