sad_rsa/
encoding.rs

1//! PKCS#1 and PKCS#8 encoding support.
2//!
3//! Note: PKCS#1 support is achieved through a blanket impl of the
4//! `pkcs1` crate's traits for types which impl the `pkcs8` crate's traits.
5
6#![cfg(feature = "encoding")]
7
8use crate::{
9    traits::{PrivateKeyParts, PublicKeyParts},
10    RsaPrivateKey, RsaPublicKey,
11};
12use core::convert::{TryFrom, TryInto};
13use crypto_bigint::{BoxedUint, NonZero, Resize};
14use pkcs8::{
15    der::{asn1::OctetStringRef, Decode},
16    Document, EncodePrivateKey, EncodePublicKey, ObjectIdentifier, SecretDocument,
17};
18use zeroize::Zeroizing;
19
20/// ObjectID for the RSA PSS keys
21pub const ID_RSASSA_PSS: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10");
22
23// PKCS#1
24
25fn uint_from_slice(data: &[u8], bits: u32) -> pkcs1::Result<BoxedUint> {
26    BoxedUint::from_be_slice(data, bits).map_err(|_| pkcs1::Error::KeyMalformed)
27}
28
29impl pkcs1::DecodeRsaPrivateKey for RsaPrivateKey {
30    fn from_pkcs1_der(bytes: &[u8]) -> pkcs1::Result<Self> {
31        pkcs1::RsaPrivateKey::from_der(bytes)?.try_into()
32    }
33}
34
35impl pkcs1::DecodeRsaPublicKey for RsaPublicKey {
36    fn from_pkcs1_der(bytes: &[u8]) -> pkcs1::Result<Self> {
37        pkcs1::RsaPublicKey::from_der(bytes)?.try_into()
38    }
39}
40
41impl TryFrom<pkcs1::RsaPrivateKey<'_>> for RsaPrivateKey {
42    type Error = pkcs1::Error;
43
44    fn try_from(pkcs1_key: pkcs1::RsaPrivateKey<'_>) -> pkcs1::Result<RsaPrivateKey> {
45        use pkcs1::Error::KeyMalformed;
46
47        // Multi-prime RSA keys not currently supported
48        if pkcs1_key.version() != pkcs1::Version::TwoPrime {
49            return Err(pkcs1::Error::Version);
50        }
51
52        let bits = u32::try_from(pkcs1_key.modulus.as_bytes().len()).map_err(|_| KeyMalformed)? * 8;
53
54        let n = uint_from_slice(pkcs1_key.modulus.as_bytes(), bits)?;
55        let bits_e = u32::try_from(pkcs1_key.public_exponent.as_bytes().len())
56            .map_err(|_| pkcs1::Error::KeyMalformed)?
57            * 8;
58        let e = uint_from_slice(pkcs1_key.public_exponent.as_bytes(), bits_e)?;
59        let e = Option::from(e).ok_or(KeyMalformed)?;
60
61        let d = uint_from_slice(pkcs1_key.private_exponent.as_bytes(), bits)?;
62        let prime1 = uint_from_slice(pkcs1_key.prime1.as_bytes(), bits)?;
63        let prime2 = uint_from_slice(pkcs1_key.prime2.as_bytes(), bits)?;
64        let primes = vec![prime1, prime2];
65
66        RsaPrivateKey::from_components(n, e, d, primes).map_err(|_| KeyMalformed)
67    }
68}
69
70impl TryFrom<pkcs1::RsaPublicKey<'_>> for RsaPublicKey {
71    type Error = pkcs1::Error;
72
73    fn try_from(pkcs1_key: pkcs1::RsaPublicKey<'_>) -> pkcs1::Result<Self> {
74        use pkcs1::Error::KeyMalformed;
75
76        let bits = u32::try_from(pkcs1_key.modulus.as_bytes().len()).map_err(|_| KeyMalformed)? * 8;
77        let n = uint_from_slice(pkcs1_key.modulus.as_bytes(), bits)?;
78
79        let bits_e = u32::try_from(pkcs1_key.public_exponent.as_bytes().len())
80            .map_err(|_| KeyMalformed)?
81            * 8;
82        let e = uint_from_slice(pkcs1_key.public_exponent.as_bytes(), bits_e)?;
83
84        RsaPublicKey::new(n, e).map_err(|_| KeyMalformed)
85    }
86}
87
88impl pkcs1::EncodeRsaPrivateKey for RsaPrivateKey {
89    fn to_pkcs1_der(&self) -> pkcs1::Result<SecretDocument> {
90        // Check if the key is multi prime
91        if self.primes.len() > 2 {
92            return Err(pkcs1::Error::Crypto);
93        }
94
95        let modulus = self.n().to_be_bytes();
96        let public_exponent = self.e().to_be_bytes();
97        let private_exponent = Zeroizing::new(self.d().to_be_bytes());
98        let prime1 = Zeroizing::new(self.primes[0].to_be_bytes());
99        let prime2 = Zeroizing::new(self.primes[1].to_be_bytes());
100
101        let bits = self.d().bits_precision();
102
103        debug_assert!(bits >= self.primes[0].bits_vartime());
104        debug_assert!(bits >= self.primes[1].bits_vartime());
105
106        let exponent1 = Zeroizing::new(
107            (self.d()
108                % NonZero::new((&self.primes[0]).resize_unchecked(bits) - &BoxedUint::one())
109                    .unwrap())
110            .to_be_bytes(),
111        );
112        let exponent2 = Zeroizing::new(
113            (self.d()
114                % NonZero::new((&self.primes[1]).resize_unchecked(bits) - &BoxedUint::one())
115                    .unwrap())
116            .to_be_bytes(),
117        );
118        let coefficient = Zeroizing::new(
119            self.crt_coefficient()
120                .ok_or(pkcs1::Error::Crypto)?
121                .to_be_bytes(),
122        );
123
124        Ok(SecretDocument::encode_msg(&pkcs1::RsaPrivateKey {
125            modulus: pkcs1::UintRef::new(&modulus)?,
126            public_exponent: pkcs1::UintRef::new(&public_exponent)?,
127            private_exponent: pkcs1::UintRef::new(&private_exponent)?,
128            prime1: pkcs1::UintRef::new(&prime1)?,
129            prime2: pkcs1::UintRef::new(&prime2)?,
130            exponent1: pkcs1::UintRef::new(&exponent1)?,
131            exponent2: pkcs1::UintRef::new(&exponent2)?,
132            coefficient: pkcs1::UintRef::new(&coefficient)?,
133            other_prime_infos: None,
134        })?)
135    }
136}
137
138impl pkcs1::EncodeRsaPublicKey for RsaPublicKey {
139    fn to_pkcs1_der(&self) -> pkcs1::Result<Document> {
140        let modulus = self.n().to_be_bytes();
141        let public_exponent = self.e().to_be_bytes();
142
143        Ok(Document::encode_msg(&pkcs1::RsaPublicKey {
144            modulus: pkcs1::UintRef::new(&modulus)?,
145            public_exponent: pkcs1::UintRef::new(&public_exponent)?,
146        })?)
147    }
148}
149
150// PKCS#8
151
152/// Verify that the `AlgorithmIdentifier` for a key is correct.
153pub(crate) fn verify_algorithm_id(algorithm: &spki::AlgorithmIdentifierRef) -> spki::Result<()> {
154    match algorithm.oid {
155        pkcs1::ALGORITHM_OID => {
156            if algorithm.parameters_any()? != pkcs8::der::asn1::Null.into() {
157                return Err(spki::Error::KeyMalformed);
158            }
159        }
160        ID_RSASSA_PSS => {
161            if algorithm.parameters.is_some() {
162                return Err(spki::Error::KeyMalformed);
163            }
164        }
165        _ => return Err(spki::Error::OidUnknown { oid: algorithm.oid }),
166    };
167
168    Ok(())
169}
170
171impl TryFrom<pkcs8::PrivateKeyInfoRef<'_>> for RsaPrivateKey {
172    type Error = pkcs8::Error;
173
174    fn try_from(private_key_info: pkcs8::PrivateKeyInfoRef<'_>) -> pkcs8::Result<Self> {
175        verify_algorithm_id(&private_key_info.algorithm)?;
176
177        pkcs1::RsaPrivateKey::try_from(private_key_info.private_key)
178            .and_then(TryInto::try_into)
179            .map_err(pkcs1_error_to_pkcs8)
180    }
181}
182
183impl TryFrom<pkcs8::SubjectPublicKeyInfoRef<'_>> for RsaPublicKey {
184    type Error = spki::Error;
185
186    fn try_from(spki: pkcs8::SubjectPublicKeyInfoRef<'_>) -> spki::Result<Self> {
187        use spki::Error::KeyMalformed;
188
189        verify_algorithm_id(&spki.algorithm)?;
190
191        pkcs1::RsaPublicKey::try_from(spki.subject_public_key.as_bytes().ok_or(KeyMalformed)?)
192            .and_then(TryInto::try_into)
193            .map_err(pkcs1_error_to_spki)
194    }
195}
196
197impl EncodePrivateKey for RsaPrivateKey {
198    fn to_pkcs8_der(&self) -> pkcs8::Result<SecretDocument> {
199        let private_key =
200            pkcs1::EncodeRsaPrivateKey::to_pkcs1_der(self).map_err(pkcs1_error_to_pkcs8)?;
201
202        pkcs8::PrivateKeyInfoRef::new(
203            pkcs1::ALGORITHM_ID,
204            OctetStringRef::new(private_key.as_bytes())?,
205        )
206        .try_into()
207    }
208}
209
210impl EncodePublicKey for RsaPublicKey {
211    fn to_public_key_der(&self) -> spki::Result<Document> {
212        let subject_public_key =
213            pkcs1::EncodeRsaPublicKey::to_pkcs1_der(self).map_err(pkcs1_error_to_spki)?;
214
215        pkcs8::SubjectPublicKeyInfoRef {
216            algorithm: pkcs1::ALGORITHM_ID,
217            subject_public_key: pkcs8::der::asn1::BitStringRef::new(
218                0,
219                subject_public_key.as_ref(),
220            )?,
221        }
222        .try_into()
223    }
224}
225
226/// Convert `pkcs1::Result` to `pkcs8::Result`.
227fn pkcs1_error_to_pkcs8(error: pkcs1::Error) -> pkcs8::Error {
228    match error {
229        pkcs1::Error::Asn1(e) => pkcs8::Error::Asn1(e),
230        _ => pkcs8::Error::KeyMalformed,
231    }
232}
233
234/// Convert `pkcs1::Result` to `spki::Result`.
235fn pkcs1_error_to_spki(error: pkcs1::Error) -> spki::Error {
236    match error {
237        pkcs1::Error::Asn1(e) => spki::Error::Asn1(e),
238        _ => spki::Error::KeyMalformed,
239    }
240}