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};
16use ring::signature;
17
18use crate::signed_data::alg_id;
19
20/// A `SignatureVerificationAlgorithm` implemented using *ring*.
21#[derive(Debug)]
22struct RingAlgorithm {
23    public_key_alg_id: AlgorithmIdentifier,
24    signature_alg_id: AlgorithmIdentifier,
25    verification_alg: &'static dyn signature::VerificationAlgorithm,
26}
27
28impl SignatureVerificationAlgorithm for RingAlgorithm {
29    fn public_key_alg_id(&self) -> AlgorithmIdentifier {
30        self.public_key_alg_id
31    }
32
33    fn signature_alg_id(&self) -> AlgorithmIdentifier {
34        self.signature_alg_id
35    }
36
37    fn verify_signature(
38        &self,
39        public_key: &[u8],
40        message: &[u8],
41        signature: &[u8],
42    ) -> Result<(), InvalidSignature> {
43        signature::UnparsedPublicKey::new(self.verification_alg, public_key)
44            .verify(message, signature)
45            .map_err(|_| InvalidSignature)
46    }
47}
48
49/// ECDSA signatures using the P-256 curve and SHA-256.
50pub static ECDSA_P256_SHA256: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
51    public_key_alg_id: alg_id::ECDSA_P256,
52    signature_alg_id: alg_id::ECDSA_SHA256,
53    verification_alg: &signature::ECDSA_P256_SHA256_ASN1,
54};
55
56/// ECDSA signatures using the P-256 curve and SHA-384. Deprecated.
57pub static ECDSA_P256_SHA384: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
58    public_key_alg_id: alg_id::ECDSA_P256,
59    signature_alg_id: alg_id::ECDSA_SHA384,
60    verification_alg: &signature::ECDSA_P256_SHA384_ASN1,
61};
62
63/// ECDSA signatures using the P-384 curve and SHA-256. Deprecated.
64pub static ECDSA_P384_SHA256: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
65    public_key_alg_id: alg_id::ECDSA_P384,
66    signature_alg_id: alg_id::ECDSA_SHA256,
67    verification_alg: &signature::ECDSA_P384_SHA256_ASN1,
68};
69
70/// ECDSA signatures using the P-384 curve and SHA-384.
71pub static ECDSA_P384_SHA384: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
72    public_key_alg_id: alg_id::ECDSA_P384,
73    signature_alg_id: alg_id::ECDSA_SHA384,
74    verification_alg: &signature::ECDSA_P384_SHA384_ASN1,
75};
76
77/// RSA PKCS#1 1.5 signatures using SHA-256 for keys of 2048-8192 bits.
78#[cfg(feature = "alloc")]
79pub static RSA_PKCS1_2048_8192_SHA256: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
80    public_key_alg_id: alg_id::RSA_ENCRYPTION,
81    signature_alg_id: alg_id::RSA_PKCS1_SHA256,
82    verification_alg: &signature::RSA_PKCS1_2048_8192_SHA256,
83};
84
85/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 2048-8192 bits.
86#[cfg(feature = "alloc")]
87pub static RSA_PKCS1_2048_8192_SHA384: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
88    public_key_alg_id: alg_id::RSA_ENCRYPTION,
89    signature_alg_id: alg_id::RSA_PKCS1_SHA384,
90    verification_alg: &signature::RSA_PKCS1_2048_8192_SHA384,
91};
92
93/// RSA PKCS#1 1.5 signatures using SHA-512 for keys of 2048-8192 bits.
94#[cfg(feature = "alloc")]
95pub static RSA_PKCS1_2048_8192_SHA512: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
96    public_key_alg_id: alg_id::RSA_ENCRYPTION,
97    signature_alg_id: alg_id::RSA_PKCS1_SHA512,
98    verification_alg: &signature::RSA_PKCS1_2048_8192_SHA512,
99};
100
101/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 3072-8192 bits.
102#[cfg(feature = "alloc")]
103pub static RSA_PKCS1_3072_8192_SHA384: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
104    public_key_alg_id: alg_id::RSA_ENCRYPTION,
105    signature_alg_id: alg_id::RSA_PKCS1_SHA384,
106    verification_alg: &signature::RSA_PKCS1_3072_8192_SHA384,
107};
108
109/// RSA PSS signatures using SHA-256 for keys of 2048-8192 bits and of
110/// type rsaEncryption; see [RFC 4055 Section 1.2].
111///
112/// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
113#[cfg(feature = "alloc")]
114pub static RSA_PSS_2048_8192_SHA256_LEGACY_KEY: &dyn SignatureVerificationAlgorithm =
115    &RingAlgorithm {
116        public_key_alg_id: alg_id::RSA_ENCRYPTION,
117        signature_alg_id: alg_id::RSA_PSS_SHA256,
118        verification_alg: &signature::RSA_PSS_2048_8192_SHA256,
119    };
120
121/// RSA PSS signatures using SHA-384 for keys of 2048-8192 bits and of
122/// type rsaEncryption; see [RFC 4055 Section 1.2].
123///
124/// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
125#[cfg(feature = "alloc")]
126pub static RSA_PSS_2048_8192_SHA384_LEGACY_KEY: &dyn SignatureVerificationAlgorithm =
127    &RingAlgorithm {
128        public_key_alg_id: alg_id::RSA_ENCRYPTION,
129        signature_alg_id: alg_id::RSA_PSS_SHA384,
130        verification_alg: &signature::RSA_PSS_2048_8192_SHA384,
131    };
132
133/// RSA PSS signatures using SHA-512 for keys of 2048-8192 bits and of
134/// type rsaEncryption; see [RFC 4055 Section 1.2].
135///
136/// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
137#[cfg(feature = "alloc")]
138pub static RSA_PSS_2048_8192_SHA512_LEGACY_KEY: &dyn SignatureVerificationAlgorithm =
139    &RingAlgorithm {
140        public_key_alg_id: alg_id::RSA_ENCRYPTION,
141        signature_alg_id: alg_id::RSA_PSS_SHA512,
142        verification_alg: &signature::RSA_PSS_2048_8192_SHA512,
143    };
144
145/// ED25519 signatures according to RFC 8410
146pub static ED25519: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {
147    public_key_alg_id: alg_id::ED25519,
148    signature_alg_id: alg_id::ED25519,
149    verification_alg: &signature::ED25519,
150};
151
152#[cfg(test)]
153#[path = "."]
154mod tests {
155    use crate::Error;
156
157    static SUPPORTED_ALGORITHMS_IN_TESTS: &[&dyn super::SignatureVerificationAlgorithm] = &[
158        // Reasonable algorithms.
159        super::ECDSA_P256_SHA256,
160        super::ECDSA_P384_SHA384,
161        super::ED25519,
162        #[cfg(feature = "alloc")]
163        super::RSA_PKCS1_2048_8192_SHA256,
164        #[cfg(feature = "alloc")]
165        super::RSA_PKCS1_2048_8192_SHA384,
166        #[cfg(feature = "alloc")]
167        super::RSA_PKCS1_2048_8192_SHA512,
168        #[cfg(feature = "alloc")]
169        super::RSA_PKCS1_3072_8192_SHA384,
170        #[cfg(feature = "alloc")]
171        super::RSA_PSS_2048_8192_SHA256_LEGACY_KEY,
172        #[cfg(feature = "alloc")]
173        super::RSA_PSS_2048_8192_SHA384_LEGACY_KEY,
174        #[cfg(feature = "alloc")]
175        super::RSA_PSS_2048_8192_SHA512_LEGACY_KEY,
176        // Algorithms deprecated because they are nonsensical combinations.
177        super::ECDSA_P256_SHA384, // Truncates digest.
178        super::ECDSA_P384_SHA256, // Digest is unnecessarily short.
179    ];
180
181    const UNSUPPORTED_SIGNATURE_ALGORITHM_FOR_RSA_KEY: Error = if cfg!(feature = "alloc") {
182        Error::UnsupportedSignatureAlgorithmForPublicKey
183    } else {
184        Error::UnsupportedSignatureAlgorithm
185    };
186
187    const UNSUPPORTED_ECDSA_SHA512_SIGNATURE: Error = Error::UnsupportedSignatureAlgorithm;
188
189    const INVALID_SIGNATURE_FOR_RSA_KEY: Error = if cfg!(feature = "alloc") {
190        Error::InvalidSignatureForPublicKey
191    } else {
192        Error::UnsupportedSignatureAlgorithm
193    };
194
195    const OK_IF_RSA_AVAILABLE: Result<(), Error> = if cfg!(feature = "alloc") {
196        Ok(())
197    } else {
198        Err(Error::UnsupportedSignatureAlgorithm)
199    };
200
201    const OK_IF_POINT_COMPRESSION_SUPPORTED: Result<(), Error> =
202        Err(Error::InvalidSignatureForPublicKey);
203
204    #[path = "alg_tests.rs"]
205    mod alg_tests;
206}