Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:26
erlang
1654-ssl-public_key-Add-possiblity-to-provide-c...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 1654-ssl-public_key-Add-possiblity-to-provide-customize-o.patch of Package erlang
From ac3a3b0e16585e64a206464ef2ba1c99d4cbb8a3 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin <ingela@erlang.org> Date: Mon, 27 Nov 2023 09:27:31 +0100 Subject: [PATCH 4/4] ssl, public_key: Add possiblity to provide customize options to key signing fun --- lib/public_key/doc/src/public_key.xml | 25 +++++++++++++++++++++---- lib/public_key/src/public_key.erl | 5 +++-- lib/ssl/doc/src/ssl.xml | 12 +++++++----- lib/ssl/src/ssl.erl | 4 +++- lib/ssl/src/ssl_handshake.erl | 11 +++++++++-- lib/ssl/test/ssl_api_SUITE.erl | 20 +++++++++++++++++++- lib/ssl/test/ssl_cert_tests.erl | 16 ++++++++-------- 7 files changed, 70 insertions(+), 23 deletions(-) diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index 5fc2420fab..bb1c5c4630 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -145,6 +145,14 @@ </desc> </datatype> + <datatype> + <name name="custom_key_opts"/> + <desc> + <p>Can be provided together with a custom private key, that specifies a key fun, + to provide additional options understood by the fun.</p> + </desc> + </datatype> + <datatype> <name name="ed_oid_name"/> <desc> @@ -390,9 +398,14 @@ <name name="encrypt_private" arity="3" since="OTP 21.1"/> <fsummary>Public-key encryption using the private key.</fsummary> <desc> - <p>Public-key encryption using the private key. - See also <seemfa - marker="crypto:crypto#private_encrypt/4">crypto:private_encrypt/4</seemfa>.</p> + <p>Public-key encryption using the private key. See also <seemfa + marker="crypto:crypto#private_encrypt/4">crypto:private_encrypt/4</seemfa>. + The key, can besides a standard RSA key, be a map specifing the + key algorithm <c>rsa</c> and a fun to handle the encryption + operation. This may be used for customized the encryption + operation with for instance hardware security modules (HSM) or + trusted platform modules (TPM). + </p> </desc> </func> @@ -1006,7 +1019,11 @@ end <p>Creates a digital signature.</p> <p>The <c>Msg</c> is either the binary "plain text" data to be signed or it is the hashed value of "plain text", that is, the - digest.</p> + digest. The key, can besides a standard key, be a map specifing + a key algorithm and a fun that should handle the signing. This may + be used for customized signing with for instance hardware security + modules (HSM) or trusted platform modules (TPM). + </p> </desc> </func> diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index 99f12f3a95..2cd045bd24 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -124,6 +124,7 @@ ed_private_key() | #{algorithm := eddsa | rsa_pss_pss | ecdsa | rsa | dsa, sign_fun => fun()} . +-type custom_key_opts() :: [term()]. -type rsa_public_key() :: #'RSAPublicKey'{}. -type rsa_private_key() :: #'RSAPrivateKey'{} | #{algorithm := rsa, encrypt_fun => fun()}. @@ -646,7 +647,7 @@ encrypt_private(PlainText, Key) -> CipherText when PlainText :: binary(), Key :: rsa_private_key(), - Options :: crypto:pk_encrypt_decrypt_opts(), + Options :: crypto:pk_encrypt_decrypt_opts() | custom_key_opts(), CipherText :: binary() . encrypt_private(PlainText, Key, Options) when is_binary(PlainText), @@ -842,7 +843,7 @@ sign(DigestOrPlainText, DigestType, Key) -> Signature when Msg :: binary() | {digest,binary()}, DigestType :: digest_type(), Key :: private_key(), - Options :: crypto:pk_sign_verify_opts(), + Options :: crypto:pk_sign_verify_opts() | custom_key_opts(), Signature :: binary() . sign(Digest, none, Key = #'DSAPrivateKey'{}, Options) when is_binary(Digest) -> %% Backwards compatible diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index 1ae7d924e6..403872dff0 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -344,11 +344,13 @@ <name name="key"/> <desc> - <p>The user's private key. The map formats referring to a - crypto engine/provider (with key reference information) or Erlang fun, - can both be used for customized signing with - for instance hardware security modules (HSM) or trusted - platform modules (TPM). </p> + <p>The user's private key. Either the key can be provided + directly as DER encoded entity, or indirectly using a crypto + engine/provider (with key reference information) or an Erlang + fun (with possible custom options). The latter two options + can both be used for customized signing with for instance + hardware security modules (HSM) or trusted platform modules + (TPM). </p> <list> <item><p>A DER encoded key will need to specify the ASN-1 type used to diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 5a137c0566..0e42e95d56 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -357,7 +357,9 @@ password => crypto:password()} | #{algorithm := sign_algo(), sign_fun := fun(), - encrypt_fun => fun() %% Only TLS-1.0, TLS-1.1 and rsa-key + sign_opts => list(), + encrypt_fun => fun(), %% Only TLS-1.0, TLS-1.1 and rsa-key + encrypt_opts => list() }. % exported -type key_pem() :: file:filename(). -type key_pem_password() :: iodata() | fun(() -> iodata()). diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index c59d97b882..473a7b5ddf 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -2151,9 +2151,11 @@ do_digitally_signed(Version, {digest, Digest}, _HashAlgo, #'RSAPrivateKey'{} = K when ?TLS_LTE(Version, ?TLS_1_1) -> public_key:encrypt_private(Digest, Key, [{rsa_pad, rsa_pkcs1_padding}]); -do_digitally_signed(Version, {digest, Digest}, _HashAlgo, #{algorithm := rsa, encrypt_fun := _} = Key, rsa) +do_digitally_signed(Version, {digest, Digest}, _HashAlgo, #{algorithm := rsa, encrypt_fun := Fun} = Key0, rsa) when ?TLS_LTE(Version, ?TLS_1_1) -> - public_key:encrypt_private(Digest, Key, [{rsa_pad, rsa_pkcs1_padding}]); + CustomOpts = maps:get(encrypt_opts, Key0, []), + Key = #{algorithm => rsa, encrypt_fun => Fun}, + public_key:encrypt_private(Digest, Key, CustomOpts ++ [{rsa_pad, rsa_pkcs1_padding}]); do_digitally_signed(Version, {digest, Digest}, _, #{algorithm := rsa, engine := _} = Engine, rsa) when ?TLS_LTE(Version, ?TLS_1_1) -> crypto:private_encrypt(rsa, Digest, maps:remove(algorithm, Engine), @@ -2163,6 +2165,11 @@ do_digitally_signed(_, Msg, HashAlgo, #{algorithm := Alg, engine := _} = Engine, crypto:sign(Alg, HashAlgo, Msg, maps:remove(algorithm, Engine), Options); do_digitally_signed(Version, {digest, _} = Msg , HashAlgo, Key, _) when ?TLS_LTE(Version,?TLS_1_1) -> public_key:sign(Msg, HashAlgo, Key); +do_digitally_signed(_, Msg, HashAlgo, #{algorithm := SignAlgo, sign_fun := Fun} = Key0, SignAlgo) -> + CustomOpts = maps:get(sign_opts, Key0, []), + Options = signature_options(SignAlgo, HashAlgo), + Key = #{algorithm => SignAlgo, sign_fun => Fun}, + public_key:sign(Msg, HashAlgo, Key, CustomOpts ++ Options); do_digitally_signed(_, Msg, HashAlgo, Key, SignAlgo) -> Options = signature_options(SignAlgo, HashAlgo), public_key:sign(Msg, HashAlgo, Key, Options). diff --git a/lib/ssl/test/ssl_api_SUITE.erl b/lib/ssl/test/ssl_api_SUITE.erl index aa93a021a0..b33a072db6 100644 --- a/lib/ssl/test/ssl_api_SUITE.erl +++ b/lib/ssl/test/ssl_api_SUITE.erl @@ -2503,7 +2503,17 @@ options_cert(Config) -> %% cert[file] cert_keys keys password [{key, {rsa, <<>>}}], client, Old), ?OK(#{certs_keys := [#{key := #{}}]}, [{key, #{engine => foo, algorithm => foo, key_id => foo}}], client, Old), - + ?OK(#{certs_keys := [#{key := #{}}]}, + [{key, #{algorithm => eddsa, sign_fun => fun(_,_,_,_) -> << "dummy signature">> end}}, + {versions, ['tlsv1.3']}], client, Old), + ?OK(#{certs_keys := [#{key := #{}}]}, + [{key, #{algorithm => ecdsa, sign_fun => fun(_,_,_,_) -> << "dummy signature">> end}}], + client, Old), + ?OK(#{certs_keys := [#{key := #{}}]}, + [{key, #{algorithm => rsa, + sign_fun => fun(_,_,_,_) -> << "dummy signature">> end, + encrypt_fun => fun(_,_,_) -> << "dummy encrypt">> end}}, + {versions, ['tlsv1.3', 'tlsv1.2', 'tlsv1.1']}], client, Old), ?OK(#{certs_keys := [#{password := _}]}, [{password, "foobar"}], client, Old), ?OK(#{certs_keys := [#{password := _}]}, [{password, <<"foobar">>}], client, Old), Pwd = fun() -> "foobar" end, @@ -2517,6 +2527,14 @@ options_cert(Config) -> %% cert[file] cert_keys keys password client, Old), %% Errors + ?ERR({options,incompatible,[key,{versions,['tlsv1.2']}]}, + [{key, #{algorithm => eddsa, sign_fun => fun(_,_,_,_) -> << "dummy signature">> end}}, + {versions, ['tlsv1.2']}], client), + ?ERR({options,incompatible,[key,{versions,['tlsv1.3','tlsv1.2']}]}, + [{key, #{algorithm => rsa, + sign_fun => fun(_,_,_,_) -> << "dummy signature">> end, + encrypt_fun => fun(_,_,_) -> << "dummy encrypt">> end + }}], client), ?ERR({cert, #{}}, [{cert, #{}}], client), ?ERR({certfile, cert}, [{certfile, cert}], client), ?ERR({certs_keys, #{}}, [{certs_keys, #{}}], client), diff --git a/lib/ssl/test/ssl_cert_tests.erl b/lib/ssl/test/ssl_cert_tests.erl index d8795138ae..d2e5e76e27 100644 --- a/lib/ssl/test/ssl_cert_tests.erl +++ b/lib/ssl/test/ssl_cert_tests.erl @@ -89,28 +89,28 @@ auth() -> auth(Config) -> Version = proplists:get_value(version,Config), + CommonClientOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)], ClientOpts = case Version of 'tlsv1.3' -> - [{verify, verify_peer}, - {certificate_authorities, true} | - ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)]; + [{certificate_authorities, true} | CommonClientOpts]; _ -> - [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)] + CommonClientOpts end, ServerOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config)], ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config). + %%-------------------------------------------------------------------- client_auth_custom_key() -> [{doc,"Test that client and server can connect using their own signature function"}]. client_auth_custom_key(Config) when is_list(Config) -> Version = proplists:get_value(version,Config), + CommonClientOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)], ClientOpts0 = case Version of 'tlsv1.3' -> - [{verify, verify_peer}, - {certificate_authorities, true} | - ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)]; - _ ->[{verify, verify_peer} | ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)] + [{certificate_authorities, true} | CommonClientOpts]; + _ -> + CommonClientOpts end, ClientKeyFilePath = proplists:get_value(keyfile, ClientOpts0), [ClientKeyEntry] = ssl_test_lib:pem_to_der(ClientKeyFilePath), -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor