Support in Erlang's SSL library for GRiSP's Secure Element without using OpenSSL crypto engines. Usage: Key = #{algorithm => ecdsa, sign_fun => {my_module, my_sign_fun}}. Then add {key, Key} to the SSL options (server and/or client possible). The sign_fun has arity one and will get the to be signed Message (TLS 1.3) or {digest, Digest} (TLS 1.2), analogous to ssl:sign/3. The intended use here is providing a callback for grisp_cryptoauth:sign/2. While this patch makes heavy use of the existing infrastructure for crypto engines it is completely backwards compatible, e.g. crypto engines still work. diff --git a/lib/ssl/src/ssl_config.erl b/lib/ssl/src/ssl_config.erl index 46578c05a5..c4e11622a6 100644 --- a/lib/ssl/src/ssl_config.erl +++ b/lib/ssl/src/ssl_config.erl @@ -104,6 +104,9 @@ group_pairs([#{private_key := #'DSAPrivateKey'{}} = Pair | Rest], #{dsa := DSA} group_pairs([#{private_key := #{algorithm := dss, engine := _}} = Pair | Rest], Group) -> Pairs = maps:get(dsa, Group), group_pairs(Rest, Group#{dsa => [Pair | Pairs]}); +group_pairs([#{private_key := #{algorithm := Alg, sign_fun := _}} = Pair | Rest], Group) -> + Pairs = maps:get(Alg, Group), + group_pairs(Rest, Group#{Alg => [Pair | Pairs]}); group_pairs([#{private_key := #{algorithm := Alg, engine := _}} = Pair | Rest], Group) -> Pairs = maps:get(Alg, Group), group_pairs(Rest, Group#{Alg => [Pair | Pairs]}). @@ -308,6 +311,9 @@ init_certificates(OwnCerts, _, _, _) when is_binary(OwnCerts)-> init_certificates(OwnCerts, _, _, _) -> {ok, OwnCerts}. +%% HACK: allow callbacks for signing using the GRiSP Secure Element +init_private_key(_, #{algorithm := ecdsa, sign_fun := _SignFun} = Key, _, _, _) -> + Key; init_private_key(_, #{algorithm := Alg} = Key, _, _Password, _Client) when Alg == ecdsa; Alg == rsa; Alg == dss -> diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 56a1ca81b9..8163c7640b 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -2121,6 +2121,12 @@ digitally_signed(Version, Msg, HashAlgo, PrivateKey, SignAlgo) -> throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, bad_key(PrivateKey))) end. +%% HACK: allow callbacks for signing using the GRiSP Secure Element +%% We only care here for sha256 + ecdsa for TLS 1.2 and 1.3 (SSL 3.3 and 3.4) +do_digitally_signed({3, 4}, Msg, sha256, #{algorithm := ecdsa, sign_fun := {Mod, Fun}}, ecdsa) -> + Mod:Fun(Msg); +do_digitally_signed({3, 3}, Hash, sha256, #{algorithm := ecdsa, sign_fun := {Mod, Fun}}, ecdsa) -> + Mod:Fun({digest, Hash}); do_digitally_signed({3, Minor}, Msg, HashAlgo, {#'RSAPrivateKey'{} = Key, #'RSASSA-PSS-params'{}}, SignAlgo) when Minor >= 3 -> Options = signature_options(SignAlgo, HashAlgo),