Skip to content

Commit 4fc5ff6

Browse files
lukacanPavel Siska
authored andcommitted
QUIC: moved version parsing
1 parent 36b5740 commit 4fc5ff6

File tree

2 files changed

+157
-125
lines changed

2 files changed

+157
-125
lines changed

process/quic.cpp

Lines changed: 151 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,23 @@
4242
*/
4343

4444

45+
#include <iostream>
46+
#include <cstring>
47+
#include <sstream>
48+
#include <endian.h>
49+
50+
51+
#include <openssl/kdf.h>
52+
#include <openssl/evp.h>
53+
54+
#ifdef WITH_NEMEA
55+
#include <unirec/unirec.h>
56+
#endif
57+
58+
#include <ipfixprobe/byte-utils.hpp>
59+
60+
#include "quic.hpp"
61+
4562

4663

4764
// known versions
@@ -75,22 +92,10 @@ MVFST
7592
*/
7693

7794

78-
#include <iostream>
79-
#include <cstring>
80-
#include <sstream>
81-
#include <endian.h>
8295

8396

84-
#include <openssl/kdf.h>
85-
#include <openssl/evp.h>
8697

87-
#ifdef WITH_NEMEA
88-
#include <unirec/unirec.h>
89-
#endif
90-
91-
#include <ipfixprobe/byte-utils.hpp>
9298

93-
#include "quic.hpp"
9499

95100

96101

@@ -151,6 +156,10 @@ QUICPlugin::QUICPlugin()
151156

152157

153158
can_parse = false;
159+
160+
is_version2 = false;
161+
162+
salt = nullptr;
154163
}
155164

156165
QUICPlugin::~QUICPlugin()
@@ -168,6 +177,8 @@ void QUICPlugin::close()
168177
delete quic_ptr;
169178
}
170179
quic_ptr = nullptr;
180+
salt = nullptr;
181+
final_payload = nullptr;
171182
}
172183

173184
ProcessPlugin *QUICPlugin::copy()
@@ -569,108 +580,8 @@ bool QUICPlugin::quic_check_version(uint32_t version, uint8_t max_version)
569580
return draft_version && draft_version <= max_version;
570581
}
571582

572-
bool QUICPlugin::quic_create_initial_secrets(CommSide side,RecordExtQUIC * rec)
583+
bool QUICPlugin::quic_create_initial_secrets(CommSide side)
573584
{
574-
uint32_t version = quic_h1->version;
575-
576-
version = ntohl(version);
577-
rec->quic_version = version;
578-
579-
// this salt is used to draft 7-9
580-
static const uint8_t handshake_salt_draft_7[SALT_LENGTH] = {
581-
0xaf, 0xc8, 0x24, 0xec, 0x5f, 0xc7, 0x7e, 0xca, 0x1e, 0x9d,
582-
0x36, 0xf3, 0x7f, 0xb2, 0xd4, 0x65, 0x18, 0xc3, 0x66, 0x39
583-
};
584-
// this salt is used to draft 10-16
585-
static const uint8_t handshake_salt_draft_10[SALT_LENGTH] = {
586-
0x9c, 0x10, 0x8f, 0x98, 0x52, 0x0a, 0x5c, 0x5c, 0x32, 0x96,
587-
0x8e, 0x95, 0x0e, 0x8a, 0x2c, 0x5f, 0xe0, 0x6d, 0x6c, 0x38
588-
};
589-
// this salt is used to draft 17-20
590-
static const uint8_t handshake_salt_draft_17[SALT_LENGTH] = {
591-
0xef, 0x4f, 0xb0, 0xab, 0xb4, 0x74, 0x70, 0xc4, 0x1b, 0xef,
592-
0xcf, 0x80, 0x31, 0x33, 0x4f, 0xae, 0x48, 0x5e, 0x09, 0xa0
593-
};
594-
// this salt is used to draft 21-22
595-
static const uint8_t handshake_salt_draft_21[SALT_LENGTH] = {
596-
0x7f, 0xbc, 0xdb, 0x0e, 0x7c, 0x66, 0xbb, 0xe9, 0x19, 0x3a,
597-
0x96, 0xcd, 0x21, 0x51, 0x9e, 0xbd, 0x7a, 0x02, 0x64, 0x4a
598-
};
599-
// this salt is used to draft 23-28
600-
static const uint8_t handshake_salt_draft_23[SALT_LENGTH] = {
601-
0xc3, 0xee, 0xf7, 0x12, 0xc7, 0x2e, 0xbb, 0x5a, 0x11, 0xa7,
602-
0xd2, 0x43, 0x2b, 0xb4, 0x63, 0x65, 0xbe, 0xf9, 0xf5, 0x02,
603-
};
604-
// this salt is used to draft 29-32
605-
static const uint8_t handshake_salt_draft_29[SALT_LENGTH] = {
606-
0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c, 0x9e, 0x97,
607-
0x86, 0xf1, 0x9c, 0x61, 0x11, 0xe0, 0x43, 0x90, 0xa8, 0x99
608-
};
609-
// newest 33 -
610-
static const uint8_t handshake_salt_v1[SALT_LENGTH] = {
611-
0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17,
612-
0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a
613-
};
614-
615-
static const uint8_t handshake_salt_v2[SALT_LENGTH] = {
616-
0xa7, 0x07, 0xc2, 0x03, 0xa5, 0x9b, 0x47, 0x18, 0x4a, 0x1d,
617-
0x62, 0xca, 0x57, 0x04, 0x06, 0xea, 0x7a, 0xe3, 0xe5, 0xd3
618-
};
619-
620-
621-
622-
// google salts
623-
/*static const uint8_t hanshake_salt_draft_q50[SALT_LENGTH] = {
624-
0x50, 0x45, 0x74, 0xEF, 0xD0, 0x66, 0xFE, 0x2F, 0x9D, 0x94,
625-
0x5C, 0xFC, 0xDB, 0xD3, 0xA7, 0xF0, 0xD3, 0xB5, 0x6B, 0x45
626-
};
627-
static const uint8_t hanshake_salt_draft_t50[SALT_LENGTH] = {
628-
0x7f, 0xf5, 0x79, 0xe5, 0xac, 0xd0, 0x72, 0x91, 0x55, 0x80,
629-
0x30, 0x4c, 0x43, 0xa2, 0x36, 0x7c, 0x60, 0x48, 0x83, 0x10
630-
};
631-
static const uint8_t hanshake_salt_draft_t51[SALT_LENGTH] = {
632-
0x7a, 0x4e, 0xde, 0xf4, 0xe7, 0xcc, 0xee, 0x5f, 0xa4, 0x50,
633-
0x6c, 0x19, 0x12, 0x4f, 0xc8, 0xcc, 0xda, 0x6e, 0x03, 0x3d
634-
};*/
635-
636-
637-
const uint8_t *salt;
638-
639-
640-
// these three are Google QUIC version
641-
642-
// we do not parse gQUIC
643-
if (version == 0x00000000) {
644-
DEBUG_MSG("Error, version negotiation\n");
645-
return false;
646-
} else if (version == 0x00000001){
647-
salt = handshake_salt_v1;
648-
can_parse = true;
649-
} else if (quic_check_version(version, 9)) {
650-
salt = handshake_salt_draft_7;
651-
can_parse = true;
652-
} else if (quic_check_version(version, 16)) {
653-
salt = handshake_salt_draft_10;
654-
can_parse = true;
655-
} else if (quic_check_version(version, 20)) {
656-
salt = handshake_salt_draft_17;
657-
can_parse = true;
658-
} else if (quic_check_version(version, 22)) {
659-
salt = handshake_salt_draft_21;
660-
can_parse = true;
661-
} else if (quic_check_version(version, 28)) {
662-
salt = handshake_salt_draft_23;
663-
can_parse = true;
664-
} else if (quic_check_version(version, 32)) {
665-
salt = handshake_salt_draft_29;
666-
can_parse = true;
667-
} else if (quic_check_version(version, 100)) {
668-
salt = handshake_salt_v2;
669-
can_parse = true;
670-
} else {
671-
DEBUG_MSG("Error, version not supported\n");
672-
return false;
673-
}
674585

675586
uint8_t extracted_secret[HASH_SHA2_256_LENGTH] = { 0 };
676587
uint8_t expanded_secret[HASH_SHA2_256_LENGTH] = { 0 };
@@ -1094,7 +1005,109 @@ bool QUICPlugin::quic_assemble()
10941005
return true;
10951006
}
10961007

1097-
bool QUICPlugin::quic_parse_data(const Packet &pkt)
1008+
1009+
bool QUICPlugin::handle_version(RecordExtQUIC * rec)
1010+
{
1011+
uint32_t version = quic_h1->version;
1012+
version = ntohl(version);
1013+
rec->quic_version = version;
1014+
1015+
1016+
1017+
1018+
// this salt is used to draft 7-9
1019+
static const uint8_t handshake_salt_draft_7[SALT_LENGTH] = {
1020+
0xaf, 0xc8, 0x24, 0xec, 0x5f, 0xc7, 0x7e, 0xca, 0x1e, 0x9d,
1021+
0x36, 0xf3, 0x7f, 0xb2, 0xd4, 0x65, 0x18, 0xc3, 0x66, 0x39
1022+
};
1023+
// this salt is used to draft 10-16
1024+
static const uint8_t handshake_salt_draft_10[SALT_LENGTH] = {
1025+
0x9c, 0x10, 0x8f, 0x98, 0x52, 0x0a, 0x5c, 0x5c, 0x32, 0x96,
1026+
0x8e, 0x95, 0x0e, 0x8a, 0x2c, 0x5f, 0xe0, 0x6d, 0x6c, 0x38
1027+
};
1028+
// this salt is used to draft 17-20
1029+
static const uint8_t handshake_salt_draft_17[SALT_LENGTH] = {
1030+
0xef, 0x4f, 0xb0, 0xab, 0xb4, 0x74, 0x70, 0xc4, 0x1b, 0xef,
1031+
0xcf, 0x80, 0x31, 0x33, 0x4f, 0xae, 0x48, 0x5e, 0x09, 0xa0
1032+
};
1033+
// this salt is used to draft 21-22
1034+
static const uint8_t handshake_salt_draft_21[SALT_LENGTH] = {
1035+
0x7f, 0xbc, 0xdb, 0x0e, 0x7c, 0x66, 0xbb, 0xe9, 0x19, 0x3a,
1036+
0x96, 0xcd, 0x21, 0x51, 0x9e, 0xbd, 0x7a, 0x02, 0x64, 0x4a
1037+
};
1038+
// this salt is used to draft 23-28
1039+
static const uint8_t handshake_salt_draft_23[SALT_LENGTH] = {
1040+
0xc3, 0xee, 0xf7, 0x12, 0xc7, 0x2e, 0xbb, 0x5a, 0x11, 0xa7,
1041+
0xd2, 0x43, 0x2b, 0xb4, 0x63, 0x65, 0xbe, 0xf9, 0xf5, 0x02,
1042+
};
1043+
// this salt is used to draft 29-32
1044+
static const uint8_t handshake_salt_draft_29[SALT_LENGTH] = {
1045+
0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c, 0x9e, 0x97,
1046+
0x86, 0xf1, 0x9c, 0x61, 0x11, 0xe0, 0x43, 0x90, 0xa8, 0x99
1047+
};
1048+
// newest 33 -
1049+
static const uint8_t handshake_salt_v1[SALT_LENGTH] = {
1050+
0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17,
1051+
0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a
1052+
};
1053+
static const uint8_t handshake_salt_v2[SALT_LENGTH] = {
1054+
0xa7, 0x07, 0xc2, 0x03, 0xa5, 0x9b, 0x47, 0x18, 0x4a, 0x1d,
1055+
0x62, 0xca, 0x57, 0x04, 0x06, 0xea, 0x7a, 0xe3, 0xe5, 0xd3
1056+
};
1057+
1058+
1059+
1060+
// google salts
1061+
/*static const uint8_t hanshake_salt_draft_q50[SALT_LENGTH] = {
1062+
0x50, 0x45, 0x74, 0xEF, 0xD0, 0x66, 0xFE, 0x2F, 0x9D, 0x94,
1063+
0x5C, 0xFC, 0xDB, 0xD3, 0xA7, 0xF0, 0xD3, 0xB5, 0x6B, 0x45
1064+
};
1065+
static const uint8_t hanshake_salt_draft_t50[SALT_LENGTH] = {
1066+
0x7f, 0xf5, 0x79, 0xe5, 0xac, 0xd0, 0x72, 0x91, 0x55, 0x80,
1067+
0x30, 0x4c, 0x43, 0xa2, 0x36, 0x7c, 0x60, 0x48, 0x83, 0x10
1068+
};
1069+
static const uint8_t hanshake_salt_draft_t51[SALT_LENGTH] = {
1070+
0x7a, 0x4e, 0xde, 0xf4, 0xe7, 0xcc, 0xee, 0x5f, 0xa4, 0x50,
1071+
0x6c, 0x19, 0x12, 0x4f, 0xc8, 0xcc, 0xda, 0x6e, 0x03, 0x3d
1072+
};*/
1073+
1074+
1075+
if (version == 0x00000000) {
1076+
DEBUG_MSG("Error, version negotiation\n");
1077+
return false;
1078+
} else if (version == 0x00000001 && !is_version2){
1079+
salt = handshake_salt_v1;
1080+
can_parse = true;
1081+
} else if (quic_check_version(version, 9) && !is_version2) {
1082+
salt = handshake_salt_draft_7;
1083+
can_parse = true;
1084+
} else if (quic_check_version(version, 16) && !is_version2) {
1085+
salt = handshake_salt_draft_10;
1086+
can_parse = true;
1087+
} else if (quic_check_version(version, 20) && !is_version2) {
1088+
salt = handshake_salt_draft_17;
1089+
can_parse = true;
1090+
} else if (quic_check_version(version, 22) && !is_version2) {
1091+
salt = handshake_salt_draft_21;
1092+
can_parse = true;
1093+
} else if (quic_check_version(version, 28) && !is_version2) {
1094+
salt = handshake_salt_draft_23;
1095+
can_parse = true;
1096+
} else if (quic_check_version(version, 32) && !is_version2) {
1097+
salt = handshake_salt_draft_29;
1098+
can_parse = true;
1099+
} else if (quic_check_version(version, 100) && is_version2) {
1100+
salt = handshake_salt_v2;
1101+
can_parse = true;
1102+
} else {
1103+
DEBUG_MSG("Error, version not supported\n");
1104+
return false;
1105+
}
1106+
1107+
return true;
1108+
1109+
}
1110+
bool QUICPlugin::quic_parse_data(const Packet &pkt,RecordExtQUIC * rec)
10981111
{
10991112

11001113

@@ -1114,10 +1127,14 @@ bool QUICPlugin::quic_parse_data(const Packet &pkt)
11141127
quic_h1 = (quic_header1 *) (tmp_pointer + offset);
11151128

11161129

1117-
if (quic_h1->version == 0x0) {
1130+
if (!handle_version(rec))
1131+
{
11181132
return false;
11191133
}
11201134

1135+
1136+
1137+
11211138
offset += sizeof(quic_header1);
11221139

11231140

@@ -1211,7 +1228,21 @@ bool QUICPlugin::quic_parse_data(const Packet &pkt)
12111228
bool QUICPlugin::quic_check_initial(uint8_t packet0)
12121229
{
12131230
// check if packet has LONG HEADER form (& 0x80 == 0x80) and is type INITIAL (& 0x30 == 0x00).
1214-
return (packet0 & 0xB0) == 0x80;
1231+
1232+
1233+
// version 1 (header form:long header(1) | fixed bit:fixed(1) | long packet type:initial(00) --> 1100 --> C)
1234+
if ((packet0 & 0xF0) == 0xC0)
1235+
{
1236+
return true;
1237+
}
1238+
// version 2 (header form:long header(1) | fixed bit:fixed(1) | long packet type:initial(01) --> 1101 --> D)
1239+
else if ((packet0 & 0xF0) == 0xD0)
1240+
{
1241+
is_version2 = true;
1242+
return true;
1243+
}
1244+
else
1245+
return false;
12151246
}
12161247

12171248

@@ -1227,15 +1258,12 @@ bool QUICPlugin::process_quic(RecordExtQUIC *quic_data, const Packet &pkt)
12271258
return false;
12281259
}
12291260

1230-
1231-
// header data extraction can extract data for both sides (client and server side), the differece is that server side header contains SCID length and so SCID.
1232-
if (!quic_parse_data(pkt)) {
1233-
return false;
1234-
}
1235-
12361261
// check port a.k.a direction, Server side does not contain ClientHello packets so neither SNI, but implemented for future expansion
12371262
if (pkt.dst_port == 443) {
1238-
if (!quic_create_initial_secrets(CommSide::CLIENT_IN,quic_data)) {
1263+
if (!quic_parse_data(pkt,quic_data)) {
1264+
return false;
1265+
}
1266+
if (!quic_create_initial_secrets(CommSide::CLIENT_IN)) {
12391267
DEBUG_MSG("Error, creation of initial secrets failed (client side)\n");
12401268
return false;
12411269
}

process/quic.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,8 @@ class QUICPlugin : public ProcessPlugin
249249
bool process_quic(RecordExtQUIC *, const Packet&);
250250

251251
bool quic_check_initial(uint8_t);
252-
bool quic_parse_data(const Packet&);
253-
bool quic_create_initial_secrets(CommSide side,RecordExtQUIC*);
252+
bool quic_parse_data(const Packet&,RecordExtQUIC*);
253+
bool quic_create_initial_secrets(CommSide side);
254254
bool quic_check_version(uint32_t, uint8_t);
255255
uint8_t quic_draft_version(uint32_t);
256256

@@ -262,6 +262,7 @@ class QUICPlugin : public ProcessPlugin
262262
bool expand_label(const char *, const char *, const uint8_t *, uint8_t, uint16_t, uint8_t *, uint8_t &);
263263
bool parse_tls(RecordExtQUIC *);
264264
bool quic_assemble();
265+
bool handle_version(RecordExtQUIC*);
265266

266267

267268
// header pointers
@@ -277,6 +278,8 @@ class QUICPlugin : public ProcessPlugin
277278
uint8_t server_In_Buffer[quic_serverIn_hkdf];
278279
uint8_t nonce[TLS13_AEAD_NONCE_LENGTH] = { 0 };
279280

281+
const uint8_t *salt;
282+
280283

281284
// important pointers into QUIC packet, used in decryption process
282285

@@ -309,6 +312,7 @@ class QUICPlugin : public ProcessPlugin
309312

310313

311314
bool can_parse;
315+
bool is_version2;
312316
};
313317

314318
}

0 commit comments

Comments
 (0)