aboutsummaryrefslogtreecommitdiffstats
path: root/lib/public_key/src/public_key.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/public_key/src/public_key.erl')
-rw-r--r--lib/public_key/src/public_key.erl90
1 files changed, 87 insertions, 3 deletions
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 736c18cdd4..6c25428ea4 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -94,7 +94,9 @@ pem_entry_decode({'SubjectPublicKeyInfo', Der, _}) ->
der_decode(KeyType, Key0);
'DSAPublicKey' ->
{params, DssParams} = der_decode('DSAParams', Params),
- {der_decode(KeyType, Key0), DssParams}
+ {der_decode(KeyType, Key0), DssParams};
+ 'ECPrivateKey' ->
+ der_decode(KeyType, Key0)
end;
pem_entry_decode({Asn1Type, Der, not_encrypted}) when is_atom(Asn1Type),
is_binary(Der) ->
@@ -336,6 +338,40 @@ format_rsa_private_key(#'RSAPrivateKey'{modulus = N, publicExponent = E,
privateExponent = D}) ->
[crypto:mpint(K) || K <- [E, N, D]].
+%%
+%% Description: convert a ECPrivate key into resource Key
+%%--------------------------------------------------------------------
+list2int(L) ->
+ S = length(L) * 8,
+ <<R:S/integer>> = erlang:iolist_to_binary(L),
+ R.
+
+ec_private_key_to_eckey(#'ECPrivateKey'{privateKey = PrivKey,
+ parameters = Param,
+ publicKey = _PubKey}) ->
+ ECCurve = case Param of
+ #'OTPECParameters'{ fieldID = FieldId, curve = PCurve, base = Base, order = Order, cofactor = CoFactor } ->
+ Field = {pubkey_cert_records:supportedCurvesTypes(FieldId#'OTPFieldID'.fieldType), FieldId#'OTPFieldID'.parameters},
+ Curve = {list2int(PCurve#'Curve'.a), list2int(PCurve#'Curve'.b), none},
+ {Field, Curve, erlang:list_to_binary(Base), Order, CoFactor};
+ {namedCurve, OID} ->
+ pubkey_cert_records:namedCurves(OID)
+ end,
+ Key = {ECCurve, list2int(PrivKey), undefined},
+ {'ECKey', crypto:term_to_ec_key(Key)}.
+
+ec_public_key_to_eckey({#'ECPoint'{point = ECPoint}, Param}) ->
+ ECCurve = case Param of
+ #'OTPECParameters'{ fieldID = FieldId, curve = PCurve, base = Base, order = Order, cofactor = CoFactor } ->
+ Field = {pubkey_cert_records:supportedCurvesTypes(FieldId#'OTPFieldID'.fieldType), FieldId#'OTPFieldID'.parameters},
+ Curve = {list2int(PCurve#'Curve'.a), list2int(PCurve#'Curve'.b), none},
+ {Field, Curve, erlang:list_to_binary(Base), Order, CoFactor};
+ {namedCurve, OID} ->
+ pubkey_cert_records:namedCurves(OID)
+ end,
+ Key = {ECCurve, undefined, ECPoint},
+ {'ECKey', crypto:term_to_ec_key(Key)}.
+
%%--------------------------------------------------------------------
-spec pkix_sign_types(SignatureAlg::oid()) ->
@@ -362,7 +398,15 @@ pkix_sign_types(?md5WithRSAEncryption) ->
pkix_sign_types(?'id-dsa-with-sha1') ->
{sha, dsa};
pkix_sign_types(?'id-dsaWithSHA1') ->
- {sha, dsa}.
+ {sha, dsa};
+pkix_sign_types(?'ecdsa-with-SHA1') ->
+ {sha, ecdsa};
+pkix_sign_types(?'ecdsa-with-SHA256') ->
+ {sha256, ecdsa};
+pkix_sign_types(?'ecdsa-with-SHA384') ->
+ {sha384, ecdsa};
+pkix_sign_types(?'ecdsa-with-SHA512') ->
+ {sha512, ecdsa}.
%%--------------------------------------------------------------------
-spec sign(binary() | {digest, binary()}, rsa_digest_type() | dss_digest_type(),
@@ -386,6 +430,18 @@ sign(PlainText, sha, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X}) ->
[crypto:mpint(P), crypto:mpint(Q),
crypto:mpint(G), crypto:mpint(X)]);
+sign(Digest, DigestType, Key = {?'id-ecPublicKey', _, _}) ->
+ sign(Digest, DigestType, ec_public_key_to_eckey(Key));
+
+sign(Digest, DigestType, Key = #'ECPrivateKey'{}) ->
+ sign(Digest, DigestType, ec_private_key_to_eckey(Key));
+
+sign({digest,_}=Digest, DigestType, {'ECKey', Key}) ->
+ crypto:ecdsa_sign(DigestType, Digest, Key);
+
+sign(PlainText, DigestType, {'ECKey', Key}) ->
+ crypto:ecdsa_sign(DigestType, sized_binary(PlainText), Key);
+
%% Backwards compatible
sign(Digest, none, #'DSAPrivateKey'{} = Key) ->
sign({digest,Digest}, sha, Key).
@@ -414,6 +470,24 @@ verify({digest,_}=Digest, sha, Signature, {Key, #'Dss-Parms'{p = P, q = Q, g =
crypto:dss_verify(Digest, sized_binary(Signature),
[crypto:mpint(P), crypto:mpint(Q),
crypto:mpint(G), crypto:mpint(Key)]);
+
+verify({digest,_}=Digest, DigestType, Signature, {'ECKey', Key}) ->
+ crypto:ecdsa_verify(DigestType, Digest,
+ sized_binary(Signature),
+ Key);
+
+verify(PlainText, DigestType, Signature, Key = #'ECPrivateKey'{}) ->
+ verify(PlainText, DigestType, Signature, ec_private_key_to_eckey(Key));
+
+verify(PlainText, DigestType, Signature, Key = {#'ECPoint'{}, _}) ->
+ verify(PlainText, DigestType, Signature, ec_public_key_to_eckey(Key));
+
+verify(PlainText, DigestType, Signature, {'ECKey', Key}) ->
+ crypto:ecdsa_verify(DigestType,
+ sized_binary(PlainText),
+ sized_binary(Signature),
+ Key);
+
%% Backwards compatibility
verify(Digest, none, Signature, {_, #'Dss-Parms'{}} = Key ) ->
verify({digest,Digest}, sha, Signature, Key);
@@ -458,7 +532,17 @@ pkix_verify(DerCert, {Key, #'Dss-Parms'{}} = DSAKey)
pkix_verify(DerCert, #'RSAPublicKey'{} = RSAKey)
when is_binary(DerCert) ->
{DigestType, PlainText, Signature} = pubkey_cert:verify_data(DerCert),
- verify(PlainText, DigestType, Signature, RSAKey).
+ verify(PlainText, DigestType, Signature, RSAKey);
+
+pkix_verify(DerCert, #'ECPrivateKey'{} = ECKey)
+ when is_binary(DerCert) ->
+ {DigestType, PlainText, Signature} = pubkey_cert:verify_data(DerCert),
+ verify(PlainText, DigestType, Signature, ECKey);
+
+pkix_verify(DerCert, Key = {'ECKey', _})
+ when is_binary(DerCert) ->
+ {DigestType, PlainText, Signature} = pubkey_cert:verify_data(DerCert),
+ verify(PlainText, DigestType, Signature, Key).
%%--------------------------------------------------------------------
-spec pkix_is_issuer(Cert :: der_encoded()| #'OTPCertificate'{} | #'CertificateList'{},