aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/src
diff options
context:
space:
mode:
authorRaimo Niskanen <[email protected]>2019-02-08 16:18:58 +0100
committerRaimo Niskanen <[email protected]>2019-02-13 14:18:22 +0100
commit38ce21e37be4578a7a89856ddb91516279e58c13 (patch)
treedc11b7d43da11e6b3053fb0c11a2fffe5aeb51bd /lib/ssl/src
parentbdcfbe7966328a07814c301787173b80e5c20aa6 (diff)
downloadotp-38ce21e37be4578a7a89856ddb91516279e58c13.tar.gz
otp-38ce21e37be4578a7a89856ddb91516279e58c13.tar.bz2
otp-38ce21e37be4578a7a89856ddb91516279e58c13.zip
Small binary handling optimizations
Diffstat (limited to 'lib/ssl/src')
-rw-r--r--lib/ssl/src/ssl_cipher.erl5
-rw-r--r--lib/ssl/src/ssl_record.erl21
-rw-r--r--lib/ssl/src/tls_record.erl62
3 files changed, 48 insertions, 40 deletions
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index da2be0e50f..fce48d1678 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -113,12 +113,11 @@ nonce_seed(Seed, CipherState) ->
%% data is calculated and the data plus the HMAC is ecncrypted.
%%-------------------------------------------------------------------
cipher(?NULL, CipherState, <<>>, Fragment, _Version) ->
- GenStreamCipherList = [Fragment, <<>>],
- {GenStreamCipherList, CipherState};
+ {iolist_to_binary(Fragment), CipherState};
cipher(?RC4, CipherState = #cipher_state{state = State0}, Mac, Fragment, _Version) ->
GenStreamCipherList = [Fragment, Mac],
{State1, T} = crypto:stream_encrypt(State0, GenStreamCipherList),
- {T, CipherState#cipher_state{state = State1}};
+ {iolist_to_binary(T), CipherState#cipher_state{state = State1}};
cipher(?DES, CipherState, Mac, Fragment, Version) ->
block_cipher(fun(Key, IV, T) ->
crypto:block_encrypt(des_cbc, Key, IV, T)
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index a82efe2799..cf5368a19f 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -423,11 +423,13 @@ random() ->
Random_28_bytes = ssl_cipher:random_bytes(28),
<<?UINT32(Secs_since_1970), Random_28_bytes/binary>>.
+-compile({inline, [is_correct_mac/2]}).
is_correct_mac(Mac, Mac) ->
true;
is_correct_mac(_M,_H) ->
false.
+-compile({inline, [record_protocol_role/1]}).
record_protocol_role(client) ->
?CLIENT;
record_protocol_role(server) ->
@@ -451,13 +453,15 @@ initial_security_params(ConnectionEnd) ->
compression_algorithm = ?NULL},
ssl_cipher:security_parameters(?TLS_NULL_WITH_NULL_NULL, SecParams).
+-define(end_additional_data(AAD, Len), << (begin(AAD)end)/binary, ?UINT16(begin(Len)end) >>).
+
do_cipher_aead(?CHACHA20_POLY1305 = Type, Fragment, #cipher_state{key=Key} = CipherState, AAD0) ->
- AAD = end_additional_data(AAD0, erlang:iolist_size(Fragment)),
+ AAD = ?end_additional_data(AAD0, erlang:iolist_size(Fragment)),
Nonce = encrypt_nonce(Type, CipherState),
{Content, CipherTag} = ssl_cipher:aead_encrypt(Type, Key, Nonce, Fragment, AAD),
{<<Content/binary, CipherTag/binary>>, CipherState};
do_cipher_aead(Type, Fragment, #cipher_state{key=Key, nonce = ExplicitNonce} = CipherState, AAD0) ->
- AAD = end_additional_data(AAD0, erlang:iolist_size(Fragment)),
+ AAD = ?end_additional_data(AAD0, erlang:iolist_size(Fragment)),
Nonce = encrypt_nonce(Type, CipherState),
{Content, CipherTag} = ssl_cipher:aead_encrypt(Type, Key, Nonce, Fragment, AAD),
{<<ExplicitNonce:64/integer, Content/binary, CipherTag/binary>>, CipherState#cipher_state{nonce = ExplicitNonce + 1}}.
@@ -473,15 +477,12 @@ decrypt_nonce(?CHACHA20_POLY1305, #cipher_state{nonce = Nonce, iv = IV}, _) ->
decrypt_nonce(?AES_GCM, #cipher_state{iv = <<Salt:4/bytes, _/binary>>}, <<ExplicitNonce:8/bytes, _/binary>>) ->
<<Salt/binary, ExplicitNonce/binary>>.
+-compile({inline, [aead_ciphertext_split/4]}).
aead_ciphertext_split(?CHACHA20_POLY1305, #cipher_state{tag_len = Len}, CipherTextFragment, AAD) ->
- CipherLen = size(CipherTextFragment) - Len,
+ CipherLen = byte_size(CipherTextFragment) - Len,
<<CipherText:CipherLen/bytes, CipherTag:Len/bytes>> = CipherTextFragment,
- {end_additional_data(AAD, CipherLen), CipherText, CipherTag};
+ {?end_additional_data(AAD, CipherLen), CipherText, CipherTag};
aead_ciphertext_split(?AES_GCM, #cipher_state{tag_len = Len}, CipherTextFragment, AAD) ->
- CipherLen = size(CipherTextFragment) - (Len + 8), %% 8 is length of explicit Nonce
+ CipherLen = byte_size(CipherTextFragment) - (Len + 8), %% 8 is length of explicit Nonce
<< _:8/bytes, CipherText:CipherLen/bytes, CipherTag:Len/bytes>> = CipherTextFragment,
- {end_additional_data(AAD, CipherLen), CipherText, CipherTag}.
-
-end_additional_data(AAD, Len) ->
- <<AAD/binary, ?UINT16(Len)>>.
-
+ {?end_additional_data(AAD, CipherLen), CipherText, CipherTag}.
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index ce21e40dd8..e68f9a19df 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -155,26 +155,34 @@ encode_data(Frag, Version,
%%
%% Description: Decode cipher text
%%--------------------------------------------------------------------
-decode_cipher_text(#ssl_tls{type = Type, version = Version} = CipherText,
+decode_cipher_text(CipherText,
#{current_read :=
#{sequence_number := Seq,
- security_parameters := #security_parameters{cipher_type = ?AEAD} = SecParams
- } = ReadState0} = ConnnectionStates0, _) ->
- AAD = start_additional_data(Type, Version, Seq),
- #{cipher_state := CipherS0} = ReadState0,
- BulkCipherAlgo = SecParams#security_parameters.bulk_cipher_algorithm,
- CipherS1 = ssl_record:nonce_seed(BulkCipherAlgo, <<?UINT64(Seq)>>, CipherS0),
- case ssl_record:decipher_aead(BulkCipherAlgo, CipherS1, AAD, CipherText#ssl_tls.fragment, Version) of
- {PlainFragment, CipherState} ->
- #{compression_state := CompressionS0} = ReadState0,
- {Plain, CompressionS1} = ssl_record:uncompress(SecParams#security_parameters.compression_algorithm,
- PlainFragment, CompressionS0),
- ConnnectionStates = ConnnectionStates0#{
+ security_parameters :=
+ #security_parameters{cipher_type = ?AEAD,
+ bulk_cipher_algorithm = BulkCipherAlgo},
+ cipher_state := CipherS0
+ }
+ } = ConnectionStates0, _) ->
+ SeqBin = <<?UINT64(Seq)>>,
+ CipherS1 = ssl_record:nonce_seed(BulkCipherAlgo, SeqBin, CipherS0),
+ #ssl_tls{type = Type, version = {MajVer,MinVer} = Version, fragment = Fragment} = CipherText,
+ StartAdditionalData = <<SeqBin/binary, ?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer)>>,
+ case ssl_record:decipher_aead(
+ BulkCipherAlgo, CipherS1, StartAdditionalData, Fragment, Version)
+ of
+ {PlainFragment, CipherS} ->
+ #{current_read :=
+ #{security_parameters := SecParams,
+ compression_state := CompressionS0} = ReadState0} = ConnectionStates0,
+ {Plain, CompressionS} = ssl_record:uncompress(SecParams#security_parameters.compression_algorithm,
+ PlainFragment, CompressionS0),
+ ConnectionStates = ConnectionStates0#{
current_read => ReadState0#{
- cipher_state => CipherState,
+ cipher_state => CipherS,
sequence_number => Seq + 1,
- compression_state => CompressionS1}},
- {CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
+ compression_state => CompressionS}},
+ {CipherText#ssl_tls{fragment = Plain}, ConnectionStates};
#alert{} = Alert ->
Alert
end;
@@ -534,10 +542,14 @@ encode_iolist(Type, Version, [Text|Data],
compression_algorithm = CompAlg} = SecPars}} = CS,
CompS0, CipherS0, Seq, CipherFragments) ->
{CompText, CompS} = ssl_record:compress(CompAlg, Text, CompS0),
- CipherS1 = ssl_record:nonce_seed(BCAlg, <<?UINT64(Seq)>>, CipherS0),
- AAD = start_additional_data(Type, Version, Seq),
- {CipherFragment,CipherS} = ssl_record:cipher_aead(Version, CompText, CipherS1, AAD, SecPars),
- CipherHeader = cipher_header(Type, Version, CipherFragment),
+ SeqBin = <<?UINT64(Seq)>>,
+ CipherS1 = ssl_record:nonce_seed(BCAlg, SeqBin, CipherS0),
+ {MajVer, MinVer} = Version,
+ VersionBin = <<?BYTE(MajVer), ?BYTE(MinVer)>>,
+ StartAdditionalData = <<SeqBin/binary, ?BYTE(Type), VersionBin/binary>>,
+ {CipherFragment,CipherS} = ssl_record:cipher_aead(Version, CompText, CipherS1, StartAdditionalData, SecPars),
+ Length = byte_size(CipherFragment),
+ CipherHeader = <<?BYTE(Type), VersionBin/binary, ?UINT16(Length)>>,
encode_iolist(Type, Version, Data, CS, CompS, CipherS, Seq + 1,
[[CipherHeader, CipherFragment] | CipherFragments]);
encode_iolist(Type, Version, [Text|Data],
@@ -549,18 +561,14 @@ encode_iolist(Type, Version, [Text|Data],
{CompText, CompS} = ssl_record:compress(CompAlg, Text, CompS0),
MacHash = ssl_cipher:calc_mac_hash(Type, Version, CompText, MacAlgorithm, MacSecret, Seq),
{CipherFragment,CipherS} = ssl_record:cipher(Version, CompText, CipherS0, MacHash, SecPars),
- CipherHeader = cipher_header(Type, Version, CipherFragment),
+ Length = byte_size(CipherFragment),
+ {MajVer, MinVer} = Version,
+ CipherHeader = <<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Length)>>,
encode_iolist(Type, Version, Data, CS, CompS, CipherS, Seq + 1,
[[CipherHeader, CipherFragment] | CipherFragments]);
encode_iolist(_Type, _Version, _Data, CS, _CompS, _CipherS, _Seq, _CipherFragments) ->
exit({cs, CS}).
%%--------------------------------------------------------------------
-cipher_header(Type, {MajVer, MinVer}, CipherFragment) ->
- Length = erlang:iolist_size(CipherFragment),
- <<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Length)>>.
-
-start_additional_data(Type, {MajVer, MinVer}, SeqNo) ->
- <<?UINT64(SeqNo), ?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer)>>.
%% 1/n-1 splitting countermeasure Rizzo/Duong-Beast, RC4 chiphers are
%% not vulnerable to this attack.