aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/src/tls_v1.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl/src/tls_v1.erl')
-rw-r--r--lib/ssl/src/tls_v1.erl52
1 files changed, 39 insertions, 13 deletions
diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl
index df2a421bce..f103f3218b 100644
--- a/lib/ssl/src/tls_v1.erl
+++ b/lib/ssl/src/tls_v1.erl
@@ -37,14 +37,14 @@
groups/1, groups/2, group_to_enum/1, enum_to_group/1, default_groups/1]).
-export([derive_secret/4, hkdf_expand_label/5, hkdf_extract/3, hkdf_expand/4,
- key_schedule/3, key_schedule/4,
+ key_schedule/3, key_schedule/4, create_info/3,
external_binder_key/2, resumption_binder_key/2,
client_early_traffic_secret/3, early_exporter_master_secret/3,
client_handshake_traffic_secret/3, server_handshake_traffic_secret/3,
client_application_traffic_secret_0/3, server_application_traffic_secret_0/3,
exporter_master_secret/3, resumption_master_secret/3,
update_traffic_secret/2, calculate_traffic_keys/3,
- transcript_hash/2]).
+ transcript_hash/2, finished_key/2, finished_verify_data/3]).
-type named_curve() :: sect571r1 | sect571k1 | secp521r1 | brainpoolP512r1 |
sect409k1 | sect409r1 | brainpoolP384r1 | secp384r1 |
@@ -64,7 +64,7 @@
%% TLS 1.3 ---------------------------------------------------
-spec derive_secret(Secret::binary(), Label::binary(),
- Messages::iodata(), Algo::ssl_cipher_format:hash()) -> Key::binary().
+ Messages::iodata(), Algo::ssl:hash()) -> Key::binary().
derive_secret(Secret, Label, Messages, Algo) ->
Hash = crypto:hash(mac_algo(Algo), Messages),
hkdf_expand_label(Secret, Label,
@@ -72,22 +72,28 @@ derive_secret(Secret, Label, Messages, Algo) ->
-spec hkdf_expand_label(Secret::binary(), Label0::binary(),
Context::binary(), Length::integer(),
- Algo::ssl_cipher_format:hash()) -> KeyingMaterial::binary().
+ Algo::ssl:hash()) -> KeyingMaterial::binary().
hkdf_expand_label(Secret, Label0, Context, Length, Algo) ->
+ HkdfLabel = create_info(Label0, Context, Length),
+ hkdf_expand(Secret, HkdfLabel, Length, Algo).
+
+%% Create info parameter for HKDF-Expand:
+%% HKDF-Expand(PRK, info, L) -> OKM
+create_info(Label0, Context0, Length) ->
%% struct {
%% uint16 length = Length;
%% opaque label<7..255> = "tls13 " + Label;
%% opaque context<0..255> = Context;
%% } HkdfLabel;
Label1 = << <<"tls13 ">>/binary, Label0/binary>>,
- LLen = size(Label1),
- Label = <<?BYTE(LLen), Label1/binary>>,
+ LabelLen = size(Label1),
+ Label = <<?BYTE(LabelLen), Label1/binary>>,
+ ContextLen = size(Context0),
+ Context = <<?BYTE(ContextLen),Context0/binary>>,
Content = <<Label/binary, Context/binary>>,
- Len = size(Content),
- HkdfLabel = <<?UINT16(Len), Content/binary>>,
- hkdf_expand(Secret, HkdfLabel, Length, Algo).
+ <<?UINT16(Length), Content/binary>>.
--spec hkdf_extract(MacAlg::ssl_cipher_format:hash(), Salt::binary(),
+-spec hkdf_extract(MacAlg::ssl:hash(), Salt::binary(),
KeyingMaterial::binary()) -> PseudoRandKey::binary().
hkdf_extract(MacAlg, Salt, KeyingMaterial) ->
@@ -95,14 +101,14 @@ hkdf_extract(MacAlg, Salt, KeyingMaterial) ->
-spec hkdf_expand(PseudoRandKey::binary(), ContextInfo::binary(),
- Length::integer(), Algo::ssl_cipher_format:hash()) -> KeyingMaterial::binary().
+ Length::integer(), Algo::ssl:hash()) -> KeyingMaterial::binary().
hkdf_expand(PseudoRandKey, ContextInfo, Length, Algo) ->
Iterations = erlang:ceil(Length / ssl_cipher:hash_size(Algo)),
hkdf_expand(Algo, PseudoRandKey, ContextInfo, Length, 1, Iterations, <<>>, <<>>).
--spec transcript_hash(Messages::iodata(), Algo::ssl_cipher_format:hash()) -> Hash::binary().
+-spec transcript_hash(Messages::iodata(), Algo::ssl:hash()) -> Hash::binary().
transcript_hash(Messages, Algo) ->
crypto:hash(mac_algo(Algo), Messages).
@@ -368,6 +374,25 @@ exporter_master_secret(Algo, {master_secret, Secret}, M) ->
resumption_master_secret(Algo, {master_secret, Secret}, M) ->
derive_secret(Secret, <<"res master">>, M, Algo).
+-spec finished_key(binary(), atom()) -> binary().
+finished_key(BaseKey, Algo) ->
+ %% finished_key =
+ %% HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
+ ssl_cipher:hash_size(Algo),
+ hkdf_expand_label(BaseKey, <<"finished">>, <<>>, ssl_cipher:hash_size(Algo), Algo).
+
+-spec finished_verify_data(binary(), atom(), iodata()) -> binary().
+finished_verify_data(FinishedKey, HKDFAlgo, Messages) ->
+ %% The verify_data value is computed as follows:
+ %%
+ %% verify_data =
+ %% HMAC(finished_key,
+ %% Transcript-Hash(Handshake Context,
+ %% Certificate*, CertificateVerify*))
+ Context = lists:reverse(Messages),
+ THash = tls_v1:transcript_hash(Context, HKDFAlgo),
+ tls_v1:hmac_hash(HKDFAlgo, FinishedKey, THash).
+
%% The next-generation application_traffic_secret is computed as:
%%
%% application_traffic_secret_N+1 =
@@ -394,7 +419,8 @@ update_traffic_secret(Algo, Secret) ->
-spec calculate_traffic_keys(atom(), atom(), binary()) -> {binary(), binary()}.
calculate_traffic_keys(HKDFAlgo, Cipher, Secret) ->
Key = hkdf_expand_label(Secret, <<"key">>, <<>>, ssl_cipher:key_material(Cipher), HKDFAlgo),
- IV = hkdf_expand_label(Secret, <<"iv">>, <<>>, ssl_cipher:key_material(Cipher), HKDFAlgo),
+ %% TODO: remove hard coded IV size
+ IV = hkdf_expand_label(Secret, <<"iv">>, <<>>, 12, HKDFAlgo),
{Key, IV}.
%% TLS v1.3 ---------------------------------------------------