rustls/
x509.rs

1// Additional x509/asn1 functions to those provided in webpki/ring.
2
3use alloc::vec::Vec;
4
5/// Prepend stuff to `bytes` to put it in a DER SEQUENCE.
6pub(crate) fn wrap_in_sequence(bytes: &[u8]) -> Vec<u8> {
7    asn1_wrap(DER_SEQUENCE_TAG, bytes, &[])
8}
9
10/// Prepend stuff to `bytes_a` + `bytes_b` to put it in a DER SEQUENCE.
11#[cfg_attr(not(feature = "ring"), allow(dead_code))]
12pub(crate) fn wrap_concat_in_sequence(bytes_a: &[u8], bytes_b: &[u8]) -> Vec<u8> {
13    asn1_wrap(DER_SEQUENCE_TAG, bytes_a, bytes_b)
14}
15
16/// Prepend stuff to `bytes` to put it in a DER BIT STRING.
17pub(crate) fn wrap_in_bit_string(bytes: &[u8]) -> Vec<u8> {
18    asn1_wrap(DER_BIT_STRING_TAG, &[0u8], bytes)
19}
20
21/// Prepend stuff to `bytes` to put it in a DER OCTET STRING.
22#[cfg_attr(not(feature = "ring"), allow(dead_code))]
23pub(crate) fn wrap_in_octet_string(bytes: &[u8]) -> Vec<u8> {
24    asn1_wrap(DER_OCTET_STRING_TAG, bytes, &[])
25}
26
27fn asn1_wrap(tag: u8, bytes_a: &[u8], bytes_b: &[u8]) -> Vec<u8> {
28    let len = bytes_a.len() + bytes_b.len();
29
30    if len <= 0x7f {
31        // Short form
32        let mut ret = Vec::with_capacity(2 + len);
33        ret.push(tag);
34        ret.push(len as u8);
35        ret.extend_from_slice(bytes_a);
36        ret.extend_from_slice(bytes_b);
37        ret
38    } else {
39        // Long form
40        let size = len.to_be_bytes();
41        let leading_zero_bytes = size
42            .iter()
43            .position(|&x| x != 0)
44            .unwrap_or(size.len());
45        assert!(leading_zero_bytes < size.len());
46        let encoded_bytes = size.len() - leading_zero_bytes;
47
48        let mut ret = Vec::with_capacity(2 + encoded_bytes + len);
49        ret.push(tag);
50
51        ret.push(0x80 + encoded_bytes as u8);
52        ret.extend_from_slice(&size[leading_zero_bytes..]);
53
54        ret.extend_from_slice(bytes_a);
55        ret.extend_from_slice(bytes_b);
56        ret
57    }
58}
59
60const DER_SEQUENCE_TAG: u8 = 0x30;
61const DER_BIT_STRING_TAG: u8 = 0x03;
62const DER_OCTET_STRING_TAG: u8 = 0x04;
63
64#[cfg(test)]
65mod tests {
66    use std::vec;
67
68    use super::*;
69
70    #[test]
71    fn test_empty() {
72        assert_eq!(vec![0x30, 0x00], wrap_in_sequence(&[]));
73    }
74
75    #[test]
76    fn test_small() {
77        assert_eq!(
78            vec![0x30, 0x04, 0x00, 0x11, 0x22, 0x33],
79            wrap_in_sequence(&[0x00, 0x11, 0x22, 0x33])
80        );
81    }
82
83    #[test]
84    fn test_medium() {
85        let mut val = Vec::new();
86        val.resize(255, 0x12);
87        assert_eq!(
88            vec![0x30, 0x81, 0xff, 0x12, 0x12, 0x12],
89            wrap_in_sequence(&val)[..6]
90        );
91    }
92
93    #[test]
94    fn test_large() {
95        let mut val = Vec::new();
96        val.resize(4660, 0x12);
97        wrap_in_sequence(&val);
98        assert_eq!(
99            vec![0x30, 0x82, 0x12, 0x34, 0x12, 0x12],
100            wrap_in_sequence(&val)[..6]
101        );
102    }
103
104    #[test]
105    fn test_huge() {
106        let mut val = Vec::new();
107        val.resize(0xffff, 0x12);
108        let result = wrap_in_sequence(&val);
109        assert_eq!(vec![0x30, 0x82, 0xff, 0xff, 0x12, 0x12], result[..6]);
110        assert_eq!(result.len(), 0xffff + 4);
111    }
112
113    #[test]
114    fn test_gigantic() {
115        let mut val = Vec::new();
116        val.resize(0x100000, 0x12);
117        let result = wrap_in_sequence(&val);
118        assert_eq!(vec![0x30, 0x83, 0x10, 0x00, 0x00, 0x12, 0x12], result[..7]);
119        assert_eq!(result.len(), 0x100000 + 5);
120    }
121
122    #[test]
123    fn test_ludicrous() {
124        let mut val = Vec::new();
125        val.resize(0x1000000, 0x12);
126        let result = wrap_in_sequence(&val);
127        assert_eq!(
128            vec![0x30, 0x84, 0x01, 0x00, 0x00, 0x00, 0x12, 0x12],
129            result[..8]
130        );
131        assert_eq!(result.len(), 0x1000000 + 6);
132    }
133
134    #[test]
135    fn test_wrap_in_bit_string() {
136        // The BIT STRING encoding starts with a single octet on
137        // the front saying how many bits to disregard from the
138        // last octet. So this zero means "no bits" unused, which
139        // is correct because our input is an string of octets.
140        //
141        // So if we encode &[0x55u8] with this function, we should get:
142        //
143        // 0x03    0x02    0x00                0x55
144        // ^ tag   ^ len   ^ no unused bits    ^ value
145        assert_eq!(wrap_in_bit_string(&[0x55u8]), vec![0x03, 0x02, 0x00, 0x55]);
146    }
147}