webpki/
ring_algs.rs

1// Copyright 2015 Brian Smith.
2//
3// Permission to use, copy, modify, and/or distribute this software for any
4// purpose with or without fee is hereby granted, provided that the above
5// copyright notice and this permission notice appear in all copies.
6//
7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
10// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15use pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm, alg_id};
16use ring::signature;
17
18/// A `SignatureVerificationAlgorithm` implemented using *ring*.
19#[derive(Debug)]
20struct RingAlgorithm {
21    public_key_alg_id: AlgorithmIdentifier,
22    signature_alg_id: AlgorithmIdentifier,
23    verification_alg: &'static dyn signature::VerificationAlgorithm,
24}
25
26impl SignatureVerificationAlgorithm for RingAlgorithm {
27    fn public_key_alg_id(&self) -> AlgorithmIdentifier {
28        self.public_key_alg_id
29    }
30
31    fn signature_alg_id(&self) -> AlgorithmIdentifier {
32        self.signature_alg_id
33    }
34
35    fn verify_signature(
36        &self,
37        public_key: &[u8],
38        message: &[u8],
39        signature: &[u8],
40    ) -> Result<(), InvalidSignature> {
41        signature::UnparsedPublicKey::new(self.verification_alg, public_key)
42            .verify(message, signature)
43            .map_err(|_| InvalidSignature)
44    }
45}
46
47/// ECDSA signatures using the P-256 curve and SHA-256.
48pub static ECDSA_P256_SHA256: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
49    public_key_alg_id: alg_id::ECDSA_P256,
50    signature_alg_id: alg_id::ECDSA_SHA256,
51    verification_alg: &signature::ECDSA_P256_SHA256_ASN1,
52};
53
54/// ECDSA signatures using the P-256 curve and SHA-384. Deprecated.
55pub static ECDSA_P256_SHA384: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
56    public_key_alg_id: alg_id::ECDSA_P256,
57    signature_alg_id: alg_id::ECDSA_SHA384,
58    verification_alg: &signature::ECDSA_P256_SHA384_ASN1,
59};
60
61/// ECDSA signatures using the P-384 curve and SHA-256. Deprecated.
62pub static ECDSA_P384_SHA256: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
63    public_key_alg_id: alg_id::ECDSA_P384,
64    signature_alg_id: alg_id::ECDSA_SHA256,
65    verification_alg: &signature::ECDSA_P384_SHA256_ASN1,
66};
67
68/// ECDSA signatures using the P-384 curve and SHA-384.
69pub static ECDSA_P384_SHA384: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
70    public_key_alg_id: alg_id::ECDSA_P384,
71    signature_alg_id: alg_id::ECDSA_SHA384,
72    verification_alg: &signature::ECDSA_P384_SHA384_ASN1,
73};
74
75/// RSA PKCS#1 1.5 signatures using SHA-256 for keys of 2048-8192 bits.
76#[cfg(feature = "alloc")]
77pub static RSA_PKCS1_2048_8192_SHA256: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
78    public_key_alg_id: alg_id::RSA_ENCRYPTION,
79    signature_alg_id: alg_id::RSA_PKCS1_SHA256,
80    verification_alg: &signature::RSA_PKCS1_2048_8192_SHA256,
81};
82
83/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 2048-8192 bits.
84#[cfg(feature = "alloc")]
85pub static RSA_PKCS1_2048_8192_SHA384: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
86    public_key_alg_id: alg_id::RSA_ENCRYPTION,
87    signature_alg_id: alg_id::RSA_PKCS1_SHA384,
88    verification_alg: &signature::RSA_PKCS1_2048_8192_SHA384,
89};
90
91/// RSA PKCS#1 1.5 signatures using SHA-512 for keys of 2048-8192 bits.
92#[cfg(feature = "alloc")]
93pub static RSA_PKCS1_2048_8192_SHA512: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
94    public_key_alg_id: alg_id::RSA_ENCRYPTION,
95    signature_alg_id: alg_id::RSA_PKCS1_SHA512,
96    verification_alg: &signature::RSA_PKCS1_2048_8192_SHA512,
97};
98
99/// RSA PKCS#1 1.5 signatures using SHA-256 for keys of 2048-8192 bits,
100/// with illegally absent AlgorithmIdentifier parameters.
101///
102/// RFC4055 says on sha256WithRSAEncryption and company:
103///
104/// >   When any of these four object identifiers appears within an
105/// >   AlgorithmIdentifier, the parameters MUST be NULL.  Implementations
106/// >   MUST accept the parameters being absent as well as present.
107///
108/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA256`] covers
109/// the present case.
110#[cfg(feature = "alloc")]
111pub static RSA_PKCS1_2048_8192_SHA256_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
112    &RingAlgorithm {
113        public_key_alg_id: alg_id::RSA_ENCRYPTION,
114        signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
115            "data/alg-rsa-pkcs1-sha256-absent-params.der"
116        )),
117        verification_alg: &signature::RSA_PKCS1_2048_8192_SHA256,
118    };
119
120/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 2048-8192 bits,
121/// with illegally absent AlgorithmIdentifier parameters.
122///
123/// RFC4055 says on sha256WithRSAEncryption and company:
124///
125/// >   When any of these four object identifiers appears within an
126/// >   AlgorithmIdentifier, the parameters MUST be NULL.  Implementations
127/// >   MUST accept the parameters being absent as well as present.
128///
129/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA384`] covers
130/// the present case.
131#[cfg(feature = "alloc")]
132pub static RSA_PKCS1_2048_8192_SHA384_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
133    &RingAlgorithm {
134        public_key_alg_id: alg_id::RSA_ENCRYPTION,
135        signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
136            "data/alg-rsa-pkcs1-sha384-absent-params.der"
137        )),
138        verification_alg: &signature::RSA_PKCS1_2048_8192_SHA384,
139    };
140
141/// RSA PKCS#1 1.5 signatures using SHA-512 for keys of 2048-8192 bits,
142/// with illegally absent AlgorithmIdentifier parameters.
143///
144/// RFC4055 says on sha256WithRSAEncryption and company:
145///
146/// >   When any of these four object identifiers appears within an
147/// >   AlgorithmIdentifier, the parameters MUST be NULL.  Implementations
148/// >   MUST accept the parameters being absent as well as present.
149///
150/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA512`] covers
151/// the present case.
152#[cfg(feature = "alloc")]
153pub static RSA_PKCS1_2048_8192_SHA512_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
154    &RingAlgorithm {
155        public_key_alg_id: alg_id::RSA_ENCRYPTION,
156        signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
157            "data/alg-rsa-pkcs1-sha512-absent-params.der"
158        )),
159        verification_alg: &signature::RSA_PKCS1_2048_8192_SHA512,
160    };
161
162/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 3072-8192 bits.
163#[cfg(feature = "alloc")]
164pub static RSA_PKCS1_3072_8192_SHA384: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
165    public_key_alg_id: alg_id::RSA_ENCRYPTION,
166    signature_alg_id: alg_id::RSA_PKCS1_SHA384,
167    verification_alg: &signature::RSA_PKCS1_3072_8192_SHA384,
168};
169
170/// RSA PSS signatures using SHA-256 for keys of 2048-8192 bits and of
171/// type rsaEncryption; see [RFC 4055 Section 1.2].
172///
173/// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
174#[cfg(feature = "alloc")]
175pub static RSA_PSS_2048_8192_SHA256_LEGACY_KEY: &dyn SignatureVerificationAlgorithm =
176    &RingAlgorithm {
177        public_key_alg_id: alg_id::RSA_ENCRYPTION,
178        signature_alg_id: alg_id::RSA_PSS_SHA256,
179        verification_alg: &signature::RSA_PSS_2048_8192_SHA256,
180    };
181
182/// RSA PSS signatures using SHA-384 for keys of 2048-8192 bits and of
183/// type rsaEncryption; see [RFC 4055 Section 1.2].
184///
185/// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
186#[cfg(feature = "alloc")]
187pub static RSA_PSS_2048_8192_SHA384_LEGACY_KEY: &dyn SignatureVerificationAlgorithm =
188    &RingAlgorithm {
189        public_key_alg_id: alg_id::RSA_ENCRYPTION,
190        signature_alg_id: alg_id::RSA_PSS_SHA384,
191        verification_alg: &signature::RSA_PSS_2048_8192_SHA384,
192    };
193
194/// RSA PSS signatures using SHA-512 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
198#[cfg(feature = "alloc")]
199pub static RSA_PSS_2048_8192_SHA512_LEGACY_KEY: &dyn SignatureVerificationAlgorithm =
200    &RingAlgorithm {
201        public_key_alg_id: alg_id::RSA_ENCRYPTION,
202        signature_alg_id: alg_id::RSA_PSS_SHA512,
203        verification_alg: &signature::RSA_PSS_2048_8192_SHA512,
204    };
205
206/// ED25519 signatures according to RFC 8410
207pub static ED25519: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
208    public_key_alg_id: alg_id::ED25519,
209    signature_alg_id: alg_id::ED25519,
210    verification_alg: &signature::ED25519,
211};
212
213#[cfg(test)]
214#[path = "."]
215mod tests {
216    use crate::Error;
217
218    static SUPPORTED_ALGORITHMS_IN_TESTS: &[&dyn super::SignatureVerificationAlgorithm] = &[
219        // Reasonable algorithms.
220        super::ECDSA_P256_SHA256,
221        super::ECDSA_P384_SHA384,
222        super::ED25519,
223        #[cfg(feature = "alloc")]
224        super::RSA_PKCS1_2048_8192_SHA256,
225        #[cfg(feature = "alloc")]
226        super::RSA_PKCS1_2048_8192_SHA384,
227        #[cfg(feature = "alloc")]
228        super::RSA_PKCS1_2048_8192_SHA512,
229        #[cfg(feature = "alloc")]
230        super::RSA_PKCS1_3072_8192_SHA384,
231        #[cfg(feature = "alloc")]
232        super::RSA_PSS_2048_8192_SHA256_LEGACY_KEY,
233        #[cfg(feature = "alloc")]
234        super::RSA_PSS_2048_8192_SHA384_LEGACY_KEY,
235        #[cfg(feature = "alloc")]
236        super::RSA_PSS_2048_8192_SHA512_LEGACY_KEY,
237        // Algorithms deprecated because they are nonsensical combinations.
238        super::ECDSA_P256_SHA384, // Truncates digest.
239        super::ECDSA_P384_SHA256, // Digest is unnecessarily short.
240    ];
241
242    const UNSUPPORTED_SIGNATURE_ALGORITHM_FOR_RSA_KEY: Error = if cfg!(feature = "alloc") {
243        Error::UnsupportedSignatureAlgorithmForPublicKey
244    } else {
245        Error::UnsupportedSignatureAlgorithm
246    };
247
248    const UNSUPPORTED_ECDSA_SHA512_SIGNATURE: Error = Error::UnsupportedSignatureAlgorithm;
249
250    const INVALID_SIGNATURE_FOR_RSA_KEY: Error = if cfg!(feature = "alloc") {
251        Error::InvalidSignatureForPublicKey
252    } else {
253        Error::UnsupportedSignatureAlgorithm
254    };
255
256    const OK_IF_RSA_AVAILABLE: Result<(), Error> = if cfg!(feature = "alloc") {
257        Ok(())
258    } else {
259        Err(Error::UnsupportedSignatureAlgorithm)
260    };
261
262    const OK_IF_POINT_COMPRESSION_SUPPORTED: Result<(), Error> =
263        Err(Error::InvalidSignatureForPublicKey);
264
265    #[path = "alg_tests.rs"]
266    mod alg_tests;
267}