mirror of https://github.com/ctz/rustls
Allow applications to pass data through resumption tickets
Needed for QUIC and HTTP/3.
This commit is contained in:
parent
431f42b662
commit
0e2649b80e
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue