• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Functionality related to RSA.
2 
3 use super::{KeyMaterial, KeySizeInBits, OpaqueOr, RsaExponent};
4 use crate::{km_err, tag, try_to_vec, Error, FallibleAllocExt};
5 use alloc::vec::Vec;
6 use der::{Decode, Encode};
7 use kmr_wire::keymint::{Digest, KeyParam, PaddingMode};
8 use pkcs1::RsaPrivateKey;
9 use spki::{AlgorithmIdentifier, SubjectPublicKeyInfo};
10 use zeroize::ZeroizeOnDrop;
11 
12 /// Overhead for PKCS#1 v1.5 signature padding of undigested messages.  Digested messages have
13 /// additional overhead, for the digest algorithmIdentifier required by PKCS#1.
14 pub const PKCS1_UNDIGESTED_SIGNATURE_PADDING_OVERHEAD: usize = 11;
15 
16 /// OID value for PKCS#1-encoded RSA keys held in PKCS#8 and X.509; see RFC 3447 A.1.
17 pub const X509_OID: pkcs8::ObjectIdentifier =
18     pkcs8::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.1");
19 
20 /// OID value for PKCS#1 signature with SHA-256 and RSA, see RFC 4055 s5.
21 pub const SHA256_PKCS1_SIGNATURE_OID: pkcs8::ObjectIdentifier =
22     pkcs8::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.11");
23 
24 /// An RSA key, in the form of an ASN.1 DER encoding of an PKCS#1 `RSAPrivateKey` structure,
25 /// as specified by RFC 3447 sections A.1.2 and 3.2:
26 ///
27 /// ```asn1
28 /// RSAPrivateKey ::= SEQUENCE {
29 ///     version           Version,
30 ///     modulus           INTEGER,  -- n
31 ///     publicExponent    INTEGER,  -- e
32 ///     privateExponent   INTEGER,  -- d
33 ///     prime1            INTEGER,  -- p
34 ///     prime2            INTEGER,  -- q
35 ///     exponent1         INTEGER,  -- d mod (p-1)
36 ///     exponent2         INTEGER,  -- d mod (q-1)
37 ///     coefficient       INTEGER,  -- (inverse of q) mod p
38 ///     otherPrimeInfos   OtherPrimeInfos OPTIONAL
39 /// }
40 ///
41 /// OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
42 ///
43 /// OtherPrimeInfo ::= SEQUENCE {
44 ///     prime             INTEGER,  -- ri
45 ///     exponent          INTEGER,  -- di
46 ///     coefficient       INTEGER   -- ti
47 /// }
48 /// ```
49 #[derive(Clone, PartialEq, Eq, ZeroizeOnDrop)]
50 pub struct Key(pub Vec<u8>);
51 
52 impl Key {
53     /// Return the `subjectPublicKey` that holds an ASN.1 DER-encoded `SEQUENCE`
54     /// as per RFC 3279 section 2.3.1:
55     ///     ```asn1
56     ///     RSAPublicKey ::= SEQUENCE {
57     ///        modulus            INTEGER,    -- n
58     ///        publicExponent     INTEGER  }  -- e
59     ///     ```
subject_public_key(&self) -> Result<Vec<u8>, Error>60     pub fn subject_public_key(&self) -> Result<Vec<u8>, Error> {
61         let rsa_pvt_key = RsaPrivateKey::from_der(self.0.as_slice())?;
62         let rsa_pub_key = rsa_pvt_key.public_key();
63         let mut encoded_data = Vec::<u8>::new();
64         rsa_pub_key.encode_to_vec(&mut encoded_data)?;
65         Ok(encoded_data)
66     }
67 
68     /// Size of the key in bytes.
size(&self) -> usize69     pub fn size(&self) -> usize {
70         let rsa_pvt_key = match RsaPrivateKey::from_der(self.0.as_slice()) {
71             Ok(k) => k,
72             Err(e) => {
73                 log::error!("failed to determine RSA key length: {:?}", e);
74                 return 0;
75             }
76         };
77         let len = u32::from(rsa_pvt_key.modulus.len());
78         len as usize
79     }
80 }
81 
82 impl OpaqueOr<Key> {
83     /// Encode into `buf` the public key information as an ASN.1 DER encodable
84     /// `SubjectPublicKeyInfo`, as described in RFC 5280 section 4.1.
85     ///
86     /// ```asn1
87     /// SubjectPublicKeyInfo  ::=  SEQUENCE  {
88     ///    algorithm            AlgorithmIdentifier,
89     ///    subjectPublicKey     BIT STRING  }
90     ///
91     /// AlgorithmIdentifier  ::=  SEQUENCE  {
92     ///    algorithm               OBJECT IDENTIFIER,
93     ///    parameters              ANY DEFINED BY algorithm OPTIONAL  }
94     /// ```
95     ///
96     /// For RSA keys, the contents are described in RFC 3279 section 2.3.1.
97     ///
98     /// - The `AlgorithmIdentifier` has an algorithm OID of 1.2.840.113549.1.1.1.
99     /// - The `AlgorithmIdentifier` has `NULL` parameters.
100     /// - The `subjectPublicKey` bit string holds an ASN.1 DER-encoded `SEQUENCE`:
101     ///     ```asn1
102     ///     RSAPublicKey ::= SEQUENCE {
103     ///        modulus            INTEGER,    -- n
104     ///        publicExponent     INTEGER  }  -- e
105     ///     ```
subject_public_key_info<'a>( &'a self, buf: &'a mut Vec<u8>, rsa: &dyn super::Rsa, ) -> Result<SubjectPublicKeyInfo<'a>, Error>106     pub fn subject_public_key_info<'a>(
107         &'a self,
108         buf: &'a mut Vec<u8>,
109         rsa: &dyn super::Rsa,
110     ) -> Result<SubjectPublicKeyInfo<'a>, Error> {
111         let pub_key = rsa.subject_public_key(self)?;
112         buf.try_extend_from_slice(&pub_key)?;
113         Ok(SubjectPublicKeyInfo {
114             algorithm: AlgorithmIdentifier { oid: X509_OID, parameters: Some(der::AnyRef::NULL) },
115             subject_public_key: buf,
116         })
117     }
118 }
119 
120 /// RSA decryption mode.
121 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
122 pub enum DecryptionMode {
123     NoPadding,
124     OaepPadding { msg_digest: Digest, mgf_digest: Digest },
125     Pkcs1_1_5Padding,
126 }
127 
128 impl DecryptionMode {
129     /// Determine the [`DecryptionMode`] from parameters.
new(params: &[KeyParam]) -> Result<Self, Error>130     pub fn new(params: &[KeyParam]) -> Result<Self, Error> {
131         let padding = tag::get_padding_mode(params)?;
132         match padding {
133             PaddingMode::None => Ok(DecryptionMode::NoPadding),
134             PaddingMode::RsaOaep => {
135                 let msg_digest = tag::get_digest(params)?;
136                 let mgf_digest = tag::get_mgf_digest(params)?;
137                 Ok(DecryptionMode::OaepPadding { msg_digest, mgf_digest })
138             }
139             PaddingMode::RsaPkcs115Encrypt => Ok(DecryptionMode::Pkcs1_1_5Padding),
140             _ => Err(km_err!(
141                 UnsupportedPaddingMode,
142                 "padding mode {:?} not supported for RSA decryption",
143                 padding
144             )),
145         }
146     }
147 }
148 
149 /// RSA signature mode.
150 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
151 pub enum SignMode {
152     NoPadding,
153     PssPadding(Digest),
154     Pkcs1_1_5Padding(Digest),
155 }
156 
157 impl SignMode {
158     /// Determine the [`SignMode`] from parameters.
new(params: &[KeyParam]) -> Result<Self, Error>159     pub fn new(params: &[KeyParam]) -> Result<Self, Error> {
160         let padding = tag::get_padding_mode(params)?;
161         match padding {
162             PaddingMode::None => Ok(SignMode::NoPadding),
163             PaddingMode::RsaPss => {
164                 let digest = tag::get_digest(params)?;
165                 Ok(SignMode::PssPadding(digest))
166             }
167             PaddingMode::RsaPkcs115Sign => {
168                 let digest = tag::get_digest(params)?;
169                 Ok(SignMode::Pkcs1_1_5Padding(digest))
170             }
171             _ => Err(km_err!(
172                 UnsupportedPaddingMode,
173                 "padding mode {:?} not supported for RSA signing",
174                 padding
175             )),
176         }
177     }
178 }
179 
180 /// Import an RSA key in PKCS#8 format, also returning the key size in bits and public exponent.
import_pkcs8_key(data: &[u8]) -> Result<(KeyMaterial, KeySizeInBits, RsaExponent), Error>181 pub fn import_pkcs8_key(data: &[u8]) -> Result<(KeyMaterial, KeySizeInBits, RsaExponent), Error> {
182     let key_info = pkcs8::PrivateKeyInfo::try_from(data)
183         .map_err(|_| km_err!(InvalidArgument, "failed to parse PKCS#8 RSA key"))?;
184     if key_info.algorithm.oid != X509_OID {
185         return Err(km_err!(
186             InvalidArgument,
187             "unexpected OID {:?} for PKCS#1 RSA key import",
188             key_info.algorithm.oid
189         ));
190     }
191     // For RSA, the inner private key is an ASN.1 `RSAPrivateKey`, as per PKCS#1 (RFC 3447 A.1.2).
192     import_pkcs1_key(key_info.private_key)
193 }
194 
195 /// Import an RSA key in PKCS#1 format, also returning the key size in bits and public exponent.
import_pkcs1_key( private_key: &[u8], ) -> Result<(KeyMaterial, KeySizeInBits, RsaExponent), Error>196 pub fn import_pkcs1_key(
197     private_key: &[u8],
198 ) -> Result<(KeyMaterial, KeySizeInBits, RsaExponent), Error> {
199     let key = Key(try_to_vec(private_key)?);
200 
201     // Need to parse it to find size/exponent.
202     let parsed_key = pkcs1::RsaPrivateKey::try_from(private_key)
203         .map_err(|_| km_err!(InvalidArgument, "failed to parse inner PKCS#1 key"))?;
204     let key_size = parsed_key.modulus.as_bytes().len() as u32 * 8;
205 
206     let pub_exponent_bytes = parsed_key.public_exponent.as_bytes();
207     if pub_exponent_bytes.len() > 8 {
208         return Err(km_err!(
209             InvalidArgument,
210             "public exponent of length {} too big",
211             pub_exponent_bytes.len()
212         ));
213     }
214     let offset = 8 - pub_exponent_bytes.len();
215     let mut pub_exponent_arr = [0u8; 8];
216     pub_exponent_arr[offset..].copy_from_slice(pub_exponent_bytes);
217     let pub_exponent = u64::from_be_bytes(pub_exponent_arr);
218 
219     Ok((KeyMaterial::Rsa(key.into()), KeySizeInBits(key_size), RsaExponent(pub_exponent)))
220 }
221