diff options
Diffstat (limited to 'lib/public_key/src')
-rw-r--r-- | lib/public_key/src/pubkey_cert.erl | 152 | ||||
-rw-r--r-- | lib/public_key/src/pubkey_pbe.erl | 3 | ||||
-rw-r--r-- | lib/public_key/src/pubkey_ssh.erl | 138 | ||||
-rw-r--r-- | lib/public_key/src/public_key.erl | 56 |
4 files changed, 197 insertions, 152 deletions
diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl index 76fd0f8133..c433a96585 100644 --- a/lib/public_key/src/pubkey_cert.erl +++ b/lib/public_key/src/pubkey_cert.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2016. All Rights Reserved. +%% Copyright Ericsson AB 2008-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -33,11 +33,12 @@ is_fixed_dh_cert/1, verify_data/1, verify_fun/4, select_extension/2, match_name/3, extensions_list/1, cert_auth_key_id/1, time_str_2_gregorian_sec/1, - gen_test_certs/1]). + gen_test_certs/1, root_cert/2]). -define(NULL, 0). --export_type([chain_opts/0, test_config/0]). +-export_type([cert_opt/0, chain_opts/0, conf_opt/0, + test_config/0, test_root_cert/0]). -type cert_opt() :: {digest, public_key:digest_type()} | {key, public_key:key_params() | public_key:private_key()} | @@ -46,9 +47,12 @@ -type chain_end() :: root | peer. -type chain_opts() :: #{chain_end() := [cert_opt()], intermediates => [[cert_opt()]]}. -type conf_opt() :: {cert, public_key:der_encoded()} | - {key, public_key:der_encoded()} | + {key, public_key:private_key()} | {cacerts, [public_key:der_encoded()]}. --type test_config() :: #{server_config := [conf_opt()], client_config := [conf_opt()]}. +-type test_config() :: + #{server_config := [conf_opt()], client_config := [conf_opt()]}. +-type test_root_cert() :: + #{cert := binary(), key := public_key:private_key()}. %%==================================================================== %% Internal application APIu %%==================================================================== @@ -430,31 +434,94 @@ match_name(Fun, Name, PermittedName, [Head | Tail]) -> false -> match_name(Fun, Name, Head, Tail) end. + %%% --spec gen_test_certs(#{server_chain:= chain_opts(), client_chain:= chain_opts()}) -> test_config(). - -%% Generates server and and client configuration for testing +-spec gen_test_certs(#{server_chain:= chain_opts(), + client_chain:= chain_opts()} | + chain_opts()) -> + test_config() | + [conf_opt()]. +%% +%% Generates server and and client configuration for testing %% purposes. All certificate options have default values -gen_test_certs(#{client_chain := #{root := ClientRootConf, - intermediates := ClientCAs, - peer := ClientPeer}, - server_chain := - #{root := ServerRootConf, - intermediates := ServerCAs, - peer := ServerPeer}}) -> - SRootKey = gen_key(proplists:get_value(key, ServerRootConf, default_key_gen())), - CRootKey = gen_key(proplists:get_value(key, ClientRootConf, default_key_gen())), - ServerRoot = root_cert("server", SRootKey, ClientRootConf), - ClientRoot = root_cert("client", CRootKey, ServerRootConf), - - [{ServerDERCert, ServerDERKey} | ServerCAsKeys] = config(server, ServerRoot, - SRootKey, lists:reverse([ServerPeer | lists:reverse(ServerCAs)])), - [{ClientDERCert, ClientDERKey} | ClientCAsKeys] = config(client, ClientRoot, - CRootKey, lists:reverse([ClientPeer | lists:reverse(ClientCAs)])), - ServerDERCA = ca_config(ClientRoot, ServerCAsKeys), - ClientDERCA = ca_config(ServerRoot, ClientCAsKeys), - #{server_config => [{cert, ServerDERCert}, {key, ServerDERKey}, {cacerts, ServerDERCA}], - client_config => [{cert, ClientDERCert}, {key, ClientDERKey}, {cacerts, ClientDERCA}]}. +gen_test_certs( + #{client_chain := + #{root := ClientRoot, + intermediates := ClientCAs, + peer := ClientPeer}, + server_chain := + #{root := ServerRoot, + intermediates := ServerCAs, + peer := ServerPeer}}) -> + #{cert := ServerRootCert, key := ServerRootKey} = + case ServerRoot of + #{} -> + ServerRoot; + ServerRootConf when is_list(ServerRootConf) -> + root_cert("SERVER ROOT CA", ServerRootConf) + end, + #{cert := ClientRootCert, key := ClientRootKey} = + case ClientRoot of + #{} -> + ClientRoot; + ClientRootConf when is_list(ClientRootConf) -> + root_cert("CLIENT ROOT CA", ClientRootConf) + end, + [{ServerDERCert, ServerDERKey} | ServerCAsKeys] = + config( + server, ServerRootCert, ServerRootKey, + lists:reverse([ServerPeer | lists:reverse(ServerCAs)])), + [{ClientDERCert, ClientDERKey} | ClientCAsKeys] = + config( + client, ClientRootCert, ClientRootKey, + lists:reverse([ClientPeer | lists:reverse(ClientCAs)])), + ServerDERCA = ca_config(ClientRootCert, ServerCAsKeys), + ClientDERCA = ca_config(ServerRootCert, ClientCAsKeys), + #{server_config => + [{cert, ServerDERCert}, {key, ServerDERKey}, + {cacerts, ServerDERCA}], + client_config => + [{cert, ClientDERCert}, {key, ClientDERKey}, + {cacerts, ClientDERCA}]}; +%% +%% Generates a node configuration for testing purposes, +%% when using the node server cert also for the client. +%% All certificate options have default values +gen_test_certs( + #{root := Root, intermediates := CAs, peer := Peer}) -> + #{cert := RootCert, key := RootKey} = + case Root of + #{} -> + Root; + RootConf when is_list(RootConf) -> + root_cert("SERVER ROOT CA", RootConf) + end, + [{DERCert, DERKey} | CAsKeys] = + config( + server, RootCert, RootKey, + lists:reverse([Peer | lists:reverse(CAs)])), + DERCAs = ca_config(RootCert, CAsKeys), + [{cert, DERCert}, {key, DERKey}, {cacerts, DERCAs}]. + +%%% +-spec root_cert(string(), [cert_opt()]) -> test_root_cert(). +%% +%% Generate a self-signed root cert +root_cert(Name, Opts) -> + PrivKey = gen_key(proplists:get_value(key, Opts, default_key_gen())), + TBS = cert_template(), + Issuer = subject("root", Name), + OTPTBS = + TBS#'OTPTBSCertificate'{ + signature = sign_algorithm(PrivKey, Opts), + issuer = Issuer, + validity = validity(Opts), + subject = Issuer, + subjectPublicKeyInfo = public_key(PrivKey), + extensions = extensions(undefined, ca, Opts) + }, + #{cert => public_key:pkix_sign(OTPTBS, PrivKey), + key => PrivKey}. %%-------------------------------------------------------------------- %%% Internal functions @@ -1103,7 +1170,7 @@ missing_basic_constraints(OtpCert, SelfSigned, ValidationState, VerifyFun, UserS UserState} end. - gen_key(KeyGen) -> +gen_key(KeyGen) -> case is_key(KeyGen) of true -> KeyGen; @@ -1120,28 +1187,14 @@ is_key(#'ECPrivateKey'{}) -> is_key(_) -> false. -root_cert(Role, PrivKey, Opts) -> - TBS = cert_template(), - Issuer = issuer("root", Role, " ROOT CA"), - OTPTBS = TBS#'OTPTBSCertificate'{ - signature = sign_algorithm(PrivKey, Opts), - issuer = Issuer, - validity = validity(Opts), - subject = Issuer, - subjectPublicKeyInfo = public_key(PrivKey), - extensions = extensions(Role, ca, Opts) - }, - public_key:pkix_sign(OTPTBS, PrivKey). cert_template() -> #'OTPTBSCertificate'{ version = v3, - serialNumber = trunc(rand:uniform()*100000000)*10000 + 1, + serialNumber = erlang:unique_integer([positive, monotonic]), issuerUniqueID = asn1_NOVALUE, subjectUniqueID = asn1_NOVALUE }. -issuer(Contact, Role, Name) -> - subject(Contact, Role ++ Name). subject(Contact, Name) -> Opts = [{email, Contact ++ "@example.org"}, @@ -1176,9 +1229,11 @@ validity(Opts) -> DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1), DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7), {DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}), - Format = fun({Y,M,D}) -> - lists:flatten(io_lib:format("~w~2..0w~2..0w000000Z",[Y,M,D])) - end, + Format = + fun({Y,M,D}) -> + lists:flatten( + io_lib:format("~4..0w~2..0w~2..0w000000Z",[Y,M,D])) + end, #'Validity'{notBefore={generalTime, Format(DefFrom)}, notAfter ={generalTime, Format(DefTo)}}. @@ -1240,7 +1295,6 @@ cert(Role, #'OTPCertificate'{tbsCertificate = #'OTPTBSCertificate'{subject = Iss subject = subject(Contact, atom_to_list(Role) ++ Name), subjectPublicKeyInfo = public_key(Key), extensions = extensions(Role, Type, Opts) - }, public_key:pkix_sign(OTPTBS, PrivKey). @@ -1297,7 +1351,7 @@ add_default_extensions(server, peer, Exts) -> ], add_default_extensions(Default, Exts); -add_default_extensions(_, peer, Exts) -> +add_default_extensions(client, peer, Exts) -> Exts. add_default_extensions(Defaults0, Exts) -> diff --git a/lib/public_key/src/pubkey_pbe.erl b/lib/public_key/src/pubkey_pbe.erl index 0243bcaa82..e89e16f120 100644 --- a/lib/public_key/src/pubkey_pbe.erl +++ b/lib/public_key/src/pubkey_pbe.erl @@ -222,7 +222,8 @@ pbe_pad(Data, {#'PBEParameter'{}, _}) -> pbe_pad(Data, #'PBES2-params'{}) -> pbe_pad(Data); pbe_pad(Data, _) -> - Data. +pbe_pad(Data).%% Data. + pbe_pad(Data) -> N = 8 - (erlang:byte_size(Data) rem 8), diff --git a/lib/public_key/src/pubkey_ssh.erl b/lib/public_key/src/pubkey_ssh.erl index 75c1880655..a7d018e440 100644 --- a/lib/public_key/src/pubkey_ssh.erl +++ b/lib/public_key/src/pubkey_ssh.erl @@ -29,7 +29,15 @@ ]). -define(UINT32(X), X:32/unsigned-big-integer). --define(STRING(X), ?UINT32((size(X))), (X)/binary). +-define(STRING(X), ?UINT32((byte_size(X))), (X)/binary). + +-define(DEC_BIN(X,Len), ?UINT32(Len), X:Len/binary ). +-define(DEC_MPINT(I,Len), ?DEC_INT(I,Len) ). +-define(DEC_INT(I,Len), ?UINT32(Len), I:Len/big-signed-integer-unit:8 ). + +-define(Empint(X), (mpint(X))/binary ). +-define(Estring(X), (string(X))/binary ). + %% Max encoded line length is 72, but conformance examples use 68 %% Comment from rfc 4716: "The following are some examples of public @@ -47,12 +55,12 @@ %% Description: Decodes a ssh file-binary. %%-------------------------------------------------------------------- decode(Bin, public_key)-> - case binary:match(Bin, begin_marker()) of - nomatch -> - openssh_decode(Bin, openssh_public_key); - _ -> - rfc4716_decode(Bin) - end; + PKtype = + case binary:match(Bin, begin_marker()) of + nomatch -> openssh_public_key; + _ -> rfc4716_public_key + end, + decode(Bin, PKtype); decode(Bin, rfc4716_public_key) -> rfc4716_decode(Bin); decode(Bin, ssh2_pubkey) -> @@ -164,26 +172,8 @@ join_entry([Line | Lines], Entry) -> join_entry(Lines, [Line | Entry]). -rfc4716_pubkey_decode(<<?UINT32(Len), Type:Len/binary, - ?UINT32(SizeE), E:SizeE/binary, - ?UINT32(SizeN), N:SizeN/binary>>) when Type == <<"ssh-rsa">> -> - #'RSAPublicKey'{modulus = erlint(SizeN, N), - publicExponent = erlint(SizeE, E)}; - -rfc4716_pubkey_decode(<<?UINT32(Len), Type:Len/binary, - ?UINT32(SizeP), P:SizeP/binary, - ?UINT32(SizeQ), Q:SizeQ/binary, - ?UINT32(SizeG), G:SizeG/binary, - ?UINT32(SizeY), Y:SizeY/binary>>) when Type == <<"ssh-dss">> -> - {erlint(SizeY, Y), - #'Dss-Parms'{p = erlint(SizeP, P), - q = erlint(SizeQ, Q), - g = erlint(SizeG, G)}}; -rfc4716_pubkey_decode(<<?UINT32(Len), ECDSA_SHA2_etc:Len/binary, - ?UINT32(SizeId), Id:SizeId/binary, - ?UINT32(SizeQ), Q:SizeQ/binary>>) -> - <<"ecdsa-sha2-", Id/binary>> = ECDSA_SHA2_etc, - {#'ECPoint'{point = Q}, {namedCurve,public_key:ssh_curvename2oid(Id)}}. +rfc4716_pubkey_decode(BinKey) -> ssh2_pubkey_decode(BinKey). + openssh_decode(Bin, FileType) -> Lines = binary:split(Bin, <<"\n">>, [global]), @@ -267,18 +257,14 @@ decode_comment(Comment) -> openssh_pubkey_decode(Type, Base64Enc) -> try - ssh2_pubkey_decode(Type, base64:mime_decode(Base64Enc)) + <<?DEC_BIN(Type,_TL), Bin/binary>> = base64:mime_decode(Base64Enc), + ssh2_pubkey_decode(Type, Bin) catch _:_ -> {Type, base64:mime_decode(Base64Enc)} end. -erlint(MPIntSize, MPIntValue) -> - Bits= MPIntSize * 8, - <<Integer:Bits/integer>> = MPIntValue, - Integer. - ssh1_rsa_pubkey_decode(MBin, EBin) -> #'RSAPublicKey'{modulus = integer_decode(MBin), publicExponent = integer_decode(EBin)}. @@ -411,71 +397,37 @@ comma_list_encode([Option | Rest], Acc) -> ssh2_pubkey_encode(#'RSAPublicKey'{modulus = N, publicExponent = E}) -> - ssh2_pubkey_encode({#'RSAPublicKey'{modulus = N, publicExponent = E}, 'ssh-rsa'}); - -ssh2_pubkey_encode({Key, 'rsa-sha2-256'}) -> ssh2_pubkey_encode({Key, 'ssh-rsa'}); -ssh2_pubkey_encode({Key, 'rsa-sha2-512'}) -> ssh2_pubkey_encode({Key, 'ssh-rsa'}); -ssh2_pubkey_encode({#'RSAPublicKey'{modulus = N, publicExponent = E}, SignAlg}) -> - SignAlgName = list_to_binary(atom_to_list(SignAlg)), - StrLen = size(SignAlgName), - EBin = mpint(E), - NBin = mpint(N), - <<?UINT32(StrLen), SignAlgName:StrLen/binary, - EBin/binary, - NBin/binary>>; -ssh2_pubkey_encode({{_,#'Dss-Parms'{}}=Key, _}) -> - ssh2_pubkey_encode(Key); + <<?STRING(<<"ssh-rsa">>), ?Empint(E), ?Empint(N)>>; ssh2_pubkey_encode({Y, #'Dss-Parms'{p = P, q = Q, g = G}}) -> - TypeStr = <<"ssh-dss">>, - StrLen = size(TypeStr), - PBin = mpint(P), - QBin = mpint(Q), - GBin = mpint(G), - YBin = mpint(Y), - <<?UINT32(StrLen), TypeStr:StrLen/binary, - PBin/binary, - QBin/binary, - GBin/binary, - YBin/binary>>; -ssh2_pubkey_encode({{#'ECPoint'{},_}=Key, _}) -> - ssh2_pubkey_encode(Key); + <<?STRING(<<"ssh-dss">>), ?Empint(P), ?Empint(Q), ?Empint(G), ?Empint(Y)>>; ssh2_pubkey_encode(Key={#'ECPoint'{point = Q}, {namedCurve,OID}}) -> - TypeStr = key_type(Key), - StrLen = size(TypeStr), - IdB = public_key:oid2ssh_curvename(OID), - <<?UINT32(StrLen), TypeStr:StrLen/binary, - (string(IdB))/binary, - (string(Q))/binary>>. + Curve = public_key:oid2ssh_curvename(OID), + <<?STRING(key_type(Key)), ?Estring(Curve), ?Estring(Q)>>. -ssh2_pubkey_decode(Bin = <<?UINT32(Len), Type:Len/binary, _/binary>>) -> +ssh2_pubkey_decode(<<?DEC_BIN(Type,_TL), Bin/binary>>) -> ssh2_pubkey_decode(Type, Bin). -ssh2_pubkey_decode(<<"rsa-sha2-256">>, Bin) -> ssh2_pubkey_decode(<<"ssh-rsa">>, Bin); -ssh2_pubkey_decode(<<"rsa-sha2-512">>, Bin) -> ssh2_pubkey_decode(<<"ssh-rsa">>, Bin); +%% ssh2_pubkey_decode(<<"rsa-sha2-256">>, Bin) -> ssh2_pubkey_decode(<<"ssh-rsa">>, Bin); +%% ssh2_pubkey_decode(<<"rsa-sha2-512">>, Bin) -> ssh2_pubkey_decode(<<"ssh-rsa">>, Bin); ssh2_pubkey_decode(<<"ssh-rsa">>, - <<?UINT32(Len), _:Len/binary, - ?UINT32(SizeE), E:SizeE/binary, - ?UINT32(SizeN), N:SizeN/binary>>) -> - #'RSAPublicKey'{modulus = erlint(SizeN, N), - publicExponent = erlint(SizeE, E)}; + <<?DEC_INT(E, _EL), + ?DEC_INT(N, _NL)>>) -> + #'RSAPublicKey'{modulus = N, + publicExponent = E}; ssh2_pubkey_decode(<<"ssh-dss">>, - <<?UINT32(Len), _:Len/binary, - ?UINT32(SizeP), P:SizeP/binary, - ?UINT32(SizeQ), Q:SizeQ/binary, - ?UINT32(SizeG), G:SizeG/binary, - ?UINT32(SizeY), Y:SizeY/binary>>) -> - {erlint(SizeY, Y), - #'Dss-Parms'{p = erlint(SizeP, P), - q = erlint(SizeQ, Q), - g = erlint(SizeG, G)}}; + <<?DEC_INT(P, _PL), + ?DEC_INT(Q, _QL), + ?DEC_INT(G, _GL), + ?DEC_INT(Y, _YL)>>) -> + {Y, #'Dss-Parms'{p = P, + q = Q, + g = G}}; ssh2_pubkey_decode(<<"ecdsa-sha2-",Id/binary>>, - <<?UINT32(Len), ECDSA_SHA2_etc:Len/binary, - ?UINT32(SizeId), Id:SizeId/binary, - ?UINT32(SizeQ), Q:SizeQ/binary>>) -> - <<"ecdsa-sha2-", Id/binary>> = ECDSA_SHA2_etc, + <<?DEC_BIN(Id, _IL), + ?DEC_BIN(Q, _QL)>>) -> {#'ECPoint'{point = Q}, {namedCurve,public_key:ssh_curvename2oid(Id)}}. @@ -575,17 +527,16 @@ mpint(X) -> mpint_pos(X). mpint_neg(X) -> Bin = int_to_bin_neg(X, []), - Sz = byte_size(Bin), - <<?UINT32(Sz), Bin/binary>>. + <<?STRING(Bin)>>. mpint_pos(X) -> Bin = int_to_bin_pos(X, []), <<MSB,_/binary>> = Bin, - Sz = byte_size(Bin), if MSB band 16#80 == 16#80 -> - <<?UINT32((Sz+1)), 0, Bin/binary>>; + B = << 0, Bin/binary>>, + <<?STRING(B)>>; true -> - <<?UINT32(Sz), Bin/binary>> + <<?STRING(Bin)>> end. int_to_bin_pos(0,Ds=[_|_]) -> @@ -602,7 +553,8 @@ int_to_bin_neg(X,Ds) -> string(X) when is_binary(X) -> << ?STRING(X) >>; string(X) -> - << ?STRING(list_to_binary(X)) >>. + B = list_to_binary(X), + << ?STRING(B) >>. is_ssh_curvename(Id) -> try public_key:ssh_curvename2oid(Id) of _ -> true catch _:_ -> false diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index 31cb1fff3c..034126655c 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -59,7 +59,8 @@ pkix_crl_verify/2, pkix_crl_issuer/1, short_name_hash/1, - pkix_test_data/1 + pkix_test_data/1, + pkix_test_root_cert/2 ]). -export_type([public_key/0, private_key/0, pem_entry/0, @@ -942,7 +943,6 @@ ssh_decode(SshBin, Type) when is_binary(SshBin), %%-------------------------------------------------------------------- -spec ssh_encode([{public_key(), Attributes::list()}], ssh_file()) -> binary() ; (public_key(), ssh2_pubkey) -> binary() - ; ({public_key(),atom()}, ssh2_pubkey) -> binary() . %% %% Description: Encodes a list of ssh file entries (public keys and @@ -1034,10 +1034,12 @@ short_name_hash({rdnSequence, _Attributes} = Name) -> %%-------------------------------------------------------------------- --spec pkix_test_data(#{chain_type() := pubkey_cert:chain_opts()}) -> - pubkey_cert:test_config(). +-spec pkix_test_data(#{chain_type() := pubkey_cert:chain_opts()} | + pubkey_cert:chain_opts()) -> + pubkey_cert:test_config() | + [pubkey_cert:conf_opt()]. -%% Description: Generates OpenSSL-style hash of a name. +%% Description: Generates cert(s) and ssl configuration %%-------------------------------------------------------------------- pkix_test_data(#{client_chain := ClientChain0, @@ -1046,7 +1048,21 @@ pkix_test_data(#{client_chain := ClientChain0, ClientChain = maps:merge(Default, ClientChain0), ServerChain = maps:merge(Default, ServerChain0), pubkey_cert:gen_test_certs(#{client_chain => ClientChain, - server_chain => ServerChain}). + server_chain => ServerChain}); +pkix_test_data(#{} = Chain) -> + Default = #{intermediates => []}, + pubkey_cert:gen_test_certs(maps:merge(Default, Chain)). + +%%-------------------------------------------------------------------- +-spec pkix_test_root_cert( + Name :: string(), Opts :: [pubkey_cert:cert_opt()]) -> + pubkey_cert:test_root_cert(). + +%% Description: Generates a root cert suitable for pkix_test_data/1 +%%-------------------------------------------------------------------- + +pkix_test_root_cert(Name, Opts) -> + pubkey_cert:root_cert(Name, Opts). %%-------------------------------------------------------------------- %%% Internal functions @@ -1324,9 +1340,9 @@ ec_normalize_params(#'ECParameters'{} = ECParams) -> ec_normalize_params(Other) -> Other. -spec ec_curve_spec(ecpk_parameters_api()) -> term(). -ec_curve_spec( #'ECParameters'{fieldID = FieldId, curve = PCurve, base = Base, order = Order, cofactor = CoFactor }) -> - Field = {pubkey_cert_records:supportedCurvesTypes(FieldId#'FieldID'.fieldType), - FieldId#'FieldID'.parameters}, +ec_curve_spec( #'ECParameters'{fieldID = #'FieldID'{fieldType = Type, + parameters = Params}, curve = PCurve, base = Base, order = Order, cofactor = CoFactor }) -> + Field = format_field(pubkey_cert_records:supportedCurvesTypes(Type), Params), Curve = {PCurve#'Curve'.a, PCurve#'Curve'.b, none}, {Field, Curve, Base, Order, CoFactor}; ec_curve_spec({ecParameters, ECParams}) -> @@ -1336,6 +1352,26 @@ ec_curve_spec({namedCurve, OID}) when is_tuple(OID), is_integer(element(1,OID)) ec_curve_spec({namedCurve, Name}) when is_atom(Name) -> crypto:ec_curve(Name). +format_field(characteristic_two_field = Type, Params0) -> + #'Characteristic-two'{ + m = M, + basis = BasisOid, + parameters = Params} = der_decode('Characteristic-two', Params0), + {Type, M, field_param_decode(BasisOid, Params)}; +format_field(prime_field, Params0) -> + Prime = der_decode('Prime-p', Params0), + {prime_field, Prime}. + +field_param_decode(?'ppBasis', Params) -> + #'Pentanomial'{k1 = K1, k2 = K2, k3 = K3} = + der_decode('Pentanomial', Params), + {ppbasis, K1, K2, K3}; +field_param_decode(?'tpBasis', Params) -> + K = der_decode('Trinomial', Params), + {tpbasis, K}; +field_param_decode(?'gnBasis', _) -> + onbasis. + -spec ec_key({PubKey::term(), PrivateKey::term()}, Params::ecpk_parameters()) -> #'ECPrivateKey'{}. ec_key({PubKey, PrivateKey}, Params) -> #'ECPrivateKey'{version = 1, @@ -1529,6 +1565,8 @@ verify_hostname_match_loop(Refs, Pres, MatchFun, FailCB, Cert) -> Refs). +to_lower_ascii({ip,_}=X) -> X; +to_lower_ascii({iPAddress,_}=X) -> X; to_lower_ascii(S) when is_list(S) -> lists:map(fun to_lower_ascii/1, S); to_lower_ascii({T,S}) -> {T, to_lower_ascii(S)}; to_lower_ascii(C) when $A =< C,C =< $Z -> C + ($a-$A); |