4141 *
4242 */
4343
44+
45+
46+
47+ // known versions
48+ /*
49+ 0x00000000 -- version negotiation
50+ 0x00000001 -- newest , rfc 9000
51+ 0xff0000xx -- drafts (IETF)
52+ 0x709a50c4 -- quic version 2 -- newest draft (IETF)
53+ 0xff020000 -- quic version 2 draft 00
54+
55+
56+ Google
57+ 0x51303433 -- Q043 -- no evidence -- based on google doc , this should not be encrypted
58+ 0x51303434 -- Q044 -- no evidence
59+ 0x51303436 -- Q046 -- wireshark cant parse -- based on google doc , this should not be encrypted
60+ 0x51303530 -- Q050 -- looks like no TLS inside crypto
61+
62+ 0x54303530 -- T050
63+ 0x54303531 -- T051
64+
65+
66+ MVFST
67+ 0xfaceb001 -- should be draft 22
68+ 0xfaceb002 -- should be draft 27
69+ 0xfaceb003 -- ?
70+ 0xfaceb00e -- experimental
71+ 0xfaceb010 -- mvfst alias
72+ 0xfaceb00f -- MVFST_INVALID
73+ 0xfaceb011 -- MVFST_EXPERIMENTAL2
74+ 0xfaceb013 -- MVFST_EXPERIMENTAL3
75+ */
76+
77+
4478#include < iostream>
4579#include < cstring>
4680#include < sstream>
4781#include < endian.h>
4882
83+
4984#include < openssl/kdf.h>
5085#include < openssl/evp.h>
5186
5893#include " quic.hpp"
5994
6095
96+ int counter = 0 ;
97+
6198namespace ipxp {
6299
63100int RecordExtQUIC::REGISTERED_ID = -1 ;
@@ -72,7 +109,6 @@ __attribute__((constructor)) static void register_this_plugin()
72109
73110// Print debug message if debugging is allowed.
74111
75-
76112#ifdef DEBUG_QUIC
77113# define DEBUG_MSG (format, ...) fprintf(stderr, format, ## __VA_ARGS__)
78114#else
@@ -115,7 +151,7 @@ QUICPlugin::QUICPlugin()
115151 quic_ptr = nullptr ;
116152
117153
118- google_QUIC = false ;
154+ ietf_quic = false ;
119155}
120156
121157QUICPlugin::~QUICPlugin ()
@@ -502,25 +538,28 @@ bool QUICPlugin::quic_derive_secrets(uint8_t *secret)
502538
503539uint8_t QUICPlugin::quic_draft_version (uint32_t version)
504540{
541+
542+ // this is IETF implementation, older version used
505543 if ((version >> 8 ) == 0xff0000 ) {
506544 return (uint8_t ) version;
507545 }
508-
509546 switch (version) {
547+ // older mvfst version, but still used, based on draft 22, but salt 21 used
510548 case (0xfaceb001 ):
511549 return 22 ;
550+ // more used atm, salt 23 used
512551 case 0xfaceb002 :
513552 case 0xfaceb00e :
514- case 0x51303530 :
515- case 0x54303530 :
516- case 0x54303531 :
517553 return 27 ;
518554 case (0x0a0a0a0a & 0x0F0F0F0F ):
519555 return 29 ;
520- case 0x00000001 :
521- return 33 ;
556+ // version 2 draft 00
557+ // newest
558+ case 0xff020000 :
559+ case 0x709a50c4 :
560+ return 100 ;
522561 default :
523- return 0 ;
562+ return 255 ;
524563 }
525564}
526565
@@ -538,23 +577,51 @@ bool QUICPlugin::quic_create_initial_secrets(CommSide side,RecordExtQUIC * rec)
538577 version = ntohl (version);
539578 rec->quic_version = version;
540579
541- static const uint8_t handshake_salt_draft_22[SALT_LENGTH] = {
580+ // this salt is used to draft 7-9
581+ static const uint8_t handshake_salt_draft_7[SALT_LENGTH] = {
582+ 0xaf , 0xc8 , 0x24 , 0xec , 0x5f , 0xc7 , 0x7e , 0xca , 0x1e , 0x9d ,
583+ 0x36 , 0xf3 , 0x7f , 0xb2 , 0xd4 , 0x65 , 0x18 , 0xc3 , 0x66 , 0x39
584+ };
585+ // this salt is used to draft 10-16
586+ static const uint8_t handshake_salt_draft_10[SALT_LENGTH] = {
587+ 0x9c , 0x10 , 0x8f , 0x98 , 0x52 , 0x0a , 0x5c , 0x5c , 0x32 , 0x96 ,
588+ 0x8e , 0x95 , 0x0e , 0x8a , 0x2c , 0x5f , 0xe0 , 0x6d , 0x6c , 0x38
589+ };
590+ // this salt is used to draft 17-20
591+ static const uint8_t handshake_salt_draft_17[SALT_LENGTH] = {
592+ 0xef , 0x4f , 0xb0 , 0xab , 0xb4 , 0x74 , 0x70 , 0xc4 , 0x1b , 0xef ,
593+ 0xcf , 0x80 , 0x31 , 0x33 , 0x4f , 0xae , 0x48 , 0x5e , 0x09 , 0xa0
594+ };
595+ // this salt is used to draft 21-22
596+ static const uint8_t handshake_salt_draft_21[SALT_LENGTH] = {
542597 0x7f , 0xbc , 0xdb , 0x0e , 0x7c , 0x66 , 0xbb , 0xe9 , 0x19 , 0x3a ,
543598 0x96 , 0xcd , 0x21 , 0x51 , 0x9e , 0xbd , 0x7a , 0x02 , 0x64 , 0x4a
544599 };
600+ // this salt is used to draft 23-28
545601 static const uint8_t handshake_salt_draft_23[SALT_LENGTH] = {
546602 0xc3 , 0xee , 0xf7 , 0x12 , 0xc7 , 0x2e , 0xbb , 0x5a , 0x11 , 0xa7 ,
547603 0xd2 , 0x43 , 0x2b , 0xb4 , 0x63 , 0x65 , 0xbe , 0xf9 , 0xf5 , 0x02 ,
548604 };
605+ // this salt is used to draft 29-32
549606 static const uint8_t handshake_salt_draft_29[SALT_LENGTH] = {
550607 0xaf , 0xbf , 0xec , 0x28 , 0x99 , 0x93 , 0xd2 , 0x4c , 0x9e , 0x97 ,
551608 0x86 , 0xf1 , 0x9c , 0x61 , 0x11 , 0xe0 , 0x43 , 0x90 , 0xa8 , 0x99
552609 };
610+ // newest 33 -
553611 static const uint8_t handshake_salt_v1[SALT_LENGTH] = {
554612 0x38 , 0x76 , 0x2c , 0xf7 , 0xf5 , 0x59 , 0x34 , 0xb3 , 0x4d , 0x17 ,
555613 0x9a , 0xe6 , 0xa4 , 0xc8 , 0x0c , 0xad , 0xcc , 0xbb , 0x7f , 0x0a
556614 };
557- static const uint8_t hanshake_salt_draft_q50[SALT_LENGTH] = {
615+
616+ static const uint8_t handshake_salt_v2[SALT_LENGTH] = {
617+ 0xa7 , 0x07 , 0xc2 , 0x03 , 0xa5 , 0x9b , 0x47 , 0x18 , 0x4a , 0x1d ,
618+ 0x62 , 0xca , 0x57 , 0x04 , 0x06 , 0xea , 0x7a , 0xe3 , 0xe5 , 0xd3
619+ };
620+
621+
622+
623+ // google salts
624+ /* static const uint8_t hanshake_salt_draft_q50[SALT_LENGTH] = {
558625 0x50, 0x45, 0x74, 0xEF, 0xD0, 0x66, 0xFE, 0x2F, 0x9D, 0x94,
559626 0x5C, 0xFC, 0xDB, 0xD3, 0xA7, 0xF0, 0xD3, 0xB5, 0x6B, 0x45
560627 };
@@ -565,37 +632,47 @@ bool QUICPlugin::quic_create_initial_secrets(CommSide side,RecordExtQUIC * rec)
565632 static const uint8_t hanshake_salt_draft_t51[SALT_LENGTH] = {
566633 0x7a, 0x4e, 0xde, 0xf4, 0xe7, 0xcc, 0xee, 0x5f, 0xa4, 0x50,
567634 0x6c, 0x19, 0x12, 0x4f, 0xc8, 0xcc, 0xda, 0x6e, 0x03, 0x3d
568- };
635+ };*/
569636
570637
571638 const uint8_t *salt;
572639
573640
574641 // these three are Google QUIC version
575- if (version == 0x51303530 ) {
576- salt = hanshake_salt_draft_q50;
577- google_QUIC = true ;
578- } else if (version == 0x54303530 ) {
579- salt = hanshake_salt_draft_t50;
580- google_QUIC = true ;
581- } else if (version == 0x54303531 ) {
582- salt = hanshake_salt_draft_t51;
583- google_QUIC = true ;
642+
643+ // we do not parse gQUIC
644+ if (version == 0x00000000 ) {
645+ DEBUG_MSG (" Error, version negotiation\n " );
646+ return false ;
647+ } else if (version == 0x00000001 ){
648+ salt = handshake_salt_v1;
649+ ietf_quic = true ;
650+ } else if (quic_check_version (version, 9 )) {
651+ salt = handshake_salt_draft_7;
652+ ietf_quic = true ;
653+ } else if (quic_check_version (version, 16 )) {
654+ salt = handshake_salt_draft_10;
655+ ietf_quic = true ;
656+ } else if (quic_check_version (version, 20 )) {
657+ salt = handshake_salt_draft_17;
658+ ietf_quic = true ;
584659 } else if (quic_check_version (version, 22 )) {
585- salt = handshake_salt_draft_22 ;
586- google_QUIC = false ;
660+ salt = handshake_salt_draft_21 ;
661+ ietf_quic = true ;
587662 } else if (quic_check_version (version, 28 )) {
588663 salt = handshake_salt_draft_23;
589- google_QUIC = false ;
664+ ietf_quic = true ;
590665 } else if (quic_check_version (version, 32 )) {
591666 salt = handshake_salt_draft_29;
592- google_QUIC = false ;
667+ ietf_quic = true ;
668+ } else if (quic_check_version (version, 100 )) {
669+ salt = handshake_salt_v2;
670+ ietf_quic = true ;
593671 } else {
594- salt = handshake_salt_v1 ;
595- google_QUIC = false ;
672+ DEBUG_MSG ( " Error, version not supported \n " ) ;
673+ return false ;
596674 }
597675
598-
599676 uint8_t extracted_secret[HASH_SHA2_256_LENGTH] = { 0 };
600677 uint8_t expanded_secret[HASH_SHA2_256_LENGTH] = { 0 };
601678 size_t expd_len = HASH_SHA2_256_LENGTH;
@@ -790,9 +867,12 @@ bool QUICPlugin::quic_decrypt_header()
790867
791868
792869 // after de-obfuscating pkn, we know exactly pkn length so we can correctly adjust start of payload
870+ DEBUG_MSG (" PPKN LEN %d\n " ,pkn_len);
793871 payload = payload + pkn_len;
794872 payload_len = payload_len - pkn_len;
795873
874+ DEBUG_MSG (" PAYLOAD LEN %d\n " ,payload_len);
875+
796876 // SET HEADER LENGTH, if header length is set incorrectly AEAD will calculate wrong tag, so decryption will fail
797877 header_len = payload - header;
798878
@@ -937,14 +1017,74 @@ bool QUICPlugin::quic_assemble()
9371017 }
9381018 // https://www.rfc-editor.org/rfc/rfc9000.html#name-frames-and-frame-types
9391019 // only those frames can occure in initial packets
1020+ } else if (*(decrypted_payload + offset) == ACK1)
1021+ {
1022+ // https://www.rfc-editor.org/rfc/rfc9000.html#name-ack-frames
1023+ // skip type
1024+ offset++;
1025+ uint64_t quic_largest_acknowledged = quic_get_variable_length (decrypted_payload,offset);
1026+ uint64_t quic_ack_delay = quic_get_variable_length (decrypted_payload,offset);
1027+ uint64_t quic_ack_range_count = quic_get_variable_length (decrypted_payload,offset);
1028+ uint64_t quic_first_ack_range = quic_get_variable_length (decrypted_payload,offset);
1029+
1030+
1031+ uint64_t quic_gap;
1032+ uint64_t quic_ack_range_length;
1033+
1034+ for (uint x = 0 ; x < quic_ack_range_count;x++)
1035+ {
1036+ quic_gap = quic_get_variable_length (decrypted_payload,offset);
1037+ quic_ack_range_length = quic_get_variable_length (decrypted_payload,offset);
1038+ }
1039+
1040+ } else if (*(decrypted_payload + offset) == ACK2)
1041+ {
1042+ // https://www.rfc-editor.org/rfc/rfc9000.html#name-ack-frames
1043+ // skip type
1044+ offset++;
1045+ uint64_t quic_largest_acknowledged = quic_get_variable_length (decrypted_payload,offset);
1046+ uint64_t quic_ack_delay = quic_get_variable_length (decrypted_payload,offset);
1047+ uint64_t quic_ack_range_count = quic_get_variable_length (decrypted_payload,offset);
1048+ uint64_t quic_first_ack_range = quic_get_variable_length (decrypted_payload,offset);
1049+
1050+
1051+ uint64_t quic_gap;
1052+ uint64_t quic_ack_range_length;
1053+
1054+ for (uint x = 0 ; x < quic_ack_range_count;x++)
1055+ {
1056+ quic_gap = quic_get_variable_length (decrypted_payload,offset);
1057+ quic_ack_range_length = quic_get_variable_length (decrypted_payload,offset);
1058+ }
1059+
1060+ uint64_t ect0 = quic_get_variable_length (decrypted_payload,offset);
1061+ uint64_t ect1 = quic_get_variable_length (decrypted_payload,offset);
1062+ uint64_t ecn_ce = quic_get_variable_length (decrypted_payload,offset);
1063+
1064+
1065+ } else if (*(decrypted_payload + offset) == CONNECTION_CLOSE1)
1066+ {
1067+ // skip type
1068+ offset++;
1069+
1070+ uint64_t error_code = quic_get_variable_length (decrypted_payload,offset);
1071+ uint64_t frame_type = quic_get_variable_length (decrypted_payload,offset);
1072+ uint64_t reason_phrase_length = quic_get_variable_length (decrypted_payload,offset);
1073+ offset+= reason_phrase_length;
1074+
1075+ } else if (*(decrypted_payload + offset) == CONNECTION_CLOSE2)
1076+ {
1077+ // skip type
1078+ offset++;
1079+ uint64_t error_code = quic_get_variable_length (decrypted_payload,offset);
1080+ uint64_t reason_phrase_length = quic_get_variable_length (decrypted_payload,offset);
1081+ offset+= reason_phrase_length;
1082+
9401083 } else if (*(decrypted_payload + offset) == PADDING
941- || *(decrypted_payload + offset) == PING
942- || *(decrypted_payload + offset) == ACK1
943- || *(decrypted_payload + offset) == ACK2
944- || *(decrypted_payload + offset) == CONNECTION_CLOSE)
1084+ || *(decrypted_payload + offset) == PING)
9451085 {
9461086 offset++;
947- } else {
1087+ }else {
9481088 DEBUG_MSG (" Wrong Frame type read during frames assemble\n " );
9491089 return false ;
9501090 }
@@ -1073,9 +1213,19 @@ bool QUICPlugin::quic_check_initial(uint8_t packet0)
10731213 return (packet0 & 0xB0 ) == 0x80 ;
10741214}
10751215
1216+
10761217bool QUICPlugin::process_quic (RecordExtQUIC *quic_data, const Packet &pkt)
10771218{
10781219
1220+
1221+ DEBUG_MSG (" COUNTER %d\n " ,counter++);
1222+ DEBUG_MSG (" FIRST %02x\n " ,pkt.payload [0 ] & 0xB0 );
1223+ DEBUG_MSG (" FIRSTTT %02x\n " ,pkt.payload [0 ]);
1224+
1225+
1226+ memset (decrypted_payload,0 ,1500 );
1227+ memset (assembled_payload,0 ,1500 );
1228+
10791229 // check if packet contains LONG HEADER and is of type INITIAL
10801230 if (pkt.ip_proto != 17 || !quic_check_initial (pkt.payload [0 ])) {
10811231 DEBUG_MSG (" Packet is not Initial or does not contains LONG HEADER\n " );
@@ -1102,12 +1252,12 @@ bool QUICPlugin::process_quic(RecordExtQUIC *quic_data, const Packet &pkt)
11021252 DEBUG_MSG (" Error, payload decryption failed (client side)\n " );
11031253 return false ;
11041254 }
1105- if (!google_QUIC && !quic_assemble ())
1255+ if (ietf_quic && !quic_assemble ())
11061256 {
11071257 DEBUG_MSG (" Error, reassembling of crypto frames failed (client side)\n " );
11081258 return false ;
11091259 }
1110- if (!google_QUIC && !parse_tls (quic_data))
1260+ if (ietf_quic && !parse_tls (quic_data))
11111261 {
11121262 DEBUG_MSG (" SNI and User Agent Extraction failed\n " );
11131263 return false ;
@@ -1128,12 +1278,12 @@ bool QUICPlugin::process_quic(RecordExtQUIC *quic_data, const Packet &pkt)
11281278 DEBUG_MSG("Error, payload decryption failed (server side)\n");
11291279 return false;
11301280 }
1131- if (!google_QUIC && !quic_assemble())
1281+ if (ietf_quic && !quic_assemble())
11321282 {
11331283 DEBUG_MSG("Error, reassembling of crypto frames failed (server side)\n");
11341284 return false;
11351285 }
1136- if (!google_QUIC && !parse_tls(quic_data))
1286+ if (ietf_quic && !parse_tls(quic_data))
11371287 {
11381288 DEBUG_MSG("SNI and User Agent Extraction failed\n");
11391289 return false;
@@ -1147,7 +1297,7 @@ bool QUICPlugin::process_quic(RecordExtQUIC *quic_data, const Packet &pkt)
11471297} // QUICPlugin::process_quic
11481298
11491299int QUICPlugin::pre_create (Packet &pkt)
1150- {
1300+ {
11511301 return 0 ;
11521302}
11531303
0 commit comments