aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/asn1/src/asn1ct_constructed_per.erl26
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl3
-rw-r--r--lib/asn1/src/asn1ct_imm.erl7
-rw-r--r--lib/asn1/test/asn1_SUITE.erl7
-rw-r--r--lib/asn1/test/asn1_SUITE_data/EnumExt.asn120
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn19
-rw-r--r--lib/asn1/test/asn1_SUITE_data/SeqExtension2.asn1208
-rw-r--r--lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl3
-rw-r--r--lib/asn1/test/asn1_test_lib.erl12
-rw-r--r--lib/asn1/test/testConstraints.erl31
-rw-r--r--lib/asn1/test/testEnumExt.erl26
-rw-r--r--lib/asn1/test/testSeqExtension.erl33
-rw-r--r--lib/crypto/c_src/crypto.c72
-rw-r--r--lib/crypto/doc/src/crypto.xml113
-rw-r--r--lib/crypto/src/crypto.appup.src14
-rw-r--r--lib/crypto/src/crypto.erl1648
-rw-r--r--lib/crypto/test/crypto_SUITE.erl132
-rw-r--r--lib/crypto/vsn.mk2
-rw-r--r--lib/diameter/Makefile8
-rw-r--r--lib/diameter/doc/src/Makefile4
-rw-r--r--lib/diameter/doc/src/diameter.xml6
-rw-r--r--lib/diameter/doc/src/diameter_compile.xml6
-rw-r--r--lib/diameter/doc/src/diameter_dict.xml4
-rw-r--r--lib/diameter/doc/src/diameter_intro.xml6
-rw-r--r--lib/diameter/doc/src/diameter_sctp.xml22
-rw-r--r--lib/diameter/doc/src/diameter_tcp.xml15
-rw-r--r--lib/diameter/doc/src/diameter_using.xml6
-rw-r--r--lib/diameter/src/Makefile10
-rw-r--r--lib/diameter/src/base/diameter_codec.erl2
-rw-r--r--lib/diameter/src/base/diameter_peer.erl94
-rw-r--r--lib/diameter/src/base/diameter_traffic.erl2
-rw-r--r--lib/diameter/src/diameter.app.src (renamed from lib/diameter/src/base/diameter.app.src)0
-rw-r--r--lib/diameter/src/diameter.appup.src (renamed from lib/diameter/src/base/diameter.appup.src)31
-rw-r--r--lib/diameter/src/dict/base_rfc3588.dia6
-rw-r--r--lib/diameter/src/transport/diameter_sctp.erl74
-rw-r--r--lib/diameter/src/transport/diameter_tcp.erl64
-rw-r--r--lib/diameter/test/Makefile6
-rw-r--r--lib/diameter/test/diameter_codec_SUITE.erl2
-rw-r--r--lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl2
-rw-r--r--lib/diameter/test/diameter_examples_SUITE.erl2
-rw-r--r--lib/diameter/test/diameter_util.erl2
-rw-r--r--lib/diameter/vsn.mk2
-rw-r--r--lib/erl_interface/vsn.mk2
-rw-r--r--lib/et/vsn.mk2
-rw-r--r--lib/kernel/src/inet.erl41
-rw-r--r--lib/kernel/src/inet_db.erl65
-rw-r--r--lib/kernel/src/inet_hosts.erl9
-rw-r--r--lib/kernel/src/inet_res.erl6
-rw-r--r--lib/kernel/test/inet_SUITE.erl197
-rw-r--r--lib/kernel/test/inet_res_SUITE.erl198
-rw-r--r--lib/kernel/test/inet_res_SUITE_data/otptest/named_inc.conf6
-rw-r--r--lib/kernel/test/inet_res_SUITE_data/otptest/root.zone6
-rw-r--r--lib/mnesia/src/mnesia_subscr.erl10
-rw-r--r--lib/mnesia/test/mnesia_evil_coverage_test.erl4
-rw-r--r--lib/mnesia/test/mnesia_isolation_test.erl10
-rw-r--r--lib/os_mon/vsn.mk2
-rw-r--r--lib/public_key/doc/src/public_key.xml20
-rw-r--r--lib/public_key/src/public_key.app.src2
-rw-r--r--lib/public_key/src/public_key.erl3
-rw-r--r--lib/public_key/test/pkits_SUITE.erl2
-rw-r--r--lib/public_key/test/public_key_SUITE.erl2
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/ssh/src/ssh.erl2
-rw-r--r--lib/ssl/src/ssl.erl4
-rw-r--r--lib/ssl/src/ssl_cipher.erl12
-rw-r--r--lib/ssl/src/ssl_manager.erl1
-rw-r--r--lib/ssl/src/tls.erl2
-rw-r--r--lib/ssl/src/tls_connection.erl3
-rw-r--r--lib/ssl/src/tls_handshake.erl2
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl3
-rw-r--r--lib/ssl/test/ssl_certificate_verify_SUITE.erl3
-rw-r--r--lib/ssl/test/ssl_npn_handshake_SUITE.erl1
-rw-r--r--lib/ssl/test/ssl_packet_SUITE.erl2
-rw-r--r--lib/ssl/test/ssl_payload_SUITE.erl1
-rw-r--r--lib/ssl/test/ssl_session_cache_SUITE.erl2
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl1
76 files changed, 2155 insertions, 1225 deletions
diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl
index efb55cf015..d279e9697f 100644
--- a/lib/asn1/src/asn1ct_constructed_per.erl
+++ b/lib/asn1/src/asn1ct_constructed_per.erl
@@ -354,8 +354,7 @@ gen_dec_constructed_imm_2(Typename, CompList,
%% we don't return named lists any more Cnames = mkcnamelist(CompList),
demit({"Result = "}), %dbg
%% return value as record
- RecordName = lists:concat([get_record_name_prefix(),
- asn1ct_gen:list2rname(Typename)]),
+ RecordName = record_name(Typename),
case Typename of
['EXTERNAL'] ->
emit({" OldFormat={'",RecordName,
@@ -377,6 +376,29 @@ gen_dec_constructed_imm_2(Typename, CompList,
end,
emit({{curr,bytes},"}"}).
+%% record_name([TypeName]) -> RecordNameString
+%% Construct a record name for the constructed type, ignoring any
+%% fake sequences that are used to represent an extension addition
+%% group. Such fake sequences never appear as a top type, and their
+%% name always start with "ExtAddGroup".
+
+record_name(Typename0) ->
+ [TopType|Typename1] = lists:reverse(Typename0),
+ Typename = filter_ext_add_groups(Typename1, [TopType]),
+ lists:concat([get_record_name_prefix(),
+ asn1ct_gen:list2rname(Typename)]).
+
+filter_ext_add_groups([H|T], Acc) when is_atom(H) ->
+ case atom_to_list(H) of
+ "ExtAddGroup"++_ ->
+ filter_ext_add_groups(T, Acc);
+ _ ->
+ filter_ext_add_groups(T, [H|Acc])
+ end;
+filter_ext_add_groups([H|T], Acc) ->
+ filter_ext_add_groups(T, [H|Acc]);
+filter_ext_add_groups([], Acc) -> Acc.
+
textual_order([#'ComponentType'{textual_order=undefined}|_],TermList) ->
TermList;
textual_order(CompList,TermList) when is_list(CompList) ->
diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl
index 30c9ab9365..69d9d51bf1 100644
--- a/lib/asn1/src/asn1ct_gen_per.erl
+++ b/lib/asn1/src/asn1ct_gen_per.erl
@@ -250,7 +250,8 @@ emit_enc_enumerated_case(Erules, C, EnumName, Count) ->
enc_ext_and_val(per, E, F, Args) ->
[E|apply(asn1ct_eval_per, F, Args)];
enc_ext_and_val(uper, E, F, Args) ->
- <<E:1,(apply(asn1ct_eval_uper, F, Args))/bitstring>>.
+ Bs = list_to_bitstring([apply(asn1ct_eval_uper, F, Args)]),
+ <<E:1,Bs/bitstring>>.
%% Object code generating for encoding and decoding
diff --git a/lib/asn1/src/asn1ct_imm.erl b/lib/asn1/src/asn1ct_imm.erl
index c6803a0f96..bf362db843 100644
--- a/lib/asn1/src/asn1ct_imm.erl
+++ b/lib/asn1/src/asn1ct_imm.erl
@@ -86,7 +86,7 @@ per_dec_enumerated(BaseNamedList, NamedListExt0, Aligned) ->
bit_case(Base, Ext).
per_dec_extension_map(Aligned) ->
- Len = {add,per_dec_normally_small_number(Aligned),1},
+ Len = per_dec_normally_small_length(Aligned),
{get_bits,Len,[1,bitstring]}.
per_dec_integer(Constraint0, Aligned) ->
@@ -240,6 +240,11 @@ per_dec_normally_small_number(Aligned) ->
Unlimited = per_decode_semi_constrained(0, Aligned),
bit_case(Small, Unlimited).
+per_dec_normally_small_length(Aligned) ->
+ Small = {add,{get_bits,6,[1]},1},
+ Unlimited = decode_unconstrained_length(false, Aligned),
+ bit_case(Small, Unlimited).
+
per_decode_semi_constrained(Lb, Aligned) ->
add_lb(Lb, {get_bits,decode_unconstrained_length(false, Aligned),[8]}).
diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl
index 6be493320c..f00b23a8b2 100644
--- a/lib/asn1/test/asn1_SUITE.erl
+++ b/lib/asn1/test/asn1_SUITE.erl
@@ -454,10 +454,13 @@ testSeqDefault(Config, Rule, Opts) ->
testSeqExtension(Config) -> test(Config, fun testSeqExtension/3).
testSeqExtension(Config, Rule, Opts) ->
- asn1_test_lib:compile_all(["External", "SeqExtension"], Config,
+ asn1_test_lib:compile_all(["External",
+ "SeqExtension",
+ "SeqExtension2"],
+ Config,
[Rule|Opts]),
DataDir = ?config(data_dir, Config),
- testSeqExtension:main(DataDir, [Rule|Opts]).
+ testSeqExtension:main(Rule, DataDir, [Rule|Opts]).
testSeqExternal(Config) -> test(Config, fun testSeqExternal/3).
testSeqExternal(Config, Rule, Opts) ->
diff --git a/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1 b/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1
index 3a727e46bb..8dc5f3d7e1 100644
--- a/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1
@@ -31,5 +31,25 @@ Seq ::= SEQUENCE {
i INTEGER
}
+EnumExtBig ::= ENUMERATED {
+ base,
+ ...,
+ e00,e01,e02,e03,e04,e05,e06,e07,e08,e09,e0a,e0b,e0c,e0d,e0e,e0f,
+ e10,e11,e12,e13,e14,e15,e16,e17,e18,e19,e1a,e1b,e1c,e1d,e1e,e1f,
+ e20,e21,e22,e23,e24,e25,e26,e27,e28,e29,e2a,e2b,e2c,e2d,e2e,e2f,
+ e30,e31,e32,e33,e34,e35,e36,e37,e38,e39,e3a,e3b,e3c,e3d,e3e,e3f,
+ e40,e41,e42,e43,e44,e45,e46,e47,e48,e49,e4a,e4b,e4c,e4d,e4e,e4f,
+ e50,e51,e52,e53,e54,e55,e56,e57,e58,e59,e5a,e5b,e5c,e5d,e5e,e5f,
+ e60,e61,e62,e63,e64,e65,e66,e67,e68,e69,e6a,e6b,e6c,e6d,e6e,e6f,
+ e70,e71,e72,e73,e74,e75,e76,e77,e78,e79,e7a,e7b,e7c,e7d,e7e,e7f,
+ e80
+}
+
+SeqBig ::= SEQUENCE {
+ b BOOLEAN,
+ e EnumExtBig,
+ i INTEGER
+}
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn b/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn
index b07dcd8baa..0e905d8839 100644
--- a/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn
+++ b/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn
@@ -118,4 +118,23 @@ AC-BarringConfig ::= SEQUENCE {
ac-BarringForSpecialAC BIT STRING (SIZE(5))
}
+InlinedSeq ::= SEQUENCE {
+ ...,
+ [[
+ s SEQUENCE {
+ a INTEGER,
+ b BOOLEAN
+ }
+ ]]
+}
+
+-- 'ExtAddGroup1' is used internally to represent fake sequences for
+-- extension addition groups. Make sure that a real sequence with that
+-- name at the top-level doesn't cause a problem.
+
+ExtAddGroup1 ::= SEQUENCE {
+ x INTEGER,
+ y INTEGER
+}
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/SeqExtension2.asn1 b/lib/asn1/test/asn1_SUITE_data/SeqExtension2.asn1
new file mode 100644
index 0000000000..44900d9d39
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/SeqExtension2.asn1
@@ -0,0 +1,208 @@
+SeqExtension2 DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+
+SeqExt66 ::= SEQUENCE {
+ ...,
+ i0 INTEGER (0..127) OPTIONAL,
+ i1 INTEGER (0..127) OPTIONAL,
+ i2 INTEGER (0..127) OPTIONAL,
+ i3 INTEGER (0..127) OPTIONAL,
+ i4 INTEGER (0..127) OPTIONAL,
+ i5 INTEGER (0..127) OPTIONAL,
+ i6 INTEGER (0..127) OPTIONAL,
+ i7 INTEGER (0..127) OPTIONAL,
+ i8 INTEGER (0..127) OPTIONAL,
+ i9 INTEGER (0..127) OPTIONAL,
+ i10 INTEGER (0..127) OPTIONAL,
+ i11 INTEGER (0..127) OPTIONAL,
+ i12 INTEGER (0..127) OPTIONAL,
+ i13 INTEGER (0..127) OPTIONAL,
+ i14 INTEGER (0..127) OPTIONAL,
+ i15 INTEGER (0..127) OPTIONAL,
+ i16 INTEGER (0..127) OPTIONAL,
+ i17 INTEGER (0..127) OPTIONAL,
+ i18 INTEGER (0..127) OPTIONAL,
+ i19 INTEGER (0..127) OPTIONAL,
+ i20 INTEGER (0..127) OPTIONAL,
+ i21 INTEGER (0..127) OPTIONAL,
+ i22 INTEGER (0..127) OPTIONAL,
+ i23 INTEGER (0..127) OPTIONAL,
+ i24 INTEGER (0..127) OPTIONAL,
+ i25 INTEGER (0..127) OPTIONAL,
+ i26 INTEGER (0..127) OPTIONAL,
+ i27 INTEGER (0..127) OPTIONAL,
+ i28 INTEGER (0..127) OPTIONAL,
+ i29 INTEGER (0..127) OPTIONAL,
+ i30 INTEGER (0..127) OPTIONAL,
+ i31 INTEGER (0..127) OPTIONAL,
+ i32 INTEGER (0..127) OPTIONAL,
+ i33 INTEGER (0..127) OPTIONAL,
+ i34 INTEGER (0..127) OPTIONAL,
+ i35 INTEGER (0..127) OPTIONAL,
+ i36 INTEGER (0..127) OPTIONAL,
+ i37 INTEGER (0..127) OPTIONAL,
+ i38 INTEGER (0..127) OPTIONAL,
+ i39 INTEGER (0..127) OPTIONAL,
+ i40 INTEGER (0..127) OPTIONAL,
+ i41 INTEGER (0..127) OPTIONAL,
+ i42 INTEGER (0..127) OPTIONAL,
+ i43 INTEGER (0..127) OPTIONAL,
+ i44 INTEGER (0..127) OPTIONAL,
+ i45 INTEGER (0..127) OPTIONAL,
+ i46 INTEGER (0..127) OPTIONAL,
+ i47 INTEGER (0..127) OPTIONAL,
+ i48 INTEGER (0..127) OPTIONAL,
+ i49 INTEGER (0..127) OPTIONAL,
+ i50 INTEGER (0..127) OPTIONAL,
+ i51 INTEGER (0..127) OPTIONAL,
+ i52 INTEGER (0..127) OPTIONAL,
+ i53 INTEGER (0..127) OPTIONAL,
+ i54 INTEGER (0..127) OPTIONAL,
+ i55 INTEGER (0..127) OPTIONAL,
+ i56 INTEGER (0..127) OPTIONAL,
+ i57 INTEGER (0..127) OPTIONAL,
+ i58 INTEGER (0..127) OPTIONAL,
+ i59 INTEGER (0..127) OPTIONAL,
+ i60 INTEGER (0..127) OPTIONAL,
+ i61 INTEGER (0..127) OPTIONAL,
+ i62 INTEGER (0..127) OPTIONAL,
+ i63 INTEGER (0..127) OPTIONAL,
+ i64 INTEGER (0..127) OPTIONAL,
+ i65 INTEGER (0..127) OPTIONAL
+}
+
+SeqExt130 ::= SEQUENCE {
+ ...,
+ i0 INTEGER (0..255) OPTIONAL,
+ i1 INTEGER (0..255) OPTIONAL,
+ i2 INTEGER (0..255) OPTIONAL,
+ i3 INTEGER (0..255) OPTIONAL,
+ i4 INTEGER (0..255) OPTIONAL,
+ i5 INTEGER (0..255) OPTIONAL,
+ i6 INTEGER (0..255) OPTIONAL,
+ i7 INTEGER (0..255) OPTIONAL,
+ i8 INTEGER (0..255) OPTIONAL,
+ i9 INTEGER (0..255) OPTIONAL,
+ i10 INTEGER (0..255) OPTIONAL,
+ i11 INTEGER (0..255) OPTIONAL,
+ i12 INTEGER (0..255) OPTIONAL,
+ i13 INTEGER (0..255) OPTIONAL,
+ i14 INTEGER (0..255) OPTIONAL,
+ i15 INTEGER (0..255) OPTIONAL,
+ i16 INTEGER (0..255) OPTIONAL,
+ i17 INTEGER (0..255) OPTIONAL,
+ i18 INTEGER (0..255) OPTIONAL,
+ i19 INTEGER (0..255) OPTIONAL,
+ i20 INTEGER (0..255) OPTIONAL,
+ i21 INTEGER (0..255) OPTIONAL,
+ i22 INTEGER (0..255) OPTIONAL,
+ i23 INTEGER (0..255) OPTIONAL,
+ i24 INTEGER (0..255) OPTIONAL,
+ i25 INTEGER (0..255) OPTIONAL,
+ i26 INTEGER (0..255) OPTIONAL,
+ i27 INTEGER (0..255) OPTIONAL,
+ i28 INTEGER (0..255) OPTIONAL,
+ i29 INTEGER (0..255) OPTIONAL,
+ i30 INTEGER (0..255) OPTIONAL,
+ i31 INTEGER (0..255) OPTIONAL,
+ i32 INTEGER (0..255) OPTIONAL,
+ i33 INTEGER (0..255) OPTIONAL,
+ i34 INTEGER (0..255) OPTIONAL,
+ i35 INTEGER (0..255) OPTIONAL,
+ i36 INTEGER (0..255) OPTIONAL,
+ i37 INTEGER (0..255) OPTIONAL,
+ i38 INTEGER (0..255) OPTIONAL,
+ i39 INTEGER (0..255) OPTIONAL,
+ i40 INTEGER (0..255) OPTIONAL,
+ i41 INTEGER (0..255) OPTIONAL,
+ i42 INTEGER (0..255) OPTIONAL,
+ i43 INTEGER (0..255) OPTIONAL,
+ i44 INTEGER (0..255) OPTIONAL,
+ i45 INTEGER (0..255) OPTIONAL,
+ i46 INTEGER (0..255) OPTIONAL,
+ i47 INTEGER (0..255) OPTIONAL,
+ i48 INTEGER (0..255) OPTIONAL,
+ i49 INTEGER (0..255) OPTIONAL,
+ i50 INTEGER (0..255) OPTIONAL,
+ i51 INTEGER (0..255) OPTIONAL,
+ i52 INTEGER (0..255) OPTIONAL,
+ i53 INTEGER (0..255) OPTIONAL,
+ i54 INTEGER (0..255) OPTIONAL,
+ i55 INTEGER (0..255) OPTIONAL,
+ i56 INTEGER (0..255) OPTIONAL,
+ i57 INTEGER (0..255) OPTIONAL,
+ i58 INTEGER (0..255) OPTIONAL,
+ i59 INTEGER (0..255) OPTIONAL,
+ i60 INTEGER (0..255) OPTIONAL,
+ i61 INTEGER (0..255) OPTIONAL,
+ i62 INTEGER (0..255) OPTIONAL,
+ i63 INTEGER (0..255) OPTIONAL,
+ i64 INTEGER (0..255) OPTIONAL,
+ i65 INTEGER (0..255) OPTIONAL,
+ i66 INTEGER (0..255) OPTIONAL,
+ i67 INTEGER (0..255) OPTIONAL,
+ i68 INTEGER (0..255) OPTIONAL,
+ i69 INTEGER (0..255) OPTIONAL,
+ i70 INTEGER (0..255) OPTIONAL,
+ i71 INTEGER (0..255) OPTIONAL,
+ i72 INTEGER (0..255) OPTIONAL,
+ i73 INTEGER (0..255) OPTIONAL,
+ i74 INTEGER (0..255) OPTIONAL,
+ i75 INTEGER (0..255) OPTIONAL,
+ i76 INTEGER (0..255) OPTIONAL,
+ i77 INTEGER (0..255) OPTIONAL,
+ i78 INTEGER (0..255) OPTIONAL,
+ i79 INTEGER (0..255) OPTIONAL,
+ i80 INTEGER (0..255) OPTIONAL,
+ i81 INTEGER (0..255) OPTIONAL,
+ i82 INTEGER (0..255) OPTIONAL,
+ i83 INTEGER (0..255) OPTIONAL,
+ i84 INTEGER (0..255) OPTIONAL,
+ i85 INTEGER (0..255) OPTIONAL,
+ i86 INTEGER (0..255) OPTIONAL,
+ i87 INTEGER (0..255) OPTIONAL,
+ i88 INTEGER (0..255) OPTIONAL,
+ i89 INTEGER (0..255) OPTIONAL,
+ i90 INTEGER (0..255) OPTIONAL,
+ i91 INTEGER (0..255) OPTIONAL,
+ i92 INTEGER (0..255) OPTIONAL,
+ i93 INTEGER (0..255) OPTIONAL,
+ i94 INTEGER (0..255) OPTIONAL,
+ i95 INTEGER (0..255) OPTIONAL,
+ i96 INTEGER (0..255) OPTIONAL,
+ i97 INTEGER (0..255) OPTIONAL,
+ i98 INTEGER (0..255) OPTIONAL,
+ i99 INTEGER (0..255) OPTIONAL,
+ i100 INTEGER (0..255) OPTIONAL,
+ i101 INTEGER (0..255) OPTIONAL,
+ i102 INTEGER (0..255) OPTIONAL,
+ i103 INTEGER (0..255) OPTIONAL,
+ i104 INTEGER (0..255) OPTIONAL,
+ i105 INTEGER (0..255) OPTIONAL,
+ i106 INTEGER (0..255) OPTIONAL,
+ i107 INTEGER (0..255) OPTIONAL,
+ i108 INTEGER (0..255) OPTIONAL,
+ i109 INTEGER (0..255) OPTIONAL,
+ i110 INTEGER (0..255) OPTIONAL,
+ i111 INTEGER (0..255) OPTIONAL,
+ i112 INTEGER (0..255) OPTIONAL,
+ i113 INTEGER (0..255) OPTIONAL,
+ i114 INTEGER (0..255) OPTIONAL,
+ i115 INTEGER (0..255) OPTIONAL,
+ i116 INTEGER (0..255) OPTIONAL,
+ i117 INTEGER (0..255) OPTIONAL,
+ i118 INTEGER (0..255) OPTIONAL,
+ i119 INTEGER (0..255) OPTIONAL,
+ i120 INTEGER (0..255) OPTIONAL,
+ i121 INTEGER (0..255) OPTIONAL,
+ i122 INTEGER (0..255) OPTIONAL,
+ i123 INTEGER (0..255) OPTIONAL,
+ i124 INTEGER (0..255) OPTIONAL,
+ i125 INTEGER (0..255) OPTIONAL,
+ i126 INTEGER (0..255) OPTIONAL,
+ i127 INTEGER (0..255) OPTIONAL,
+ i128 INTEGER (0..255) OPTIONAL,
+ i129 INTEGER (0..255) OPTIONAL
+}
+
+END
diff --git a/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl
index 00e4c707dd..8e21e6ca84 100644
--- a/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl
+++ b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl
@@ -34,6 +34,9 @@ run(Erule) ->
run3(),
run3(Erule),
+ roundtrip('InlinedSeq', #'InlinedSeq'{s=#'InlinedSeq_s'{a=42,b=true}}),
+ roundtrip('ExtAddGroup1', #'ExtAddGroup1'{x=42,y=1023}),
+
ok.
%% From X.691 (07/2002) A.4.
diff --git a/lib/asn1/test/asn1_test_lib.erl b/lib/asn1/test/asn1_test_lib.erl
index b839dfcf2a..7d7364e2a4 100644
--- a/lib/asn1/test/asn1_test_lib.erl
+++ b/lib/asn1/test/asn1_test_lib.erl
@@ -22,6 +22,7 @@
-export([compile/3]).
-export([compile_all/3]).
-export([compile_erlang/3]).
+-export([hex_to_bin/1]).
-export([ticket_7407_compile/2,ticket_7407_code/1, ticket_7678/2,
ticket_7708/2, ticket_7763/1, ticket_7876/3]).
@@ -61,6 +62,13 @@ compile_erlang(Mod, Config, Options) ->
{ok, M} = compile:file(filename:join(DataDir, Mod),
[report,{i,CaseDir},{outdir,CaseDir}|Options]).
+hex_to_bin(S) ->
+ << <<(hex2num(C)):4>> || C <- S, C =/= $\s >>.
+
+%%%
+%%% Internal functions.
+%%%
+
should_load(File, Options) ->
case lists:member(abs, Options) of
true ->
@@ -79,6 +87,10 @@ strip_extension(File, Ext) when Ext == ".asn"; Ext == ".set"; Ext == ".asn1"->
strip_extension(File, _Ext) ->
File.
+hex2num(C) when $0 =< C, C =< $9 -> C - $0;
+hex2num(C) when $A =< C, C =< $F -> C - $A + 10;
+hex2num(C) when $a =< C, C =< $f -> C - $a + 10.
+
ticket_7407_compile(Config,Option) ->
?line DataDir = ?config(data_dir,Config),
diff --git a/lib/asn1/test/testConstraints.erl b/lib/asn1/test/testConstraints.erl
index e825302629..14e508d2b5 100644
--- a/lib/asn1/test/testConstraints.erl
+++ b/lib/asn1/test/testConstraints.erl
@@ -126,19 +126,29 @@ int_constraints(Rules) ->
%%==========================================================
roundtrip('SemiConstrained', 100),
+ v_roundtrip(Rules, 'SemiConstrained', 100+128),
roundtrip('SemiConstrained', 397249742397243),
+ roundtrip('SemiConstrained', 100 + 1 bsl 128*8),
+ roundtrip('SemiConstrained', 100 + 1 bsl 256*8),
+
roundtrip('NegSemiConstrained', -128),
+ v_roundtrip(Rules, 'NegSemiConstrained', 0),
roundtrip('NegSemiConstrained', -1),
roundtrip('NegSemiConstrained', 500),
roundtrip('SemiConstrainedExt', -65536),
roundtrip('SemiConstrainedExt', 0),
roundtrip('SemiConstrainedExt', 42),
+ v_roundtrip(Rules, 'SemiConstrainedExt', 42+128),
roundtrip('SemiConstrainedExt', 100),
roundtrip('SemiConstrainedExt', 47777789),
+ roundtrip('SemiConstrainedExt', 42 + 1 bsl 128*8),
+ roundtrip('SemiConstrainedExt', 42 + 1 bsl 256*8),
+
roundtrip('NegSemiConstrainedExt', -1023),
roundtrip('NegSemiConstrainedExt', -128),
roundtrip('NegSemiConstrainedExt', -1),
+ v_roundtrip(Rules, 'NegSemiConstrainedExt', 0),
roundtrip('NegSemiConstrainedExt', 500),
%%==========================================================
@@ -174,6 +184,21 @@ int_constraints(Rules) ->
ok.
+%% PER: Ensure that if the lower bound is Lb, Lb+16#80 is encoded
+%% in two bytes as 16#0180. (Not in three bytes as 16#010080.)
+v(ber, 'SemiConstrained', 100+128) -> "020200E4";
+v(per, 'SemiConstrained', 100+128) -> "0180";
+v(uper, 'SemiConstrained', 100+128) -> "0180";
+v(ber, 'NegSemiConstrained', 0) -> "020100";
+v(per, 'NegSemiConstrained', 0) -> "0180";
+v(uper, 'NegSemiConstrained', 0) -> "0180";
+v(ber, 'SemiConstrainedExt', 42+128) -> "020200AA";
+v(per, 'SemiConstrainedExt', 42+128) -> "000180";
+v(uper, 'SemiConstrainedExt', 42+128) -> "00C000";
+v(ber, 'NegSemiConstrainedExt', 0) -> "020100";
+v(per, 'NegSemiConstrainedExt', 0) -> "000180";
+v(uper, 'NegSemiConstrainedExt', 0) -> "00C000".
+
shorter_ext(per, "a") -> <<16#80,16#01,16#61>>;
shorter_ext(uper, "a") -> <<16#80,16#E1>>;
shorter_ext(ber, _) -> none.
@@ -183,13 +208,17 @@ refed_NNL_name(_Erule) ->
?line {error,_Reason} =
asn1_wrapper:encode('Constraints','AnotherThing',fred3).
+v_roundtrip(Erule, Type, Value) ->
+ Encoded = asn1_test_lib:hex_to_bin(v(Erule, Type, Value)),
+ Encoded = roundtrip('Constraints', Type, Value).
+
roundtrip(Type, Value) ->
roundtrip('Constraints', Type, Value).
roundtrip(Module, Type, Value) ->
{ok,Encoded} = Module:encode(Type, Value),
{ok,Value} = Module:decode(Type, Encoded),
- ok.
+ Encoded.
roundtrip_enc(Type, Value, Enc) ->
Module = 'Constraints',
diff --git a/lib/asn1/test/testEnumExt.erl b/lib/asn1/test/testEnumExt.erl
index 8840ed6d2f..8779f3b83b 100644
--- a/lib/asn1/test/testEnumExt.erl
+++ b/lib/asn1/test/testEnumExt.erl
@@ -38,7 +38,7 @@ main(Rule) when Rule =:= per; Rule =:= uper ->
%% ENUMERATED no extensionmark
B64 = <<64>>,
B64 = roundtrip('Noext', red),
- common();
+ common(Rule);
main(ber) ->
io:format("main(ber)~n",[]),
%% ENUMERATED with extensionmark (value is in root set)
@@ -56,18 +56,38 @@ main(ber) ->
roundtrip('Globalstate', preop),
roundtrip('Globalstate', com),
- common().
+ common(ber).
-common() ->
+common(Erule) ->
roundtrip('Seq', {'Seq',blue,42}),
roundtrip('Seq', {'Seq',red,42}),
roundtrip('Seq', {'Seq',green,42}),
roundtrip('Seq', {'Seq',orange,47}),
roundtrip('Seq', {'Seq',black,4711}),
roundtrip('Seq', {'Seq',magenta,4712}),
+
+ [begin
+ S = io_lib:format("e~2.016.0b", [I]),
+ E = list_to_atom(lists:flatten(S)),
+ roundtrip('SeqBig', {'SeqBig',true,E,9357})
+ end || I <- lists:seq(0, 128)],
+
+ v_roundtrip(Erule, 'SeqBig', {'SeqBig',true,e40,9357}),
+ v_roundtrip(Erule, 'SeqBig', {'SeqBig',true,e80,9357}),
ok.
roundtrip(Type, Value) ->
{ok,Encoded} = 'EnumExt':encode(Type, Value),
{ok,Value} = 'EnumExt':decode(Type, Encoded),
Encoded.
+
+v_roundtrip(Erule, Type, Value) ->
+ Encoded = roundtrip(Type, Value),
+ Encoded = asn1_test_lib:hex_to_bin(v(Erule, Value)).
+
+v(ber, {'SeqBig',true,e40,9357}) -> "300A8001 FF810141 8202248D";
+v(ber, {'SeqBig',true,e80,9357}) -> "300B8001 FF810200 81820224 8D";
+v(per, {'SeqBig',true,e40,9357}) -> "E0014002 248D";
+v(per, {'SeqBig',true,e80,9357}) -> "E0018002 248D";
+v(uper, {'SeqBig',true,e40,9357}) -> "E0280044 91A0";
+v(uper, {'SeqBig',true,e80,9357}) -> "E0300044 91A0".
diff --git a/lib/asn1/test/testSeqExtension.erl b/lib/asn1/test/testSeqExtension.erl
index 1128d9a7c3..724f485fa0 100644
--- a/lib/asn1/test/testSeqExtension.erl
+++ b/lib/asn1/test/testSeqExtension.erl
@@ -20,7 +20,7 @@
-module(testSeqExtension).
-include("External.hrl").
--export([main/2]).
+-export([main/3]).
-include_lib("test_server/include/test_server.hrl").
@@ -32,7 +32,7 @@
-record('SeqExt6',{i1,i2,i3,i4,i5,i6,i7}).
-record('SuperSeq',{s1,s2,s3,s4,s5,s6,i}).
-main(DataDir, Opts) ->
+main(Erule, DataDir, Opts) ->
roundtrip('SeqExt1', #'SeqExt1'{}),
roundtrip('SeqExt2', #'SeqExt2'{bool=true,int=99}),
@@ -92,9 +92,38 @@ main(DataDir, Opts) ->
s5={'SeqExt5'},
s6={'SeqExt6',531,601,999,777,11953},
i=BigInt} = DecodedSuperSeq,
+
+
+ %% Test more than 64 extensions.
+ roundtrip2('SeqExt66',
+ list_to_tuple(['SeqExt66'|lists:seq(0, 65)])),
+ v_roundtrip2(Erule, 'SeqExt66',
+ list_to_tuple(['SeqExt66'|
+ lists:duplicate(65, asn1_NOVALUE)++[125]])),
+ roundtrip2('SeqExt130',
+ list_to_tuple(['SeqExt130'|lists:seq(0, 129)])),
+ v_roundtrip2(Erule, 'SeqExt130',
+ list_to_tuple(['SeqExt130'|
+ lists:duplicate(129, asn1_NOVALUE)++[199]])),
ok.
roundtrip(Type, Value) ->
{ok,Encoded} = 'SeqExtension':encode(Type, Value),
{ok,Value} = 'SeqExtension':decode(Type, Encoded),
ok.
+
+v_roundtrip2(Erule, Type, Value) ->
+ Encoded = asn1_test_lib:hex_to_bin(v(Erule, Type)),
+ Encoded = roundtrip2(Type, Value).
+
+roundtrip2(Type, Value) ->
+ {ok,Encoded} = 'SeqExtension2':encode(Type, Value),
+ {ok,Value} = 'SeqExtension2':decode(Type, Encoded),
+ Encoded.
+
+v(ber, 'SeqExt66') -> "30049F41 017D";
+v(per, 'SeqExt66') -> "C0420000 00000000 00004001 FA";
+v(uper, 'SeqExt66') -> "D0800000 00000000 00101FA0";
+v(ber, 'SeqExt130') -> "30069F81 010200C7";
+v(per, 'SeqExt130') -> "C0808200 00000000 00000000 00000000 00000040 01C7";
+v(uper, 'SeqExt130') -> "E0208000 00000000 00000000 00000000 0000101C 70".
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 98ebb21f29..00abeb9990 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -142,6 +142,19 @@
(s)[3] = (char)((i) & 0xff);\
}
+/* This shall correspond to the similar macro in crypto.erl */
+/* Current value is: erlang:system_info(context_reductions) * 10 */
+#define MAX_BYTES_TO_NIF 20000
+
+#define CONSUME_REDS(NifEnv, Ibin) \
+do { \
+ int _cost = ((Ibin).size * 100) / MAX_BYTES_TO_NIF;\
+ if (_cost) { \
+ (void) enif_consume_timeslice((NifEnv), \
+ (_cost > 100) ? 100 : _cost); \
+ } \
+ } while (0)
+
/* NIF interface declarations */
static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info);
@@ -208,7 +221,7 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -338,7 +351,7 @@ static ErlNifFunc nif_funcs[] = {
{"dss_verify_nif", 4, dss_verify_nif},
{"rsa_verify_nif", 4, rsa_verify_nif},
{"aes_cbc_crypt", 4, aes_cbc_crypt},
- {"exor", 2, exor},
+ {"do_exor", 2, do_exor},
{"rc4_encrypt", 2, rc4_encrypt},
{"rc4_set_key", 1, rc4_set_key},
{"rc4_encrypt_with_state", 2, rc4_encrypt_with_state},
@@ -778,6 +791,7 @@ static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
}
MD5((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,MD5_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
}
static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -799,6 +813,7 @@ static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
new_ctx = (MD5_CTX*) enif_make_new_binary(env,MD5_CTX_LEN, &ret);
memcpy(new_ctx, ctx_bin.data, MD5_CTX_LEN);
MD5_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
}
static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -820,10 +835,11 @@ static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
ERL_NIF_TERM ret;
if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ return enif_make_badarg(env);
}
RIPEMD160((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,RIPEMD160_LEN, &ret));
+ enif_make_new_binary(env,RIPEMD160_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
}
static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -838,13 +854,14 @@ static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TER
ErlNifBinary ctx_bin, data_bin;
ERL_NIF_TERM ret;
if (!enif_inspect_binary(env, argv[0], &ctx_bin)
- || ctx_bin.size != RIPEMD160_CTX_LEN
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
+ || ctx_bin.size != RIPEMD160_CTX_LEN
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
}
new_ctx = (RIPEMD160_CTX*) enif_make_new_binary(env,RIPEMD160_CTX_LEN, &ret);
memcpy(new_ctx, ctx_bin.data, RIPEMD160_CTX_LEN);
RIPEMD160_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env, data_bin);
return ret;
}
static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -853,7 +870,7 @@ static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM
RIPEMD160_CTX ctx_clone;
ERL_NIF_TERM ret;
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN) {
- return enif_make_badarg(env);
+ return enif_make_badarg(env);
}
memcpy(&ctx_clone, ctx_bin.data, RIPEMD160_CTX_LEN); /* writable */
RIPEMD160_Final(enif_make_new_binary(env, RIPEMD160_LEN, &ret), &ctx_clone);
@@ -871,6 +888,7 @@ static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
}
SHA1((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,SHA_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
}
static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -891,6 +909,7 @@ static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
new_ctx = (SHA_CTX*) enif_make_new_binary(env,SHA_CTX_LEN, &ret);
memcpy(new_ctx, ctx_bin.data, SHA_CTX_LEN);
SHA1_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
}
static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -917,6 +936,7 @@ static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
}
SHA224((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,SHA224_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
#else
return atom_notsup;
@@ -945,6 +965,7 @@ static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret);
memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX));
SHA224_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
#else
return atom_notsup;
@@ -978,6 +999,7 @@ static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
}
SHA256((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,SHA256_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
#else
return atom_notsup;
@@ -1006,6 +1028,7 @@ static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret);
memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX));
SHA256_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
#else
return atom_notsup;
@@ -1039,6 +1062,7 @@ static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
}
SHA384((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,SHA384_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
#else
return atom_notsup;
@@ -1067,6 +1091,7 @@ static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret);
memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX));
SHA384_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
#else
return atom_notsup;
@@ -1100,6 +1125,7 @@ static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
}
SHA512((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,SHA512_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
#else
return atom_notsup;
@@ -1128,6 +1154,7 @@ static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret);
memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX));
SHA512_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
#else
return atom_notsup;
@@ -1161,6 +1188,7 @@ static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
}
MD4((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,MD4_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
}
static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -1181,6 +1209,7 @@ static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
new_ctx = (MD4_CTX*) enif_make_new_binary(env,MD4_CTX_LEN, &ret);
memcpy(new_ctx, ctx_bin.data, MD4_CTX_LEN);
MD4_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
}
static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -1210,6 +1239,7 @@ static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
}
hmac_md5(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret), hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
}
@@ -1228,6 +1258,7 @@ static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
hmac_sha1(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret),
hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
}
@@ -1247,6 +1278,7 @@ static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
hmac_sha224(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret),
hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
#else
return atom_notsup;
@@ -1269,6 +1301,7 @@ static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
hmac_sha256(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret),
hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
#else
return atom_notsup;
@@ -1291,6 +1324,7 @@ static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
hmac_sha384(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret),
hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
#else
return atom_notsup;
@@ -1314,6 +1348,7 @@ static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
hmac_sha512(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret),
hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
#else
return atom_notsup;
@@ -1371,6 +1406,7 @@ static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
ctx_buf = enif_make_new_binary(env, sizeof(HMAC_CTX), &ret);
memcpy(ctx_buf, context.data, context.size);
HMAC_Update((HMAC_CTX *)ctx_buf, data.data, data.size);
+ CONSUME_REDS(env,data);
return ret;
}
@@ -1427,6 +1463,7 @@ static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
DES_set_key((const_DES_cblock*)key.data, &schedule);
DES_ncbc_encrypt(text.data, enif_make_new_binary(env, text.size, &ret),
text.size, &schedule, &ivec_clone, (argv[3] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
}
@@ -1446,6 +1483,7 @@ static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
DES_set_key((const_DES_cblock*)key.data, &schedule);
DES_cfb_encrypt(text.data, enif_make_new_binary(env, text.size, &ret),
8, text.size, &schedule, &ivec_clone, (argv[3] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
}
@@ -1462,6 +1500,7 @@ static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
DES_ecb_encrypt((const_DES_cblock*)text.data,
(DES_cblock*)enif_make_new_binary(env, 8, &ret),
&schedule, (argv[2] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
}
@@ -1488,6 +1527,7 @@ static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_T
DES_ede3_cbc_encrypt(text.data, enif_make_new_binary(env,text.size,&ret),
text.size, &schedule1, &schedule2, &schedule3,
&ivec_clone, (argv[5] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
}
@@ -1514,6 +1554,7 @@ static ERL_NIF_TERM des_ede3_cfb_crypt_nif(ErlNifEnv* env, int argc, const ERL_N
DES_ede3_cfb_encrypt(text.data, enif_make_new_binary(env,text.size,&ret),
8, text.size, &schedule1, &schedule2, &schedule3,
&ivec_clone, (argv[5] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
#else
return atom_notsup;
@@ -1540,6 +1581,7 @@ static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE
enif_make_new_binary(env, text.size, &ret),
text.size, &aes_key, ivec_clone, &new_ivlen,
(argv[3] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
}
@@ -1565,6 +1607,7 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
AES_ctr128_encrypt((unsigned char *) text.data,
enif_make_new_binary(env, text.size, &ret),
text.size, &aes_key, ivec_clone, ecount_buf, &num);
+ CONSUME_REDS(env,text);
/* To do an incremental {en|de}cryption, the state to to keep between calls
must include ivec_clone, ecount_buf and num. */
@@ -1608,6 +1651,7 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N
num2_term = enif_make_uint(env, num);
new_state_term = enif_make_tuple4(env, state_term[0], ivec2_term, ecount2_term, num2_term);
ret = enif_make_tuple2(env, new_state_term, cipher_term);
+ CONSUME_REDS(env,text_bin);
return ret;
}
@@ -2055,10 +2099,11 @@ static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
ret_ptr = enif_make_new_binary(env, data_bin.size, &ret);
memcpy(ivec, ivec_bin.data, 16); /* writable copy */
AES_cbc_encrypt(data_bin.data, ret_ptr, data_bin.size, &aes_key, ivec, i);
+ CONSUME_REDS(env,data_bin);
return ret;
}
-static ERL_NIF_TERM exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Data1, Data2) */
ErlNifBinary d1, d2;
unsigned char* ret_ptr;
@@ -2075,6 +2120,7 @@ static ERL_NIF_TERM exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
for (i=0; i<d1.size; i++) {
ret_ptr[i] = d1.data[i] ^ d2.data[i];
}
+ CONSUME_REDS(env,d1);
return ret;
}
@@ -2091,6 +2137,7 @@ static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
RC4_set_key(&rc4_key, key.size, key.data);
RC4(&rc4_key, data.size, data.data,
enif_make_new_binary(env, data.size, &ret));
+ CONSUME_REDS(env,data);
return ret;
}
@@ -2123,7 +2170,7 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N
memcpy(rc4_key, state.data, sizeof(RC4_KEY));
RC4(rc4_key, data.size, data.data,
enif_make_new_binary(env, data.size, &new_data));
-
+ CONSUME_REDS(env,data);
return enif_make_tuple2(env,new_state,new_data);
}
@@ -2150,6 +2197,7 @@ static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
data_bin.size, &rc2_key,
iv_copy,
(argv[3] == atom_true));
+ CONSUME_REDS(env,data_bin);
return ret;
}
@@ -2781,6 +2829,7 @@ static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
BF_cfb64_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
data_bin.size, &bf_key, bf_tkey, &bf_n,
(argv[3] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
+ CONSUME_REDS(env,data_bin);
return ret;
}
@@ -2804,6 +2853,7 @@ static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
BF_cbc_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
data_bin.size, &bf_key, bf_tkey,
(argv[3] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
+ CONSUME_REDS(env,data_bin);
return ret;
}
@@ -2821,6 +2871,7 @@ static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
BF_set_key(&bf_key, key_bin.size, key_bin.data);
BF_ecb_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
&bf_key, (argv[2] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
+ CONSUME_REDS(env,data_bin);
return ret;
}
@@ -2843,6 +2894,7 @@ static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_N
memcpy(bf_tkey, ivec_bin.data, 8);
BF_ofb64_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
data_bin.size, &bf_key, bf_tkey, &bf_n);
+ CONSUME_REDS(env,data_bin);
return ret;
}
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 2df407018e..99d167bfa9 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -208,7 +208,7 @@
</type>
<desc>
<p>Computes the shared secret from the private key and the other party's public key.
- See also <seealso marker="public_key:public_key#compute_key/2">public_key:compute_key/2</seealso>
+ See also <seealso marker="public_key:public_key#compute_key-2">public_key:compute_key/2</seealso>
</p>
</desc>
</func>
@@ -240,7 +240,7 @@
</type>
<desc>
<p>Generates public keys of type <c>Type</c>.
- See also <seealso marker="public_key:public_key#generate_key/1">public_key:generate_key/1</seealso>
+ See also <seealso marker="public_key:public_key#generate_key-1">public_key:generate_key/1</seealso>
</p>
</desc>
</func>
@@ -269,7 +269,7 @@
<desc>
<p>Initializes the context for streaming hash operations. <c>Type</c> determines
which digest to use. The returned context should be used as argument
- to <seealso marker="#hash_update/2">hash_update</seealso>.</p>
+ to <seealso marker="#hash_update-2">hash_update</seealso>.</p>
<p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
is not supported by the underlying OpenSSL implementation.</p>
</desc>
@@ -283,10 +283,10 @@
</type>
<desc>
<p>Updates the digest represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c>
- must have been generated using <seealso marker="#hash_init/1">hash_init</seealso>
+ must have been generated using <seealso marker="#hash_init-1">hash_init</seealso>
or a previous call to this function. <c>Data</c> can be any length. <c>NewContext</c>
must be passed into the next call to <c>hash_update</c>
- or <seealso marker="#hash_final/1">hash_final</seealso>.</p>
+ or <seealso marker="#hash_final-1">hash_final</seealso>.</p>
</desc>
</func>
<func>
@@ -297,7 +297,7 @@
</type>
<desc>
<p>Finalizes the hash operation referenced by <c>Context</c> returned
- from a previous call to <seealso marker="#hash_update/2">hash_update</seealso>.
+ from a previous call to <seealso marker="#hash_update-2">hash_update</seealso>.
The size of <c>Digest</c> is determined by the type of hash
function used to generate it.</p>
</desc>
@@ -346,10 +346,10 @@
<desc>
<p>Updates the HMAC represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c>
must have been generated using an HMAC init function (such as
- <seealso marker="#hmac_init/2">hmac_init</seealso>). <c>Data</c> can be any length. <c>NewContext</c>
+ <seealso marker="#hmac_init-2">hmac_init</seealso>). <c>Data</c> can be any length. <c>NewContext</c>
must be passed into the next call to <c>hmac_update</c>
- or to one of the functions <seealso marker="#hmac_final/1">hmac_final</seealso> and
- <seealso marker="#hmac_final_n/1">hmac_final_n</seealso>
+ or to one of the functions <seealso marker="#hmac_final-1">hmac_final</seealso> and
+ <seealso marker="#hmac_final_n-2">hmac_final_n</seealso>
</p>
</desc>
@@ -447,36 +447,36 @@
<v>PlainText = binary()</v>
</type>
<desc>
- <p>Decrypts the <c>ChipherText</c> (usually a session key encrypted with
- <seealso marker="#public_encrypt/3">public_encrypt/3</seealso>)
- using the <c>PrivateKey</c> and returns the
- message. The <c>Padding</c> is the padding mode that was
- used to encrypt the data,
- see <seealso marker="#public_encrypt/3">public_encrypt/3</seealso>.
- See also <seealso marker="public_key:public_key#decrypt_private/2">public_key:decrypt_private/[2,3]</seealso>
+ <p>Decrypts the <c>ChipherText</c>, encrypted with
+ <seealso marker="#public_encrypt-4">public_encrypt/4</seealso> (or equivalent function)
+ using the <c>PrivateKey</c>, and returns the
+ plaintext (message digest). This is a low level signature verification operation
+ used for instance by older versions of the SSL protocol.
+ See also <seealso marker="public_key:public_key#decrypt_private-2">public_key:decrypt_private/[2,3]</seealso>
</p>
</desc>
</func>
-
+
<func>
<name>private_encrypt(Type, PlainText, PrivateKey, Padding) -> ChipherText</name>
- <fsummary>Encrypts Msg using the private Key.</fsummary>
+ <fsummary>Encrypts PlainText using the private Key.</fsummary>
<type>
<v>Type = rsa</v>
<v>PlainText = binary()</v>
+ <d> The size of the <c>PlainText</c> must be less
+ than <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is
+ used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c> is
+ used, where N is public modulus of the RSA key.</d>
<v>PrivateKey = rsa_private()</v>
<v>Padding = rsa_pkcs1_padding | rsa_no_padding</v>
<v>ChipherText = binary()</v>
</type>
<desc>
<p>Encrypts the <c>PlainText</c> using the <c>PrivateKey</c>
- and returns the cipher. The <c>Padding</c> decides what padding mode is used,
- <c>rsa_pkcs1_padding</c> is PKCS #1 v1.5 currently the most
- used mode.
- The size of the <c>Msg</c> must be less than <c>byte_size(N)-11</c> if
- <c>rsa_pkcs1_padding</c> is used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c>
- is used, where N is public modulus of the RSA key.
- See also <seealso marker="public_key:public_key#encrypt_private/2">public_key:encrypt_private/[2,3]</seealso>
+ and returns the ciphertext. This is a low level signature operation
+ used for instance by older versions of the SSL protocol. See
+ also <seealso
+ marker="public_key:public_key#encrypt_private-2">public_key:encrypt_private/[2,3]</seealso>
</p>
</desc>
</func>
@@ -491,42 +491,35 @@
<v>PlainText = binary()</v>
</type>
<desc>
- <p>Decrypts the <c>ChipherText</c> (encrypted with
- <seealso marker="#private_encrypt/3">private_encrypt/3</seealso>)
- using the <c>PrivateKey</c> and returns the
- message. The <c>Padding</c> is the padding mode that was
- used to encrypt the data,
- see <seealso marker="#private_encrypt/3">private_encrypt/3</seealso>.
- See also <seealso marker="public_key:public_key#decrypt_public/2">public_key:decrypt_public/[2,3]</seealso>
+ <p>Decrypts the <c>ChipherText</c>, encrypted with
+ <seealso marker="#private_encrypt-4">private_encrypt/4</seealso>(or equivalent function)
+ using the <c>PrivateKey</c>, and returns the
+ plaintext (message digest). This is a low level signature verification operation
+ used for instance by older versions of the SSL protocol.
+ See also <seealso marker="public_key:public_key#decrypt_public-2">public_key:decrypt_public/[2,3]</seealso>
</p>
</desc>
</func>
<func>
<name>public_encrypt(Type, PlainText, PublicKey, Padding) -> ChipherText</name>
- <fsummary>Encrypts Msg using the public Key.</fsummary>
+ <fsummary>Encrypts PlainText using the public Key.</fsummary>
<type>
<v>Type = rsa</v>
<v>PlainText = binary()</v>
+ <d> The size of the <c>PlainText</c> must be less
+ than <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is
+ used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c> is
+ used, where N is public modulus of the RSA key.</d>
<v>PublicKey = rsa_public()</v>
<v>Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding</v>
<v>ChipherText = binary()</v>
</type>
<desc>
- <p>Encrypts the <c>PlainText</c> (usually a session key) using
- the <c>PublicKey</c> and returns the <c>CipherText</c>. The
- <c>Padding</c> decides what padding mode is used,
- <c>rsa_pkcs1_padding</c> is PKCS #1 v1.5 currently the most
- used mode and <c>rsa_pkcs1_oaep_padding</c> is EME-OAEP as
- defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty encoding
- parameter. This mode is recommended for all new
- applications. The size of the <c>Msg</c> must be less than
- <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is
- used, <c>byte_size(N)-41</c> if
- <c>rsa_pkcs1_oaep_padding</c> is used and
- <c>byte_size(N)</c> if <c>rsa_no_padding</c> is used, where N is public modulus of the RSA key.
- See also <seealso
- marker="public_key:public_key#encrypt_public/2">public_key:encrypt_public/[2,3]</seealso>
+ <p>Encrypts the <c>PlainText</c> (message digest) using the <c>PublicKey</c>
+ and returns the <c>CipherText</c>. This is a low level signature operation
+ used for instance by older versions of the SSL protocol. See also <seealso
+ marker="public_key:public_key#encrypt_public-2">public_key:encrypt_public/[2,3]</seealso>
</p>
</desc>
</func>
@@ -563,9 +556,9 @@
<type>
<v>Algorithm = rsa | dss | ecdsa </v>
<v>Msg = binary() | {digest,binary()}</v>
- <d>The msg is either the binary "plain text" data to be
- signed or it is the hashed value of "plain text" i.e. the
- digest.</d>
+ <d>The msg is either the binary "cleartext" data to be
+ signed or it is the hashed value of "cleartext" i.e. the
+ digest (plaintext).</d>
<v>DigestType = digest_type()</v>
<v>Key = rsa_private() | dss_private() | [ecdh_private(),ecdh_params()]</v>
</type>
@@ -573,7 +566,7 @@
<p>Creates a digital signature.</p>
<p>Algorithm <c>dss</c> can only be used together with digest type
<c>sha</c>.</p>
- See also <seealso marker="public_key:public_key#sign/3">public_key:sign/3</seealso>
+ See also <seealso marker="public_key:public_key#sign-3">public_key:sign/3</seealso>
</desc>
</func>
@@ -617,8 +610,8 @@
</type>
<desc>
<p>Initializes the state for use in RC4 stream encryption
- <seealso marker="#stream_encrypt/2">stream_encrypt</seealso> and
- <seealso marker="#stream_decrypt/2">stream_decrypt</seealso></p>
+ <seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and
+ <seealso marker="#stream_decrypt-2">stream_decrypt</seealso></p>
</desc>
</func>
@@ -635,8 +628,8 @@
<p>Initializes the state for use in streaming AES encryption using Counter mode (CTR).
<c>Key</c> is the AES key and must be either 128, 192, or 256 bts long. <c>IVec</c> is
an arbitrary initializing vector of 128 bits (16 bytes). This state is for use with
- <seealso marker="#stream_encrypt/2">stream_encrypt</seealso> and
- <seealso marker="#stream_decrypt/2">stream_decrypt</seealso>.</p>
+ <seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and
+ <seealso marker="#stream_decrypt-2">stream_decrypt</seealso>.</p>
</desc>
</func>
@@ -650,7 +643,7 @@
<desc>
<p>Encrypts <c>PlainText</c> according to the stream cipher <c>Type</c> specified in stream_init/3.
<c>Text</c> can be any number of bytes. The initial <c>State</c> is created using
- <seealso marker="#stream_init/2">stream_init</seealso>.
+ <seealso marker="#stream_init-2">stream_init</seealso>.
<c>NewState</c> must be passed into the next call to <c>stream_encrypt</c>.</p>
</desc>
</func>
@@ -665,7 +658,7 @@
<desc>
<p>Decrypts <c>CipherText</c> according to the stream cipher <c>Type</c> specified in stream_init/3.
<c>PlainText</c> can be any number of bytes. The initial <c>State</c> is created using
- <seealso marker="#stream_init/2">stream_init</seealso>.
+ <seealso marker="#stream_init-2">stream_init</seealso>.
<c>NewState</c> must be passed into the next call to <c>stream_encrypt</c>.</p>
</desc>
</func>
@@ -692,8 +685,8 @@
<type>
<v> Algorithm = rsa | dss | ecdsa </v>
<v>Msg = binary() | {digest,binary()}</v>
- <d>The msg is either the binary "plain text" data
- or it is the hashed value of "plain text" i.e. the digest.</d>
+ <d>The msg is either the binary "cleartext" data
+ or it is the hashed value of "cleartext" i.e. the digest (plaintext).</d>
<v>DigestType = digest_type()</v>
<v>Signature = binary()</v>
<v>Key = rsa_public() | dss_public() | [ecdh_public(),ecdh_params()]</v>
@@ -703,7 +696,7 @@
<p>Algorithm <c>dss</c> can only be used together with digest type
<c>sha</c>.</p>
- See also <seealso marker="public_key:public_key#sign/3">public_key:verify/3</seealso>
+ See also <seealso marker="public_key:public_key#verify-4">public_key:verify/4</seealso>
</desc>
</func>
diff --git a/lib/crypto/src/crypto.appup.src b/lib/crypto/src/crypto.appup.src
index b39ef734eb..5b4ce5acee 100644
--- a/lib/crypto/src/crypto.appup.src
+++ b/lib/crypto/src/crypto.appup.src
@@ -1,7 +1,8 @@
+%% -*- erlang -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -17,6 +18,11 @@
%% %CopyrightEnd%
%%
{"%VSN%",
- [],
- []
-}.
+ [
+ {<<"2\\.*">>, [{restart_application, crypto}]}
+ {<<"1\\.*">>, [{restart_application, crypto}]}
+ ],
+ [
+ {<<"2\\.*">>, [{restart_application, crypto}]}
+ {<<"1\\.*">>, [{restart_application, crypto}]}
+ ]}.
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index e042545094..a093b45410 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -35,7 +35,6 @@
-export([private_encrypt/4, public_decrypt/4]).
-export([dh_generate_parameters/2, dh_check/1]). %% Testing see
-
%% DEPRECATED
%% Replaced by hash_*
-export([md4/1, md4_init/0, md4_update/2, md4_final/1]).
@@ -165,60 +164,8 @@
-export([info/0]).
-deprecated({info, 0, next_major_release}).
--define(FUNC_LIST, [hash, hash_init, hash_update, hash_final,
- hmac, hmac_init, hmac_update, hmac_final, hmac_final_n,
- %% deprecated
- md4, md4_init, md4_update, md4_final,
- md5, md5_init, md5_update, md5_final,
- sha, sha_init, sha_update, sha_final,
- md5_mac, md5_mac_96,
- sha_mac, sha_mac_96,
- %%
- block_encrypt, block_decrypt,
- %% deprecated
- des_cbc_encrypt, des_cbc_decrypt,
- des_cfb_encrypt, des_cfb_decrypt,
- des_ecb_encrypt, des_ecb_decrypt,
- des3_cbc_encrypt, des3_cbc_decrypt,
- des3_cfb_encrypt, des3_cfb_decrypt,
- aes_cfb_128_encrypt, aes_cfb_128_decrypt,
- rc2_cbc_encrypt, rc2_cbc_decrypt,
- rc2_40_cbc_encrypt, rc2_40_cbc_decrypt,
- aes_cbc_128_encrypt, aes_cbc_128_decrypt,
- aes_cbc_256_encrypt, aes_cbc_256_decrypt,
- blowfish_cbc_encrypt, blowfish_cbc_decrypt,
- blowfish_cfb64_encrypt, blowfish_cfb64_decrypt,
- blowfish_ecb_encrypt, blowfish_ecb_decrypt, blowfish_ofb64_encrypt,
- %%
- rand_bytes,
- strong_rand_bytes,
- rand_uniform,
- mod_pow,
- exor,
- %% deprecated
- mod_exp,strong_rand_mpint,erlint, mpint,
- %%
- sign, verify, generate_key, compute_key,
- %% deprecated
- dss_verify,dss_sign,
- rsa_verify,rsa_sign,
- rsa_public_encrypt,rsa_private_decrypt,
- rsa_private_encrypt,rsa_public_decrypt,
- dh_generate_key, dh_compute_key,
- %%
- stream_init, stream_encrypt, stream_decrypt,
- %% deprecated
- rc4_encrypt, rc4_set_key, rc4_encrypt_with_state,
- aes_ctr_encrypt, aes_ctr_decrypt,
- aes_ctr_stream_init, aes_ctr_stream_encrypt, aes_ctr_stream_decrypt,
- %%
- next_iv,
- %% deprecated
- aes_cbc_ivec,
- des_cbc_ivec, des_cfb_ivec,
- info,
- %%
- info_lib, supports]).
+%% This should correspond to the similar macro in crypto.c
+-define(MAX_BYTES_TO_NIF, 20000). %% Current value is: erlang:system_info(context_reductions) * 10
-type mpint() :: binary().
-type rsa_digest_type() :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'.
@@ -235,76 +182,27 @@
%%-type ec_curve() :: ec_named_curve() | ec_curve_spec().
%%-type ec_key() :: {Curve :: ec_curve(), PrivKey :: binary() | undefined, PubKey :: ec_point() | undefined}.
--define(nif_stub,nif_stub_error(?LINE)).
-
-on_load(on_load/0).
-
-define(CRYPTO_NIF_VSN,201).
-on_load() ->
- LibBaseName = "crypto",
- PrivDir = code:priv_dir(crypto),
- LibName = case erlang:system_info(build_type) of
- opt ->
- LibBaseName;
- Type ->
- LibTypeName = LibBaseName ++ "." ++ atom_to_list(Type),
- case (filelib:wildcard(
- filename:join(
- [PrivDir,
- "lib",
- LibTypeName ++ "*"])) /= []) orelse
- (filelib:wildcard(
- filename:join(
- [PrivDir,
- "lib",
- erlang:system_info(system_architecture),
- LibTypeName ++ "*"])) /= []) of
- true -> LibTypeName;
- false -> LibBaseName
- end
- end,
- Lib = filename:join([PrivDir, "lib", LibName]),
- Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,Lib}) of
- ok -> ok;
- {error, {load_failed, _}}=Error1 ->
- ArchLibDir =
- filename:join([PrivDir, "lib",
- erlang:system_info(system_architecture)]),
- Candidate =
- filelib:wildcard(filename:join([ArchLibDir,LibName ++ "*" ])),
- case Candidate of
- [] -> Error1;
- _ ->
- ArchLib = filename:join([ArchLibDir, LibName]),
- erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,ArchLib})
- end;
- Error1 -> Error1
- end,
- case Status of
- ok -> ok;
- {error, {E, Str}} ->
- error_logger:error_msg("Unable to load crypto library. Failed with error:~n\"~p, ~s\"~n"
- "OpenSSL might not be installed on this system.~n",[E,Str]),
- Status
- end.
-
+-define(nif_stub,nif_stub_error(?LINE)).
nif_stub_error(Line) ->
erlang:nif_error({nif_not_loaded,module,?MODULE,line,Line}).
+%%--------------------------------------------------------------------
+%%% API
+%%--------------------------------------------------------------------
+%% Crypto app version history:
+%% (no version): Driver implementation
+%% 2.0 : NIF implementation, requires OTP R14
+version() -> ?CRYPTO_VSN.
+
start() ->
application:start(crypto).
stop() ->
application:stop(crypto).
-info() ->
- ?FUNC_LIST.
-
-info_lib() -> ?nif_stub.
-
-algorithms() -> ?nif_stub.
-
supports()->
Algs = algorithms(),
PubKeyAlgs =
@@ -316,32 +214,20 @@ supports()->
end,
[{hashs, Algs -- [ec]},
{ciphers, [des_cbc, des_cfb, des3_cbc, des3_cbf, des_ede3, blowfish_cbc,
- blowfish_cfb64, blowfish_ofb64, blowfish_ecb, aes_cbc128, aes_cfb128, aes_cbc256, rc2_cbc, aes_ctr, rc4
+ blowfish_cfb64, blowfish_ofb64, blowfish_ecb, aes_cbc128, aes_cfb128,
+ aes_cbc256, rc2_cbc, aes_ctr, rc4
]},
PubKeyAlgs
].
-%% Crypto app version history:
-%% (no version): Driver implementation
-%% 2.0 : NIF implementation, requires OTP R14
-version() -> ?CRYPTO_VSN.
-
-%% Below Key and Data are binaries or IO-lists. IVec is a binary.
-%% Output is always a binary. Context is a binary.
-
-%%
-%% MESSAGE DIGESTS
-%%
+info_lib() -> ?nif_stub.
-spec hash(_, iodata()) -> binary().
-hash(md5, Data) -> md5(Data);
-hash(md4, Data) -> md4(Data);
-hash(sha, Data) -> sha(Data);
-hash(ripemd160, Data) -> ripemd160(Data);
-hash(sha224, Data) -> sha224(Data);
-hash(sha256, Data) -> sha256(Data);
-hash(sha384, Data) -> sha384(Data);
-hash(sha512, Data) -> sha512(Data).
+
+hash(Hash, Data0) ->
+ Data = iolist_to_binary(Data0),
+ MaxByts = max_bytes(),
+ hash(Hash, Data, erlang:byte_size(Data), MaxByts, initial).
-spec hash_init('md5'|'md4'|'ripemd160'|
'sha'|'sha224'|'sha256'|'sha384'|'sha512') -> any().
@@ -357,14 +243,10 @@ hash_init(sha512) -> {sha512, sha512_init()}.
-spec hash_update(_, iodata()) -> any().
-hash_update({md5,Context}, Data) -> {md5, md5_update(Context,Data)};
-hash_update({md4,Context}, Data) -> {md4, md4_update(Context,Data)};
-hash_update({sha,Context}, Data) -> {sha, sha_update(Context,Data)};
-hash_update({ripemd160,Context}, Data) -> {ripemd160, ripemd160_update(Context,Data)};
-hash_update({sha224,Context}, Data) -> {sha224, sha224_update(Context,Data)};
-hash_update({sha256,Context}, Data) -> {sha256, sha256_update(Context,Data)};
-hash_update({sha384,Context}, Data) -> {sha384, sha384_update(Context,Data)};
-hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data)}.
+hash_update(State, Data0) ->
+ Data = iolist_to_binary(Data0),
+ MaxBytes = max_bytes(),
+ hash_update(State, Data, erlang:byte_size(Data), MaxBytes).
-spec hash_final(_) -> binary().
@@ -377,6 +259,457 @@ hash_final({sha256,Context}) -> sha256_final(Context);
hash_final({sha384,Context}) -> sha384_final(Context);
hash_final({sha512,Context}) -> sha512_final(Context).
+
+-spec hmac(_, iodata(), iodata()) -> binary().
+-spec hmac(_, iodata(), iodata(), integer()) -> binary().
+-spec hmac_init(atom(), iodata()) -> binary().
+-spec hmac_update(binary(), iodata()) -> binary().
+-spec hmac_final(binary()) -> binary().
+-spec hmac_final_n(binary(), integer()) -> binary().
+
+hmac(Type, Key, Data0) ->
+ Data = iolist_to_binary(Data0),
+ hmac(Type, Key, Data, undefined, erlang:byte_size(Data), max_bytes(), initial).
+hmac(Type, Key, Data0, MacSize) ->
+ Data = iolist_to_binary(Data0),
+ hmac(Type, Key, Data, MacSize, erlang:byte_size(Data), max_bytes(), initial).
+
+
+hmac_init(_Type, _Key) -> ?nif_stub.
+
+hmac_update(State, Data0) ->
+ Data = iolist_to_binary(Data0),
+ hmac_update(State, Data, erlang:byte_size(Data), max_bytes()).
+hmac_final(_Context) -> ? nif_stub.
+hmac_final_n(_Context, _HashLen) -> ? nif_stub.
+
+%% Ecrypt/decrypt %%%
+
+-spec block_encrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc |
+ blowfish_cfb64 | aes_cbc128 | aes_cfb128 | aes_cbc256 | rc2_cbc,
+ Key::iodata(), Ivec::binary(), Data::iodata()) -> binary().
+
+block_encrypt(des_cbc, Key, Ivec, Data) ->
+ des_cbc_encrypt(Key, Ivec, Data);
+block_encrypt(des_cfb, Key, Ivec, Data) ->
+ des_cfb_encrypt(Key, Ivec, Data);
+block_encrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) ->
+ des3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data);
+block_encrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) ->
+ des3_cfb_encrypt(Key1, Key2, Key3, Ivec, Data);
+block_encrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) ->
+ des_ede3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data);
+block_encrypt(blowfish_cbc, Key, Ivec, Data) ->
+ blowfish_cbc_encrypt(Key, Ivec, Data);
+block_encrypt(blowfish_cfb64, Key, Ivec, Data) ->
+ blowfish_cfb64_encrypt(Key, Ivec, Data);
+block_encrypt(blowfish_ofb64, Key, Ivec, Data) ->
+ blowfish_ofb64_encrypt(Key, Ivec, Data);
+block_encrypt(aes_cbc128, Key, Ivec, Data) ->
+ aes_cbc_128_encrypt(Key, Ivec, Data);
+block_encrypt(aes_cbc256, Key, Ivec, Data) ->
+ aes_cbc_256_encrypt(Key, Ivec, Data);
+block_encrypt(aes_cfb128, Key, Ivec, Data) ->
+ aes_cfb_128_encrypt(Key, Ivec, Data);
+block_encrypt(rc2_cbc, Key, Ivec, Data) ->
+ rc2_cbc_encrypt(Key, Ivec, Data).
+
+-spec block_decrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc |
+ blowfish_cfb64 | blowfish_ofb64 | aes_cbc128 | aes_cbc256 | aes_cfb128 | rc2_cbc,
+ Key::iodata(), Ivec::binary(), Data::iodata()) -> binary().
+
+block_decrypt(des_cbc, Key, Ivec, Data) ->
+ des_cbc_decrypt(Key, Ivec, Data);
+block_decrypt(des_cfb, Key, Ivec, Data) ->
+ des_cfb_decrypt(Key, Ivec, Data);
+block_decrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) ->
+ des3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data);
+block_decrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) ->
+ des3_cfb_decrypt(Key1, Key2, Key3, Ivec, Data);
+block_decrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) ->
+ des_ede3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data);
+block_decrypt(blowfish_cbc, Key, Ivec, Data) ->
+ blowfish_cbc_decrypt(Key, Ivec, Data);
+block_decrypt(blowfish_cfb64, Key, Ivec, Data) ->
+ blowfish_cfb64_decrypt(Key, Ivec, Data);
+block_decrypt(blowfish_ofb64, Key, Ivec, Data) ->
+ blowfish_ofb64_decrypt(Key, Ivec, Data);
+block_decrypt(aes_cbc128, Key, Ivec, Data) ->
+ aes_cbc_128_decrypt(Key, Ivec, Data);
+block_decrypt(aes_cbc256, Key, Ivec, Data) ->
+ aes_cbc_256_decrypt(Key, Ivec, Data);
+block_decrypt(aes_cfb128, Key, Ivec, Data) ->
+ aes_cfb_128_decrypt(Key, Ivec, Data);
+block_decrypt(rc2_cbc, Key, Ivec, Data) ->
+ rc2_cbc_decrypt(Key, Ivec, Data).
+
+-spec block_encrypt(des_ecb | blowfish_ecb, Key::iodata(), Data::iodata()) -> binary().
+
+block_encrypt(des_ecb, Key, Data) ->
+ des_ecb_encrypt(Key, Data);
+block_encrypt(blowfish_ecb, Key, Data) ->
+ blowfish_ecb_encrypt(Key, Data).
+
+-spec block_decrypt(des_ecb | blowfish_ecb, Key::iodata(), Data::iodata()) -> binary().
+
+block_decrypt(des_ecb, Key, Data) ->
+ des_ecb_decrypt(Key, Data);
+block_decrypt(blowfish_ecb, Key, Data) ->
+ blowfish_ecb_decrypt(Key, Data).
+
+-spec next_iv(des_cbc | des3_cbc | aes_cbc, Data::iodata()) -> binary().
+
+next_iv(des_cbc, Data) ->
+ des_cbc_ivec(Data);
+next_iv(des3_cbc, Data) ->
+ des_cbc_ivec(Data);
+next_iv(aes_cbc, Data) ->
+ aes_cbc_ivec(Data).
+
+-spec next_iv(des_cfb, Data::iodata(), Ivec::binary()) -> binary().
+
+next_iv(des_cfb, Data, Ivec) ->
+ des_cfb_ivec(Ivec, Data);
+next_iv(Type, Data, _Ivec) ->
+ next_iv(Type, Data).
+
+stream_init(aes_ctr, Key, Ivec) ->
+ {aes_ctr, aes_ctr_stream_init(Key, Ivec)}.
+stream_init(rc4, Key) ->
+ {rc4, rc4_set_key(Key)}.
+
+stream_encrypt(State, Data0) ->
+ Data = iolist_to_binary(Data0),
+ MaxByts = max_bytes(),
+ stream_crypt(fun do_stream_encrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []).
+
+stream_decrypt(State, Data0) ->
+ Data = iolist_to_binary(Data0),
+ MaxByts = max_bytes(),
+ stream_crypt(fun do_stream_decrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []).
+
+%%
+%% RAND - pseudo random numbers using RN_ functions in crypto lib
+%%
+-spec rand_bytes(non_neg_integer()) -> binary().
+-spec strong_rand_bytes(non_neg_integer()) -> binary().
+-spec rand_uniform(crypto_integer(), crypto_integer()) ->
+ crypto_integer().
+
+rand_bytes(_Bytes) -> ?nif_stub.
+
+strong_rand_bytes(Bytes) ->
+ case strong_rand_bytes_nif(Bytes) of
+ false -> erlang:error(low_entropy);
+ Bin -> Bin
+ end.
+strong_rand_bytes_nif(_Bytes) -> ?nif_stub.
+
+rand_bytes(_Bytes, _Topmask, _Bottommask) -> ?nif_stub.
+
+
+rand_uniform(From,To) when is_binary(From), is_binary(To) ->
+ case rand_uniform_nif(From,To) of
+ <<Len:32/integer, MSB, Rest/binary>> when MSB > 127 ->
+ <<(Len + 1):32/integer, 0, MSB, Rest/binary>>;
+ Whatever ->
+ Whatever
+ end;
+rand_uniform(From,To) when is_integer(From),is_integer(To) ->
+ if From < 0 ->
+ rand_uniform_pos(0, To - From) + From;
+ true ->
+ rand_uniform_pos(From, To)
+ end.
+
+rand_uniform_pos(From,To) when From < To ->
+ BinFrom = mpint(From),
+ BinTo = mpint(To),
+ case rand_uniform(BinFrom, BinTo) of
+ Result when is_binary(Result) ->
+ erlint(Result);
+ Other ->
+ Other
+ end;
+rand_uniform_pos(_,_) ->
+ error(badarg).
+
+rand_uniform_nif(_From,_To) -> ?nif_stub.
+
+
+-spec mod_pow(binary()|integer(), binary()|integer(), binary()|integer()) -> binary() | error.
+mod_pow(Base, Exponent, Prime) ->
+ case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of
+ <<0>> -> error;
+ R -> R
+ end.
+verify(dss, none, Data, Signature, Key) when is_binary(Data) ->
+ verify(dss, sha, {digest, Data}, Signature, Key);
+verify(Alg, Type, Data, Signature, Key) when is_binary(Data) ->
+ verify(Alg, Type, {digest, hash(Type, Data)}, Signature, Key);
+verify(dss, Type, Data, Signature, Key) ->
+ dss_verify_nif(Type, Data, Signature, map_ensure_int_as_bin(Key));
+verify(rsa, Type, DataOrDigest, Signature, Key) ->
+ case rsa_verify_nif(Type, DataOrDigest, Signature, map_ensure_int_as_bin(Key)) of
+ notsup -> erlang:error(notsup);
+ Bool -> Bool
+ end;
+verify(ecdsa, Type, DataOrDigest, Signature, [Key, Curve]) ->
+ case ecdsa_verify_nif(Type, DataOrDigest, Signature, term_to_ec_key(Curve, undefined, Key)) of
+ notsup -> erlang:error(notsup);
+ Bool -> Bool
+ end.
+sign(dss, none, Data, Key) when is_binary(Data) ->
+ sign(dss, sha, {digest, Data}, Key);
+sign(Alg, Type, Data, Key) when is_binary(Data) ->
+ sign(Alg, Type, {digest, hash(Type, Data)}, Key);
+sign(rsa, Type, DataOrDigest, Key) ->
+ case rsa_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of
+ error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
+ Sign -> Sign
+ end;
+sign(dss, Type, DataOrDigest, Key) ->
+ case dss_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of
+ error -> erlang:error(badkey, [DataOrDigest, Key]);
+ Sign -> Sign
+ end;
+sign(ecdsa, Type, DataOrDigest, [Key, Curve]) ->
+ case ecdsa_sign_nif(Type, DataOrDigest, term_to_ec_key(Curve, Key, undefined)) of
+ error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
+ Sign -> Sign
+ end.
+
+-spec public_encrypt(rsa, binary(), [binary()], rsa_padding()) ->
+ binary().
+-spec public_decrypt(rsa, binary(), [integer() | binary()], rsa_padding()) ->
+ binary().
+-spec private_encrypt(rsa, binary(), [integer() | binary()], rsa_padding()) ->
+ binary().
+-spec private_decrypt(rsa, binary(), [integer() | binary()], rsa_padding()) ->
+ binary().
+
+public_encrypt(rsa, BinMesg, Key, Padding) ->
+ case rsa_public_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, true) of
+ error ->
+ erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
+ end.
+
+%% Binary, Key = [E,N,D]
+private_decrypt(rsa, BinMesg, Key, Padding) ->
+ case rsa_private_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, false) of
+ error ->
+ erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
+ end.
+
+
+%% Binary, Key = [E,N,D]
+private_encrypt(rsa, BinMesg, Key, Padding) ->
+ case rsa_private_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, true) of
+ error ->
+ erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
+ end.
+
+%% Binary, Key = [E,N]
+public_decrypt(rsa, BinMesg, Key, Padding) ->
+ case rsa_public_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, false) of
+ error ->
+ erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
+ end.
+
+%%
+%% XOR - xor to iolists and return a binary
+%% NB doesn't check that they are the same size, just concatenates
+%% them and sends them to the driver
+%%
+-spec exor(iodata(), iodata()) -> binary().
+
+exor(Bin1, Bin2) ->
+ Data1 = iolist_to_binary(Bin1),
+ Data2 = iolist_to_binary(Bin2),
+ MaxBytes = max_bytes(),
+ exor(Data1, Data2, erlang:byte_size(Data1), MaxBytes, []).
+
+generate_key(Type, Params) ->
+ generate_key(Type, Params, undefined).
+
+generate_key(dh, DHParameters, PrivateKey) ->
+ dh_generate_key_nif(ensure_int_as_bin(PrivateKey),
+ map_ensure_int_as_bin(DHParameters), 0);
+
+generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, PrivArg)
+ when is_binary(Verifier), is_binary(Generator), is_binary(Prime), is_atom(Version) ->
+ Private = case PrivArg of
+ undefined -> random_bytes(32);
+ _ -> ensure_int_as_bin(PrivArg)
+ end,
+ host_srp_gen_key(Private, Verifier, Generator, Prime, Version);
+
+generate_key(srp, {user, [Generator, Prime, Version]}, PrivateArg)
+ when is_binary(Generator), is_binary(Prime), is_atom(Version) ->
+ Private = case PrivateArg of
+ undefined -> random_bytes(32);
+ _ -> PrivateArg
+ end,
+ user_srp_gen_key(Private, Generator, Prime);
+
+generate_key(ecdh, Curve, undefined) ->
+ ec_key_to_term_nif(ec_key_generate(Curve)).
+
+
+compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) ->
+ case dh_compute_key_nif(ensure_int_as_bin(OthersPublicKey),
+ ensure_int_as_bin(MyPrivateKey),
+ map_ensure_int_as_bin(DHParameters)) of
+ error -> erlang:error(computation_failed,
+ [OthersPublicKey,MyPrivateKey,DHParameters]);
+ Ret -> Ret
+ end;
+
+compute_key(srp, HostPublic, {UserPublic, UserPrivate},
+ {user, [DerivedKey, Prime, Generator, Version | ScramblerArg]}) when
+ is_binary(Prime),
+ is_binary(Generator),
+ is_atom(Version) ->
+ HostPubBin = ensure_int_as_bin(HostPublic),
+ Multiplier = srp_multiplier(Version, Generator, Prime),
+ Scrambler = case ScramblerArg of
+ [] -> srp_scrambler(Version, ensure_int_as_bin(UserPublic),
+ HostPubBin, Prime);
+ [S] -> S
+ end,
+ srp_user_secret_nif(ensure_int_as_bin(UserPrivate), Scrambler, HostPubBin,
+ Multiplier, Generator, DerivedKey, Prime);
+
+compute_key(srp, UserPublic, {HostPublic, HostPrivate},
+ {host,[Verifier, Prime, Version | ScramblerArg]}) when
+ is_binary(Verifier),
+ is_binary(Prime),
+ is_atom(Version) ->
+ UserPubBin = ensure_int_as_bin(UserPublic),
+ Scrambler = case ScramblerArg of
+ [] -> srp_scrambler(Version, UserPubBin, ensure_int_as_bin(HostPublic), Prime);
+ [S] -> S
+ end,
+ srp_host_secret_nif(Verifier, ensure_int_as_bin(HostPrivate), Scrambler,
+ UserPubBin, Prime);
+
+compute_key(ecdh, Others, My, Curve) ->
+ ecdh_compute_key_nif(ensure_int_as_bin(Others),
+ term_to_ec_key(Curve,My,undefined)).
+
+
+random_bytes(N) ->
+ try strong_rand_bytes(N) of
+ RandBytes ->
+ RandBytes
+ catch
+ error:low_entropy ->
+ rand_bytes(N)
+ end.
+
+%%--------------------------------------------------------------------
+%%% On load
+%%--------------------------------------------------------------------
+
+on_load() ->
+ LibBaseName = "crypto",
+ PrivDir = code:priv_dir(crypto),
+ LibName = case erlang:system_info(build_type) of
+ opt ->
+ LibBaseName;
+ Type ->
+ LibTypeName = LibBaseName ++ "." ++ atom_to_list(Type),
+ case (filelib:wildcard(
+ filename:join(
+ [PrivDir,
+ "lib",
+ LibTypeName ++ "*"])) /= []) orelse
+ (filelib:wildcard(
+ filename:join(
+ [PrivDir,
+ "lib",
+ erlang:system_info(system_architecture),
+ LibTypeName ++ "*"])) /= []) of
+ true -> LibTypeName;
+ false -> LibBaseName
+ end
+ end,
+ Lib = filename:join([PrivDir, "lib", LibName]),
+ Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,Lib}) of
+ ok -> ok;
+ {error, {load_failed, _}}=Error1 ->
+ ArchLibDir =
+ filename:join([PrivDir, "lib",
+ erlang:system_info(system_architecture)]),
+ Candidate =
+ filelib:wildcard(filename:join([ArchLibDir,LibName ++ "*" ])),
+ case Candidate of
+ [] -> Error1;
+ _ ->
+ ArchLib = filename:join([ArchLibDir, LibName]),
+ erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,ArchLib})
+ end;
+ Error1 -> Error1
+ end,
+ case Status of
+ ok -> ok;
+ {error, {E, Str}} ->
+ error_logger:error_msg("Unable to load crypto library. Failed with error:~n\"~p, ~s\"~n"
+ "OpenSSL might not be installed on this system.~n",[E,Str]),
+ Status
+ end.
+%%--------------------------------------------------------------------
+%%% Internal functions (some internal API functions are part of the deprecated API)
+%%--------------------------------------------------------------------
+max_bytes() ->
+ ?MAX_BYTES_TO_NIF.
+
+%% HASH --------------------------------------------------------------------
+hash(Hash, Data, Size, Max, initial) when Size =< Max ->
+ do_hash(Hash, Data);
+hash(State0, Data, Size, Max, continue) when Size =< Max ->
+ State = do_hash_update(State0, Data),
+ hash_final(State);
+hash(Hash, Data, _Size, Max, initial) ->
+ <<Increment:Max/binary, Rest/binary>> = Data,
+ State0 = hash_init(Hash),
+ State = do_hash_update(State0, Increment),
+ hash(State, Rest, erlang:byte_size(Rest), max_bytes(), continue);
+hash(State0, Data, _Size, MaxByts, continue) ->
+ <<Increment:MaxByts/binary, Rest/binary>> = Data,
+ State = do_hash_update(State0, Increment),
+ hash(State, Rest, erlang:byte_size(Rest), max_bytes(), continue).
+
+do_hash(md5, Data) -> md5(Data);
+do_hash(md4, Data) -> md4(Data);
+do_hash(sha, Data) -> sha(Data);
+do_hash(ripemd160, Data) -> ripemd160(Data);
+do_hash(sha224, Data) -> sha224(Data);
+do_hash(sha256, Data) -> sha256(Data);
+do_hash(sha384, Data) -> sha384(Data);
+do_hash(sha512, Data) -> sha512(Data).
+
+hash_update(State, Data, Size, MaxBytes) when Size =< MaxBytes ->
+ do_hash_update(State, Data);
+hash_update(State0, Data, _, MaxBytes) ->
+ <<Increment:MaxBytes/binary, Rest/binary>> = Data,
+ State = do_hash_update(State0, Increment),
+ hash_update(State, Rest, erlang:byte_size(Rest), MaxBytes).
+
+do_hash_update({md5,Context}, Data) -> {md5, md5_update(Context,Data)};
+do_hash_update({md4,Context}, Data) -> {md4, md4_update(Context,Data)};
+do_hash_update({sha,Context}, Data) -> {sha, sha_update(Context,Data)};
+do_hash_update({ripemd160,Context}, Data) -> {ripemd160, ripemd160_update(Context,Data)};
+do_hash_update({sha224,Context}, Data) -> {sha224, sha224_update(Context,Data)};
+do_hash_update({sha256,Context}, Data) -> {sha256, sha256_update(Context,Data)};
+do_hash_update({sha384,Context}, Data) -> {sha384, sha384_update(Context,Data)};
+do_hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data)}.
+
+
%%
%% MD5
%%
@@ -567,40 +900,56 @@ sha512_init_nif() -> ?nif_stub.
sha512_update_nif(_Context, _Data) -> ?nif_stub.
sha512_final_nif(_Context) -> ?nif_stub.
-%%
-%% MESSAGE AUTHENTICATION CODES
-%%
-
-%%
-%% HMAC (multiple hash options)
-%%
+%% HMAC --------------------------------------------------------------------
--spec hmac(_, iodata(), iodata()) -> binary().
--spec hmac(_, iodata(), iodata(), integer()) -> binary().
--spec hmac_init(atom(), iodata()) -> binary().
--spec hmac_update(binary(), iodata()) -> binary().
--spec hmac_final(binary()) -> binary().
--spec hmac_final_n(binary(), integer()) -> binary().
-
-hmac(md5, Key, Data) -> md5_mac(Key, Data);
-hmac(sha, Key, Data) -> sha_mac(Key, Data);
-hmac(sha224, Key, Data) -> sha224_mac(Key, Data);
-hmac(sha256, Key, Data) -> sha256_mac(Key, Data);
-hmac(sha384, Key, Data) -> sha384_mac(Key, Data);
-hmac(sha512, Key, Data) -> sha512_mac(Key, Data).
-
-hmac(md5, Key, Data, Size) -> md5_mac_n(Key, Data, Size);
-hmac(sha, Key, Data, Size) -> sha_mac_n(Key, Data, Size);
-hmac(sha224, Key, Data, Size) -> sha224_mac(Key, Data, Size);
-hmac(sha256, Key, Data, Size) -> sha256_mac(Key, Data, Size);
-hmac(sha384, Key, Data, Size) -> sha384_mac(Key, Data, Size);
-hmac(sha512, Key, Data, Size) -> sha512_mac(Key, Data, Size).
+hmac(Type, Key, Data, MacSize, Size, MaxBytes, initial) when Size =< MaxBytes ->
+ case MacSize of
+ undefined ->
+ do_hmac(Type, Key, Data);
+ _ ->
+ do_hmac(Type, Key, Data, MacSize)
+ end;
+hmac(Type, Key, Data, MacSize, _, MaxBytes, initial) ->
+ <<Increment:MaxBytes/binary, Rest/binary>> = Data,
+ State0 = hmac_init(Type, Key),
+ State = hmac_update(State0, Increment),
+ hmac(State, Rest, MacSize, erlang:byte_size(Rest), max_bytes(), continue).
+hmac(State0, Data, MacSize, Size, MaxBytes, continue) when Size =< MaxBytes ->
+ State = hmac_update(State0, Data),
+ case MacSize of
+ undefined ->
+ hmac_final(State);
+ _ ->
+ hmac_final_n(State, MacSize)
+ end;
+hmac(State0, Data, MacSize, _Size, MaxBytes, continue) ->
+ <<Increment:MaxBytes/binary, Rest/binary>> = Data,
+ State = hmac_update(State0, Increment),
+ hmac(State, Rest, MacSize, erlang:byte_size(Rest), max_bytes(), continue).
+
+hmac_update(State, Data, Size, MaxBytes) when Size =< MaxBytes ->
+ do_hmac_update(State, Data);
+hmac_update(State0, Data, _, MaxBytes) ->
+ <<Increment:MaxBytes/binary, Rest/binary>> = Data,
+ State = do_hmac_update(State0, Increment),
+ hmac_update(State, Rest, erlang:byte_size(Rest), MaxBytes).
+
+do_hmac(md5, Key, Data) -> md5_mac(Key, Data);
+do_hmac(sha, Key, Data) -> sha_mac(Key, Data);
+do_hmac(sha224, Key, Data) -> sha224_mac(Key, Data);
+do_hmac(sha256, Key, Data) -> sha256_mac(Key, Data);
+do_hmac(sha384, Key, Data) -> sha384_mac(Key, Data);
+do_hmac(sha512, Key, Data) -> sha512_mac(Key, Data).
+
+do_hmac(md5, Key, Data, Size) -> md5_mac_n(Key, Data, Size);
+do_hmac(sha, Key, Data, Size) -> sha_mac_n(Key, Data, Size);
+do_hmac(sha224, Key, Data, Size) -> sha224_mac(Key, Data, Size);
+do_hmac(sha256, Key, Data, Size) -> sha256_mac(Key, Data, Size);
+do_hmac(sha384, Key, Data, Size) -> sha384_mac(Key, Data, Size);
+do_hmac(sha512, Key, Data, Size) -> sha512_mac(Key, Data, Size).
+
+do_hmac_update(_Context, _Data) -> ? nif_stub.
-hmac_init(_Type, _Key) -> ?nif_stub.
-hmac_update(_Context, _Data) -> ? nif_stub.
-hmac_final(_Context) -> ? nif_stub.
-hmac_final_n(_Context, _HashLen) -> ? nif_stub.
-
%%
%% MD5_MAC
%%
@@ -696,172 +1045,7 @@ sha512_mac(Key, Data, MacSz) ->
sha512_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-
-%% Ecrypt/decrypt %%%
-
--spec block_encrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc |
- blowfish_cfb64 | aes_cbc128 | aes_cfb128 | aes_cbc256 | rc2_cbc,
- Key::iodata(), Ivec::binary(), Data::iodata()) -> binary().
-
-block_encrypt(des_cbc, Key, Ivec, Data) ->
- des_cbc_encrypt(Key, Ivec, Data);
-block_encrypt(des_cfb, Key, Ivec, Data) ->
- des_cfb_encrypt(Key, Ivec, Data);
-block_encrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data);
-block_encrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cfb_encrypt(Key1, Key2, Key3, Ivec, Data);
-block_encrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) ->
- des_ede3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data);
-block_encrypt(blowfish_cbc, Key, Ivec, Data) ->
- blowfish_cbc_encrypt(Key, Ivec, Data);
-block_encrypt(blowfish_cfb64, Key, Ivec, Data) ->
- blowfish_cfb64_encrypt(Key, Ivec, Data);
-block_encrypt(blowfish_ofb64, Key, Ivec, Data) ->
- blowfish_ofb64_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cbc128, Key, Ivec, Data) ->
- aes_cbc_128_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cbc256, Key, Ivec, Data) ->
- aes_cbc_256_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cfb128, Key, Ivec, Data) ->
- aes_cfb_128_encrypt(Key, Ivec, Data);
-block_encrypt(rc2_cbc, Key, Ivec, Data) ->
- rc2_cbc_encrypt(Key, Ivec, Data).
-
--spec block_decrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc |
- blowfish_cfb64 | blowfish_ofb64 | aes_cbc128 | aes_cbc256 | aes_cfb128 | rc2_cbc,
- Key::iodata(), Ivec::binary(), Data::iodata()) -> binary().
-
-block_decrypt(des_cbc, Key, Ivec, Data) ->
- des_cbc_decrypt(Key, Ivec, Data);
-block_decrypt(des_cfb, Key, Ivec, Data) ->
- des_cfb_decrypt(Key, Ivec, Data);
-block_decrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data);
-block_decrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cfb_decrypt(Key1, Key2, Key3, Ivec, Data);
-block_decrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) ->
- des_ede3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data);
-block_decrypt(blowfish_cbc, Key, Ivec, Data) ->
- blowfish_cbc_decrypt(Key, Ivec, Data);
-block_decrypt(blowfish_cfb64, Key, Ivec, Data) ->
- blowfish_cfb64_decrypt(Key, Ivec, Data);
-block_decrypt(blowfish_ofb64, Key, Ivec, Data) ->
- blowfish_ofb64_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cbc128, Key, Ivec, Data) ->
- aes_cbc_128_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cbc256, Key, Ivec, Data) ->
- aes_cbc_256_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cfb128, Key, Ivec, Data) ->
- aes_cfb_128_decrypt(Key, Ivec, Data);
-block_decrypt(rc2_cbc, Key, Ivec, Data) ->
- rc2_cbc_decrypt(Key, Ivec, Data).
-
--spec block_encrypt(des_ecb | blowfish_ecb, Key::iodata(), Data::iodata()) -> binary().
-
-block_encrypt(des_ecb, Key, Data) ->
- des_ecb_encrypt(Key, Data);
-block_encrypt(blowfish_ecb, Key, Data) ->
- blowfish_ecb_encrypt(Key, Data).
-
--spec block_decrypt(des_ecb | blowfish_ecb, Key::iodata(), Data::iodata()) -> binary().
-
-block_decrypt(des_ecb, Key, Data) ->
- des_ecb_decrypt(Key, Data);
-block_decrypt(blowfish_ecb, Key, Data) ->
- blowfish_ecb_decrypt(Key, Data).
-
--spec next_iv(des_cbc | des3_cbc | aes_cbc, Data::iodata()) -> binary().
-
-next_iv(des_cbc, Data) ->
- des_cbc_ivec(Data);
-next_iv(des3_cbc, Data) ->
- des_cbc_ivec(Data);
-next_iv(aes_cbc, Data) ->
- aes_cbc_ivec(Data).
-
--spec next_iv(des_cfb, Data::iodata(), Ivec::binary()) -> binary().
-
-next_iv(des_cfb, Data, Ivec) ->
- des_cfb_ivec(Ivec, Data);
-next_iv(Type, Data, _Ivec) ->
- next_iv(Type, Data).
-
-stream_init(aes_ctr, Key, Ivec) ->
- {aes_ctr, aes_ctr_stream_init(Key, Ivec)}.
-stream_init(rc4, Key) ->
- {rc4, rc4_set_key(Key)}.
-stream_encrypt({aes_ctr, State0}, Data) ->
- {State, Cipher} = aes_ctr_stream_encrypt(State0, Data),
- {{aes_ctr, State}, Cipher};
-stream_encrypt({rc4, State0}, Data) ->
- {State, Cipher} = rc4_encrypt_with_state(State0, Data),
- {{rc4, State}, Cipher}.
-stream_decrypt({aes_ctr, State0}, Data) ->
- {State, Text} = aes_ctr_stream_decrypt(State0, Data),
- {{aes_ctr, State}, Text};
-stream_decrypt({rc4, State0}, Data) ->
- {State, Text} = rc4_encrypt_with_state (State0, Data),
- {{rc4, State}, Text}.
-
-%%
-%% CRYPTO FUNCTIONS
-%%
-
-%%
-%% DES - in cipher block chaining mode (CBC)
-%%
--spec des_cbc_encrypt(iodata(), binary(), iodata()) -> binary().
--spec des_cbc_decrypt(iodata(), binary(), iodata()) -> binary().
-
-des_cbc_encrypt(Key, IVec, Data) ->
- des_cbc_crypt(Key, IVec, Data, true).
-
-des_cbc_decrypt(Key, IVec, Data) ->
- des_cbc_crypt(Key, IVec, Data, false).
-
-des_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-
-%%
-%% dec_cbc_ivec(Data) -> binary()
-%%
-%% Returns the IVec to be used in the next iteration of
-%% des_cbc_[encrypt|decrypt].
-%%
--spec des_cbc_ivec(iodata()) -> binary().
-
-des_cbc_ivec(Data) when is_binary(Data) ->
- {_, IVec} = split_binary(Data, size(Data) - 8),
- IVec;
-des_cbc_ivec(Data) when is_list(Data) ->
- des_cbc_ivec(list_to_binary(Data)).
-
-%%
-%% DES - in 8-bits cipher feedback mode (CFB)
-%%
--spec des_cfb_encrypt(iodata(), binary(), iodata()) -> binary().
--spec des_cfb_decrypt(iodata(), binary(), iodata()) -> binary().
-
-des_cfb_encrypt(Key, IVec, Data) ->
- des_cfb_crypt(Key, IVec, Data, true).
-
-des_cfb_decrypt(Key, IVec, Data) ->
- des_cfb_crypt(Key, IVec, Data, false).
-
-des_cfb_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-
-%%
-%% dec_cfb_ivec(IVec, Data) -> binary()
-%%
-%% Returns the IVec to be used in the next iteration of
-%% des_cfb_[encrypt|decrypt].
-%%
--spec des_cfb_ivec(iodata(), iodata()) -> binary().
-
-des_cfb_ivec(IVec, Data) ->
- IVecAndData = list_to_binary([IVec, Data]),
- {_, NewIVec} = split_binary(IVecAndData, byte_size(IVecAndData) - 8),
- NewIVec.
+%% CIPHERS --------------------------------------------------------------------
%%
%% DES - in electronic codebook mode (ECB)
@@ -973,292 +1157,63 @@ aes_cfb_128_decrypt(Key, IVec, Data) ->
aes_cfb_128_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-%%
-%% RAND - pseudo random numbers using RN_ functions in crypto lib
%%
--spec rand_bytes(non_neg_integer()) -> binary().
--spec strong_rand_bytes(non_neg_integer()) -> binary().
--spec rand_uniform(crypto_integer(), crypto_integer()) ->
- crypto_integer().
--spec strong_rand_mpint(Bits::non_neg_integer(),
- Top::-1..1,
- Bottom::0..1) -> binary().
-
-rand_bytes(_Bytes) -> ?nif_stub.
-
-strong_rand_bytes(Bytes) ->
- case strong_rand_bytes_nif(Bytes) of
- false -> erlang:error(low_entropy);
- Bin -> Bin
- end.
-strong_rand_bytes_nif(_Bytes) -> ?nif_stub.
-
-rand_bytes(_Bytes, _Topmask, _Bottommask) -> ?nif_stub.
-
-strong_rand_mpint(Bits, Top, Bottom) ->
- case strong_rand_mpint_nif(Bits,Top,Bottom) of
- false -> erlang:error(low_entropy);
- Bin -> Bin
- end.
-strong_rand_mpint_nif(_Bits, _Top, _Bottom) -> ?nif_stub.
-
+%% DES - in cipher block chaining mode (CBC)
+%%
+-spec des_cbc_encrypt(iodata(), binary(), iodata()) -> binary().
+-spec des_cbc_decrypt(iodata(), binary(), iodata()) -> binary().
-rand_uniform(From,To) when is_binary(From), is_binary(To) ->
- case rand_uniform_nif(From,To) of
- <<Len:32/integer, MSB, Rest/binary>> when MSB > 127 ->
- <<(Len + 1):32/integer, 0, MSB, Rest/binary>>;
- Whatever ->
- Whatever
- end;
-rand_uniform(From,To) when is_integer(From),is_integer(To) ->
- if From < 0 ->
- rand_uniform_pos(0, To - From) + From;
- true ->
- rand_uniform_pos(From, To)
- end.
+des_cbc_encrypt(Key, IVec, Data) ->
+ des_cbc_crypt(Key, IVec, Data, true).
-rand_uniform_pos(From,To) when From < To ->
- BinFrom = mpint(From),
- BinTo = mpint(To),
- case rand_uniform(BinFrom, BinTo) of
- Result when is_binary(Result) ->
- erlint(Result);
- Other ->
- Other
- end;
-rand_uniform_pos(_,_) ->
- error(badarg).
+des_cbc_decrypt(Key, IVec, Data) ->
+ des_cbc_crypt(Key, IVec, Data, false).
-rand_uniform_nif(_From,_To) -> ?nif_stub.
+des_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
%%
-%% mod_exp - utility for rsa generation and SRP
+%% dec_cbc_ivec(Data) -> binary()
%%
-mod_exp(Base, Exponent, Modulo)
- when is_integer(Base), is_integer(Exponent), is_integer(Modulo) ->
- bin_to_int(mod_exp_nif(int_to_bin(Base), int_to_bin(Exponent), int_to_bin(Modulo), 0));
-
-mod_exp(Base, Exponent, Modulo) ->
- mod_exp_nif(mpint_to_bin(Base),mpint_to_bin(Exponent),mpint_to_bin(Modulo), 4).
-
--spec mod_pow(binary()|integer(), binary()|integer(), binary()|integer()) -> binary() | error.
-mod_pow(Base, Exponent, Prime) ->
- case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of
- <<0>> -> error;
- R -> R
- end.
-
+%% Returns the IVec to be used in the next iteration of
+%% des_cbc_[encrypt|decrypt].
+%%
+-spec des_cbc_ivec(iodata()) -> binary().
-mod_exp_nif(_Base,_Exp,_Mod,_bin_hdr) -> ?nif_stub.
+des_cbc_ivec(Data) when is_binary(Data) ->
+ {_, IVec} = split_binary(Data, size(Data) - 8),
+ IVec;
+des_cbc_ivec(Data) when is_list(Data) ->
+ des_cbc_ivec(list_to_binary(Data)).
%%
-%% DSS, RSA - verify
+%% DES - in 8-bits cipher feedback mode (CFB)
%%
--spec dss_verify(data_or_digest(), binary(), [binary()]) -> boolean().
--spec dss_verify(dss_digest_type(), data_or_digest(), binary(), [binary()]) -> boolean().
--spec rsa_verify(data_or_digest(), binary(), [binary()]) -> boolean().
--spec rsa_verify(rsa_digest_type(), data_or_digest(), binary(), [binary()]) ->
- boolean().
-
-%% Key = [P,Q,G,Y] P,Q,G=DSSParams Y=PublicKey
-dss_verify(Data,Signature,Key) ->
- dss_verify(sha, Data, Signature, Key).
-
-dss_verify(Type,Data,Signature,Key) when is_binary(Data), Type=/=none ->
- verify(dss,Type,mpint_to_bin(Data),mpint_to_bin(Signature),map_mpint_to_bin(Key));
-dss_verify(Type,Digest,Signature,Key) ->
- verify(dss,Type,Digest,mpint_to_bin(Signature),map_mpint_to_bin(Key)).
-
-% Key = [E,N] E=PublicExponent N=PublicModulus
-rsa_verify(Data,Signature,Key) ->
- rsa_verify(sha, Data,Signature,Key).
-rsa_verify(Type, Data, Signature, Key) when is_binary(Data) ->
- verify(rsa, Type, mpint_to_bin(Data), mpint_to_bin(Signature), map_mpint_to_bin(Key));
-rsa_verify(Type, Digest, Signature, Key) ->
- verify(rsa, Type, Digest, mpint_to_bin(Signature), map_mpint_to_bin(Key)).
-
-
-verify(dss, Type, Data, Signature, Key) ->
- dss_verify_nif(Type, Data, Signature, map_ensure_int_as_bin(Key));
-
-verify(rsa, Type, DataOrDigest, Signature, Key) ->
- case rsa_verify_nif(Type, DataOrDigest, Signature, map_ensure_int_as_bin(Key)) of
- notsup -> erlang:error(notsup);
- Bool -> Bool
- end;
-verify(ecdsa, Type, DataOrDigest, Signature, [Key, Curve]) ->
- case ecdsa_verify_nif(Type, DataOrDigest, Signature, term_to_ec_key(Curve, undefined, Key)) of
- notsup -> erlang:error(notsup);
- Bool -> Bool
- end.
+-spec des_cfb_encrypt(iodata(), binary(), iodata()) -> binary().
+-spec des_cfb_decrypt(iodata(), binary(), iodata()) -> binary().
+des_cfb_encrypt(Key, IVec, Data) ->
+ des_cfb_crypt(Key, IVec, Data, true).
-dss_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
-rsa_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
-ecdsa_verify_nif(_Type, _DataOrDigest, _Signature, _Key) -> ?nif_stub.
+des_cfb_decrypt(Key, IVec, Data) ->
+ des_cfb_crypt(Key, IVec, Data, false).
+des_cfb_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
%%
-%% DSS, RSA - sign
+%% dec_cfb_ivec(IVec, Data) -> binary()
%%
-%% Key = [P,Q,G,X] P,Q,G=DSSParams X=PrivateKey
--spec dss_sign(data_or_digest(), [binary()]) -> binary().
--spec dss_sign(dss_digest_type(), data_or_digest(), [binary()]) -> binary().
--spec rsa_sign(data_or_digest(), [binary()]) -> binary().
--spec rsa_sign(rsa_digest_type(), data_or_digest(), [binary()]) -> binary().
-
-dss_sign(DataOrDigest,Key) ->
- dss_sign(sha,DataOrDigest,Key).
-dss_sign(Type, Data, Key) when is_binary(Data), Type=/=none ->
- sign(dss, Type, mpint_to_bin(Data), map_mpint_to_bin(Key));
-dss_sign(Type, Digest, Key) ->
- sign(dss, Type, Digest, map_mpint_to_bin(Key)).
-
-
-%% Key = [E,N,D] E=PublicExponent N=PublicModulus D=PrivateExponent
-rsa_sign(DataOrDigest,Key) ->
- rsa_sign(sha, DataOrDigest, Key).
-
-rsa_sign(Type, Data, Key) when is_binary(Data) ->
- sign(rsa, Type, mpint_to_bin(Data), map_mpint_to_bin(Key));
-rsa_sign(Type, Digest, Key) ->
- sign(rsa, Type, Digest, map_mpint_to_bin(Key)).
-
-map_mpint_to_bin(List) ->
- lists:map(fun(E) -> mpint_to_bin(E) end, List ).
-
-map_ensure_int_as_bin([H|_]=List) when is_integer(H) ->
- lists:map(fun(E) -> int_to_bin(E) end, List);
-map_ensure_int_as_bin(List) ->
- List.
-
-ensure_int_as_bin(Int) when is_integer(Int) ->
- int_to_bin(Int);
-ensure_int_as_bin(Bin) ->
- Bin.
-
-map_to_norm_bin([H|_]=List) when is_integer(H) ->
- lists:map(fun(E) -> int_to_bin(E) end, List);
-map_to_norm_bin(List) ->
- lists:map(fun(E) -> mpint_to_bin(E) end, List).
-
-
-sign(rsa, Type, DataOrDigest, Key) ->
- case rsa_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
- Sign -> Sign
- end;
-sign(dss, Type, DataOrDigest, Key) ->
- case dss_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [DataOrDigest, Key]);
- Sign -> Sign
- end;
-sign(ecdsa, Type, DataOrDigest, [Key, Curve]) ->
- case ecdsa_sign_nif(Type, DataOrDigest, term_to_ec_key(Curve, Key, undefined)) of
- error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
- Sign -> Sign
- end.
-
-rsa_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
-dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
-ecdsa_sign_nif(_Type, _DataOrDigest, _Key) -> ?nif_stub.
-
-
-
-
--spec public_encrypt(rsa, binary(), [binary()], rsa_padding()) ->
- binary().
--spec public_decrypt(rsa, binary(), [integer() | binary()], rsa_padding()) ->
- binary().
--spec private_encrypt(rsa, binary(), [integer() | binary()], rsa_padding()) ->
- binary().
--spec private_decrypt(rsa, binary(), [integer() | binary()], rsa_padding()) ->
- binary().
-
-public_encrypt(rsa, BinMesg, Key, Padding) ->
- case rsa_public_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, true) of
- error ->
- erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-%% Binary, Key = [E,N,D]
-private_decrypt(rsa, BinMesg, Key, Padding) ->
- case rsa_private_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, false) of
- error ->
- erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-
-%% Binary, Key = [E,N,D]
-private_encrypt(rsa, BinMesg, Key, Padding) ->
- case rsa_private_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, true) of
- error ->
- erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-%% Binary, Key = [E,N]
-public_decrypt(rsa, BinMesg, Key, Padding) ->
- case rsa_public_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, false) of
- error ->
- erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-
+%% Returns the IVec to be used in the next iteration of
+%% des_cfb_[encrypt|decrypt].
%%
-%% rsa_public_encrypt
-%% rsa_private_decrypt
--type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' | 'rsa_no_padding'.
-
--spec rsa_public_encrypt(binary(), [binary()], rsa_padding()) ->
- binary().
--spec rsa_public_decrypt(binary(), [integer() | mpint()], rsa_padding()) ->
- binary().
--spec rsa_private_encrypt(binary(), [integer() | mpint()], rsa_padding()) ->
- binary().
--spec rsa_private_decrypt(binary(), [integer() | mpint()], rsa_padding()) ->
- binary().
-%% Binary, Key = [E,N]
-rsa_public_encrypt(BinMesg, Key, Padding) ->
- case rsa_public_crypt(BinMesg, map_to_norm_bin(Key), Padding, true) of
- error ->
- erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-rsa_public_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub.
+-spec des_cfb_ivec(iodata(), iodata()) -> binary().
-%% Binary, Key = [E,N,D]
-rsa_private_decrypt(BinMesg, Key, Padding) ->
- case rsa_private_crypt(BinMesg, map_to_norm_bin(Key), Padding, false) of
- error ->
- erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
+des_cfb_ivec(IVec, Data) ->
+ IVecAndData = list_to_binary([IVec, Data]),
+ {_, NewIVec} = split_binary(IVecAndData, byte_size(IVecAndData) - 8),
+ NewIVec.
-rsa_private_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub.
-
-%% Binary, Key = [E,N,D]
-rsa_private_encrypt(BinMesg, Key, Padding) ->
- case rsa_private_crypt(BinMesg, map_to_norm_bin(Key), Padding, true) of
- error ->
- erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-%% Binary, Key = [E,N]
-rsa_public_decrypt(BinMesg, Key, Padding) ->
- case rsa_public_crypt(BinMesg, map_to_norm_bin(Key), Padding, false) of
- error ->
- erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
%%
%% AES - with 128 or 256 bit key in cipher block chaining mode (CBC)
%%
@@ -1298,6 +1253,33 @@ aes_cbc_ivec(Data) when is_binary(Data) ->
aes_cbc_ivec(Data) when is_list(Data) ->
aes_cbc_ivec(list_to_binary(Data)).
+
+%% Stream ciphers --------------------------------------------------------------------
+
+stream_crypt(Fun, State, Data, Size, MaxByts, []) when Size =< MaxByts ->
+ Fun(State, Data);
+stream_crypt(Fun, State0, Data, Size, MaxByts, Acc) when Size =< MaxByts ->
+ {State, Cipher} = Fun(State0, Data),
+ {State, list_to_binary(lists:reverse([Cipher | Acc]))};
+stream_crypt(Fun, State0, Data, _, MaxByts, Acc) ->
+ <<Increment:MaxByts/binary, Rest/binary>> = Data,
+ {State, CipherText} = Fun(State0, Increment),
+ stream_crypt(Fun, State, Rest, erlang:byte_size(Rest), MaxByts, [CipherText | Acc]).
+
+do_stream_encrypt({aes_ctr, State0}, Data) ->
+ {State, Cipher} = aes_ctr_stream_encrypt(State0, Data),
+ {{aes_ctr, State}, Cipher};
+do_stream_encrypt({rc4, State0}, Data) ->
+ {State, Cipher} = rc4_encrypt_with_state(State0, Data),
+ {{rc4, State}, Cipher}.
+
+do_stream_decrypt({aes_ctr, State0}, Data) ->
+ {State, Text} = aes_ctr_stream_decrypt(State0, Data),
+ {{aes_ctr, State}, Text};
+do_stream_decrypt({rc4, State0}, Data) ->
+ {State, Text} = rc4_encrypt_with_state(State0, Data),
+ {{rc4, State}, Text}.
+
%%
%% AES - in counter mode (CTR)
%%
@@ -1305,7 +1287,7 @@ aes_cbc_ivec(Data) when is_list(Data) ->
binary().
-spec aes_ctr_decrypt(iodata(), binary(), iodata()) ->
binary().
-
+
aes_ctr_encrypt(_Key, _IVec, _Data) -> ?nif_stub.
aes_ctr_decrypt(_Key, _IVec, _Cipher) -> ?nif_stub.
@@ -1326,15 +1308,6 @@ aes_ctr_stream_encrypt({_Key, _IVec, _ECount, _Num}=_State, _Data) -> ?nif_stub.
aes_ctr_stream_decrypt({_Key, _IVec, _ECount, _Num}=_State, _Cipher) -> ?nif_stub.
%%
-%% XOR - xor to iolists and return a binary
-%% NB doesn't check that they are the same size, just concatenates
-%% them and sends them to the driver
-%%
--spec exor(iodata(), iodata()) -> binary().
-
-exor(_A, _B) -> ?nif_stub.
-
-%%
%% RC4 - symmetric stream cipher
%%
-spec rc4_encrypt(iodata(), iodata()) -> binary().
@@ -1363,7 +1336,76 @@ rc2_40_cbc_encrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
rc2_40_cbc_decrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
rc2_cbc_crypt(Key,IVec,Data,false).
-%%
+
+%% Secure remote password -------------------------------------------------------------------
+
+user_srp_gen_key(Private, Generator, Prime) ->
+ case mod_pow(Generator, Private, Prime) of
+ error ->
+ error;
+ Public ->
+ {Public, Private}
+ end.
+
+host_srp_gen_key(Private, Verifier, Generator, Prime, Version) ->
+ Multiplier = srp_multiplier(Version, Generator, Prime),
+ case srp_value_B_nif(Multiplier, Verifier, Generator, Private, Prime) of
+ error ->
+ error;
+ Public ->
+ {Public, Private}
+ end.
+
+srp_multiplier('6a', Generator, Prime) ->
+ %% k = SHA1(N | PAD(g)) from http://srp.stanford.edu/design.html
+ C0 = sha_init(),
+ C1 = sha_update(C0, Prime),
+ C2 = sha_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)),
+ sha_final(C2);
+srp_multiplier('6', _, _) ->
+ <<3/integer>>;
+srp_multiplier('3', _, _) ->
+ <<1/integer>>.
+
+srp_scrambler(Version, UserPublic, HostPublic, Prime) when Version == '6'; Version == '6a'->
+ %% SHA1(PAD(A) | PAD(B)) from http://srp.stanford.edu/design.html
+ PadLength = erlang:byte_size(Prime),
+ C0 = sha_init(),
+ C1 = sha_update(C0, srp_pad_to(PadLength, UserPublic)),
+ C2 = sha_update(C1, srp_pad_to(PadLength, HostPublic)),
+ sha_final(C2);
+srp_scrambler('3', _, HostPublic, _Prime) ->
+ %% The parameter u is a 32-bit unsigned integer which takes its value
+ %% from the first 32 bits of the SHA1 hash of B, MSB first.
+ <<U:32/bits, _/binary>> = sha(HostPublic),
+ U.
+
+srp_pad_length(Width, Length) ->
+ (Width - Length rem Width) rem Width.
+
+srp_pad_to(Width, Binary) ->
+ case srp_pad_length(Width, size(Binary)) of
+ 0 -> Binary;
+ N -> << 0:(N*8), Binary/binary>>
+ end.
+
+srp_host_secret_nif(_Verifier, _B, _U, _A, _Prime) -> ?nif_stub.
+
+srp_user_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?nif_stub.
+
+srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub.
+
+
+%% Digital signatures --------------------------------------------------------------------
+rsa_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
+dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
+ecdsa_sign_nif(_Type, _DataOrDigest, _Key) -> ?nif_stub.
+
+dss_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
+rsa_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
+ecdsa_verify_nif(_Type, _DataOrDigest, _Signature, _Key) -> ?nif_stub.
+
+%% Public Keys --------------------------------------------------------------------
%% DH Diffie-Hellman functions
%%
@@ -1412,80 +1454,10 @@ dh_compute_key(OthersPublicKey, MyPrivateKey, DHParameters) ->
dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub.
-generate_key(Type, Params) ->
- generate_key(Type, Params, undefined).
-
-generate_key(dh, DHParameters, PrivateKey) ->
- dh_generate_key_nif(ensure_int_as_bin(PrivateKey),
- map_ensure_int_as_bin(DHParameters), 0);
-
-generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, PrivArg)
- when is_binary(Verifier), is_binary(Generator), is_binary(Prime), is_atom(Version) ->
- Private = case PrivArg of
- undefined -> random_bytes(32);
- _ -> ensure_int_as_bin(PrivArg)
- end,
- host_srp_gen_key(Private, Verifier, Generator, Prime, Version);
-
-generate_key(srp, {user, [Generator, Prime, Version]}, PrivateArg)
- when is_binary(Generator), is_binary(Prime), is_atom(Version) ->
- Private = case PrivateArg of
- undefined -> random_bytes(32);
- _ -> PrivateArg
- end,
- user_srp_gen_key(Private, Generator, Prime);
-
-generate_key(ecdh, Curve, undefined) ->
- ec_key_to_term_nif(ec_key_generate(Curve)).
-
-
ec_key_generate(_Key) -> ?nif_stub.
-
-compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) ->
- case dh_compute_key_nif(ensure_int_as_bin(OthersPublicKey),
- ensure_int_as_bin(MyPrivateKey),
- map_ensure_int_as_bin(DHParameters)) of
- error -> erlang:error(computation_failed,
- [OthersPublicKey,MyPrivateKey,DHParameters]);
- Ret -> Ret
- end;
-
-compute_key(srp, HostPublic, {UserPublic, UserPrivate},
- {user, [DerivedKey, Prime, Generator, Version | ScramblerArg]}) when
- is_binary(Prime),
- is_binary(Generator),
- is_atom(Version) ->
- HostPubBin = ensure_int_as_bin(HostPublic),
- Multiplier = srp_multiplier(Version, Generator, Prime),
- Scrambler = case ScramblerArg of
- [] -> srp_scrambler(Version, ensure_int_as_bin(UserPublic),
- HostPubBin, Prime);
- [S] -> S
- end,
- srp_user_secret_nif(ensure_int_as_bin(UserPrivate), Scrambler, HostPubBin,
- Multiplier, Generator, DerivedKey, Prime);
-
-compute_key(srp, UserPublic, {HostPublic, HostPrivate},
- {host,[Verifier, Prime, Version | ScramblerArg]}) when
- is_binary(Verifier),
- is_binary(Prime),
- is_atom(Version) ->
- UserPubBin = ensure_int_as_bin(UserPublic),
- Scrambler = case ScramblerArg of
- [] -> srp_scrambler(Version, UserPubBin, ensure_int_as_bin(HostPublic), Prime);
- [S] -> S
- end,
- srp_host_secret_nif(Verifier, ensure_int_as_bin(HostPrivate), Scrambler,
- UserPubBin, Prime);
-
-compute_key(ecdh, Others, My, Curve) ->
- ecdh_compute_key_nif(ensure_int_as_bin(Others),
- term_to_ec_key(Curve,My,undefined)).
-
ecdh_compute_key_nif(_Others, _My) -> ?nif_stub.
-
%%
%% EC
%%
@@ -1511,65 +1483,181 @@ term_to_ec_key(Curve, PrivKey, PubKey) ->
term_to_ec_key_nif(_Curve, _PrivKey, _PubKey) -> ?nif_stub.
+%% MISC --------------------------------------------------------------------
+
+exor(Data1, Data2, Size, MaxByts, []) when Size =< MaxByts ->
+ do_exor(Data1, Data2);
+exor(Data1, Data2, Size, MaxByts, Acc) when Size =< MaxByts ->
+ Result = do_exor(Data1, Data2),
+ list_to_binary(lists:reverse([Result | Acc]));
+exor(Data1, Data2, _Size, MaxByts, Acc) ->
+ <<Increment1:MaxByts/binary, Rest1/binary>> = Data1,
+ <<Increment2:MaxByts/binary, Rest2/binary>> = Data2,
+ Result = do_exor(Increment1, Increment2),
+ exor(Rest1, Rest2, erlang:byte_size(Rest1), MaxByts, [Result | Acc]).
+
+do_exor(_A, _B) -> ?nif_stub.
-%% LOCAL FUNCTIONS
+algorithms() -> ?nif_stub.
+
+int_to_bin(X) when X < 0 -> int_to_bin_neg(X, []);
+int_to_bin(X) -> int_to_bin_pos(X, []).
+
+int_to_bin_pos(0,Ds=[_|_]) ->
+ list_to_binary(Ds);
+int_to_bin_pos(X,Ds) ->
+ int_to_bin_pos(X bsr 8, [(X band 255)|Ds]).
+
+int_to_bin_neg(-1, Ds=[MSB|_]) when MSB >= 16#80 ->
+ list_to_binary(Ds);
+int_to_bin_neg(X,Ds) ->
+ int_to_bin_neg(X bsr 8, [(X band 255)|Ds]).
+
+bytes_to_integer(Bin) ->
+ bin_to_int(Bin).
+
+bin_to_int(Bin) when is_binary(Bin) ->
+ Bits = bit_size(Bin),
+ <<Integer:Bits/integer>> = Bin,
+ Integer;
+bin_to_int(undefined) ->
+ undefined.
+
+map_ensure_int_as_bin([H|_]=List) when is_integer(H) ->
+ lists:map(fun(E) -> int_to_bin(E) end, List);
+map_ensure_int_as_bin(List) ->
+ List.
+
+ensure_int_as_bin(Int) when is_integer(Int) ->
+ int_to_bin(Int);
+ensure_int_as_bin(Bin) ->
+ Bin.
+
+map_to_norm_bin([H|_]=List) when is_integer(H) ->
+ lists:map(fun(E) -> int_to_bin(E) end, List);
+map_to_norm_bin(List) ->
+ lists:map(fun(E) -> mpint_to_bin(E) end, List).
+
+%%--------------------------------------------------------------------
+%%% Deprecated
+%%--------------------------------------------------------------------
%%
+%% rsa_public_encrypt
+%% rsa_private_decrypt
+-type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' | 'rsa_no_padding'.
-user_srp_gen_key(Private, Generator, Prime) ->
- case mod_pow(Generator, Private, Prime) of
+-spec rsa_public_encrypt(binary(), [binary()], rsa_padding()) ->
+ binary().
+-spec rsa_public_decrypt(binary(), [integer() | mpint()], rsa_padding()) ->
+ binary().
+-spec rsa_private_encrypt(binary(), [integer() | mpint()], rsa_padding()) ->
+ binary().
+-spec rsa_private_decrypt(binary(), [integer() | mpint()], rsa_padding()) ->
+ binary().
+
+%% Binary, Key = [E,N]
+rsa_public_encrypt(BinMesg, Key, Padding) ->
+ case rsa_public_crypt(BinMesg, map_to_norm_bin(Key), Padding, true) of
error ->
- error;
- Public ->
- {Public, Private}
+ erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
end.
-host_srp_gen_key(Private, Verifier, Generator, Prime, Version) ->
- Multiplier = srp_multiplier(Version, Generator, Prime),
- case srp_value_B_nif(Multiplier, Verifier, Generator, Private, Prime) of
- error ->
- error;
- Public ->
- {Public, Private}
- end.
+rsa_public_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub.
-srp_multiplier('6a', Generator, Prime) ->
- %% k = SHA1(N | PAD(g)) from http://srp.stanford.edu/design.html
- C0 = sha_init(),
- C1 = sha_update(C0, Prime),
- C2 = sha_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)),
- sha_final(C2);
-srp_multiplier('6', _, _) ->
- <<3/integer>>;
-srp_multiplier('3', _, _) ->
- <<1/integer>>.
+%% Binary, Key = [E,N,D]
+rsa_private_decrypt(BinMesg, Key, Padding) ->
+ case rsa_private_crypt(BinMesg, map_to_norm_bin(Key), Padding, false) of
+ error ->
+ erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
+ end.
-srp_scrambler(Version, UserPublic, HostPublic, Prime) when Version == '6'; Version == '6a'->
- %% SHA1(PAD(A) | PAD(B)) from http://srp.stanford.edu/design.html
- PadLength = erlang:byte_size(Prime),
- C0 = sha_init(),
- C1 = sha_update(C0, srp_pad_to(PadLength, UserPublic)),
- C2 = sha_update(C1, srp_pad_to(PadLength, HostPublic)),
- sha_final(C2);
-srp_scrambler('3', _, HostPublic, _Prime) ->
- %% The parameter u is a 32-bit unsigned integer which takes its value
- %% from the first 32 bits of the SHA1 hash of B, MSB first.
- <<U:32/bits, _/binary>> = sha(HostPublic),
- U.
+rsa_private_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub.
-srp_pad_length(Width, Length) ->
- (Width - Length rem Width) rem Width.
-srp_pad_to(Width, Binary) ->
- case srp_pad_length(Width, size(Binary)) of
- 0 -> Binary;
- N -> << 0:(N*8), Binary/binary>>
+%% Binary, Key = [E,N,D]
+rsa_private_encrypt(BinMesg, Key, Padding) ->
+ case rsa_private_crypt(BinMesg, map_to_norm_bin(Key), Padding, true) of
+ error ->
+ erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
end.
-srp_host_secret_nif(_Verifier, _B, _U, _A, _Prime) -> ?nif_stub.
+%% Binary, Key = [E,N]
+rsa_public_decrypt(BinMesg, Key, Padding) ->
+ case rsa_public_crypt(BinMesg, map_to_norm_bin(Key), Padding, false) of
+ error ->
+ erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
+ end.
-srp_user_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?nif_stub.
+map_mpint_to_bin(List) ->
+ lists:map(fun(E) -> mpint_to_bin(E) end, List ).
+
+%%
+%% DSS, RSA - sign
+%%
+%% Key = [P,Q,G,X] P,Q,G=DSSParams X=PrivateKey
+-spec dss_sign(data_or_digest(), [binary()]) -> binary().
+-spec dss_sign(dss_digest_type(), data_or_digest(), [binary()]) -> binary().
+-spec rsa_sign(data_or_digest(), [binary()]) -> binary().
+-spec rsa_sign(rsa_digest_type(), data_or_digest(), [binary()]) -> binary().
+
+dss_sign(DataOrDigest,Key) ->
+ dss_sign(sha,DataOrDigest,Key).
+dss_sign(Type, Data, Key) when is_binary(Data), Type=/=none ->
+ sign(dss, Type, mpint_to_bin(Data), map_mpint_to_bin(Key));
+dss_sign(Type, Digest, Key) ->
+ sign(dss, Type, Digest, map_mpint_to_bin(Key)).
+
+
+%% Key = [E,N,D] E=PublicExponent N=PublicModulus D=PrivateExponent
+rsa_sign(DataOrDigest,Key) ->
+ rsa_sign(sha, DataOrDigest, Key).
+
+rsa_sign(Type, Data, Key) when is_binary(Data) ->
+ sign(rsa, Type, mpint_to_bin(Data), map_mpint_to_bin(Key));
+rsa_sign(Type, Digest, Key) ->
+ sign(rsa, Type, Digest, map_mpint_to_bin(Key)).
+
+%%
+%% DSS, RSA - verify
+%%
+-spec dss_verify(data_or_digest(), binary(), [binary()]) -> boolean().
+-spec dss_verify(dss_digest_type(), data_or_digest(), binary(), [binary()]) -> boolean().
+-spec rsa_verify(data_or_digest(), binary(), [binary()]) -> boolean().
+-spec rsa_verify(rsa_digest_type(), data_or_digest(), binary(), [binary()]) ->
+ boolean().
+
+%% Key = [P,Q,G,Y] P,Q,G=DSSParams Y=PublicKey
+dss_verify(Data,Signature,Key) ->
+ dss_verify(sha, Data, Signature, Key).
+
+dss_verify(Type,Data,Signature,Key) when is_binary(Data), Type=/=none ->
+ verify(dss,Type,mpint_to_bin(Data),mpint_to_bin(Signature),map_mpint_to_bin(Key));
+dss_verify(Type,Digest,Signature,Key) ->
+ verify(dss,Type,Digest,mpint_to_bin(Signature),map_mpint_to_bin(Key)).
+
+% Key = [E,N] E=PublicExponent N=PublicModulus
+rsa_verify(Data,Signature,Key) ->
+ rsa_verify(sha, Data,Signature,Key).
+rsa_verify(Type, Data, Signature, Key) when is_binary(Data) ->
+ verify(rsa, Type, mpint_to_bin(Data), mpint_to_bin(Signature), map_mpint_to_bin(Key));
+rsa_verify(Type, Digest, Signature, Key) ->
+ verify(rsa, Type, Digest, mpint_to_bin(Signature), map_mpint_to_bin(Key)).
+
+-spec strong_rand_mpint(Bits::non_neg_integer(),
+ Top::-1..1,
+ Bottom::0..1) -> binary().
+
+strong_rand_mpint(Bits, Top, Bottom) ->
+ case strong_rand_mpint_nif(Bits,Top,Bottom) of
+ false -> erlang:error(low_entropy);
+ Bin -> Bin
+ end.
+strong_rand_mpint_nif(_Bits, _Top, _Bottom) -> ?nif_stub.
-srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub.
%% large integer in a binary with 32bit length
%% MP representaion (SSH2)
@@ -1594,32 +1682,6 @@ mpint_pos(X) ->
<<?UINT32(Sz), Bin/binary>>
end.
-int_to_bin(X) when X < 0 -> int_to_bin_neg(X, []);
-int_to_bin(X) -> int_to_bin_pos(X, []).
-
-%%int_to_bin_pos(X) when X >= 0 ->
-%% int_to_bin_pos(X, []).
-
-int_to_bin_pos(0,Ds=[_|_]) ->
- list_to_binary(Ds);
-int_to_bin_pos(X,Ds) ->
- int_to_bin_pos(X bsr 8, [(X band 255)|Ds]).
-
-int_to_bin_neg(-1, Ds=[MSB|_]) when MSB >= 16#80 ->
- list_to_binary(Ds);
-int_to_bin_neg(X,Ds) ->
- int_to_bin_neg(X bsr 8, [(X band 255)|Ds]).
-
-bytes_to_integer(Bin) ->
- bin_to_int(Bin).
-
-bin_to_int(Bin) when is_binary(Bin) ->
- Bits = bit_size(Bin),
- <<Integer:Bits/integer>> = Bin,
- Integer;
-bin_to_int(undefined) ->
- undefined.
-
%% int from integer in a binary with 32bit length
erlint(<<MPIntSize:32/integer,MPIntValue/binary>>) ->
Bits= MPIntSize * 8,
@@ -1629,11 +1691,71 @@ erlint(<<MPIntSize:32/integer,MPIntValue/binary>>) ->
mpint_to_bin(<<Len:32, Bin:Len/binary>>) ->
Bin.
-random_bytes(N) ->
- try strong_rand_bytes(N) of
- RandBytes ->
- RandBytes
- catch
- error:low_entropy ->
- rand_bytes(N)
- end.
+%%
+%% mod_exp - utility for rsa generation and SRP
+%%
+mod_exp(Base, Exponent, Modulo)
+ when is_integer(Base), is_integer(Exponent), is_integer(Modulo) ->
+ bin_to_int(mod_exp_nif(int_to_bin(Base), int_to_bin(Exponent), int_to_bin(Modulo), 0));
+
+mod_exp(Base, Exponent, Modulo) ->
+ mod_exp_nif(mpint_to_bin(Base),mpint_to_bin(Exponent),mpint_to_bin(Modulo), 4).
+
+mod_exp_nif(_Base,_Exp,_Mod,_bin_hdr) -> ?nif_stub.
+
+-define(FUNC_LIST, [hash, hash_init, hash_update, hash_final,
+ hmac, hmac_init, hmac_update, hmac_final, hmac_final_n,
+ %% deprecated
+ md4, md4_init, md4_update, md4_final,
+ md5, md5_init, md5_update, md5_final,
+ sha, sha_init, sha_update, sha_final,
+ md5_mac, md5_mac_96,
+ sha_mac, sha_mac_96,
+ %%
+ block_encrypt, block_decrypt,
+ %% deprecated
+ des_cbc_encrypt, des_cbc_decrypt,
+ des_cfb_encrypt, des_cfb_decrypt,
+ des_ecb_encrypt, des_ecb_decrypt,
+ des3_cbc_encrypt, des3_cbc_decrypt,
+ des3_cfb_encrypt, des3_cfb_decrypt,
+ aes_cfb_128_encrypt, aes_cfb_128_decrypt,
+ rc2_cbc_encrypt, rc2_cbc_decrypt,
+ rc2_40_cbc_encrypt, rc2_40_cbc_decrypt,
+ aes_cbc_128_encrypt, aes_cbc_128_decrypt,
+ aes_cbc_256_encrypt, aes_cbc_256_decrypt,
+ blowfish_cbc_encrypt, blowfish_cbc_decrypt,
+ blowfish_cfb64_encrypt, blowfish_cfb64_decrypt,
+ blowfish_ecb_encrypt, blowfish_ecb_decrypt, blowfish_ofb64_encrypt,
+ %%
+ rand_bytes,
+ strong_rand_bytes,
+ rand_uniform,
+ mod_pow,
+ exor,
+ %% deprecated
+ mod_exp,strong_rand_mpint,erlint, mpint,
+ %%
+ sign, verify, generate_key, compute_key,
+ %% deprecated
+ dss_verify,dss_sign,
+ rsa_verify,rsa_sign,
+ rsa_public_encrypt,rsa_private_decrypt,
+ rsa_private_encrypt,rsa_public_decrypt,
+ dh_generate_key, dh_compute_key,
+ %%
+ stream_init, stream_encrypt, stream_decrypt,
+ %% deprecated
+ rc4_encrypt, rc4_set_key, rc4_encrypt_with_state,
+ aes_ctr_encrypt, aes_ctr_decrypt,
+ aes_ctr_stream_init, aes_ctr_stream_encrypt, aes_ctr_stream_decrypt,
+ %%
+ next_iv,
+ %% deprecated
+ aes_cbc_ivec,
+ des_cbc_ivec, des_cfb_ivec,
+ info,
+ %%
+ info_lib, supports]).
+info() ->
+ ?FUNC_LIST.
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index b3bb5dbd17..58aaa78d28 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -212,16 +212,8 @@ mod_pow(Config) when is_list(Config) ->
exor() ->
[{doc, "Test the exor function"}].
exor(Config) when is_list(Config) ->
- B = <<1, 2, 3, 4, 5, 6, 7, 8, 9, 10>>,
- Z1 = zero_bin(B),
- Z1 = crypto:exor(B, B),
- B1 = crypto:rand_bytes(100),
- B2 = crypto:rand_bytes(100),
- Z2 = zero_bin(B1),
- Z2 = crypto:exor(B1, B1),
- Z2 = crypto:exor(B2, B2),
- R = xor_bytes(B1, B2),
- R = crypto:exor(B1, B2).
+ do_exor(<<1, 2, 3, 4, 5, 6, 7, 8, 9, 10>>),
+ do_exor(term_to_binary(lists:seq(1, 1000000))).
%%--------------------------------------------------------------------
rand_uniform() ->
[{doc, "rand_uniform and random_bytes testing"}].
@@ -229,10 +221,10 @@ rand_uniform(Config) when is_list(Config) ->
rand_uniform_aux_test(10),
10 = byte_size(crypto:rand_bytes(10)),
10 = byte_size(crypto:strong_rand_bytes(10)).
+
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
-
hash(_, [], []) ->
ok;
hash(Type, [Msg | RestMsg], [Digest| RestDigest]) ->
@@ -491,7 +483,7 @@ do_block_iolistify({Type, Key, IV, PlainText}) ->
iolistify(<<"Test With Truncation">>)->
%% Do not iolistify as it spoils this special case
<<"Test With Truncation">>;
-iolistify(Msg)->
+iolistify(Msg) when is_binary(Msg) ->
Length = erlang:byte_size(Msg),
Split = Length div 2,
List0 = binary_to_list(Msg),
@@ -500,7 +492,9 @@ iolistify(Msg)->
[[Element], List1, List2];
{List1, List2}->
[List1, List2]
- end.
+ end;
+iolistify(Msg) ->
+ iolistify(list_to_binary(Msg)).
des_iolistify(Msg) ->
des_iolist(erlang:byte_size(Msg) div 8, Msg, []).
@@ -540,6 +534,17 @@ ipow(A, B, M, Prod) ->
ipow(A1, B1, M, (A*Prod) rem M)
end.
+do_exor(B) ->
+ Z1 = zero_bin(B),
+ Z1 = crypto:exor(B, B),
+ B1 = crypto:rand_bytes(100),
+ B2 = crypto:rand_bytes(100),
+ Z2 = zero_bin(B1),
+ Z2 = crypto:exor(B1, B1),
+ Z2 = crypto:exor(B2, B2),
+ R = xor_bytes(B1, B2),
+ R = crypto:exor(B1, B2).
+
zero_bin(N) when is_integer(N) ->
N8 = N * 8,
<<0:N8/integer>>;
@@ -586,20 +591,20 @@ group_config(md4 = Type, Config) ->
group_config(md5 = Type, Config) ->
Msgs = rfc_1321_msgs(),
Digests = rfc_1321_md5_digests(),
- Keys = rfc_2202_md5_keys(),
- Data = rfc_2202_msgs(),
- Hmac = rfc_2202_hmac_md5(),
+ Keys = rfc_2202_md5_keys() ++ [long_hmac_key(md5)],
+ Data = rfc_2202_msgs() ++ [long_msg()],
+ Hmac = rfc_2202_hmac_md5() ++ [long_hmac(md5)],
[{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
group_config(ripemd160 = Type, Config) ->
Msgs = ripemd160_msgs(),
Digests = ripemd160_digests(),
[{hash, {Type, Msgs, Digests}} | Config];
group_config(sha = Type, Config) ->
- Msgs = [rfc_4634_test1(), rfc_4634_test2_1()],
- Digests = rfc_4634_sha_digests(),
- Keys = rfc_2202_sha_keys(),
- Data = rfc_2202_msgs(),
- Hmac = rfc_2202_hmac_sha(),
+ Msgs = [rfc_4634_test1(), rfc_4634_test2_1(),long_msg()],
+ Digests = rfc_4634_sha_digests() ++ [long_sha_digest()],
+ Keys = rfc_2202_sha_keys() ++ [long_hmac_key(sha)],
+ Data = rfc_2202_msgs() ++ [long_msg()],
+ Hmac = rfc_2202_hmac_sha() ++ [long_hmac(sha)],
[{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
group_config(sha224 = Type, Config) ->
Msgs = [rfc_4634_test1(), rfc_4634_test2_1()],
@@ -609,25 +614,25 @@ group_config(sha224 = Type, Config) ->
Hmac = rfc4231_hmac_sha224(),
[{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
group_config(sha256 = Type, Config) ->
- Msgs = [rfc_4634_test1(), rfc_4634_test2_1()],
- Digests = rfc_4634_sha256_digests(),
- Keys = rfc_4231_keys(),
- Data = rfc_4231_msgs(),
- Hmac = rfc4231_hmac_sha256(),
+ Msgs = [rfc_4634_test1(), rfc_4634_test2_1(), long_msg()],
+ Digests = rfc_4634_sha256_digests() ++ [long_sha256_digest()],
+ Keys = rfc_4231_keys() ++ [long_hmac_key(sha256)],
+ Data = rfc_4231_msgs() ++ [long_msg()],
+ Hmac = rfc4231_hmac_sha256() ++ [long_hmac(sha256)],
[{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
group_config(sha384 = Type, Config) ->
- Msgs = [rfc_4634_test1(), rfc_4634_test2()],
- Digests = rfc_4634_sha384_digests(),
- Keys = rfc_4231_keys(),
- Data = rfc_4231_msgs(),
- Hmac = rfc4231_hmac_sha384(),
+ Msgs = [rfc_4634_test1(), rfc_4634_test2(), long_msg()],
+ Digests = rfc_4634_sha384_digests() ++ [long_sha384_digest()],
+ Keys = rfc_4231_keys() ++ [long_hmac_key(sha384)],
+ Data = rfc_4231_msgs() ++ [long_msg()],
+ Hmac = rfc4231_hmac_sha384() ++ [long_hmac(sha384)],
[{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
group_config(sha512 = Type, Config) ->
- Msgs = [rfc_4634_test1(), rfc_4634_test2()],
- Digests = rfc_4634_sha512_digests(),
- Keys = rfc_4231_keys(),
- Data = rfc_4231_msgs(),
- Hmac = rfc4231_hmac_sha512(),
+ Msgs = [rfc_4634_test1(), rfc_4634_test2(), long_msg()],
+ Digests = rfc_4634_sha512_digests() ++ [long_sha512_digest()],
+ Keys = rfc_4231_keys() ++ [long_hmac_key(sha512)],
+ Data = rfc_4231_msgs() ++ [long_msg()],
+ Hmac = rfc4231_hmac_sha512() ++ [long_hmac(sha512)],
[{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
group_config(rsa = Type, Config) ->
Msg = rsa_plain(),
@@ -789,6 +794,23 @@ rfc_4634_sha512_digests() ->
"454D4423643CE80E2A9AC94FA54CA49F"),
hexstr2bin("8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA17299AEADB6889018501D289E4900F7E4331B99DEC4B5433AC7D329EEB6DD26545E96E55B874BE909")].
+long_msg() ->
+ lists:duplicate(1000000, $a).
+
+long_sha_digest() ->
+ hexstr2bin("34aa973c" "d4c4daa4" "f61eeb2b" "dbad2731" "6534016f").
+
+long_sha256_digest() ->
+ hexstr2bin("cdc76e5c" "9914fb92" "81a1c7e2" "84d73e67" "f1809a48" "a497200e" "046d39cc" "c7112cd0").
+
+long_sha384_digest() ->
+ hexstr2bin("9d0e1809716474cb" "086e834e310a4a1c" "ed149e9c00f24852" "7972cec5704c2a5b"
+ "07b8b3dc38ecc4eb" "ae97ddd87f3d8985").
+
+long_sha512_digest() ->
+ hexstr2bin("e718483d0ce76964" "4e2e42c7bc15b463" "8e1f98b13b204428" "5632a803afa973eb"
+ "de0ff244877ea60a" "4cb0432ce577c31b" "eb009c5c2c49aa2e" "4eadb217ad8cc09b").
+
ripemd160_msgs() ->
[<<"">>,
<<"a">>,
@@ -852,6 +874,35 @@ hmac_key(_) ->
hmac_inc(_) ->
[<<"Sampl">>, <<"e #1">>].
+%% https://www.cosic.esat.kuleuven.be/nessie/testvectors/
+long_hmac_key(Type) when Type == sha384;
+ Type == sha512 ->
+ hexstr2bin("00112233445566778899AABBCCDDEEFF"
+ "0123456789ABCDEF0011223344556677"
+ "8899AABBCCDDEEFF0123456789ABCDEF"
+ "00112233445566778899AABBCCDDEEFF");
+long_hmac_key(_) ->
+ hexstr2bin("0123456789ABCDEF0123456789ABCDEF"
+ "0123456789ABCDEF0123456789ABCDEF"
+ "0123456789ABCDEF0123456789ABCDEF"
+ "0123456789ABCDEF0123456789ABCDEF").
+long_hmac(md5) ->
+ hexstr2bin("82FDDA30202CB6ACC6F24D4F8A50EB7A");
+long_hmac(sha) ->
+ hexstr2bin("61D1D0B6459860755FDA892938C23DD401E54A7E");
+long_hmac(sha256) ->
+ hexstr2bin("50008B8DC7ED3926936347FDC1A01E9D"
+ "5220C6CC4B038B482C0F28A4CD88CA37");
+long_hmac(sha384) ->
+ hexstr2bin("C1EB08DAFA015833D3FC6B29A387558B"
+ "3F6FA1524AA1A8EB64798D5A76A39D6E"
+ "A1465525342E060EE996277B4FFCDDC9");
+long_hmac(sha512) ->
+ hexstr2bin("D116BF471AAE1264854F1906025E846A"
+ "61618A965FCA30B695220EA2D6E547E3"
+ "F3B5A4B54E6778928C26D5D3D810498E"
+ "8DF86CB3CC1E9F66A00419B13B6B0C9A").
+
rfc_2202_hmac_md5() ->
[
hexstr2bin("9294727a3638bb1c13f48ef8158bfc9d"),
@@ -1193,7 +1244,8 @@ blowfish_ofb64() ->
rc4() ->
[{rc4, <<"apaapa">>, <<"Yo baby yo">>},
- {rc4, <<"apaapa">>, list_to_binary(lists:seq(0, 255))}
+ {rc4, <<"apaapa">>, list_to_binary(lists:seq(0, 255))},
+ {rc4, <<"apaapa">>, lists:duplicate(1000000, $a)}
].
aes_ctr() ->
@@ -1237,7 +1289,11 @@ aes_ctr() ->
hexstr2bin("30c81c46a35ce411e5fbc1191a0a52ef")},
{aes_ctr, hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff02"),
- hexstr2bin("f69f2445df4f9b17ad2b417be66c3710")}
+ hexstr2bin("f69f2445df4f9b17ad2b417be66c3710")},
+
+ {aes_ctr, hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
+ hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
+ lists:duplicate(1000000, $a)}
].
rsa_plain() ->
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
index 2a0cb57aa9..d5d7c8a128 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 2.3
+CRYPTO_VSN = 3.0
diff --git a/lib/diameter/Makefile b/lib/diameter/Makefile
index 9961d627cf..aa1c9f7f20 100644
--- a/lib/diameter/Makefile
+++ b/lib/diameter/Makefile
@@ -1,7 +1,7 @@
-#
+#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2012. All Rights Reserved.
+# Copyright Ericsson AB 2010-2013. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -22,11 +22,11 @@ include vsn.mk
include subdirs.mk
SUB_DIRECTORIES = $(SUB_DIRS) doc/src
-SPECIAL_TARGETS =
+SPECIAL_TARGETS =
include $(ERL_TOP)/make/otp_subdir.mk
-info:
+info:
@echo "APP_VSN = $(APP_VSN)"
.PHONY: info
diff --git a/lib/diameter/doc/src/Makefile b/lib/diameter/doc/src/Makefile
index 99a6680f12..bd2b6b103a 100644
--- a/lib/diameter/doc/src/Makefile
+++ b/lib/diameter/doc/src/Makefile
@@ -1,4 +1,4 @@
-#
+#
# %CopyrightBegin%
#
# Copyright Ericsson AB 2010-2013. All Rights Reserved.
@@ -117,7 +117,7 @@ info:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
index eda9496e81..db19fbb271 100644
--- a/lib/diameter/doc/src/diameter.xml
+++ b/lib/diameter/doc/src/diameter.xml
@@ -29,12 +29,12 @@ Version 1.1, (the "License"); you may not use this file except in
compliance with the License. You should have received a copy of the
Erlang Public License along with this software. If not, it can be
retrieved online at http://www.erlang.org/.
-
+
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.
-
+
</legalnotice>
<title>diameter(3)</title>
@@ -1652,7 +1652,7 @@ The <c>caps</c> entry identifies the capabilities sent by the local
node and received from the peer during capabilities exchange.
The <c>port</c> entry displays socket-level information about the
transport connection.
-The <c>statistics</c> entry presents Diameter-level counters,
+The <c>statistics</c> entry presents Diameter-level counters,
an entry like <c>{{{0,280,1},recv},2}</c> saying that the client has
received 2 DWR messages: <c>{0,280,1} = {Application_Id, Command_Code,
R_Flag}</c>.</p>
diff --git a/lib/diameter/doc/src/diameter_compile.xml b/lib/diameter/doc/src/diameter_compile.xml
index fc81e4efed..6630019e5c 100644
--- a/lib/diameter/doc/src/diameter_compile.xml
+++ b/lib/diameter/doc/src/diameter_compile.xml
@@ -16,9 +16,9 @@
</copyright>
<legalnotice>
-The program may be used and/or copied only with the written permission
-from Ericsson AB, or in accordance with the terms and conditions
-stipulated in the agreement/contract under which the program has been
+The program may be used and/or copied only with the written permission
+from Ericsson AB, or in accordance with the terms and conditions
+stipulated in the agreement/contract under which the program has been
supplied.
</legalnotice>
diff --git a/lib/diameter/doc/src/diameter_dict.xml b/lib/diameter/doc/src/diameter_dict.xml
index 419dc143af..4fcde495b3 100644
--- a/lib/diameter/doc/src/diameter_dict.xml
+++ b/lib/diameter/doc/src/diameter_dict.xml
@@ -25,12 +25,12 @@ Version 1.1, (the "License"); you may not use this file except in
compliance with the License. You should have received a copy of the
Erlang Public License along with this software. If not, it can be
retrieved online at http://www.erlang.org/.
-
+
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.
-
+
</legalnotice>
<title>diameter_dict(4)</title>
diff --git a/lib/diameter/doc/src/diameter_intro.xml b/lib/diameter/doc/src/diameter_intro.xml
index fd578ccf45..288ebc0c7c 100644
--- a/lib/diameter/doc/src/diameter_intro.xml
+++ b/lib/diameter/doc/src/diameter_intro.xml
@@ -7,7 +7,7 @@
<chapter>
<header>
<copyright>
-<year>2011</year><year>2012</year>
+<year>2011</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
@@ -17,12 +17,12 @@ Version 1.1, (the "License"); you may not use this file except in
compliance with the License. You should have received a copy of the
Erlang Public License along with this software. If not, it can be
retrieved online at http://www.erlang.org/.
-
+
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.
-
+
</legalnotice>
<title>Introduction</title>
diff --git a/lib/diameter/doc/src/diameter_sctp.xml b/lib/diameter/doc/src/diameter_sctp.xml
index df140b16b9..5fe14b1ef6 100644
--- a/lib/diameter/doc/src/diameter_sctp.xml
+++ b/lib/diameter/doc/src/diameter_sctp.xml
@@ -70,10 +70,15 @@ and implements the behaviour documented in
<v>Type = connect | accept</v>
<v>Ref = &mod_transport_ref;</v>
<v>Svc = #diameter_service{}</v>
-<v>Opt = {raddr, &ip_address;} | {rport, integer()} | term()</v>
+<v>Opt = OwnOpt | SctpOpt</v>
<v>Pid = pid()</v>
<v>LAddr = &ip_address;</v>
<v>Reason = term()</v>
+<v>OwnOpt = {raddr, &ip_address;}
+ | {rport, integer()}
+ | {accept, Match}</v>
+<v>SctpOpt = term()</v>
+<v>Match = &ip_address; | string() | [Match]</v>
</type>
<desc>
@@ -85,9 +90,20 @@ Options <c>raddr</c> and <c>rport</c> specify the remote address
and port for a connecting transport and not valid for a listening
transport: the former is required while latter defaults to 3868 if
unspecified.
-More than one <c>raddr</c> option can be specified, in which case the
+Mupltiple <c>raddr</c> options can be specified, in which case the
connecting transport in question attempts each in sequence until
-an association is established.
+an association is established.</p>
+
+<p>
+Option <c>accept</c> specifies remote addresses for a listening
+transport and is not valid for a connecting transport.
+If specified, a remote address that does not match one of the
+specified addresses causes the association to be aborted.
+Multiple <c>accept</c> options can be specified.
+A string-valued <c>Match</c> that does not parse as an address is
+interpreted as a regular expression.</p>
+
+<p>
Remaining options are any accepted by &gen_sctp_open1;, with the exception
of options <c>mode</c>, <c>binary</c>, <c>list</c>, <c>active</c>
and <c>sctp_events</c>.
diff --git a/lib/diameter/doc/src/diameter_tcp.xml b/lib/diameter/doc/src/diameter_tcp.xml
index 8e509aa829..ce4d6cfd0f 100644
--- a/lib/diameter/doc/src/diameter_tcp.xml
+++ b/lib/diameter/doc/src/diameter_tcp.xml
@@ -96,10 +96,12 @@ before configuring TLS capability on diameter transports.</p>
<v>Reason = term()</v>
<v>OwnOpt = {raddr, &ip_address;}
| {rport, integer()}
+ | {accept, Match}
| {port, integer()}
| {fragment_timer, infinity | 0..16#FFFFFFFF}</v>
<v>SslOpt = {ssl_options, true | list()}</v>
<v>TcpOpt = term()</v>
+<v>Match = &ip_address; | string() | [Match]</v>
</type>
<desc>
@@ -109,7 +111,18 @@ The start function required by &man_transport;.</p>
<p>
Options <c>raddr</c> and <c>rport</c> specify the remote address
and port for a connecting transport and are not valid for a listening
-transport.
+transport.</p>
+
+<p>
+Option <c>accept</c> specifies remote addresses for a listening
+transport and is not valid for a connecting transport.
+If specified, a remote address that does not match one of the
+specified addresses causes the connection to be aborted.
+Multiple <c>accept</c> options can be specified.
+A string-valued <c>Match</c> that does not parse as an address is
+interpreted as a regular expression.</p>
+
+<p>
Option <c>ssl_options</c> must be specified for a transport
that should support TLS: a value of <c>true</c> results in a
TLS handshake immediately upon connection establishment while
diff --git a/lib/diameter/doc/src/diameter_using.xml b/lib/diameter/doc/src/diameter_using.xml
index 7d9c0cd492..c487d94a16 100644
--- a/lib/diameter/doc/src/diameter_using.xml
+++ b/lib/diameter/doc/src/diameter_using.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
-<year>2011</year><year>2012</year>
+<year>2011</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
@@ -15,12 +15,12 @@ Version 1.1, (the "License"); you may not use this file except in
compliance with the License. You should have received a copy of the
Erlang Public License along with this software. If not, it can be
retrieved online at http://www.erlang.org/.
-
+
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.
-
+
</legalnotice>
<title>Usage</title>
diff --git a/lib/diameter/src/Makefile b/lib/diameter/src/Makefile
index c0cf418f06..578bbaee2e 100644
--- a/lib/diameter/src/Makefile
+++ b/lib/diameter/src/Makefile
@@ -1,19 +1,19 @@
-#
+#
# %CopyrightBegin%
-#
+#
# Copyright Ericsson AB 2010-2013. All Rights Reserved.
-#
+#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of the
# Erlang Public License along with this software. If not, it can be
# retrieved online at http://www.erlang.org/.
-#
+#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and limitations
# under the License.
-#
+#
# %CopyrightEnd%
include $(ERL_TOP)/make/target.mk
diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index 6c0e73de36..1d647b8c87 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -204,7 +204,7 @@ msg_header(Mod, 'answer-message' = MsgName, Header) ->
#diameter_header{application_id = Aid,
cmd_code = Code}
= Header,
- {-1, Flags, ?DIAMETER_APP_ID_COMMON} = Mod:msg_header(MsgName),
+ {-1, Flags, ?APP_ID_COMMON} = Mod:msg_header(MsgName),
{Code, Flags, Aid};
msg_header(Mod, MsgName, _) ->
diff --git a/lib/diameter/src/base/diameter_peer.erl b/lib/diameter/src/base/diameter_peer.erl
index 0d2efd4d1f..e5d4b28766 100644
--- a/lib/diameter/src/base/diameter_peer.erl
+++ b/lib/diameter/src/base/diameter_peer.erl
@@ -25,7 +25,8 @@
-export([recv/2,
up/1,
up/2,
- up/3]).
+ up/3,
+ match/2]).
%% ... and the stack.
-export([start/1,
@@ -63,16 +64,16 @@
-define(DEFAULT_TCFG, []).
-define(DEFAULT_TTMO, infinity).
-%%% ---------------------------------------------------------------------------
-%%% # notify/3
-%%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+%% # notify/3
+%% ---------------------------------------------------------------------------
notify(Nodes, SvcName, T) ->
rpc:abcast(Nodes, ?SERVER, {notify, SvcName, T}).
-%%% ---------------------------------------------------------------------------
-%%% # start/1
-%%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+%% # start/1
+%% ---------------------------------------------------------------------------
-spec start({T, [Opt], #diameter_service{}})
-> {TPid, [Addr], Tmo, Data}
@@ -180,9 +181,34 @@ start(T, [M|Ms], Cfg, Svc, Tmo, Rest, Errs) ->
start(Mod, Args) ->
apply(Mod, start, Args).
-%%% ---------------------------------------------------------------------------
-%%% # up/1-3
-%%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+%% # match/2
+%% ---------------------------------------------------------------------------
+
+match(Addrs, Matches)
+ when is_list(Addrs) ->
+ lists:all(fun(A) -> match1(A, Matches) end, Addrs).
+
+match1(Addr, Matches)
+ when not is_integer(hd(Matches)) ->
+ lists:any(fun(M) -> match1(Addr, M) end, Matches);
+
+match1(Addr, Match) ->
+ match(Addr, addr(Match), Match).
+
+match(Addr, {ok, A}, _) ->
+ Addr == A;
+match(Addr, {error, _}, RE) ->
+ match == re:run(inet_parse:ntoa(Addr), RE, [{capture, none}]).
+
+addr([_|_] = A) ->
+ inet_parse:address(A);
+addr(A) ->
+ {ok, A}.
+
+%% ---------------------------------------------------------------------------
+%% # up/1-3
+%% ---------------------------------------------------------------------------
up(Pid) -> %% accepting transport
ifc_send(Pid, {self(), connected}).
@@ -193,16 +219,16 @@ up(Pid, Remote) -> %% connecting transport
up(Pid, Remote, LAddrs) -> %% connecting transport
ifc_send(Pid, {self(), connected, Remote, LAddrs}).
-%%% ---------------------------------------------------------------------------
-%%% # recv/2
-%%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+%% # recv/2
+%% ---------------------------------------------------------------------------
recv(Pid, Pkt) ->
ifc_send(Pid, {recv, Pkt}).
-%%% ---------------------------------------------------------------------------
-%%% # send/2
-%%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+%% # send/2
+%% ---------------------------------------------------------------------------
send(Pid, #diameter_packet{transport_data = undefined,
bin = Bin}) ->
@@ -211,16 +237,16 @@ send(Pid, #diameter_packet{transport_data = undefined,
send(Pid, Pkt) ->
ifc_send(Pid, {send, Pkt}).
-%%% ---------------------------------------------------------------------------
-%%% # close/1
-%%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+%% # close/1
+%% ---------------------------------------------------------------------------
close(Pid) ->
ifc_send(Pid, {close, self()}).
-%%% ---------------------------------------------------------------------------
-%%% # abort/1
-%%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+%% # abort/1
+%% ---------------------------------------------------------------------------
abort(Pid) ->
exit(Pid, shutdown).
@@ -241,16 +267,16 @@ state() ->
uptime() ->
call(uptime).
-%%% ----------------------------------------------------------
-%%% # init(Role)
-%%% ----------------------------------------------------------
+%% ----------------------------------------------------------
+%% # init(Role)
+%% ----------------------------------------------------------
init([]) ->
{ok, #state{}}.
-%%% ----------------------------------------------------------
-%%% # handle_call(Request, From, State)
-%%% ----------------------------------------------------------
+%% ----------------------------------------------------------
+%% # handle_call(Request, From, State)
+%% ----------------------------------------------------------
handle_call(state, _, State) ->
{reply, State, State};
@@ -262,17 +288,17 @@ handle_call(Req, From, State) ->
?UNEXPECTED([Req, From]),
{reply, nok, State}.
-%%% ----------------------------------------------------------
-%%% # handle_cast(Request, State)
-%%% ----------------------------------------------------------
+%% ----------------------------------------------------------
+%% # handle_cast(Request, State)
+%% ----------------------------------------------------------
handle_cast(Msg, State) ->
?UNEXPECTED([Msg]),
{noreply, State}.
-%%% ----------------------------------------------------------
-%%% # handle_info(Request, State)
-%%% ----------------------------------------------------------
+%% ----------------------------------------------------------
+%% # handle_info(Request, State)
+%% ----------------------------------------------------------
%% Remote service is distributing a message.
handle_info({notify, SvcName, T}, S) ->
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 6f81ade30e..8b6f026b34 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -791,7 +791,7 @@ failed([MsgName | Values], FailedAvp, Dict) ->
%% ... or record.
failed(Rec, FailedAvp, Dict) ->
try
- RecName = element(1, Rec),
+ RecName = element(1, Rec),
Dict:'#info-'(RecName, {index, 'Failed-AVP'}),
{'Failed-AVP', [FailedAvp]}
catch
diff --git a/lib/diameter/src/base/diameter.app.src b/lib/diameter/src/diameter.app.src
index ceefb9b398..ceefb9b398 100644
--- a/lib/diameter/src/base/diameter.app.src
+++ b/lib/diameter/src/diameter.app.src
diff --git a/lib/diameter/src/base/diameter.appup.src b/lib/diameter/src/diameter.appup.src
index 359f434941..62ace16faa 100644
--- a/lib/diameter/src/base/diameter.appup.src
+++ b/lib/diameter/src/diameter.appup.src
@@ -31,10 +31,36 @@
{"1.4", [{restart_application, diameter}]}, %% R16A
{"1.4.1", [{load_module, diameter_reg}, %% R16B
{load_module, diameter_stats},
+ {load_module, diameter_traffic},
{load_module, diameter_service},
+ {load_module, diameter_config},
+ {load_module, diameter_peer},
+ {load_module, diameter_peer_fsm},
{load_module, diameter_watchdog},
{load_module, diameter_capx},
- {load_module, diameter}]}
+ {load_module, diameter_codec},
+ {load_module, diameter_gen_base_rfc3588},
+ {load_module, diameter_gen_base_accounting},
+ {load_module, diameter_gen_base_rfc6733},
+ {load_module, diameter_gen_base_acct6733},
+ {load_module, diameter_tcp},
+ {load_module, diameter_lib},
+ {load_module, diameter}]},
+ {"1.4.1.1", [{load_module, diameter_traffic},
+ {load_module, diameter_service},
+ {load_module, diameter_config},
+ {load_module, diameter_peer},
+ {load_module, diameter_peer_fsm},
+ {load_module, diameter_watchdog},
+ {load_module, diameter_capx},
+ {load_module, diameter_codec},
+ {load_module, diameter_gen_base_rfc3588},
+ {load_module, diameter_gen_base_accounting},
+ {load_module, diameter_gen_base_rfc6733},
+ {load_module, diameter_gen_base_acct6733},
+ {load_module, diameter_tcp},
+ {load_module, diameter_lib},
+ {load_module, diameter}]}
],
[
{"0.9", [{restart_application, diameter}]},
@@ -46,6 +72,7 @@
{"1.3", [{restart_application, diameter}]},
{"1.3.1", [{restart_application, diameter}]},
{"1.4", [{restart_application, diameter}]},
- {"1.4.1", [{restart_application, diameter}]}
+ {"1.4.1", [{restart_application, diameter}]},
+ {"1.4.1.1", [{restart_application, diameter}]}
]
}.
diff --git a/lib/diameter/src/dict/base_rfc3588.dia b/lib/diameter/src/dict/base_rfc3588.dia
index acd7fffd00..43a417b8dc 100644
--- a/lib/diameter/src/dict/base_rfc3588.dia
+++ b/lib/diameter/src/dict/base_rfc3588.dia
@@ -1,7 +1,7 @@
;;
;; %CopyrightBegin%
;;
-;; Copyright Ericsson AB 2010-2011. All Rights Reserved.
+;; Copyright Ericsson AB 2010-2013. All Rights Reserved.
;;
;; The contents of this file are subject to the Erlang Public License,
;; Version 1.1, (the "License"); you may not use this file except in
@@ -421,7 +421,7 @@
DIAMETER_INVALID_AVP_BIT_COMBO 5016
DIAMETER_NO_COMMON_SECURITY 5017
-@grouped
+@grouped
Proxy-Info ::= < AVP Header: 284 >
{ Proxy-Host }
@@ -440,7 +440,7 @@
[ Auth-Application-Id ]
[ Acct-Application-Id ]
-;; The E2E-Sequence AVP is defined in RFC 3588 as Grouped, but
+;; The E2E-Sequence AVP is defined in RFC 3588 as Grouped, but
;; there is no definition of the group - only an informal text stating
;; that there should be a nonce (an OctetString) and a counter
;; (integer)
diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl
index 8b8c2a6694..49a530b4eb 100644
--- a/lib/diameter/src/transport/diameter_sctp.erl
+++ b/lib/diameter/src/transport/diameter_sctp.erl
@@ -42,6 +42,9 @@
-export([ports/0,
ports/1]).
+-export_type([listen_option/0,
+ connect_option/0]).
+
-include_lib("kernel/include/inet_sctp.hrl").
-include_lib("diameter/include/diameter.hrl").
@@ -54,6 +57,9 @@
%% The default port for a listener.
-define(DEFAULT_PORT, 3868). %% RFC 3588, ch 2.1
+%% Remote addresses to accept connections from.
+-define(DEFAULT_ACCEPT, []). %% any
+
%% How long a listener with no associations lives before offing
%% itself.
-define(LISTENER_TIMEOUT, 30000).
@@ -62,6 +68,17 @@
%% association establishment.
-define(ACCEPT_TIMEOUT, 5000).
+-type connect_option() :: {raddr, inet:ip_address()}
+ | {rport, inet:port_number()}
+ | gen_sctp:open_option().
+
+-type match() :: inet:ip_address()
+ | string()
+ | [match()].
+
+-type listen_option() :: {accept, match()}
+ | gen_sctp:open_option().
+
-type uint() :: non_neg_integer().
%% Accepting/connecting transport process state.
@@ -69,7 +86,7 @@
{parent :: pid(),
mode :: {accept, pid()}
| accept
- | {connect, {list(inet:ip_address()), uint(), list()}}
+ | {connect, {[inet:ip_address()], uint(), list()}}
%% {RAs, RP, Errors}
| connect,
socket :: gen_sctp:sctp_socket(),
@@ -86,7 +103,8 @@
tmap = ets:new(?MODULE, []) :: ets:tid(),
%% {MRef, Pid|AssocId}, {AssocId, Pid}
pending = {0, ets:new(?MODULE, [ordered_set])},
- tref :: reference()}).
+ tref :: reference(),
+ accept :: [match()]}).
%% Field tmap is used to map an incoming message or event to the
%% relevent transport process. Field pending implements a queue of
%% transport processes to which an association has been assigned (at
@@ -102,6 +120,13 @@
%% # start/3
%% ---------------------------------------------------------------------------
+-spec start({accept, Ref}, #diameter_service{}, [listen_option()])
+ -> {ok, pid(), [inet:ip_address()]}
+ when Ref :: diameter:transport_ref();
+ ({connect, Ref}, #diameter_service{}, [connect_option()])
+ -> {ok, pid(), [inet:ip_address()]}
+ when Ref :: diameter:transport_ref().
+
start(T, #diameter_service{capabilities = Caps}, Opts)
when is_list(Opts) ->
diameter_sctp_sup:start(), %% start supervisors on demand
@@ -169,12 +194,14 @@ init(T) ->
%% A process owning a listening socket.
i({listen, Ref, {Opts, Addrs}}) ->
- {LAs, Sock} = AS = open(Addrs, Opts, ?DEFAULT_PORT),
+ {[Matches], Rest} = proplists:split(Opts, [accept]),
+ {LAs, Sock} = AS = open(Addrs, Rest, ?DEFAULT_PORT),
proc_lib:init_ack({ok, self(), LAs}),
ok = gen_sctp:listen(Sock, true),
true = diameter_reg:add_new({?MODULE, listener, {Ref, AS}}),
start_timer(#listener{ref = Ref,
- socket = Sock});
+ socket = Sock,
+ accept = accept(Matches)});
%% A connecting transport.
i({connect, Pid, Opts, Addrs, Ref}) ->
@@ -311,6 +338,9 @@ handle_call({{accept, Ref}, Pid}, _, #listener{ref = Ref,
{TPid, NewS} = accept(Ref, Pid, S),
{reply, {ok, TPid}, NewS#listener{count = N+1}};
+handle_call(T, From, {listener,_,_,_,_,_,_} = S) -> % started in old code
+ handle_call(T, From, upgrade(S));
+
handle_call(_, _, State) ->
{reply, nok, State}.
@@ -329,7 +359,10 @@ handle_info(T, #transport{} = S) ->
{noreply, #transport{} = t(T,S)};
handle_info(T, #listener{} = S) ->
- {noreply, #listener{} = l(T,S)}.
+ {noreply, #listener{} = l(T,S)};
+
+handle_info(T, {listener,_,_,_,_,_,_} = S) -> % started in old code
+ handle_info(T, upgrade(S)).
%% ---------------------------------------------------------------------------
%% # code_change/3
@@ -363,6 +396,9 @@ terminate(_, #listener{socket = Sock}) ->
%% ---------------------------------------------------------------------------
+upgrade(S) ->
+ #listener{} = erlang:append_element(S, ?DEFAULT_ACCEPT).
+
putr(Key, Val) ->
put({?MODULE, Key}, Val).
@@ -386,7 +422,7 @@ l({sctp, Sock, _RA, _RP, Data} = Msg, #listener{socket = Sock} = S) ->
try find(Id, Data, S) of
{TPid, NewS} ->
- TPid ! {peeloff, peeloff(Sock, Id, TPid), Msg},
+ TPid ! {peeloff, peeloff(Sock, Id, TPid), Msg, S#listener.accept},
NewS;
false ->
S
@@ -460,11 +496,14 @@ t(T,S) ->
%% transition/2
%% Listening process is transfering ownership of an association.
-transition({peeloff, Sock, {sctp, LSock, _RA, _RP, _Data} = Msg},
+transition({peeloff, Sock, {sctp, LSock, _RA, _RP, _Data} = Msg, Matches},
#transport{mode = {accept, _},
socket = LSock}
= S) ->
+ ok = accept_peer(Sock, Matches),
transition(Msg, S#transport{socket = Sock});
+transition({peeloff = T, _Sock, _Msg} = T, #transport{} = S) ->% from old code
+ transition(erlang:append_element(T, ?DEFAULT_ACCEPT), S);
%% Incoming message.
transition({sctp, _Sock, _RA, _RP, Data}, #transport{socket = Sock} = S) ->
@@ -510,6 +549,27 @@ transition({resolve_port, Pid}, #transport{socket = Sock})
%% Crash on anything unexpected.
+ok({ok, T}) ->
+ T;
+ok(T) ->
+ x(T).
+
+%% accept_peer/2
+
+accept_peer(_, []) ->
+ ok;
+
+accept_peer(Sock, Matches) ->
+ {RAddrs, _} = ok(inet:peername(Sock)),
+ diameter_peer:match(RAddrs, Matches)
+ orelse x({accept, RAddrs, Matches}),
+ ok.
+
+%% accept/1
+
+accept(Opts) ->
+ [[M] || {accept, M} <- Opts].
+
%% accept/3
%%
%% Start a new transport process or use one that's already been
diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl
index cbbba714ac..4d1b8bec51 100644
--- a/lib/diameter/src/transport/diameter_tcp.erl
+++ b/lib/diameter/src/transport/diameter_tcp.erl
@@ -42,6 +42,9 @@
-export([ports/0,
ports/1]).
+-export_type([connect_option/0,
+ listen_option/0]).
+
-include_lib("diameter/include/diameter.hrl").
%% Keys into process dictionary.
@@ -80,6 +83,25 @@
-type frag() :: {length(), size(), binary(), list(binary())}
| binary().
+-type connect_option() :: {raddr, inet:ip_address()}
+ | {rport, pos_integer()}
+ | {ssl_options, true | [ssl:connect_option()]}
+ | option()
+ | ssl:connect_option()
+ | gen_tcp:connect_option().
+
+-type match() :: inet:ip_address()
+ | string()
+ | [match()].
+
+-type listen_option() :: {accept, match()}
+ | {ssl_options, true | [ssl:listen_option()]}
+ | ssl:listen_option()
+ | gen_tcp:listen_option().
+
+-type option() :: {port, non_neg_integer()}
+ | {fragment_timer, 0..16#FFFFFFFF}.
+
%% Accepting/connecting transport process state.
-record(transport,
{socket :: inet:socket() | ssl:sslsocket(), %% accept/connect socket
@@ -100,18 +122,14 @@
%% # start/3
%% ---------------------------------------------------------------------------
--spec start({accept, Ref}, Svc, [Opt])
+-spec start({accept, Ref}, #diameter_service{}, [listen_option()])
-> {ok, pid(), [inet:ip_address()]}
- when Ref :: diameter:transport_ref(),
- Svc :: #diameter_service{},
- Opt :: diameter:transport_opt();
- ({connect, Ref}, Svc, [Opt])
+ when Ref :: diameter:transport_ref();
+ ({connect, Ref}, #diameter_service{}, [connect_option()])
-> {ok, pid(), [inet:ip_address()]}
| {ok, pid()}
- when Ref :: diameter:transport_ref(),
- Svc :: #diameter_service{},
- Opt :: diameter:transport_opt().
-
+ when Ref :: diameter:transport_ref().
+
start({T, Ref}, #diameter_service{capabilities = Caps}, Opts) ->
diameter_tcp_sup:start(), %% start tcp supervisors on demand
{Mod, Rest} = split(Opts),
@@ -225,10 +243,10 @@ laddr([], Mod, Sock) ->
Addr;
laddr([{ip, Addr}], _, _) ->
Addr.
-
+
own(Opts) ->
- {Own, Rest} = proplists:split(Opts, [fragment_timer]),
- {lists:append(Own), Rest}.
+ {[Own], Rest} = proplists:split(Opts, [fragment_timer]),
+ {Own, Rest}.
ssl(Opts) ->
{[SslOpts], Rest} = proplists:split(Opts, [ssl_options]),
@@ -257,9 +275,11 @@ init(Type, Ref, Mod, Pid, _, Opts, Addrs) ->
%% init/6
init(accept = T, Ref, Mod, Pid, Opts, Addrs) ->
- {LAddr, LSock} = listener(Ref, {Mod, Opts, Addrs}),
+ {[Matches], Rest} = proplists:split(Opts, [accept]),
+ {LAddr, LSock} = listener(Ref, {Mod, Rest, Addrs}),
proc_lib:init_ack({ok, self(), [LAddr]}),
Sock = ok(accept(Mod, LSock)),
+ ok = accept_peer(Mod, Sock, accept(Matches)),
publish(Mod, T, Ref, Sock),
diameter_peer:up(Pid),
Sock;
@@ -282,7 +302,7 @@ init_rc([]) ->
up(Pid, Remote, [{ip, _Addr}], _, _) ->
diameter_peer:up(Pid, Remote);
-up(Pid, Remote, [], Mod, Sock) ->
+up(Pid, Remote, [], Mod, Sock) ->
{Addr, _Port} = ok(sockname(Mod, Sock)),
diameter_peer:up(Pid, Remote, [Addr]).
@@ -298,6 +318,22 @@ ok(No) ->
x(Reason) ->
exit({shutdown, Reason}).
+%% accept_peer/3
+
+accept_peer(_Mod, _Sock, []) ->
+ ok;
+
+accept_peer(Mod, Sock, Matches) ->
+ {RAddr, _} = ok(peername(Mod, Sock)),
+ diameter_peer:match([RAddr], Matches)
+ orelse x({accept, RAddr, Matches}),
+ ok.
+
+%% accept/1
+
+accept(Opts) ->
+ [[M] || {accept, M} <- Opts].
+
%% listener/2
listener(LRef, T) ->
diff --git a/lib/diameter/test/Makefile b/lib/diameter/test/Makefile
index 9719c67b32..aff1b18cf8 100644
--- a/lib/diameter/test/Makefile
+++ b/lib/diameter/test/Makefile
@@ -1,4 +1,4 @@
-#
+#
# %CopyrightBegin%
#
# Copyright Ericsson AB 2010-2013. All Rights Reserved.
@@ -76,7 +76,7 @@ any: opt
$(MAKE) -i $(SUITES)
clean:
- rm -f $(TARGET_FILES)
+ rm -f $(TARGET_FILES)
rm -f depend.mk coverspec
realclean: clean
@@ -159,7 +159,7 @@ log:
# ----------------------------------------------------
# Release Targets
-# ----------------------------------------------------
+# ----------------------------------------------------
/%: % force
sed -f release.sed $< > "$(RELSYSDIR)$@"
diff --git a/lib/diameter/test/diameter_codec_SUITE.erl b/lib/diameter/test/diameter_codec_SUITE.erl
index 2e219bbb10..cd8ca41f66 100644
--- a/lib/diameter/test/diameter_codec_SUITE.erl
+++ b/lib/diameter/test/diameter_codec_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
index 49f2158b1a..cdf0cf55e1 100644
--- a/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
+++ b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/diameter/test/diameter_examples_SUITE.erl b/lib/diameter/test/diameter_examples_SUITE.erl
index 1954bc319b..75b542b679 100644
--- a/lib/diameter/test/diameter_examples_SUITE.erl
+++ b/lib/diameter/test/diameter_examples_SUITE.erl
@@ -149,7 +149,7 @@ to_erl(File, Opts) ->
No ->
throw({make, No})
end.
-
+
to_beam(Name) ->
case compile:file(Name ++ ".erl", [return]) of
{ok, _, _} ->
diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl
index aa489fef5f..92c72c84e7 100644
--- a/lib/diameter/test/diameter_util.erl
+++ b/lib/diameter/test/diameter_util.erl
@@ -336,7 +336,7 @@ opts(Prot, T) ->
{transport_config, [{ip, ?ADDR}, {port, 0} | opts(T)]}].
opts(listen) ->
- [];
+ [{accept, M} || M <- [{256,0,0,1}, ["256.0.0.1", ["^.+$"]]]];
opts(PortNr) ->
[{raddr, ?ADDR}, {rport, PortNr}].
diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk
index 757f29a32e..f7462c3916 100644
--- a/lib/diameter/vsn.mk
+++ b/lib/diameter/vsn.mk
@@ -18,5 +18,5 @@
# %CopyrightEnd%
APPLICATION = diameter
-DIAMETER_VSN = 1.4.1.1
+DIAMETER_VSN = 1.4.2
APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN)
diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk
index 9287e105df..6f08d380ca 100644
--- a/lib/erl_interface/vsn.mk
+++ b/lib/erl_interface/vsn.mk
@@ -1 +1 @@
-EI_VSN = 3.7.12
+EI_VSN = 3.7.13
diff --git a/lib/et/vsn.mk b/lib/et/vsn.mk
index 99532ee3f3..40cdc2b298 100644
--- a/lib/et/vsn.mk
+++ b/lib/et/vsn.mk
@@ -1 +1 @@
-ET_VSN = 1.4.4.3
+ET_VSN = 1.4.4.4
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index aada1252ad..3ea530a366 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -947,21 +947,34 @@ gethostbyname_self(Name, Type) when is_atom(Name) ->
gethostbyname_self(Name, Type)
when is_list(Name), Type =:= inet;
is_list(Name), Type =:= inet6 ->
- case inet_db:gethostname() of
- Name ->
- {ok,make_hostent(Name,
- [translate_ip(loopback, Type)],
- [], Type)};
- Self ->
+ N = inet_db:tolower(Name),
+ Self = inet_db:gethostname(),
+ %%
+ %% This is the final fallback that pretends /etc/hosts has got
+ %% a line for the hostname on the loopback address.
+ %% Lookups into /etc/hosts are case insensitive and return
+ %% what is in the file. Therefore the letter case may differ between
+ %% the returned hostent record and the hostname that was asked for.
+ %%
+ case inet_db:tolower(Self) of
+ N ->
+ {ok,
+ make_hostent(
+ Self, [translate_ip(loopback, Type)], [], Type)};
+ _ ->
case inet_db:res_option(domain) of
- "" -> {error,nxdomain};
+ "" ->
+ {error,nxdomain};
Domain ->
- case lists:append([Self,".",Domain]) of
- Name ->
- {ok,make_hostent(Name,
- [translate_ip(loopback, Type)],
- [], Type)};
- _ -> {error,nxdomain}
+ FQDN = lists:append([Self,".",Domain]),
+ case inet_db:tolower(FQDN) of
+ N ->
+ {ok,
+ make_hostent(
+ FQDN,
+ [translate_ip(loopback, Type)], [], Type)};
+ _ ->
+ {error,nxdomain}
end
end
end;
diff --git a/lib/kernel/src/inet_db.erl b/lib/kernel/src/inet_db.erl
index d4749b9756..a7679c531b 100644
--- a/lib/kernel/src/inet_db.erl
+++ b/lib/kernel/src/inet_db.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -845,7 +845,8 @@ init([]) ->
process_flag(trap_exit, true),
Db = ets:new(inet_db, [public, named_table]),
reset_db(Db),
- Cache = ets:new(inet_cache, [public, bag, {keypos,2}, named_table]),
+ CacheOpts = [public, bag, {keypos,#dns_rr.domain}, named_table],
+ Cache = ets:new(inet_cache, CacheOpts),
BynameOpts = [protected, bag, named_table, {keypos,1}],
ByaddrOpts = [protected, bag, named_table, {keypos,3}],
HostsByname = ets:new(inet_hosts_byname, BynameOpts),
@@ -901,15 +902,21 @@ reset_db(Db) ->
handle_call(Request, From, #state{db=Db}=State) ->
case Request of
{load_hosts_file,IPNmAs} when is_list(IPNmAs) ->
- NIPs = lists:flatten([ [{N,if tuple_size(IP) =:= 4 -> inet;
- tuple_size(IP) =:= 8 -> inet6
- end,IP} || N <- [Nm|As]]
- || {IP,Nm,As} <- IPNmAs]),
+ NIPs =
+ lists:flatten(
+ [ [{N,
+ if tuple_size(IP) =:= 4 -> inet;
+ tuple_size(IP) =:= 8 -> inet6
+ end,IP} || N <- [Nm|As]]
+ || {IP,Nm,As} <- IPNmAs]),
Byname = State#state.hosts_file_byname,
Byaddr = State#state.hosts_file_byaddr,
ets:delete_all_objects(Byname),
ets:delete_all_objects(Byaddr),
- ets:insert(Byname, NIPs),
+ %% Byname has lowercased names while Byaddr keep the name casing.
+ %% This is to be able to reconstruct the original
+ %% /etc/hosts entry.
+ ets:insert(Byname, [{tolower(N),Type,IP} || {N,Type,IP} <- NIPs]),
ets:insert(Byaddr, NIPs),
{reply, ok, State};
@@ -938,16 +945,14 @@ handle_call(Request, From, #state{db=Db}=State) ->
{reply, ok, State};
{add_rr, RR} when is_record(RR, dns_rr) ->
- RR1 = lower_rr(RR),
- ?dbg("add_rr: ~p~n", [RR1]),
- do_add_rr(RR1, Db, State),
+ ?dbg("add_rr: ~p~n", [RR]),
+ do_add_rr(RR, Db, State),
{reply, ok, State};
{del_rr, RR} when is_record(RR, dns_rr) ->
- RR1 = lower_rr(RR),
%% note. del_rr will handle wildcards !!!
Cache = State#state.cache,
- ets:match_delete(Cache, RR1),
+ ets:match_delete(Cache, RR),
{reply, ok, State};
{lookup_rr, Domain, Class, Type} ->
@@ -1225,15 +1230,18 @@ handle_set_file(ParseFun, Bin, From, State) ->
handle_rc_list(Opts, From, State)
end.
+%% Byname has lowercased names while Byaddr keep the name casing.
+%% This is to be able to reconstruct the original /etc/hosts entry.
+
do_add_host(Byname, Byaddr, Names, Type, IP) ->
do_del_host(Byname, Byaddr, IP),
- NIPs = [{tolower(N),Type,IP} || N <- Names],
- ets:insert(Byname, NIPs),
- ets:insert(Byaddr, NIPs),
+ ets:insert(Byname, [{tolower(N),Type,IP} || N <- Names]),
+ ets:insert(Byaddr, [{N,Type,IP} || N <- Names]),
ok.
do_del_host(Byname, Byaddr, IP) ->
- [ets:delete_object(Byname, NIP) || NIP <- ets:lookup(Byaddr, IP)],
+ [ets:delete_object(Byname, {tolower(Name),Type,Addr}) ||
+ {Name,Type,Addr} <- ets:lookup(Byaddr, IP)],
ets:delete(Byaddr, IP),
ok.
@@ -1369,7 +1377,7 @@ times() ->
%% lookup and remove old entries
do_lookup_rr(Domain, Class, Type) ->
- match_rr(#dns_rr{domain = tolower(Domain), class = Class,type = Type,
+ match_rr(#dns_rr{domain = Domain, class = Class,type = Type,
cnt = '_', tm = '_', ttl = '_',
bm = '_', func = '_', data = '_'}).
@@ -1393,23 +1401,20 @@ filter_rr([], _Time) -> [].
%%
-%% Lower case the domain name before storage
-%%
-lower_rr(RR) ->
- Dn = RR#dns_rr.domain,
- if is_list(Dn) ->
- RR#dns_rr { domain = tolower(Dn) };
- true -> RR
- end.
-
+%% Case fold upper-case to lower-case according to RFC 4343
+%% "Domain Name System (DNS) Case Insensitivity Clarification".
%%
-%% Map upper-case to lower-case
%% NOTE: this code is in kernel and we don't want to relay
-%% to much on stdlib
+%% to much on stdlib. Furthermore string:to_lower/1
+%% does not follow RFC 4343.
%%
tolower([]) -> [];
-tolower([C|Cs]) when C >= $A, C =< $Z -> [(C-$A)+$a|tolower(Cs)];
-tolower([C|Cs]) -> [C|tolower(Cs)].
+tolower([C|Cs]) when is_integer(C) ->
+ if C >= $A, C =< $Z ->
+ [(C-$A)+$a|tolower(Cs)];
+ true ->
+ [C|tolower(Cs)]
+ end.
dn_ip6_int(A,B,C,D,E,F,G,H) ->
dnib(H) ++ dnib(G) ++ dnib(F) ++ dnib(E) ++
diff --git a/lib/kernel/src/inet_hosts.erl b/lib/kernel/src/inet_hosts.erl
index df1d4fc0be..6e9719b4aa 100644
--- a/lib/kernel/src/inet_hosts.erl
+++ b/lib/kernel/src/inet_hosts.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -38,9 +38,12 @@ gethostbyname(_) -> {error, formerr}.
gethostbyname(Name, Type) when is_list(Name), is_atom(Type) ->
- case gethostbyname(Name, Type, inet_hosts_byname, inet_hosts_byaddr) of
+ %% Byname has lowercased names while Byaddr keep the name casing.
+ %% This is to be able to reconstruct the original /etc/hosts entry.
+ N = inet_db:tolower(Name),
+ case gethostbyname(N, Type, inet_hosts_byname, inet_hosts_byaddr) of
false ->
- case gethostbyname(Name, Type,
+ case gethostbyname(N, Type,
inet_hosts_file_byname,
inet_hosts_file_byaddr) of
false -> {error,nxdomain};
diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl
index 59ba408d7a..94a9f7c64d 100644
--- a/lib/kernel/src/inet_res.erl
+++ b/lib/kernel/src/inet_res.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -181,8 +181,8 @@ lookup(Name, Class, Type, Opts, Timeout) ->
lookup_filter({ok,#dns_rec{anlist=Answers}}, Class, Type) ->
[A#dns_rr.data || A <- Answers,
- A#dns_rr.class =:= Class,
- A#dns_rr.type =:= Type];
+ Class =:= any orelse A#dns_rr.class =:= Class,
+ Type =:= any orelse A#dns_rr.type =:= Type];
lookup_filter({error,_}, _, _) -> [].
%% --------------------------------------------------------------------------
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index 1f7724d0dc..62ba95e1a3 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -183,80 +183,74 @@ t_gethostbyname(Config) when is_list(Config) ->
h_addr_list = [IP]},
?line HEntF_ = HEntF,
?line check_elems([{HEnt#hostent.h_aliases,[[],Aliases]}]),
+ %%
+ ?line FullNameU = toupper(FullName),
+ ?line {ok,HEntU} = inet:gethostbyname(FullNameU),
+ ?line FullNameU = toupper(HEntU#hostent.h_name),
+ ?line #hostent{
+ h_addrtype = inet,
+ h_length = 4,
+ h_addr_list = [IP]} = HEntU,
+ ?line check_elems(
+ [{[toupper(H) || H <- HEntU#hostent.h_aliases],
+ [[],[toupper(A) || A <- Aliases]]}]),
?line {DName, _DFullName, _DIPStr, _DIP, _, _, _} =
ct:get_config(test_dummy_host),
?line {error,nxdomain} = inet:gethostbyname(DName),
- ?line {error,nxdomain} = inet:gethostbyname(IP_46_Str).
+ ?line {error,nxdomain} = inet:gethostbyname(IP_46_Str),
+ ok.
t_gethostbyname_v6() -> required(v6).
t_gethostbyname_v6(doc) -> "Test the inet:gethostbyname/1 inet6 function.";
t_gethostbyname_v6(suite) -> [];
t_gethostbyname_v6(Config) when is_list(Config) ->
- ?line {Name, _, _, _,Aliases,IP_46_Str,IP_46} =
- ct:get_config(test_host_ipv4_only),
+ {Name, FullName, IPStr, IP, Aliases} =
+ ct:get_config(test_host_ipv6_only),
- case {inet:gethostbyname(IP_46_Str, inet6),
- inet:gethostbyname(Name, inet6)} of
- {{ok,HEnt46},{ok,_}} ->
- ?line HEnt46_ = HEnt46#hostent{h_name = IP_46_Str,
- h_addrtype = inet6,
- h_length = 16,
- h_addr_list = [IP_46]},
- ?line HEnt46_ = HEnt46,
- ?line check_elems([{HEnt46#hostent.h_aliases,[[],Aliases]}]),
-
- ?line {Name6, FullName6, IPStr6, IP6, Aliases6} =
- ct:get_config(test_host_ipv6_only),
- ?line {ok,_} = inet:gethostbyname(IPStr6, inet6),
- ?line {ok,HEnt6} = inet:gethostbyname(Name6, inet6),
- ?line {ok,HEnt6} = inet:gethostbyname(list_to_atom(Name6), inet6),
- ?line case HEnt6#hostent.h_addr_list of
- [IP6] -> % ipv6 ok
- ?line HEnt6_ = HEnt6#hostent{h_addrtype = inet6,
- h_length = 16,
- h_addr_list = [IP6]},
- ?line HEnt6_ = HEnt6,
- ?line check_elems([{HEnt6#hostent.h_name,[Name6,FullName6]},
- {HEnt6#hostent.h_aliases,[[],Aliases6]}]);
- _ -> % ipv4 compatible addr
- ?line {ok,HEnt4} = inet:gethostbyname(Name6, inet),
- ?line [IP4] = HEnt4#hostent.h_addr_list,
- ?line {ok,IP46_2} =
- inet_parse:ipv6_address("::ffff:"++inet_parse:ntoa(IP4)),
- ?line HEnt6_ = HEnt6#hostent{h_addrtype = inet6,
- h_length = 16,
- h_addr_list = [IP46_2]},
- ?line HEnt6_ = HEnt6,
- ?line check_elems([{HEnt6#hostent.h_name,[Name6,FullName6]}])
- end,
-
- ?line {ok,HEntF6} = inet:gethostbyname(FullName6, inet6),
- ?line case HEntF6#hostent.h_addr_list of
- [IP6] -> % ipv6 ok
- ?line HEntF6_ = HEntF6#hostent{h_name = FullName6,
- h_addrtype = inet6,
- h_length = 16,
- h_addr_list = [IP6]},
- ?line HEntF6_ = HEntF6,
- ?line check_elems([{HEntF6#hostent.h_aliases,[[],Aliases6]}]);
- _ -> % ipv4 compatible addr
- ?line {ok,HEntF4} = inet:gethostbyname(FullName6, inet),
- ?line [IPF4] = HEntF4#hostent.h_addr_list,
- ?line {ok,IPF46_2} =
- inet_parse:ipv6_address("::ffff:"++inet_parse:ntoa(IPF4)),
- ?line HEntF6_ = HEntF6#hostent{h_addrtype = inet6,
- h_length = 16,
- h_addr_list = [IPF46_2]},
- ?line HEntF6_ = HEntF6,
- ?line check_elems([{HEntF6#hostent.h_name,[Name6,FullName6]}])
- end,
-
- ?line {DName6, _DFullName6, _DIPStr6, _DIP6, _} =
- ct:get_config(test_dummy_ipv6_host),
- ?line {error,nxdomain} = inet:gethostbyname(DName6, inet6),
- ok;
- {_,_} ->
+ case inet:gethostbyname(Name, inet6) of
+ {ok,HEnt} ->
+ {ok,_} = inet:gethostbyname(IPStr, inet6),
+ {ok,HEnt} = inet:gethostbyname(list_to_atom(Name), inet6),
+ case HEnt#hostent.h_addr_list of
+ [IP] -> % IPv6 address
+ #hostent{h_addrtype = inet6,
+ h_length = 16} = HEnt,
+ check_elems(
+ [{HEnt#hostent.h_name,[Name,FullName]},
+ {HEnt#hostent.h_aliases,[[],Aliases]}]);
+ [IP46] -> % IPv4 compatible address
+ {ok,HEnt4} = inet:gethostbyname(Name, inet),
+ #hostent{h_addrtype = inet,
+ h_length = 4,
+ h_addr_list = [IP4]} = HEnt4,
+ {ok,IP46} =
+ inet_parse:ipv6_address(
+ "::ffff:" ++ inet_parse:ntoa(IP4)),
+ check_elems(
+ [{HEnt#hostent.h_name,[Name,FullName]}])
+ end,
+
+ {ok,HEntF} = inet:gethostbyname(FullName, inet6),
+ case HEntF#hostent.h_addr_list of
+ [IP] -> % IPv6 address
+ #hostent{h_name = FullName,
+ h_addrtype = inet6,
+ h_length = 16} = HEntF,
+ check_elems(
+ [{HEnt#hostent.h_aliases,[[],Aliases]}]);
+ [IP46F] -> % IPv4 compatible address
+ {ok,HEnt4F} = inet:gethostbyname(FullName, inet),
+ #hostent{h_addrtype = inet,
+ h_length = 4,
+ h_addr_list = [IP4F]} = HEnt4F,
+ {ok,IP46F} =
+ inet_parse:ipv6_address(
+ "::ffff:" ++ inet_parse:ntoa(IP4F)),
+ check_elems(
+ [{HEntF#hostent.h_name,[Name,FullName]}])
+ end;
+ _ ->
{skip, "IPv6 is not supported on this host"}
end.
@@ -290,47 +284,35 @@ t_getaddr(Config) when is_list(Config) ->
?line {error,nxdomain} = inet:getaddr(DName, inet),
?line {error,nxdomain} = inet:getaddr(DFullName, inet),
?line {ok,DIP} = inet:getaddr(DIPStr, inet),
- ?line {ok,DIP} = inet:getaddr(DIP, inet).
+ ?line {ok,DIP} = inet:getaddr(DIP, inet),
+ ok.
t_getaddr_v6() -> required(v4) ++ required(v6).
t_getaddr_v6(doc) -> "Test the inet:getaddr/2 function.";
t_getaddr_v6(suite) -> [];
t_getaddr_v6(Config) when is_list(Config) ->
- ?line {Name,FullName,IPStr,_IP,_,IP_46_Str,IP46} =
- ct:get_config(test_host_ipv4_only),
- case {inet:getaddr(IP_46_Str, inet6),inet:getaddr(Name, inet6)} of
- {{ok,IP46},{ok,V4Addr}} when V4Addr /= {0,0,0,0,0,0,0,1} ->
- %% Since we suceeded in parsing an IPv6 address string and
- %% look up the name, this computer fully supports IPv6.
- ?line {ok,IP46} = inet:getaddr(IP46, inet6),
- ?line {ok,IP46} = inet:getaddr(Name, inet6),
- ?line {ok,IP46} = inet:getaddr(FullName, inet6),
- ?line {ok,IP46} = inet:getaddr(IPStr, inet6),
-%% ?line IP4toIP6 = inet:getaddr(IPStr, inet6),
-%% ?line case IP4toIP6 of
-%% {ok,IP46} ->
-%% ?line ok;
-%% {error,nxdomain} ->
-%% ?line false =
-%% lists:member(native,
-%% inet_db:res_option(lookup))
-%% end,
- ?line {Name6, FullName6, IPStr6, IP6, _} =
- ct:get_config(test_host_ipv6_only),
- ?line {ok,_} = inet:getaddr(list_to_atom(Name6), inet6),
- ?line {ok,_} = inet:getaddr(Name6, inet6),
- ?line {ok,_} = inet:getaddr(FullName6, inet6),
- ?line {ok,IP6} = inet:getaddr(IP6, inet6),
- ?line {ok,IP6} = inet:getaddr(IPStr6, inet6),
-
- ?line {DName6, DFullName6, DIPStr6, DIP6, _} =
+ {Name,FullName,IPStr,IP,_} =
+ ct:get_config(test_host_ipv6_only),
+
+ case inet:getaddr(Name, inet6) of
+ {ok,Addr} ->
+ IP = Addr,
+ {ok,IP} = inet:getaddr(toupper(Name), inet6),
+ {ok,IP} = inet:getaddr(list_to_atom(Name), inet6),
+ {ok,IP} = inet:getaddr(list_to_atom(toupper(Name)), inet6),
+ {ok,IP} = inet:getaddr(FullName, inet6),
+ {ok,IP} = inet:getaddr(toupper(FullName), inet6),
+ {ok,IP} = inet:getaddr(IP, inet6),
+ {ok,IP} = inet:getaddr(IPStr, inet6),
+ %%
+ {DName,DFullName,DIPStr,DIP,_} =
ct:get_config(test_dummy_ipv6_host),
- ?line {error,nxdomain} = inet:getaddr(DName6, inet6),
- ?line {error,nxdomain} = inet:getaddr(DFullName6, inet6),
- ?line {ok,DIP6} = inet:getaddr(DIPStr6, inet6),
- ?line {ok,DIP6} = inet:getaddr(DIP6, inet6),
+ {error,nxdomain} = inet:getaddr(DName, inet6),
+ {error,nxdomain} = inet:getaddr(DFullName, inet6),
+ {ok,DIP} = inet:getaddr(DIPStr, inet6),
+ {ok,DIP} = inet:getaddr(DIP, inet6),
ok;
- {_,_} ->
+ _ ->
{skip, "IPv6 is not supported on this host"}
end.
@@ -608,8 +590,12 @@ t_parse_address(Func, [String|L]) ->
t_parse_address(Func, L).
parse_strict_address(Config) when is_list(Config) ->
- {ok, Ipv4} = inet:parse_strict_address("127.0.0.1"),
- {ok, Ipv6} = inet:parse_strict_address("c11:0c22:5c33:c440:55c0:c66c:77:0088").
+ {ok, {127,0,0,1}} =
+ inet:parse_strict_address("127.0.0.1"),
+ {ok, {3089,3106,23603,50240,21952,50796,119,136}} =
+ inet:parse_strict_address("c11:0c22:5c33:c440:55c0:c66c:77:0088"),
+ {ok, {3089,3106,23603,50240,0,0,119,136}} =
+ inet:parse_strict_address("c11:0c22:5c33:c440::077:0088").
t_gethostnative(suite) ->[];
t_gethostnative(doc) ->[];
@@ -1102,3 +1088,14 @@ ip_member({127,_,_,_}, [{127,_,_,_}|_]) -> true;
ip_member(K, [K|_]) -> true;
ip_member(K, [_|T]) -> ip_member(K, T);
ip_member(_, []) -> false.
+
+%% Case fold to upper case according to RFC 4343
+%%
+toupper([C|Cs]) when is_integer(C) ->
+ if $a =< C, C =< $z ->
+ [(C - $a + $A)|toupper(Cs)];
+ true ->
+ [C|toupper(Cs)]
+ end;
+toupper([]) ->
+ [].
diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl
index f3ba28e4f9..1bc93e3138 100644
--- a/lib/kernel/test/inet_res_SUITE.erl
+++ b/lib/kernel/test/inet_res_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -282,6 +282,7 @@ basic(doc) ->
basic(Config) when is_list(Config) ->
NS = ns(Config),
Name = "ns.otptest",
+ NameC = caseflip(Name),
IP = {127,0,0,254},
%%
%% nslookup
@@ -292,6 +293,17 @@ basic(Config) when is_list(Config) ->
Bin1 = inet_dns:encode(Msg1),
%%io:format("Bin1 = ~w~n", [Bin1]),
{ok,Msg1} = inet_dns:decode(Bin1),
+ %% Now with scrambled case
+ {ok,Msg1b} = inet_res:nslookup(NameC, in, a, [NS]),
+ io:format("~p~n", [Msg1b]),
+ [RR1b] = inet_dns:msg(Msg1b, anlist),
+ IP = inet_dns:rr(RR1b, data),
+ Bin1b = inet_dns:encode(Msg1b),
+ %%io:format("Bin1b = ~w~n", [Bin1b]),
+ {ok,Msg1b} = inet_dns:decode(Bin1b),
+ true =
+ (tolower(inet_dns:rr(RR1, domain))
+ =:= tolower(inet_dns:rr(RR1b, domain))),
%%
%% resolve
{ok,Msg2} = inet_res:resolve(Name, in, a, [{nameservers,[NS]},verbose]),
@@ -301,15 +313,29 @@ basic(Config) when is_list(Config) ->
Bin2 = inet_dns:encode(Msg2),
%%io:format("Bin2 = ~w~n", [Bin2]),
{ok,Msg2} = inet_dns:decode(Bin2),
+ %% Now with scrambled case
+ {ok,Msg2b} = inet_res:resolve(NameC, in, a, [{nameservers,[NS]},verbose]),
+ io:format("~p~n", [Msg2b]),
+ [RR2b] = inet_dns:msg(Msg2b, anlist),
+ IP = inet_dns:rr(RR2b, data),
+ Bin2b = inet_dns:encode(Msg2b),
+ %%io:format("Bin2b = ~w~n", [Bin2b]),
+ {ok,Msg2b} = inet_dns:decode(Bin2b),
+ true =
+ (tolower(inet_dns:rr(RR2, domain))
+ =:= tolower(inet_dns:rr(RR2b, domain))),
%%
%% lookup
[IP] = inet_res:lookup(Name, in, a, [{nameservers,[NS]},verbose]),
+ [IP] = inet_res:lookup(NameC, in, a, [{nameservers,[NS]},verbose]),
%%
%% gethostbyname
{ok,#hostent{h_addr_list=[IP]}} = inet_res:gethostbyname(Name),
+ {ok,#hostent{h_addr_list=[IP]}} = inet_res:gethostbyname(NameC),
%%
%% getbyname
{ok,#hostent{h_addr_list=[IP]}} = inet_res:getbyname(Name, a),
+ {ok,#hostent{h_addr_list=[IP]}} = inet_res:getbyname(NameC, a),
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -317,63 +343,115 @@ basic(Config) when is_list(Config) ->
resolve(doc) ->
["Lookup different records using resolve/2..4"];
resolve(Config) when is_list(Config) ->
+ Class = in,
NS = ns(Config),
Domain = "otptest",
RDomain4 = "0.0.127.in-addr.arpa",
RDomain6 = "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa",
Name = "resolve."++Domain,
- L = [{in,a,Name,[{127,0,0,28}],undefined},
- {in,aaaa,Name,[{0,0,0,0,0,0,32512,28}],undefined},
- {in,cname,"cname."++Name,[Name],undefined},
- {in,a,"cname."++Name,[Name,{127,0,0,28}],undefined},
- {in,ns,"ns."++Name,[],[Name]},
- {in,soa,Domain,[],[{"ns.otptest","lsa.otptest",1,60,10,300,30}]},
+ L = [{a,Name,[{a,{127,0,0,28}}],undefined},
+ {aaaa,Name,[{aaaa,{0,0,0,0,0,0,32512,28}}],undefined},
+ {cname,"cname."++Name,[{cname,Name}],undefined},
+ {a,"cname."++Name,[{cname,Name},{a,{127,0,0,28}}],undefined},
+ {ns,"ns."++Name,[],[{ns,Name}]},
+ {soa,Domain,[],[{soa,{"ns.otptest","lsa.otptest",1,60,10,300,30}}]},
%% WKS: protocol TCP (6), services (bits) TELNET (23) and SMTP (25)
- {in,wks,"wks."++Name,[{{127,0,0,28},6,<<0,0,1,64>>}],undefined},
- {in,ptr,"28."++RDomain4,[Name],undefined},
- {in,ptr,"c.1.0.0.0.0.f.7."++RDomain6,[Name],undefined},
- {in,hinfo,Name,[{"BEAM","Erlang/OTP"}],undefined},
- {in,mx,RDomain4,[{10,"mx."++Domain}],undefined},
- {in,srv,"_srv._tcp."++Name,[{10,3,4711,Name}],undefined},
- {in,naptr,"naptr."++Name,
- [{10,5,"s","http","","_srv._tcp."++Name}],undefined},
- {in,txt,"txt."++Name,
- [["Hej ","du ","glade "],["ta ","en ","spade!"]],undefined},
- {in,mb,"mb."++Name,["mx."++Name],undefined},
- {in,mg,"mg."++Name,["lsa."++Domain],undefined},
- {in,mr,"mr."++Name,["lsa."++Domain],undefined},
- {in,minfo,"minfo."++Name,
- [{"minfo-owner."++Name,"minfo-bounce."++Name}],undefined},
- {in,any,"cname."++Name,[Name],undefined},
- {in,any,Name,[{127,0,0,28},
- {0,0,0,0,0,0,32512,28},
- {"BEAM","Erlang/OTP"}],undefined}
+ {wks,"wks."++Name,[{wks,{{127,0,0,28},6,<<0,0,1,64>>}}],undefined},
+ {ptr,"28."++RDomain4,[{ptr,Name}],undefined},
+ {ptr,"c.1.0.0.0.0.f.7."++RDomain6,[{ptr,Name}],undefined},
+ {hinfo,Name,[{hinfo,{"BEAM","Erlang/OTP"}}],undefined},
+ {mx,RDomain4,[{mx,{10,"mx."++Domain}}],undefined},
+ {srv,"_srv._tcp."++Name,[{srv,{10,3,4711,Name}}],undefined},
+ {naptr,"naptr."++Name,
+ [{naptr,{10,5,"s","http","","_srv._tcp."++Name}}],
+ undefined},
+ {txt,"txt."++Name,
+ [{txt,["Hej ","du ","glade "]},{txt,["ta ","en ","spade!"]}],
+ undefined},
+ {mb,"mb."++Name,[{mb,"mx."++Name}],undefined},
+ {mg,"mg."++Name,[{mg,"Lsa."++Domain}],undefined},
+ {mr,"mr."++Name,[{mr,"LSA."++Domain}],undefined},
+ {minfo,"minfo."++Name,
+ [{minfo,{"minfo-OWNER."++Name,"MinfoBounce."++Name}}],
+ undefined},
+ {any,"cname."++Name,[{cname,Name}],undefined},
+ {any,Name,
+ [{a,{127,0,0,28}},
+ {aaaa,{0,0,0,0,0,0,32512,28}},
+ {hinfo,{"BEAM","Erlang/OTP"}}],
+ undefined}
],
- resolve([{edns,false},{nameservers,[NS]}], L),
- resolve([{edns,0},{nameservers,[NS]}], L).
-
-resolve(_Opts, []) -> ok;
-resolve(Opts, [{Class,Type,Name,Answers,Authority}=Q|Qs]) ->
+ resolve(Class, [{edns,0},{nameservers,[NS]}], L),
+ resolve(Class, [{edns,false},{nameservers,[NS]}], L),
+ %% Again, to see ensure the cache does not mess things up
+ resolve(Class, [{edns,0},{nameservers,[NS]}], L),
+ resolve(Class, [{edns,false},{nameservers,[NS]}], L).
+
+resolve(_Class, _Opts, []) ->
+ ok;
+resolve(Class, Opts, [{Type,Nm,Answers,Authority}=Q|Qs]) ->
io:format("Query: ~p~nOptions: ~p~n", [Q,Opts]),
- {ok,Msg} = inet_res:resolve(Name, Class, Type, Opts),
+ {Name,NameC} =
+ case erlang:phash2(Q) band 4 of
+ 0 ->
+ {Nm,caseflip(Nm)};
+ _ ->
+ {caseflip(Nm),Nm}
+ end,
AnList =
if
Answers =/= undefined ->
- lists:sort(Answers);
+ normalize_answers(Answers);
true ->
undefined
end,
NsList =
if
Authority =/= undefined ->
- lists:sort(Authority);
+ normalize_answers(Authority);
true ->
undefined
end,
- case {lists:sort
- ([inet_dns:rr(RR, data) || RR <- inet_dns:msg(Msg, anlist)]),
- lists:sort
- ([inet_dns:rr(RR, data) || RR <- inet_dns:msg(Msg, nslist)])} of
+ {ok,Msg} = inet_res:resolve(Name, Class, Type, Opts),
+ check_msg(Class, Type, Msg, AnList, NsList),
+ {ok,MsgC} = inet_res:resolve(NameC, Class, Type, Opts),
+ check_msg(Class, Type, MsgC, AnList, NsList),
+ resolve(Class, Opts, Qs).
+
+
+
+normalize_answers(AnList) ->
+ lists:sort([normalize_answer(Answer) || Answer <- AnList]).
+
+normalize_answer({soa,{NS,HM,Ser,Ref,Ret,Exp,Min}}) ->
+ {tolower(NS),tolower_email(HM),Ser,Ref,Ret,Exp,Min};
+normalize_answer({mx,{Prio,DN}}) ->
+ {Prio,tolower(DN)};
+normalize_answer({srv,{Prio,Weight,Port,DN}}) ->
+ {Prio,Weight,Port,tolower(DN)};
+normalize_answer({naptr,{Order,Pref,Flags,Service,RE,Repl}}) ->
+ {Order,Pref,Flags,Service,RE,tolower(Repl)};
+normalize_answer({minfo,{RespM,ErrM}}) ->
+ {tolower_email(RespM),tolower_email(ErrM)};
+normalize_answer({T,MN}) when T =:= mg; T =:= mr ->
+ tolower_email(MN);
+normalize_answer({T,DN}) when T =:= cname; T =:= ns; T =:= ptr; T =:= mb ->
+ tolower(DN);
+normalize_answer(Answer) ->
+ Answer.
+
+check_msg(Class, Type, Msg, AnList, NsList) ->
+ io:format("check_msg Type: ~p, Msg: ~p~n.", [Type,Msg]),
+ case {normalize_answers(
+ [begin
+ Class = inet_dns:rr(RR, class),
+ {inet_dns:rr(RR, type),inet_dns:rr(RR, data)}
+ end || RR <- inet_dns:msg(Msg, anlist)]),
+ normalize_answers(
+ [begin
+ Class = inet_dns:rr(RR, class),
+ {inet_dns:rr(RR, type),inet_dns:rr(RR, data)}
+ end || RR <- inet_dns:msg(Msg, nslist)])} of
{AnList,NsList} ->
ok;
{NsList,AnList} when Type =:= ns ->
@@ -389,7 +467,7 @@ resolve(Opts, [{Class,Type,Name,Answers,Authority}=Q|Qs]) ->
end,
Buf = inet_dns:encode(Msg),
{ok,Msg} = inet_dns:decode(Buf),
- resolve(Opts, Qs).
+ ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -497,6 +575,7 @@ files_monitor(Config) when is_list(Config) ->
do_files_monitor(Config) ->
Dir = ?config(priv_dir, Config),
{ok,Hostname} = inet:gethostname(),
+ io:format("Hostname = ~p.~n", [Hostname]),
FQDN =
case inet_db:res_option(domain) of
"" ->
@@ -504,11 +583,13 @@ do_files_monitor(Config) ->
_ ->
Hostname++"."++inet_db:res_option(domain)
end,
+ io:format("FQDN = ~p.~n", [FQDN]),
HostsFile = filename:join(Dir, "files_monitor_hosts"),
ResolvConf = filename:join(Dir, "files_monitor_resolv.conf"),
ok = inet_db:res_option(resolv_conf, ResolvConf),
ok = inet_db:res_option(hosts_file, HostsFile),
[] = inet_db:res_option(search),
+ %% The inet function will use its final fallback to find this host
{ok,#hostent{h_name = Hostname,
h_addrtype = inet,
h_length = 4,
@@ -521,6 +602,7 @@ do_files_monitor(Config) ->
{error,nxdomain} = inet_res:gethostbyname(FQDN),
{ok,{127,0,0,10}} = inet:getaddr("mx.otptest", inet),
{ok,{0,0,0,0,0,0,32512,28}} = inet:getaddr("resolve.otptest", inet6),
+ %% The inet function will use its final fallback to find this host
{ok,#hostent{h_name = Hostname,
h_addrtype = inet6,
h_length = 16,
@@ -603,3 +685,41 @@ ipv4_to_ipv6() -> inet_SUITE:ipv4_to_ipv6().
ipv4_to_ipv6(Config) -> inet_SUITE:ipv4_to_ipv6(Config).
host_and_addr() -> inet_SUITE:host_and_addr().
host_and_addr(Config) -> inet_SUITE:host_and_addr(Config).
+
+
+
+%% Case flip helper
+
+caseflip([C|Cs]) when is_integer(C), $a =< C, C =< $z ->
+ [(C - $a + $A)|caseflip_skip(Cs)];
+caseflip([C|Cs]) when is_integer(C), $A =< C, C =< $Z ->
+ [(C - $A + $a)|caseflip_skip(Cs)];
+caseflip([C|Cs]) ->
+ [C|caseflip(Cs)];
+caseflip([]) ->
+ [].
+
+caseflip_skip([C|Cs]) when is_integer(C), $a =< C, C =< $z ->
+ [C|caseflip(Cs)];
+caseflip_skip([C|Cs]) when is_integer(C), $A =< C, C =< $Z ->
+ [C|caseflip(Cs)];
+caseflip_skip([C|Cs]) ->
+ [C|caseflip_skip(Cs)];
+caseflip_skip([]) ->
+ [].
+
+tolower_email([$.|Cs]) ->
+ [$.|tolower(Cs)];
+tolower_email([C|Cs]) ->
+ [C|tolower_email(Cs)].
+
+%% Case fold to lower case according to RFC 4343
+%%
+tolower([C|Cs]) when is_integer(C) ->
+ if $A =< C, C =< $Z ->
+ [(C - $A + $a)|tolower(Cs)];
+ true ->
+ [C|tolower(Cs)]
+ end;
+tolower([]) ->
+ [].
diff --git a/lib/kernel/test/inet_res_SUITE_data/otptest/named_inc.conf b/lib/kernel/test/inet_res_SUITE_data/otptest/named_inc.conf
index 0b01b25204..2d68f6e59c 100644
--- a/lib/kernel/test/inet_res_SUITE_data/otptest/named_inc.conf
+++ b/lib/kernel/test/inet_res_SUITE_data/otptest/named_inc.conf
@@ -2,11 +2,11 @@ zone "." in {
type master;
file "root.zone";
};
-zone "0.0.127.in-addr.arpa" in {
+zone "0.0.127.in-addr.arpa." in {
type master;
file "0.0.127.in-addr.arpa.zone";
};
-zone "0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" in {
+zone "0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." in {
type master;
file "0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.zone";
-}; \ No newline at end of file
+};
diff --git a/lib/kernel/test/inet_res_SUITE_data/otptest/root.zone b/lib/kernel/test/inet_res_SUITE_data/otptest/root.zone
index 11cba18d45..5a56eac95c 100644
--- a/lib/kernel/test/inet_res_SUITE_data/otptest/root.zone
+++ b/lib/kernel/test/inet_res_SUITE_data/otptest/root.zone
@@ -43,8 +43,8 @@ naptr.resolve.otptest IN NAPTR 10 5 "S" "HTTP" "" _srv._tcp.resolve.otptest
txt.resolve.otptest IN TXT "Hej " "du " "glade "
txt.resolve.otptest IN TXT "ta " "en " "spade!"
mb.resolve.otptest IN MB mx.resolve.otptest
-mg.resolve.otptest IN MG lsa.otptest
-mr.resolve.otptest IN MR lsa.otptest
-minfo.resolve.otptest IN MINFO minfo-owner.resolve.otptest minfo-bounce.resolve.otptest
+mg.resolve.otptest IN MG Lsa.otptest
+mr.resolve.otptest IN MR LSA.otptest
+minfo.resolve.otptest IN MINFO minfo-OWNER.resolve.otptest MinfoBounce.resolve.otptest
ns.otptest IN A 127.0.0.254
diff --git a/lib/mnesia/src/mnesia_subscr.erl b/lib/mnesia/src/mnesia_subscr.erl
index 415c69d508..8f78dc55e8 100644
--- a/lib/mnesia/src/mnesia_subscr.erl
+++ b/lib/mnesia/src/mnesia_subscr.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -447,8 +447,12 @@ deactivate(ClientPid, What, Var, SubscrTab) ->
{'EXIT', _} ->
unlink(ClientPid)
end,
- del_subscr(Var, What, ClientPid),
- {ok, node()}.
+ try
+ del_subscr(Var, What, ClientPid),
+ {ok, node()}
+ catch _:_ ->
+ {error, badarg}
+ end.
del_subscr(subscribers, _What, Pid) ->
mnesia_lib:del(subscribers, Pid);
diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl
index 0df245b75d..db23a39943 100644
--- a/lib/mnesia/test/mnesia_evil_coverage_test.erl
+++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl
@@ -1985,6 +1985,10 @@ subscribe_standard(Config) when is_list(Config)->
?match({atomic, ok}, mnesia:create_table(Tab, Def)),
%% Check system events
+ ?match({error, {badarg, foo}}, mnesia:unsubscribe(foo)),
+ ?match({error, badarg}, mnesia:unsubscribe({table, foo})),
+ ?match(_, mnesia:unsubscribe(activity)),
+
?match({ok, N1}, mnesia:subscribe(system)),
?match({ok, N1}, mnesia:subscribe(activity)),
diff --git a/lib/mnesia/test/mnesia_isolation_test.erl b/lib/mnesia/test/mnesia_isolation_test.erl
index 3273bc4d40..d57f976d1f 100644
--- a/lib/mnesia/test/mnesia_isolation_test.erl
+++ b/lib/mnesia/test/mnesia_isolation_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -613,11 +613,11 @@ unbound2(Config) when is_list(Config) ->
?match_receive({B, continuing}),
%% B should now be in lock queue.
- A ! continue,
- ?match_receive({A, {atomic, ok}}),
- ?match_receive({B, {atomic, [{ul,{key,{17,42}},val}]}}),
+ A ! continue,
+ ?match_multi_receive([{A, {atomic, ok}},
+ {B, {atomic, [{ul,{key,{17,42}},val}]}}]),
ok.
-
+
receiver() ->
receive
{_Pid, begin_trans} ->
diff --git a/lib/os_mon/vsn.mk b/lib/os_mon/vsn.mk
index 7d6c5484a7..e3acea0258 100644
--- a/lib/os_mon/vsn.mk
+++ b/lib/os_mon/vsn.mk
@@ -1 +1 @@
-OS_MON_VSN = 2.2.11
+OS_MON_VSN = 2.2.12
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index 10c95a39ac..bce6d58682 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -43,7 +43,8 @@
<title>public_key</title>
<list type="bulleted">
- <item>public_key requires the crypto application.</item>
+ <item>public_key requires the crypto and asn1 applications, the latter since R16 (hopefully the runtime dependency on asn1 will
+ be removed again in the future).</item>
<item>Supports <url href="http://www.ietf.org/rfc/rfc5280.txt">RFC 5280 </url> -
Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile </item>
@@ -154,8 +155,8 @@
<funcs>
<func>
- <name> compute_key(OthersKey, MyKey)-></name>
- <name> compute_key(OthersKey, MyKey, Params)-></name>
+ <name>compute_key(OthersKey, MyKey)-></name>
+ <name>compute_key(OthersKey, MyKey, Params)-></name>
<fsummary> Compute shared secret</fsummary>
<type>
<v>OthersKey = #'ECPoint'{} | binary(), MyKey = #'ECPrivateKey'{} | binary()</v>
@@ -176,7 +177,8 @@
<v>Options = public_crypt_options()</v>
</type>
<desc>
- <p>Public key decryption using the private key.</p>
+ <p>Public key decryption using the private key. See also <seealso
+ marker="crypto:crypto#private_decrypt/4">crypto:private_decrypt/4</seealso></p>
</desc>
</func>
@@ -190,7 +192,8 @@
<v>Options = public_crypt_options()</v>
</type>
<desc>
- <p> Public key decryption using the public key.</p>
+ <p> Public key decryption using the public key. See also <seealso
+ marker="crypto:crypto#public_decrypt/4">crypto:public_decrypt/4</seealso></p>
</desc>
</func>
@@ -304,7 +307,9 @@
<v>Key = rsa_private_key()</v>
</type>
<desc>
- <p> Public key encryption using the private key.</p>
+ <p> Public key encryption using the private key.
+ See also <seealso
+ marker="crypto:crypto#private_encrypt/4">crypto:private_encrypt/4</seealso></p>
</desc>
</func>
@@ -316,7 +321,8 @@
<v>Key = rsa_public_key()</v>
</type>
<desc>
- <p> Public key encryption using the public key.</p>
+ <p> Public key encryption using the public key. See also <seealso
+ marker="crypto:crypto#public_encrypt/4">crypto:public_encrypt/4</seealso></p>
</desc>
</func>
diff --git a/lib/public_key/src/public_key.app.src b/lib/public_key/src/public_key.app.src
index 9f0677606d..736a778a4b 100644
--- a/lib/public_key/src/public_key.app.src
+++ b/lib/public_key/src/public_key.app.src
@@ -11,7 +11,7 @@
'OTP-PUB-KEY',
'PKCS-FRAME'
]},
- {applications, [crypto, kernel, stdlib]},
+ {applications, [asn1, crypto, kernel, stdlib]},
{registered, []},
{env, []}
]
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 3eea6f6ec4..cdbfe6e07c 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -252,8 +252,7 @@ decrypt_private(CipherText, Key) ->
decrypt_private(CipherText, Key, []).
decrypt_private(CipherText,
- #'RSAPrivateKey'{modulus = N, publicExponent = E,
- privateExponent = D} = Key,
+ #'RSAPrivateKey'{} = Key,
Options)
when is_binary(CipherText),
is_list(Options) ->
diff --git a/lib/public_key/test/pkits_SUITE.erl b/lib/public_key/test/pkits_SUITE.erl
index c490493e13..9180fa968b 100644
--- a/lib/public_key/test/pkits_SUITE.erl
+++ b/lib/public_key/test/pkits_SUITE.erl
@@ -113,12 +113,14 @@ groups() ->
init_per_suite(Config) ->
try crypto:start() of
ok ->
+ application:start(asn1),
crypto_support_check(Config)
catch _:_ ->
{skip, "Crypto did not start"}
end.
end_per_suite(_Config) ->
+ application:stop(asn1),
application:stop(crypto).
%%--------------------------------------------------------------------
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index 5a64140c67..f2596e3d85 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -58,12 +58,14 @@ groups() ->
init_per_suite(Config) ->
try crypto:start() of
ok ->
+ application:start(asn1),
Config
catch _:_ ->
{skip, "Crypto did not start"}
end.
end_per_suite(_Config) ->
+ application:stop(asn1),
application:stop(crypto).
%%-------------------------------------------------------------------
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index bd20a5546b..b820f24d2a 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 0.18
+PUBLIC_KEY_VSN = 0.19
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 3a7aa79d16..7d5478c3f6 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -41,11 +41,13 @@
%%--------------------------------------------------------------------
start() ->
application:start(crypto),
+ application:start(asn1),
application:start(public_key),
application:start(ssh).
start(Type) ->
application:start(crypto, Type),
+ application:start(asn1),
application:start(public_key, Type),
application:start(ssh, Type).
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 75c17b14db..0c1e47311d 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -214,8 +214,8 @@ prf(Socket, Secret, Label, Seed, WantedLength) ->
clear_pem_cache() ->
tls:clear_pem_cache().
-format_error(Reason) when is_list(Reason) ->
- tls:format_error(Reason).
+format_error(Error) ->
+ tls:format_error(Error).
random_bytes(N) ->
tls:random_bytes(N).
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 898b421dff..ec5d793d65 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -1190,14 +1190,16 @@ hash_size(md5) ->
16;
hash_size(sha) ->
20;
-hash_size(sha224) ->
- 28;
+%% Uncomment when adding cipher suite that needs it
+%% hash_size(sha224) ->
+%% 28;
hash_size(sha256) ->
32;
hash_size(sha384) ->
- 48;
-hash_size(sha512) ->
- 64.
+ 48.
+%% Uncomment when adding cipher suite that needs it
+%% hash_size(sha512) ->
+%% 64.
%% RFC 5246: 6.2.3.2. CBC Block Cipher
%%
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index 1b06e351cf..7af4a68461 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -104,7 +104,6 @@ connection_init(Trustedcerts, Role) ->
%%--------------------------------------------------------------------
cache_pem_file(File, DbHandle) ->
MD5 = crypto:hash(md5, File),
- MD5 = crypto:md5(File),
case ssl_pkix_db:lookup_cached_pem(DbHandle, MD5) of
[{Content,_}] ->
{ok, Content};
diff --git a/lib/ssl/src/tls.erl b/lib/ssl/src/tls.erl
index fcecf8196f..bb02695c12 100644
--- a/lib/ssl/src/tls.erl
+++ b/lib/ssl/src/tls.erl
@@ -94,11 +94,13 @@
%%--------------------------------------------------------------------
start() ->
application:start(crypto),
+ application:start(asn1),
application:start(public_key),
application:start(ssl).
start(Type) ->
application:start(crypto, Type),
+ application:start(asn1),
application:start(public_key, Type),
application:start(ssl, Type).
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index 6a0461e805..246fecf34a 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -673,8 +673,7 @@ certify_client_key_exchange(#encrypted_premaster_secret{premaster_secret= EncPMS
certify_client_key_exchange(#client_diffie_hellman_public{dh_public = ClientPublicDhKey},
#state{negotiated_version = Version,
- diffie_hellman_params = #'DHParameter'{prime = P,
- base = G} = Params,
+ diffie_hellman_params = #'DHParameter'{} = Params,
diffie_hellman_keys = {_, ServerDhPrivateKey}} = State0) ->
case dh_master_secret(Params, ClientPublicDhKey, ServerDhPrivateKey, State0) of
#state{} = State1 ->
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index fea75736f7..51fd2e1dc9 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -866,7 +866,7 @@ handle_ecc_point_fmt_extension(undefined) ->
handle_ecc_point_fmt_extension(_) ->
#ec_point_formats{ec_point_format_list = [?ECPOINT_UNCOMPRESSED]}.
-handle_ecc_curves_extension(Version, undefined) ->
+handle_ecc_curves_extension(_Version, undefined) ->
undefined;
handle_ecc_curves_extension(Version, _) ->
#elliptic_curves{elliptic_curve_list = ssl_tls1:ecc_curves(Version)}.
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index fed590f0ef..b5cf6d1212 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -190,8 +190,7 @@ init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- application:start(public_key),
-
+ ssl:start(),
%% make rsa certs using oppenssl
Result =
(catch make_certs:all(?config(data_dir, Config0),
diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
index 4e095dc184..f76c55f670 100644
--- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl
+++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
@@ -80,8 +80,7 @@ init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- application:start(public_key),
- application:start(ssl),
+ ssl:start(),
%% make rsa certs using oppenssl
Result =
(catch make_certs:all(?config(data_dir, Config0),
diff --git a/lib/ssl/test/ssl_npn_handshake_SUITE.erl b/lib/ssl/test/ssl_npn_handshake_SUITE.erl
index 7b271c4d5d..30c0a67a36 100644
--- a/lib/ssl/test/ssl_npn_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_npn_handshake_SUITE.erl
@@ -69,7 +69,6 @@ init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- application:start(public_key),
ssl:start(),
Result =
(catch make_certs:all(?config(data_dir, Config),
diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl
index 5a374e234d..36f7af784d 100644
--- a/lib/ssl/test/ssl_packet_SUITE.erl
+++ b/lib/ssl/test/ssl_packet_SUITE.erl
@@ -139,7 +139,7 @@ init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- application:start(public_key),
+ ssl:start(),
Result =
(catch make_certs:all(?config(data_dir, Config),
?config(priv_dir, Config))),
diff --git a/lib/ssl/test/ssl_payload_SUITE.erl b/lib/ssl/test/ssl_payload_SUITE.erl
index 5f5166391f..f95eae51b7 100644
--- a/lib/ssl/test/ssl_payload_SUITE.erl
+++ b/lib/ssl/test/ssl_payload_SUITE.erl
@@ -71,7 +71,6 @@ init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- application:start(public_key),
ssl:start(),
make_certs:all(?config(data_dir, Config), ?config(priv_dir, Config)),
ssl_test_lib:cert_options(Config)
diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl
index 6cc6c4bdb2..c31f6c2d7d 100644
--- a/lib/ssl/test/ssl_session_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_session_cache_SUITE.erl
@@ -56,9 +56,7 @@ init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- application:start(public_key),
ssl:start(),
-
%% make rsa certs using oppenssl
Result =
(catch make_certs:all(?config(data_dir, Config0),
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index 0564b37f1c..019ed58b1b 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -99,7 +99,6 @@ init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- application:start(public_key),
ssl:start(),
Result =
(catch make_certs:all(?config(data_dir, Config0),