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::ML_DSA_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::ML_DSA_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::ML_DSA_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-256 curve and SHA-512. Deprecated.
107pub static ECDSA_P256_SHA512: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
108    public_key_alg_id: alg_id::ECDSA_P256,
109    signature_alg_id: alg_id::ECDSA_SHA512,
110    verification_alg: &signature::ECDSA_P256_SHA512_ASN1,
111    in_fips_submission: true,
112};
113
114/// ECDSA signatures using the P-384 curve and SHA-256. Deprecated.
115pub static ECDSA_P384_SHA256: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
116    public_key_alg_id: alg_id::ECDSA_P384,
117    signature_alg_id: alg_id::ECDSA_SHA256,
118    verification_alg: &signature::ECDSA_P384_SHA256_ASN1,
119    in_fips_submission: true,
120};
121
122/// ECDSA signatures using the P-384 curve and SHA-384.
123pub static ECDSA_P384_SHA384: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
124    public_key_alg_id: alg_id::ECDSA_P384,
125    signature_alg_id: alg_id::ECDSA_SHA384,
126    verification_alg: &signature::ECDSA_P384_SHA384_ASN1,
127    in_fips_submission: true,
128};
129
130/// ECDSA signatures using the P-384 curve and SHA-512. Deprecated.
131pub static ECDSA_P384_SHA512: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
132    public_key_alg_id: alg_id::ECDSA_P384,
133    signature_alg_id: alg_id::ECDSA_SHA512,
134    verification_alg: &signature::ECDSA_P384_SHA512_ASN1,
135    in_fips_submission: true,
136};
137
138/// ECDSA signatures using the P-521 curve and SHA-256.
139pub static ECDSA_P521_SHA256: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
140    public_key_alg_id: alg_id::ECDSA_P521,
141    signature_alg_id: alg_id::ECDSA_SHA256,
142    verification_alg: &signature::ECDSA_P521_SHA256_ASN1,
143    in_fips_submission: true,
144};
145
146/// ECDSA signatures using the P-521 curve and SHA-384.
147pub static ECDSA_P521_SHA384: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
148    public_key_alg_id: alg_id::ECDSA_P521,
149    signature_alg_id: alg_id::ECDSA_SHA384,
150    verification_alg: &signature::ECDSA_P521_SHA384_ASN1,
151    in_fips_submission: true,
152};
153
154/// ECDSA signatures using the P-521 curve and SHA-512.
155pub static ECDSA_P521_SHA512: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
156    public_key_alg_id: alg_id::ECDSA_P521,
157    signature_alg_id: alg_id::ECDSA_SHA512,
158    verification_alg: &signature::ECDSA_P521_SHA512_ASN1,
159    in_fips_submission: true,
160};
161
162/// RSA PKCS#1 1.5 signatures using SHA-256 for keys of 2048-8192 bits.
163pub static RSA_PKCS1_2048_8192_SHA256: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
164    public_key_alg_id: alg_id::RSA_ENCRYPTION,
165    signature_alg_id: alg_id::RSA_PKCS1_SHA256,
166    verification_alg: &signature::RSA_PKCS1_2048_8192_SHA256,
167    in_fips_submission: true,
168};
169
170/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 2048-8192 bits.
171pub static RSA_PKCS1_2048_8192_SHA384: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
172    public_key_alg_id: alg_id::RSA_ENCRYPTION,
173    signature_alg_id: alg_id::RSA_PKCS1_SHA384,
174    verification_alg: &signature::RSA_PKCS1_2048_8192_SHA384,
175    in_fips_submission: true,
176};
177
178/// RSA PKCS#1 1.5 signatures using SHA-512 for keys of 2048-8192 bits.
179pub static RSA_PKCS1_2048_8192_SHA512: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
180    public_key_alg_id: alg_id::RSA_ENCRYPTION,
181    signature_alg_id: alg_id::RSA_PKCS1_SHA512,
182    verification_alg: &signature::RSA_PKCS1_2048_8192_SHA512,
183    in_fips_submission: true,
184};
185
186/// RSA PKCS#1 1.5 signatures using SHA-256 for keys of 2048-8192 bits,
187/// with illegally absent AlgorithmIdentifier parameters.
188///
189/// RFC4055 says on sha256WithRSAEncryption and company:
190///
191/// >   When any of these four object identifiers appears within an
192/// >   AlgorithmIdentifier, the parameters MUST be NULL.  Implementations
193/// >   MUST accept the parameters being absent as well as present.
194///
195/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA256`] covers
196/// the present case.
197pub static RSA_PKCS1_2048_8192_SHA256_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
198    &AwsLcRsAlgorithm {
199        public_key_alg_id: alg_id::RSA_ENCRYPTION,
200        signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
201            "data/alg-rsa-pkcs1-sha256-absent-params.der"
202        )),
203        verification_alg: &signature::RSA_PKCS1_2048_8192_SHA256,
204        in_fips_submission: true,
205    };
206
207/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 2048-8192 bits,
208/// with illegally absent AlgorithmIdentifier parameters.
209///
210/// RFC4055 says on sha256WithRSAEncryption and company:
211///
212/// >   When any of these four object identifiers appears within an
213/// >   AlgorithmIdentifier, the parameters MUST be NULL.  Implementations
214/// >   MUST accept the parameters being absent as well as present.
215///
216/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA384`] covers
217/// the present case.
218pub static RSA_PKCS1_2048_8192_SHA384_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
219    &AwsLcRsAlgorithm {
220        public_key_alg_id: alg_id::RSA_ENCRYPTION,
221        signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
222            "data/alg-rsa-pkcs1-sha384-absent-params.der"
223        )),
224        verification_alg: &signature::RSA_PKCS1_2048_8192_SHA384,
225        in_fips_submission: true,
226    };
227
228/// RSA PKCS#1 1.5 signatures using SHA-512 for keys of 2048-8192 bits,
229/// with illegally absent AlgorithmIdentifier parameters.
230///
231/// RFC4055 says on sha256WithRSAEncryption and company:
232///
233/// >   When any of these four object identifiers appears within an
234/// >   AlgorithmIdentifier, the parameters MUST be NULL.  Implementations
235/// >   MUST accept the parameters being absent as well as present.
236///
237/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA512`] covers
238/// the present case.
239pub static RSA_PKCS1_2048_8192_SHA512_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
240    &AwsLcRsAlgorithm {
241        public_key_alg_id: alg_id::RSA_ENCRYPTION,
242        signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
243            "data/alg-rsa-pkcs1-sha512-absent-params.der"
244        )),
245        verification_alg: &signature::RSA_PKCS1_2048_8192_SHA512,
246        in_fips_submission: true,
247    };
248
249/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 3072-8192 bits.
250pub static RSA_PKCS1_3072_8192_SHA384: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
251    public_key_alg_id: alg_id::RSA_ENCRYPTION,
252    signature_alg_id: alg_id::RSA_PKCS1_SHA384,
253    verification_alg: &signature::RSA_PKCS1_3072_8192_SHA384,
254    in_fips_submission: true,
255};
256
257/// RSA PSS signatures using SHA-256 for keys of 2048-8192 bits and of
258/// type rsaEncryption; see [RFC 4055 Section 1.2].
259///
260/// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
261pub static RSA_PSS_2048_8192_SHA256_LEGACY_KEY: &dyn SignatureVerificationAlgorithm =
262    &AwsLcRsAlgorithm {
263        public_key_alg_id: alg_id::RSA_ENCRYPTION,
264        signature_alg_id: alg_id::RSA_PSS_SHA256,
265        verification_alg: &signature::RSA_PSS_2048_8192_SHA256,
266        in_fips_submission: true,
267    };
268
269/// RSA PSS signatures using SHA-384 for keys of 2048-8192 bits and of
270/// type rsaEncryption; see [RFC 4055 Section 1.2].
271///
272/// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
273pub static RSA_PSS_2048_8192_SHA384_LEGACY_KEY: &dyn SignatureVerificationAlgorithm =
274    &AwsLcRsAlgorithm {
275        public_key_alg_id: alg_id::RSA_ENCRYPTION,
276        signature_alg_id: alg_id::RSA_PSS_SHA384,
277        verification_alg: &signature::RSA_PSS_2048_8192_SHA384,
278        in_fips_submission: true,
279    };
280
281/// RSA PSS signatures using SHA-512 for keys of 2048-8192 bits and of
282/// type rsaEncryption; see [RFC 4055 Section 1.2].
283///
284/// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
285pub static RSA_PSS_2048_8192_SHA512_LEGACY_KEY: &dyn SignatureVerificationAlgorithm =
286    &AwsLcRsAlgorithm {
287        public_key_alg_id: alg_id::RSA_ENCRYPTION,
288        signature_alg_id: alg_id::RSA_PSS_SHA512,
289        verification_alg: &signature::RSA_PSS_2048_8192_SHA512,
290        in_fips_submission: true,
291    };
292
293/// ED25519 signatures according to RFC 8410
294pub static ED25519: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
295    public_key_alg_id: alg_id::ED25519,
296    signature_alg_id: alg_id::ED25519,
297    verification_alg: &signature::ED25519,
298    in_fips_submission: true,
299};
300
301#[cfg(test)]
302#[path = "."]
303mod tests {
304    use crate::error::{
305        Error, UnsupportedSignatureAlgorithmContext,
306        UnsupportedSignatureAlgorithmForPublicKeyContext,
307    };
308
309    static SUPPORTED_ALGORITHMS_IN_TESTS: &[&dyn super::SignatureVerificationAlgorithm] = &[
310        // Reasonable algorithms.
311        super::ECDSA_P256_SHA256,
312        super::ECDSA_P384_SHA384,
313        super::ECDSA_P521_SHA256,
314        super::ECDSA_P521_SHA384,
315        super::ECDSA_P521_SHA512,
316        super::ED25519,
317        super::RSA_PKCS1_2048_8192_SHA256,
318        super::RSA_PKCS1_2048_8192_SHA384,
319        super::RSA_PKCS1_2048_8192_SHA512,
320        super::RSA_PKCS1_3072_8192_SHA384,
321        super::RSA_PSS_2048_8192_SHA256_LEGACY_KEY,
322        super::RSA_PSS_2048_8192_SHA384_LEGACY_KEY,
323        super::RSA_PSS_2048_8192_SHA512_LEGACY_KEY,
324        // Algorithms deprecated because they are nonsensical combinations.
325        super::ECDSA_P256_SHA384, // Truncates digest.
326        super::ECDSA_P384_SHA256, // Digest is unnecessarily short.
327        #[cfg(all(feature = "aws-lc-rs-unstable", not(feature = "aws-lc-rs-fips")))]
328        super::ML_DSA_44,
329        #[cfg(all(feature = "aws-lc-rs-unstable", not(feature = "aws-lc-rs-fips")))]
330        super::ML_DSA_65,
331        #[cfg(all(feature = "aws-lc-rs-unstable", not(feature = "aws-lc-rs-fips")))]
332        super::ML_DSA_87,
333    ];
334
335    const OK_IF_POINT_COMPRESSION_SUPPORTED: Result<(), Error> = Ok(());
336
337    #[path = "alg_tests.rs"]
338    mod alg_tests;
339
340    fn maybe_rsa() -> Result<(), Error> {
341        Ok(())
342    }
343
344    fn unsupported_for_rsa(_sig_alg_id: &[u8], _public_key_alg_id: &[u8]) -> Error {
345        Error::UnsupportedSignatureAlgorithmForPublicKeyContext(
346            UnsupportedSignatureAlgorithmForPublicKeyContext {
347                #[cfg(feature = "alloc")]
348                signature_algorithm_id: _sig_alg_id.to_vec(),
349                #[cfg(feature = "alloc")]
350                public_key_algorithm_id: _public_key_alg_id.to_vec(),
351            },
352        )
353    }
354
355    fn invalid_rsa_signature() -> Error {
356        Error::InvalidSignatureForPublicKey
357    }
358
359    fn unsupported_for_ecdsa(_sig_alg_id: &[u8], _public_key_alg_id: &[u8]) -> Error {
360        Error::UnsupportedSignatureAlgorithmForPublicKeyContext(
361            UnsupportedSignatureAlgorithmForPublicKeyContext {
362                #[cfg(feature = "alloc")]
363                signature_algorithm_id: _sig_alg_id.to_vec(),
364                #[cfg(feature = "alloc")]
365                public_key_algorithm_id: _public_key_alg_id.to_vec(),
366            },
367        )
368    }
369
370    fn unsupported(_sig_alg_id: &[u8]) -> Error {
371        Error::UnsupportedSignatureAlgorithmContext(UnsupportedSignatureAlgorithmContext {
372            #[cfg(feature = "alloc")]
373            signature_algorithm_id: _sig_alg_id.to_vec(),
374            #[cfg(feature = "alloc")]
375            supported_algorithms: SUPPORTED_ALGORITHMS_IN_TESTS
376                .iter()
377                .map(|&alg| alg.signature_alg_id())
378                .collect(),
379        })
380    }
381}