зеркало из https://github.com/microsoft/ivy.git
quic15 finishes one full test with encryption
This commit is contained in:
Родитель
700cc0b7e5
Коммит
b2e8d64c0c
|
@ -12,6 +12,8 @@ object quic_deser = {}
|
|||
|
||||
<<< impl
|
||||
|
||||
#define QUIC_DESER_FAKE_CHECKSUM_LENGTH 0
|
||||
|
||||
class `quic_deser` : public ivy_binary_deser {
|
||||
enum {quic_s_init,
|
||||
quic_s_type,
|
||||
|
@ -145,9 +147,9 @@ object quic_deser = {}
|
|||
{
|
||||
fence = 0;
|
||||
if (payload_length > 0) {
|
||||
fence = pos + payload_length - 16;
|
||||
fence = pos + payload_length - QUIC_DESER_FAKE_CHECKSUM_LENGTH;
|
||||
} else {
|
||||
fence = inp.size() - 16;
|
||||
fence = inp.size() - QUIC_DESER_FAKE_CHECKSUM_LENGTH;
|
||||
}
|
||||
get_pkt_num(res);
|
||||
state = quic_s_payload;
|
||||
|
@ -452,7 +454,7 @@ object quic_deser = {}
|
|||
void close_list() {
|
||||
if (state == quic_s_payload) {
|
||||
state = quic_s_init;
|
||||
pos += 16; // skip the checksum
|
||||
pos += QUIC_DESER_FAKE_CHECKSUM_LENGTH; // skip the fake checksum
|
||||
}
|
||||
if (state == quic_s_retry_token) {
|
||||
state = quic_s_payload_length;
|
||||
|
|
|
@ -48,6 +48,18 @@ module quic_protection(tls_id,tls) = {
|
|||
var pnum_pos := h.pkt_num_pos;
|
||||
var pnum_len := get_pnum_len(pkt,pnum_pos);
|
||||
var hdr_len := pnum_pos + pnum_len;
|
||||
|
||||
# Tricky: before encrypting the payload, we need to adjust the length field
|
||||
# so that it includes the aead checksum. Of course, we don't know what
|
||||
# that actually is. Here we assume it is 16 bytes. Even worse, the length of
|
||||
# the length field could grow. Here, we assume the length field format is
|
||||
# always two bytes.
|
||||
if h.hdr_long {
|
||||
var new_len := to_var_int_16(h.payload_length+16);
|
||||
pkt := pkt.set(pnum_pos-2,new_len.value(0));
|
||||
pkt := pkt.set(pnum_pos-1,new_len.value(1));
|
||||
};
|
||||
|
||||
var hdr := pkt.segment(0,pnum_pos);
|
||||
var pnum := pkt.segment(pnum_pos,hdr_len);
|
||||
var pyld := pkt.segment(hdr_len,pkt.end);
|
||||
|
@ -99,8 +111,14 @@ module quic_protection(tls_id,tls) = {
|
|||
var new_seq := get_pnum(pnum,0,pnum_len);
|
||||
new_seq := correct_pnum(seq,new_seq,pnum_len);
|
||||
var pyld := pkt.segment(pnum_pos + pnum_len,pkt.end);
|
||||
var res := tls.decrypt_aead(c,level,pyld,new_seq,hdr);
|
||||
res := tls.decrypt_aead(c,level,pyld,new_seq,hdr);
|
||||
if res.ok {
|
||||
# fix up the length field to account for removal of checksum
|
||||
if h.hdr_long {
|
||||
var new_len := to_var_int_16(h.payload_length-16);
|
||||
hdr := hdr.set(pnum_pos-2,new_len.value(0));
|
||||
hdr := hdr.set(pnum_pos-1,new_len.value(1));
|
||||
};
|
||||
res.data := hdr.extend(res.data);
|
||||
}
|
||||
}
|
||||
|
@ -137,10 +155,12 @@ module quic_protection(tls_id,tls) = {
|
|||
h.dcid := bytes_to_cid(pkt.segment(6,6+dcil));
|
||||
h.scid := bytes_to_cid(pkt.segment(6+dcil,6+dcil+scil));
|
||||
var pos := 6 + dcil + scil;
|
||||
if h.hdr_type = 0x7f {
|
||||
var len := get_var_int_len(pkt,pos);
|
||||
var retry_token_len := get_var_int(pkt,pos,len);
|
||||
pos := pos + len + retry_token_len;
|
||||
};
|
||||
var len := get_var_int_len(pkt,pos);
|
||||
var retry_token_len := get_var_int(pkt,pos,len);
|
||||
pos := pos + len + retry_token_len;
|
||||
len := get_var_int_len(pkt,pos);
|
||||
h.payload_length := get_var_int(pkt,pos,len);
|
||||
h.pkt_num_pos := pos + len;
|
||||
}
|
||||
|
@ -226,6 +246,13 @@ module quic_protection(tls_id,tls) = {
|
|||
}
|
||||
}
|
||||
|
||||
action to_var_int_16(val:stream_pos) returns (bytes:stream_data) = {
|
||||
<<<
|
||||
bytes.push_back(0x40 | (val >> 8) & 0x3f);
|
||||
bytes.push_back(val & 0xff);
|
||||
>>>
|
||||
}
|
||||
|
||||
action bytes_to_cid(bytes:stream_data) returns (val:cid) = {
|
||||
<<<
|
||||
val.val = 0;
|
||||
|
@ -285,16 +312,16 @@ object quic_prot_deser = {}
|
|||
<<< impl
|
||||
|
||||
class `quic_prot_deser` : public ivy_binary_deser {
|
||||
unsigned data_remaining;
|
||||
int data_remaining;
|
||||
int level;
|
||||
public:
|
||||
quic_prot_deser(const std::vector<char> &inp) : ivy_binary_deser(inp),level(0) {}
|
||||
|
||||
void get(long long res) {
|
||||
void get(long long &res) {
|
||||
getn(res,1);
|
||||
}
|
||||
|
||||
char peek(unsigned p) {
|
||||
unsigned char peek(unsigned p) {
|
||||
return more(p-pos+1) ? inp[p] : 0;
|
||||
}
|
||||
|
||||
|
@ -320,27 +347,31 @@ object quic_prot_deser = {}
|
|||
dcil = (dcil != 0) ? dcil + 3 : 0;
|
||||
scil = (scil != 0) ? scil + 3 : 0;
|
||||
unsigned pnum_pos = pos + 6 + dcil + scil;
|
||||
if (peek(pos) == 0xff) { // initial packets have tokens
|
||||
unsigned len = get_var_int_len(pnum_pos);
|
||||
unsigned retry_token_len = get_var_int(pnum_pos,len);
|
||||
pnum_pos = pnum_pos + len + retry_token_len;
|
||||
}
|
||||
unsigned len = get_var_int_len(pnum_pos);
|
||||
unsigned retry_token_len = get_var_int(pnum_pos,len);
|
||||
pnum_pos = pnum_pos + len + retry_token_len;
|
||||
len = get_var_int_len(pnum_pos);
|
||||
unsigned pyld_len = get_var_int(pnum_pos,len);
|
||||
data_remaining = pnum_pos + len + pyld_len;
|
||||
}
|
||||
else {
|
||||
data_remaining = 0xffffffff;
|
||||
data_remaining = 0x7fffffff;
|
||||
}
|
||||
}
|
||||
|
||||
bool open_list_elem() {
|
||||
level++;
|
||||
if (!more(1)) {
|
||||
return false;
|
||||
}
|
||||
if (level == 2) {
|
||||
return data_remaining-- > 0;
|
||||
bool res = true;
|
||||
if (level == 1) {
|
||||
res = data_remaining-- > 0;
|
||||
}
|
||||
return true;
|
||||
if (res)
|
||||
level++;
|
||||
return res;
|
||||
}
|
||||
void close_list_elem() {
|
||||
level--;
|
||||
|
|
|
@ -145,8 +145,13 @@ implement botan.lower.send(tls_id:botan.id,bytes:stream_data) {
|
|||
}
|
||||
}
|
||||
|
||||
after tls_send_event(src:ip.endpoint, dst:ip.endpoint, scid:cid, dcid:cid, data : stream_data) {
|
||||
after tls_send_event(src:ip.endpoint, dst:ip.endpoint, scid:cid, dcid:cid, data : stream_data, e:encryption_level) {
|
||||
call show_tls_send_event(src,dst,scid,dcid,data);
|
||||
# HACK: send crypto data to client TLS right away, else we won't have the keys when next packet arrives.
|
||||
# Really this should happen on a tls_recv_event, but this is too late.
|
||||
if dst = client.ep | dst = client_alt {
|
||||
call botan.lower.recv(client.tls_id,data);
|
||||
}
|
||||
}
|
||||
|
||||
# Assume that initial packets are sent only to the server under test
|
||||
|
@ -249,16 +254,18 @@ instance pkt_serdes : serdes(quic_packet,stream_data,quic_ser,quic_deser)
|
|||
# QUIC packet per UDP datagram.
|
||||
|
||||
after packet_event(src:ip.endpoint,dst:ip.endpoint,pkt:quic_packet) {
|
||||
var spkt := pkt_serdes.to_bytes(pkt);
|
||||
var rnum := reference_pkt_num(spkt);
|
||||
var ppkt := prot.encrypt(client.tls_id,rnum,spkt);
|
||||
var pkts := prot.arr.empty;
|
||||
pkts := pkts.append(ppkt);
|
||||
if src = client.ep {
|
||||
call net.send(endpoint_id.client,sock,dst,pkts);
|
||||
} else if src = client_alt {
|
||||
call net.send(endpoint_id.client_alt,sock_alt,dst,pkts);
|
||||
}
|
||||
if src = client.ep | src = client_alt {
|
||||
var spkt := pkt_serdes.to_bytes(pkt);
|
||||
var rnum := reference_pkt_num(spkt);
|
||||
var ppkt := prot.encrypt(client.tls_id,rnum,spkt);
|
||||
var pkts := prot.arr.empty;
|
||||
pkts := pkts.append(ppkt);
|
||||
if src = client.ep {
|
||||
call net.send(endpoint_id.client,sock,dst,pkts);
|
||||
} else if src = client_alt {
|
||||
call net.send(endpoint_id.client_alt,sock_alt,dst,pkts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# When an packet arrives at the client endpoint, decrypt it, deserialize it,
|
||||
|
@ -312,7 +319,7 @@ around tls_recv_event(src:ip.endpoint, dst:ip.endpoint, scid:cid, dcid:cid, e:en
|
|||
data := data.append(crypto_data(scid,e).value(idx));
|
||||
idx := idx.next
|
||||
};
|
||||
call botan.lower.recv(tls_id,data)
|
||||
# call botan.lower.recv(tls_id,data)
|
||||
}
|
||||
|
||||
action hi_byte_pos(x:stream_pos) returns (res:byte) = {
|
||||
|
|
|
@ -396,6 +396,12 @@ module tls_gnutls(cid,index,bytes,extens,exten_ser,lower,upper) = {
|
|||
|
||||
picotls_connection *s = `cid_map`[c];
|
||||
ptls_cipher_context_t *pn_enc = (ptls_cipher_context_t *)(s->crypto_context[l].pn_enc);
|
||||
if (!pn_enc)
|
||||
pn_enc = (ptls_cipher_context_t *)(s->crypto_context[l].pn_dec);
|
||||
if (!pn_enc) {
|
||||
std::cerr << "cipher for level " << l << " is not set\n";
|
||||
exit(1);
|
||||
}
|
||||
sz = pn_enc->algo->iv_size;
|
||||
|
||||
>>>
|
||||
|
@ -456,7 +462,7 @@ module tls_gnutls(cid,index,bytes,extens,exten_ser,lower,upper) = {
|
|||
std::vector<uint8_t> input, output;
|
||||
input.resize(cipher.size());
|
||||
std::copy(cipher.begin(),cipher.end(),input.begin());
|
||||
output.resize(cipher.size() + checksum_length);
|
||||
output.resize(cipher.size() - checksum_length);
|
||||
size_t decrypted = ptls_aead_decrypt(aead,
|
||||
&output[0], &input[0], input.size(), seq,
|
||||
&bytes[0], bytes.size());
|
||||
|
|
Загрузка…
Ссылка в новой задаче