aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/compiler/src/beam_ssa_pre_codegen.erl141
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl35
-rw-r--r--lib/crypto/doc/src/crypto.xml56
-rw-r--r--lib/crypto/doc/src/new_api.xml89
-rw-r--r--lib/crypto/src/crypto.erl21
-rw-r--r--lib/erl_interface/doc/src/ei.xml60
-rw-r--r--lib/erl_interface/include/ei.h8
-rw-r--r--lib/erl_interface/src/decode/decode_binary.c61
-rw-r--r--lib/erl_interface/src/decode/decode_skip.c10
-rw-r--r--lib/erl_interface/src/encode/encode_binary.c101
-rw-r--r--lib/erl_interface/src/misc/ei_printterm.c14
-rw-r--r--lib/erl_interface/src/misc/ei_x_encode.c6
-rw-r--r--lib/erl_interface/src/misc/show_msg.c9
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c7
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c15
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE.erl20
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c79
-rw-r--r--lib/kernel/src/erl_distribution.erl6
-rw-r--r--lib/kernel/src/user_drv.erl8
-rw-r--r--lib/kernel/test/erl_distribution_SUITE.erl8
-rw-r--r--lib/sasl/src/Makefile4
-rw-r--r--lib/sasl/src/systools_make.erl10
-rw-r--r--lib/ssh/src/ssh.app.src10
-rw-r--r--lib/ssl/test/Makefile1
-rw-r--r--lib/ssl/test/openssl_server_cipher_suite_SUITE.erl768
-rw-r--r--lib/ssl/test/ssl_ECC_SUITE.erl59
-rw-r--r--lib/ssl/test/ssl_ECC_openssl_SUITE.erl96
-rw-r--r--lib/ssl/test/ssl_cipher_suite_SUITE.erl55
-rw-r--r--lib/ssl/test/ssl_test_lib.erl89
-rw-r--r--lib/stdlib/doc/src/gb_trees.xml7
-rw-r--r--lib/stdlib/doc/src/queue.xml2
31 files changed, 1431 insertions, 424 deletions
diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl
index bad43a9c4e..bf99e8fc26 100644
--- a/lib/compiler/src/beam_ssa_pre_codegen.erl
+++ b/lib/compiler/src/beam_ssa_pre_codegen.erl
@@ -342,21 +342,22 @@ make_save_point_dict_1([], Ctx, I, Acc) ->
[{Ctx,I}|Acc].
bs_restores([{L,#b_blk{is=Is,last=Last}}|Bs], CtxChain, D0, Rs0) ->
- FPos = case D0 of
- #{L:=Pos0} -> Pos0;
- #{} -> #{}
- end,
- {SPos,Rs} = bs_restores_is(Is, CtxChain, FPos, Rs0),
- D = bs_update_successors(Last, SPos, FPos, D0),
+ InPos = maps:get(L, D0, #{}),
+ {SuccPos, FailPos, Rs} = bs_restores_is(Is, CtxChain, InPos, InPos, Rs0),
+
+ D = bs_update_successors(Last, SuccPos, FailPos, D0),
bs_restores(Bs, CtxChain, D, Rs);
bs_restores([], _, _, Rs) -> Rs.
bs_update_successors(#b_br{succ=Succ,fail=Fail}, SPos, FPos, D) ->
join_positions([{Succ,SPos},{Fail,FPos}], D);
-bs_update_successors(#b_switch{fail=Fail,list=List}, SPos, _FPos, D) ->
+bs_update_successors(#b_switch{fail=Fail,list=List}, SPos, FPos, D) ->
+ SPos = FPos, %Assertion.
Update = [{L,SPos} || {_,L} <- List] ++ [{Fail,SPos}],
join_positions(Update, D);
-bs_update_successors(#b_ret{}, _, _, D) -> D.
+bs_update_successors(#b_ret{}, SPos, FPos, D) ->
+ SPos = FPos, %Assertion.
+ D.
join_positions([{L,MapPos0}|T], D) ->
case D of
@@ -382,75 +383,91 @@ join_positions_1(MapPos0, MapPos1) ->
end, MapPos1),
maps:merge(MapPos0, MapPos2).
+%%
+%% Updates the restore and position maps according to the given instructions.
+%%
+%% Note that positions may be updated even when a match fails; if a match
+%% requires a restore, the position at the fail block will be the position
+%% we've *restored to* and not the one we entered the current block with.
+%%
+
bs_restores_is([#b_set{op=bs_start_match,dst=Start}|Is],
- CtxChain, PosMap0, Rs) ->
- PosMap = PosMap0#{Start=>Start},
- bs_restores_is(Is, CtxChain, PosMap, Rs);
+ CtxChain, SPos0, FPos, Rs) ->
+ %% We only allow one match per block.
+ SPos0 = FPos, %Assertion.
+ SPos = SPos0#{Start=>Start},
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs);
bs_restores_is([#b_set{op=bs_match,dst=NewPos,args=Args}=I|Is],
- CtxChain, PosMap0, Rs0) ->
+ CtxChain, SPos0, FPos0, Rs0) ->
+ SPos0 = FPos0, %Assertion.
Start = bs_subst_ctx(NewPos, CtxChain),
[_,FromPos|_] = Args,
- case PosMap0 of
+ case SPos0 of
#{Start:=FromPos} ->
%% Same position, no restore needed.
- PosMap = case bs_match_type(I) of
+ SPos = case bs_match_type(I) of
plain ->
%% Update position to new position.
- PosMap0#{Start:=NewPos};
+ SPos0#{Start:=NewPos};
_ ->
%% Position will not change (test_unit
%% instruction or no instruction at
%% all).
- PosMap0#{Start:=FromPos}
+ SPos0#{Start:=FromPos}
end,
- bs_restores_is(Is, CtxChain, PosMap, Rs0);
+ bs_restores_is(Is, CtxChain, SPos, FPos0, Rs0);
#{Start:=_} ->
%% Different positions, might need a restore instruction.
case bs_match_type(I) of
none ->
- %% The tail test will be optimized away.
- %% No need to do a restore.
- PosMap = PosMap0#{Start:=FromPos},
- bs_restores_is(Is, CtxChain, PosMap, Rs0);
+ %% This is a tail test that will be optimized away.
+ %% There's no need to do a restore, and all
+ %% positions are unchanged.
+ bs_restores_is(Is, CtxChain, SPos0, FPos0, Rs0);
test_unit ->
%% This match instruction will be replaced by
%% a test_unit instruction. We will need a
%% restore. The new position will be the position
%% restored to (NOT NewPos).
- PosMap = PosMap0#{Start:=FromPos},
+ SPos = SPos0#{Start:=FromPos},
+ FPos = FPos0#{Start:=FromPos},
Rs = Rs0#{NewPos=>{Start,FromPos}},
- bs_restores_is(Is, CtxChain, PosMap, Rs);
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs);
plain ->
%% Match or skip. Position will be changed.
- PosMap = PosMap0#{Start:=NewPos},
+ SPos = SPos0#{Start:=NewPos},
+ FPos = FPos0#{Start:=FromPos},
Rs = Rs0#{NewPos=>{Start,FromPos}},
- bs_restores_is(Is, CtxChain, PosMap, Rs)
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs)
end
end;
bs_restores_is([#b_set{op=bs_extract,args=[FromPos|_]}|Is],
- CtxChain, PosMap, Rs) ->
+ CtxChain, SPos, FPos, Rs) ->
Start = bs_subst_ctx(FromPos, CtxChain),
- #{Start:=FromPos} = PosMap, %Assertion.
- bs_restores_is(Is, CtxChain, PosMap, Rs);
+ #{Start:=FromPos} = SPos, %Assertion.
+ #{Start:=FromPos} = FPos, %Assertion.
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs);
bs_restores_is([#b_set{op=call,dst=Dst,args=Args}|Is],
- CtxChain, PosMap0, Rs0) ->
- {Rs,PosMap1} = bs_restore_args(Args, PosMap0, CtxChain, Dst, Rs0),
- PosMap = bs_invalidate_pos(Args, PosMap1, CtxChain),
- bs_restores_is(Is, CtxChain, PosMap, Rs);
-bs_restores_is([#b_set{op=landingpad}|Is], CtxChain, PosMap0, Rs) ->
+ CtxChain, SPos0, FPos0, Rs0) ->
+ {Rs, SPos1, FPos1} = bs_restore_args(Args, SPos0, FPos0, CtxChain, Dst, Rs0),
+ {SPos, FPos} = bs_invalidate_pos(Args, SPos1, FPos1, CtxChain),
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs);
+bs_restores_is([#b_set{op=landingpad}|Is], CtxChain, SPos0, FPos0, Rs) ->
%% We can land here from any point, so all positions are invalid.
- PosMap = maps:map(fun(_Start,_Pos) -> unknown end, PosMap0),
- bs_restores_is(Is, CtxChain, PosMap, Rs);
+ Invalidate = fun(_Start,_Pos) -> unknown end,
+ SPos = maps:map(Invalidate, SPos0),
+ FPos = maps:map(Invalidate, FPos0),
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs);
bs_restores_is([#b_set{op=Op,dst=Dst,args=Args}|Is],
- CtxChain, PosMap0, Rs0)
+ CtxChain, SPos0, FPos0, Rs0)
when Op =:= bs_test_tail;
Op =:= bs_get_tail ->
- {Rs,PosMap} = bs_restore_args(Args, PosMap0, CtxChain, Dst, Rs0),
- bs_restores_is(Is, CtxChain, PosMap, Rs);
-bs_restores_is([_|Is], CtxChain, PosMap, Rs) ->
- bs_restores_is(Is, CtxChain, PosMap, Rs);
-bs_restores_is([], _CtxChain, PosMap, Rs) ->
- {PosMap,Rs}.
+ {Rs, SPos, FPos} = bs_restore_args(Args, SPos0, FPos0, CtxChain, Dst, Rs0),
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs);
+bs_restores_is([_|Is], CtxChain, SPos, FPos, Rs) ->
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs);
+bs_restores_is([], _CtxChain, SPos, FPos, Rs) ->
+ {SPos, FPos, Rs}.
bs_match_type(#b_set{args=[#b_literal{val=skip},_Ctx,
#b_literal{val=binary},_Flags,
@@ -464,40 +481,42 @@ bs_match_type(_) ->
%% Call instructions leave the match position in an undefined state,
%% requiring us to invalidate each affected argument.
-bs_invalidate_pos([#b_var{}=Arg|Args], PosMap0, CtxChain) ->
+bs_invalidate_pos([#b_var{}=Arg|Args], SPos0, FPos0, CtxChain) ->
Start = bs_subst_ctx(Arg, CtxChain),
- case PosMap0 of
+ case SPos0 of
#{Start:=_} ->
- PosMap = PosMap0#{Start:=unknown},
- bs_invalidate_pos(Args, PosMap, CtxChain);
+ SPos = SPos0#{Start:=unknown},
+ FPos = FPos0#{Start:=unknown},
+ bs_invalidate_pos(Args, SPos, FPos, CtxChain);
#{} ->
%% Not a match context.
- bs_invalidate_pos(Args, PosMap0, CtxChain)
+ bs_invalidate_pos(Args, SPos0, FPos0, CtxChain)
end;
-bs_invalidate_pos([_|Args], PosMap, CtxChain) ->
- bs_invalidate_pos(Args, PosMap, CtxChain);
-bs_invalidate_pos([], PosMap, _CtxChain) ->
- PosMap.
+bs_invalidate_pos([_|Args], SPos, FPos, CtxChain) ->
+ bs_invalidate_pos(Args, SPos, FPos, CtxChain);
+bs_invalidate_pos([], SPos, FPos, _CtxChain) ->
+ {SPos, FPos}.
-bs_restore_args([#b_var{}=Arg|Args], PosMap0, CtxChain, Dst, Rs0) ->
+bs_restore_args([#b_var{}=Arg|Args], SPos0, FPos0, CtxChain, Dst, Rs0) ->
Start = bs_subst_ctx(Arg, CtxChain),
- case PosMap0 of
+ case SPos0 of
#{Start:=Arg} ->
%% Same position, no restore needed.
- bs_restore_args(Args, PosMap0, CtxChain, Dst, Rs0);
+ bs_restore_args(Args, SPos0, FPos0, CtxChain, Dst, Rs0);
#{Start:=_} ->
%% Different positions, need a restore instruction.
- PosMap = PosMap0#{Start:=Arg},
+ SPos = SPos0#{Start:=Arg},
+ FPos = FPos0#{Start:=Arg},
Rs = Rs0#{Dst=>{Start,Arg}},
- bs_restore_args(Args, PosMap, CtxChain, Dst, Rs);
+ bs_restore_args(Args, SPos, FPos, CtxChain, Dst, Rs);
#{} ->
%% Not a match context.
- bs_restore_args(Args, PosMap0, CtxChain, Dst, Rs0)
+ bs_restore_args(Args, SPos0, FPos0, CtxChain, Dst, Rs0)
end;
-bs_restore_args([_|Args], PosMap, CtxChain, Dst, Rs) ->
- bs_restore_args(Args, PosMap, CtxChain, Dst, Rs);
-bs_restore_args([], PosMap, _CtxChain, _Dst, Rs) ->
- {Rs,PosMap}.
+bs_restore_args([_|Args], SPos, FPos, CtxChain, Dst, Rs) ->
+ bs_restore_args(Args, SPos, FPos, CtxChain, Dst, Rs);
+bs_restore_args([], SPos, FPos, _CtxChain, _Dst, Rs) ->
+ {Rs,SPos,FPos}.
%% Insert all bs_save and bs_restore instructions.
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 41e4918b1e..d97f49c56e 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -1891,15 +1891,37 @@ expression_before_match_1(R) ->
%% Make sure that context positions are updated on calls.
restore_on_call(Config) when is_list(Config) ->
- ok = restore_on_call_1(<<0, 1, 2>>).
+ ok = restore_on_call_plain(<<0, 1, 2>>),
+ <<"x">> = restore_on_call_match(<<0, "x">>),
+ ok.
-restore_on_call_1(<<0, Rest/binary>>) ->
- <<2>> = restore_on_call_2(Rest),
- <<2>> = restore_on_call_2(Rest), %% {badmatch, <<>>} on missing restore.
+restore_on_call_plain(<<0, Rest/binary>>) ->
+ <<2>> = restore_on_call_plain_1(Rest),
+ %% {badmatch, <<>>} on missing restore.
+ <<2>> = restore_on_call_plain_1(Rest),
ok.
-restore_on_call_2(<<1, Rest/binary>>) -> Rest;
-restore_on_call_2(Other) -> Other.
+restore_on_call_plain_1(<<1, Rest/binary>>) -> Rest;
+restore_on_call_plain_1(Other) -> Other.
+
+%% Calls a function that moves the match context passed to it, and then matches
+%% on its result to confuse the reposition algorithm's success/fail logic.
+restore_on_call_match(<<0, Bin/binary>>) ->
+ case skip_until_zero(Bin) of
+ {skipped, Rest} ->
+ Rest;
+ not_found ->
+ %% The match context did not get repositioned before the
+ %% bs_get_tail instruction here.
+ Bin
+ end.
+
+skip_until_zero(<<0,Rest/binary>>) ->
+ {skipped, Rest};
+skip_until_zero(<<_C,Rest/binary>>) ->
+ skip_until_zero(Rest);
+skip_until_zero(_) ->
+ not_found.
%% 'catch' must invalidate positions.
restore_after_catch(Config) when is_list(Config) ->
@@ -1983,5 +2005,4 @@ do_matching_meets_apply(_Bin, {Handler, State}) ->
%% Another case of the above.
Handler:abs(State).
-
id(I) -> I.
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 641738247e..d1d1252f29 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -678,7 +678,8 @@
</p>
<p>For encryption, set the <c>EncryptFlag</c> to <c>true</c>. For decryption, set it to <c>false</c>.
</p>
- <p>See <seealso marker="crypto:new_api#the-new-api">examples in the User's Guide.</seealso>
+ <p>See <seealso marker="crypto:new_api#examples-of-crypto_init-4-and-crypto_update-2">
+ examples in the User's Guide.</seealso>
</p>
</desc>
</func>
@@ -696,7 +697,8 @@
or
<seealso marker="crypto#crypto_init/4">crypto_init/4</seealso>.
</p>
- <p>See <seealso marker="crypto:new_api#the-new-api">examples in the User's Guide.</seealso>
+ <p>See <seealso marker="crypto:new_api#examples-of-crypto_init-4-and-crypto_update-2">
+ examples in the User's Guide.</seealso>
</p>
</desc>
</func>
@@ -712,8 +714,6 @@
</p>
<p>For encryption, set the <c>EncryptFlag</c> to <c>true</c>. For decryption, set it to <c>false</c>.
</p>
- <p>See <seealso marker="crypto:new_api#the-new-api">examples in the User's Guide.</seealso>
- </p>
</desc>
</func>
@@ -726,8 +726,6 @@
The <c>State</c> should be created with
<seealso marker="crypto#crypto_dyn_iv_init/3">crypto_dyn_iv_init/3</seealso>.
</p>
- <p>See <seealso marker="crypto:new_api#the-new-api">examples in the User's Guide.</seealso>
- </p>
</desc>
</func>
@@ -744,11 +742,11 @@
<fsummary>Do a complete encrypt or decrypt of the full text</fsummary>
<desc>
<p>Part of the <seealso marker="crypto:new_api#the-new-api">new API</seealso>.
- Do a complete encrypt or decrypt of the full text.
+ Do a complete encrypt or decrypt of the full text in the argument <c>Data</c>.
</p>
<p>For encryption, set the <c>EncryptFlag</c> to <c>true</c>. For decryption, set it to <c>false</c>.
</p>
- <p>See <seealso marker="crypto:new_api#the-new-api">examples in the User's Guide.</seealso>
+ <p>See <seealso marker="crypto:new_api#example-of-crypto_one_time-5">examples in the User's Guide.</seealso>
</p>
</desc>
</func>
@@ -768,10 +766,23 @@
<p>For decryption, set the <c>EncryptFlag</c> to <c>false</c> and put the tag to be checked
in the argument <c>TagOrTagLength</c>.
</p>
- <p>See <seealso marker="crypto:new_api#the-new-api">examples in the User's Guide.</seealso>
+ <p>See <seealso marker="crypto:new_api#example-of-crypto_one_time_aead-6">examples in the User's Guide.</seealso>
</p>
</desc>
</func>
+
+ <func>
+ <name name="supports" arity="1" since="OTP 22.0"/>
+ <fsummary>Provide a list of available crypto algorithms.</fsummary>
+ <desc>
+ <p> Can be used to determine which crypto algorithms that are supported
+ by the underlying libcrypto library</p>
+ <p>See <seealso marker="#hash_info-1">hash_info/1</seealso> and <seealso marker="#cipher_info-1">cipher_info/1</seealso>
+ for information about the hash and cipher algorithms.
+ </p>
+ </desc>
+ </func>
+
</funcs>
<section>
@@ -1425,18 +1436,6 @@ FloatValue = rand:uniform(). % again
</desc>
</func>
- <func>
- <name name="supports" arity="0" since="OTP R16B01"/>
- <fsummary>Provide a list of available crypto algorithms.</fsummary>
- <desc>
- <p> Can be used to determine which crypto algorithms that are supported
- by the underlying libcrypto library</p>
- <p>See <seealso marker="#hash_info-1">hash_info/1</seealso> and <seealso marker="#cipher_info-1">cipher_info/1</seealso>
- for information about the hash and cipher algorithms.
- </p>
- </desc>
- </func>
-
<func>
<name name="ec_curves" arity="0" since="OTP 17.0"/>
<fsummary>Provide a list of available named elliptic curves.</fsummary>
@@ -1947,6 +1946,21 @@ FloatValue = rand:uniform(). % again
</desc>
</func>
+ <func>
+ <name name="supports" arity="0" since="OTP R16B01"/>
+ <fsummary>Provide a list of available crypto algorithms.</fsummary>
+ <desc>
+ <dont><p>Don't use this function for new programs! Use
+ <seealso marker="crypto#supports-1">supports/1</seealso> in
+ <seealso marker="crypto:new_api">the new api</seealso>.</p></dont>
+ <p> Can be used to determine which crypto algorithms that are supported
+ by the underlying libcrypto library</p>
+ <p>See <seealso marker="#hash_info-1">hash_info/1</seealso> and <seealso marker="#cipher_info-1">cipher_info/1</seealso>
+ for information about the hash and cipher algorithms.
+ </p>
+ </desc>
+ </func>
+
</funcs>
diff --git a/lib/crypto/doc/src/new_api.xml b/lib/crypto/doc/src/new_api.xml
index 79096b55e8..bd2334ac9f 100644
--- a/lib/crypto/doc/src/new_api.xml
+++ b/lib/crypto/doc/src/new_api.xml
@@ -59,8 +59,9 @@
<item><seealso marker="crypto#stream_init-2">stream_init/3</seealso></item>
<item><seealso marker="crypto#stream_encrypt-2">stream_encrypt/2</seealso></item>
<item><seealso marker="crypto#stream_decrypt-2">stream_decrypt/2</seealso></item>
+ <item><seealso marker="crypto#supports-0">supports/0</seealso></item>
</list>
- <p>They are not deprecated for now, but may be in a future.
+ <p>They are not deprecated for now, but may be in a future release.
</p>
</section>
@@ -75,7 +76,8 @@
<item><seealso marker="crypto#crypto_one_time_aead/7">crypto_one_time_aead/7</seealso></item>
</list>
<p>In those functions the internal crypto state is first created and initialized
- with the cipher type, the key and possibly other data. Then the data is encrypted or decrypted,
+ with the cipher type, the key and possibly other data. Then the single binary is encrypted
+ or decrypted,
the crypto state is de-allocated and the result of the crypto operation is returned.
</p>
<p>The <c>crypto_one_time_aead</c> functions are for the ciphers of mode <c>ccm</c> or
@@ -94,7 +96,7 @@
<c>crypto_update</c> does the acual encryption or decryption. Note that AEAD ciphers
can't be handled this way due to their nature.
</p>
- <p>Finally, for repeated encryption or decryption of a text divided in parts where the
+ <p>For repeated encryption or decryption of a text divided in parts where the
same cipher and same key is used, but a new initialization vector (nounce) should be applied
for each part, the functions are:
</p>
@@ -103,32 +105,49 @@
<item><seealso marker="crypto#crypto_dyn_iv_update/3">crypto_dyn_iv_update/3</seealso></item>
</list>
<p>An example of where those functions are needed, is when handling the TLS protocol.</p>
+ <p>For information about available algorithms, use:
+ </p>
+ <list>
+ <item><seealso marker="crypto#supports-1">supports/1</seealso></item>
+ <item><seealso marker="crypto#hash_info-1">hash_info/1</seealso></item>
+ <item><seealso marker="crypto#cipher_info-1">cipher_info/1</seealso></item>
+ </list>
<section>
<title>Examples of crypto_init/4 and crypto_update/2</title>
- <p>Encrypting two blocks:</p>
+ <p>The functions <seealso marker="crypto#crypto_init/4">crypto_init/4</seealso>
+ and <seealso marker="crypto#crypto_update/2">crypto_update/2</seealso> are intended
+ to be used for encrypting or decrypting a sequence of blocks. First one call of
+ <c>crypto_init/4</c> initialises the crypto context. One or more calls <c>crypto_update/2</c>
+ does the actual encryption or decryption for each block.
+ </p>
+ <p>This example shows first the encryption of two blocks and then decryptions of the cipher
+ text, but divided into three blocks just to show that it is possible to divide the plain text and
+ cipher text differently for some ciphers:</p>
<code type="erl">
1> crypto:start().
ok
2> Key = &lt;&lt;1:128>>.
- 2> IV = &lt;&lt;0:128>>.
- 2> StateEnc = crypto:crypto_init(aes_128_ctr, Key, IV, true). % encrypt -> true
+ &lt;&lt;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
+ 3> IV = &lt;&lt;0:128>>.
+ &lt;&lt;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
+ 4> StateEnc = crypto:crypto_init(aes_128_ctr, Key, IV, true). % encrypt -> true
#Ref&lt;0.3768901617.1128660993.124047>
- 3> crypto:crypto_update(StateEnc, &lt;&lt;"First bytes">>).
+ 5> crypto:crypto_update(StateEnc, &lt;&lt;"First bytes">>).
&lt;&lt;67,44,216,166,25,130,203,5,66,6,162>>
- 4> crypto:crypto_update(StateEnc, &lt;&lt;"Second bytes">>).
+ 6> crypto:crypto_update(StateEnc, &lt;&lt;"Second bytes">>).
&lt;&lt;16,79,94,115,234,197,94,253,16,144,151,41>>
- 5>
- 5> StateDec = crypto:crypto_init(aes_128_ctr, Key, IV, false). % decrypt -> false
+ 7>
+ 7> StateDec = crypto:crypto_init(aes_128_ctr, Key, IV, false). % decrypt -> false
#Ref&lt;0.3768901617.1128660994.124255>
- 6> crypto:crypto_update(StateDec, &lt;&lt;67,44,216,166,25,130,203>>).
+ 8> crypto:crypto_update(StateDec, &lt;&lt;67,44,216,166,25,130,203>>).
&lt;&lt;"First b">>
- 7> crypto:crypto_update(StateDec, &lt;&lt;5,66,6,162,16,79,94,115,234,197,
- 94,253,16,144,151>>).
+ 9> crypto:crypto_update(StateDec, &lt;&lt;5,66,6,162,16,79,94,115,234,197,
+ 94,253,16,144,151>>).
&lt;&lt;"ytesSecond byte">>
- 8> crypto:crypto_update(StateDec, &lt;&lt;41>>).
+ 10> crypto:crypto_update(StateDec, &lt;&lt;41>>).
&lt;&lt;"s">>
- 9>
+ 11>
</code>
<p>Note that the internal data that the <c>StateEnc</c> and <c>StateDec</c> references are
destructivly updated by the calls to <seealso marker="crypto#crypto_update/2">crypto_update/2</seealso>.
@@ -155,21 +174,51 @@
<title>Example of crypto_one_time/5</title>
<p>The same example as in the
<seealso marker="#examples-of-crypto_init-4-and-crypto_update-2">previous section</seealso>,
- but now with one call to <c>crypto_one_time/5</c>:
+ but now with one call to <seealso marker="crypto#crypto_one_time/5">crypto_one_time/5</seealso>:
</p>
<code>
- 2> Key = &lt;&lt;1:128>>.
+ 1> Key = &lt;&lt;1:128>>.
+ &lt;&lt;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
2> IV = &lt;&lt;0:128>>.
- 2> Txt = [&lt;&lt;"First bytes">>,&lt;&lt;"Second bytes">>],
- 2> crypto:crypto_one_time(aes_128_ctr, Key, IV, Txt, true).
+ &lt;&lt;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
+ 3> Txt = [&lt;&lt;"First bytes">>,&lt;&lt;"Second bytes">>].
+ [&lt;&lt;"First bytes">>,&lt;&lt;"Second bytes">>]
+ 4> crypto:crypto_one_time(aes_128_ctr, Key, IV, Txt, true).
&lt;&lt;67,44,216,166,25,130,203,5,66,6,162,16,79,94,115,234,
197,94,253,16,144,151,41>>
- 3>
+ 5>
+ </code>
+ <p>The <c>[&lt;&lt;"First bytes">>,&lt;&lt;"Second bytes">>]</c> could of course have been one
+ single binary: <c>&lt;&lt;"First bytesSecond bytes">></c>.
+ </p>
+ </section>
+
+ <section>
+ <title>Example of crypto_one_time_aead/6</title>
+ <p>The same example as in the
+ <seealso marker="#example-of-crypto_one_time-5">previous section</seealso>,
+ but now with one call to <seealso marker="crypto#crypto_one_time_aead/6">crypto_one_time_aead/6</seealso>:
+ </p>
+ <code>
+ 1> Key = &lt;&lt;1:128>>.
+ &lt;&lt;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
+ 2> IV = &lt;&lt;0:128>>.
+ &lt;&lt;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
+ 3> Txt = [&lt;&lt;"First bytes">>,&lt;&lt;"Second bytes">>].
+ [&lt;&lt;"First bytes">>,&lt;&lt;"Second bytes">>]
+ 4> AAD = &lt;&lt;"Some bytes">>.
+ &lt;&lt;"Some bytes">>
+ 5> crypto:crypto_one_time_aead(aes_128_gcm, Key, IV, Txt, AAD, true).
+ {&lt;&lt;240,130,38,96,130,241,189,52,3,190,179,213,132,1,72,
+ 192,103,176,90,104,15,71,158>>,
+ &lt;&lt;131,47,45,91,142,85,9,244,21,141,214,71,31,135,2,155>>}
+ 9>
</code>
<p>The <c>[&lt;&lt;"First bytes">>,&lt;&lt;"Second bytes">>]</c> could of course have been one
single binary: <c>&lt;&lt;"First bytesSecond bytes">></c>.
</p>
</section>
+
</section>
<section>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 98378412d4..8ffdde2b90 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -509,6 +509,27 @@ supports() ->
{rsa_opts, rsa_opts_algorithms()}
].
+
+-spec supports(Type) -> Support
+ when Type :: hashs
+ | ciphers
+ | public_keys
+ | macs
+ | curves
+ | rsa_opts,
+ Support :: Hashs
+ | Ciphers
+ | PKs
+ | Macs
+ | Curves
+ | RSAopts,
+ Hashs :: [sha1() | sha2() | sha3() | blake2() | ripemd160 | compatibility_only_hash()],
+ Ciphers :: [cipher()],
+ PKs :: [rsa | dss | ecdsa | dh | ecdh | ec_gf2m],
+ Macs :: [hmac | cmac | poly1305],
+ Curves :: [ec_named_curve() | edwards_curve_dh() | edwards_curve_ed()],
+ RSAopts :: [rsa_sign_verify_opt() | rsa_opt()] .
+
supports(hashs) -> hash_algorithms();
supports(public_keys) -> pubkey_algorithms();
supports(ciphers) -> cipher_algorithms();
diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml
index 254ae27cc8..7808bfd94f 100644
--- a/lib/erl_interface/doc/src/ei.xml
+++ b/lib/erl_interface/doc/src/ei.xml
@@ -183,28 +183,36 @@ typedef enum {
</func>
<func>
- <name since="OTP @OTP-15712@"><ret>int</ret><nametext>ei_decode_bitstring(const char *buf, int *index, void *p, size_t plen, size_t *bitsp)</nametext></name>
+ <name since="OTP @OTP-15712@"><ret>int</ret><nametext>ei_decode_bitstring(const char *buf, int *index, const char **pp, unsigned int *bitoffsp, size_t *nbitsp)</nametext></name>
<fsummary>Decode a bitstring.</fsummary>
<desc>
- <p>Decodes a bitstring from the binary format.</p>
+ <p>Decodes a bit string from the binary format.</p>
<taglist>
- <tag><c>p</c></tag>
- <item><p>Either <c>NULL</c> or points to a buffer where the bytes of the
- bitstring will be written.</p>
+ <tag><c>pp</c></tag>
+ <item><p>Either <c>NULL</c> or <c>*pp</c> returns a pointer to
+ the first byte of the bit string. The returned bit string is
+ readable as long as the buffer pointed to by <c>buf</c> is
+ readable and not written to.</p>
</item>
- <tag><c>plen</c></tag>
- <item><p>The max size of the bitstring in <em>bytes</em>, that is the
- size of the buffer if <c>p != NULL</c>.</p>
+ <tag><c>bitoffsp</c></tag>
+ <item><p>Either <c>NULL</c> or <c>*bitoffsp</c> returns the
+ number of unused bits in the first byte pointed to by
+ <c>*pp</c>. The value of <c>*bitoffsp</c> is between 0 and 7.
+ Unused bits in the first byte are the most significant bits.</p>
</item>
- <tag><c>*bitsp</c></tag>
- <item><p>If <c>bitsp</c> is not <c>NULL</c>, set to the actual
- number of <em>bits</em> of the bitstring.</p>
+ <tag><c>nbitsp</c></tag>
+ <item><p>Either <c>NULL</c> or <c>*nbitsp</c> returns the length
+ of the bit string in <em>bits</em>.</p>
</item>
</taglist>
- <p>Returns <c>0</c> if it was a bitstring no longer than <c>plen</c>
- bytes. The actual length of the bitstring will be
- <c>(*bitsp+7)/8</c> bytes. If <c>(*bitsp % 8) > 0</c> only the high
- <c>(*bitsp % 8)</c> bits of the last byte are significant.</p>
+ <p>Returns <c>0</c> if it was a bit string term.</p>
+ <p>The number of <em>bytes</em> pointed to by <c>*pp</c>, which are
+ part of the bit string, is <c>(*bitoffsp + *nbitsp + 7)/8</c>. If
+ <c>(*bitoffsp + *bitsp)%8 > 0</c> then only <c>(*bitoffsp +
+ *bitsp)%8</c> bits of the last byte are used. Unused bits in
+ the last byte are the least significant bits.</p>
+ <p>The values of unused bits in the first and last byte are undefined
+ and cannot be relied on.</p>
<p>Number of bits may be divisible by 8, which means a binary
decodable by <c>ei_decode_binary</c> is also decodable by
<c>ei_decode_bitstring</c>.</p>
@@ -490,14 +498,24 @@ typedef enum {
</func>
<func>
- <name since="OTP @OTP-15712@"><ret>int</ret><nametext>ei_encode_bitstring(char *buf, int *index, const void *p, size_t bits)</nametext></name>
- <name since="OTP @OTP-15712@"><ret>int</ret><nametext>ei_x_encode_bitstring(ei_x_buff* x, const void *p, size_t bits)</nametext></name>
+ <name since="OTP @OTP-15712@"><ret>int</ret>
+ <nametext>ei_encode_bitstring(char *buf, int *index, const char *p, size_t bitoffs, size_t nbits)</nametext></name>
+ <name since="OTP @OTP-15712@"><ret>int</ret>
+ <nametext>ei_x_encode_bitstring(ei_x_buff* x, const char *p, size_t bitoffs, size_t nbits)</nametext></name>
<fsummary>Encode a bitstring.</fsummary>
<desc>
- <p>Encodes a bitstring in the binary format. The data is at
- <c>p</c>. The size of the data is <c>bits</c> bits or
- <c>(bits+7)/8</c> bytes. If <c>(bits%8) > 0</c> only the high
- <c>(bits%8)</c> bits of the last byte are significant.</p>
+ <p>Encodes a bit string in the binary format.</p>
+ <p>The data is at <c>p</c>. The length of the bit string is <c>nbits</c>
+ bits. The first <c>bitoffs</c> bits of the data at <c>p</c> are unused.
+ The first byte which is part of the bit string is
+ <c>p[bitoffs/8]</c>. The <c>bitoffs%8</c> most significant bits of
+ the first byte <c>p[bitoffs/8]</c> are unused.</p>
+ <p>The number of bytes which is part of the bit string is <c>(bitoffs +
+ nbits + 7)/8</c>. If <c>(bitoffs + nbits)%8 > 0</c> then only <c>(bitoffs +
+ nbits)%8</c> bits of the last byte are used. Unused bits in
+ the last byte are the least significant bits.</p>
+ <p>The values of unused bits are disregarded and does not need to be
+ cleared.</p>
</desc>
</func>
diff --git a/lib/erl_interface/include/ei.h b/lib/erl_interface/include/ei.h
index a860df3f77..ed0420300d 100644
--- a/lib/erl_interface/include/ei.h
+++ b/lib/erl_interface/include/ei.h
@@ -526,9 +526,9 @@ int ei_x_encode_atom_len(ei_x_buff* x, const char* s, int len);
int ei_x_encode_atom_len_as(ei_x_buff* x, const char* s, int len,
erlang_char_encoding from, erlang_char_encoding to);
int ei_encode_binary(char *buf, int *index, const void *p, long len);
-int ei_encode_bitstring(char *buf, int *index, const void *p, size_t bits);
+int ei_encode_bitstring(char *buf, int *index, const char *p, size_t bitoffs, size_t bits);
int ei_x_encode_binary(ei_x_buff* x, const void* s, int len);
-int ei_x_encode_bitstring(ei_x_buff* x, const void* p, size_t bits);
+int ei_x_encode_bitstring(ei_x_buff* x, const char* p, size_t bitoffs, size_t bits);
int ei_encode_pid(char *buf, int *index, const erlang_pid *p);
int ei_x_encode_pid(ei_x_buff* x, const erlang_pid* pid);
int ei_encode_fun(char* buf, int* index, const erlang_fun* p);
@@ -578,7 +578,9 @@ int ei_decode_string(const char *buf, int *index, char *p);
int ei_decode_atom(const char *buf, int *index, char *p);
int ei_decode_atom_as(const char *buf, int *index, char *p, int destlen, erlang_char_encoding want, erlang_char_encoding* was, erlang_char_encoding* result);
int ei_decode_binary(const char *buf, int *index, void *p, long *len);
-int ei_decode_bitstring(const char *buf, int *index, void *p, size_t plen, size_t *bitsp);
+int ei_decode_bitstring(const char *buf, int *index, const char** pp,
+ unsigned int* bitoffsp, size_t *nbitsp);
+
int ei_decode_fun(const char* buf, int* index, erlang_fun* p);
void free_fun(erlang_fun* f);
int ei_decode_pid(const char *buf, int *index, erlang_pid *p);
diff --git a/lib/erl_interface/src/decode/decode_binary.c b/lib/erl_interface/src/decode/decode_binary.c
index 2799438bef..0d28c67230 100644
--- a/lib/erl_interface/src/decode/decode_binary.c
+++ b/lib/erl_interface/src/decode/decode_binary.c
@@ -40,40 +40,41 @@ int ei_decode_binary(const char *buf, int *index, void *p, long *lenp)
return 0;
}
-int ei_decode_bitstring(const char *buf, int *index, void *p, size_t plen,
- size_t *bitsp)
+int ei_decode_bitstring(const char *buf, int *index,
+ const char** pp,
+ unsigned int* bitoffsp,
+ size_t *nbitsp)
{
- const char *s = buf + *index;
- const char *s0 = s;
- unsigned long len;
- unsigned char last_bits;
- const unsigned char tag = get8(s);
+ const char *s = buf + *index;
+ const char *s0 = s;
+ unsigned char last_bits;
+ const unsigned char tag = get8(s);
+ size_t len = get32be(s);
- if (tag == ERL_BINARY_EXT) {
- long bytes;
- int ret = ei_decode_binary(buf, index, p, &bytes);
- if (bitsp)
- *bitsp = (size_t)bytes * 8;
- return ret;
- }
+ switch(tag) {
+ case ERL_BINARY_EXT:
+ if (nbitsp)
+ *nbitsp = len * 8;
+ break;
+ case ERL_BIT_BINARY_EXT:
+ last_bits = get8(s);
+ if (((last_bits==0) != (len==0)) || last_bits > 8)
+ return -1;
- if (tag != ERL_BIT_BINARY_EXT)
- return -1;
-
- len = get32be(s);
- last_bits = get8(s);
-
- if (len > plen || ((last_bits==0) != (len==0)) || last_bits > 8)
- return -1;
-
- if (p)
- memcpy(p, s, len);
- s += len;
+ if (nbitsp)
+ *nbitsp = (len == 0) ? 0 : ((len-1) * 8) + last_bits;
+ break;
+ default:
+ return -1;
+ }
- if (bitsp)
- *bitsp = (len == 0) ? 0 : ((len-1) * 8) + last_bits;
+ if (pp)
+ *pp = s;
+ if (bitoffsp)
+ *bitoffsp = 0;
- *index += s-s0;
- return 0;
+ s += len;
+ *index += s-s0;
+ return 0;
}
diff --git a/lib/erl_interface/src/decode/decode_skip.c b/lib/erl_interface/src/decode/decode_skip.c
index 11d3bc1786..736c00e074 100644
--- a/lib/erl_interface/src/decode/decode_skip.c
+++ b/lib/erl_interface/src/decode/decode_skip.c
@@ -21,14 +21,6 @@
#include "eiext.h"
#include "decode_skip.h"
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-
-#ifndef SIZE_MAX
-# define SIZE_MAX (~((size_t)0))
-#endif
-
int ei_skip_term(const char* buf, int* index)
{
int i, n, ty;
@@ -88,7 +80,7 @@ int ei_skip_term(const char* buf, int* index)
return -1;
break;
case ERL_BIT_BINARY_EXT:
- if (ei_decode_bitstring(buf, index, NULL, SIZE_MAX, NULL) < 0)
+ if (ei_decode_bitstring(buf, index, NULL, NULL, NULL) < 0)
return -1;
break;
case ERL_SMALL_INTEGER_EXT:
diff --git a/lib/erl_interface/src/encode/encode_binary.c b/lib/erl_interface/src/encode/encode_binary.c
index 4aa9f6bc16..0562979417 100644
--- a/lib/erl_interface/src/encode/encode_binary.c
+++ b/lib/erl_interface/src/encode/encode_binary.c
@@ -22,6 +22,10 @@
#include "eiext.h"
#include "putget.h"
+static void copy_bits(const unsigned char* src, size_t soffs,
+ unsigned char* dst, size_t n);
+
+
int ei_encode_binary(char *buf, int *index, const void *p, long len)
{
char *s = buf + *index;
@@ -40,23 +44,28 @@ int ei_encode_binary(char *buf, int *index, const void *p, long len)
return 0;
}
-int ei_encode_bitstring(char *buf, int *index, const void *p, size_t bits)
+int ei_encode_bitstring(char *buf, int *index,
+ const char *p,
+ size_t bitoffs,
+ size_t bits)
{
char *s = buf + *index;
char *s0 = s;
size_t bytes = (bits + 7) / 8;
char last_bits = bits % 8;
- if (bytes == 0 || last_bits == 0)
- return ei_encode_binary(buf, index, p, bytes);
-
- if (!buf) s += 6;
+ if (!buf) s += last_bits ? 6 : 5;
else {
- put8(s, ERL_BIT_BINARY_EXT);
+ char* tagp = s++;
put32be(s, bytes);
- put8(s, last_bits);
- memcpy(s, p, bytes);
- s[bytes-1] &= (0xff << (8-last_bits));
+ if (last_bits) {
+ *tagp = ERL_BIT_BINARY_EXT;
+ put8(s, last_bits);
+ }
+ else
+ *tagp = ERL_BINARY_EXT;
+
+ copy_bits((const unsigned char*)p, bitoffs, (unsigned char*)s, bits);
}
s += bytes;
@@ -64,3 +73,77 @@ int ei_encode_bitstring(char *buf, int *index, const void *p, size_t bits)
return 0;
}
+
+
+/*
+ * MAKE_MASK(n) constructs a mask with n bits.
+ * Example: MAKE_MASK(3) returns the binary number 00000111.
+ */
+#define MAKE_MASK(n) ((((unsigned) 1) << (n))-1)
+
+
+static
+void copy_bits(const unsigned char* src, /* Base pointer to source. */
+ size_t soffs, /* Bit offset for source relative to src. */
+ unsigned char* dst, /* Destination. */
+ size_t n) /* Number of bits to copy. */
+{
+ unsigned rmask;
+ unsigned count;
+ unsigned deoffs;
+ unsigned bits;
+ unsigned bits1;
+ unsigned rshift;
+
+ if (n == 0)
+ return;
+
+ deoffs = n & 7;
+ rmask = deoffs ? (MAKE_MASK(deoffs) << (8-deoffs)) : 0;
+
+ if (soffs == 0) {
+ unsigned nbytes = (n + 7) / 8;
+ memcpy(dst, src, nbytes);
+ if (rmask)
+ dst[nbytes-1] &= rmask;
+ return;
+ }
+
+ src += soffs / 8;
+ soffs &= 7;
+
+ if (n < 8) { /* Less than one byte */
+ bits = (*src << soffs);
+ if (soffs+n > 8) {
+ src++;
+ bits |= (*src >> (8 - soffs));
+ }
+ *dst = bits & rmask;
+ return;
+ }
+
+ count = n >> 3;
+
+ rshift = 8 - soffs;
+ bits = *src;
+ if (soffs + n > 8) {
+ src++;
+ }
+
+ while (count--) {
+ bits1 = bits << soffs;
+ bits = *src;
+ src++;
+ *dst = bits1 | (bits >> rshift);
+ dst++;
+ }
+
+ if (rmask) {
+ bits1 = bits << soffs;
+ if ((rmask << rshift) & 0xff) {
+ bits = *src;
+ bits1 |= (bits >> rshift);
+ }
+ *dst = bits1 & rmask;
+ }
+}
diff --git a/lib/erl_interface/src/misc/ei_printterm.c b/lib/erl_interface/src/misc/ei_printterm.c
index a89b990ac1..5c40fb7747 100644
--- a/lib/erl_interface/src/misc/ei_printterm.c
+++ b/lib/erl_interface/src/misc/ei_printterm.c
@@ -250,12 +250,13 @@ static int print_term(FILE* fp, ei_x_buff* x,
ei_free(p);
break;
case ERL_BIT_BINARY_EXT: {
+ const char* cp;
size_t bits;
+ unsigned int bitoffs;
int trunc = 0;
- p = ei_malloc(n);
- if (p == NULL) goto err;
- if (ei_decode_bitstring(buf, index, p, n, &bits) < 0) {
- ei_free(p);
+
+ if (ei_decode_bitstring(buf, index, &cp, &bitoffs, &bits) < 0
+ || bitoffs != 0) {
goto err;
}
ch_written += xprintf(fp, x, "#Bits<");
@@ -266,15 +267,14 @@ static int print_term(FILE* fp, ei_x_buff* x,
}
--m;
for (i = 0; i < m; ++i) {
- ch_written += xprintf(fp, x, "%d,", p[i]);
+ ch_written += xprintf(fp, x, "%d,", cp[i]);
}
- ch_written += xprintf(fp, x, "%d", p[i]);
+ ch_written += xprintf(fp, x, "%d", cp[i]);
if (trunc)
ch_written += xprintf(fp, x, ",...");
else if (bits % 8 != 0)
ch_written += xprintf(fp, x, ":%u", (unsigned)(bits % 8));
xputc('>', fp, x); ++ch_written;
- ei_free(p);
break;
}
case ERL_SMALL_INTEGER_EXT:
diff --git a/lib/erl_interface/src/misc/ei_x_encode.c b/lib/erl_interface/src/misc/ei_x_encode.c
index 2da271795f..8e77679d2a 100644
--- a/lib/erl_interface/src/misc/ei_x_encode.c
+++ b/lib/erl_interface/src/misc/ei_x_encode.c
@@ -117,14 +117,14 @@ int ei_x_encode_binary(ei_x_buff* x, const void* p, int len)
return ei_encode_binary(x->buff, &x->index, p, len);
}
-int ei_x_encode_bitstring(ei_x_buff* x, const void* p, size_t bits)
+int ei_x_encode_bitstring(ei_x_buff* x, const char* p, size_t bitoffs, size_t bits)
{
int i = x->index;
- if (ei_encode_bitstring(NULL, &i, p, bits) == -1)
+ if (ei_encode_bitstring(NULL, &i, p, bitoffs, bits) == -1)
return -1;
if (!x_fix_buff(x, i))
return -1;
- return ei_encode_bitstring(x->buff, &x->index, p, bits);
+ return ei_encode_bitstring(x->buff, &x->index, p, bitoffs, bits);
}
int ei_x_encode_long(ei_x_buff* x, long n)
diff --git a/lib/erl_interface/src/misc/show_msg.c b/lib/erl_interface/src/misc/show_msg.c
index 2d49eb6449..805d69e9b3 100644
--- a/lib/erl_interface/src/misc/show_msg.c
+++ b/lib/erl_interface/src/misc/show_msg.c
@@ -24,13 +24,6 @@
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-
-#ifndef SIZE_MAX
-# define SIZE_MAX (~((size_t)0))
-#endif
#include <sys/types.h>
@@ -464,7 +457,7 @@ static void show_term(const char *termbuf, int *index, FILE *stream)
case ERL_BIT_BINARY_EXT: {
size_t bits;
- ei_decode_bitstring(termbuf, index, NULL, SIZE_MAX, &bits);
+ ei_decode_bitstring(termbuf, index, NULL, NULL, &bits);
fprintf(stream, "#Bits<%lu>", (unsigned long)bits);
break;
}
diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
index 7c9e79f837..385bcdd422 100644
--- a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
+++ b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
@@ -209,8 +209,9 @@ static void cmd_ei_send_funs(char* buf, int len)
erlang_pid pid;
ei_x_buff x;
erlang_fun fun1, fun2;
- unsigned char bitstring[10];
+ char* bitstring;
size_t bits;
+ int bitoffs;
if (ei_decode_long(buf, &index, &fd) < 0)
fail("expected long");
@@ -224,7 +225,7 @@ static void cmd_ei_send_funs(char* buf, int len)
fail("expected Fun1");
if (ei_decode_fun(buf, &index, &fun2) < 0)
fail("expected Fun2");
- if (ei_decode_bitstring(buf, &index, bitstring, sizeof(bitstring), &bits) < 0)
+ if (ei_decode_bitstring(buf, &index, &bitstring, &bitoffs, &bits) < 0)
fail("expected bitstring");
if (ei_x_new_with_version(&x) < 0)
fail("ei_x_new_with_version");
@@ -234,7 +235,7 @@ static void cmd_ei_send_funs(char* buf, int len)
fail("encode fun1");
if (ei_x_encode_fun(&x, &fun2) < 0)
fail("encode fun2");
- if (ei_x_encode_bitstring(&x, bitstring, bits) < 0)
+ if (ei_x_encode_bitstring(&x, bitstring, bitoffs, bits) < 0)
fail("encode bitstring");
free_fun(&fun1);
free_fun(&fun2);
diff --git a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
index d39970a857..46d6b8f2af 100644
--- a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
+++ b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
@@ -319,17 +319,18 @@ static void decode_bin(int exp_size, const char* val, int exp_len)
static void decode_bits(int exp_size, const char* val, size_t exp_bits)
{
- char p[1024];
+ const char* p;
char *buf;
size_t bits;
+ int bitoffs;
int size1 = 0;
int size2 = 0;
int err;
message("ei_decode_bitstring should be %d bits", (int)exp_bits);
buf = read_packet(NULL);
- err = ei_decode_bitstring(buf+1, &size1, NULL, sizeof(p), &bits);
- message("err = %d, size = %d, len = %d, expected size = %d, expected bits = %d\n",\
- err,size1, (int)bits, exp_size, (int)exp_bits);
+ err = ei_decode_bitstring(buf+1, &size1, NULL, &bitoffs, &bits);
+ message("err = %d, size = %d, bitoffs = %d, bits = %d, expected size = %d, expected bits = %d\n",\
+ err,size1, bitoffs, (int)bits, exp_size, (int)exp_bits);
if (err != 0) {
if (err != -1) {
@@ -344,8 +345,12 @@ static void decode_bits(int exp_size, const char* val, size_t exp_bits)
fail("number of bits is not correct");
return;
}
+ if (bitoffs != 0) {
+ fail("non zero bit offset");
+ return;
+ }
- err = ei_decode_bitstring(buf+1, &size2, p, sizeof(p), &bits);
+ err = ei_decode_bitstring(buf+1, &size2, &p, NULL, &bits);
message("err = %d, size = %d, len = %d, expected size = %d, expected len = %d\n",\
err,size2, (int)bits, exp_size, (int)exp_bits);
if (err != 0) {
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
index d8b0bce3ae..3451d9f503 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
@@ -122,9 +122,29 @@ test_ei_decode_encode(Config) when is_list(Config) ->
[send_rec(P, <<16#dec0deb175:B/little>>) || B <- lists:seq(0,48)],
+ % And last an ugly duckling to test ei_encode_bitstring with bitoffs != 0
+ encode_bitstring(P),
+
runner:recv_eot(P),
ok.
+encode_bitstring(P) ->
+ %% Send one bitstring to c-node
+ Bits = <<16#18f6d4b2907e5c3a1:66>>,
+ P ! {self(), {command, term_to_binary(Bits, [{minor_version, 2}])}},
+
+ %% and then receive and verify a number of different sub-bitstrings
+ receive_sub_bitstring(P, Bits, 0, bit_size(Bits)).
+
+receive_sub_bitstring(_, _, _, NBits) when NBits < 0 ->
+ ok;
+receive_sub_bitstring(P, Bits, BitOffs, NBits) ->
+ <<_:BitOffs, Sub:NBits/bits, _/bits>> = Bits,
+ %%io:format("expecting term_to_binary(~p) = ~p\n", [Sub, term_to_binary(Sub)]),
+ {_B,Sub} = get_buf_and_term(P),
+ receive_sub_bitstring(P, Bits, BitOffs+1, NBits - ((NBits div 20)+1)).
+
+
%% ######################################################################## %%
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
index f9c05b2739..85ca6c56e9 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
@@ -42,7 +42,8 @@ typedef struct
typedef struct
{
- char bytes[MAXATOMLEN_UTF8];
+ const char* bytes;
+ unsigned int bitoffs;
size_t nbits;
}my_bitstring;
@@ -128,17 +129,17 @@ struct Type my_atom_type = {
int ei_decode_my_bits(const char *buf, int *index, my_bitstring* a)
{
- return ei_decode_bitstring(buf, index, (a ? a->bytes : NULL),
- sizeof(a->bytes),
+ return ei_decode_bitstring(buf, index, (a ? &a->bytes : NULL),
+ (a ? &a->bitoffs : NULL),
(a ? &a->nbits : NULL));
}
int ei_encode_my_bits(char *buf, int *index, my_bitstring* a)
{
- return ei_encode_bitstring(buf, index, a->bytes, a->nbits);
+ return ei_encode_bitstring(buf, index, a->bytes, a->bitoffs, a->nbits);
}
int ei_x_encode_my_bits(ei_x_buff* x, my_bitstring* a)
{
- return ei_x_encode_bitstring(x, a->bytes, a->nbits);
+ return ei_x_encode_bitstring(x, a->bytes, a->bitoffs, a->nbits);
}
struct Type my_bitstring_type = {
@@ -264,11 +265,7 @@ void decode_encode(struct Type** tv, int nobj)
size1 = 0;
err = t->ei_decode_fp(inp, &size1, NULL);
if (err != 0) {
- if (err != -1) {
- fail("decode returned non zero but not -1");
- } else {
- fail1("decode '%s' returned non zero", t->name);
- }
+ fail2("decode '%s' returned non zero %d", t->name, err);
return;
}
if (size1 < 1) {
@@ -497,6 +494,66 @@ void decode_encode_big(struct Type* t)
}
+void encode_bitstring(void)
+{
+ char* packet;
+ char* inp;
+ char out_buf[BUFSZ];
+ int size;
+ int err, i;
+ ei_x_buff arg;
+ const char* p;
+ unsigned int bitoffs;
+ size_t nbits, org_nbits;
+
+ packet = read_packet(NULL);
+ inp = packet+1;
+
+ size = 0;
+ err = ei_decode_bitstring(inp, &size, &p, &bitoffs, &nbits);
+ if (err != 0) {
+ fail1("ei_decode_bitstring returned non zero %d", err);
+ return;
+ }
+
+ /*
+ * Now send a bunch of different sub-bitstrings back
+ * encoded both with ei_encode_ and ei_x_encode_.
+ */
+ org_nbits = nbits;
+ do {
+ size = 0;
+ err = ei_encode_bitstring(out_buf, &size, p, bitoffs, nbits);
+ if (err != 0) {
+ fail1("ei_encode_bitstring returned non zero %d", err);
+ return;
+ }
+
+ ei_x_new(&arg);
+ err = ei_x_encode_bitstring(&arg, p, bitoffs, nbits);
+ if (err != 0) {
+ fail1("ei_x_encode_bitstring returned non zero %d", err);
+ ei_x_free(&arg);
+ return;
+ }
+
+ if (arg.index < 1) {
+ fail("size is < 1");
+ ei_x_free(&arg);
+ return;
+ }
+
+ send_buffer(out_buf, size);
+ send_buffer(arg.buff, arg.index);
+ ei_x_free(&arg);
+
+ bitoffs++;
+ nbits -= (nbits / 20) + 1;
+ } while (nbits < org_nbits);
+
+ free_packet(packet);
+}
+
/* ******************************************************************** */
@@ -568,6 +625,8 @@ TESTCASE(test_ei_decode_encode)
decode_encode_one(&my_bitstring_type);
}
+ encode_bitstring();
+
report(1);
}
diff --git a/lib/kernel/src/erl_distribution.erl b/lib/kernel/src/erl_distribution.erl
index 0bec78e938..cdb2d2f1f6 100644
--- a/lib/kernel/src/erl_distribution.erl
+++ b/lib/kernel/src/erl_distribution.erl
@@ -21,6 +21,8 @@
-behaviour(supervisor).
+-include_lib("kernel/include/logger.hrl").
+
-export([start_link/0,start_link/2,init/1,start/1,stop/0]).
-define(DBG,erlang:display([?MODULE,?LINE])).
@@ -83,6 +85,10 @@ do_start_link([{Arg,Flag}|T]) ->
case init:get_argument(Arg) of
{ok,[[Name]]} ->
start_link([list_to_atom(Name),Flag|ticktime()], true);
+ {ok,[[Name]|_Rest]} ->
+ ?LOG_WARNING("Multiple -~p given to erl, using the first, ~p",
+ [Arg, Name]),
+ start_link([list_to_atom(Name),Flag|ticktime()], true);
_ ->
do_start_link(T)
end;
diff --git a/lib/kernel/src/user_drv.erl b/lib/kernel/src/user_drv.erl
index 08286dd476..69ff8e7971 100644
--- a/lib/kernel/src/user_drv.erl
+++ b/lib/kernel/src/user_drv.erl
@@ -120,7 +120,7 @@ server1(Iport, Oport, Shell) ->
{Curr,Shell1} =
case init:get_argument(remsh) of
{ok,[[Node]]} ->
- ANode = list_to_atom(Node),
+ ANode = list_to_atom(append_hostname(Node)),
RShell = {ANode,shell,start,[]},
RGr = group:start(self(), RShell, rem_sh_opts(ANode)),
{RGr,RShell};
@@ -139,6 +139,12 @@ server1(Iport, Oport, Shell) ->
%% Enter the server loop.
server_loop(Iport, Oport, Curr, User, Gr, {false, queue:new()}).
+append_hostname(Node) ->
+ case string:find(Node, "@") of
+ nomatch -> Node ++ string:find(atom_to_list(node()), "@");
+ _ -> Node
+ end.
+
rem_sh_opts(Node) ->
[{expand_fun,fun(B)-> rpc:call(Node,edlin_expand,expand,[B]) end}].
diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl
index 8dd4ef1987..c3a022df0a 100644
--- a/lib/kernel/test/erl_distribution_SUITE.erl
+++ b/lib/kernel/test/erl_distribution_SUITE.erl
@@ -205,6 +205,9 @@ nodenames(Config) when is_list(Config) ->
legal("a-1@b"),
legal("a_1@b"),
+ %% Test that giving two -sname works as it should
+ test_node("a_1@b", false, long_or_short() ++ "a_0@b"),
+
illegal("cdé@a"),
illegal("te欢st@a").
@@ -258,8 +261,11 @@ illegal(Name) ->
test_node(Name) ->
test_node(Name, false).
test_node(Name, Illigal) ->
+ test_node(Name, Illigal, "").
+test_node(Name, Illigal, ExtraArgs) ->
ProgName = ct:get_progname(),
- Command = ProgName ++ " -noinput " ++ long_or_short() ++ Name ++
+ Command = ProgName ++ " -noinput " ++ ExtraArgs ++
+ long_or_short() ++ Name ++
" -eval \"net_adm:ping('" ++ atom_to_list(node()) ++ "')\"" ++
case Illigal of
true ->
diff --git a/lib/sasl/src/Makefile b/lib/sasl/src/Makefile
index 7338bdf016..fd62588f5c 100644
--- a/lib/sasl/src/Makefile
+++ b/lib/sasl/src/Makefile
@@ -61,7 +61,11 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
+
ERL_COMPILE_FLAGS += -I../../stdlib/include -Werror
+ifeq ($(USE_ESOCK), yes)
+ERL_COMPILE_FLAGS += -DUSE_ESOCK=true
+endif
# ----------------------------------------------------
diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index c2c91fd667..b5a6b44f93 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -33,6 +33,7 @@
-export([read_application/4]).
-export([make_hybrid_boot/4]).
+-export([preloaded/0]). % Exported just for testing
-import(lists, [filter/2, keysort/2, keysearch/3, map/2, reverse/1,
append/1, foldl/3, member/2, foreach/2]).
@@ -45,6 +46,13 @@
-compile({inline,[{badarg,2}]}).
+-ifdef(USE_ESOCK).
+-define(ESOCK_MODS, [socket]).
+-else.
+-define(ESOCK_MODS, []).
+-endif.
+
+
%%-----------------------------------------------------------------
%% Create a boot script from a release file.
%% Options is a list of {path, Path} | silent | local
@@ -1566,7 +1574,7 @@ preloaded() ->
erts_code_purger,erts_dirty_process_signal_handler,
erts_internal,erts_literal_area_collector,
init,net,persistent_term,prim_buffer,prim_eval,prim_file,
- prim_inet,prim_zip,socket,zlib].
+ prim_inet,prim_zip] ++ ?ESOCK_MODS ++ [zlib].
%%______________________________________________________________________
%% Kernel processes; processes that are specially treated by the init
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src
index 410061cded..7449405d20 100644
--- a/lib/ssh/src/ssh.app.src
+++ b/lib/ssh/src/ssh.app.src
@@ -44,10 +44,10 @@
{env, []},
{mod, {ssh_app, []}},
{runtime_dependencies, [
- "crypto-4.2",
- "erts-6.0",
- "kernel-3.0",
- "public_key-1.5.2",
- "stdlib-3.3"
+ "crypto-@OTP-15644@",
+ "erts-9.0",
+ "kernel-5.3",
+ "public_key-1.6.1",
+ "stdlib-3.4.1"
]}]}.
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index f7fae16088..dba90aaff0 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -44,6 +44,7 @@ MODULES = \
ssl_bench_SUITE \
ssl_cipher_SUITE \
ssl_cipher_suite_SUITE \
+ openssl_server_cipher_suite_SUITE\
ssl_certificate_verify_SUITE\
ssl_crl_SUITE\
ssl_dist_SUITE \
diff --git a/lib/ssl/test/openssl_server_cipher_suite_SUITE.erl b/lib/ssl/test/openssl_server_cipher_suite_SUITE.erl
new file mode 100644
index 0000000000..907de1abe2
--- /dev/null
+++ b/lib/ssl/test/openssl_server_cipher_suite_SUITE.erl
@@ -0,0 +1,768 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(openssl_server_cipher_suite_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+all() ->
+ [
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
+ ].
+
+groups() ->
+ %% TODO: Enable SRP, PSK suites (needs OpenSSL s_server conf)
+ %% TODO: Enable all "kex" on DTLS
+ [
+ {'tlsv1.2', [], kex()},
+ {'tlsv1.1', [], kex()},
+ {'tlsv1', [], kex()},
+ {'sslv3', [], kex()},
+ {'dtlsv1.2', [], dtls_kex()},
+ {'dtlsv1', [], dtls_kex()},
+ {dhe_rsa, [],[dhe_rsa_3des_ede_cbc,
+ dhe_rsa_aes_128_cbc,
+ dhe_rsa_aes_256_cbc,
+ dhe_rsa_chacha20_poly1305
+ ]},
+ {ecdhe_rsa, [], [ecdhe_rsa_3des_ede_cbc,
+ ecdhe_rsa_aes_128_cbc,
+ ecdhe_rsa_aes_128_gcm,
+ ecdhe_rsa_aes_256_cbc,
+ ecdhe_rsa_aes_256_gcm,
+ ecdhe_rsa_chacha20_poly1305
+ ]},
+ {ecdhe_ecdsa, [],[ecdhe_ecdsa_rc4_128,
+ ecdhe_ecdsa_3des_ede_cbc,
+ ecdhe_ecdsa_aes_128_cbc,
+ ecdhe_ecdsa_aes_128_gcm,
+ ecdhe_ecdsa_aes_256_cbc,
+ ecdhe_ecdsa_aes_256_gcm,
+ ecdhe_ecdsa_chacha20_poly1305
+ ]},
+ {rsa, [], [rsa_3des_ede_cbc,
+ rsa_aes_128_cbc,
+ rsa_aes_256_cbc,
+ rsa_rc4_128
+ ]},
+ {dhe_dss, [], [dhe_dss_3des_ede_cbc,
+ dhe_dss_aes_128_cbc,
+ dhe_dss_aes_256_cbc]},
+ %% {srp_rsa, [], [srp_rsa_3des_ede_cbc,
+ %% srp_rsa_aes_128_cbc,
+ %% srp_rsa_aes_256_cbc]},
+ %% {srp_dss, [], [srp_dss_3des_ede_cbc,
+ %% srp_dss_aes_128_cbc,
+ %% srp_dss_aes_256_cbc]},
+ %% {rsa_psk, [], [rsa_psk_3des_ede_cbc,
+ %% rsa_psk_rc4_128,
+ %% rsa_psk_aes_128_cbc,
+ %% rsa_psk_aes_256_cbc
+ %% ]},
+ {dh_anon, [], [dh_anon_rc4_128,
+ dh_anon_3des_ede_cbc,
+ dh_anon_aes_128_cbc,
+ dh_anon_aes_128_gcm,
+ dh_anon_aes_256_cbc,
+ dh_anon_aes_256_gcm]},
+ {ecdh_anon, [], [ecdh_anon_3des_ede_cbc,
+ ecdh_anon_aes_128_cbc,
+ ecdh_anon_aes_256_cbc
+ ]}
+ %% {srp_anon, [], [srp_anon_3des_ede_cbc,
+ %% srp_anon_aes_128_cbc,
+ %% srp_anon_aes_256_cbc]},
+ %% {psk, [], [psk_3des_ede_cbc,
+ %% psk_rc4_128,
+ %% psk_aes_128_cbc,
+ %% psk_aes_128_ccm,
+ %% psk_aes_128_ccm_8,
+ %% psk_aes_256_cbc,
+ %% psk_aes_256_ccm,
+ %% psk_aes_256_ccm_8
+ %% ]},
+ %% {dhe_psk, [], [dhe_psk_3des_ede_cbc,
+ %% dhe_psk_rc4_128,
+ %% dhe_psk_aes_128_cbc,
+ %% dhe_psk_aes_128_ccm,
+ %% dhe_psk_aes_128_ccm_8,
+ %% dhe_psk_aes_256_cbc,
+ %% dhe_psk_aes_256_ccm,
+ %% dhe_psk_aes_256_ccm_8
+ %% ]},
+ %% {ecdhe_psk, [], [ecdhe_psk_3des_ede_cbc,
+ %% ecdhe_psk_rc4_128,
+ %% ecdhe_psk_aes_128_cbc,
+ %% ecdhe_psk_aes_128_ccm,
+ %% ecdhe_psk_aes_128_ccm_8,
+ %% ecdhe_psk_aes_256_cbc
+ %% ]}
+ ].
+
+kex() ->
+ rsa() ++ ecdsa() ++ dss() ++ anonymous().
+
+dtls_kex() -> %% Should be all kex in the future
+ dtls_rsa() ++ dss() ++ anonymous().
+
+rsa() ->
+ [{group, dhe_rsa},
+ {group, ecdhe_rsa},
+ {group, rsa} %%, {group, srp_rsa},
+ %%{group, rsa_psk}
+ ].
+
+dtls_rsa() ->
+ [
+ {group, rsa}
+ %%,{group, rsa_psk}
+ ].
+
+ecdsa() ->
+ [{group, ecdhe_ecdsa}].
+
+dss() ->
+ [{group, dhe_dss}
+ %%{group, srp_dss}
+ ].
+
+anonymous() ->
+ [{group, dh_anon},
+ {group, ecdh_anon}
+ %% {group, psk},
+ %%{group, dhe_psk},
+ %%{group, ecdhe_psk}
+ %%{group, srp_anon}
+ ].
+
+init_per_suite(Config) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto).
+
+%%--------------------------------------------------------------------
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:supports_ssl_tls_version(GroupName) of
+ true ->
+ do_init_per_group(GroupName, Config);
+ false ->
+ {skip, {openssl_does_not_support, GroupName}}
+ end;
+ false ->
+ do_init_per_group(GroupName, Config)
+ end.
+
+do_init_per_group(GroupName, Config) when GroupName == ecdh_anon;
+ GroupName == ecdhe_rsa;
+ GroupName == ecdhe_psk ->
+ case proplists:get_bool(ecdh, proplists:get_value(public_keys, crypto:supports())) of
+ true ->
+ init_certs(GroupName, Config);
+ false ->
+ {skip, "Missing EC crypto support"}
+ end;
+do_init_per_group(ecdhe_ecdsa = GroupName, Config) ->
+ PKAlg = proplists:get_value(public_keys, crypto:supports()),
+ case lists:member(ecdh, PKAlg) andalso lists:member(ecdsa, PKAlg) of
+ true ->
+ init_certs(GroupName, Config);
+ false ->
+ {skip, "Missing EC crypto support"}
+ end;
+do_init_per_group(dhe_dss = GroupName, Config) ->
+ PKAlg = proplists:get_value(public_keys, crypto:supports()),
+ case lists:member(dss, PKAlg) andalso lists:member(dh, PKAlg) of
+ true ->
+ init_certs(GroupName, Config);
+ false ->
+ {skip, "Missing DSS crypto support"}
+ end;
+do_init_per_group(srp_dss = GroupName, Config) ->
+ PKAlg = proplists:get_value(public_keys, crypto:supports()),
+ case lists:member(dss, PKAlg) andalso lists:member(srp, PKAlg) of
+ true ->
+ init_certs(GroupName, Config);
+ false ->
+ {skip, "Missing DSS_SRP crypto support"}
+ end;
+do_init_per_group(GroupName, Config) when GroupName == srp_anon;
+ GroupName == srp_rsa ->
+ PKAlg = proplists:get_value(public_keys, crypto:supports()),
+ case lists:member(srp, PKAlg) of
+ true ->
+ init_certs(GroupName, Config);
+ false ->
+ {skip, "Missing SRP crypto support"}
+ end;
+do_init_per_group(dhe_psk = GroupName, Config) ->
+ PKAlg = proplists:get_value(public_keys, crypto:supports()),
+ case lists:member(dh, PKAlg) of
+ true ->
+ init_certs(GroupName, Config);
+ false ->
+ {skip, "Missing SRP crypto support"}
+ end;
+do_init_per_group(GroupName, Config0) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName, end_per_group(GroupName, Config0));
+ false ->
+ init_certs(GroupName, Config0)
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+init_per_testcase(TestCase, Config) when TestCase == psk_3des_ede_cbc;
+ TestCase == srp_anon_3des_ede_cbc;
+ TestCase == dhe_psk_3des_ede_cbc;
+ TestCase == ecdhe_psk_3des_ede_cbc;
+ TestCase == srp_rsa_3des_ede_cbc;
+ TestCase == srp_dss_3des_ede_cbc;
+ TestCase == rsa_psk_3des_ede_cbc;
+ TestCase == rsa_3des_ede_cbc;
+ TestCase == dhe_rsa_3des_ede_cbc;
+ TestCase == dhe_dss_3des_ede_cbc;
+ TestCase == ecdhe_rsa_3des_ede_cbc;
+ TestCase == srp_anon_dss_3des_ede_cbc;
+ TestCase == dh_anon_3des_ede_cbc;
+ TestCase == ecdh_anon_3des_ede_cbc;
+ TestCase == ecdhe_ecdsa_3des_ede_cbc ->
+ SupCiphers = proplists:get_value(ciphers, crypto:supports()),
+ case lists:member(des_ede3, SupCiphers) of
+ true ->
+ ct:timetrap({seconds, 5}),
+ Config;
+ _ ->
+ {skip, "Missing 3DES crypto support"}
+ end;
+init_per_testcase(TestCase, Config) when TestCase == psk_rc4_128;
+ TestCase == ecdhe_psk_rc4_128;
+ TestCase == dhe_psk_rc4_128;
+ TestCase == rsa_psk_rc4_128;
+ TestCase == rsa_rc4_128;
+ TestCase == ecdhe_rsa_rc4_128;
+ TestCase == ecdhe_ecdsa_rc4_128;
+ TestCase == dh_anon_rc4_128 ->
+ SupCiphers = proplists:get_value(ciphers, crypto:supports()),
+ case lists:member(rc4, SupCiphers) of
+ true ->
+ ct:timetrap({seconds, 5}),
+ Config;
+ _ ->
+ {skip, "Missing RC4 crypto support"}
+ end;
+init_per_testcase(TestCase, Config) when TestCase == psk_aes_128_ccm_8;
+ TestCase == rsa_psk_aes_128_ccm_8;
+ TestCase == psk_aes_128_ccm_8;
+ TestCase == dhe_psk_aes_128_ccm_8;
+ TestCase == ecdhe_psk_aes_128_ccm_8 ->
+ SupCiphers = proplists:get_value(ciphers, crypto:supports()),
+ case lists:member(aes_128_ccm, SupCiphers) of
+ true ->
+ ct:timetrap({seconds, 5}),
+ Config;
+ _ ->
+ {skip, "Missing AES_128_CCM crypto support"}
+ end;
+init_per_testcase(TestCase, Config) when TestCase == psk_aes_256_ccm_8;
+ TestCase == rsa_psk_aes_256_ccm_8;
+ TestCase == psk_aes_256_ccm_8;
+ TestCase == dhe_psk_aes_256_ccm_8;
+ TestCase == ecdhe_psk_aes_256_ccm_8 ->
+ SupCiphers = proplists:get_value(ciphers, crypto:supports()),
+ case lists:member(aes_256_ccm, SupCiphers) of
+ true ->
+ ct:timetrap({seconds, 5}),
+ Config;
+ _ ->
+ {skip, "Missing AES_256_CCM crypto support"}
+ end;
+init_per_testcase(TestCase, Config) ->
+ Cipher = ssl_test_lib:test_cipher(TestCase, Config),
+ SupCiphers = proplists:get_value(ciphers, crypto:supports()),
+ case lists:member(Cipher, SupCiphers) of
+ true ->
+ ct:timetrap({seconds, 5}),
+ Config;
+ _ ->
+ {skip, {Cipher, SupCiphers}}
+ end.
+
+end_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Initializtion ------------------------------------------
+%%--------------------------------------------------------------------
+init_certs(srp_rsa, Config) ->
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain, ssl_test_lib:default_cert_chain_conf()},
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ Config, ""),
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}} | ServerOpts],
+ client_config => [{srp_identity, {"Test-User", "secret"}} | ClientOpts]}} |
+ proplists:delete(tls_config, Config)];
+init_certs(srp_anon, Config) ->
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}}],
+ client_config => [{srp_identity, {"Test-User", "secret"}}]}} |
+ proplists:delete(tls_config, Config)];
+init_certs(rsa_psk, Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature, keyEncipherment]}]),
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
+ [[ssl_test_lib:digest()],[ssl_test_lib:digest()],
+ [ssl_test_lib:digest(), {extensions, Ext}]]},
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ Config, "_peer_keyEncipherment"),
+ PskSharedSecret = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}} | ServerOpts],
+ client_config => [{psk_identity, "Test-User"},
+ {user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}} | ClientOpts]}} |
+ proplists:delete(tls_config, Config)];
+init_certs(rsa, Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature, keyEncipherment]}]),
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
+ [[ssl_test_lib:digest()],[ssl_test_lib:digest()],
+ [ssl_test_lib:digest(), {extensions, Ext}]]}
+ ],
+ Config, "_peer_keyEncipherment"),
+ [{tls_config, #{server_config => ServerOpts,
+ client_config => ClientOpts}} |
+ proplists:delete(tls_config, Config)];
+init_certs(dhe_dss, Config) ->
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_dsa_cert_chains([{server_chain, ssl_test_lib:default_cert_chain_conf()},
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ Config, ""),
+ [{tls_config, #{server_config => ServerOpts,
+ client_config => ClientOpts}} |
+ proplists:delete(tls_config, Config)];
+init_certs(srp_dss, Config) ->
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_dsa_cert_chains([{server_chain, ssl_test_lib:default_cert_chain_conf()},
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ Config, ""),
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}} | ServerOpts],
+ client_config => [{srp_identity, {"Test-User", "secret"}} | ClientOpts]}} |
+ proplists:delete(tls_config, Config)];
+init_certs(GroupName, Config) when GroupName == dhe_rsa;
+ GroupName == ecdhe_rsa ->
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain, ssl_test_lib:default_cert_chain_conf()},
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ Config, ""),
+ [{tls_config, #{server_config => ServerOpts,
+ client_config => ClientOpts}} |
+ proplists:delete(tls_config, Config)];
+init_certs(GroupName, Config) when GroupName == dhe_ecdsa;
+ GroupName == ecdhe_ecdsa ->
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_ecc_cert_chains([{server_chain, ssl_test_lib:default_cert_chain_conf()},
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ Config, ""),
+ [{tls_config, #{server_config => ServerOpts,
+ client_config => ClientOpts}} |
+ proplists:delete(tls_config, Config)];
+init_certs(GroupName, Config) when GroupName == psk;
+ GroupName == dhe_psk;
+ GroupName == ecdhe_psk ->
+ PskSharedSecret = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}}],
+ client_config => [{psk_identity, "Test-User"},
+ {user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}}]}} |
+ proplists:delete(tls_config, Config)];
+init_certs(srp, Config) ->
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}}],
+ client_config => [{srp_identity, {"Test-User", "secret"}}]}} |
+ proplists:delete(tls_config, Config)];
+init_certs(_GroupName, Config) ->
+ %% Anonymous does not need certs
+ [{tls_config, #{server_config => [],
+ client_config => []}} |
+ proplists:delete(tls_config, Config)].
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% SRP --------------------------------------------------------
+%%--------------------------------------------------------------------
+srp_rsa_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_rsa, '3des_ede_cbc', Config).
+
+srp_rsa_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_rsa, 'aes_128_cbc', Config).
+
+srp_rsa_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_rsa, 'aes_256_cbc', Config).
+
+srp_dss_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_dss, '3des_ede_cbc', Config).
+
+srp_dss_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_dss, 'aes_128_cbc', Config).
+
+srp_dss_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_dss, 'aes_256_cbc', Config).
+
+%%--------------------------------------------------------------------
+%% PSK --------------------------------------------------------
+%%--------------------------------------------------------------------
+rsa_psk_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, '3des_ede_cbc', Config).
+
+rsa_psk_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, 'aes_128_cbc', Config).
+
+rsa_psk_aes_128_ccm(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, 'aes_128_ccm', Config).
+
+rsa_psk_aes_128_ccm_8(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, 'aes_128_ccm_8', Config).
+
+rsa_psk_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, 'aes_256_cbc', Config).
+
+rsa_psk_aes_256_ccm(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, 'aes_256_ccm', Config).
+
+rsa_psk_aes_256_ccm_8(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, 'aes_256_ccm_8', Config).
+
+rsa_psk_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, 'rc4_128', Config).
+
+%%--------------------------------------------------------------------
+%% RSA --------------------------------------------------------
+%%--------------------------------------------------------------------
+rsa_des_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(rsa, 'des_cbc', Config).
+
+rsa_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(rsa, '3des_ede_cbc', Config).
+
+rsa_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(rsa, 'aes_128_cbc', Config).
+
+rsa_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(rsa, 'aes_256_cbc', Config).
+
+rsa_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(rsa, 'aes_128_gcm', Config).
+
+rsa_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(rsa, 'aes_256_gcm', Config).
+
+rsa_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(rsa, 'rc4_128', Config).
+%%--------------------------------------------------------------------
+%% DHE_RSA --------------------------------------------------------
+%%--------------------------------------------------------------------
+dhe_rsa_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_rsa, '3des_ede_cbc', Config).
+
+dhe_rsa_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_rsa, 'aes_128_cbc', Config).
+
+dhe_rsa_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_rsa, 'aes_128_gcm', Config).
+
+dhe_rsa_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_rsa, 'aes_256_cbc', Config).
+
+dhe_rsa_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_rsa, 'aes_256_gcm', Config).
+
+dhe_rsa_chacha20_poly1305(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_rsa, 'chacha20_poly1305', Config).
+%%--------------------------------------------------------------------
+%% ECDHE_RSA --------------------------------------------------------
+%%--------------------------------------------------------------------
+ecdhe_rsa_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_rsa, '3des_ede_cbc', Config).
+
+ecdhe_rsa_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_rsa, 'aes_128_cbc', Config).
+
+ecdhe_rsa_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_rsa, 'aes_128_gcm', Config).
+
+ecdhe_rsa_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_rsa, 'aes_256_cbc', Config).
+
+ecdhe_rsa_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_rsa, 'aes_256_gcm', Config).
+
+ecdhe_rsa_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_rsa, 'rc4_128', Config).
+
+ecdhe_rsa_chacha20_poly1305(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_rsa, 'chacha20_poly1305', Config).
+
+%%--------------------------------------------------------------------
+%% ECDHE_ECDSA --------------------------------------------------------
+%%--------------------------------------------------------------------
+ecdhe_ecdsa_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_ecdsa, 'rc4_128', Config).
+
+ecdhe_ecdsa_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_ecdsa, '3des_ede_cbc', Config).
+
+ecdhe_ecdsa_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_ecdsa, 'aes_128_cbc', Config).
+
+ecdhe_ecdsa_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_ecdsa, 'aes_128_gcm', Config).
+
+ecdhe_ecdsa_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_ecdsa, 'aes_256_cbc', Config).
+
+ecdhe_ecdsa_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_ecdsa, 'aes_256_gcm', Config).
+
+ecdhe_ecdsa_chacha20_poly1305(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_ecdsa, 'chacha20_poly1305', Config).
+%%--------------------------------------------------------------------
+%% DHE_DSS --------------------------------------------------------
+%%--------------------------------------------------------------------
+dhe_dss_des_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_dss, 'des_cbc', Config).
+
+dhe_dss_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_dss, '3des_ede_cbc', Config).
+
+dhe_dss_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_dss, 'aes_128_cbc', Config).
+
+dhe_dss_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_dss, 'aes_256_cbc', Config).
+
+dhe_dss_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_dss, 'aes_128_gcm', Config).
+
+dhe_dss_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_dss, 'aes_256_gcm', Config).
+
+%%--------------------------------------------------------------------
+%% Anonymous --------------------------------------------------------
+%%--------------------------------------------------------------------
+dh_anon_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dh_anon, '3des_ede_cbc', Config).
+
+dh_anon_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dh_anon, 'aes_128_cbc', Config).
+
+dh_anon_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dh_anon, 'aes_128_gcm', Config).
+
+dh_anon_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dh_anon, 'aes_256_cbc', Config).
+
+dh_anon_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dh_anon, 'aes_256_gcm', Config).
+
+dh_anon_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(dh_anon, 'rc4_128', Config).
+
+ecdh_anon_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdh_anon, '3des_ede_cbc', Config).
+
+ecdh_anon_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdh_anon, 'aes_128_cbc', Config).
+
+ecdh_anon_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdh_anon, 'aes_256_cbc', Config).
+
+srp_anon_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_anon, '3des_ede_cbc', Config).
+
+srp_anon_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_anon, 'aes_128_cbc', Config).
+
+srp_anon_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_anon, 'aes_256_cbc', Config).
+
+dhe_psk_des_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'des_cbc', Config).
+
+dhe_psk_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'rc4_128', Config).
+
+dhe_psk_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, '3des_ede_cbc', Config).
+
+dhe_psk_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_128_cbc', Config).
+
+dhe_psk_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_256_cbc', Config).
+
+dhe_psk_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_128_gcm', Config).
+
+dhe_psk_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_256_gcm', Config).
+
+dhe_psk_aes_128_ccm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_128_ccm', Config).
+
+dhe_psk_aes_256_ccm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_256_ccm', Config).
+
+dhe_psk_aes_128_ccm_8(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_128_ccm_8', Config).
+
+dhe_psk_aes_256_ccm_8(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_256_ccm_8', Config).
+
+ecdhe_psk_des_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'des_cbc', Config).
+
+ecdhe_psk_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'rc4_128', Config).
+
+ecdhe_psk_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, '3des_ede_cbc', Config).
+
+ecdhe_psk_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_128_cbc', Config).
+
+ecdhe_psk_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_256_cbc', Config).
+
+ecdhe_psk_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_128_gcm', Config).
+
+ecdhe_psk_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_256_gcm', Config).
+
+ecdhe_psk_aes_128_ccm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_128_ccm', Config).
+
+ecdhe_psk_aes_128_ccm_8(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_128_ccm_8', Config).
+
+psk_des_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'des_cbc', Config).
+
+psk_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'rc4_128', Config).
+
+psk_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(psk, '3des_ede_cbc', Config).
+
+psk_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_128_cbc', Config).
+
+psk_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_256_cbc', Config).
+
+psk_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_128_gcm', Config).
+
+psk_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_256_gcm', Config).
+
+psk_aes_128_ccm(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_128_ccm', Config).
+
+psk_aes_256_ccm(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_256_ccm', Config).
+
+psk_aes_128_ccm_8(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_128_ccm_8', Config).
+
+psk_aes_256_ccm_8(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_256_ccm_8', Config).
+
+%%--------------------------------------------------------------------
+%% Internal functions ----------------------------------------------
+%%--------------------------------------------------------------------
+run_ciphers_test(Kex, Cipher, Config) ->
+ Version = ssl_test_lib:protocol_version(Config),
+ TestCiphers = test_ciphers(Kex, Cipher, Version),
+
+ case TestCiphers of
+ [_|_] ->
+ lists:foreach(fun(TestCipher) ->
+ cipher_suite_test(TestCipher, Version, Config)
+ end, TestCiphers);
+ [] ->
+ {skip, {not_sup, Kex, Cipher, Version}}
+ end.
+
+cipher_suite_test(CipherSuite, _Version, Config) ->
+ #{server_config := SOpts,
+ client_config := COpts} = proplists:get_value(tls_config, Config),
+ ServerOpts = ssl_test_lib:ssl_options(SOpts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(COpts, Config),
+ ct:log("Testing CipherSuite ~p~n", [CipherSuite]),
+ ct:log("Server Opts ~p~n", [ServerOpts]),
+ ct:log("Client Opts ~p~n", [ClientOpts]),
+ ssl_test_lib:basic_test([{ciphers, [CipherSuite]} | COpts], SOpts, [{client_type, erlang},
+ {server_type, openssl} | Config]).
+
+
+test_ciphers(Kex, Cipher, Version) ->
+ Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(default, Version) ++ ssl:cipher_suites(anonymous, Version),
+ [{key_exchange,
+ fun(Kex0) when Kex0 == Kex -> true;
+ (_) -> false
+ end},
+ {cipher,
+ fun(Cipher0) when Cipher0 == Cipher -> true;
+ (_) -> false
+ end}]),
+ ct:log("Version ~p Testing ~p~n", [Version, Ciphers]),
+ OpenSSLCiphers = openssl_ciphers(),
+ ct:log("OpenSSLCiphers ~p~n", [OpenSSLCiphers]),
+ lists:filter(fun(C) ->
+ ct:log("Cipher ~p~n", [C]),
+ lists:member(ssl_cipher_format:suite_map_to_openssl_str(C), OpenSSLCiphers)
+ end, Ciphers).
+
+
+openssl_ciphers() ->
+ Str = os:cmd("openssl ciphers"),
+ string:split(string:strip(Str, right, $\n), ":", all).
diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl
index c64358960c..d02888793c 100644
--- a/lib/ssl/test/ssl_ECC_SUITE.erl
+++ b/lib/ssl/test/ssl_ECC_SUITE.erl
@@ -51,35 +51,7 @@ groups() ->
].
test_cases()->
- key_cert_combinations()
- ++ misc()
- ++ ecc_negotiation().
-
-key_cert_combinations() ->
- server_ecdh_rsa() ++
- server_ecdhe_rsa() ++
- server_ecdh_ecdsa() ++
- server_ecdhe_ecdsa().
-
-server_ecdh_rsa() ->
- [client_ecdh_rsa_server_ecdh_rsa,
- client_ecdhe_rsa_server_ecdh_rsa,
- client_ecdhe_ecdsa_server_ecdh_rsa].
-
-server_ecdhe_rsa() ->
- [client_ecdh_rsa_server_ecdhe_rsa,
- client_ecdhe_rsa_server_ecdhe_rsa,
- client_ecdhe_ecdsa_server_ecdhe_rsa].
-
-server_ecdh_ecdsa() ->
- [client_ecdh_ecdsa_server_ecdh_ecdsa,
- client_ecdhe_rsa_server_ecdh_ecdsa,
- client_ecdhe_ecdsa_server_ecdh_ecdsa].
-
-server_ecdhe_ecdsa() ->
- [client_ecdh_rsa_server_ecdhe_ecdsa,
- client_ecdh_ecdsa_server_ecdhe_ecdsa,
- client_ecdhe_ecdsa_server_ecdhe_ecdsa].
+ misc() ++ ecc_negotiation().
misc()->
[client_ecdsa_server_ecdsa_with_raw_key].
@@ -160,35 +132,6 @@ end_per_testcase(_TestCase, Config) ->
%% Test diffrent certificate chain types, note that it is the servers
%% chain that affect what cipher suit that will be choosen
-%% ECDH_RSA
-client_ecdh_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_rsa_server_ecdh_rsa(Config).
-client_ecdhe_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_rsa_server_ecdh_rsa(Config).
-client_ecdhe_ecdsa_server_ecdh_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdh_rsa(Config).
-%% ECDHE_RSA
-client_ecdh_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_rsa_server_ecdhe_rsa(Config).
-client_ecdhe_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_rsa_server_ecdhe_rsa(Config).
-client_ecdhe_ecdsa_server_ecdhe_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_rsa(Config).
-%% ECDH_ECDSA
-client_ecdh_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_ecdsa_server_ecdh_ecdsa(Config).
-client_ecdhe_rsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_rsa_server_ecdh_ecdsa(Config).
-client_ecdhe_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdh_ecdsa(Config).
-%% ECDHE_ECDSA
-client_ecdh_rsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_rsa_server_ecdhe_ecdsa(Config).
-client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_ecdsa_server_ecdhe_ecdsa(Config).
-client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config).
-
client_ecdsa_server_ecdsa_with_raw_key(Config) when is_list(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
diff --git a/lib/ssl/test/ssl_ECC_openssl_SUITE.erl b/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
index 81a7dfd2da..68d4e910fd 100644
--- a/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
@@ -33,77 +33,23 @@
%%--------------------------------------------------------------------
all() ->
- case test_cases() of
- [_|_] ->
- all_groups();
- [] ->
- [skip]
- end.
-
-all_groups() ->
case ssl_test_lib:openssl_sane_dtls() of
true ->
[{group, 'tlsv1.2'},
- {group, 'tlsv1.1'},
- {group, 'tlsv1'},
- {group, 'dtlsv1.2'},
- {group, 'dtlsv1'}];
+ {group, 'dtlsv1.2'}];
false ->
- [{group, 'tlsv1.2'},
- {group, 'tlsv1.1'},
- {group, 'tlsv1'}]
+ [{group, 'tlsv1.2'}]
end.
groups() ->
case ssl_test_lib:openssl_sane_dtls() of
true ->
- [{'tlsv1.2', [], [mix_sign | test_cases()]},
- {'tlsv1.1', [], test_cases()},
- {'tlsv1', [], test_cases()},
- {'dtlsv1.2', [], [mix_sign | test_cases()]},
- {'dtlsv1', [], test_cases()}];
+ [{'tlsv1.2', [], [mix_sign]},
+ {'dtlsv1.2', [], [mix_sign]}];
false ->
- [{'tlsv1.2', [], [mix_sign | test_cases()]},
- {'tlsv1.1', [], test_cases()},
- {'tlsv1', [], test_cases()}]
+ [{'tlsv1.2', [], [mix_sign]}]
end.
-
-test_cases()->
- cert_combinations().
-cert_combinations() ->
- lists:append(lists:map(fun({Name, Suites}) ->
- case ssl_test_lib:openssl_filter(Name) of
- [] ->
- [];
- [_|_] ->
- Suites
- end
- end, [{"ECDH-ECDSA", server_ecdh_ecdsa()},
- {"ECDH-RSA", server_ecdh_rsa()},
- {"ECDHE-RSA", server_ecdhe_rsa()},
- {"ECDHE-ECDSA", server_ecdhe_ecdsa()}
- ])).
-server_ecdh_rsa() ->
- [client_ecdh_rsa_server_ecdh_rsa,
- client_ecdhe_rsa_server_ecdh_rsa,
- client_ecdhe_ecdsa_server_ecdh_rsa].
-
-server_ecdhe_rsa() ->
- [client_ecdh_rsa_server_ecdhe_rsa,
- client_ecdhe_rsa_server_ecdhe_rsa,
- client_ecdhe_ecdsa_server_ecdhe_rsa].
-
-server_ecdh_ecdsa() ->
- [client_ecdh_ecdsa_server_ecdh_ecdsa,
- client_ecdhe_rsa_server_ecdh_ecdsa,
- client_ecdhe_ecdsa_server_ecdh_ecdsa].
-
-server_ecdhe_ecdsa() ->
- [client_ecdh_rsa_server_ecdhe_ecdsa,
- client_ecdh_ecdsa_server_ecdhe_ecdsa,
- client_ecdhe_ecdsa_server_ecdhe_ecdsa].
-
%%--------------------------------------------------------------------
init_per_suite(Config0) ->
end_per_suite(Config0),
@@ -171,38 +117,6 @@ end_per_testcase(_TestCase, Config) ->
skip(Config) when is_list(Config) ->
{skip, openssl_does_not_support_ECC}.
-%% Test diffrent certificate chain types, note that it is the servers
-%% chain that affect what cipher suit that will be choosen
-
-%% ECDH_RSA
-client_ecdh_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_rsa_server_ecdh_rsa(Config).
-client_ecdhe_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_rsa_server_ecdh_rsa(Config).
-client_ecdhe_ecdsa_server_ecdh_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdh_rsa(Config).
-%% ECDHE_RSA
-client_ecdh_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_rsa_server_ecdhe_rsa(Config).
-client_ecdhe_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_rsa_server_ecdhe_rsa(Config).
-client_ecdhe_ecdsa_server_ecdhe_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_rsa(Config).
-%% ECDH_ECDSA
-client_ecdh_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_ecdsa_server_ecdh_ecdsa(Config).
-client_ecdhe_rsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_rsa_server_ecdh_ecdsa(Config).
-client_ecdhe_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdh_ecdsa(Config).
-%% ECDHE_ECDSA
-client_ecdh_rsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_rsa_server_ecdhe_ecdsa(Config).
-client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_ecdsa_server_ecdhe_ecdsa(Config).
-client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config).
-
mix_sign(Config) ->
{COpts0, SOpts0} = ssl_test_lib:make_mix_cert(Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
diff --git a/lib/ssl/test/ssl_cipher_suite_SUITE.erl b/lib/ssl/test/ssl_cipher_suite_SUITE.erl
index 8805df7b52..51788c29e7 100644
--- a/lib/ssl/test/ssl_cipher_suite_SUITE.erl
+++ b/lib/ssl/test/ssl_cipher_suite_SUITE.erl
@@ -127,7 +127,6 @@ groups() ->
]}
].
-
kex() ->
rsa() ++ ecdsa() ++ dss() ++ anonymous().
@@ -154,7 +153,6 @@ anonymous() ->
{group, ecdhe_psk},
{group, srp_anon}
].
-
init_per_suite(Config) ->
catch crypto:stop(),
@@ -170,7 +168,7 @@ end_per_suite(_Config) ->
ssl:stop(),
application:stop(crypto).
-%%--------------------------------------------------------------------
+
init_per_group(GroupName, Config) when GroupName == ecdh_anon;
GroupName == ecdhe_rsa;
GroupName == ecdhe_psk ->
@@ -236,6 +234,7 @@ end_per_group(GroupName, Config) ->
false ->
Config
end.
+
init_per_testcase(TestCase, Config) when TestCase == psk_3des_ede_cbc;
TestCase == srp_anon_3des_ede_cbc;
TestCase == dhe_psk_3des_ede_cbc;
@@ -302,8 +301,7 @@ init_per_testcase(TestCase, Config) when TestCase == psk_aes_256_ccm_8;
{skip, "Missing AES_256_CCM crypto support"}
end;
init_per_testcase(TestCase, Config) ->
- Cipher = test_cipher(TestCase, Config),
- %%Reason = io_lib:format("Missing ~p crypto support", [Cipher]),
+ Cipher = ssl_test_lib:test_cipher(TestCase, Config),
SupCiphers = proplists:get_value(ciphers, crypto:supports()),
case lists:member(Cipher, SupCiphers) of
true ->
@@ -316,17 +314,21 @@ init_per_testcase(TestCase, Config) ->
end_per_testcase(_TestCase, Config) ->
Config.
+%%--------------------------------------------------------------------
+%% Initializtion ------------------------------------------
+%%--------------------------------------------------------------------
+
init_certs(srp_rsa, Config) ->
DefConf = ssl_test_lib:default_cert_chain_conf(),
CertChainConf = ssl_test_lib:gen_conf(rsa, rsa, DefConf, DefConf),
#{server_config := ServerOpts,
client_config := ClientOpts}
= public_key:pkix_test_data(CertChainConf),
- [{tls_config, #{server_config => [{user_lookup_fun, {fun user_lookup/3, undefined}} | ServerOpts],
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}} | ServerOpts],
client_config => [{srp_identity, {"Test-User", "secret"}} | ClientOpts]}} |
proplists:delete(tls_config, Config)];
init_certs(srp_anon, Config) ->
- [{tls_config, #{server_config => [{user_lookup_fun, {fun user_lookup/3, undefined}}],
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}}],
client_config => [{srp_identity, {"Test-User", "secret"}}]}} |
proplists:delete(tls_config, Config)];
init_certs(rsa_psk, Config) ->
@@ -335,9 +337,9 @@ init_certs(rsa_psk, Config) ->
[[],[],[{extensions, ClientExt}]]}],
Config, "_peer_keyEncipherment"),
PskSharedSecret = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
- [{tls_config, #{server_config => [{user_lookup_fun, {fun user_lookup/3, PskSharedSecret}} | ServerOpts],
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}} | ServerOpts],
client_config => [{psk_identity, "Test-User"},
- {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}} | ClientOpts]}} |
+ {user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}} | ClientOpts]}} |
proplists:delete(tls_config, Config)];
init_certs(rsa, Config) ->
ClientExt = x509_test:extensions([{key_usage, [digitalSignature, keyEncipherment]}]),
@@ -362,7 +364,7 @@ init_certs(srp_dss, Config) ->
#{server_config := ServerOpts,
client_config := ClientOpts}
= public_key:pkix_test_data(CertChainConf),
- [{tls_config, #{server_config => [{user_lookup_fun, {fun user_lookup/3, undefined}} | ServerOpts],
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}} | ServerOpts],
client_config => [{srp_identity, {"Test-User", "secret"}} | ClientOpts]}} |
proplists:delete(tls_config, Config)];
init_certs(GroupName, Config) when GroupName == dhe_rsa;
@@ -389,12 +391,12 @@ init_certs(GroupName, Config) when GroupName == psk;
GroupName == dhe_psk;
GroupName == ecdhe_psk ->
PskSharedSecret = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
- [{tls_config, #{server_config => [{user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}],
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}}],
client_config => [{psk_identity, "Test-User"},
- {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}]}} |
+ {user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}}]}} |
proplists:delete(tls_config, Config)];
init_certs(srp, Config) ->
- [{tls_config, #{server_config => [{user_lookup_fun, {fun user_lookup/3, undefined}}],
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}}],
client_config => [{srp_identity, {"Test-User", "secret"}}]}} |
proplists:delete(tls_config, Config)];
init_certs(_GroupName, Config) ->
@@ -402,6 +404,7 @@ init_certs(_GroupName, Config) ->
[{tls_config, #{server_config => [],
client_config => []}} |
proplists:delete(tls_config, Config)].
+
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
@@ -700,10 +703,6 @@ psk_aes_256_ccm_8(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
%% Internal functions ----------------------------------------------
%%--------------------------------------------------------------------
-test_cipher(TestCase, Config) ->
- [{name, Group} |_] = proplists:get_value(tc_group_properties, Config),
- list_to_atom(re:replace(atom_to_list(TestCase), atom_to_list(Group) ++ "_", "", [{return, list}])).
-
run_ciphers_test(Kex, Cipher, Config) ->
Version = ssl_test_lib:protocol_version(Config),
TestCiphers = test_ciphers(Kex, Cipher, Version),
@@ -717,30 +716,28 @@ run_ciphers_test(Kex, Cipher, Config) ->
{skip, {not_sup, Kex, Cipher, Version}}
end.
-cipher_suite_test(CipherSuite, Version, Config) ->
+cipher_suite_test(ErlangCipherSuite, Version, Config) ->
#{server_config := SOpts,
client_config := COpts} = proplists:get_value(tls_config, Config),
ServerOpts = ssl_test_lib:ssl_options(SOpts, Config),
ClientOpts = ssl_test_lib:ssl_options(COpts, Config),
- ct:log("Testing CipherSuite ~p~n", [CipherSuite]),
+ ct:log("Testing CipherSuite ~p~n", [ErlangCipherSuite]),
ct:log("Server Opts ~p~n", [ServerOpts]),
ct:log("Client Opts ~p~n", [ClientOpts]),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- ErlangCipherSuite = erlang_cipher_suite(CipherSuite),
-
ConnectionInfo = {ok, {Version, ErlangCipherSuite}},
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}},
- {options, [{versions, [Version]}, {ciphers, [CipherSuite]} | ServerOpts]}]),
+ {options, [{versions, [Version]}, {ciphers, [ErlangCipherSuite]} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
{mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}},
- {options, [{versions, [Version]}, {ciphers, [CipherSuite]} |
+ {options, [{versions, [Version]}, {ciphers, [ErlangCipherSuite]} |
ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client, ok),
@@ -748,17 +745,6 @@ cipher_suite_test(CipherSuite, Version, Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
-erlang_cipher_suite(Suite) when is_list(Suite)->
- ssl_cipher_format:suite_definition(ssl_cipher_format:suite_openssl_str_to_map(Suite));
-erlang_cipher_suite(Suite) ->
- Suite.
-
-user_lookup(psk, _Identity, UserState) ->
- {ok, UserState};
-user_lookup(srp, Username, _UserState) ->
- Salt = ssl_cipher:random_bytes(16),
- UserPassHash = crypto:hash(sha, [Salt, crypto:hash(sha, [Username, <<$:>>, <<"secret">>])]),
- {ok, {srp_1024, Salt, UserPassHash}}.
test_ciphers(Kex, Cipher, Version) ->
ssl:filter_cipher_suites(ssl:cipher_suites(all, Version) ++ ssl:cipher_suites(anonymous, Version),
@@ -770,3 +756,4 @@ test_ciphers(Kex, Cipher, Version) ->
fun(Cipher0) when Cipher0 == Cipher -> true;
(_) -> false
end}]).
+
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index 65b8998cc3..3b161a0c8a 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -631,6 +631,40 @@ make_rsa_cert_chains(UserConf, Config, Suffix) ->
[{reuseaddr, true}, {verify, verify_peer} | ServerConf]
}.
+make_ecc_cert_chains(UserConf, Config, Suffix) ->
+ ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
+ CertChainConf = gen_conf(ecdsa, ecdsa, ClientChain, ServerChain),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa" ++ Suffix]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa" ++ Suffix]),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ {[{verify, verify_peer} | ClientConf],
+ [{reuseaddr, true}, {verify, verify_peer} | ServerConf]
+ }.
+
+
+make_dsa_cert_chains(UserConf, Config, Suffix) ->
+ CryptoSupport = crypto:supports(),
+ case proplists:get_bool(dss, proplists:get_value(public_keys, CryptoSupport)) of
+ true ->
+ ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
+ CertChainConf = gen_conf(dsa, dsa, ClientChain, ServerChain),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa" ++ Suffix]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa" ++ Suffix]),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ {[{verify, verify_peer} | ClientConf],
+ [{reuseaddr, true}, {verify, verify_peer} | ServerConf]};
+ false ->
+ Config
+ end.
+
make_ec_cert_chains(UserConf, ClientChainType, ServerChainType, Config) ->
make_ec_cert_chains(UserConf, ClientChainType, ServerChainType, Config, ?DEFAULT_CURVE).
%%
@@ -1067,7 +1101,7 @@ accepters(Acc, N) ->
basic_test(COpts, SOpts, Config) ->
SType = proplists:get_value(server_type, Config),
CType = proplists:get_value(client_type, Config),
- {Server, Port} = start_server(SType, SOpts, Config),
+ {Server, Port} = start_server(SType, COpts, SOpts, Config),
Client = start_client(CType, Port, COpts, Config),
gen_check_result(Server, SType, Client, CType),
stop(Server, Client).
@@ -1134,7 +1168,7 @@ start_client(erlang, Port, ClientOpts, Config) ->
{host, Hostname},
{from, self()},
{mfa, {ssl_test_lib, check_key_exchange_send_active, [KeyEx]}},
- {options, [{verify, verify_peer} | ClientOpts]}]).
+ {options, ClientOpts}]).
%% Workaround for running tests on machines where openssl
%% s_client would use an IPv6 address with localhost. As
@@ -1169,20 +1203,19 @@ start_client_ecc_error(erlang, Port, ClientOpts, ECCOpts, Config) ->
[{verify, verify_peer} | ClientOpts]}]).
-start_server(openssl, ServerOpts, Config) ->
- Cert = proplists:get_value(certfile, ServerOpts),
- Key = proplists:get_value(keyfile, ServerOpts),
- CA = proplists:get_value(cacertfile, ServerOpts),
+start_server(openssl, ClientOpts, ServerOpts, Config) ->
Port = inet_port(node()),
Version = protocol_version(Config),
Exe = "openssl",
- Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
- "-verify", "2", "-cert", Cert, "-CAfile", CA,
- "-key", Key, "-msg", "-debug"],
+ CertArgs = openssl_cert_options(ServerOpts),
+ [Cipher|_] = proplists:get_value(ciphers, ClientOpts, ssl:cipher_suites(default,Version)),
+ Args = ["s_server", "-accept", integer_to_list(Port), "-cipher",
+ ssl_cipher_format:suite_map_to_openssl_str(Cipher),
+ ssl_test_lib:version_flag(Version)] ++ CertArgs ++ ["-msg", "-debug"],
OpenSslPort = portable_open_port(Exe, Args),
true = port_command(OpenSslPort, "Hello world"),
{OpenSslPort, Port};
-start_server(erlang, ServerOpts, Config) ->
+start_server(erlang, _, ServerOpts, Config) ->
{_, ServerNode, _} = ssl_test_lib:run_where(Config),
KeyEx = proplists:get_value(check_keyex, Config, false),
Server = start_server([{node, ServerNode}, {port, 0},
@@ -1245,6 +1278,29 @@ stop(Client, Server) ->
close(Server),
close(Client).
+
+openssl_cert_options(ServerOpts) ->
+ Cert = proplists:get_value(certfile, ServerOpts, undefined),
+ Key = proplists:get_value(keyfile, ServerOpts, undefined),
+ CA = proplists:get_value(cacertfile, ServerOpts, undefined),
+ case CA of
+ undefined ->
+ case cert_option("-cert", Cert) ++ cert_option("-key", Key) of
+ [] ->
+ ["-nocert"];
+ Other ->
+ Other
+ end;
+ _ ->
+ cert_option("-cert", Cert) ++ cert_option("-CAfile", CA) ++
+ cert_option("-key", Key) ++ ["-verify", "2"]
+ end.
+
+cert_option(_, undefined) ->
+ [];
+cert_option(Opt, Value) ->
+ [Opt, Value].
+
supported_eccs(Opts) ->
ToCheck = proplists:get_value(eccs, Opts, []),
Supported = ssl:eccs(),
@@ -2374,3 +2430,16 @@ user_lookup(srp, Username, _UserState) ->
Salt = ssl_cipher:random_bytes(16),
UserPassHash = crypto:hash(sha, [Salt, crypto:hash(sha, [Username, <<$:>>, <<"secret">>])]),
{ok, {srp_1024, Salt, UserPassHash}}.
+
+test_cipher(TestCase, Config) ->
+ [{name, Group} |_] = proplists:get_value(tc_group_properties, Config),
+ list_to_atom(re:replace(atom_to_list(TestCase), atom_to_list(Group) ++ "_", "", [{return, list}])).
+
+digest() ->
+ case application:get_env(ssl, protocol_version, application:get_env(ssl, dtls_protocol_version)) of
+ Ver when Ver == 'tlsv1.2';
+ Ver == 'dtlsv1.2' ->
+ {digest, sha256};
+ _ ->
+ {digest, sha1}
+ end.
diff --git a/lib/stdlib/doc/src/gb_trees.xml b/lib/stdlib/doc/src/gb_trees.xml
index 570c9c7cb6..08aa1865e8 100644
--- a/lib/stdlib/doc/src/gb_trees.xml
+++ b/lib/stdlib/doc/src/gb_trees.xml
@@ -42,11 +42,8 @@
<section>
<title>Data Structure</title>
- <code type="none">
-{Size, Tree}</code>
-
- <p><c>Tree</c> is composed of nodes of the form <c>{Key, Value, Smaller,
- Bigger}</c> and the "empty tree" node <c>nil</c>.</p>
+ <p>Trees and iterators are built using opaque data structures that should
+ not be pattern-matched from outside this module.</p>
<p>There is no attempt to balance trees after deletions. As
deletions do not increase the height of a tree, this should be OK.</p>
diff --git a/lib/stdlib/doc/src/queue.xml b/lib/stdlib/doc/src/queue.xml
index 83a8afea81..89cce6d85b 100644
--- a/lib/stdlib/doc/src/queue.xml
+++ b/lib/stdlib/doc/src/queue.xml
@@ -168,7 +168,7 @@
<fsummary>Test if a queue is empty.</fsummary>
<desc>
<p>Tests if <c><anno>Q</anno></c> is empty and returns <c>true</c> if
- so, otherwise otherwise.</p>
+ so, otherwise <c>false</c>.</p>
</desc>
</func>