Allow applications to pass data through resumption tickets

Needed for QUIC and HTTP/3.
This commit is contained in:
Benjamin Saunders 2019-09-19 19:37:06 -07:00 committed by ctz
parent 431f42b662
commit 0e2649b80e
5 changed files with 47 additions and 4 deletions

View File

@ -172,6 +172,7 @@ pub struct ServerSessionValue {
pub extended_ms: bool,
pub client_cert_chain: Option<CertificatePayload>,
pub alpn: Option<PayloadU8>,
pub application_data: PayloadU16,
}
impl Codec for ServerSessionValue {
@ -199,6 +200,7 @@ impl Codec for ServerSessionValue {
} else {
0u8.encode(bytes);
}
self.application_data.encode(bytes);
}
fn read(r: &mut Reader) -> Option<ServerSessionValue> {
@ -227,6 +229,7 @@ impl Codec for ServerSessionValue {
} else {
None
};
let application_data = PayloadU16::read(r)?;
Some(ServerSessionValue {
sni,
@ -236,6 +239,7 @@ impl Codec for ServerSessionValue {
extended_ms: ems == 1u8,
client_cert_chain: ccert,
alpn,
application_data,
})
}
}
@ -246,7 +250,8 @@ impl ServerSessionValue {
cs: CipherSuite,
ms: Vec<u8>,
cert_chain: &Option<CertificatePayload>,
alpn: Option<Vec<u8>>)
alpn: Option<Vec<u8>>,
application_data: Vec<u8>)
-> ServerSessionValue {
ServerSessionValue {
sni: sni.cloned(),
@ -256,6 +261,7 @@ impl ServerSessionValue {
extended_ms: false,
client_cert_chain: cert_chain.clone(),
alpn: alpn.map(PayloadU8::new),
application_data: PayloadU16::new(application_data),
}
}

View File

@ -35,7 +35,8 @@ fn serversessionvalue_is_debug() {
CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
vec![1, 2, 3],
&None,
None);
None,
vec![4, 5, 6]);
println!("{:?}", ssv);
}
@ -47,6 +48,7 @@ fn serversessionvalue_no_sni() {
0xc0, 0x23,
0x03, 0x01, 0x02, 0x03,
0x00, 0x00, 0x00,
0x00, 0x00,
];
let mut rd = Reader::init(&bytes);
let ssv = ServerSessionValue::read(&mut rd).unwrap();
@ -62,6 +64,7 @@ fn serversessionvalue_with_cert() {
0x03, 0x01, 0x02, 0x03,
0x00,
0x00, 0x00,
0x00, 0x00,
];
let mut rd = Reader::init(&bytes);
let ssv = ServerSessionValue::read(&mut rd).unwrap();

View File

@ -302,6 +302,8 @@ pub struct ServerSessionImpl {
sni: Option<webpki::DNSName>,
pub alpn_protocol: Option<Vec<u8>>,
pub quic_params: Option<Vec<u8>>,
pub received_resumption_data: Option<Vec<u8>>,
pub resumption_data: Vec<u8>,
pub error: Option<TLSError>,
pub state: Option<Box<dyn hs::State + Send + Sync>>,
pub client_cert_chain: Option<Vec<key::Certificate>>,
@ -322,6 +324,8 @@ impl ServerSessionImpl {
sni: None,
alpn_protocol: None,
quic_params: None,
received_resumption_data: None,
resumption_data: Vec::new(),
error: None,
state: Some(Box::new(hs::ExpectClientHello::new(server_config, extra_exts))),
client_cert_chain: None,
@ -507,6 +511,28 @@ impl ServerSession {
pub fn get_sni_hostname(&self)-> Option<&str> {
self.imp.get_sni().map(|s| s.as_ref().into())
}
/// Application-controlled portion of the resumption ticket supplied by the client, if any.
///
/// Recovered from the prior session's `set_resumption_data`. Integrity is guaranteed by rustls.
///
/// Returns `Some` iff a valid resumption ticket has been received from the client.
pub fn received_resumption_data(&self) -> Option<&[u8]> {
self.imp.received_resumption_data.as_ref().map(|x| &x[..])
}
/// Set the resumption data to embed in future resumption tickets supplied to the client.
///
/// Defaults to the empty byte string. Must be less than 2^15 bytes to allow room for other
/// data. Should be called while `is_handshaking` returns true to ensure all transmitted
/// resumption tickets are affected.
///
/// Integrity will be assured by rustls, but the data will be visible to the client. If secrecy
/// from the client is desired, encrypt the data separately.
pub fn set_resumption_data(&mut self, data: &[u8]) {
assert!(data.len() < 2usize.pow(15));
self.imp.resumption_data = data.into();
}
}
impl Session for ServerSession {

View File

@ -236,7 +236,9 @@ fn get_server_session_value_tls12(handshake: &HandshakeDetails,
sess.get_sni(), version,
scs.suite, secret,
&sess.client_cert_chain,
sess.alpn_protocol.clone());
sess.alpn_protocol.clone(),
sess.resumption_data.clone(),
);
if handshake.using_ems {
v.set_extended_ms_used();

View File

@ -569,6 +569,10 @@ impl CompleteClientHelloHandling {
self.send_ticket = true;
}
if let Some(ref resume) = resumedata {
sess.received_resumption_data = Some(resume.application_data.0.clone());
}
let full_handshake = resumedata.is_none();
self.handshake.transcript.add_message(chm);
self.emit_server_hello(sess, &client_hello.session_id,
@ -731,7 +735,9 @@ fn get_server_session_value(handshake: &mut HandshakeDetails,
sess.get_sni(), version,
scs.suite, secret,
&sess.client_cert_chain,
sess.alpn_protocol.clone())
sess.alpn_protocol.clone(),
sess.resumption_data.clone(),
)
}
pub struct ExpectFinished {