From f0dbde23b539999add8754ec84541698419fc8b5 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Tue, 20 Apr 2010 12:00:00 +0200 Subject: public_key, ssl: Patch 1112 OTP-7046 Support for Diffie-Hellman. ssl-3.11 requires public_key-0.6. OTP-8553 Moved extended key usage test for ssl values to ssl. OTP-8557 Fixes handling of the option fail_if_no_peer_cert and some undocumented options. Thanks to Rory Byrne. OTP-7046 Support for Diffie-Hellman. ssl-3.11 requires public_key-0.6. OTP-8517 New ssl now properly handles ssl renegotiation, and initiates a renegotiation if ssl/ltls-sequence numbers comes close to the max value. However RFC-5746 is not yet supported, but will be in an upcoming release. OTP-8545 When gen_tcp is configured with the {packet,http} option, it automatically switches to expect HTTP Headers after a HTTP Request/Response line has been received. This update fixes ssl to behave in the same way. Thanks to Rory Byrne. OTP-8554 Ssl now correctly verifies the extended_key_usage extension and also allows the user to verify application specific extensions by supplying an appropriate fun. OTP-8560 Fixed ssl:transport_accept/2 to return properly when socket is closed. Thanks to Rory Byrne. --- lib/public_key/asn1/Makefile | 14 ++++---- lib/public_key/asn1/OTP-PUB-KEY.set.asn | 1 + lib/public_key/asn1/PKCS-3.asn1 | 21 ++++++++++++ lib/public_key/doc/src/notes.xml | 21 ++++++++++++ lib/public_key/src/pubkey_cert.erl | 35 +++---------------- lib/public_key/src/pubkey_crypto.erl | 59 +++++++++++++++++++++++---------- lib/public_key/src/pubkey_pem.erl | 12 +++---- lib/public_key/src/public_key.appup.src | 26 +++++++++++++-- lib/public_key/src/public_key.erl | 47 +++++++++++++++++++++----- lib/public_key/vsn.mk | 7 ++-- 10 files changed, 170 insertions(+), 73 deletions(-) create mode 100644 lib/public_key/asn1/PKCS-3.asn1 (limited to 'lib/public_key') diff --git a/lib/public_key/asn1/Makefile b/lib/public_key/asn1/Makefile index fbea701be9..94abec083c 100644 --- a/lib/public_key/asn1/Makefile +++ b/lib/public_key/asn1/Makefile @@ -1,19 +1,19 @@ # # %CopyrightBegin% -# -# Copyright Ericsson AB 2008-2009. All Rights Reserved. -# +# +# Copyright Ericsson AB 2008-2010. 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% # @@ -40,7 +40,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/public_key-$(VSN) ASN_TOP = OTP-PUB-KEY ASN_MODULES = PKIX1Explicit88 PKIX1Implicit88 PKIX1Algorithms88 \ - PKIXAttributeCertificate OTP-PKIX + PKIXAttributeCertificate PKCS-1 PKCS-3 OTP-PKIX ASN_ASNS = $(ASN_MODULES:%=%.asn1) ASN_ERLS = $(ASN_TOP).erl ASN_HRLS = $(ASN_TOP).hrl @@ -110,4 +110,6 @@ OTP-PUB-KEY.asn1db: PKIX1Algorithms88.asn1 \ PKIX1Explicit88.asn1 \ PKIX1Implicit88.asn1 \ PKIXAttributeCertificate.asn1 \ + PKCS-1.asn1\ + PKCS-3.asn1\ OTP-PKIX.asn1 diff --git a/lib/public_key/asn1/OTP-PUB-KEY.set.asn b/lib/public_key/asn1/OTP-PUB-KEY.set.asn index 2f9ccd6b0e..5c76d13115 100644 --- a/lib/public_key/asn1/OTP-PUB-KEY.set.asn +++ b/lib/public_key/asn1/OTP-PUB-KEY.set.asn @@ -4,4 +4,5 @@ PKIX1Implicit88.asn1 PKIXAttributeCertificate.asn1 PKIX1Algorithms88.asn1 PKCS-1.asn1 +PKCS-3.asn1 DSS.asn1 diff --git a/lib/public_key/asn1/PKCS-3.asn1 b/lib/public_key/asn1/PKCS-3.asn1 new file mode 100644 index 0000000000..64180b3a85 --- /dev/null +++ b/lib/public_key/asn1/PKCS-3.asn1 @@ -0,0 +1,21 @@ +PKCS-3 { + iso(1) member-body(2) us(840) rsadsi(113549) + pkcs(1) 3 +} + +DEFINITIONS EXPLICIT TAGS ::= + +BEGIN + +pkcs-3 OBJECT IDENTIFIER ::= + { iso(1) member-body(2) us(840) rsadsi(113549) + pkcs(1) 3 } + +dhKeyAgreement OBJECT IDENTIFIER ::= { pkcs-3 1 } + +DHParameter ::= SEQUENCE { + prime INTEGER, -- p + base INTEGER, -- g + privateValueLength INTEGER OPTIONAL } + +END \ No newline at end of file diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml index a5fbc81093..33a424f432 100644 --- a/lib/public_key/doc/src/notes.xml +++ b/lib/public_key/doc/src/notes.xml @@ -33,6 +33,27 @@ A notes.xml +
Public_Key 0.6 + +
Improvements and New Features + + +

+ Support for Diffie-Hellman. ssl-3.11 requires + public_key-0.6.

+

+ Own Id: OTP-7046

+
+ +

+ Moved extended key usage test for ssl values to ssl.

+

+ Own Id: OTP-8553 Aux Id: seq11541, OTP-8554

+
+
+
+ +
Public_Key 0.5 diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl index 0ccc74799c..8f7dfa8352 100644 --- a/lib/public_key/src/pubkey_cert.erl +++ b/lib/public_key/src/pubkey_cert.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2008-2010. 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% %% @@ -455,24 +455,6 @@ validate_extensions([#'Extension'{extnID = ?'id-ce-keyUsage', AccErr) end; -validate_extensions([#'Extension'{extnID = ?'id-ce-extKeyUsage', - extnValue = KeyUse, - critical = true} | Rest], - #path_validation_state{} = ValidationState, - ExistBasicCon, SelfSigned, UnknownExtensions, Verify, - AccErr0) -> - case is_valid_extkey_usage(KeyUse) of - true -> - validate_extensions(Rest, ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, - Verify, AccErr0); - false -> - AccErr = - not_valid({bad_cert, invalid_ext_key_usage}, Verify, AccErr0), - validate_extensions(Rest, ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, AccErr) - end; - validate_extensions([#'Extension'{extnID = ?'id-ce-subjectAltName', extnValue = Names} | Rest], ValidationState, ExistBasicCon, @@ -590,13 +572,6 @@ validate_extensions([Extension | Rest], ValidationState, is_valid_key_usage(KeyUse, Use) -> lists:member(Use, KeyUse). -is_valid_extkey_usage(?'id-kp-clientAuth') -> - true; -is_valid_extkey_usage(?'id-kp-serverAuth') -> - true; -is_valid_extkey_usage(_) -> - false. - validate_subject_alt_names([]) -> true; validate_subject_alt_names([AltName | Rest]) -> diff --git a/lib/public_key/src/pubkey_crypto.erl b/lib/public_key/src/pubkey_crypto.erl index fe4e97fcc5..4ab655e977 100644 --- a/lib/public_key/src/pubkey_crypto.erl +++ b/lib/public_key/src/pubkey_crypto.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2008-2010. 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% %% @@ -26,7 +26,7 @@ -export([encrypt_public/3, decrypt_private/3, encrypt_private/3, decrypt_public/3, - sign/2, sign/3, verify/5]). + sign/2, sign/3, verify/5, gen_key/2]). -define(UINT32(X), X:32/unsigned-big-integer). @@ -44,10 +44,14 @@ %% %% Description: Public key encrypts PlainText. %%-------------------------------------------------------------------- -encrypt_public(PlainText, #'RSAPublicKey'{modulus=N,publicExponent=E},Padding) -> - crypto:rsa_public_encrypt(PlainText, [crypto:mpint(E),crypto:mpint(N)],Padding); -encrypt_public(PlainText, #'RSAPrivateKey'{modulus=N,publicExponent=E},Padding) -> - crypto:rsa_public_encrypt(PlainText, [crypto:mpint(E),crypto:mpint(N)],Padding). +encrypt_public(PlainText, #'RSAPublicKey'{modulus=N,publicExponent=E}, + Padding) -> + crypto:rsa_public_encrypt(PlainText, [crypto:mpint(E),crypto:mpint(N)], + Padding); +encrypt_public(PlainText, #'RSAPrivateKey'{modulus=N,publicExponent=E}, + Padding) -> + crypto:rsa_public_encrypt(PlainText, [crypto:mpint(E),crypto:mpint(N)], + Padding). encrypt_private(PlainText, #'RSAPrivateKey'{modulus = N, publicExponent = E, @@ -67,15 +71,20 @@ encrypt_private(PlainText, #'RSAPrivateKey'{modulus = N, %% Description: Uses private key to decrypt public key encrypted data. %%-------------------------------------------------------------------- decrypt_private(CipherText, - #'RSAPrivateKey'{modulus = N,publicExponent = E,privateExponent = D}, + #'RSAPrivateKey'{modulus = N,publicExponent = E, + privateExponent = D}, Padding) -> crypto:rsa_private_decrypt(CipherText, - [crypto:mpint(E), crypto:mpint(N),crypto:mpint(D)], - Padding). -decrypt_public(CipherText, #'RSAPublicKey'{modulus = N, publicExponent = E}, Padding) -> - crypto:rsa_public_decrypt(CipherText,[crypto:mpint(E), crypto:mpint(N)], Padding); -decrypt_public(CipherText, #'RSAPrivateKey'{modulus = N, publicExponent = E}, Padding) -> - crypto:rsa_public_decrypt(CipherText,[crypto:mpint(E), crypto:mpint(N)], Padding). + [crypto:mpint(E), crypto:mpint(N), + crypto:mpint(D)], Padding). +decrypt_public(CipherText, #'RSAPublicKey'{modulus = N, publicExponent = E}, + Padding) -> + crypto:rsa_public_decrypt(CipherText,[crypto:mpint(E), crypto:mpint(N)], + Padding); +decrypt_public(CipherText, #'RSAPrivateKey'{modulus = N, publicExponent = E}, + Padding) -> + crypto:rsa_public_decrypt(CipherText,[crypto:mpint(E), crypto:mpint(N)], + Padding). %%-------------------------------------------------------------------- %% Function: sign(PlainText, Key) -> @@ -125,10 +134,24 @@ verify(sha, PlainText, Signature, Key, #'Dss-Parms'{p = P, q = Q, g = G}) -> [crypto:mpint(P), crypto:mpint(Q), crypto:mpint(G), crypto:mpint(Key)]). + +%%-------------------------------------------------------------------- +%% Function: gen_key(Type, Params) -> +%% Type = diffie_hellman +%% Params = [P,G] | [Y, P, G] +%% Description: Generates keys. +%% ----------------------------------------------------------------- +gen_key(diffie_hellman, [Y, P, G]) -> + crypto:dh_generate_key(crypto:mpint(Y), [crypto:mpint(P), + crypto:mpint(G)]); +gen_key(diffie_hellman, [P, G]) -> + crypto:dh_generate_key([crypto:mpint(P), crypto:mpint(G)]). + +%%% TODO: Support rsa, dss key_gen + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- - sized_binary(Binary) when is_binary(Binary) -> Size = size(Binary), <>; diff --git a/lib/public_key/src/pubkey_pem.erl b/lib/public_key/src/pubkey_pem.erl index abd46fa00e..9fc17b6f73 100644 --- a/lib/public_key/src/pubkey_pem.erl +++ b/lib/public_key/src/pubkey_pem.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2008-2010. 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% %% @@ -155,7 +155,7 @@ unhex(S) -> unhex(S, []). unhex("", Acc) -> - lists:reverse(Acc); + list_to_binary(lists:reverse(Acc)); unhex([D1, D2 | Rest], Acc) -> unhex(Rest, [erlang:list_to_integer([D1, D2], 16) | Acc]). diff --git a/lib/public_key/src/public_key.appup.src b/lib/public_key/src/public_key.appup.src index ee0f9a3cc1..46e5ecca33 100644 --- a/lib/public_key/src/public_key.appup.src +++ b/lib/public_key/src/public_key.appup.src @@ -1,18 +1,40 @@ %% -*- erlang -*- {"%VSN%", [ + {"0.5", + [ + {update, public_key, soft, soft_purge, soft_purge, []}, + {update, pubkey_crypto, soft, soft_purge, soft_purge, []}, + {update, pubkey_pem, soft, soft_purge, soft_purge, []}, + {update, pubkey_cert, soft, soft_purge, soft_purge, []} + ] + }, {"0.4", [ {update, public_key, soft, soft_purge, soft_purge, []}, - {update, pubkey_cert_records, soft, soft_purge, soft_purge, []} + {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}, + {update, pubkey_crypto, soft, soft_purge, soft_purge, []}, + {update, pubkey_pem, soft, soft_purge, soft_purge, []}, + {update, pubkey_cert, soft, soft_purge, soft_purge, []} ] } ], [ + {"0.5", + [ + {update, public_key, soft, soft_purge, soft_purge, []}, + {update, pubkey_crypto, soft, soft_purge, soft_purge, []}, + {update, pubkey_pem, soft, soft_purge, soft_purge, []}, + {update, pubkey_cert, soft, soft_purge, soft_purge, []} + ] + }, {"0.4", [ {update, public_key, soft, soft_purge, soft_purge, []}, - {update, pubkey_cert_records, soft, soft_purge, soft_purge, []} + {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}, + {update, pubkey_crypto, soft, soft_purge, soft_purge, []}, + {update, pubkey_pem, soft, soft_purge, soft_purge, []}, + {update, pubkey_cert, soft, soft_purge, soft_purge, []} ] } ]}. diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index 52c695523f..157e76bb21 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -23,13 +23,12 @@ -include("public_key.hrl"). --export([decode_private_key/1, decode_private_key/2, +-export([decode_private_key/1, decode_private_key/2, decode_dhparams/1, decrypt_private/2, decrypt_private/3, encrypt_public/2, encrypt_public/3, decrypt_public/2, decrypt_public/3, - encrypt_private/2, encrypt_private/3, - sign/2, sign/3, + encrypt_private/2, encrypt_private/3, gen_key/1, sign/2, sign/3, verify_signature/3, verify_signature/4, verify_signature/5, - pem_to_der/1, pem_to_der/2, + pem_to_der/1, pem_to_der/2, der_to_pem/2, pkix_decode_cert/2, pkix_encode_cert/1, pkix_transform/2, pkix_is_self_signed/1, pkix_is_fixed_dh_cert/1, pkix_issuer_id/2, @@ -62,6 +61,21 @@ decode_private_key(KeyInfo = {dsa_private_key, _, _}, Password) -> DerEncoded = pubkey_pem:decode_key(KeyInfo, Password), 'OTP-PUB-KEY':decode('DSAPrivateKey', DerEncoded). + +%%-------------------------------------------------------------------- +%% Function: decode_dhparams(DhParamInfo) -> +%% {ok, DhParams} | {error, Reason} +%% +%% DhParamsInfo = {Type, der_bin(), ChipherInfo} - as returned from +%% pem_to_der/[1,2] for DH parameters. +%% Type = dh_params +%% ChipherInfo = opaque() | no_encryption +%% +%% Description: Decodes an asn1 der encoded DH parameters. +%%-------------------------------------------------------------------- +decode_dhparams({dh_params, DerEncoded, not_encrypted}) -> + 'OTP-PUB-KEY':decode('DHParameter', DerEncoded). + %%-------------------------------------------------------------------- %% Function: decrypt_private(CipherText, Key) -> %% decrypt_private(CipherText, Key, Options) -> PlainTex @@ -108,6 +122,18 @@ encrypt_private(PlainText, Key, Options) -> Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_oaep_padding), pubkey_crypto:encrypt_private(PlainText, Key, Padding). +%%-------------------------------------------------------------------- +%% Function: gen_key(Params) -> Keys +%% +%% Params = #'DomainParameters'{} - Currently only supported option +%% Keys = {PublicDHKey = integer(), PrivateDHKey = integer()} +%% +%% Description: Generates keys. Currently supports Diffie-Hellman keys. +%%-------------------------------------------------------------------- +gen_key(#'DHParameter'{prime = P, base = G}) when is_integer(P), + is_integer(G) -> + pubkey_crypto:gen_key(diffie_hellman, [P, G]). + %%-------------------------------------------------------------------- %% Function: pem_to_der(CertSource) -> %% pem_to_der(CertSource, Password) -> {ok, [Entry]} | @@ -116,7 +142,6 @@ encrypt_private(PlainText, Key, Options) -> %% CertSource = File | CertData %% CertData = binary() %% File = path() -%% Password = string() %% Entry = {entry_type(), der_bin(), ChipherInfo} %% ChipherInfo = opague() | no_encryption %% der_bin() = binary() @@ -127,7 +152,9 @@ encrypt_private(PlainText, Key, Options) -> %% entries as asn1 der encoded entities. Currently supported entry %% types are certificates, certificate requests, rsa private keys and %% dsa private keys. In the case of a key entry ChipherInfo will be -%% used by decode_private_key/2 if the key is protected by a password. +%% private keys and Diffie Hellam parameters .In the case of a key +%% entry ChipherInfo will be used by decode_private_key/2 if the key +%% is protected by a password. %%-------------------------------------------------------------------- pem_to_der(CertSource) -> pem_to_der(CertSource, no_passwd). @@ -137,6 +164,9 @@ pem_to_der(File, Password) when is_list(File) -> pem_to_der(PemBin, Password) when is_binary(PemBin) -> pubkey_pem:decode(PemBin, Password). +der_to_pem(File, TypeDerList) -> + pubkey_pem:write_file(File, TypeDerList). + %%-------------------------------------------------------------------- %% Function: pkix_decode_cert(BerCert, Type) -> {ok, Cert} | {error, Reason} %% @@ -288,9 +318,10 @@ sign(Msg, #'RSAPrivateKey'{} = Key) when is_binary(Msg) -> sign(Msg, #'DSAPrivateKey'{} = Key) when is_binary(Msg) -> pubkey_crypto:sign(Msg, Key); -sign(#'OTPTBSCertificate'{signature = SigAlg} = TBSCert, Key) -> +sign(#'OTPTBSCertificate'{signature = #'SignatureAlgorithm'{algorithm = Alg} + = SigAlg} = TBSCert, Key) -> Msg = pubkey_cert_records:encode_tbs_cert(TBSCert), - DigestType = pubkey_cert:digest_type(SigAlg), + DigestType = pubkey_cert:digest_type(Alg), Signature = pubkey_crypto:sign(DigestType, Msg, Key), Cert = #'OTPCertificate'{tbsCertificate= TBSCert, signatureAlgorithm = SigAlg, diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk index f4d5281e94..da1465d538 100644 --- a/lib/public_key/vsn.mk +++ b/lib/public_key/vsn.mk @@ -1,6 +1,7 @@ -PUBLIC_KEY_VSN = 0.5 - -TICKETS = OTP-8372 +PUBLIC_KEY_VSN = 0.6 +TICKETS = OTP-7046 \ + OTP-8553 +#TICKETS_o.5 = OTP-8372 #TICKETS_0.4 = OTP-8250 #TICKETS_0.3 = OTP-8100 OTP-8142 #TICKETS_0.2 = OTP-7860 -- cgit v1.2.3