Skip to main content

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::AsUintRef, 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::RsaPrivateKeyRef::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::RsaPublicKeyRef::from_der(bytes)?.try_into()
38    }
39}
40
41impl<U: AsUintRef> TryFrom<pkcs1::RsaPrivateKey<U>> for RsaPrivateKey {
42    type Error = pkcs1::Error;
43
44    fn try_from(pkcs1_key: pkcs1::RsaPrivateKey<U>) -> 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_uint_ref().as_bytes().len())
53            .map_err(|_| KeyMalformed)?
54            * 8;
55
56        let n = uint_from_slice(pkcs1_key.modulus.as_uint_ref().as_bytes(), bits)?;
57        let bits_e = u32::try_from(pkcs1_key.public_exponent.as_uint_ref().as_bytes().len())
58            .map_err(|_| pkcs1::Error::KeyMalformed)?
59            * 8;
60        let e = uint_from_slice(pkcs1_key.public_exponent.as_uint_ref().as_bytes(), bits_e)?;
61        let e = Option::from(e).ok_or(KeyMalformed)?;
62
63        let d = uint_from_slice(pkcs1_key.private_exponent.as_uint_ref().as_bytes(), bits)?;
64        let prime1 = uint_from_slice(pkcs1_key.prime1.as_uint_ref().as_bytes(), bits)?;
65        let prime2 = uint_from_slice(pkcs1_key.prime2.as_uint_ref().as_bytes(), bits)?;
66        let primes = vec![prime1, prime2];
67
68        RsaPrivateKey::from_components(n, e, d, primes).map_err(|_| KeyMalformed)
69    }
70}
71
72impl<U: AsUintRef> TryFrom<pkcs1::RsaPublicKey<U>> for RsaPublicKey {
73    type Error = pkcs1::Error;
74
75    fn try_from(pkcs1_key: pkcs1::RsaPublicKey<U>) -> pkcs1::Result<Self> {
76        use pkcs1::Error::KeyMalformed;
77
78        let bits = u32::try_from(pkcs1_key.modulus.as_uint_ref().as_bytes().len())
79            .map_err(|_| KeyMalformed)?
80            * 8;
81        let n = uint_from_slice(pkcs1_key.modulus.as_uint_ref().as_bytes(), bits)?;
82
83        let bits_e = u32::try_from(pkcs1_key.public_exponent.as_uint_ref().as_bytes().len())
84            .map_err(|_| KeyMalformed)?
85            * 8;
86        let e = uint_from_slice(pkcs1_key.public_exponent.as_uint_ref().as_bytes(), bits_e)?;
87
88        RsaPublicKey::new(n, e).map_err(|_| KeyMalformed)
89    }
90}
91
92impl pkcs1::EncodeRsaPrivateKey for RsaPrivateKey {
93    fn to_pkcs1_der(&self) -> pkcs1::Result<SecretDocument> {
94        // Check if the key is multi prime
95        if self.primes.len() > 2 {
96            return Err(pkcs1::Error::Crypto);
97        }
98
99        let modulus = self.n().to_be_bytes();
100        let public_exponent = self.e().to_be_bytes();
101        let private_exponent = Zeroizing::new(self.d().to_be_bytes());
102        let prime1 = Zeroizing::new(self.primes[0].to_be_bytes());
103        let prime2 = Zeroizing::new(self.primes[1].to_be_bytes());
104
105        let bits = self.d().bits_precision();
106
107        debug_assert!(bits >= self.primes[0].bits_vartime());
108        debug_assert!(bits >= self.primes[1].bits_vartime());
109
110        let exponent1 = Zeroizing::new(
111            (self.d()
112                % NonZero::new((&self.primes[0]).resize_unchecked(bits) - &BoxedUint::one())
113                    .unwrap())
114            .to_be_bytes(),
115        );
116        let exponent2 = Zeroizing::new(
117            (self.d()
118                % NonZero::new((&self.primes[1]).resize_unchecked(bits) - &BoxedUint::one())
119                    .unwrap())
120            .to_be_bytes(),
121        );
122        let coefficient = Zeroizing::new(
123            self.crt_coefficient()
124                .ok_or(pkcs1::Error::Crypto)?
125                .to_be_bytes(),
126        );
127
128        Ok(SecretDocument::encode_msg(&pkcs1::RsaPrivateKey {
129            modulus: pkcs1::UintRef::new(&modulus)?,
130            public_exponent: pkcs1::UintRef::new(&public_exponent)?,
131            private_exponent: pkcs1::UintRef::new(&private_exponent)?,
132            prime1: pkcs1::UintRef::new(&prime1)?,
133            prime2: pkcs1::UintRef::new(&prime2)?,
134            exponent1: pkcs1::UintRef::new(&exponent1)?,
135            exponent2: pkcs1::UintRef::new(&exponent2)?,
136            coefficient: pkcs1::UintRef::new(&coefficient)?,
137            other_prime_infos: None,
138        })?)
139    }
140}
141
142impl pkcs1::EncodeRsaPublicKey for RsaPublicKey {
143    fn to_pkcs1_der(&self) -> pkcs1::Result<Document> {
144        let modulus = self.n().to_be_bytes();
145        let public_exponent = self.e().to_be_bytes();
146
147        Ok(Document::encode_msg(&pkcs1::RsaPublicKeyRef {
148            modulus: pkcs1::UintRef::new(&modulus)?,
149            public_exponent: pkcs1::UintRef::new(&public_exponent)?,
150        })?)
151    }
152}
153
154// PKCS#8
155
156/// Verify that the `AlgorithmIdentifier` for a key is correct.
157pub(crate) fn verify_algorithm_id(algorithm: &spki::AlgorithmIdentifierRef) -> spki::Result<()> {
158    match algorithm.oid {
159        pkcs1::ALGORITHM_OID => {
160            if algorithm.parameters_any()? != pkcs8::der::asn1::Null.into() {
161                return Err(spki::Error::KeyMalformed);
162            }
163        }
164        ID_RSASSA_PSS => {
165            if algorithm.parameters.is_some() {
166                return Err(spki::Error::KeyMalformed);
167            }
168        }
169        _ => return Err(spki::Error::OidUnknown { oid: algorithm.oid }),
170    };
171
172    Ok(())
173}
174
175impl TryFrom<pkcs8::PrivateKeyInfoRef<'_>> for RsaPrivateKey {
176    type Error = pkcs8::Error;
177
178    fn try_from(private_key_info: pkcs8::PrivateKeyInfoRef<'_>) -> pkcs8::Result<Self> {
179        verify_algorithm_id(&private_key_info.algorithm)?;
180
181        pkcs1::RsaPrivateKeyRef::try_from(private_key_info.private_key)
182            .and_then(TryInto::try_into)
183            .map_err(pkcs1_error_to_pkcs8)
184    }
185}
186
187impl TryFrom<pkcs8::SubjectPublicKeyInfoRef<'_>> for RsaPublicKey {
188    type Error = spki::Error;
189
190    fn try_from(spki: pkcs8::SubjectPublicKeyInfoRef<'_>) -> spki::Result<Self> {
191        use spki::Error::KeyMalformed;
192
193        verify_algorithm_id(&spki.algorithm)?;
194
195        pkcs1::RsaPublicKeyRef::try_from(spki.subject_public_key.as_bytes().ok_or(KeyMalformed)?)
196            .and_then(TryInto::try_into)
197            .map_err(pkcs1_error_to_spki)
198    }
199}
200
201impl EncodePrivateKey for RsaPrivateKey {
202    fn to_pkcs8_der(&self) -> pkcs8::Result<SecretDocument> {
203        let private_key =
204            pkcs1::EncodeRsaPrivateKey::to_pkcs1_der(self).map_err(pkcs1_error_to_pkcs8)?;
205
206        pkcs8::PrivateKeyInfoRef::new(
207            pkcs1::ALGORITHM_ID,
208            OctetStringRef::new(private_key.as_bytes())?,
209        )
210        .try_into()
211    }
212}
213
214impl EncodePublicKey for RsaPublicKey {
215    fn to_public_key_der(&self) -> spki::Result<Document> {
216        let subject_public_key =
217            pkcs1::EncodeRsaPublicKey::to_pkcs1_der(self).map_err(pkcs1_error_to_spki)?;
218
219        pkcs8::SubjectPublicKeyInfoRef {
220            algorithm: pkcs1::ALGORITHM_ID,
221            subject_public_key: pkcs8::der::asn1::BitStringRef::new(
222                0,
223                subject_public_key.as_ref(),
224            )?,
225        }
226        .try_into()
227    }
228}
229
230/// Convert `pkcs1::Result` to `pkcs8::Result`.
231fn pkcs1_error_to_pkcs8(error: pkcs1::Error) -> pkcs8::Error {
232    match error {
233        pkcs1::Error::Asn1(e) => pkcs8::Error::Asn1(e),
234        _ => pkcs8::KeyError::Invalid.into(),
235    }
236}
237
238/// Convert `pkcs1::Result` to `spki::Result`.
239fn pkcs1_error_to_spki(error: pkcs1::Error) -> spki::Error {
240    match error {
241        pkcs1::Error::Asn1(e) => spki::Error::Asn1(e),
242        _ => spki::Error::KeyMalformed,
243    }
244}