// Deep TLS Extension parsing details
///|
pub struct KeyShareEntry {
group : UInt16
key_exchange : Bytes
} derive(Debug, Eq)
///|
pub struct KeyShareClient {
client_shares : Array[KeyShareEntry]
} derive(Debug, Eq)
///|
pub struct KeyShareServer {
server_share : KeyShareEntry
} derive(Debug, Eq)
///|
pub struct SupportedVersionsClient {
versions : Array[UInt16]
} derive(Debug, Eq)
///|
pub struct ServerNameEntry {
name_type : Byte
name : String
} derive(Debug, Eq)
///|
pub struct ServerNameList {
names : Array[ServerNameEntry]
} derive(Debug, Eq)
///|
pub struct TlsCookie {
cookie : Bytes
} derive(Debug, Eq)
///|
pub fn parse_key_share_client(
data : BytesView,
) -> Result[KeyShareClient, ParseError] {
if data.length() < 2 {
return Err(BadLength(field="key_share.client_length", offset=0))
}
guard read_u16_int(data, 0) is Some(shares_len) else {
return Err(BadLength(field="key_share.client_length", offset=0))
}
if shares_len < 0 || shares_len + 2 > data.length() {
return Err(BadLength(field="key_share.client_body", offset=2))
}
let shares : Array[KeyShareEntry] = []
let mut cursor = 2
let end = 2 + shares_len
while cursor + 4 <= end {
guard read_u16(data, cursor) is Some(group) else {
return Err(BadLength(field="key_share.client_group", offset=cursor))
}
guard read_u16_int(data, cursor + 2) is Some(key_len) else {
return Err(BadLength(field="key_share.client_key_len", offset=cursor + 2))
}
cursor = cursor + 4
if key_len < 0 ||
cursor + key_len > end ||
!has_range(data, cursor, key_len) {
return Err(BadLength(field="key_share.client_key_body", offset=cursor))
}
let key_arr = Array::new(capacity=key_len)
for i in 0.. Result[KeyShareServer, ParseError] {
if data.length() < 4 {
return Err(BadLength(field="key_share.server_header", offset=0))
}
guard read_u16(data, 0) is Some(group) else {
return Err(BadLength(field="key_share.server_group", offset=0))
}
guard read_u16_int(data, 2) is Some(key_len) else {
return Err(BadLength(field="key_share.server_key_len", offset=2))
}
if key_len < 0 || 4 + key_len > data.length() || !has_range(data, 4, key_len) {
return Err(BadLength(field="key_share.server_body", offset=4))
}
let key_arr = Array::new(capacity=key_len)
for i in 0.. Result[SupportedVersionsClient, ParseError] {
if data.length() < 1 {
return Err(BadLength(field="supported_versions.client_length", offset=0))
}
let len = data[0].to_int()
if len < 0 || len + 1 > data.length() || len % 2 != 0 {
return Err(BadLength(field="supported_versions.client_body", offset=1))
}
let versions : Array[UInt16] = []
let mut cursor = 1
let end = 1 + len
while cursor + 2 <= end {
guard read_u16(data, cursor) is Some(ver) else {
return Err(
BadLength(field="supported_versions.client_version", offset=cursor),
)
}
if !is_grease(ver) {
versions.push(ver)
}
cursor = cursor + 2
}
Ok({ versions, })
}
///|
pub fn parse_server_name_list(
data : BytesView,
) -> Result[ServerNameList, ParseError] {
if data.length() < 2 {
return Err(BadLength(field="sni.list_len", offset=0))
}
guard read_u16_int(data, 0) is Some(list_len) else {
return Err(BadLength(field="sni.list_len", offset=0))
}
if list_len < 0 || list_len + 2 > data.length() {
return Err(BadLength(field="sni.list_body", offset=2))
}
let names : Array[ServerNameEntry] = []
let mut cursor = 2
let end = 2 + list_len
while cursor + 3 <= end {
let name_type = data[cursor]
guard read_u16_int(data, cursor + 1) is Some(name_len) else {
return Err(BadLength(field="sni.name_len", offset=cursor + 1))
}
cursor = cursor + 3
if name_len < 0 ||
cursor + name_len > end ||
!has_range(data, cursor, name_len) {
return Err(BadLength(field="sni.name_body", offset=cursor))
}
match bytes_to_ascii(data, cursor, name_len) {
Some(name) => names.push({ name_type, name })
None => ()
}
cursor = cursor + name_len
}
Ok({ names, })
}
///|
pub fn parse_tls_cookie(data : BytesView) -> Result[TlsCookie, ParseError] {
if data.length() < 2 {
return Err(BadLength(field="cookie.len", offset=0))
}
guard read_u16_int(data, 0) is Some(cookie_len) else {
return Err(BadLength(field="cookie.len", offset=0))
}
if cookie_len < 0 ||
cookie_len + 2 > data.length() ||
!has_range(data, 2, cookie_len) {
return Err(BadLength(field="cookie.body", offset=2))
}
let cookie_arr = Array::new(capacity=cookie_len)
for i in 0..