webpki/
aws_lc_rs_algs.rs

1#[cfg(all(feature = "aws-lc-rs-unstable", not(feature = "aws-lc-rs-fips")))]
2use aws_lc_rs::unstable;
3use aws_lc_rs::{signature, try_fips_mode};
4use pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm, alg_id};
5
6// nb. aws-lc-rs has an API that is broadly compatible with *ring*,
7// so this is very similar to ring_algs.rs.
8
9/// A `SignatureVerificationAlgorithm` implemented using aws-lc-rs.
10#[derive(Debug)]
11struct AwsLcRsAlgorithm {
12    public_key_alg_id: AlgorithmIdentifier,
13    signature_alg_id: AlgorithmIdentifier,
14    verification_alg: &'static dyn signature::VerificationAlgorithm,
15    in_fips_submission: bool,
16}
17
18impl SignatureVerificationAlgorithm for AwsLcRsAlgorithm {
19    fn public_key_alg_id(&self) -> AlgorithmIdentifier {
20        self.public_key_alg_id
21    }
22
23    fn signature_alg_id(&self) -> AlgorithmIdentifier {
24        self.signature_alg_id
25    }
26
27    fn verify_signature(
28        &self,
29        public_key: &[u8],
30        message: &[u8],
31        signature: &[u8],
32    ) -> Result<(), InvalidSignature> {
33        if matches!(
34            self.public_key_alg_id,
35            alg_id::ECDSA_P256 | alg_id::ECDSA_P384 | alg_id::ECDSA_P521
36        ) {
37            // Restrict the allowed encodings of EC public keys.
38            //
39            // "The first octet of the OCTET STRING indicates whether the key is
40            //  compressed or uncompressed.  The uncompressed form is indicated
41            //  by 0x04 and the compressed form is indicated by either 0x02 or
42            //  0x03 (see 2.3.3 in [SEC1]).  The public key MUST be rejected if
43            //  any other value is included in the first octet."
44            // -- <https://datatracker.ietf.org/doc/html/rfc5480#section-2.2>
45            match public_key.first() {
46                Some(0x04) | Some(0x02) | Some(0x03) => {}
47                _ => return Err(InvalidSignature),
48            };
49        }
50        signature::UnparsedPublicKey::new(self.verification_alg, public_key)
51            .verify(message, signature)
52            .map_err(|_| InvalidSignature)
53    }
54
55    fn fips(&self) -> bool {
56        self.in_fips_submission && try_fips_mode().is_ok()
57    }
58}
59
60/// ML-DSA signatures using the [4, 4] matrix (security strength category 2).
61#[cfg(all(feature = "aws-lc-rs-unstable", not(feature = "aws-lc-rs-fips")))]
62pub static ML_DSA_44: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
63    public_key_alg_id: alg_id::ML_DSA_44,
64    signature_alg_id: alg_id::ML_DSA_44,
65    verification_alg: &unstable::signature::MLDSA_44,
66    // Not included in AWS-LC-FIPS 3.0 FIPS scope
67    in_fips_submission: false,
68};
69
70/// ML-DSA signatures using the [6, 5] matrix (security strength category 3).
71#[cfg(all(feature = "aws-lc-rs-unstable", not(feature = "aws-lc-rs-fips")))]
72pub static ML_DSA_65: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
73    public_key_alg_id: alg_id::ML_DSA_65,
74    signature_alg_id: alg_id::ML_DSA_65,
75    verification_alg: &unstable::signature::MLDSA_65,
76    // Not included in AWS-LC-FIPS 3.0 FIPS scope
77    in_fips_submission: false,
78};
79
80/// ML-DSA signatures using the [8. 7] matrix (security strength category 5).
81#[cfg(all(feature = "aws-lc-rs-unstable", not(feature = "aws-lc-rs-fips")))]
82pub static ML_DSA_87: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
83    public_key_alg_id: alg_id::ML_DSA_87,
84    signature_alg_id: alg_id::ML_DSA_87,
85    verification_alg: &unstable::signature::MLDSA_87,
86    // Not included in AWS-LC-FIPS 3.0 FIPS scope
87    in_fips_submission: false,
88};
89
90/// ECDSA signatures using the P-256 curve and SHA-256.
91pub static ECDSA_P256_SHA256: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
92    public_key_alg_id: alg_id::ECDSA_P256,
93    signature_alg_id: alg_id::ECDSA_SHA256,
94    verification_alg: &signature::ECDSA_P256_SHA256_ASN1,
95    in_fips_submission: true,
96};
97
98/// ECDSA signatures using the P-256 curve and SHA-384. Deprecated.
99pub static ECDSA_P256_SHA384: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
100    public_key_alg_id: alg_id::ECDSA_P256,
101    signature_alg_id: alg_id::ECDSA_SHA384,
102    verification_alg: &signature::ECDSA_P256_SHA384_ASN1,
103    in_fips_submission: true,
104};
105
106/// ECDSA signatures using the P-384 curve and SHA-256. Deprecated.
107pub static ECDSA_P384_SHA256: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
108    public_key_alg_id: alg_id::ECDSA_P384,
109    signature_alg_id: alg_id::ECDSA_SHA256,
110    verification_alg: &signature::ECDSA_P384_SHA256_ASN1,
111    in_fips_submission: true,
112};
113
114/// ECDSA signatures using the P-384 curve and SHA-384.
115pub static ECDSA_P384_SHA384: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
116    public_key_alg_id: alg_id::ECDSA_P384,
117    signature_alg_id: alg_id::ECDSA_SHA384,
118    verification_alg: &signature::ECDSA_P384_SHA384_ASN1,
119    in_fips_submission: true,
120};
121
122/// ECDSA signatures using the P-521 curve and SHA-256.
123pub static ECDSA_P521_SHA256: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
124    public_key_alg_id: alg_id::ECDSA_P521,
125    signature_alg_id: alg_id::ECDSA_SHA256,
126    verification_alg: &signature::ECDSA_P521_SHA256_ASN1,
127    in_fips_submission: true,
128};
129
130/// ECDSA signatures using the P-521 curve and SHA-384.
131pub static ECDSA_P521_SHA384: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
132    public_key_alg_id: alg_id::ECDSA_P521,
133    signature_alg_id: alg_id::ECDSA_SHA384,
134    verification_alg: &signature::ECDSA_P521_SHA384_ASN1,
135    in_fips_submission: true,
136};
137
138/// ECDSA signatures using the P-521 curve and SHA-512.
139pub static ECDSA_P521_SHA512: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
140    public_key_alg_id: alg_id::ECDSA_P521,
141    signature_alg_id: alg_id::ECDSA_SHA512,
142    verification_alg: &signature::ECDSA_P521_SHA512_ASN1,
143    in_fips_submission: true,
144};
145
146/// RSA PKCS#1 1.5 signatures using SHA-256 for keys of 2048-8192 bits.
147pub static RSA_PKCS1_2048_8192_SHA256: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
148    public_key_alg_id: alg_id::RSA_ENCRYPTION,
149    signature_alg_id: alg_id::RSA_PKCS1_SHA256,
150    verification_alg: &signature::RSA_PKCS1_2048_8192_SHA256,
151    in_fips_submission: true,
152};
153
154/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 2048-8192 bits.
155pub static RSA_PKCS1_2048_8192_SHA384: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
156    public_key_alg_id: alg_id::RSA_ENCRYPTION,
157    signature_alg_id: alg_id::RSA_PKCS1_SHA384,
158    verification_alg: &signature::RSA_PKCS1_2048_8192_SHA384,
159    in_fips_submission: true,
160};
161
162/// RSA PKCS#1 1.5 signatures using SHA-512 for keys of 2048-8192 bits.
163pub static RSA_PKCS1_2048_8192_SHA512: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
164    public_key_alg_id: alg_id::RSA_ENCRYPTION,
165    signature_alg_id: alg_id::RSA_PKCS1_SHA512,
166    verification_alg: &signature::RSA_PKCS1_2048_8192_SHA512,
167    in_fips_submission: true,
168};
169
170/// RSA PKCS#1 1.5 signatures using SHA-256 for keys of 2048-8192 bits,
171/// with illegally absent AlgorithmIdentifier parameters.
172///
173/// RFC4055 says on sha256WithRSAEncryption and company:
174///
175/// >   When any of these four object identifiers appears within an
176/// >   AlgorithmIdentifier, the parameters MUST be NULL.  Implementations
177/// >   MUST accept the parameters being absent as well as present.
178///
179/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA256`] covers
180/// the present case.
181pub static RSA_PKCS1_2048_8192_SHA256_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
182    &AwsLcRsAlgorithm {
183        public_key_alg_id: alg_id::RSA_ENCRYPTION,
184        signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
185            "data/alg-rsa-pkcs1-sha256-absent-params.der"
186        )),
187        verification_alg: &signature::RSA_PKCS1_2048_8192_SHA256,
188        in_fips_submission: true,
189    };
190
191/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 2048-8192 bits,
192/// with illegally absent AlgorithmIdentifier parameters.
193///
194/// RFC4055 says on sha256WithRSAEncryption and company:
195///
196/// >   When any of these four object identifiers appears within an
197/// >   AlgorithmIdentifier, the parameters MUST be NULL.  Implementations
198/// >   MUST accept the parameters being absent as well as present.
199///
200/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA384`] covers
201/// the present case.
202pub static RSA_PKCS1_2048_8192_SHA384_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
203    &AwsLcRsAlgorithm {
204        public_key_alg_id: alg_id::RSA_ENCRYPTION,
205        signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
206            "data/alg-rsa-pkcs1-sha384-absent-params.der"
207        )),
208        verification_alg: &signature::RSA_PKCS1_2048_8192_SHA384,
209        in_fips_submission: true,
210    };
211
212/// RSA PKCS#1 1.5 signatures using SHA-512 for keys of 2048-8192 bits,
213/// with illegally absent AlgorithmIdentifier parameters.
214///
215/// RFC4055 says on sha256WithRSAEncryption and company:
216///
217/// >   When any of these four object identifiers appears within an
218/// >   AlgorithmIdentifier, the parameters MUST be NULL.  Implementations
219/// >   MUST accept the parameters being absent as well as present.
220///
221/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA512`] covers
222/// the present case.
223pub static RSA_PKCS1_2048_8192_SHA512_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
224    &AwsLcRsAlgorithm {
225        public_key_alg_id: alg_id::RSA_ENCRYPTION,
226        signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
227            "data/alg-rsa-pkcs1-sha512-absent-params.der"
228        )),
229        verification_alg: &signature::RSA_PKCS1_2048_8192_SHA512,
230        in_fips_submission: true,
231    };
232
233/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 3072-8192 bits.
234pub static RSA_PKCS1_3072_8192_SHA384: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
235    public_key_alg_id: alg_id::RSA_ENCRYPTION,
236    signature_alg_id: alg_id::RSA_PKCS1_SHA384,
237    verification_alg: &signature::RSA_PKCS1_3072_8192_SHA384,
238    in_fips_submission: true,
239};
240
241/// RSA PSS signatures using SHA-256 for keys of 2048-8192 bits and of
242/// type rsaEncryption; see [RFC 4055 Section 1.2].
243///
244/// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
245pub static RSA_PSS_2048_8192_SHA256_LEGACY_KEY: &dyn SignatureVerificationAlgorithm =
246    &AwsLcRsAlgorithm {
247        public_key_alg_id: alg_id::RSA_ENCRYPTION,
248        signature_alg_id: alg_id::RSA_PSS_SHA256,
249        verification_alg: &signature::RSA_PSS_2048_8192_SHA256,
250        in_fips_submission: true,
251    };
252
253/// RSA PSS signatures using SHA-384 for keys of 2048-8192 bits and of
254/// type rsaEncryption; see [RFC 4055 Section 1.2].
255///
256/// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
257pub static RSA_PSS_2048_8192_SHA384_LEGACY_KEY: &dyn SignatureVerificationAlgorithm =
258    &AwsLcRsAlgorithm {
259        public_key_alg_id: alg_id::RSA_ENCRYPTION,
260        signature_alg_id: alg_id::RSA_PSS_SHA384,
261        verification_alg: &signature::RSA_PSS_2048_8192_SHA384,
262        in_fips_submission: true,
263    };
264
265/// RSA PSS signatures using SHA-512 for keys of 2048-8192 bits and of
266/// type rsaEncryption; see [RFC 4055 Section 1.2].
267///
268/// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
269pub static RSA_PSS_2048_8192_SHA512_LEGACY_KEY: &dyn SignatureVerificationAlgorithm =
270    &AwsLcRsAlgorithm {
271        public_key_alg_id: alg_id::RSA_ENCRYPTION,
272        signature_alg_id: alg_id::RSA_PSS_SHA512,
273        verification_alg: &signature::RSA_PSS_2048_8192_SHA512,
274        in_fips_submission: true,
275    };
276
277/// ED25519 signatures according to RFC 8410
278pub static ED25519: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
279    public_key_alg_id: alg_id::ED25519,
280    signature_alg_id: alg_id::ED25519,
281    verification_alg: &signature::ED25519,
282    in_fips_submission: true,
283};
284
285#[cfg(test)]
286#[path = "."]
287mod tests {
288    use crate::error::{
289        Error, UnsupportedSignatureAlgorithmContext,
290        UnsupportedSignatureAlgorithmForPublicKeyContext,
291    };
292
293    static SUPPORTED_ALGORITHMS_IN_TESTS: &[&dyn super::SignatureVerificationAlgorithm] = &[
294        // Reasonable algorithms.
295        super::ECDSA_P256_SHA256,
296        super::ECDSA_P384_SHA384,
297        super::ECDSA_P521_SHA256,
298        super::ECDSA_P521_SHA384,
299        super::ECDSA_P521_SHA512,
300        super::ED25519,
301        super::RSA_PKCS1_2048_8192_SHA256,
302        super::RSA_PKCS1_2048_8192_SHA384,
303        super::RSA_PKCS1_2048_8192_SHA512,
304        super::RSA_PKCS1_3072_8192_SHA384,
305        super::RSA_PSS_2048_8192_SHA256_LEGACY_KEY,
306        super::RSA_PSS_2048_8192_SHA384_LEGACY_KEY,
307        super::RSA_PSS_2048_8192_SHA512_LEGACY_KEY,
308        // Algorithms deprecated because they are nonsensical combinations.
309        super::ECDSA_P256_SHA384, // Truncates digest.
310        super::ECDSA_P384_SHA256, // Digest is unnecessarily short.
311        #[cfg(all(feature = "aws-lc-rs-unstable", not(feature = "aws-lc-rs-fips")))]
312        super::ML_DSA_44,
313        #[cfg(all(feature = "aws-lc-rs-unstable", not(feature = "aws-lc-rs-fips")))]
314        super::ML_DSA_65,
315        #[cfg(all(feature = "aws-lc-rs-unstable", not(feature = "aws-lc-rs-fips")))]
316        super::ML_DSA_87,
317    ];
318
319    const OK_IF_POINT_COMPRESSION_SUPPORTED: Result<(), Error> = Ok(());
320
321    #[path = "alg_tests.rs"]
322    mod alg_tests;
323
324    fn maybe_rsa() -> Result<(), Error> {
325        Ok(())
326    }
327
328    fn unsupported_for_rsa(_sig_alg_id: &[u8], _public_key_alg_id: &[u8]) -> Error {
329        Error::UnsupportedSignatureAlgorithmForPublicKeyContext(
330            UnsupportedSignatureAlgorithmForPublicKeyContext {
331                #[cfg(feature = "alloc")]
332                signature_algorithm_id: _sig_alg_id.to_vec(),
333                #[cfg(feature = "alloc")]
334                public_key_algorithm_id: _public_key_alg_id.to_vec(),
335            },
336        )
337    }
338
339    fn invalid_rsa_signature() -> Error {
340        Error::InvalidSignatureForPublicKey
341    }
342
343    fn unsupported_for_ecdsa(_sig_alg_id: &[u8], _public_key_alg_id: &[u8]) -> Error {
344        Error::UnsupportedSignatureAlgorithmForPublicKeyContext(
345            UnsupportedSignatureAlgorithmForPublicKeyContext {
346                #[cfg(feature = "alloc")]
347                signature_algorithm_id: _sig_alg_id.to_vec(),
348                #[cfg(feature = "alloc")]
349                public_key_algorithm_id: _public_key_alg_id.to_vec(),
350            },
351        )
352    }
353
354    fn unsupported(_sig_alg_id: &[u8]) -> Error {
355        Error::UnsupportedSignatureAlgorithmContext(UnsupportedSignatureAlgorithmContext {
356            #[cfg(feature = "alloc")]
357            signature_algorithm_id: _sig_alg_id.to_vec(),
358            #[cfg(feature = "alloc")]
359            supported_algorithms: SUPPORTED_ALGORITHMS_IN_TESTS
360                .iter()
361                .map(|&alg| alg.signature_alg_id())
362                .collect(),
363        })
364    }
365}