1use crate::{
2 CertificateChain, CtLog, Version,
3 signature::{Signature, SignatureValidationError},
4 store::Hashable,
5 tree::HashOutput,
6 utils::codec::{CodecError, Decode, Encode},
7 v1::{
8 LogEntry, LogId, SignatureType,
9 extension::{CtExtensions, LeafIndex},
10 },
11};
12use serde::{Deserialize, Serialize};
13use sha2::{Digest, Sha256};
14use std::io::{Cursor, ErrorKind, IoSlice, Read, Write};
15
16impl CtLog {
17 pub fn validate_sct_v1(
18 &self,
19 cert: &CertificateChain,
20 sct: &SignedCertificateTimestamp,
21 as_precert: bool,
22 ) -> Result<(), SignatureValidationError> {
23 let timestamp = CertificateTimeStamp {
24 sct_version: Version::V1,
25 timestamp: sct.timestamp,
26 entry: cert
27 .as_log_entry_v1(as_precert)
28 .map_err(SignatureValidationError::CodecError)?,
29 extensions: sct.extensions.clone(),
30 };
31
32 sct.signature.validate(×tamp, &self.config.key)
33 }
34}
35
36#[derive(Debug, Clone, PartialEq, Eq)]
38pub(crate) struct SctList(Vec<SignedCertificateTimestamp>);
39
40impl SctList {
41 #[allow(dead_code)]
42 pub fn new(scts: Vec<SignedCertificateTimestamp>) -> Self {
43 Self(scts)
44 }
45
46 pub fn into_inner(self) -> Vec<SignedCertificateTimestamp> {
47 self.0
48 }
49}
50
51impl Encode for SctList {
52 fn encode(&self, mut writer: impl Write) -> Result<(), CodecError> {
53 let mut bytes = 0;
54 let mut encoded_scts = vec![];
55 for sct in &self.0 {
56 let mut buf = Cursor::new(vec![0, 0]);
57 buf.set_position(2);
58
59 sct.encode(&mut buf)?;
60 let mut buf = buf.into_inner();
61
62 let len = ((buf.len() - 2) as u16).to_be_bytes();
64 buf[0] = len[0];
65 buf[1] = len[1];
66
67 bytes += buf.len();
69 encoded_scts.push(buf);
70 }
71 let mut slices = encoded_scts
72 .iter()
73 .map(|buf| IoSlice::new(buf))
74 .collect::<Vec<_>>();
75
76 let bytes: u16 = bytes.try_into().map_err(|_| CodecError::UnexpectedSize {
77 read: bytes,
78 expected: u16::MAX as usize,
79 })?;
80
81 bytes.encode(&mut writer)?;
82
83 let mut slices: &mut [IoSlice] = &mut slices;
84 while !slices.is_empty() {
85 match writer.write_vectored(slices) {
86 Ok(0) => {
87 return Err(CodecError::IoError(std::io::ErrorKind::WriteZero));
88 }
89 Ok(n) => IoSlice::advance_slices(&mut slices, n),
90 Err(e) if e.kind() == ErrorKind::Interrupted => {}
91 Err(e) => return Err(e.into()),
92 }
93 }
94
95 Ok(())
96 }
97}
98
99impl Decode for SctList {
100 fn decode(mut reader: impl Read) -> Result<Self, CodecError> {
101 let length = u16::decode(&mut reader)?.into();
102 let mut scts = vec![];
103
104 let mut reader = reader.take(length);
105 loop {
106 match u16::decode(&mut reader) {
107 Ok(_) => (),
108 Err(CodecError::IoError(ErrorKind::UnexpectedEof)) => break,
109 Err(err) => return Err(err),
110 }
111
112 let sct = SignedCertificateTimestamp::decode(&mut reader)?;
113 scts.push(sct)
114 }
115
116 Ok(Self(scts))
117 }
118}
119
120#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
124pub struct SignedCertificateTimestamp {
125 pub(crate) sct_version: Version,
126 pub(crate) id: LogId,
127 pub(crate) timestamp: u64,
128 pub(crate) extensions: CtExtensions,
129 pub(crate) signature: Signature<CertificateTimeStamp>,
130}
131
132impl SignedCertificateTimestamp {
133 pub fn log_id(&self) -> crate::LogId {
134 crate::LogId::V1(self.id.clone())
135 }
136
137 pub fn timestamp(&self) -> u64 {
138 self.timestamp
139 }
140
141 pub fn leaf_index(&self) -> Option<LeafIndex> {
142 self.extensions.leaf_index()
143 }
144}
145
146impl Encode for SignedCertificateTimestamp {
147 fn encode(&self, mut writer: impl Write) -> Result<(), CodecError> {
148 self.sct_version.encode(&mut writer)?;
149 self.id.encode(&mut writer)?;
150 self.timestamp.encode(&mut writer)?;
151 self.extensions.encode(&mut writer)?;
152 self.signature.encode(&mut writer)?;
153 Ok(())
154 }
155}
156
157impl Decode for SignedCertificateTimestamp {
158 fn decode(mut reader: impl Read) -> Result<Self, CodecError> {
159 Ok(Self {
160 sct_version: Version::decode(&mut reader)?,
161 id: LogId::decode(&mut reader)?,
162 timestamp: u64::decode(&mut reader)?,
163 extensions: CtExtensions::decode(&mut reader)?,
164 signature: Signature::decode(&mut reader)?,
165 })
166 }
167}
168
169impl Hashable for SignedCertificateTimestamp {
170 fn hash(&self) -> HashOutput {
171 let mut bytes = Cursor::new(vec![]);
172 self.encode(&mut bytes).unwrap();
173 Sha256::digest(bytes.into_inner()).into()
174 }
175}
176
177#[derive(Debug, Clone, PartialEq, Eq)]
179pub(crate) struct CertificateTimeStamp {
180 sct_version: Version,
181 timestamp: u64,
183 entry: LogEntry,
184 extensions: CtExtensions,
185}
186
187impl Encode for CertificateTimeStamp {
188 fn encode(&self, mut writer: impl Write) -> Result<(), CodecError> {
189 self.sct_version.encode(&mut writer)?;
190 SignatureType::CertificateTimeStamp.encode(&mut writer)?;
191 self.timestamp.encode(&mut writer)?;
192 self.entry.encode(&mut writer)?;
193 self.extensions.encode(&mut writer)?;
194 Ok(())
195 }
196}
197
198impl Decode for CertificateTimeStamp {
199 fn decode(mut reader: impl Read) -> Result<Self, CodecError> {
200 let sct_version = Version::decode(&mut reader)?;
201 let signature_type = SignatureType::decode(&mut reader)?;
202 match signature_type {
203 SignatureType::TreeHash => return Err(CodecError::UnexpectedVariant),
204 SignatureType::CertificateTimeStamp => (),
205 }
206 let timestamp = u64::decode(&mut reader)?;
207 let entry = LogEntry::decode(&mut reader)?;
208 let extensions = CtExtensions::decode(&mut reader)?;
209
210 Ok(Self {
211 sct_version,
212 timestamp,
213 entry,
214 extensions,
215 })
216 }
217}