Skip to main content

webpki/
aws_lc_rs_algs.rs

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