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
156165QUICPlugin::~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
173184ProcessPlugin *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)
12111228bool 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 }
0 commit comments