aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/public_key/doc/src/public_key_records.xml6
-rw-r--r--lib/public_key/src/public_key.erl26
-rw-r--r--lib/public_key/test/public_key_SUITE.erl44
-rw-r--r--lib/public_key/test/public_key_SUITE_data/ec_key2.pem29
4 files changed, 94 insertions, 11 deletions
diff --git a/lib/public_key/doc/src/public_key_records.xml b/lib/public_key/doc/src/public_key_records.xml
index d34f3ed9a3..739310c88b 100644
--- a/lib/public_key/doc/src/public_key_records.xml
+++ b/lib/public_key/doc/src/public_key_records.xml
@@ -171,9 +171,9 @@
#'ECPrivateKey'{
version, % integer()
privateKey, % binary()
- parameters, % der_encoded() - {'EcpkParameters', #'ECParameters'{}} |
- {'EcpkParameters', {namedCurve, oid()}} |
- {'EcpkParameters', 'NULL'} % Inherited by CA
+ parameters, % {ecParameters, #'ECParameters'{}} |
+ % {namedCurve, Oid::tuple()} |
+ % {implicitlyCA, 'NULL'}
publicKey % bitstring()
}.
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index c2060c144c..9a61184f8a 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -71,7 +71,9 @@
-type rsa_private_key() :: #'RSAPrivateKey'{}.
-type dsa_private_key() :: #'DSAPrivateKey'{}.
-type dsa_public_key() :: {integer(), #'Dss-Parms'{}}.
--type ec_public_key() :: {#'ECPoint'{},{namedCurve, Oid::tuple()} | #'ECParameters'{}}.
+-type ecpk_parameters() :: {ecParameters, #'ECParameters'{}} | {namedCurve, Oid::tuple()}.
+-type ecpk_parameters_api() :: ecpk_parameters() | #'ECParameters'{} | {namedCurve, Name::atom()}.
+-type ec_public_key() :: {#'ECPoint'{}, ecpk_parameters_api()}.
-type ec_private_key() :: #'ECPrivateKey'{}.
-type der_encoded() :: binary().
-type pki_asn1_type() :: 'Certificate' | 'RSAPrivateKey' | 'RSAPublicKey'
@@ -399,9 +401,7 @@ dh_gex_group(Min, N, Max, Groups) ->
%%--------------------------------------------------------------------
-spec generate_key(#'DHParameter'{}) ->
{Public::binary(), Private::binary()};
- ({namedCurve, Name ::oid()}) ->
- #'ECPrivateKey'{};
- (#'ECParameters'{}) ->
+ (ecpk_parameters_api()) ->
#'ECPrivateKey'{};
({rsa, Size::pos_integer(), PubExp::pos_integer()}) ->
#'RSAPrivateKey'{}.
@@ -412,6 +412,8 @@ generate_key(#'DHParameter'{prime = P, base = G}) ->
crypto:generate_key(dh, [P, G]);
generate_key({namedCurve, _} = Params) ->
ec_generate_key(Params);
+generate_key({ecParameters, _} = Params) ->
+ ec_generate_key(Params);
generate_key(#'ECParameters'{} = Params) ->
ec_generate_key(Params);
generate_key({rsa, ModulusSize, PublicExponent}) ->
@@ -1286,22 +1288,34 @@ format_rsa_private_key(#'RSAPrivateKey'{modulus = N, publicExponent = E,
is_integer(D) ->
[E, N, D].
+-spec ec_generate_key(ecpk_parameters_api()) -> #'ECPrivateKey'{}.
ec_generate_key(Params) ->
Curve = ec_curve_spec(Params),
Term = crypto:generate_key(ecdh, Curve),
- ec_key(Term, Params).
+ NormParams = ec_normalize_params(Params),
+ ec_key(Term, NormParams).
+-spec ec_normalize_params(ecpk_parameters_api()) -> ecpk_parameters().
+ec_normalize_params({namedCurve, Name}) when is_atom(Name) ->
+ {namedCurve, pubkey_cert_records:namedCurves(Name)};
+ec_normalize_params(#'ECParameters'{} = ECParams) ->
+ {ecParameters, ECParams};
+ec_normalize_params(Other) -> Other.
+
+-spec ec_curve_spec(ecpk_parameters_api()) -> term().
ec_curve_spec( #'ECParameters'{fieldID = FieldId, curve = PCurve, base = Base, order = Order, cofactor = CoFactor }) ->
Field = {pubkey_cert_records:supportedCurvesTypes(FieldId#'FieldID'.fieldType),
FieldId#'FieldID'.parameters},
Curve = {PCurve#'Curve'.a, PCurve#'Curve'.b, none},
{Field, Curve, Base, Order, CoFactor};
+ec_curve_spec({ecParameters, ECParams}) ->
+ ec_curve_spec(ECParams);
ec_curve_spec({namedCurve, OID}) when is_tuple(OID), is_integer(element(1,OID)) ->
ec_curve_spec({namedCurve, pubkey_cert_records:namedCurves(OID)});
ec_curve_spec({namedCurve, Name}) when is_atom(Name) ->
crypto:ec_curve(Name).
-
+-spec ec_key({PubKey::term(), PrivateKey::term()}, Params::ecpk_parameters()) -> #'ECPrivateKey'{}.
ec_key({PubKey, PrivateKey}, Params) ->
#'ECPrivateKey'{version = 1,
privateKey = PrivateKey,
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index 80895ce97c..4b1b771613 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -60,7 +60,8 @@ all() ->
groups() ->
[{pem_decode_encode, [], [dsa_pem, rsa_pem, ec_pem, encrypted_pem,
- dh_pem, cert_pem, pkcs7_pem, pkcs10_pem]},
+ dh_pem, cert_pem, pkcs7_pem, pkcs10_pem, ec_pem2,
+ ec_pem_encode_generated]},
{ssh_public_key_decode_encode, [],
[ssh_rsa_public_key, ssh_dsa_public_key, ssh_ecdsa_public_key,
ssh_rfc4716_rsa_comment, ssh_rfc4716_dsa_comment,
@@ -101,6 +102,7 @@ init_per_testcase(TestCase, Config) ->
ssh_hostkey_fingerprint_sha384 -> init_fingerprint_testcase([sha384], Config);
ssh_hostkey_fingerprint_sha512 -> init_fingerprint_testcase([sha512], Config);
ssh_hostkey_fingerprint_list -> init_fingerprint_testcase([sha,md5], Config);
+ ec_pem_encode_generated -> init_ec_pem_encode_generated(Config);
_ -> init_common_per_testcase(Config)
end.
@@ -217,9 +219,47 @@ ec_pem(Config) when is_list(Config) ->
true = check_entry_type(ECParams, 'EcpkParameters'),
ECPrivKey = public_key:pem_entry_decode(Entry2),
true = check_entry_type(ECPrivKey, 'ECPrivateKey'),
+ true = check_entry_type(ECPrivKey#'ECPrivateKey'.parameters, 'EcpkParameters'),
ECPemNoEndNewLines = strip_superfluous_newlines(ECPrivPem),
ECPemNoEndNewLines = strip_superfluous_newlines(public_key:pem_encode([Entry1, Entry2])).
+ec_pem2() ->
+ [{doc, "EC key w/explicit params PEM-file decode/encode"}].
+ec_pem2(Config) when is_list(Config) ->
+ Datadir = proplists:get_value(data_dir, Config),
+
+ %% Load key with explicit curve parameters. Generated with...
+ %% openssl ecparam -name secp521r1 -genkey -param_enc explicit -out ec_key2.pem
+ {ok, ECPrivPem} = file:read_file(filename:join(Datadir, "ec_key2.pem")),
+ [{'EcpkParameters', _, not_encrypted} = Entry1,
+ {'ECPrivateKey', _, not_encrypted} = Entry2] = public_key:pem_decode(ECPrivPem),
+
+ ECParams = public_key:pem_entry_decode(Entry1),
+ true = check_entry_type(ECParams, 'EcpkParameters'),
+ ECPrivKey = public_key:pem_entry_decode(Entry2),
+ true = check_entry_type(ECPrivKey, 'ECPrivateKey'),
+ true = check_entry_type(ECPrivKey#'ECPrivateKey'.parameters, 'EcpkParameters'),
+ ECPemNoEndNewLines = strip_superfluous_newlines(ECPrivPem),
+ ECPemNoEndNewLines = strip_superfluous_newlines(public_key:pem_encode([Entry1, Entry2])).
+
+
+init_ec_pem_encode_generated(Config) ->
+ case catch true = lists:member('secp384r1', crypto:ec_curves()) of
+ {'EXIT', _} -> {skip, {'secp384r1', not_supported}};
+ _ -> init_common_per_testcase(Config)
+ end.
+
+ec_pem_encode_generated() ->
+ [{doc, "PEM-encode generated EC key"}].
+ec_pem_encode_generated(Config) ->
+
+ Key1 = public_key:generate_key({namedCurve, 'secp384r1'}),
+ public_key:pem_entry_encode('ECPrivateKey', Key1),
+
+ Key2 = public_key:generate_key({namedCurve, ?'secp384r1'}),
+ public_key:pem_entry_encode('ECPrivateKey', Key2).
+
+
%%--------------------------------------------------------------------
encrypted_pem() ->
@@ -1095,7 +1135,7 @@ check_entry_type(#'ECPrivateKey'{}, 'ECPrivateKey') ->
true;
check_entry_type({namedCurve, _}, 'EcpkParameters') ->
true;
-check_entry_type(#'ECParameters'{}, 'EcpkParameters') ->
+check_entry_type({ecParameters, #'ECParameters'{}}, 'EcpkParameters') ->
true;
check_entry_type(_,_) ->
false.
diff --git a/lib/public_key/test/public_key_SUITE_data/ec_key2.pem b/lib/public_key/test/public_key_SUITE_data/ec_key2.pem
new file mode 100644
index 0000000000..56b8169e86
--- /dev/null
+++ b/lib/public_key/test/public_key_SUITE_data/ec_key2.pem
@@ -0,0 +1,29 @@
+-----BEGIN EC PARAMETERS-----
+MIIBwgIBATBNBgcqhkjOPQEBAkIB////////////////////////////////////
+//////////////////////////////////////////////////8wgZ4EQgH/////
+////////////////////////////////////////////////////////////////
+/////////////////ARBUZU+uWGOHJofkpohoLaFQO6i2nJbmbMV87i0iZGO8Qnh
+Vhk5Uex+k3sWUsC9O7G/BzVz34g9LDTx70Uf1GtQPwADFQDQnogAKRy4U5bMZxc5
+MoSqoNpkugSBhQQAxoWOBrcEBOnNnj7LZiOVtEKcZIE5BT+1Ifgor2BrTT26oUte
+d+/nWSj+HcEnov+o3jNIs8GFakKb+X5+McLlvWYBGDkpaniaO8AEXIpftCx9G9mY
+9URJV5tEaBevvRcnPmYsl+5ymV70JkDFULkBP60HYTU8cIaicsJAiL6Udp/RZlAC
+QgH///////////////////////////////////////////pRhoeDvy+Wa3/MAUj3
+CaXQO7XJuImcR667b7cekThkCQIBAQ==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MIICnQIBAQRCAVE6lUKRj5AE8Cw21A+iPWhXSg+XNuerrTyeFERY6AtOrRJ9mTQ3
+Av3xjiM3zhZy2KWnm62hvkvlGbZ7iDKcqg2GoIIBxjCCAcICAQEwTQYHKoZIzj0B
+AQJCAf//////////////////////////////////////////////////////////
+////////////////////////////MIGeBEIB////////////////////////////
+//////////////////////////////////////////////////////////wEQVGV
+PrlhjhyaH5KaIaC2hUDuotpyW5mzFfO4tImRjvEJ4VYZOVHsfpN7FlLAvTuxvwc1
+c9+IPSw08e9FH9RrUD8AAxUA0J6IACkcuFOWzGcXOTKEqqDaZLoEgYUEAMaFjga3
+BATpzZ4+y2YjlbRCnGSBOQU/tSH4KK9ga009uqFLXnfv51ko/h3BJ6L/qN4zSLPB
+hWpCm/l+fjHC5b1mARg5KWp4mjvABFyKX7QsfRvZmPVESVebRGgXr70XJz5mLJfu
+cple9CZAxVC5AT+tB2E1PHCGonLCQIi+lHaf0WZQAkIB////////////////////
+///////////////////////6UYaHg78vlmt/zAFI9wml0Du1ybiJnEeuu2+3HpE4
+ZAkCAQGhgYkDgYYABAFLBJzBphlIJmSPuXzTDTnZpL7A0fnyqit9V3TBvaOcL6Iw
+6m2TpXvNakxi8Flj0Ok4hdRt+YhawFs0bmzZCT8kfAFs7p55BPHk7FaMZaba77R8
+4V6MhUJSKLc0I/XQBtvoOgVlPJ0MPOndnIxPspCPll886yxG5kOMUAx3HjFg16RT
+eA==
+-----END EC PRIVATE KEY-----