Coverage Report

Created: 2026-06-07 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/x509-parser-0.16.0/src/public_key.rs
Line
Count
Source
1
use crate::error::*;
2
use asn1_rs::FromDer;
3
use der_parser::{
4
    der::{parse_der_integer, parse_der_sequence_defined_g},
5
    error::BerResult,
6
};
7
8
/// Public Key value
9
#[derive(Debug, PartialEq, Eq)]
10
pub enum PublicKey<'a> {
11
    RSA(RSAPublicKey<'a>),
12
    EC(ECPoint<'a>),
13
    /// DSAPublicKey ::= INTEGER -- public key, Y (RFC 3279)
14
    DSA(&'a [u8]),
15
    /// GostR3410-94-PublicKey ::= OCTET STRING -- public key, Y (RFC 4491)
16
    GostR3410(&'a [u8]),
17
    /// GostR3410-2012-256-PublicKey ::= OCTET STRING (64),
18
    /// GostR3410-2012-512-PublicKey ::= OCTET STRING (128). (RFC 4491-bis)
19
    GostR3410_2012(&'a [u8]),
20
21
    Unknown(&'a [u8]),
22
}
23
24
impl<'a> PublicKey<'a> {
25
    /// Return the key size (in bits) or 0
26
0
    pub fn key_size(&self) -> usize {
27
0
        match self {
28
0
            Self::EC(ec) => ec.key_size(),
29
0
            Self::RSA(rsa) => rsa.key_size(),
30
0
            Self::DSA(y) | Self::GostR3410(y) => y.len() * 8,
31
0
            _ => 0,
32
        }
33
0
    }
34
}
35
36
/// RSA public Key, defined in rfc3279
37
#[derive(Debug, PartialEq, Eq)]
38
pub struct RSAPublicKey<'a> {
39
    /// Raw bytes of the modulus
40
    ///
41
    /// This possibly includes a leading 0 if the MSB is 1
42
    pub modulus: &'a [u8],
43
    /// Raw bytes of the exponent
44
    ///
45
    /// This possibly includes a leading 0 if the MSB is 1
46
    pub exponent: &'a [u8],
47
}
48
49
impl<'a> RSAPublicKey<'a> {
50
    /// Attempt to convert exponent to u64
51
    ///
52
    /// Returns an error if integer is too large, empty, or negative
53
0
    pub fn try_exponent(&self) -> Result<u64, X509Error> {
54
0
        let mut buf = [0u8; 8];
55
0
        if self.exponent.is_empty() || self.exponent[0] & 0x80 != 0 || self.exponent.len() > 8 {
56
0
            return Err(X509Error::InvalidNumber);
57
0
        }
58
0
        buf[8_usize.saturating_sub(self.exponent.len())..].copy_from_slice(self.exponent);
59
0
        let int = <u64>::from_be_bytes(buf);
60
0
        Ok(int)
61
0
    }
62
63
    /// Return the key size (in bits) or 0
64
0
    pub fn key_size(&self) -> usize {
65
0
        if !self.modulus.is_empty() && self.modulus[0] & 0x80 == 0 {
66
            // XXX len must substract leading zeroes
67
0
            let modulus = &self.modulus[1..];
68
0
            8 * modulus.len()
69
        } else {
70
0
            0
71
        }
72
0
    }
73
}
74
75
// helper function to parse with error type BerError
76
0
fn parse_rsa_key(bytes: &[u8]) -> BerResult<RSAPublicKey> {
77
0
    parse_der_sequence_defined_g(move |i, _| {
78
0
        let (i, obj_modulus) = parse_der_integer(i)?;
79
0
        let (i, obj_exponent) = parse_der_integer(i)?;
80
0
        let modulus = obj_modulus.as_slice()?;
81
0
        let exponent = obj_exponent.as_slice()?;
82
0
        let key = RSAPublicKey { modulus, exponent };
83
0
        Ok((i, key))
84
0
    })(bytes)
85
0
}
86
87
impl<'a> FromDer<'a, X509Error> for RSAPublicKey<'a> {
88
0
    fn from_der(bytes: &'a [u8]) -> X509Result<'a, Self> {
89
0
        parse_rsa_key(bytes).map_err(|_| nom::Err::Error(X509Error::InvalidSPKI))
90
0
    }
91
}
92
93
/// Elliptic Curve point, as defined in [RFC5480](https://datatracker.ietf.org/doc/html/rfc5480)
94
#[derive(Debug, PartialEq, Eq)]
95
pub struct ECPoint<'a> {
96
    data: &'a [u8],
97
}
98
99
impl<'a> ECPoint<'a> {
100
    /// EC Point content (See Standards for Efficient Cryptography Group (SECG), "SEC1: Elliptic Curve Cryptography")
101
0
    pub fn data(&'a self) -> &'a [u8] {
102
0
        self.data
103
0
    }
104
105
    /// Return the key size (in bits) or 0
106
0
    pub fn key_size(&self) -> usize {
107
0
        match self.data {
108
0
            [] => {
109
                // empty
110
0
                0
111
            }
112
0
            [4, rem @ ..] => {
113
                // uncompressed
114
0
                rem.len() * 8 / 2
115
            }
116
0
            [2..=3, rem @ ..] => {
117
                // compressed
118
0
                rem.len() * 8
119
            }
120
            _ => {
121
                // invalid
122
0
                0
123
            }
124
        }
125
0
    }
126
}
127
128
impl<'a> From<&'a [u8]> for ECPoint<'a> {
129
0
    fn from(data: &'a [u8]) -> Self {
130
0
        ECPoint { data }
131
0
    }
132
}