Skip to content

Commit

Permalink
Upgrade crypto functions to support OTP 23
Browse files Browse the repository at this point in the history
  • Loading branch information
noahshaw11 committed Jun 1, 2021
1 parent 070594e commit dae0ac3
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 12 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ language: erlang
notifications:
email: false
otp_release:
- 23.0
- 22.0
- 21.3
- 21.2.3
Expand Down
Binary file modified rebar
Binary file not shown.
1 change: 1 addition & 0 deletions rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{erl_opts, [debug_info,
{platform_define, "^R15", 'gen_tcp_r15b_workaround'},
{platform_define, "^(R14|R15|R16B-)", 'crypto_compatibility'},
{platform_define, "^(R14|R15|R16|17|18|19|20|21|22)", new_crypto_unavailable},
{platform_define, "^(R14|R15|R16B|17)", 'rand_mod_unavailable'},
{platform_define, "^(R14|R15|R16B|17)", 'sni_unavailable'},
{platform_define, "^(R14|R15|R16)", 'map_unavailable'},
Expand Down
25 changes: 23 additions & 2 deletions src/mochiweb_session.erl
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,15 @@ decrypt_data(<<IV:16/binary, Crypt/binary>>, Key) ->
crypto:aes_cfb_128_decrypt(Key, IV, Crypt).

-spec gen_key(iolist(), iolist()) -> binary().
gen_key(ExpirationTime, ServerKey)->
gen_key(ExpirationTime, ServerKey) ->
crypto:md5_mac(ServerKey, [ExpirationTime]).

-spec gen_hmac(iolist(), binary(), iolist(), binary()) -> binary().
gen_hmac(ExpirationTime, Data, SessionKey, Key) ->
crypto:sha_mac(Key, [ExpirationTime, Data, SessionKey]).

-else.
-ifdef(new_crypto_unavailable).
-spec encrypt_data(binary(), binary()) -> binary().
encrypt_data(Data, Key) ->
IV = crypto:strong_rand_bytes(16),
Expand All @@ -150,13 +151,33 @@ decrypt_data(<<IV:16/binary, Crypt/binary>>, Key) ->
crypto:block_decrypt(aes_cfb128, Key, IV, Crypt).

-spec gen_key(iolist(), iolist()) -> binary().
gen_key(ExpirationTime, ServerKey)->
gen_key(ExpirationTime, ServerKey) ->
crypto:hmac(md5, ServerKey, [ExpirationTime]).

-spec gen_hmac(iolist(), binary(), iolist(), binary()) -> binary().
gen_hmac(ExpirationTime, Data, SessionKey, Key) ->
crypto:hmac(sha, Key, [ExpirationTime, Data, SessionKey]).

-else. % new crypto available (OTP 23+)
-spec encrypt_data(binary(), binary()) -> binary().
encrypt_data(Data, Key) ->
IV = crypto:strong_rand_bytes(16),
Crypt = crypto:crypto_one_time(aes_128_cfb128, Key, IV, Data, true),
<<IV/binary, Crypt/binary>>.

-spec decrypt_data(binary(), binary()) -> binary().
decrypt_data(<<IV:16/binary, Crypt/binary>>, Key) ->
crypto:crypto_one_time(aes_128_cfb128, Key, IV, Crypt, false).

-spec gen_key(iolist(), iolist()) -> binary().
gen_key(ExpirationTime, ServerKey) ->
crypto:mac(hmac, md5, ServerKey, [ExpirationTime]).

-spec gen_hmac(iolist(), binary(), iolist(), binary()) -> binary().
gen_hmac(ExpirationTime, Data, SessionKey, Key) ->
crypto:mac(hmac, sha, Key, [ExpirationTime, Data, SessionKey]).

-endif.
-endif.

-ifdef(TEST).
Expand Down
40 changes: 30 additions & 10 deletions src/mochiweb_socket.erl
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
listen(Ssl, Port, Opts, SslOpts) ->
case Ssl of
true ->
Opts1 = add_unbroken_ciphers_default(Opts ++ SslOpts),
Opts2 = add_safe_protocol_versions(Opts1),
Opts1 = add_safe_protocol_versions(Opts),
Opts2 = add_unbroken_ciphers_default(Opts1 ++ SslOpts),
case ssl:listen(Port, Opts2) of
{ok, ListenSocket} ->
{ok, {ssl, ListenSocket}};
Expand All @@ -29,11 +29,39 @@ listen(Ssl, Port, Opts, SslOpts) ->
gen_tcp:listen(Port, Opts)
end.

-ifdef(new_crypto_unavailable).
add_unbroken_ciphers_default(Opts) ->
Default = filter_unsecure_cipher_suites(ssl:cipher_suites()),
Ciphers = filter_broken_cipher_suites(proplists:get_value(ciphers, Opts, Default)),
[{ciphers, Ciphers} | proplists:delete(ciphers, Opts)].

%% Filter old map style cipher suites
filter_unsecure_cipher_suites(Ciphers) ->
lists:filter(fun
({_,des_cbc,_}) -> false;
({_,_,md5}) -> false;
(_) -> true
end,
Ciphers).

-else.
add_unbroken_ciphers_default(Opts) ->
%% add_safe_protocol_versions/1 must have been called to ensure a {versions, _} tuple is present
Versions = proplists:get_value(versions, Opts),
CipherSuites = lists:append([ssl:cipher_suites(all, Version) || Version <- Versions]),
Default = filter_unsecure_cipher_suites(CipherSuites),
Ciphers = filter_broken_cipher_suites(proplists:get_value(ciphers, Opts, Default)),
[{ciphers, Ciphers} | proplists:delete(ciphers, Opts)].

%% Filter new map style cipher suites
filter_unsecure_cipher_suites(Ciphers) ->
ssl:filter_cipher_suites(Ciphers, [
{key_exchange, fun(des_cbc) -> false; (_) -> true end},
{mac, fun(md5) -> false; (_) -> true end}
]).

-endif.

filter_broken_cipher_suites(Ciphers) ->
case proplists:get_value(ssl_app, ssl:versions()) of
"5.3" ++ _ ->
Expand All @@ -44,14 +72,6 @@ filter_broken_cipher_suites(Ciphers) ->
Ciphers
end.

filter_unsecure_cipher_suites(Ciphers) ->
lists:filter(fun
({_,des_cbc,_}) -> false;
({_,_,md5}) -> false;
(_) -> true
end,
Ciphers).

add_safe_protocol_versions(Opts) ->
case proplists:is_defined(versions, Opts) of
true ->
Expand Down

0 comments on commit dae0ac3

Please sign in to comment.