/rust/registry/src/index.crates.io-6f17d22bba15001f/aws-lc-rs-1.13.0/src/rsa/encryption.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. |
2 | | // SPDX-License-Identifier: Apache-2.0 OR ISC |
3 | | |
4 | | pub(super) mod oaep; |
5 | | pub(super) mod pkcs1; |
6 | | |
7 | | use super::key::{generate_rsa_key, is_rsa_key}; |
8 | | use super::{encoding, KeySize}; |
9 | | use crate::aws_lc::{EVP_PKEY, EVP_PKEY_RSA}; |
10 | | use crate::encoding::{AsDer, Pkcs8V1Der, PublicKeyX509Der}; |
11 | | use crate::error::{KeyRejected, Unspecified}; |
12 | | use crate::pkcs8::Version; |
13 | | use crate::ptr::LcPtr; |
14 | | use core::fmt::Debug; |
15 | | |
16 | | /// RSA Encryption Algorithm Identifier |
17 | | #[allow(clippy::module_name_repetitions)] |
18 | | #[derive(Debug, Clone, Copy, PartialEq)] |
19 | | #[non_exhaustive] |
20 | | pub 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`]. |
35 | | pub struct PrivateDecryptingKey(LcPtr<EVP_PKEY>); |
36 | | |
37 | | impl PrivateDecryptingKey { |
38 | 0 | fn new(evp_pkey: LcPtr<EVP_PKEY>) -> Result<Self, Unspecified> { |
39 | 0 | Self::validate_key(&evp_pkey)?; |
40 | 0 | Ok(Self(evp_pkey)) |
41 | 0 | } |
42 | | |
43 | 0 | fn validate_key(key: &LcPtr<EVP_PKEY>) -> Result<(), Unspecified> { |
44 | 0 | if !is_rsa_key(key) { |
45 | 0 | return Err(Unspecified); |
46 | 0 | } |
47 | 0 | match key.key_size_bits() { |
48 | 0 | 2048..=8192 => Ok(()), |
49 | 0 | _ => Err(Unspecified), |
50 | | } |
51 | 0 | } |
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 | 0 | pub fn generate(size: KeySize) -> Result<Self, Unspecified> { |
64 | 0 | let key = generate_rsa_key(size.bits())?; |
65 | 0 | Self::new(key) |
66 | 0 | } |
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 | 0 | pub fn from_pkcs8(pkcs8: &[u8]) -> Result<Self, KeyRejected> { |
94 | 0 | let key = LcPtr::<EVP_PKEY>::parse_rfc5208_private_key(pkcs8, EVP_PKEY_RSA)?; |
95 | 0 | Ok(Self::new(key)?) |
96 | 0 | } |
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 | 0 | pub fn key_size_bytes(&self) -> usize { |
108 | 0 | self.0.signature_size_bytes() |
109 | 0 | } |
110 | | |
111 | | /// Returns the RSA key size in bits. |
112 | | #[must_use] |
113 | 0 | pub fn key_size_bits(&self) -> usize { |
114 | 0 | self.0.key_size_bits() |
115 | 0 | } |
116 | | |
117 | | /// Retrieves the `PublicEncryptingKey` corresponding with this `PrivateDecryptingKey`. |
118 | | #[must_use] |
119 | | #[allow(clippy::missing_panics_doc)] |
120 | 0 | pub fn public_key(&self) -> PublicEncryptingKey { |
121 | 0 | PublicEncryptingKey::new(self.0.clone()).expect( |
122 | 0 | "PublicEncryptingKey key size to be supported by PrivateDecryptingKey key sizes", |
123 | 0 | ) |
124 | 0 | } |
125 | | } |
126 | | |
127 | | impl Debug for PrivateDecryptingKey { |
128 | 0 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
129 | 0 | f.debug_tuple("PrivateDecryptingKey").finish() |
130 | 0 | } |
131 | | } |
132 | | |
133 | | impl AsDer<Pkcs8V1Der<'static>> for PrivateDecryptingKey { |
134 | 0 | fn as_der(&self) -> Result<Pkcs8V1Der<'static>, Unspecified> { |
135 | 0 | Ok(Pkcs8V1Der::new( |
136 | 0 | self.0.marshal_rfc5208_private_key(Version::V1)?, |
137 | | )) |
138 | 0 | } |
139 | | } |
140 | | |
141 | | impl Clone for PrivateDecryptingKey { |
142 | 0 | fn clone(&self) -> Self { |
143 | 0 | Self(self.0.clone()) |
144 | 0 | } |
145 | | } |
146 | | |
147 | | /// An RSA public key used for encrypting plaintext that is decrypted by a [`PrivateDecryptingKey`]. |
148 | | pub struct PublicEncryptingKey(LcPtr<EVP_PKEY>); |
149 | | |
150 | | impl PublicEncryptingKey { |
151 | 0 | pub(crate) fn new(evp_pkey: LcPtr<EVP_PKEY>) -> Result<Self, Unspecified> { |
152 | 0 | Self::validate_key(&evp_pkey)?; |
153 | 0 | Ok(Self(evp_pkey)) |
154 | 0 | } |
155 | | |
156 | 0 | fn validate_key(key: &LcPtr<EVP_PKEY>) -> Result<(), Unspecified> { |
157 | 0 | if !is_rsa_key(key) { |
158 | 0 | return Err(Unspecified); |
159 | 0 | } |
160 | 0 | match key.key_size_bits() { |
161 | 0 | 2048..=8192 => Ok(()), |
162 | 0 | _ => Err(Unspecified), |
163 | | } |
164 | 0 | } |
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 | 0 | pub fn from_der(value: &[u8]) -> Result<Self, KeyRejected> { |
171 | 0 | Ok(Self(encoding::rfc5280::decode_public_key_der(value)?)) |
172 | 0 | } |
173 | | |
174 | | /// Returns the RSA signature size in bytes. |
175 | | #[must_use] |
176 | 0 | pub fn key_size_bytes(&self) -> usize { |
177 | 0 | self.0.signature_size_bytes() |
178 | 0 | } |
179 | | |
180 | | /// Returns the RSA key size in bits. |
181 | | #[must_use] |
182 | 0 | pub fn key_size_bits(&self) -> usize { |
183 | 0 | self.0.key_size_bits() |
184 | 0 | } |
185 | | } |
186 | | |
187 | | impl Debug for PublicEncryptingKey { |
188 | 0 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
189 | 0 | f.debug_tuple("PublicEncryptingKey").finish() |
190 | 0 | } |
191 | | } |
192 | | |
193 | | impl Clone for PublicEncryptingKey { |
194 | 0 | fn clone(&self) -> Self { |
195 | 0 | Self(self.0.clone()) |
196 | 0 | } |
197 | | } |
198 | | |
199 | | impl 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 | 0 | fn as_der(&self) -> Result<PublicKeyX509Der<'static>, Unspecified> { |
205 | 0 | encoding::rfc5280::encode_public_key_der(&self.0) |
206 | 0 | } |
207 | | } |