summaryrefslogtreecommitdiffstats
path: root/rust/vendor/x509-parser/src/public_key.rs
blob: 4016a9f5aa1f3718b456e53e0f16c629914761f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use crate::error::*;
use asn1_rs::FromDer;
use der_parser::{
    der::{parse_der_integer, parse_der_sequence_defined_g},
    error::BerResult,
};

/// Public Key value
#[derive(Debug, PartialEq, Eq)]
pub enum PublicKey<'a> {
    RSA(RSAPublicKey<'a>),
    EC(ECPoint<'a>),
    /// DSAPublicKey ::= INTEGER -- public key, Y (RFC 3279)
    DSA(&'a [u8]),
    /// GostR3410-94-PublicKey ::= OCTET STRING -- public key, Y (RFC 4491)
    GostR3410(&'a [u8]),
    /// GostR3410-2012-256-PublicKey ::= OCTET STRING (64),
    /// GostR3410-2012-512-PublicKey ::= OCTET STRING (128). (RFC 4491-bis)
    GostR3410_2012(&'a [u8]),

    Unknown(&'a [u8]),
}

impl<'a> PublicKey<'a> {
    /// Return the key size (in bits) or 0
    pub fn key_size(&self) -> usize {
        match self {
            Self::EC(ec) => ec.key_size(),
            Self::RSA(rsa) => rsa.key_size(),
            Self::DSA(y) | Self::GostR3410(y) => y.len() * 8,
            _ => 0,
        }
    }
}

/// RSA public Key, defined in rfc3279
#[derive(Debug, PartialEq, Eq)]
pub struct RSAPublicKey<'a> {
    /// Raw bytes of the modulus
    ///
    /// This possibly includes a leading 0 if the MSB is 1
    pub modulus: &'a [u8],
    /// Raw bytes of the exponent
    ///
    /// This possibly includes a leading 0 if the MSB is 1
    pub exponent: &'a [u8],
}

impl<'a> RSAPublicKey<'a> {
    /// Attempt to convert exponent to u64
    ///
    /// Returns an error if integer is too large, empty, or negative
    pub fn try_exponent(&self) -> Result<u64, X509Error> {
        let mut buf = [0u8; 8];
        if self.exponent.is_empty() || self.exponent[0] & 0x80 != 0 || self.exponent.len() > 8 {
            return Err(X509Error::InvalidNumber);
        }
        buf[8_usize.saturating_sub(self.exponent.len())..].copy_from_slice(self.exponent);
        let int = <u64>::from_be_bytes(buf);
        Ok(int)
    }

    /// Return the key size (in bits) or 0
    pub fn key_size(&self) -> usize {
        if !self.modulus.is_empty() && self.modulus[0] & 0x80 == 0 {
            // XXX len must substract leading zeroes
            let modulus = &self.modulus[1..];
            8 * modulus.len()
        } else {
            0
        }
    }
}

// helper function to parse with error type BerError
fn parse_rsa_key(bytes: &[u8]) -> BerResult<RSAPublicKey> {
    parse_der_sequence_defined_g(move |i, _| {
        let (i, obj_modulus) = parse_der_integer(i)?;
        let (i, obj_exponent) = parse_der_integer(i)?;
        let modulus = obj_modulus.as_slice()?;
        let exponent = obj_exponent.as_slice()?;
        let key = RSAPublicKey { modulus, exponent };
        Ok((i, key))
    })(bytes)
}

impl<'a> FromDer<'a, X509Error> for RSAPublicKey<'a> {
    fn from_der(bytes: &'a [u8]) -> X509Result<'a, Self> {
        parse_rsa_key(bytes).map_err(|_| nom::Err::Error(X509Error::InvalidSPKI))
    }
}

/// Elliptic Curve point, as defined in [RFC5480](https://datatracker.ietf.org/doc/html/rfc5480)
#[derive(Debug, PartialEq, Eq)]
pub struct ECPoint<'a> {
    data: &'a [u8],
}

impl<'a> ECPoint<'a> {
    /// EC Point content (See Standards for Efficient Cryptography Group (SECG), "SEC1: Elliptic Curve Cryptography")
    pub fn data(&'a self) -> &'a [u8] {
        self.data
    }

    /// Return the key size (in bits) or 0
    pub fn key_size(&self) -> usize {
        match self.data {
            [] => {
                // empty
                0
            }
            [4, rem @ ..] => {
                // uncompressed
                rem.len() * 8 / 2
            }
            [2..=3, rem @ ..] => {
                // compressed
                rem.len() * 8
            }
            _ => {
                // invalid
                0
            }
        }
    }
}

impl<'a> From<&'a [u8]> for ECPoint<'a> {
    fn from(data: &'a [u8]) -> Self {
        ECPoint { data }
    }
}