ctclient_async/internal/
leaf.rs1use std::convert::{TryFrom, TryInto};
2use std::fmt;
3
4use crate::Error;
5use crate::jsons;
6use crate::utils;
7
8pub struct Leaf {
13 pub hash: [u8; 32],
15 pub timestamp: u64,
17 pub is_pre_cert: bool,
18 pub x509_chain: Vec<Vec<u8>>,
21 pub tbs_cert: Option<Vec<u8>>,
24 pub issuer_key_hash: Option<Vec<u8>>,
25 pub extensions: Vec<u8>,
27}
28
29impl Leaf {
30 pub fn from_raw(leaf_input: &[u8], extra_data: &[u8]) -> Result<Self, Error> {
31 let mut hash_data = Vec::with_capacity(1 + leaf_input.len());
32 hash_data.push(0);
33 hash_data.extend_from_slice(leaf_input);
34 let hash = utils::sha256(&hash_data);
35 let is_pre_cert;
36 let mut x509_chain;
37 let mut tbs = None;
38 fn err_invalid() -> Result<Leaf, Error> {
46 Err(Error::MalformedResponseBody(
47 "Invalid leaf data.".to_owned(),
48 ))
49 }
50 fn err_invalid_extra() -> Result<Leaf, Error> {
51 Err(Error::MalformedResponseBody(
52 "Invalid extra data.".to_owned(),
53 ))
54 }
55 if leaf_input.len() < 2 {
56 return err_invalid();
57 }
58 let mut leaf_slice = leaf_input;
59 let version = u8::from_be_bytes([leaf_slice[0]]);
60 let leaf_type = u8::from_be_bytes([leaf_slice[1]]);
61 if version != 0 || leaf_type != 0 {
62 return err_invalid(); }
64 leaf_slice = &leaf_slice[2..];
65 if leaf_slice.len() < 8 + 2 {
76 return err_invalid();
77 }
78 let timestamp = u64::from_be_bytes(leaf_slice[0..8].try_into().unwrap());
79 leaf_slice = &leaf_slice[8..];
80 let entry_type = u16::from_be_bytes([leaf_slice[0], leaf_slice[1]]);
81 leaf_slice = &leaf_slice[2..];
82 let issuer_key_hash;
83 match entry_type {
84 0 => {
85 is_pre_cert = false;
87 issuer_key_hash = None;
88 if leaf_slice.len() < 3 {
90 return err_invalid();
91 }
92 let len = u32::from_be_bytes([0, leaf_slice[0], leaf_slice[1], leaf_slice[2]]);
93 leaf_slice = &leaf_slice[3..];
94 if leaf_slice.len() < len as usize {
95 return err_invalid();
96 }
97 let x509_end = &leaf_slice[..len as usize]; leaf_slice = &leaf_slice[len as usize..];
99 let mut extra_slice = extra_data;
103 if extra_slice.len() < 3 {
104 return err_invalid_extra();
105 }
106 let chain_byte_len =
107 u32::from_be_bytes([0, extra_slice[0], extra_slice[1], extra_slice[2]]);
108 extra_slice = &extra_slice[3..];
109 if extra_slice.len() != chain_byte_len as usize {
110 return err_invalid_extra();
111 }
112 x509_chain = Vec::new();
113 x509_chain.push(Vec::from(x509_end));
114 while !extra_slice.is_empty() {
115 if extra_slice.len() < 3 {
116 return err_invalid_extra();
117 }
118 let len =
119 u32::from_be_bytes([0, extra_slice[0], extra_slice[1], extra_slice[2]]);
120 extra_slice = &extra_slice[3..];
121 if extra_slice.len() < len as usize {
122 return err_invalid_extra();
123 }
124 let data = &extra_slice[..len as usize];
125 extra_slice = &extra_slice[len as usize..];
126 x509_chain.push(Vec::from(data));
127 }
128 }
129 1 => {
130 is_pre_cert = true;
138 if leaf_slice.len() < 32 {
139 return err_invalid();
140 }
141 issuer_key_hash = Some(leaf_slice[0..32].to_owned());
142 leaf_slice = &leaf_slice[32..];
143 if leaf_slice.len() < 3 {
144 return err_invalid();
145 }
146 let len = u32::from_be_bytes([0, leaf_slice[0], leaf_slice[1], leaf_slice[2]]);
147 leaf_slice = &leaf_slice[3..];
148 if leaf_slice.len() < len as usize {
149 return err_invalid();
150 }
151 let tbs_data = &leaf_slice[..len as usize];
152 leaf_slice = &leaf_slice[len as usize..];
153 tbs = Some(tbs_data.to_vec());
156
157 let mut extra_slice = extra_data;
165 if extra_slice.len() < 3 {
166 return err_invalid_extra();
167 }
168 let pre_cert_len =
169 u32::from_be_bytes([0, extra_slice[0], extra_slice[1], extra_slice[2]]);
170 extra_slice = &extra_slice[3..];
171 if extra_slice.len() < pre_cert_len as usize {
172 return err_invalid_extra();
173 }
174 let pre_cert_data = &extra_slice[..pre_cert_len as usize];
175 extra_slice = &extra_slice[pre_cert_len as usize..];
176 x509_chain = Vec::new();
177 x509_chain.push(Vec::from(pre_cert_data));
178 if extra_slice.len() < 3 {
179 return err_invalid_extra();
180 }
181 let rest_len =
182 u32::from_be_bytes([0, extra_slice[0], extra_slice[1], extra_slice[2]]);
183 extra_slice = &extra_slice[3..];
184 if extra_slice.len() != rest_len as usize {
185 return err_invalid_extra();
186 }
187 while !extra_slice.is_empty() {
188 if extra_slice.len() < 3 {
189 return err_invalid_extra();
190 }
191 let len =
192 u32::from_be_bytes([0, extra_slice[0], extra_slice[1], extra_slice[2]]);
193 extra_slice = &extra_slice[3..];
194 if extra_slice.len() < len as usize {
195 return err_invalid_extra();
196 }
197 let data = &extra_slice[..len as usize];
198 extra_slice = &extra_slice[len as usize..];
199 x509_chain.push(Vec::from(data));
200 }
201 }
202 _ => {
203 return err_invalid(); }
205 }
206 if leaf_slice.len() < 2 {
207 return err_invalid();
208 }
209 let extension_len = u16::from_be_bytes([leaf_slice[0], leaf_slice[1]]);
210 leaf_slice = &leaf_slice[2..];
211 if leaf_slice.len() != extension_len as usize {
212 return err_invalid();
213 }
214 Ok(Leaf {
215 hash,
216 is_pre_cert,
217 x509_chain,
218 tbs_cert: tbs,
219 timestamp,
220 extensions: leaf_slice.to_owned(),
221 issuer_key_hash,
222 })
223 }
224}
225
226impl TryFrom<&jsons::LeafEntry> for Leaf {
227 type Error = Error;
228 fn try_from(le: &jsons::LeafEntry) -> Result<Self, Error> {
229 let leaf_input = base64::decode(&le.leaf_input).map_err(|e| {
230 Error::MalformedResponseBody(format!("base64 decode leaf_input: {}", &e))
231 })?;
232 let extra_data = base64::decode(&le.extra_data).map_err(|e| {
233 Error::MalformedResponseBody(format!("base64 decode extra_data: {}", &e))
234 })?;
235 Leaf::from_raw(&leaf_input, &extra_data)
236 }
237}
238
239impl fmt::Debug for Leaf {
240 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241 write!(f, "Leaf({})", &utils::u8_to_hex(&self.hash))?;
242 if self.is_pre_cert {
243 write!(f, " (pre_cert)")?;
244 }
245 Ok(())
246 }
247}
248
249pub mod leaf_hash_constructors {
253 use crate::utils;
254
255 pub fn with_x509(x509_endcert: &[u8], timestamp: u64, extensions_data: &[u8]) -> [u8; 32] {
256 let mut hash_data: Vec<u8> = Vec::new();
257 hash_data.push(0); hash_data.push(0); hash_data.push(0); hash_data.extend_from_slice(×tamp.to_be_bytes()); hash_data.extend_from_slice(&0u16.to_be_bytes()); assert!(x509_endcert.len() < 1 << 24);
265 hash_data.extend_from_slice(&(x509_endcert.len() as u32).to_be_bytes()[1..4]); hash_data.extend_from_slice(x509_endcert); assert!(extensions_data.len() < 1 << 16);
268 hash_data.extend_from_slice(&(extensions_data.len() as u16).to_be_bytes()); hash_data.extend_from_slice(extensions_data); utils::sha256(&hash_data)
271 }
272
273 pub fn with_precert(
274 tbs: &[u8],
275 issuer_key_hash: &[u8],
276 timestamp: u64,
277 extensions_data: &[u8],
278 ) -> [u8; 32] {
279 assert_eq!(issuer_key_hash.len(), 32);
280 let mut hash_data: Vec<u8> = Vec::new();
281 hash_data.push(0); hash_data.push(0); hash_data.push(0); hash_data.extend_from_slice(×tamp.to_be_bytes()); hash_data.extend_from_slice(&1u16.to_be_bytes()); hash_data.extend_from_slice(issuer_key_hash); assert!(tbs.len() < 1 << 24);
289 hash_data.extend_from_slice(&(tbs.len() as u32).to_be_bytes()[1..4]); hash_data.extend_from_slice(tbs); assert!(extensions_data.len() < 1 << 16);
292 hash_data.extend_from_slice(&(extensions_data.len() as u16).to_be_bytes()); hash_data.extend_from_slice(extensions_data); utils::sha256(&hash_data)
295 }
296}