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.erl137
1 files changed, 96 insertions, 41 deletions
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 095a6ff0e0..2901020e83 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. 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
@@ -41,7 +41,8 @@
pkix_is_issuer/2,
pkix_issuer_id/2,
pkix_normalize_name/1,
- pkix_path_validation/3
+ pkix_path_validation/3,
+ ssh_decode/2, ssh_encode/2
]).
%% Deprecated
@@ -51,10 +52,6 @@
-deprecated({decode_private_key, 1, next_major_release}).
-deprecated({decode_private_key, 2, next_major_release}).
--type rsa_public_key() :: #'RSAPublicKey'{}.
--type rsa_private_key() :: #'RSAPrivateKey'{}.
--type dsa_private_key() :: #'DSAPrivateKey'{}.
--type dsa_public_key() :: {integer(), #'Dss-Parms'{}}.
-type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding'
| 'rsa_no_padding'.
-type public_crypt_options() :: [{rsa_pad, rsa_padding()}].
@@ -62,11 +59,11 @@
-type dss_digest_type() :: 'none' | 'sha'.
-define(UINT32(X), X:32/unsigned-big-integer).
+-define(DER_NULL, <<5, 0>>).
%%====================================================================
%% API
%%====================================================================
-
%%--------------------------------------------------------------------
-spec pem_decode(binary()) -> [pem_entry()].
%%
@@ -90,6 +87,17 @@ pem_encode(PemEntries) when is_list(PemEntries) ->
%% Description: Decodes a pem entry. pem_decode/1 returns a list of
%% pem entries.
%%--------------------------------------------------------------------
+pem_entry_decode({'SubjectPublicKeyInfo', Der, _}) ->
+ {_, {'AlgorithmIdentifier', AlgId, Params}, {0, Key0}}
+ = der_decode('SubjectPublicKeyInfo', Der),
+ KeyType = pubkey_cert_records:supportedPublicKeyAlgorithms(AlgId),
+ case KeyType of
+ 'RSAPublicKey' ->
+ der_decode(KeyType, Key0);
+ 'DSAPublicKey' ->
+ {params, DssParams} = der_decode('DSAParams', Params),
+ {der_decode(KeyType, Key0), DssParams}
+ end;
pem_entry_decode({Asn1Type, Der, not_encrypted}) when is_atom(Asn1Type),
is_binary(Der) ->
der_decode(Asn1Type, Der).
@@ -114,6 +122,18 @@ pem_entry_decode({Asn1Type, CryptDer, {Cipher, Salt}} = PemEntry,
%
%% Description: Creates a pem entry that can be feed to pem_encode/1.
%%--------------------------------------------------------------------
+pem_entry_encode('SubjectPublicKeyInfo', Entity=#'RSAPublicKey'{}) ->
+ Der = der_encode('RSAPublicKey', Entity),
+ Spki = {'SubjectPublicKeyInfo',
+ {'AlgorithmIdentifier', ?'rsaEncryption', ?DER_NULL}, {0, Der}},
+ pem_entry_encode('SubjectPublicKeyInfo', Spki);
+pem_entry_encode('SubjectPublicKeyInfo',
+ {DsaInt, Params=#'Dss-Parms'{}}) when is_integer(DsaInt) ->
+ KeyDer = der_encode('DSAPublicKey', DsaInt),
+ ParamDer = der_encode('DSAParams', {params, Params}),
+ Spki = {'SubjectPublicKeyInfo',
+ {'AlgorithmIdentifier', ?'id-dsa', ParamDer}, {0, KeyDer}},
+ pem_entry_encode('SubjectPublicKeyInfo', Spki);
pem_entry_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
Der = der_encode(Asn1Type, Entity),
{Asn1Type, Der, not_encrypted}.
@@ -128,7 +148,7 @@ pem_entry_encode(Asn1Type, Entity,
{Asn1Type, DecryptDer, CipherInfo}.
%%--------------------------------------------------------------------
--spec der_decode(asn1_type(), der_encoded()) -> term().
+-spec der_decode(asn1_type(), Der::binary()) -> term().
%%
%% Description: Decodes a public key asn1 der encoded entity.
%%--------------------------------------------------------------------
@@ -142,7 +162,7 @@ der_decode(Asn1Type, Der) when is_atom(Asn1Type), is_binary(Der) ->
end.
%%--------------------------------------------------------------------
--spec der_encode(asn1_type(), term()) -> der_encoded().
+-spec der_encode(asn1_type(), term()) -> Der::binary().
%%
%% Description: Encodes a public key entity with asn1 DER encoding.
%%--------------------------------------------------------------------
@@ -156,7 +176,7 @@ der_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
end.
%%--------------------------------------------------------------------
--spec pkix_decode_cert(der_encoded(), plain | otp) ->
+-spec pkix_decode_cert(Cert::binary(), plain | otp) ->
#'Certificate'{} | #'OTPCertificate'{}.
%%
%% Description: Decodes an asn1 der encoded pkix certificate. The otp
@@ -177,7 +197,7 @@ pkix_decode_cert(DerCert, otp) when is_binary(DerCert) ->
end.
%%--------------------------------------------------------------------
--spec pkix_encode(asn1_type(), term(), otp | plain) -> der_encoded().
+-spec pkix_encode(asn1_type(), term(), otp | plain) -> Der::binary().
%%
%% Description: Der encodes a certificate or part of a certificate.
%% This function must be used for encoding certificates or parts of certificates
@@ -213,10 +233,13 @@ decrypt_private(CipherText,
crypto:mpint(D)], Padding).
%%--------------------------------------------------------------------
--spec decrypt_public(CipherText :: binary(), rsa_public_key()) ->
+-spec decrypt_public(CipherText :: binary(), rsa_public_key() | rsa_private_key()) ->
PlainText :: binary().
--spec decrypt_public(CipherText :: binary(), rsa_public_key(),
+-spec decrypt_public(CipherText :: binary(), rsa_public_key() | rsa_private_key(),
public_crypt_options()) -> PlainText :: binary().
+%% NOTE: The rsa_private_key() is not part of the documented API it is
+%% here for testing purposes, in a real situation this is not a relevant
+%% thing to do.
%%
%% Description: Public key decryption using the public key.
%%--------------------------------------------------------------------
@@ -232,10 +255,14 @@ decrypt_public(CipherText,#'RSAPrivateKey'{modulus = N, publicExponent = E},
decrypt_public(CipherText, N,E, Options).
%%--------------------------------------------------------------------
--spec encrypt_public(PlainText :: binary(), rsa_public_key()) ->
+-spec encrypt_public(PlainText :: binary(), rsa_public_key() | rsa_private_key()) ->
CipherText :: binary().
--spec encrypt_public(PlainText :: binary(), rsa_public_key(),
+-spec encrypt_public(PlainText :: binary(), rsa_public_key() | rsa_private_key(),
public_crypt_options()) -> CipherText :: binary().
+
+%% NOTE: The rsa_private_key() is not part of the documented API it is
+%% here for testing purposes, in a real situation this is not a relevant
+%% thing to do.
%%
%% Description: Public key encryption using the public key.
%%--------------------------------------------------------------------
@@ -280,8 +307,8 @@ encrypt_private(PlainText, #'RSAPrivateKey'{modulus = N,
sign(PlainText, DigestType, #'RSAPrivateKey'{modulus = N, publicExponent = E,
privateExponent = D})
when is_binary(PlainText),
- DigestType == md5;
- DigestType == sha ->
+ (DigestType == md5 orelse
+ DigestType == sha) ->
crypto:rsa_sign(DigestType, sized_binary(PlainText), [crypto:mpint(E),
crypto:mpint(N),
@@ -330,7 +357,7 @@ verify(PlainText, sha, Signature, {Key, #'Dss-Parms'{p = P, q = Q, g = G}})
crypto:mpint(G), crypto:mpint(Key)]).
%%--------------------------------------------------------------------
-spec pkix_sign(#'OTPTBSCertificate'{},
- rsa_private_key() | dsa_private_key()) -> der_encoded().
+ rsa_private_key() | dsa_private_key()) -> Der::binary().
%%
%% Description: Sign a pkix x.509 certificate. Returns the corresponding
%% der encoded 'Certificate'{}
@@ -339,7 +366,7 @@ pkix_sign(#'OTPTBSCertificate'{signature =
#'SignatureAlgorithm'{algorithm = Alg}
= SigAlg} = TBSCert, Key) ->
- Msg = pkix_encode('OTPTBSCertificate', TBSCert, otp),
+ Msg = pkix_encode('OTPTBSCertificate', TBSCert, otp),
DigestType = pubkey_cert:digest_type(Alg),
Signature = sign(Msg, DigestType, Key),
Cert = #'OTPCertificate'{tbsCertificate= TBSCert,
@@ -349,7 +376,7 @@ pkix_sign(#'OTPTBSCertificate'{signature =
pkix_encode('OTPCertificate', Cert, otp).
%%--------------------------------------------------------------------
--spec pkix_verify(der_encoded(), rsa_public_key()|
+-spec pkix_verify(Cert::binary(), rsa_public_key()|
dsa_public_key()) -> boolean().
%%
%% Description: Verify pkix x.509 certificate signature.
@@ -365,9 +392,9 @@ pkix_verify(DerCert, #'RSAPublicKey'{} = RSAKey)
verify(PlainText, DigestType, Signature, RSAKey).
%%--------------------------------------------------------------------
--spec pkix_is_issuer(Cert :: der_encoded()| #'OTPCertificate'{},
- IssuerCert :: der_encoded()|
- #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_issuer(Cert::binary()| #'OTPCertificate'{},
+ IssuerCert::binary()|
+ #'OTPCertificate'{}) -> boolean().
%%
%% Description: Checks if <IssuerCert> issued <Cert>.
%%--------------------------------------------------------------------
@@ -383,7 +410,7 @@ pkix_is_issuer(#'OTPCertificate'{tbsCertificate = TBSCert},
Candidate#'OTPTBSCertificate'.subject).
%%--------------------------------------------------------------------
--spec pkix_is_self_signed(der_encoded()| #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_self_signed(Cert::binary()| #'OTPCertificate'{}) -> boolean().
%%
%% Description: Checks if a Certificate is self signed.
%%--------------------------------------------------------------------
@@ -394,7 +421,7 @@ pkix_is_self_signed(Cert) when is_binary(Cert) ->
pkix_is_self_signed(OtpCert).
%%--------------------------------------------------------------------
--spec pkix_is_fixed_dh_cert(der_encoded()| #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_fixed_dh_cert(Cert::binary()| #'OTPCertificate'{}) -> boolean().
%%
%% Description: Checks if a Certificate is a fixed Diffie-Hellman Cert.
%%--------------------------------------------------------------------
@@ -405,14 +432,14 @@ pkix_is_fixed_dh_cert(Cert) when is_binary(Cert) ->
pkix_is_fixed_dh_cert(OtpCert).
%%--------------------------------------------------------------------
--spec pkix_issuer_id(der_encoded()| #'OTPCertificate'{},
- IssuedBy :: self | other) ->
- {ok, {SerialNr :: integer(),
- Issuer :: {rdnSequence,
- [#'AttributeTypeAndValue'{}]}}}
+-spec pkix_issuer_id(Cert::binary()| #'OTPCertificate'{},
+ IssuedBy :: self | other) ->
+ {ok, {SerialNr :: integer(),
+ Issuer :: {rdnSequence,
+ [#'AttributeTypeAndValue'{}]}}}
| {error, Reason :: term()}.
%
-%% Description: Returns the issuer id.
+%% Description: Returns the issuer id.
%%--------------------------------------------------------------------
pkix_issuer_id(#'OTPCertificate'{} = OtpCert, self) ->
pubkey_cert:issuer_id(OtpCert, self);
@@ -425,8 +452,8 @@ pkix_issuer_id(Cert, Signed) when is_binary(Cert) ->
pkix_issuer_id(OtpCert, Signed).
%%--------------------------------------------------------------------
--spec pkix_normalize_name({rdnSequence,
- [#'AttributeTypeAndValue'{}]}) ->
+-spec pkix_normalize_name({rdnSequence,
+ [#'AttributeTypeAndValue'{}]}) ->
{rdnSequence,
[#'AttributeTypeAndValue'{}]}.
%%
@@ -437,8 +464,8 @@ pkix_normalize_name(Issuer) ->
pubkey_cert:normalize_general_name(Issuer).
%%--------------------------------------------------------------------
--spec pkix_path_validation(der_encoded()| #'OTPCertificate'{} | atom(),
- CertChain :: [der_encoded()] ,
+-spec pkix_path_validation(Cert::binary()| #'OTPCertificate'{} | atom(),
+ CertChain :: [binary()] ,
Options :: list()) ->
{ok, {PublicKeyInfo :: term(),
PolicyTree :: term()}} |
@@ -465,7 +492,7 @@ pkix_path_validation(TrustedCert, CertChain, Options) when
is_binary(TrustedCert) -> OtpCert = pkix_decode_cert(TrustedCert,
otp), pkix_path_validation(OtpCert, CertChain, Options);
-pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options)
+pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options)
when is_list(CertChain), is_list(Options) ->
MaxPathDefault = length(CertChain),
ValidationState = pubkey_cert:init_validation_state(TrustedCert,
@@ -474,6 +501,37 @@ pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options)
path_validation(CertChain, ValidationState).
%%--------------------------------------------------------------------
+-spec ssh_decode(binary(), public_key | ssh_file()) -> [{public_key(), Attributes::list()}].
+%%
+%% Description: Decodes a ssh file-binary. In the case of know_hosts
+%% or auth_keys the binary may include one or more lines of the
+%% file. Returns a list of public keys and their attributes, possible
+%% attribute values depends on the file type represented by the
+%% binary.
+%%--------------------------------------------------------------------
+ssh_decode(SshBin, Type) when is_binary(SshBin),
+ Type == public_key;
+ Type == rfc4716_public_key;
+ Type == openssh_public_key;
+ Type == auth_keys;
+ Type == known_hosts ->
+ pubkey_ssh:decode(SshBin, Type).
+
+%%--------------------------------------------------------------------
+-spec ssh_encode([{public_key(), Attributes::list()}], ssh_file()) ->
+ binary().
+%% Description: Encodes a list of ssh file entries (public keys and
+%% attributes) to a binary. Possible attributes depends on the file
+%% type.
+%%--------------------------------------------------------------------
+ssh_encode(Entries, Type) when is_list(Entries),
+ Type == rfc4716_public_key;
+ Type == openssh_public_key;
+ Type == auth_keys;
+ Type == known_hosts ->
+ pubkey_ssh:encode(Entries, Type).
+
+%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
@@ -487,7 +545,6 @@ decrypt_public(CipherText, N,E, Options) ->
crypto:rsa_public_decrypt(CipherText,[crypto:mpint(E), crypto:mpint(N)],
Padding).
-
path_validation([], #path_validation_state{working_public_key_algorithm
= Algorithm,
working_public_key =
@@ -571,11 +628,9 @@ validate(DerCert, #path_validation_state{working_issuer_name = Issuer,
pubkey_cert:prepare_for_next_cert(OtpCert, ValidationState).
-sized_binary(Binary) when is_binary(Binary) ->
+sized_binary(Binary) ->
Size = size(Binary),
- <<?UINT32(Size), Binary/binary>>;
-sized_binary(List) ->
- sized_binary(list_to_binary(List)).
+ <<?UINT32(Size), Binary/binary>>.
%%--------------------------------------------------------------------
%%% Deprecated functions