Skip to main content

luct_core/
v1.rs

1use crate::utils::{
2    codec::{CodecError, Decode, Encode},
3    codec_vec::CodecVec,
4    u24::U24,
5};
6use base64::{Engine, prelude::BASE64_STANDARD};
7pub(crate) use sct::SctList;
8use serde::{Deserialize, Serialize};
9use std::{
10    fmt::{self, Display},
11    io::{Read, Write},
12};
13use x509_cert::{
14    certificate::{CertificateInner, Rfc5280, TbsCertificateInner},
15    der::{Decode as DerDecode, Encode as DerEncode},
16};
17
18pub(crate) mod extension;
19pub(crate) mod proof;
20pub mod responses;
21pub(crate) mod roots;
22pub(crate) mod sct;
23pub(crate) mod sth;
24pub(crate) mod tree;
25
26pub use sct::SignedCertificateTimestamp;
27pub use sth::SignedTreeHead;
28pub use tree::MerkleTreeLeaf;
29
30// TODO(Submission support): Requests and responses for submission
31
32// TODO: LogEntryChain type
33
34#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
35pub struct LogId(pub(crate) [u8; 32]);
36
37impl fmt::Debug for LogId {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        f.debug_tuple("LogId").field(&hex::encode(self.0)).finish()
40    }
41}
42
43impl Display for LogId {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        write!(f, "{}", BASE64_STANDARD.encode(self.0))
46    }
47}
48
49impl TryFrom<&str> for LogId {
50    type Error = ();
51
52    fn try_from(value: &str) -> Result<Self, Self::Error> {
53        let vec = BASE64_STANDARD.decode(value).map_err(|_| ())?;
54        let array = vec.try_into().map_err(|_| ())?;
55        Ok(Self(array))
56    }
57}
58
59impl Encode for LogId {
60    fn encode(&self, mut writer: impl Write) -> Result<(), CodecError> {
61        Ok(writer.write_all(&self.0)?)
62    }
63}
64
65impl Decode for LogId {
66    fn decode(mut reader: impl Read) -> Result<Self, CodecError> {
67        let mut buf = [0u8; 32];
68        reader.read_exact(&mut buf)?;
69
70        Ok(Self(buf))
71    }
72}
73
74/// See RFC 5246 3.2
75#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
76pub(crate) enum SignatureType {
77    CertificateTimeStamp,
78    TreeHash,
79}
80
81impl Encode for SignatureType {
82    fn encode(&self, mut writer: impl Write) -> Result<(), CodecError> {
83        let discriminant = match self {
84            SignatureType::CertificateTimeStamp => 0,
85            SignatureType::TreeHash => 1,
86        };
87        Ok(writer.write_all(&[discriminant])?)
88    }
89}
90
91impl Decode for SignatureType {
92    fn decode(mut reader: impl Read) -> Result<Self, CodecError> {
93        let mut buf = vec![0u8];
94        reader.read_exact(&mut buf)?;
95
96        match buf[0] {
97            0 => Ok(SignatureType::CertificateTimeStamp),
98            1 => Ok(SignatureType::TreeHash),
99            x => Err(CodecError::UnknownVariant("SignatureType", x as u64)),
100        }
101    }
102}
103
104// See RFC 6962 3.2
105#[derive(Debug, Clone, PartialEq, Eq)]
106pub(crate) enum LogEntry {
107    X509(CertificateInner<Rfc5280>),
108    PreCert(PreCert),
109}
110
111impl Encode for LogEntry {
112    fn encode(&self, mut writer: impl Write) -> Result<(), CodecError> {
113        match self {
114            LogEntry::X509(cert) => {
115                writer.write_all(&[0, 0])?;
116
117                let mut cert_bytes = vec![];
118                let _len = cert.encode_to_vec(&mut cert_bytes)?;
119                CodecVec::<U24>::from(cert_bytes).encode(&mut writer)?;
120            }
121            LogEntry::PreCert(pre_cert) => {
122                writer.write_all(&[0, 1])?;
123                pre_cert.encode(&mut writer)?;
124            }
125        };
126
127        Ok(())
128    }
129}
130
131impl Decode for LogEntry {
132    fn decode(mut reader: impl Read) -> Result<Self, CodecError> {
133        let mut buf = [0u8; 2];
134        reader.read_exact(&mut buf)?;
135        let entry = u16::from_be_bytes(buf);
136
137        match entry {
138            0 => {
139                let cert_bytes = CodecVec::<U24>::decode(&mut reader)?;
140                let cert = CertificateInner::<Rfc5280>::from_der(cert_bytes.as_ref())?;
141                Ok(LogEntry::X509(cert))
142            }
143            1 => Ok(LogEntry::PreCert(PreCert::decode(&mut reader)?)),
144            x => Err(CodecError::UnknownVariant("LogEntry", x as u64)),
145        }
146    }
147}
148
149/// A [`PreCert`] contains a X.509 `TbsCertificate` as well as a hash of the issuer key.
150///
151/// See RFC 6962 3.2
152#[derive(Debug, Clone, PartialEq, Eq)]
153pub(crate) struct PreCert {
154    pub(crate) issuer_key_hash: [u8; 32],
155    pub(crate) tbs_certificate: TbsCertificateInner<Rfc5280>,
156}
157
158impl Encode for PreCert {
159    fn encode(&self, mut writer: impl Write) -> Result<(), CodecError> {
160        Encode::encode(&self.issuer_key_hash, &mut writer)?;
161
162        let mut cert_bytes = vec![];
163        let _len = self.tbs_certificate.encode_to_vec(&mut cert_bytes)?;
164        CodecVec::<U24>::from(cert_bytes).encode(&mut writer)?;
165
166        Ok(())
167    }
168}
169
170impl Decode for PreCert {
171    fn decode(mut reader: impl Read) -> Result<Self, CodecError> {
172        let issuer_key_hash = <[u8; 32] as Decode>::decode(&mut reader)?;
173        let cert_bytes = CodecVec::<U24>::decode(&mut reader)?;
174        let tbs_certificate = TbsCertificateInner::<Rfc5280>::from_der(cert_bytes.as_ref())?;
175
176        Ok(Self {
177            issuer_key_hash,
178            tbs_certificate,
179        })
180    }
181}