diff --git a/samples/log.txt b/samples/log.txt new file mode 100644 index 0000000..18c2a72 --- /dev/null +++ b/samples/log.txt @@ -0,0 +1,41 @@ +SERVER_HANDSHAKE_TRAFFIC_SECRET 1ba4a034638a63221f55e3e684fa4e6a5bbbb9f9711c035e23441810b82667c8 aa87c1bd965ea9e1361d15e7fd671792980da373f34e4eefe1fd21effbd65a80 +CLIENT_HANDSHAKE_TRAFFIC_SECRET 1ba4a034638a63221f55e3e684fa4e6a5bbbb9f9711c035e23441810b82667c8 533b0dcc030ecac8feace33031a405f5e05ecd0d7c7e64a6e30fa7bbee9bb813 +EXPORTER_SECRET 1ba4a034638a63221f55e3e684fa4e6a5bbbb9f9711c035e23441810b82667c8 027a31d81dfa560205e25a50740b13dc7ce6f5c18004dac45e2b68517c0a75e1 +SERVER_TRAFFIC_SECRET_0 1ba4a034638a63221f55e3e684fa4e6a5bbbb9f9711c035e23441810b82667c8 15f1d79f92d5b5cc15a1ebb67c39bfc4cce4934aac2722fb89a0e055c81c562e +CLIENT_TRAFFIC_SECRET_0 1ba4a034638a63221f55e3e684fa4e6a5bbbb9f9711c035e23441810b82667c8 e7cd79a7d0bd712d966261ddc5a7eec31b1e9d5cff667843eafa7e01348d1dcc +SERVER_HANDSHAKE_TRAFFIC_SECRET 1ca51d8032bbf6e0748bc3852de83b111463295f913ea8a0695ee384a4503848 53f1bfdfbc44559025a6562937995d9406033304bf59a457e1b1eb817f530e16 +CLIENT_HANDSHAKE_TRAFFIC_SECRET 1ca51d8032bbf6e0748bc3852de83b111463295f913ea8a0695ee384a4503848 b8412c25f615a5674f51817604e28b8bf70b269007c05cd408b1a24cfaa9a936 +EXPORTER_SECRET 1ca51d8032bbf6e0748bc3852de83b111463295f913ea8a0695ee384a4503848 fb2e70cca12d1e15534b3c2b6b67b85a2a148ee4318922451bc2d7cc768a4c91 +SERVER_TRAFFIC_SECRET_0 1ca51d8032bbf6e0748bc3852de83b111463295f913ea8a0695ee384a4503848 17e8205e0f334bd5c34c9b73e7f791386f3c8e3316d3bdf133d8227380555109 +CLIENT_TRAFFIC_SECRET_0 1ca51d8032bbf6e0748bc3852de83b111463295f913ea8a0695ee384a4503848 eaedfbfff17ffe92267845cda264104c3ba8da6d6d10a1233ef388bfb8bbbf2d +SERVER_HANDSHAKE_TRAFFIC_SECRET 2e78ab0ab702be305ae81cf0886bc93d09967eb60d9a1d837677c0af52b88c89 91e7f391b276856033a47e458e1d64bf81d08a3292ff30aa582bcbd140d764cc8626c16742ebd6d9a7f500a68aeb5ebb +CLIENT_HANDSHAKE_TRAFFIC_SECRET 2e78ab0ab702be305ae81cf0886bc93d09967eb60d9a1d837677c0af52b88c89 ef2ac5e176b3e5713a6c205790e3b58b12b64cc4628fbb6ac0b12273a73be6e6913a0556f823eebe12c4e42199bfbcc6 +EXPORTER_SECRET 2e78ab0ab702be305ae81cf0886bc93d09967eb60d9a1d837677c0af52b88c89 ad46dd23b08dd4135c63f3291953254977a7526630d3cc9455d8da59eb5cf712cf671d9970dad31f1c793617a60c6f99 +SERVER_TRAFFIC_SECRET_0 2e78ab0ab702be305ae81cf0886bc93d09967eb60d9a1d837677c0af52b88c89 3f4de0cda8b51bf7533e12279bebd1062459700be861c1a951e4224652872aec2162bd2b8ae16a3a16fe580aa941e6ff +CLIENT_TRAFFIC_SECRET_0 2e78ab0ab702be305ae81cf0886bc93d09967eb60d9a1d837677c0af52b88c89 7ea195809a87dc2b3af3f1a1f0317a4f5d51d0e26012e59bc2aeba8c867c0ab735140853234354feb6adc49ea24714b8 +SERVER_HANDSHAKE_TRAFFIC_SECRET 172f0e36bede6f9f78157e8e338ee8b5d501a0c264a7c248d4d2092283badd19 574e234b9ed1fe38053194bd7641126bde6e0e005ce33162d5743ab34a99327fce670b1fa134caf943dfbc0a5d686ecc +CLIENT_HANDSHAKE_TRAFFIC_SECRET 172f0e36bede6f9f78157e8e338ee8b5d501a0c264a7c248d4d2092283badd19 838049b240d1ae3a80ff4ff0268e248588ec6913f4caae68dfeaf4ea03f330bcab4606d1bee74d299be6c800b2671595 +EXPORTER_SECRET 172f0e36bede6f9f78157e8e338ee8b5d501a0c264a7c248d4d2092283badd19 13965d7ae6d230cee91ebe990c07e7d5ca46ed40a6924a91bf60901618226a88d606fb5467827cd1d3765fa827476a50 +SERVER_TRAFFIC_SECRET_0 172f0e36bede6f9f78157e8e338ee8b5d501a0c264a7c248d4d2092283badd19 da4c9bb2d82ce66a35ec5899a9f7bf67e2f24e2b190f9cabc94dd56bfdbf39f54d001da93120554293f711972f03fb16 +CLIENT_TRAFFIC_SECRET_0 172f0e36bede6f9f78157e8e338ee8b5d501a0c264a7c248d4d2092283badd19 f7f968b5b7eee2b521cda8575822bfdb2887913764a08e35648a26ab4ff98aad230b192ae6b376701395575a372c1c3e +SERVER_HANDSHAKE_TRAFFIC_SECRET 4b038c23f532ba8c893ead81d1f07f1681e4d18987b65333408e20957fde7e71 9eb2c91bcc6e0864c364858e0864d041c52f41ca3ce396d128d4fb5dc386ac00 +CLIENT_HANDSHAKE_TRAFFIC_SECRET 4b038c23f532ba8c893ead81d1f07f1681e4d18987b65333408e20957fde7e71 8577431055b2a50669270c3bf08aaf32dc7dd66a7e9a5efbeb93677db231fd72 +EXPORTER_SECRET 4b038c23f532ba8c893ead81d1f07f1681e4d18987b65333408e20957fde7e71 6a58ac33631d88787f62a919a8f0d2b6c0f8d03075aeb04b880ce2330cb9b2fc +SERVER_TRAFFIC_SECRET_0 4b038c23f532ba8c893ead81d1f07f1681e4d18987b65333408e20957fde7e71 243d0b750befa5d25af82ea4d5eaacf7f52c5343dc260f75344dcaadc69544b3 +CLIENT_TRAFFIC_SECRET_0 4b038c23f532ba8c893ead81d1f07f1681e4d18987b65333408e20957fde7e71 0a921480912454ce03a14c5eeb75ae44c7c9a82a883eb632e7279cbdab3d1188 +SERVER_HANDSHAKE_TRAFFIC_SECRET 169637b581d83e615cee48ae69fd0d810f24e8855dac989600b48fac970c36d9 182ed636bf590c245fea0ad4b04d9b2304bb30279e1a2f7bfef16861d13e2462 +CLIENT_HANDSHAKE_TRAFFIC_SECRET 169637b581d83e615cee48ae69fd0d810f24e8855dac989600b48fac970c36d9 1e4ad1aaddf8a4f64f35859461df54d193d1cd081845a422ef44d71f5ca71f71 +EXPORTER_SECRET 169637b581d83e615cee48ae69fd0d810f24e8855dac989600b48fac970c36d9 23136badd3a8975b1ceea1b4d9523055cbe296dfe75596b1e90ab6f0b7100350 +SERVER_TRAFFIC_SECRET_0 169637b581d83e615cee48ae69fd0d810f24e8855dac989600b48fac970c36d9 e15200b68d7f703abe7b04165c8885566d90c4dd509c7d174dc4c2cf130cf4d2 +CLIENT_TRAFFIC_SECRET_0 169637b581d83e615cee48ae69fd0d810f24e8855dac989600b48fac970c36d9 c5fef93efea3e4a24499a408af7e3de26411738cf25063c9efaad9b8d045487d +SERVER_HANDSHAKE_TRAFFIC_SECRET 86c98dd9032df8ef2e6f74b4396c2c2acd8da6f35406412400f9da8d2b48ffbc 783799f80f8d03250acd957dac465e0cb95a5c3b5a1adf4b928a8bceda57246c9d722d02675504a512d7800ebd21f7c0 +EXPORTER_SECRET 86c98dd9032df8ef2e6f74b4396c2c2acd8da6f35406412400f9da8d2b48ffbc 363ac8e9af29c6063792ca3e2bc7301b6cbbbfbe646f82254a843528ff708846ea934d55b4e37d8b22797f842c4b5aad +SERVER_TRAFFIC_SECRET_0 86c98dd9032df8ef2e6f74b4396c2c2acd8da6f35406412400f9da8d2b48ffbc f5402ccfccbf4a46844be1f356931700bb5881ad4dfd07fe57e7330afdfeac08a753035684ffb2b48f504ae836fca1c5 +CLIENT_HANDSHAKE_TRAFFIC_SECRET 86c98dd9032df8ef2e6f74b4396c2c2acd8da6f35406412400f9da8d2b48ffbc d5f5c7ac89b41eb782181a5d230c8ddf51233f6d3989b4944a95dc95924ee200fe4b1fa02b3e6cf07908c334905a8961 +CLIENT_TRAFFIC_SECRET_0 86c98dd9032df8ef2e6f74b4396c2c2acd8da6f35406412400f9da8d2b48ffbc 6b37aa85b4698e4d6abfb66933e3fd4283f9fe08faee2a314ce8e1b95a245ceead2f64f4024c27e0cb4fc3c7b20f7ad5 +CLIENT_RANDOM ff71dd83376f0a35a8b86e8b9f516d9938a36ec3803e48b5a256fc7cd597528d 6bf5b5d1515d70facf6f2a76c997add2a9464b5712b17ee0273dbfeaa3c1ddc7daf5ff21e552cc1ab09ad45fe815d616 +SERVER_HANDSHAKE_TRAFFIC_SECRET 3c5b65efb7b4424f2f1bb4d263befa34af2fbb14058f16428ba0187586ee6973 fcb2538d16f80d242d51c0a35395169944182eb5710fb984d03c7b8df864b181642af07af807a75bc133382641ed8bd3 +CLIENT_HANDSHAKE_TRAFFIC_SECRET 3c5b65efb7b4424f2f1bb4d263befa34af2fbb14058f16428ba0187586ee6973 551c476c45b74d91062991523ff7374b211575d497a41eb0902c3d8329382b51c00df6ebc461da6f2bead0a637352c09 +EXPORTER_SECRET 3c5b65efb7b4424f2f1bb4d263befa34af2fbb14058f16428ba0187586ee6973 e4c4e35876208551f3f3db9916db2841e2c81b730e9815e52c319ca82e718cad579e351fee75b7a94181419f83d705a2 +SERVER_TRAFFIC_SECRET_0 3c5b65efb7b4424f2f1bb4d263befa34af2fbb14058f16428ba0187586ee6973 035eed62f0d1ff88326220347fbb3e60e4ee76c99b3a73415f55af9d5cb0d7a2e73e0faa29097acd718fea92c811558e +CLIENT_TRAFFIC_SECRET_0 3c5b65efb7b4424f2f1bb4d263befa34af2fbb14058f16428ba0187586ee6973 869488a30d316752c049f2704315bd505f2aa59c608f20867bc9adce929aa25a774500214a0bc06c34dc6774add3b82a diff --git a/samples/tls1.2_aes256.pcap b/samples/tls1.2_aes256.pcap new file mode 100644 index 0000000..03f5dd8 Binary files /dev/null and b/samples/tls1.2_aes256.pcap differ diff --git a/samples/tls1.3_aes128.pcap b/samples/tls1.3_aes128.pcap new file mode 100644 index 0000000..88b3afd Binary files /dev/null and b/samples/tls1.3_aes128.pcap differ diff --git a/samples/tls1.3_aes256gcm.pcap b/samples/tls1.3_aes256gcm.pcap new file mode 100644 index 0000000..3b3a101 Binary files /dev/null and b/samples/tls1.3_aes256gcm.pcap differ diff --git a/samples/tls1.3_ccm.pcap b/samples/tls1.3_ccm.pcap new file mode 100644 index 0000000..6154860 Binary files /dev/null and b/samples/tls1.3_ccm.pcap differ diff --git a/samples/tls1.3_ccm8.pcap b/samples/tls1.3_ccm8.pcap new file mode 100644 index 0000000..80a1fbd Binary files /dev/null and b/samples/tls1.3_ccm8.pcap differ diff --git a/samples/tls1.3_chacha.pcap b/samples/tls1.3_chacha.pcap new file mode 100644 index 0000000..bcfccb5 Binary files /dev/null and b/samples/tls1.3_chacha.pcap differ diff --git a/samples/tls1.3_curl_google.pcap b/samples/tls1.3_curl_google.pcap new file mode 100644 index 0000000..1c811b8 Binary files /dev/null and b/samples/tls1.3_curl_google.pcap differ diff --git a/samples/tls1.3_keyupdates_aes256.pcap b/samples/tls1.3_keyupdates_aes256.pcap new file mode 100644 index 0000000..2282b8b Binary files /dev/null and b/samples/tls1.3_keyupdates_aes256.pcap differ diff --git a/samples/tls1.3_session_resumption.pcap b/samples/tls1.3_session_resumption.pcap new file mode 100644 index 0000000..790f85b Binary files /dev/null and b/samples/tls1.3_session_resumption.pcap differ diff --git a/ssl/ciphersuites.c b/ssl/ciphersuites.c index 345a561..bd555a2 100644 --- a/ssl/ciphersuites.c +++ b/ssl/ciphersuites.c @@ -154,6 +154,11 @@ static SSL_CipherSuite CipherSuites[]={ {195,KEX_DH,SIG_DSS,ENC_CAMELLIA256,16,256,256,DIG_SHA256,32,0}, {196,KEX_DH,SIG_RSA,ENC_CAMELLIA256,16,256,256,DIG_SHA256,32,0}, {197,KEX_DH,SIG_NONE,ENC_CAMELLIA256,16,256,256,DIG_SHA256,32,0}, + {4865,KEX_DH,SIG_NONE,ENC_AES128_GCM,16,128,128,DIG_SHA256,32,0}, + {4866,KEX_DH,SIG_NONE,ENC_AES256_GCM,16,256,256,DIG_SHA384,48,0}, + {4867,KEX_DH,SIG_NONE,ENC_CHACHA20_POLY1305,64,256,256,DIG_SHA256,32,0}, + {4868,KEX_DH,SIG_NONE,ENC_AES128_CCM,16,128,128,DIG_SHA256,32,0}, + {4869,KEX_DH,SIG_NONE,ENC_AES128_CCM_8,16,128,128,DIG_SHA256,32,0}, {49153,KEX_DH,SIG_DSS,ENC_NULL,0,0,0,DIG_SHA,20,0}, {49154,KEX_DH,SIG_DSS,ENC_RC4,1,128,128,DIG_SHA,20,0}, {49155,KEX_DH,SIG_DSS,ENC_3DES,8,192,192,DIG_SHA,20,0}, diff --git a/ssl/ssl.enums.c b/ssl/ssl.enums.c index 56fd79f..2ecbd63 100644 --- a/ssl/ssl.enums.c +++ b/ssl/ssl.enums.c @@ -138,10 +138,11 @@ static int decode_ContentType_application_data(ssl,dir,seg,data) SSL_DECODE_OPAQUE_ARRAY(ssl,"data",data->len,0,data,&d); - P_(P_AD){ + if(NET_print_flags & NET_PRINT_JSON) { + json_object_object_add(jobj, "msg_data", json_object_new_string_len(d.data, d.len)); + } else P_(P_AD) { print_data(ssl,&d); - } - else { + } else { LF; } return(0); @@ -425,8 +426,6 @@ static int decode_HandshakeType_ServerHello(ssl,dir,seg,data) ja3s_c_str = calloc(6, 1); snprintf(ja3s_c_str, 6, "%u", ssl->cipher_suite); - ssl_process_server_session_id(ssl,ssl->decoder,session_id.data, - session_id.len); P_(P_HL) LF; SSL_DECODE_ENUM(ssl,"compressionMethod",1,compression_method_decoder,P_HL,data,0); @@ -457,6 +456,14 @@ static int decode_HandshakeType_ServerHello(ssl,dir,seg,data) ja3s_ex_str[strlen(ja3s_ex_str) - 1] = '\0'; } + if (ssl->version==TLSV13_VERSION){ + // tls version is known in server hello for tls1.3 hence generate keying material here + ssl_tls13_generate_keying_material(ssl,ssl->decoder); + } + + ssl_process_server_session_id(ssl,ssl->decoder,session_id.data, + session_id.len); + if(!ja3s_ver_str) { ja3s_ver_str = calloc(1, 1); *ja3s_ver_str = '\0'; @@ -519,18 +526,20 @@ static int decode_HandshakeType_Certificate(ssl,dir,seg,data) segment *seg; Data *data; { - - - UINT4 len; + UINT4 len,exlen,ex; Data cert; int r; struct json_object *jobj; jobj = ssl->cur_json_st; json_object_object_add(jobj, "handshake_type", json_object_new_string("Certificate")); + extern decoder extension_decoder[]; LF; ssl_update_handshake_messages(ssl,data); + if (ssl->version==TLSV13_VERSION){ + SSL_DECODE_OPAQUE_ARRAY(ssl,"certificate request context",-((1<<7)-1),0, data, NULL); + } SSL_DECODE_UINT24(ssl,"certificates len",0,data,&len); json_object_object_add(jobj, "cert_chain", json_object_new_array()); @@ -540,11 +549,83 @@ static int decode_HandshakeType_Certificate(ssl,dir,seg,data) 0,data,&cert); sslx_print_certificate(ssl,&cert,P_ND); len-=(cert.len + 3); + if (ssl->version==TLSV13_VERSION) { // TLS 1.3 has certificate extensions + SSL_DECODE_UINT16(ssl,"certificate extensions len",0,data,&exlen); + len-=2; + while (exlen) { + SSL_DECODE_UINT16(ssl, "extension type", 0, data, &ex); + len -= (2+ex); + if (ssl_decode_switch(ssl, extension_decoder, ex, dir, seg, data) == R_NOT_FOUND) { + decode_extension(ssl, dir, seg, data); + P_(P_RH) { explain(ssl, "Extension type: %u not yet implemented in ssldump\n", ex); } + continue; + } + LF; + } + } } return(0); } + +static int decode_HandshakeType_SessionTicket(ssl,dir,seg,data) + ssl_obj *ssl; + int dir; + segment *seg; + Data *data; +{ + int r; + UINT4 exlen, ex, val; + extern decoder extension_decoder[]; + + SSL_DECODE_UINT32(ssl, "ticket_lifetime",P_HL, data, &val); + if (ssl->version == TLSV13_VERSION) { + SSL_DECODE_UINT32(ssl, "ticket_age_add", P_HL, data, &val); + SSL_DECODE_OPAQUE_ARRAY(ssl,"ticket_nonce",-((1<<7)-1), P_ND, data, NULL); + } + SSL_DECODE_OPAQUE_ARRAY(ssl,"ticket",-((1<<15)-1), P_ND, data, NULL); + if (ssl->version == TLSV13_VERSION) { + SSL_DECODE_UINT16(ssl, "exlen", 0, data, &exlen); + if (exlen) { + while (data->len) { + SSL_DECODE_UINT16(ssl, "extension type", 0, data, &ex); + if (ssl_decode_switch(ssl, extension_decoder, ex, dir, seg, data) == R_NOT_FOUND) { + if ((r=decode_extension(ssl, dir, seg, data))) ERETURN(r); + P_(P_RH) { explain(ssl, "Extension type: %u not yet implemented in ssldump\n", ex); } + continue; + } + LF; + } + } + } +} + +static int decode_HandshakeType_EncryptedExtensions(ssl,dir,seg,data) + ssl_obj *ssl; + int dir; + segment *seg; + Data *data; + { + int r; + UINT4 exlen, ex; + extern decoder extension_decoder[]; + + SSL_DECODE_UINT16(ssl, 0, 0, data, &exlen); + LF; + if (exlen) { + while (data->len) { + SSL_DECODE_UINT16(ssl, "extension type", 0, data, &ex); + if (ssl_decode_switch(ssl, extension_decoder, ex, dir, seg, data) == R_NOT_FOUND) { + decode_extension(ssl, dir, seg, data); + P_(P_RH) { explain(ssl, "Extension type: %u not yet implemented in ssldump\n", ex); } + continue; + } + LF; + } + } + } + static int decode_HandshakeType_ServerKeyExchange(ssl,dir,seg,data) ssl_obj *ssl; int dir; @@ -650,6 +731,7 @@ static int decode_HandshakeType_CertificateVerify(ssl,dir,seg,data) int r; + UINT4 signature_type; struct json_object *jobj; jobj = ssl->cur_json_st; @@ -657,6 +739,9 @@ static int decode_HandshakeType_CertificateVerify(ssl,dir,seg,data) LF; ssl_update_handshake_messages(ssl,data); + if (ssl->version == TLSV13_VERSION) { + SSL_DECODE_UINT16(ssl,"signature_type",P_HL,data,&signature_type); + } SSL_DECODE_OPAQUE_ARRAY(ssl,"Signature",-((1<<15)-1),P_HL,data,0); return(0); @@ -732,9 +817,22 @@ static int decode_HandshakeType_Finished(ssl,dir,seg,data) break; } + ssl_process_handshake_finished(ssl,ssl->decoder,data); return (0); } + +static int decode_HandshakeType_KeyUpdate(ssl,dir,seg,data) + ssl_obj *ssl; + int dir; + segment *seg; + Data *data; +{ + LF; + ssl_tls13_update_keying_material(ssl, ssl->decoder, dir); + return 0; +} + decoder HandshakeType_decoder[]={ { 0, @@ -751,6 +849,16 @@ decoder HandshakeType_decoder[]={ "ServerHello", decode_HandshakeType_ServerHello }, + { + 4, + "SessionTicket", + decode_HandshakeType_SessionTicket + }, + { + 8, + "EncryptedExtensions", + decode_HandshakeType_EncryptedExtensions + }, { 11, "Certificate", @@ -786,6 +894,11 @@ decoder HandshakeType_decoder[]={ "Finished", decode_HandshakeType_Finished }, + { + 24, + "KeyUpdate", + decode_HandshakeType_KeyUpdate + }, {-1} }; @@ -2839,6 +2952,18 @@ static int decode_extension(ssl,dir,seg,data) return(0); } +decoder supported_groups_decoder[] = { + {0x0017,"secp256r1",0}, + {0x0018,"secp384r1",0}, + {0x0019,"secp521r1",0}, + {0x001d,"x25519",0}, + {0x001e,"x448",0}, + {0x0100,"ffdhe2048",0}, + {0x0101,"ffdhe3072",0}, + {0x0102,"ffdhe4096",0}, + {0x0103,"ffdhe6144",0}, + {0x0104,"ffdhe8192",0}, +}; // Extension #10 supported_groups (renamed from "elliptic_curves") static int decode_extension_supported_groups(ssl,dir,seg,data) ssl_obj *ssl; @@ -2856,7 +2981,8 @@ static int decode_extension_supported_groups(ssl,dir,seg,data) LF; while(l) { p=data->len; - SSL_DECODE_UINT16(ssl, "supported group", 0, data, &g); + SSL_DECODE_ENUM(ssl,"supported group",2,supported_groups_decoder,SSL_PRINT_ALL,data,&g); + LF; if(!ja3_ec_str) ja3_ec_str = calloc(7, 1); else @@ -2875,6 +3001,11 @@ static int decode_extension_supported_groups(ssl,dir,seg,data) return(0); } +decoder ec_point_formats_decoder[] = { + {0,"uncompressed",0,}, + {1,"ansiX962_compressed_prime",0,}, + {2,"ansiX962_compressed_char2",0,} +}; // Extension #11 ec_point_formats static int decode_extension_ec_point_formats(ssl,dir,seg,data) ssl_obj *ssl; @@ -2892,7 +3023,8 @@ static int decode_extension_ec_point_formats(ssl,dir,seg,data) LF; while(l) { p=data->len; - SSL_DECODE_UINT8(ssl, "ec point format", 0, data, &f); + SSL_DECODE_ENUM(ssl,"ec point format",1,ec_point_formats_decoder,SSL_PRINT_ALL,data, &f); + LF; if(!ja3_ecp_str) ja3_ecp_str = calloc(5, 1); else @@ -2912,6 +3044,72 @@ static int decode_extension_ec_point_formats(ssl,dir,seg,data) return(0); } +static int decode_extension_supported_versions(ssl,dir,seg,data) + ssl_obj *ssl; + int dir; + segment *seg; + Data *data; +{ + int r; + UINT4 len, version; + SSL_DECODE_UINT16(ssl, "extensions length", 0, data, &len); + LF; + if (dir == DIR_I2R) SSL_DECODE_UINT8(ssl, "supported versions length", 0, data, &len);//client sends extension<..> + while (len) { + SSL_DECODE_UINT16(ssl, "supported version", 0, data, &version); + explain(ssl, "version: %u.%u", (version>>8)&0xff, version&0xff); + len -= 2; + if (len) printf("\n"); + } + if (dir == DIR_R2I) ssl->version = version; // Server sets the tls version +} + +decoder tls13_certificate_types[] = { + {0,"x509",0}, + {1,"openpgp",0}, + {2,"raw public key",0}, + {3,"1609 dot 2",0} +}; +static int decode_extension_client_certificate_type(ssl,dir,seg,data) + ssl_obj *ssl; + int dir; + segment *seg; + Data *data; +{ + int r; + UINT4 len, certificate_type; + SSL_DECODE_UINT16(ssl, "extensions length", 0, data, &len); + LF; + if (dir == DIR_I2R) SSL_DECODE_UINT8(ssl, "client certificates length", 0, data, &len);//client sends certificates<..> + while (len) { + SSL_DECODE_ENUM(ssl,"certificate type",1,tls13_certificate_types,SSL_PRINT_ALL,data, &certificate_type); + len -= 1; + data += 1; + if (len) printf("\n"); + } + if (dir == DIR_R2I) ssl->extensions->client_certificate_type = certificate_type; // Server sets the client_certificate_type +} + +static int decode_extension_server_certificate_type(ssl,dir,seg,data) + ssl_obj *ssl; + int dir; + segment *seg; + Data *data; +{ + int r; + UINT4 len, certificate_type; + SSL_DECODE_UINT16(ssl, "extensions length", 0, data, &len); + LF; + if (dir == DIR_I2R) SSL_DECODE_UINT8(ssl, "server certificates length", 0, data, &len);//client sends certificates<..> + while (len) { + SSL_DECODE_ENUM(ssl,"certificate type",1,tls13_certificate_types,SSL_PRINT_ALL,data, &certificate_type); + len -= 1; + data += 1; + if (len) printf("\n"); + } + if (dir == DIR_R2I) ssl->extensions->server_certificate_type = certificate_type; // Server sets the server_certificate_type +} + decoder extension_decoder[] = { { 0, @@ -3011,12 +3209,12 @@ decoder extension_decoder[] = { { 19, "client_certificate_type", - decode_extension + decode_extension_client_certificate_type }, { 20, "server_certificate_type", - decode_extension + decode_extension_server_certificate_type }, { 21, @@ -3126,7 +3324,7 @@ decoder extension_decoder[] = { { 43, "supported_versions", - decode_extension + decode_extension_supported_versions }, { 44, @@ -3193,7 +3391,6 @@ decoder extension_decoder[] = { "renegotiation_info", decode_extension }, - {-1} }; diff --git a/ssl/ssl_h.h b/ssl/ssl_h.h index ce67b19..c95025e 100644 --- a/ssl/ssl_h.h +++ b/ssl/ssl_h.h @@ -70,6 +70,8 @@ typedef struct d_queue_ { typedef struct ssl_extensions_ { int encrypt_then_mac; int extended_master_secret; + int client_certificate_type; + int server_certificate_type; } ssl_extensions; typedef struct ssl_obj_ { @@ -135,6 +137,7 @@ typedef struct decoder_ { #define TLSV1_VERSION 0x301 #define TLSV11_VERSION 0x302 #define TLSV12_VERSION 0x303 +#define TLSV13_VERSION 0x304 /*State defines*/ #define SSL_ST_SENT_NOTHING 0 diff --git a/ssl/ssl_rec.c b/ssl/ssl_rec.c index 9e4f4c7..2150549 100644 --- a/ssl/ssl_rec.c +++ b/ssl/ssl_rec.c @@ -53,10 +53,12 @@ #include #include #include +#include #endif #include "ssldecode.h" #include "ssl_rec.h" + struct ssl_rec_decoder_ { SSL_CipherSuite *cs; Data *mac_key; @@ -65,10 +67,9 @@ struct ssl_rec_decoder_ { #ifdef OPENSSL EVP_CIPHER_CTX *evp; #endif - UINT4 seq; + UINT8 seq; }; - char *digests[]={ "MD5", "SHA1", @@ -92,7 +93,10 @@ char *ciphers[]={ "SEED", NULL, "aes-128-gcm", - "aes-256-gcm" + "aes-256-gcm", + "ChaCha20-Poly1305", + "aes-128-ccm", + "aes-128-ccm", // for ccm 8, uses the same cipher }; @@ -100,9 +104,9 @@ static int tls_check_mac PROTO_LIST((ssl_rec_decoder *d,int ct, int ver,UCHAR *data,UINT4 datalen,UCHAR *iv,UINT4 ivlen,UCHAR *mac)); static int fmt_seq PROTO_LIST((UINT4 num,UCHAR *buf)); -int ssl_create_rec_decoder(dp,cs,mk,sk,iv) +int ssl_create_rec_decoder(dp,ssl,mk,sk,iv) ssl_rec_decoder **dp; - SSL_CipherSuite *cs; + ssl_obj *ssl; UCHAR *mk; UCHAR *sk; UCHAR *iv; @@ -111,10 +115,11 @@ int ssl_create_rec_decoder(dp,cs,mk,sk,iv) ssl_rec_decoder *dec=0; #ifdef OPENSSL const EVP_CIPHER *ciph=0; + int iv_len = ssl->version == TLSV13_VERSION?12:ssl->cs->block; /* Find the SSLeay cipher */ - if(cs->enc!=ENC_NULL){ - ciph=(EVP_CIPHER *)EVP_get_cipherbyname(ciphers[cs->enc-0x30]); + if(ssl->cs->enc!=ENC_NULL){ + ciph=(EVP_CIPHER *)EVP_get_cipherbyname(ciphers[ssl->cs->enc-0x30]); if(!ciph) ABORT(R_INTERNAL); } @@ -125,28 +130,28 @@ int ssl_create_rec_decoder(dp,cs,mk,sk,iv) if(!(dec=(ssl_rec_decoder *)calloc(1,sizeof(ssl_rec_decoder)))) ABORT(R_NO_MEMORY); - dec->cs=cs; + dec->cs=ssl->cs; - if((r=r_data_alloc(&dec->mac_key,cs->dig_len))) + if((r=r_data_alloc(&dec->mac_key,ssl->cs->dig_len))) ABORT(r); - if((r=r_data_alloc(&dec->implicit_iv,cs->block))) + if((r=r_data_alloc(&dec->implicit_iv,iv_len))) ABORT(r); - memcpy(dec->implicit_iv->data,iv,cs->block); + memcpy(dec->implicit_iv->data,iv, iv_len); - if((r=r_data_create(&dec->write_key,sk,cs->eff_bits/8))) + if((r=r_data_create(&dec->write_key,sk,ssl->cs->eff_bits/8))) ABORT(r); /* This is necessary for AEAD ciphers, because we must wait to fully initialize the cipher in order to include the implicit IV */ - if(IS_AEAD_CIPHER(cs)){ + if(IS_AEAD_CIPHER(ssl->cs)){ sk=NULL; iv=NULL; } else - memcpy(dec->mac_key->data,mk,cs->dig_len); + memcpy(dec->mac_key->data,mk,ssl->cs->dig_len); if(!(dec->evp=EVP_CIPHER_CTX_new())) ABORT(R_NO_MEMORY); @@ -190,6 +195,95 @@ int ssl_destroy_rec_decoder(dp) #define MSB(a) ((a>>8)&0xff) #define LSB(a) (a&0xff) +int tls13_update_rec_key(d,newkey,newiv) + ssl_rec_decoder *d; + UCHAR *newkey; + UCHAR *newiv; +{ + d->write_key->data = newkey; + d->implicit_iv->data = newiv; + d->seq = 0; +} + +int tls13_decode_rec_data(ssl,d,ct,version,in,inl,out,outl) + ssl_obj *ssl; + ssl_rec_decoder *d; + int ct; + int version; + UCHAR *in; + int inl; + UCHAR *out; + int *outl; + { + int pad,i; + int r,encpadl,x,_status=0; + UCHAR aad[5],aead_nonce[12], *tag; + int taglen = d->cs->enc==ENC_AES128_CCM_8?8:16; + CRDUMP("CipherText",in,inl); + CRDUMPD("KEY",d->write_key); + CRDUMPD("IV",d->implicit_iv); + if (!IS_AEAD_CIPHER(d->cs)){ + fprintf(stderr, "Non aead cipher in tls13\n"); + ABORT(-1); + } + memcpy(aead_nonce, d->implicit_iv->data, 12); + for (i = 0; i < 8; i++) { // AEAD NONCE according to RFC TLS1.3 + aead_nonce[12 - 1 - i] ^= ((d->seq >> (i * 8)) & 0xFF); + } + d->seq++; + CRDUMP("NONCE",aead_nonce,12); + tag = in+(inl-taglen); + CRDUMP("Tag", tag, taglen); + + aad[0] = ct; + aad[1] = 0x03; + aad[2] = 0x03; + aad[3] = MSB(inl); + aad[4] = LSB(inl); + CRDUMP("AAD",aad,5); + inl-=taglen; + + if (!EVP_CIPHER_CTX_ctrl(d->evp, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)) { + fprintf(stderr, "Unable to set ivlen\n"); + ABORT(-1); + } + + if (IS_CCM_CIPHER(d->cs) && !EVP_CIPHER_CTX_ctrl(d->evp, EVP_CTRL_AEAD_SET_TAG, taglen, tag)) { + fprintf(stderr, "Unable to set tag for ccm cipher\n"); + ABORT(-1); + } + + if(!EVP_DecryptInit_ex(d->evp,NULL,NULL,d->write_key->data,aead_nonce)){ + fprintf(stderr,"Unable to init evp1\n"); + ABORT(-1); + } + + if (IS_CCM_CIPHER(d->cs) && !EVP_DecryptUpdate(d->evp,NULL,outl,NULL,inl)){ + fprintf(stderr,"Unable to update data length\n"); + ABORT(-1); + } + + if (!EVP_DecryptUpdate(d->evp,NULL,outl,aad,5)){ + fprintf(stderr,"Unable to update aad\n"); + ABORT(-1); + } + + CRDUMP("Real CipherText", in, inl); + if (!EVP_DecryptUpdate(d->evp,out,outl,in,inl)){ + fprintf(stderr,"Unable to update with CipherText\n"); + ABORT(-1); + } + + if (!IS_CCM_CIPHER(d->cs) && (!EVP_CIPHER_CTX_ctrl(d->evp,EVP_CTRL_GCM_SET_TAG,taglen,tag) || !EVP_DecryptFinal(d->evp,NULL,&x))) { + fprintf(stderr,"BAD MAC\n"); + ABORT(SSL_BAD_MAC); + } + +abort: + ERR_print_errors_fp(stderr); + return _status; +} + int ssl_decode_rec_data(ssl,d,ct,version,in,inl,out,outl) ssl_obj *ssl; ssl_rec_decoder *d; diff --git a/ssl/ssl_rec.h b/ssl/ssl_rec.h index 101ec86..3d2738a 100644 --- a/ssl/ssl_rec.h +++ b/ssl/ssl_rec.h @@ -51,13 +51,16 @@ typedef struct ssl_rec_decoder_ ssl_rec_decoder; int ssl_destroy_rec_decoder PROTO_LIST((ssl_rec_decoder **dp)); int ssl_create_rec_decoder PROTO_LIST((ssl_rec_decoder **dp, - SSL_CipherSuite *cs,UCHAR *mk,UCHAR *sk,UCHAR *iv)); + ssl_obj *ssl,UCHAR *mk,UCHAR *sk,UCHAR *iv)); int ssl_decode_rec_data PROTO_LIST((ssl_obj *ssl,ssl_rec_decoder *d, int ct,int version,UCHAR *in,int inl,UCHAR *out,int *outl)); +int tls13_decode_rec_data PROTO_LIST((ssl_obj *ssl,ssl_rec_decoder *d,int ct,int version,UCHAR *in,int inl,UCHAR *out,int *outl)); +int tls13_update_rec_key PROTO_LIST((ssl_rec_decoder *d,UCHAR *newkey, UCHAR *newiv)); int ssl3_check_mac(ssl_rec_decoder *d, int ct, int ver, UCHAR *data, UINT4 datalen, UCHAR *mac); -#define IS_AEAD_CIPHER(cs) (cs->enc==0x3b||cs->enc==0x3c) +#define IS_AEAD_CIPHER(cs) (cs->enc==0x3b||cs->enc==0x3c||cs->enc==0x3d||cs->enc==0x3e||cs->enc==0x3f) +#define IS_CCM_CIPHER(cs) (cs->enc==0x3e||cs->enc==0x3f) #endif diff --git a/ssl/sslciphers.h b/ssl/sslciphers.h index a41aaf4..9a1cfcc 100644 --- a/ssl/sslciphers.h +++ b/ssl/sslciphers.h @@ -79,6 +79,9 @@ typedef struct SSL_CipherSuite_ { #define ENC_NULL 0x3a #define ENC_AES128_GCM 0x3b #define ENC_AES256_GCM 0x3c +#define ENC_CHACHA20_POLY1305 0x3d +#define ENC_AES128_CCM 0x3e +#define ENC_AES128_CCM_8 0x3f #define DIG_MD5 0x40 #define DIG_SHA 0x41 diff --git a/ssl/ssldecode.c b/ssl/ssldecode.c index 1f3da1b..5a81834 100644 --- a/ssl/ssldecode.c +++ b/ssl/ssldecode.c @@ -48,6 +48,8 @@ #include "sslprint.h" #include "ssl.enums.h" #ifdef OPENSSL +#include +#include #include #include #include @@ -91,6 +93,10 @@ struct ssl_decoder_ { int ephemeral_rsa; Data *PMS; Data *MS; + Data *SHTS;//Server Handshake traffic secret + Data *CHTS;//Client Handshake traffic secret + Data *STS;//Server traffic Secret + Data *CTS;//Client traffic secret Data *handshake_messages; Data *session_hash; ssl_rec_decoder *c_to_s; @@ -115,7 +121,7 @@ static int ssl_generate_keying_material PROTO_LIST((ssl_obj *ssl, ssl_decoder *d)); static int ssl_generate_session_hash PROTO_LIST((ssl_obj *ssl, ssl_decoder *d)); -static int ssl_read_key_log_file PROTO_LIST((ssl_decoder *d)); +static int ssl_read_key_log_file PROTO_LIST((ssl_obj* obj,ssl_decoder *d)); #endif static int ssl_create_session_lookup_key PROTO_LIST((ssl_obj *ssl, @@ -196,6 +202,7 @@ int ssl_decode_ctx_destroy(dp) { #ifdef OPENSSL ssl_decode_ctx *d = *dp; + if (!d) return 0; if(d->ssl_key_log_file) { fclose(d->ssl_key_log_file); } @@ -320,19 +327,23 @@ int ssl_process_server_session_id(ssl,d,msg,len) INIT_DATA(idd,msg,len); - /* First check to see if the client tried to restore */ - if(d->session_id){ - /* Now check to see if we restored */ - if((r=r_data_compare(&idd,d->session_id))) - ABORT(r); + if (ssl->version==TLSV13_VERSION){ + // No need to save/restore session in tls1.3 since the only way of decrypting is through log file + } else { + /* First check to see if the client tried to restore */ + if(d->session_id){ + /* Now check to see if we restored */ + if((r=r_data_compare(&idd,d->session_id))) + ABORT(r); - /* Now try to look up the session. We may not be able - to find it if, for instance, the original session - was initiated with something other than static RSA */ - if((r=ssl_restore_session(ssl,d))) - ABORT(r); + /* Now try to look up the session. We may not be able + to find it if, for instance, the original session + was initiated with something other than static RSA */ + if((r=ssl_restore_session(ssl,d))) + ABORT(r); - restored=1; + restored=1; + } } _status=0; @@ -365,7 +376,7 @@ int ssl_process_client_session_id(ssl,d,msg,len) //todo: better save and destroy only when successfully read key log r_data_destroy(&d->MS); - if(d->ctx->ssl_key_log_file && (ssl_read_key_log_file(d)==0) && d->MS) + if(d->ctx->ssl_key_log_file && (ssl_read_key_log_file(ssl, d)==0) && d->MS) { //we found master secret for session in keylog //try to save session @@ -387,24 +398,37 @@ int ssl_process_client_session_id(ssl,d,msg,len) #endif } +int ssl_process_handshake_finished(ssl_obj* ssl,ssl_decoder *dec, Data *data){ + if (ssl->version==TLSV13_VERSION){ + if (ssl->direction==DIR_I2R){ // Change from handshake decoder to data traffic decoder + dec->c_to_s = dec->c_to_s_n; + dec->c_to_s_n = 0; + } else { + dec->s_to_c = dec->s_to_c_n; + dec->s_to_c_n = 0; + } + } +} + int ssl_process_change_cipher_spec(ssl,d,direction) ssl_obj *ssl; ssl_decoder *d; int direction; { -#ifdef OPENSSL - if(direction==DIR_I2R){ - d->c_to_s=d->c_to_s_n; - d->c_to_s_n=0; - if(d->c_to_s) ssl->process_ciphertext |= direction; +#ifdef OPENSSL + if (ssl->version!=TLSV13_VERSION){ + if(direction==DIR_I2R){ + d->c_to_s=d->c_to_s_n; + d->c_to_s_n=0; + if(d->c_to_s) ssl->process_ciphertext |= direction; + } + else { + d->s_to_c=d->s_to_c_n; + d->s_to_c_n=0; + if(d->s_to_c) ssl->process_ciphertext |= direction; + } } - else{ - d->s_to_c=d->s_to_c_n; - d->s_to_c_n=0; - if(d->s_to_c) ssl->process_ciphertext |= direction; - } - -#endif +#endif return(0); } int ssl_decode_record(ssl,dec,direction,ct,version,d) @@ -426,8 +450,11 @@ int ssl_decode_record(ssl,dec,direction,ct,version,d) else rd=0; state=(direction==DIR_I2R)?ssl->i_state:ssl->r_state; - - if(!rd){ + + if (ssl->version == TLSV13_VERSION && ct != 23) { // Only type 23 is encrypted in tls1.3 + ssl->record_encryption = REC_PLAINTEXT; + return 0; + } else if(!rd){ if(state & SSL_ST_SENT_CHANGE_CIPHER_SPEC){ ssl->record_encryption=REC_CIPHERTEXT; return(SSL_NO_DECRYPT); @@ -443,7 +470,12 @@ int ssl_decode_record(ssl,dec,direction,ct,version,d) if(!(out=(UCHAR *)malloc(d->len))) ABORT(R_NO_MEMORY); - if((r=ssl_decode_rec_data(ssl,rd,ct,version,d->data,d->len,out,&outl))){ + if (ssl->version==TLSV13_VERSION){ + r=tls13_decode_rec_data(ssl,rd,ct,version,d->data,d->len,out,&outl); + } else { + r=ssl_decode_rec_data(ssl,rd,ct,version,d->data,d->len,out,&outl); + } + if(r) { ABORT(r); } @@ -620,7 +652,7 @@ int ssl_process_client_key_exchange(ssl,d,msg,len) r_data_destroy(&d->MS); if(!d->ctx->ssl_key_log_file || - ssl_read_key_log_file(d) || + ssl_read_key_log_file(ssl,d) || !d->MS){ if(ssl->cs->kex!=KEX_RSA) return(-1); @@ -1070,10 +1102,10 @@ static int ssl_generate_keying_material(ssl,d) } if((r=ssl_create_rec_decoder(&d->c_to_s_n, - ssl->cs,c_mk,c_wk,c_iv))) + ssl,c_mk,c_wk,c_iv))) ABORT(r); if((r=ssl_create_rec_decoder(&d->s_to_c_n, - ssl->cs,s_mk,s_wk,s_iv))) + ssl,s_mk,s_wk,s_iv))) ABORT(r); @@ -1086,6 +1118,175 @@ static int ssl_generate_keying_material(ssl,d) return(_status); } +static int hkdf_expand_label(ssl,d,secret,label,context,length,out) + ssl_obj *ssl; + ssl_decoder *d; + Data *secret; + char *label; + Data *context; + uint16_t length; + UCHAR **out; + { + int r; + size_t outlen = length; + EVP_PKEY_CTX *pctx; + + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); + + Data hkdf_label; + UCHAR *ptr; + + //Construct HkdfLabel + hkdf_label.data = ptr = malloc(512); + *(uint16_t*)ptr = ntohs(length); + ptr+=2; + *(uint8_t*)ptr++ = 6+(label?strlen(label):0); + memcpy(ptr, "tls13 ", 6); + ptr+=6; + if (label) { + memcpy(ptr, label, strlen(label)); + ptr+=strlen(label); + } + *(uint8_t*)ptr++ = context?context->len:0; + if (context) { + memcpy(ptr, context->data, context->len); + ptr+=context->len; + } + hkdf_label.len = ptr - hkdf_label.data; + CRDUMPD("hkdf_label", &hkdf_label); + // Load parameters + *out = malloc(length); + if (EVP_PKEY_derive_init(pctx) <= 0) { + fprintf(stderr, "EVP_PKEY_derive_init failed\n"); + } + /* Error */ + if (EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY)<=0) { + fprintf(stderr, "EVP_PKEY_CTX_hkdf_mode failed\n"); + goto abort; + } + if (EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_get_digestbyname(digests[ssl->cs->dig-0x40])) <= 0) { + fprintf(stderr, "EVP_PKEY_CTX_set_hkdf_md failed\n"); + goto abort; + } + if (EVP_PKEY_CTX_set1_hkdf_key(pctx, secret->data, secret->len) <= 0) { + fprintf(stderr, "EVP_PKEY_CTX_set_hkdf_md failed\n"); + goto abort; + } + if (EVP_PKEY_CTX_add1_hkdf_info(pctx, hkdf_label.data, hkdf_label.len) <= 0) { + fprintf(stderr, "EVP_PKEY_CTX_add1_hkdf_info failed\n"); + goto abort; + } + if (EVP_PKEY_derive(pctx, *out, &outlen) <= 0) { + fprintf(stderr, "EVP_PKEY_derive failed\n"); + goto abort; + } + + CRDUMP("out_hkdf", *out, outlen); + return 0; +abort: + ERR_print_errors_fp(stderr); + return r; + } + +// Will update the keys for the particular direction +int ssl_tls13_update_keying_material(ssl,d,direction) + ssl_obj *ssl; + ssl_decoder *d; + int direction; +{ + Data *secret; + ssl_rec_decoder *decoder; + UCHAR *newsecret; + UCHAR *newkey; + UCHAR *newiv; + + if (direction == DIR_I2R) { + secret = d->CTS; + decoder = d->c_to_s; + } else { + secret = d->STS; + decoder = d->s_to_c; + } + hkdf_expand_label(ssl, d, secret, "traffic upd", NULL, ssl->cs->dig_len, &newsecret); + secret->data = newsecret; + hkdf_expand_label(ssl, d, secret, "key", NULL, ssl->cs->eff_bits/8, &newkey); + hkdf_expand_label(ssl, d, secret, "iv", NULL, 12, &newiv); + tls13_update_rec_key(decoder,newkey,newiv); + + return 0; +} + +int ssl_tls13_generate_keying_material(ssl,d) + ssl_obj* ssl; + ssl_decoder *d; +{ + int r,_status; + Data out; + UCHAR *s_wk_h,*s_iv_h,*c_wk_h,*c_iv_h, + *s_wk,*s_iv,*c_wk,*c_iv; + if (!(d->ctx->ssl_key_log_file && ssl_read_key_log_file(ssl, d)==0 && + d->SHTS && d->CHTS && d->STS && d->CTS)){ + ABORT(-1); + } + // It is 12 for all ciphers + if (hkdf_expand_label(ssl, d, d->SHTS, "key", NULL, ssl->cs->eff_bits/8, &s_wk_h)) { + fprintf(stderr, "s_wk_h hkdf_expand_label failed\n"); + goto abort; + } + if (hkdf_expand_label(ssl, d, d->SHTS, "iv", NULL, 12, &s_iv_h)) { + fprintf(stderr, "s_iv_h hkdf_expand_label failed\n"); + goto abort; + } + if (hkdf_expand_label(ssl, d, d->CHTS, "key", NULL, ssl->cs->eff_bits/8, &c_wk_h)) { + fprintf(stderr, "c_wk_h hkdf_expand_label failed\n"); + goto abort; + } + if (hkdf_expand_label(ssl, d, d->CHTS, "iv", NULL, 12, &c_iv_h)) { + fprintf(stderr, "c_iv_h hkdf_expand_label failed\n"); + goto abort; + } + if (hkdf_expand_label(ssl, d, d->STS, "key", NULL, ssl->cs->eff_bits/8, &s_wk)) { + fprintf(stderr, "s_wk hkdf_expand_label failed\n"); + goto abort; + } + if (hkdf_expand_label(ssl, d, d->STS, "iv", NULL, 12, &s_iv)) { + fprintf(stderr, "s_iv hkdf_expand_label failed\n"); + goto abort; + } + if (hkdf_expand_label(ssl, d, d->CTS, "key", NULL, ssl->cs->eff_bits/8, &c_wk)) { + fprintf(stderr, "c_wk hkdf_expand_label failed\n"); + goto abort; + } + if (hkdf_expand_label(ssl, d, d->CTS, "iv", NULL, 12, &c_iv)) { + fprintf(stderr, "c_iv hkdf_expand_label failed\n"); + goto abort; + } + CRDUMP("Server Handshake Write key", s_wk_h,ssl->cs->eff_bits/8 ); + CRDUMP("Server Handshake IV", s_iv_h, 12); + CRDUMP("Client Handshake Write key", c_wk_h, ssl->cs->eff_bits/8); + CRDUMP("Client Handshake IV", c_iv_h,12); + CRDUMP("Server Write key", s_wk,ssl->cs->eff_bits/8); + CRDUMP("Server IV", s_iv,12); + CRDUMP("Client Write key",c_wk, ssl->cs->eff_bits/8); + CRDUMP("Client IV", c_iv,12); + + if((r=ssl_create_rec_decoder(&d->c_to_s_n, + ssl,NULL,c_wk,c_iv))) + ABORT(r); + if((r=ssl_create_rec_decoder(&d->s_to_c_n, + ssl,NULL,s_wk,s_iv))) + ABORT(r); + if((r=ssl_create_rec_decoder(&d->c_to_s, + ssl,NULL,c_wk_h,c_iv_h))) + ABORT(r); + if((r=ssl_create_rec_decoder(&d->s_to_c, + ssl,NULL,s_wk_h,s_iv_h))) + ABORT(r); + return 0; +abort: + return r; +} + static int ssl_generate_session_hash(ssl,d) ssl_obj *ssl; ssl_decoder *d; @@ -1134,36 +1335,64 @@ static int ssl_generate_session_hash(ssl,d) return(_status); } -static int ssl_read_key_log_file(d) +static int read_hex_string(char *str, UCHAR *buf, int n) { + unsigned int t; + int i; + for (i = 0; i < n; i++) { + if (sscanf(str + i * 2, "%02x", &t) != 1) + return -1; + buf[i] = (char)t; + } + return 0; +} +static int ssl_read_key_log_file(ssl,d) + ssl_obj *ssl; ssl_decoder *d; { int r,_status,n,i; unsigned int t; size_t l=0; - char *line,*label_data; - - while ((n=getline(&line,&l,d->ctx->ssl_key_log_file))!=-1) { - if(n==(d->client_random->len*2)+112 && - !strncmp(line,"CLIENT_RANDOM",13)) { - - if(!(label_data=malloc((d->client_random->len*2)+1))) - ABORT(r); - - for(i=0;iclient_random->len;i++) - if(snprintf(label_data+(i*2),3,"%02x",d->client_random->data[i])!=2) - ABORT(r); - - if(STRNICMP(line+14,label_data,64)) - continue; - - if((r=r_data_alloc(&d->MS,48))) - ABORT(r); - - for(i=0; i < d->MS->len; i++) { - if(sscanf(line+14+65+(i*2),"%2x",&t)!=1) - ABORT(r); - *(d->MS->data+i)=(char)t; - } + char *line, *d_client_random, *label, *client_random, *secret; + if (ssl->version==TLSV13_VERSION && !ssl->cs)// ssl->cs is not set when called from ssl_process_client_session_id + ABORT(r); + if (!(d_client_random = malloc((d->client_random->len * 2) + 1))) + ABORT(r); + for (i = 0; i < d->client_random->len; i++) + if (snprintf(d_client_random + (i * 2), 3, "%02x", d->client_random->data[i]) != 2) + ABORT(r); + while ((n = getline(&line, &l, d->ctx->ssl_key_log_file)) != -1) { + if (line[n-1] =='\n') line[n-1] = '\0'; + if (!(label=strtok(line, " "))) continue; + if (!(client_random=strtok(NULL, " ")) || strlen(client_random)!=64 || STRNICMP(client_random, d_client_random, 64)) continue; + secret=strtok(NULL, " "); + if (!(secret) || strlen(secret)!=(ssl->version==TLSV13_VERSION?ssl->cs->dig_len*2:96)) continue; + if (!strncmp(label, "CLIENT_RANDOM", 13)) { + if ((r=r_data_alloc(&d->MS, 48))) + ABORT(r); + if (read_hex_string(secret, d->MS->data, 48)) + ABORT(r); + } + if (ssl->version!=TLSV13_VERSION) continue; + if (!strncmp(label, "SERVER_HANDSHAKE_TRAFFIC_SECRET", 31)){ + if ((r=r_data_alloc(&d->SHTS, ssl->cs->dig_len))) + ABORT(r); + if (read_hex_string(secret, d->SHTS->data, ssl->cs->dig_len)) + ABORT(r); + } else if (!strncmp(label, "CLIENT_HANDSHAKE_TRAFFIC_SECRET", 31)){ + if ((r=r_data_alloc(&d->CHTS, ssl->cs->dig_len))) + ABORT(r); + if (read_hex_string(secret, d->CHTS->data, ssl->cs->dig_len)) + ABORT(r); + } else if (!strncmp(label, "SERVER_TRAFFIC_SECRET_0", 23)){ + if ((r=r_data_alloc(&d->STS, ssl->cs->dig_len))) + ABORT(r); + if (read_hex_string(secret, d->STS->data, ssl->cs->dig_len)) + ABORT(r); + } else if (!strncmp(label, "CLIENT_TRAFFIC_SECRET_0", 23)){ + if ((r=r_data_alloc(&d->CTS, ssl->cs->dig_len))) + ABORT(r); + if (read_hex_string(secret, d->CTS->data, ssl->cs->dig_len)) + ABORT(r); } /* Eventually add support for other labels defined here: diff --git a/ssl/ssldecode.h b/ssl/ssldecode.h index a878716..15566bb 100644 --- a/ssl/ssldecode.h +++ b/ssl/ssldecode.h @@ -73,6 +73,9 @@ int ssl_update_handshake_messages PROTO_LIST((ssl_obj *ssl, Data *data)); int ssl_decode_record PROTO_LIST((ssl_obj *ssl,ssl_decoder *dec,int direction, int ct,int version,Data *d)); +int ssl_tls13_generate_keying_material PROTO_LIST((ssl_obj *obj,ssl_decoder *dec)); +int ssl_process_handshake_finished PROTO_LIST((ssl_obj* ssl,ssl_decoder *dec, Data *data)); +int ssl_tls13_update_keying_material PROTO_LIST((ssl_obj *ssl,ssl_decoder *dec,int dir)); #endif diff --git a/ssl/sslprint.c b/ssl/sslprint.c index bd42407..355db29 100644 --- a/ssl/sslprint.c +++ b/ssl/sslprint.c @@ -268,18 +268,16 @@ int ssl_expand_record(ssl,q,direction,data,len) explain(ssl," Short record: %u bytes available (expecting: %u)\n",length,d.len); return(0); } + version = ssl->version ? ssl->version : (vermaj*256+vermin); P_(P_RH){ - explain(ssl," V%d.%d(%d)",vermaj,vermin,length); + explain(ssl," V%d.%d(%d)",(version>>8)&0xff,version&0xff,length); json_object_object_add(jobj, "record_len", json_object_new_int(length)); - snprintf(verstr,8,"%d.%d",vermaj,vermin); + snprintf(verstr,8,"%d.%d",(version>>8)&0xff,version&0xff); json_object_object_add(jobj, "record_ver", json_object_new_string(verstr)); } - version=vermaj*256+vermin; - - r=ssl_decode_record(ssl,ssl->decoder,direction,ct,version,&d); - + r = ssl_decode_record(ssl, ssl->decoder, direction, ct, version, &d); if(r==SSL_BAD_MAC){ explain(ssl," bad MAC\n"); return(0); @@ -303,9 +301,15 @@ int ssl_expand_record(ssl,q,direction,data,len) else{ //try to save unencrypted data to logger //we must save record with type "application_data" (this is unencrypted data) - if ((ct == 23) && (logger)) logger->vtbl->data(ssl->logger_obj,d.data,d.len,direction); - - if((r=ssl_decode_switch(ssl,ContentType_decoder,data[0],direction,q, &d))) { + if (ct==23){ + if (logger) { + logger->vtbl->data(ssl->logger_obj,d.data,d.len,direction); + } + if (ssl->version==TLSV13_VERSION){ + ct = d.data[--d.len]; // In TLS 1.3 ct is stored in the end for encrypted records + } + } + if((r=ssl_decode_switch(ssl,ContentType_decoder,ct,direction,q, &d))) { if(!(SSL_print_flags & SSL_PRINT_JSON)) printf(" unknown record type: %d\n", ct); ERETURN(r);