quic15 finishes one full test with encryption

This commit is contained in:
Ken McMillan 2018-11-15 18:37:08 -08:00
Родитель 700cc0b7e5
Коммит b2e8d64c0c
4 изменённых файлов: 77 добавлений и 31 удалений

Просмотреть файл

@ -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());