mirror of https://github.com/ctz/rustls
Start SCT extension support
This commit is contained in:
parent
a7a36f9f0c
commit
df361f832b
|
@ -240,6 +240,7 @@ fn emit_client_hello_for_retry(sess: &mut ClientSessionImpl,
|
|||
exts.push(ClientExtension::SignatureAlgorithms(SupportedSignatureSchemes::supported_verify()));
|
||||
exts.push(ClientExtension::ExtendedMasterSecretRequest);
|
||||
exts.push(ClientExtension::CertificateStatusRequest(CertificateStatusRequest::build_ocsp()));
|
||||
exts.push(ClientExtension::SignedCertificateTimestampRequest);
|
||||
|
||||
if support_tls13 {
|
||||
exts.push(ClientExtension::KeyShare(key_shares));
|
||||
|
|
|
@ -206,6 +206,7 @@ enum_builder! {@U16
|
|||
UseSRTP => 0x000e,
|
||||
Heartbeat => 0x000f,
|
||||
ALProtocolNegotiation => 0x0010,
|
||||
SCT => 0x0012,
|
||||
Padding => 0x0015,
|
||||
ExtendedMasterSecret => 0x0017,
|
||||
SessionTicket => 0x0023,
|
||||
|
|
|
@ -585,6 +585,7 @@ pub enum ClientExtension {
|
|||
Cookie(PayloadU16),
|
||||
ExtendedMasterSecretRequest,
|
||||
CertificateStatusRequest(CertificateStatusRequest),
|
||||
SignedCertificateTimestampRequest,
|
||||
Unknown(UnknownExtension),
|
||||
}
|
||||
|
||||
|
@ -606,6 +607,7 @@ impl ClientExtension {
|
|||
ClientExtension::Cookie(_) => ExtensionType::Cookie,
|
||||
ClientExtension::ExtendedMasterSecretRequest => ExtensionType::ExtendedMasterSecret,
|
||||
ClientExtension::CertificateStatusRequest(_) => ExtensionType::StatusRequest,
|
||||
ClientExtension::SignedCertificateTimestampRequest => ExtensionType::SCT,
|
||||
ClientExtension::Unknown(ref r) => r.typ,
|
||||
}
|
||||
}
|
||||
|
@ -623,7 +625,8 @@ impl Codec for ClientExtension {
|
|||
ClientExtension::Heartbeat(ref r) => r.encode(&mut sub),
|
||||
ClientExtension::ServerName(ref r) => r.encode(&mut sub),
|
||||
ClientExtension::SessionTicketRequest |
|
||||
ClientExtension::ExtendedMasterSecretRequest => (),
|
||||
ClientExtension::ExtendedMasterSecretRequest |
|
||||
ClientExtension::SignedCertificateTimestampRequest => (),
|
||||
ClientExtension::SessionTicketOffer(ref r) => r.encode(&mut sub),
|
||||
ClientExtension::Protocols(ref r) => r.encode(&mut sub),
|
||||
ClientExtension::SupportedVersions(ref r) => r.encode(&mut sub),
|
||||
|
@ -691,6 +694,9 @@ impl Codec for ClientExtension {
|
|||
let csr = try_ret!(CertificateStatusRequest::read(&mut sub));
|
||||
ClientExtension::CertificateStatusRequest(csr)
|
||||
}
|
||||
ExtensionType::SCT if !sub.any_left() => {
|
||||
ClientExtension::SignedCertificateTimestampRequest
|
||||
}
|
||||
_ => ClientExtension::Unknown(try_ret!(UnknownExtension::read(typ, &mut sub))),
|
||||
})
|
||||
}
|
||||
|
@ -828,6 +834,7 @@ pub enum ServerExtension {
|
|||
PresharedKey(u16),
|
||||
ExtendedMasterSecretAck,
|
||||
CertificateStatusAck,
|
||||
SignedCertificateTimestamp(Payload),
|
||||
Unknown(UnknownExtension),
|
||||
}
|
||||
|
||||
|
@ -844,6 +851,7 @@ impl ServerExtension {
|
|||
ServerExtension::PresharedKey(_) => ExtensionType::PreSharedKey,
|
||||
ServerExtension::ExtendedMasterSecretAck => ExtensionType::ExtendedMasterSecret,
|
||||
ServerExtension::CertificateStatusAck => ExtensionType::StatusRequest,
|
||||
ServerExtension::SignedCertificateTimestamp(_) => ExtensionType::SCT,
|
||||
ServerExtension::Unknown(ref r) => r.typ,
|
||||
}
|
||||
}
|
||||
|
@ -865,6 +873,7 @@ impl Codec for ServerExtension {
|
|||
ServerExtension::Protocols(ref r) => r.encode(&mut sub),
|
||||
ServerExtension::KeyShare(ref r) => r.encode(&mut sub),
|
||||
ServerExtension::PresharedKey(r) => codec::encode_u16(r, &mut sub),
|
||||
ServerExtension::SignedCertificateTimestamp(ref r) => r.encode(&mut sub),
|
||||
ServerExtension::Unknown(ref r) => r.encode(&mut sub),
|
||||
}
|
||||
|
||||
|
@ -900,6 +909,9 @@ impl Codec for ServerExtension {
|
|||
ServerExtension::PresharedKey(try_ret!(codec::read_u16(&mut sub)))
|
||||
}
|
||||
ExtensionType::ExtendedMasterSecret => ServerExtension::ExtendedMasterSecretAck,
|
||||
ExtensionType::SCT => {
|
||||
ServerExtension::SignedCertificateTimestamp(try_ret!(Payload::read(&mut sub)))
|
||||
}
|
||||
_ => ServerExtension::Unknown(try_ret!(UnknownExtension::read(typ, &mut sub))),
|
||||
})
|
||||
}
|
||||
|
@ -914,6 +926,10 @@ impl ServerExtension {
|
|||
let empty = Vec::new();
|
||||
ServerExtension::RenegotiationInfo(PayloadU8::new(empty))
|
||||
}
|
||||
|
||||
pub fn make_sct(sctl: Vec<u8>) -> ServerExtension {
|
||||
ServerExtension::SignedCertificateTimestamp(Payload::new(sctl))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -1339,6 +1355,7 @@ impl Codec for CertificatePayload {
|
|||
#[derive(Debug)]
|
||||
pub enum CertificateExtension {
|
||||
CertificateStatus(CertificateStatus),
|
||||
SignedCertificateTimestamp(Payload),
|
||||
Unknown(UnknownExtension),
|
||||
}
|
||||
|
||||
|
@ -1346,9 +1363,14 @@ impl CertificateExtension {
|
|||
pub fn get_type(&self) -> ExtensionType {
|
||||
match *self {
|
||||
CertificateExtension::CertificateStatus(_) => ExtensionType::StatusRequest,
|
||||
CertificateExtension::SignedCertificateTimestamp(_) => ExtensionType::SCT,
|
||||
CertificateExtension::Unknown(ref r) => r.typ,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_sct(sct_list: Vec<u8>) -> CertificateExtension {
|
||||
CertificateExtension::SignedCertificateTimestamp(Payload::new(sct_list))
|
||||
}
|
||||
}
|
||||
|
||||
impl Codec for CertificateExtension {
|
||||
|
@ -1358,6 +1380,7 @@ impl Codec for CertificateExtension {
|
|||
let mut sub: Vec<u8> = Vec::new();
|
||||
match *self {
|
||||
CertificateExtension::CertificateStatus(ref r) => r.encode(&mut sub),
|
||||
CertificateExtension::SignedCertificateTimestamp(ref r) => r.encode(&mut sub),
|
||||
CertificateExtension::Unknown(ref r) => r.encode(&mut sub),
|
||||
}
|
||||
|
||||
|
@ -1372,7 +1395,12 @@ impl Codec for CertificateExtension {
|
|||
|
||||
Some(match typ {
|
||||
ExtensionType::StatusRequest => {
|
||||
CertificateExtension::CertificateStatus(try_ret!(CertificateStatus::read(&mut sub)))
|
||||
let st = try_ret!(CertificateStatus::read(&mut sub));
|
||||
CertificateExtension::CertificateStatus(st)
|
||||
}
|
||||
ExtensionType::SCT => {
|
||||
let scts = try_ret!(Payload::read(&mut sub));
|
||||
CertificateExtension::SignedCertificateTimestamp(scts)
|
||||
}
|
||||
_ => CertificateExtension::Unknown(try_ret!(UnknownExtension::read(typ, &mut sub))),
|
||||
})
|
||||
|
|
|
@ -397,6 +397,7 @@ pub struct ServerHandshakeData {
|
|||
pub doing_resume: bool,
|
||||
pub send_ticket: bool,
|
||||
pub send_cert_status: bool,
|
||||
pub send_sct: bool,
|
||||
pub using_ems: bool,
|
||||
pub doing_client_auth: bool,
|
||||
pub done_retry: bool,
|
||||
|
@ -414,6 +415,7 @@ impl ServerHandshakeData {
|
|||
kx_data: None,
|
||||
send_ticket: false,
|
||||
send_cert_status: false,
|
||||
send_sct: false,
|
||||
using_ems: false,
|
||||
doing_resume: false,
|
||||
doing_client_auth: false,
|
||||
|
|
|
@ -102,6 +102,22 @@ fn process_extensions(sess: &mut ServerSessionImpl,
|
|||
}
|
||||
}
|
||||
|
||||
if !for_resume &&
|
||||
hello.find_extension(ExtensionType::SCT).is_some() &&
|
||||
sess.handshake_data.server_certkey.is_some() &&
|
||||
sess.handshake_data.server_certkey.as_ref().unwrap().has_sct_list() {
|
||||
sess.handshake_data.send_sct = true;
|
||||
|
||||
if !sess.common.is_tls13() {
|
||||
let sct_list = sess.handshake_data.server_certkey
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.take_sct_list()
|
||||
.unwrap();
|
||||
ret.push(ServerExtension::make_sct(sct_list));
|
||||
}
|
||||
}
|
||||
|
||||
if !sess.common.is_tls13() {
|
||||
// Renegotiation.
|
||||
// (We don't do reneg at all, but would support the secure version if we did.)
|
||||
|
@ -492,9 +508,9 @@ fn emit_certificate_req_tls13(sess: &mut ServerSessionImpl) {
|
|||
fn emit_certificate_tls13(sess: &mut ServerSessionImpl) {
|
||||
let mut cert_body = CertificatePayloadTLS13::new();
|
||||
|
||||
let (certs, ocsp) = {
|
||||
let (certs, ocsp, sct_list) = {
|
||||
let ck = sess.handshake_data.server_certkey.as_mut().unwrap();
|
||||
(ck.take_cert(), ck.take_ocsp())
|
||||
(ck.take_cert(), ck.take_ocsp(), ck.take_sct_list())
|
||||
};
|
||||
|
||||
for cert in certs {
|
||||
|
@ -516,6 +532,14 @@ fn emit_certificate_tls13(sess: &mut ServerSessionImpl) {
|
|||
last_entry.exts.push(CertificateExtension::CertificateStatus(cst));
|
||||
}
|
||||
|
||||
// Likewise, SCT
|
||||
if sess.handshake_data.send_sct &&
|
||||
sct_list.is_some() &&
|
||||
!cert_body.list.is_empty() {
|
||||
let last_entry = cert_body.list.last_mut().unwrap();
|
||||
last_entry.exts.push(CertificateExtension::make_sct(sct_list.unwrap()));
|
||||
}
|
||||
|
||||
let c = Message {
|
||||
typ: ContentType::Handshake,
|
||||
version: ProtocolVersion::TLSv1_3,
|
||||
|
|
19
src/sign.rs
19
src/sign.rs
|
@ -47,15 +47,16 @@ pub struct CertifiedKey {
|
|||
/// attesting to its continued validity.
|
||||
pub ocsp: Option<Vec<u8>>,
|
||||
|
||||
/// An optional SCT response from a CT log, proving the
|
||||
/// certificate is included on that log.
|
||||
pub sct: Option<Vec<u8>>,
|
||||
/// An optional collection of SCTs from CT logs, proving the
|
||||
/// certificate is included on those logs. This must be
|
||||
/// a `SignedCertificateTimestampList` encoding; see RFC6962.
|
||||
pub sct_list: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl CertifiedKey {
|
||||
/// Make a new CertifiedKey, with the given chain and key.
|
||||
pub fn new(cert: Vec<key::Certificate>, key: Arc<Box<SigningKey>>) -> CertifiedKey {
|
||||
CertifiedKey { cert: cert, key: key, ocsp: None, sct: None }
|
||||
CertifiedKey { cert: cert, key: key, ocsp: None, sct_list: None }
|
||||
}
|
||||
|
||||
/// Steal ownership of the certificate chain.
|
||||
|
@ -72,6 +73,16 @@ impl CertifiedKey {
|
|||
pub fn take_ocsp(&mut self) -> Option<Vec<u8>> {
|
||||
mem::replace(&mut self.ocsp, None)
|
||||
}
|
||||
|
||||
/// Return true if there's an SCT list.
|
||||
pub fn has_sct_list(&self) -> bool {
|
||||
self.sct_list.is_some()
|
||||
}
|
||||
|
||||
/// Steal ownership of the SCT list.
|
||||
pub fn take_sct_list(&mut self) -> Option<Vec<u8>> {
|
||||
mem::replace(&mut self.sct_list, None)
|
||||
}
|
||||
}
|
||||
|
||||
/// A SigningKey for RSA-PKCS1 or RSA-PSS
|
||||
|
|
Loading…
Reference in New Issue