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/// ECDSA signatures using the P-256 curve and SHA-256.
58pub static ECDSA_P256_SHA256: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
59    public_key_alg_id: alg_id::ECDSA_P256,
60    signature_alg_id: alg_id::ECDSA_SHA256,
61    verification_alg: &signature::ECDSA_P256_SHA256_ASN1,
62};
63
64/// ECDSA signatures using the P-256 curve and SHA-384. Deprecated.
65pub static ECDSA_P256_SHA384: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
66    public_key_alg_id: alg_id::ECDSA_P256,
67    signature_alg_id: alg_id::ECDSA_SHA384,
68    verification_alg: &signature::ECDSA_P256_SHA384_ASN1,
69};
70
71/// ECDSA signatures using the P-384 curve and SHA-256. Deprecated.
72pub static ECDSA_P384_SHA256: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
73    public_key_alg_id: alg_id::ECDSA_P384,
74    signature_alg_id: alg_id::ECDSA_SHA256,
75    verification_alg: &signature::ECDSA_P384_SHA256_ASN1,
76};
77
78/// ECDSA signatures using the P-384 curve and SHA-384.
79pub static ECDSA_P384_SHA384: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
80    public_key_alg_id: alg_id::ECDSA_P384,
81    signature_alg_id: alg_id::ECDSA_SHA384,
82    verification_alg: &signature::ECDSA_P384_SHA384_ASN1,
83};
84
85/// ECDSA signatures using the P-521 curve and SHA-256.
86pub static ECDSA_P521_SHA256: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
87    public_key_alg_id: alg_id::ECDSA_P521,
88    signature_alg_id: alg_id::ECDSA_SHA256,
89    verification_alg: &signature::ECDSA_P521_SHA256_ASN1,
90};
91
92/// ECDSA signatures using the P-521 curve and SHA-384.
93pub static ECDSA_P521_SHA384: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
94    public_key_alg_id: alg_id::ECDSA_P521,
95    signature_alg_id: alg_id::ECDSA_SHA384,
96    verification_alg: &signature::ECDSA_P521_SHA384_ASN1,
97};
98
99/// ECDSA signatures using the P-521 curve and SHA-512.
100pub static ECDSA_P521_SHA512: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
101    public_key_alg_id: alg_id::ECDSA_P521,
102    signature_alg_id: alg_id::ECDSA_SHA512,
103    verification_alg: &signature::ECDSA_P521_SHA512_ASN1,
104};
105
106/// RSA PKCS#1 1.5 signatures using SHA-256 for keys of 2048-8192 bits.
107pub static RSA_PKCS1_2048_8192_SHA256: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
108    public_key_alg_id: alg_id::RSA_ENCRYPTION,
109    signature_alg_id: alg_id::RSA_PKCS1_SHA256,
110    verification_alg: &signature::RSA_PKCS1_2048_8192_SHA256,
111};
112
113/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 2048-8192 bits.
114pub static RSA_PKCS1_2048_8192_SHA384: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
115    public_key_alg_id: alg_id::RSA_ENCRYPTION,
116    signature_alg_id: alg_id::RSA_PKCS1_SHA384,
117    verification_alg: &signature::RSA_PKCS1_2048_8192_SHA384,
118};
119
120/// RSA PKCS#1 1.5 signatures using SHA-512 for keys of 2048-8192 bits.
121pub static RSA_PKCS1_2048_8192_SHA512: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
122    public_key_alg_id: alg_id::RSA_ENCRYPTION,
123    signature_alg_id: alg_id::RSA_PKCS1_SHA512,
124    verification_alg: &signature::RSA_PKCS1_2048_8192_SHA512,
125};
126
127/// RSA PKCS#1 1.5 signatures using SHA-256 for keys of 2048-8192 bits,
128/// with illegally absent AlgorithmIdentifier parameters.
129///
130/// RFC4055 says on sha256WithRSAEncryption and company:
131///
132/// >   When any of these four object identifiers appears within an
133/// >   AlgorithmIdentifier, the parameters MUST be NULL.  Implementations
134/// >   MUST accept the parameters being absent as well as present.
135///
136/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA256`] covers
137/// the present case.
138pub static RSA_PKCS1_2048_8192_SHA256_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
139    &AwsLcRsAlgorithm {
140        public_key_alg_id: alg_id::RSA_ENCRYPTION,
141        signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
142            "data/alg-rsa-pkcs1-sha256-absent-params.der"
143        )),
144        verification_alg: &signature::RSA_PKCS1_2048_8192_SHA256,
145    };
146
147/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 2048-8192 bits,
148/// with illegally absent AlgorithmIdentifier parameters.
149///
150/// RFC4055 says on sha256WithRSAEncryption and company:
151///
152/// >   When any of these four object identifiers appears within an
153/// >   AlgorithmIdentifier, the parameters MUST be NULL.  Implementations
154/// >   MUST accept the parameters being absent as well as present.
155///
156/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA384`] covers
157/// the present case.
158pub static RSA_PKCS1_2048_8192_SHA384_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
159    &AwsLcRsAlgorithm {
160        public_key_alg_id: alg_id::RSA_ENCRYPTION,
161        signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
162            "data/alg-rsa-pkcs1-sha384-absent-params.der"
163        )),
164        verification_alg: &signature::RSA_PKCS1_2048_8192_SHA384,
165    };
166
167/// RSA PKCS#1 1.5 signatures using SHA-512 for keys of 2048-8192 bits,
168/// with illegally absent AlgorithmIdentifier parameters.
169///
170/// RFC4055 says on sha256WithRSAEncryption and company:
171///
172/// >   When any of these four object identifiers appears within an
173/// >   AlgorithmIdentifier, the parameters MUST be NULL.  Implementations
174/// >   MUST accept the parameters being absent as well as present.
175///
176/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA512`] covers
177/// the present case.
178pub static RSA_PKCS1_2048_8192_SHA512_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
179    &AwsLcRsAlgorithm {
180        public_key_alg_id: alg_id::RSA_ENCRYPTION,
181        signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
182            "data/alg-rsa-pkcs1-sha512-absent-params.der"
183        )),
184        verification_alg: &signature::RSA_PKCS1_2048_8192_SHA512,
185    };
186
187/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 3072-8192 bits.
188pub static RSA_PKCS1_3072_8192_SHA384: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
189    public_key_alg_id: alg_id::RSA_ENCRYPTION,
190    signature_alg_id: alg_id::RSA_PKCS1_SHA384,
191    verification_alg: &signature::RSA_PKCS1_3072_8192_SHA384,
192};
193
194/// RSA PSS signatures using SHA-256 for keys of 2048-8192 bits and of
195/// type rsaEncryption; see [RFC 4055 Section 1.2].
196///
197/// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
198pub static RSA_PSS_2048_8192_SHA256_LEGACY_KEY: &dyn SignatureVerificationAlgorithm =
199    &AwsLcRsAlgorithm {
200        public_key_alg_id: alg_id::RSA_ENCRYPTION,
201        signature_alg_id: alg_id::RSA_PSS_SHA256,
202        verification_alg: &signature::RSA_PSS_2048_8192_SHA256,
203    };
204
205/// RSA PSS signatures using SHA-384 for keys of 2048-8192 bits and of
206/// type rsaEncryption; see [RFC 4055 Section 1.2].
207///
208/// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
209pub static RSA_PSS_2048_8192_SHA384_LEGACY_KEY: &dyn SignatureVerificationAlgorithm =
210    &AwsLcRsAlgorithm {
211        public_key_alg_id: alg_id::RSA_ENCRYPTION,
212        signature_alg_id: alg_id::RSA_PSS_SHA384,
213        verification_alg: &signature::RSA_PSS_2048_8192_SHA384,
214    };
215
216/// RSA PSS signatures using SHA-512 for keys of 2048-8192 bits and of
217/// type rsaEncryption; see [RFC 4055 Section 1.2].
218///
219/// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
220pub static RSA_PSS_2048_8192_SHA512_LEGACY_KEY: &dyn SignatureVerificationAlgorithm =
221    &AwsLcRsAlgorithm {
222        public_key_alg_id: alg_id::RSA_ENCRYPTION,
223        signature_alg_id: alg_id::RSA_PSS_SHA512,
224        verification_alg: &signature::RSA_PSS_2048_8192_SHA512,
225    };
226
227/// ED25519 signatures according to RFC 8410
228pub static ED25519: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
229    public_key_alg_id: alg_id::ED25519,
230    signature_alg_id: alg_id::ED25519,
231    verification_alg: &signature::ED25519,
232};
233
234#[cfg(test)]
235#[path = "."]
236mod tests {
237    use crate::Error;
238
239    static SUPPORTED_ALGORITHMS_IN_TESTS: &[&dyn super::SignatureVerificationAlgorithm] = &[
240        // Reasonable algorithms.
241        super::ECDSA_P256_SHA256,
242        super::ECDSA_P384_SHA384,
243        super::ECDSA_P521_SHA256,
244        super::ECDSA_P521_SHA384,
245        super::ECDSA_P521_SHA512,
246        super::ED25519,
247        super::RSA_PKCS1_2048_8192_SHA256,
248        super::RSA_PKCS1_2048_8192_SHA384,
249        super::RSA_PKCS1_2048_8192_SHA512,
250        super::RSA_PKCS1_3072_8192_SHA384,
251        super::RSA_PSS_2048_8192_SHA256_LEGACY_KEY,
252        super::RSA_PSS_2048_8192_SHA384_LEGACY_KEY,
253        super::RSA_PSS_2048_8192_SHA512_LEGACY_KEY,
254        // Algorithms deprecated because they are nonsensical combinations.
255        super::ECDSA_P256_SHA384, // Truncates digest.
256        super::ECDSA_P384_SHA256, // Digest is unnecessarily short.
257    ];
258
259    const UNSUPPORTED_SIGNATURE_ALGORITHM_FOR_RSA_KEY: Error =
260        Error::UnsupportedSignatureAlgorithmForPublicKey;
261
262    const UNSUPPORTED_ECDSA_SHA512_SIGNATURE: Error =
263        Error::UnsupportedSignatureAlgorithmForPublicKey;
264
265    const INVALID_SIGNATURE_FOR_RSA_KEY: Error = Error::InvalidSignatureForPublicKey;
266
267    const OK_IF_RSA_AVAILABLE: Result<(), Error> = Ok(());
268    const OK_IF_POINT_COMPRESSION_SUPPORTED: Result<(), Error> = Ok(());
269
270    #[path = "alg_tests.rs"]
271    mod alg_tests;
272}