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 `PrivateDecryptingKey::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        since = "1.12.3",
87        note = "Equivalent to `PrivateDecryptingKey::generate`; use that instead."
88    )]
89    pub fn generate_fips(size: KeySize) -> Result<Self, Unspecified> {
90        Self::generate(size)
91    }
92
93    /// Construct a `PrivateDecryptingKey` from the provided PKCS#8 (v1) document.
94    ///
95    /// Supports RSA key sizes between 2048 and 8192 (inclusive).
96    ///
97    /// # Errors
98    /// * `KeyRejected` if bytes do not encode an RSA private key or if the key is otherwise not
99    ///   acceptable.
100    pub fn from_pkcs8(pkcs8: &[u8]) -> Result<Self, KeyRejected> {
101        let key = LcPtr::<EVP_PKEY>::parse_rfc5208_private_key(pkcs8, EVP_PKEY_RSA)?;
102        Self::new(key)
103    }
104
105    /// Returns a boolean indicator if this RSA key is an approved FIPS 140-3 key.
106    #[cfg(feature = "fips")]
107    #[must_use]
108    pub fn is_valid_fips_key(&self) -> bool {
109        super::key::is_valid_fips_key(&self.0)
110    }
111
112    /// Returns the RSA signature size in bytes.
113    #[must_use]
114    pub fn key_size_bytes(&self) -> usize {
115        self.0.as_const().signature_size_bytes()
116    }
117
118    /// Returns the RSA key size in bits.
119    #[must_use]
120    pub fn key_size_bits(&self) -> usize {
121        self.0.as_const().key_size_bits()
122    }
123
124    /// Retrieves the `PublicEncryptingKey` corresponding with this `PrivateDecryptingKey`.
125    #[must_use]
126    #[allow(clippy::missing_panics_doc)]
127    pub fn public_key(&self) -> PublicEncryptingKey {
128        PublicEncryptingKey::new(self.0.clone()).expect(
129            "PublicEncryptingKey key size to be supported by PrivateDecryptingKey key sizes",
130        )
131    }
132}
133
134impl Debug for PrivateDecryptingKey {
135    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
136        f.debug_tuple("PrivateDecryptingKey").finish()
137    }
138}
139
140impl AsDer<Pkcs8V1Der<'static>> for PrivateDecryptingKey {
141    fn as_der(&self) -> Result<Pkcs8V1Der<'static>, Unspecified> {
142        Ok(Pkcs8V1Der::new(
143            self.0.as_const().marshal_rfc5208_private_key(Version::V1)?,
144        ))
145    }
146}
147
148impl Clone for PrivateDecryptingKey {
149    fn clone(&self) -> Self {
150        Self(self.0.clone())
151    }
152}
153
154/// An RSA public key used for encrypting plaintext that is decrypted by a [`PrivateDecryptingKey`].
155pub struct PublicEncryptingKey(LcPtr<EVP_PKEY>);
156
157// See thread-safety note on `PrivateDecryptingKey`.
158unsafe impl Send for PublicEncryptingKey {}
159unsafe impl Sync for PublicEncryptingKey {}
160
161impl PublicEncryptingKey {
162    pub(crate) fn new(evp_pkey: LcPtr<EVP_PKEY>) -> Result<Self, KeyRejected> {
163        Self::validate_key(&evp_pkey)?;
164        Ok(Self(evp_pkey))
165    }
166
167    fn validate_key(key: &LcPtr<EVP_PKEY>) -> Result<(), KeyRejected> {
168        validate_rsa_key(key)
169    }
170
171    /// Construct a `PublicEncryptingKey` from X.509 `SubjectPublicKeyInfo` DER encoded bytes.
172    ///
173    /// # Errors
174    /// * `KeyRejected` if bytes do not encode a supported RSA public key or if the key is
175    ///   otherwise not acceptable.
176    pub fn from_der(value: &[u8]) -> Result<Self, KeyRejected> {
177        let key = encoding::rfc5280::decode_public_key_der(value)?;
178        Self::new(key)
179    }
180
181    /// Returns the RSA signature size in bytes.
182    #[must_use]
183    pub fn key_size_bytes(&self) -> usize {
184        self.0.as_const().signature_size_bytes()
185    }
186
187    /// Returns the RSA key size in bits.
188    #[must_use]
189    pub fn key_size_bits(&self) -> usize {
190        self.0.as_const().key_size_bits()
191    }
192}
193
194impl Debug for PublicEncryptingKey {
195    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
196        f.debug_tuple("PublicEncryptingKey").finish()
197    }
198}
199
200impl Clone for PublicEncryptingKey {
201    fn clone(&self) -> Self {
202        Self(self.0.clone())
203    }
204}
205
206impl AsDer<PublicKeyX509Der<'static>> for PublicEncryptingKey {
207    /// Serialize this `PublicEncryptingKey` to a X.509 `SubjectPublicKeyInfo` structure as DER encoded bytes.
208    ///
209    /// # Errors
210    /// * `Unspecified` for any error that occurs serializing to bytes.
211    fn as_der(&self) -> Result<PublicKeyX509Der<'static>, Unspecified> {
212        encoding::rfc5280::encode_public_key_der(&self.0)
213    }
214}