From 5e601bce3e19cdc3d3f2b77313e3ee57b8dce482 Mon Sep 17 00:00:00 2001 From: Sergey Prokhorov Date: Tue, 13 Aug 2019 15:24:17 +0200 Subject: [PATCH] Make it really look like TLSv1.3 By providing key_share and upported_versions extensions in ServerHello --- src/mtp_fake_tls.erl | 88 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 15 deletions(-) diff --git a/src/mtp_fake_tls.erl b/src/mtp_fake_tls.erl index 9808e77..476c242 100644 --- a/src/mtp_fake_tls.erl +++ b/src/mtp_fake_tls.erl @@ -38,6 +38,7 @@ -define(TLS_10_VERSION, 3, 1). -define(TLS_12_VERSION, 3, 3). +-define(TLS_13_VERSION, 3, 4). -define(TLS_REC_CHANGE_CIPHER, 20). -define(TLS_REC_HANDSHAKE, 22). -define(TLS_REC_DATA, 23). @@ -61,6 +62,10 @@ -define(EXT_SNI, 0). -define(EXT_SNI_HOST_NAME, 0). +-define(EXT_KEY_SHARE, 51). + +-define(EXT_SUPPORTED_VERSIONS, 43). + -define(APP, mtproto_proxy). -opaque codec() :: #st{}. @@ -97,16 +102,17 @@ from_client_hello(Data, Secret) -> <> = XoredDigest = crypto:exor(ClientDigest, ServerDigest), lists:all(fun(B) -> B == 0 end, binary_to_list(Zeroes)) orelse - error({protocol_error, invalid_tls_digest, XoredDigest}), + error({protocol_error, tls_invalid_digest, XoredDigest}), <<_:(?DIGEST_LEN - 4)/binary, Timestamp:32/unsigned-little>> = XoredDigest, + KeyShare = make_key_share(Extensions), + SrvHello0 = make_srv_hello(binary:copy(<<0>>, ?DIGEST_LEN), SessionId, KeyShare), FakeHttpData = crypto:strong_rand_bytes(rand:uniform(256)), - SrvHello0 = make_srv_hello(binary:copy(<<0>>, ?DIGEST_LEN), SessionId), Response0 = [_, CC, DD] = [as_tls_frame(?TLS_REC_HANDSHAKE, SrvHello0), as_tls_frame(?TLS_REC_CHANGE_CIPHER, [1]), as_tls_frame(?TLS_REC_DATA, FakeHttpData)], SrvHelloDigest = crypto:hmac(sha256, Secret, [ClientDigest | Response0]), - SrvHello = make_srv_hello(SrvHelloDigest, SessionId), + SrvHello = make_srv_hello(SrvHelloDigest, SessionId, KeyShare), Response = [as_tls_frame(?TLS_REC_HANDSHAKE, SrvHello), CC, DD], @@ -149,9 +155,11 @@ parse_extensions(Exts) -> || <> <= Exts]. parse_extension(?EXT_SNI, <>) -> - SNIList = [{Type, Value} - || <> <= List], - SNIList; + [{Type, Value} + || <> <= List]; +parse_extension(?EXT_KEY_SHARE, <>) -> + [{Group, Key} + || <> <= Exts]; parse_extension(_Type, Data) -> Data. @@ -160,16 +168,66 @@ make_server_digest(<>, ?DIGEST_LEN), Right], crypto:hmac(sha256, Secret, Msg). -make_srv_hello(Digest, SessionId) -> +make_key_share(Exts) -> + case lists:keyfind(?EXT_KEY_SHARE, 1, Exts) of + {_, KeyShares} -> + SupportedKeyShares = + lists:dropwhile( + fun({Group, Key}) -> + not ( + byte_size(Key) < 128 + andalso + lists:member( % https://tools.ietf.org/html/rfc8446#appendix-B.3.1.4 + Group, [% secp256r1 + 16#0017, + % secp384r1 + 16#0018, + % secp521r1 + 16#0019, + % x25519 + 16#001D, + % x448 + 16#001E, + % ffdhe2048 + 16#0100, + % ffdhe3072 + 16#0101, + % ffdhe4096 + 16#0102, + % ffdhe6144 + 16#0103, + % ffdhe8192 + 16#0104]) + ) + end, KeyShares), + case SupportedKeyShares of + [] -> + error({protocol_error, tls_unsupported_key_shares, KeyShares}); + [{KSGroup, KSKey} | _] -> + {KSGroup, crypto:strong_rand_bytes(byte_size(KSKey))} + end; + _ -> + error({protocol_error, tls_missing_key_share_ext, Exts}) + end. + +make_srv_hello(Digest, SessionId, {KeyShareGroup, KeyShareKey}) -> + %% https://tools.ietf.org/html/rfc8446#section-4.1.3 + KeyShareEntity = <>, + Extensions = + [<>, + KeyShareEntity, + <>], SessionSize = byte_size(SessionId), - Payload = <>, - [<> | Payload]. + Payload = [<> + | Extensions], + [<> | Payload]. -spec new() -> codec().