barebones_x509/
spki.rs

1//! PKIX SubjectPublicKeyInfo parsing
2
3use super::{
4    der::{self, Tag},
5    Error, SignatureScheme,
6};
7
8use ring::signature;
9
10/// Restrictions on allowed signature algorithms
11#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub enum Restrictions {
13    /// Allow all supported signature algorithms. This is the default.
14    None,
15    /// Only support signature algorithms allowed by TLS1.2. This should not be
16    /// used in other contexts.
17    TLSv12,
18    /// Only support signature algorithms allowed by TLS1.3. This is a good
19    /// choice for new protocols as well.
20    TLSv13,
21}
22
23impl Default for Restrictions {
24    fn default() -> Self { Self::None }
25}
26
27/// A PKIX SubjectPublicKeyInfo struct
28#[derive(Debug, Copy, Clone)]
29pub struct SubjectPublicKeyInfo<'a> {
30    spki: &'a [u8],
31    algorithm: &'a [u8],
32    key: &'a [u8],
33}
34
35impl<'a> SubjectPublicKeyInfo<'a> {
36    /// The data over which the signature is computed.  An X.509 SEQUENCE.
37    pub fn spki(&self) -> &'a [u8] { self.spki }
38    /// The algorithm identifier, with the outer SEQUENCE stripped.
39    pub fn algorithm(&self) -> &'a [u8] { self.algorithm }
40    /// The raw bytes of the signature.
41    pub fn key(&self) -> &'a [u8] { self.key }
42    /// Read a SubjectPublicKeyInfo from an [`untrusted::Reader`]
43    pub fn read(input: &mut untrusted::Reader<'a>) -> Result<Self, Error> {
44        let (spki, (algorithm, key)) = input.read_partial(|input| {
45            der::nested(input, Tag::Sequence, Error::BadDER, |input| {
46                let algorithm = der::expect_tag_and_get_value(input, Tag::Sequence)
47                    .map_err(|_| Error::BadDER)?;
48                let key = der::bit_string_with_no_unused_bits(input).map_err(|_| Error::BadDER)?;
49                Ok((algorithm.as_slice_less_safe(), key.as_slice_less_safe()))
50            })
51        })?;
52        Ok(Self {
53            spki: spki.as_slice_less_safe(),
54            algorithm,
55            key,
56        })
57    }
58
59    /// Verify a signature by the private key corresponding to this
60    /// SubjectPublicKeyInfo. `restrictions` indicates the restrictions on
61    /// allowed algorithms.
62    pub fn check_signature(
63        &self, algorithm: SignatureScheme, message: &[u8], signature: &[u8],
64        restrictions: Restrictions,
65    ) -> Result<(), Error> {
66        self.public_key(algorithm, restrictions)?
67            .verify(message, signature)
68            .map_err(|_| Error::InvalidSignatureForPublicKey)
69    }
70
71    /// Get a [`signature::UnparsedPublicKey`] for this SubjectPublicKeyInfo.
72    ///
73    /// `restrictions` indicates the restrictions on allowed algorithms.
74    pub fn public_key(
75        &self, algorithm: SignatureScheme, restrictions: Restrictions,
76    ) -> Result<signature::UnparsedPublicKey<&'a [u8]>, Error> {
77        use signature as s;
78        #[cfg(feature = "rsa")]
79        use Restrictions::TLSv12;
80        use Restrictions::TLSv13;
81        let algorithm: &'static dyn s::VerificationAlgorithm = match algorithm {
82            #[cfg(feature = "rsa")]
83            SignatureScheme::RSA_PKCS1_SHA256 if restrictions != TLSv13 => match self.algorithm {
84                include_bytes!("data/alg-rsa-encryption.der") => (&s::RSA_PKCS1_2048_8192_SHA256),
85                _ => return Err(Error::UnsupportedSignatureAlgorithmForPublicKey),
86            },
87            #[cfg(feature = "rsa")]
88            SignatureScheme::RSA_PKCS1_SHA384 if restrictions != TLSv13 => match self.algorithm {
89                include_bytes!("data/alg-rsa-encryption.der") => (&s::RSA_PKCS1_2048_8192_SHA384),
90                _ => return Err(Error::UnsupportedSignatureAlgorithmForPublicKey),
91            },
92            #[cfg(feature = "rsa")]
93            SignatureScheme::RSA_PKCS1_SHA512 if restrictions != TLSv13 => match self.algorithm {
94                include_bytes!("data/alg-rsa-encryption.der") => &s::RSA_PKCS1_2048_8192_SHA512,
95                _ => return Err(Error::UnsupportedSignatureAlgorithmForPublicKey),
96            },
97            SignatureScheme::ECDSA_NISTP256_SHA256 => match self.algorithm {
98                include_bytes!("data/alg-ecdsa-p256.der") => &s::ECDSA_P256_SHA256_ASN1,
99                include_bytes!("data/alg-ecdsa-p384.der") if restrictions != TLSv13 =>
100                    &s::ECDSA_P384_SHA256_ASN1,
101                _ => return Err(Error::UnsupportedSignatureAlgorithmForPublicKey),
102            },
103            SignatureScheme::ECDSA_NISTP384_SHA384 => match self.algorithm {
104                include_bytes!("data/alg-ecdsa-p384.der") => &s::ECDSA_P384_SHA384_ASN1,
105                include_bytes!("data/alg-ecdsa-p256.der") if restrictions != TLSv13 =>
106                    &s::ECDSA_P256_SHA384_ASN1,
107                _ => return Err(Error::UnsupportedSignatureAlgorithmForPublicKey),
108            },
109            SignatureScheme::ED25519 => match self.algorithm {
110                include_bytes!("data/alg-ed25519.der") => &s::ED25519,
111                _ => return Err(Error::UnsupportedSignatureAlgorithmForPublicKey),
112            },
113            #[cfg(feature = "rsa")]
114            SignatureScheme::RSA_PSS_SHA256 if restrictions != TLSv12 => match self.algorithm {
115                include_bytes!("data/alg-rsa-encryption.der") => &s::RSA_PSS_2048_8192_SHA256,
116                _ => return Err(Error::UnsupportedSignatureAlgorithmForPublicKey),
117            },
118            #[cfg(feature = "rsa")]
119            SignatureScheme::RSA_PSS_SHA384 if restrictions != TLSv12 => match self.algorithm {
120                include_bytes!("data/alg-rsa-encryption.der") => &s::RSA_PSS_2048_8192_SHA384,
121                _ => return Err(Error::UnsupportedSignatureAlgorithmForPublicKey),
122            },
123            #[cfg(feature = "rsa")]
124            SignatureScheme::RSA_PSS_SHA512 if restrictions != TLSv12 => match self.algorithm {
125                include_bytes!("data/alg-rsa-encryption.der") => &s::RSA_PSS_2048_8192_SHA512,
126                _ => return Err(Error::UnsupportedSignatureAlgorithmForPublicKey),
127            },
128            _ => return Err(Error::UnsupportedSignatureAlgorithm),
129        };
130        Ok(s::UnparsedPublicKey::new(algorithm, self.key))
131    }
132
133    /// Get a [`signature::UnparsedPublicKey`] for this SubjectPublicKeyInfo
134    pub fn get_public_key_x509(
135        &self, algorithm_id: &[u8],
136    ) -> Result<ring::signature::UnparsedPublicKey<&'a [u8]>, Error> {
137        self.public_key(parse_algorithmid(algorithm_id)?, Restrictions::None)
138    }
139}
140
141const RSASSA_PSS_PREFIX: &[u8; 11] = include_bytes!("data/alg-rsa-pss.der");
142
143/// Parse the ASN.1 DER-encoded algorithm identifier in `asn1` into a
144/// `SignatureScheme`. This will fail if `asn1` is not a known signature scheme.
145pub fn parse_algorithmid(asn1: &[u8]) -> Result<SignatureScheme, Error> {
146    match asn1 {
147        include_bytes!("data/alg-rsa-pkcs1-sha256.der") => Ok(SignatureScheme::RSA_PKCS1_SHA256),
148        include_bytes!("data/alg-rsa-pkcs1-sha384.der") => Ok(SignatureScheme::RSA_PKCS1_SHA384),
149        include_bytes!("data/alg-rsa-pkcs1-sha512.der") => Ok(SignatureScheme::RSA_PKCS1_SHA512),
150        include_bytes!("data/alg-ecdsa-sha256.der") => Ok(SignatureScheme::ECDSA_NISTP256_SHA256),
151        include_bytes!("data/alg-ecdsa-sha384.der") => Ok(SignatureScheme::ECDSA_NISTP384_SHA384),
152        include_bytes!("data/alg-ed25519.der") => Ok(SignatureScheme::ED25519),
153        e if e.starts_with(&RSASSA_PSS_PREFIX[..]) => match &e[RSASSA_PSS_PREFIX.len()..] {
154            include_bytes!("data/alg-rsa-pss-sha256-v0.der")
155            | include_bytes!("data/alg-rsa-pss-sha256-v1.der")
156            | include_bytes!("data/alg-rsa-pss-sha256-v2.der")
157            | include_bytes!("data/alg-rsa-pss-sha256-v3.der") =>
158                Ok(SignatureScheme::RSA_PSS_SHA256),
159
160            include_bytes!("data/alg-rsa-pss-sha384-v0.der")
161            | include_bytes!("data/alg-rsa-pss-sha384-v1.der")
162            | include_bytes!("data/alg-rsa-pss-sha384-v2.der")
163            | include_bytes!("data/alg-rsa-pss-sha384-v3.der") =>
164                Ok(SignatureScheme::RSA_PSS_SHA384),
165
166            include_bytes!("data/alg-rsa-pss-sha512-v0.der")
167            | include_bytes!("data/alg-rsa-pss-sha512-v1.der")
168            | include_bytes!("data/alg-rsa-pss-sha512-v2.der")
169            | include_bytes!("data/alg-rsa-pss-sha512-v3.der") =>
170                Ok(SignatureScheme::RSA_PSS_SHA512),
171            _ => Err(Error::UnsupportedSignatureAlgorithm),
172        },
173        _ => Err(Error::UnsupportedSignatureAlgorithm),
174    }
175}