aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorSverker Eriksson <sverker@erlang.org>2010-06-09 12:01:01 +0000
committerErlang/OTP <otp@erlang.org>2010-06-09 14:19:56 +0200
commit8e7719b8a5ae1d9e2e464d6d1a7abe502e0f9cd3 (patch)
tree800d8c61206b3cd585f78e3110dba994bcd33ccc /lib
parent5cec02b04436ac121d95cec59c98ced8deb477d8 (diff)
downloadotp-8e7719b8a5ae1d9e2e464d6d1a7abe502e0f9cd3.tar.gz
otp-8e7719b8a5ae1d9e2e464d6d1a7abe502e0f9cd3.tar.bz2
otp-8e7719b8a5ae1d9e2e464d6d1a7abe502e0f9cd3.zip
OTP-8700 crypto:dss_sign and dss_verify with pre-hashed digest.
New variants of crypto:dss_sign and crypto:dss_verify with an extra argument to control how the digest is calculated.
Diffstat (limited to 'lib')
-rw-r--r--lib/crypto/c_src/crypto.c44
-rw-r--r--lib/crypto/doc/src/crypto.xml25
-rw-r--r--lib/crypto/src/crypto.app.src12
-rw-r--r--lib/crypto/src/crypto.erl25
-rw-r--r--lib/crypto/test/crypto_SUITE.erl42
5 files changed, 100 insertions, 48 deletions
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index bb639054a6..68079f06c7 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -198,7 +198,7 @@ static ErlNifFunc nif_funcs[] = {
{"rand_bytes", 3, rand_bytes_3},
{"rand_uniform_nif", 2, rand_uniform_nif},
{"mod_exp_nif", 3, mod_exp_nif},
- {"dss_verify", 3, dss_verify},
+ {"dss_verify", 4, dss_verify},
{"rsa_verify", 4, rsa_verify},
{"aes_cbc_crypt", 4, aes_cbc_crypt},
{"exor", 2, exor},
@@ -207,7 +207,7 @@ static ErlNifFunc nif_funcs[] = {
{"rc4_encrypt_with_state", 2, rc4_encrypt_with_state},
{"rc2_40_cbc_crypt", 4, rc2_40_cbc_crypt},
{"rsa_sign_nif", 3, rsa_sign_nif},
- {"dss_sign_nif", 2, dss_sign_nif},
+ {"dss_sign_nif", 3, dss_sign_nif},
{"rsa_public_crypt", 4, rsa_public_crypt},
{"rsa_private_crypt", 4, rsa_private_crypt},
{"dh_generate_parameters_nif", 2, dh_generate_parameters_nif},
@@ -255,6 +255,7 @@ static ERL_NIF_TERM atom_unable_to_check_generator;
static ERL_NIF_TERM atom_not_suitable_generator;
static ERL_NIF_TERM atom_check_failed;
static ERL_NIF_TERM atom_unknown;
+static ERL_NIF_TERM atom_none;
static int is_ok_load_info(ErlNifEnv* env, ERL_NIF_TERM load_info)
@@ -322,6 +323,7 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
atom_not_suitable_generator = enif_make_atom(env,"not_suitable_generator");
atom_check_failed = enif_make_atom(env,"check_failed");
atom_unknown = enif_make_atom(env,"unknown");
+ atom_none = enif_make_atom(env,"none");
*priv_data = NULL;
library_refc++;
@@ -766,7 +768,7 @@ static int inspect_mpint(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifBinary* bin)
}
static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data,Signature,Key=[P, Q, G, Y]) */
+{/* (DigestType,Data,Signature,Key=[P, Q, G, Y]) */
ErlNifBinary data_bin, sign_bin;
BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_y;
unsigned char hmacbuf[SHA_DIGEST_LENGTH];
@@ -774,9 +776,8 @@ static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
DSA *dsa;
int i;
- if (!inspect_mpint(env,argv[0],&data_bin)
- || !inspect_mpint(env,argv[1],&sign_bin)
- || !enif_get_list_cell(env, argv[2], &head, &tail)
+ if (!inspect_mpint(env, argv[2], &sign_bin)
+ || !enif_get_list_cell(env, argv[3], &head, &tail)
|| !get_bn_from_mpint(env, head, &dsa_p)
|| !enif_get_list_cell(env, tail, &head, &tail)
|| !get_bn_from_mpint(env, head, &dsa_q)
@@ -785,10 +786,18 @@ static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
|| !enif_get_list_cell(env, tail, &head, &tail)
|| !get_bn_from_mpint(env, head, &dsa_y)
|| !enif_is_empty_list(env,tail)) {
-
return enif_make_badarg(env);
}
- SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
+ if (argv[0] == atom_sha && inspect_mpint(env, argv[1], &data_bin)) {
+ SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
+ }
+ else if (argv[0] == atom_none && enif_inspect_binary(env, argv[1], &data_bin)
+ && data_bin.size == SHA_DIGEST_LENGTH) {
+ memcpy(hmacbuf, data_bin.data, SHA_DIGEST_LENGTH);
+ }
+ else {
+ return enif_make_badarg(env);
+ }
dsa = DSA_new();
dsa->p = dsa_p;
@@ -1023,7 +1032,7 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data,Key=[P,Q,G,PrivKey]) */
+{/* (DigesType, Data, Key=[P,Q,G,PrivKey]) */
ErlNifBinary data_bin, ret_bin;
ERL_NIF_TERM head, tail;
unsigned char hmacbuf[SHA_DIGEST_LENGTH];
@@ -1032,8 +1041,7 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
int i;
dsa->pub_key = NULL;
- if (!inspect_mpint(env, argv[0], &data_bin)
- || !enif_get_list_cell(env, argv[1], &head, &tail)
+ if (!enif_get_list_cell(env, argv[2], &head, &tail)
|| !get_bn_from_mpint(env, head, &dsa->p)
|| !enif_get_list_cell(env, tail, &head, &tail)
|| !get_bn_from_mpint(env, head, &dsa->q)
@@ -1042,13 +1050,21 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
|| !enif_get_list_cell(env, tail, &head, &tail)
|| !get_bn_from_mpint(env, head, &dsa->priv_key)
|| !enif_is_empty_list(env,tail)) {
-
+ goto badarg;
+ }
+ if (argv[0] == atom_sha && inspect_mpint(env, argv[1], &data_bin)) {
+ SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
+ }
+ else if (argv[0] == atom_none && enif_inspect_binary(env,argv[1],&data_bin)
+ && data_bin.size == SHA_DIGEST_LENGTH) {
+ memcpy(hmacbuf, data_bin.data, SHA_DIGEST_LENGTH);
+ }
+ else {
+ badarg:
DSA_free(dsa);
return enif_make_badarg(env);
}
- SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
-
enif_alloc_binary(DSA_size(dsa), &ret_bin);
i = DSA_sign(NID_sha1, hmacbuf, SHA_DIGEST_LENGTH,
ret_bin.data, &dsa_s_len, dsa);
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 256eab3e3c..e1431cfd81 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -755,39 +755,44 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
<func>
<name>dss_sign(Data, Key) -> Signature</name>
+ <name>dss_sign(DigestType, Data, Key) -> Signature</name>
<fsummary>Sign the data using dsa with given private key.</fsummary>
<type>
- <v>Digest = Mpint</v>
+ <v>DigestType = sha | none (default is sha)</v>
+ <v>Data = Mpint | ShaDigest</v>
<v>Key = [P, Q, G, X]</v>
<v>P, Q, G, X = Mpint</v>
<d> Where <c>P</c>, <c>Q</c> and <c>G</c> are the dss
parameters and <c>X</c> is the private key.</d>
- <v>Mpint = binary()</v>
+ <v>ShaDigest = binary() with length 20 bytes</v>
<v>Signature = binary()</v>
</type>
<desc>
- <p>Calculates the sha digest of the <c>Data</c>
- and creates a DSS signature with the private key <c>Key</c>
- of the digest.</p>
+ <p>Creates a DSS signature with the private key <c>Key</c> of a digest.
+ If <c>DigestType</c> is 'sha', the digest is calculated as SHA1 of <c>Data</c>.
+ If <c>DigestType</c> is 'none', <c>Data</c> is the precalculated SHA1 digest.</p>
</desc>
</func>
<func>
<name>dss_verify(Data, Signature, Key) -> Verified</name>
+ <name>dss_verify(DigestType, Data, Signature, Key) -> Verified</name>
<fsummary>Verify the data and signature using dsa with given public key.</fsummary>
<type>
<v>Verified = boolean()</v>
- <v>Digest, Signature = Mpint</v>
+ <v>DigestType = sha | none</v>
+ <v>Data = Mpint | ShaDigest</v>
+ <v>Signature = Mpint</v>
<v>Key = [P, Q, G, Y]</v>
<v>P, Q, G, Y = Mpint</v>
<d> Where <c>P</c>, <c>Q</c> and <c>G</c> are the dss
parameters and <c>Y</c> is the public key.</d>
- <v>Mpint = binary()</v>
+ <v>ShaDigest = binary() with length 20 bytes</v>
</type>
<desc>
- <p>Calculates the sha digest of the <c>Data</c> and verifies that the
- digest matches the DSS signature using the public key <c>Key</c>.
- </p>
+ <p>Verifies that a digest matches the DSS signature using the public key <c>Key</c>.
+ If <c>DigestType</c> is 'sha', the digest is calculated as SHA1 of <c>Data</c>.
+ If <c>DigestType</c> is 'none', <c>Data</c> is the precalculated SHA1 digest.</p>
</desc>
</func>
diff --git a/lib/crypto/src/crypto.app.src b/lib/crypto/src/crypto.app.src
index a24760a781..5548b6a1b5 100644
--- a/lib/crypto/src/crypto.app.src
+++ b/lib/crypto/src/crypto.app.src
@@ -1,23 +1,23 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1999-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%
%%
{application, crypto,
- [{description, "CRYPTO version 1"},
+ [{description, "CRYPTO version 2"},
{vsn, "%VSN%"},
{modules, [crypto,
crypto_app,
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index a93e336605..39512d27e1 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -40,8 +40,8 @@
-export([exor/2]).
-export([rc4_encrypt/2, rc4_set_key/1, rc4_encrypt_with_state/2]).
-export([rc2_40_cbc_encrypt/3, rc2_40_cbc_decrypt/3]).
--export([dss_verify/3, rsa_verify/3, rsa_verify/4]).
--export([dss_sign/2, rsa_sign/2, rsa_sign/3]).
+-export([dss_verify/3, dss_verify/4, rsa_verify/3, rsa_verify/4]).
+-export([dss_sign/2, dss_sign/3, rsa_sign/2, rsa_sign/3]).
-export([rsa_public_encrypt/3, rsa_private_decrypt/3]).
-export([rsa_private_encrypt/3, rsa_public_decrypt/3]).
-export([dh_generate_key/1, dh_generate_key/2, dh_compute_key/3]).
@@ -82,7 +82,8 @@
aes_cbc_256_encrypt, aes_cbc_256_decrypt,
info_lib]).
--type digest_type() :: 'md5' | 'sha'.
+-type rsa_digest_type() :: 'md5' | 'sha'.
+-type dss_digest_type() :: 'none' | 'sha'.
-type crypto_integer() :: binary() | integer().
-define(nif_stub,nif_stub_error(?LINE)).
@@ -385,12 +386,15 @@ mod_exp_nif(_Base,_Exp,_Mod) -> ?nif_stub.
%% DSS, RSA - verify
%%
-spec dss_verify(binary(), binary(), [binary()]) -> boolean().
+-spec dss_verify(dss_digest_type(), binary(), binary(), [binary()]) -> boolean().
-spec rsa_verify(binary(), binary(), [binary()]) -> boolean().
--spec rsa_verify(digest_type(), binary(), binary(), [binary()]) ->
+-spec rsa_verify(rsa_digest_type(), binary(), binary(), [binary()]) ->
boolean().
%% Key = [P,Q,G,Y] P,Q,G=DSSParams Y=PublicKey
-dss_verify(_Data,_Signature,_Key) -> ?nif_stub.
+dss_verify(Data,Signature,Key) ->
+ dss_verify(sha, Data, Signature, Key).
+dss_verify(_Type,_Data,_Signature,_Key) -> ?nif_stub.
% Key = [E,N] E=PublicExponent N=PublicModulus
rsa_verify(Data,Signature,Key) ->
@@ -403,16 +407,19 @@ rsa_verify(_Type,_Data,_Signature,_Key) -> ?nif_stub.
%%
%% Key = [P,Q,G,X] P,Q,G=DSSParams X=PrivateKey
-spec dss_sign(binary(), [binary()]) -> binary().
+-spec dss_sign(dss_digest_type(), binary(), [binary()]) -> binary().
-spec rsa_sign(binary(), [binary()]) -> binary().
--spec rsa_sign(digest_type(), binary(), [binary()]) -> binary().
+-spec rsa_sign(rsa_digest_type(), binary(), [binary()]) -> binary().
-dss_sign(Data, Key) ->
- case dss_sign_nif(Data,Key) of
+dss_sign(Data,Key) ->
+ dss_sign(sha,Data,Key).
+dss_sign(Type, Data, Key) ->
+ case dss_sign_nif(Type,Data,Key) of
error -> erlang:error(badkey, [Data, Key]);
Sign -> Sign
end.
-dss_sign_nif(_Data,_Key) -> ?nif_stub.
+dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
%% Key = [E,N,D] E=PublicExponent N=PublicModulus D=PrivateExponent
rsa_sign(Data,Key) ->
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 08d7a0ce99..576949d38d 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -770,18 +770,18 @@ dsa_verify_test(Config) when is_list(Config) ->
crypto:mpint(Key)
],
- ?line m(crypto:dss_verify(sized_binary(Msg), sized_binary(SigBlob),
+ ?line m(my_dss_verify(sized_binary(Msg), sized_binary(SigBlob),
ValidKey), true),
BadMsg = one_bit_wrong(Msg),
- ?line m(crypto:dss_verify(sized_binary(BadMsg), sized_binary(SigBlob),
+ ?line m(my_dss_verify(sized_binary(BadMsg), sized_binary(SigBlob),
ValidKey), false),
BadSig = one_bit_wrong(SigBlob),
- ?line m(crypto:dss_verify(sized_binary(Msg), sized_binary(BadSig),
+ ?line m(my_dss_verify(sized_binary(Msg), sized_binary(BadSig),
ValidKey), false),
SizeErr = size(SigBlob) - 13,
- BadArg = (catch crypto:dss_verify(sized_binary(Msg), <<SizeErr:32, SigBlob/binary>>,
+ BadArg = (catch my_dss_verify(sized_binary(Msg), <<SizeErr:32, SigBlob/binary>>,
ValidKey)),
?line m(element(1,element(2,BadArg)), badarg),
@@ -791,9 +791,12 @@ dsa_verify_test(Config) when is_list(Config) ->
crypto:mpint(Key+17)
],
- ?line m(crypto:dss_verify(sized_binary(Msg), sized_binary(SigBlob),
+ ?line m(my_dss_verify(sized_binary(Msg), sized_binary(SigBlob),
InValidKey), false).
+
+one_bit_wrong(List) when is_list(List) ->
+ lists:map(fun(Bin) -> one_bit_wrong(Bin) end, List);
one_bit_wrong(Bin) ->
Half = size(Bin) div 2,
<<First:Half/binary, Byte:8, Last/binary>> = Bin,
@@ -843,15 +846,15 @@ dsa_sign_test(Config) when is_list(Config) ->
ParamG = 18320614775012672475365915366944922415598782131828709277168615511695849821411624805195787607930033958243224786899641459701930253094446221381818858674389863050420226114787005820357372837321561754462061849169568607689530279303056075793886577588606958623645901271866346406773590024901668622321064384483571751669,
Params = [crypto:mpint(ParamP), crypto:mpint(ParamQ), crypto:mpint(ParamG)],
- ?line Sig1 = crypto:dss_sign(sized_binary(Msg), Params ++ [crypto:mpint(PrivKey)]),
+ ?line Sig1 = my_dss_sign(sized_binary(Msg), Params ++ [crypto:mpint(PrivKey)]),
- ?line m(crypto:dss_verify(sized_binary(Msg), sized_binary(Sig1),
+ ?line m(my_dss_verify(sized_binary(Msg), Sig1,
Params ++ [crypto:mpint(PubKey)]), true),
- ?line m(crypto:dss_verify(sized_binary(one_bit_wrong(Msg)), sized_binary(Sig1),
+ ?line m(my_dss_verify(sized_binary(one_bit_wrong(Msg)), Sig1,
Params ++ [crypto:mpint(PubKey)]), false),
- ?line m(crypto:dss_verify(sized_binary(Msg), sized_binary(one_bit_wrong(Sig1)),
+ ?line m(my_dss_verify(sized_binary(Msg), one_bit_wrong(Sig1),
Params ++ [crypto:mpint(PubKey)]), false),
%%?line Bad = crypto:dss_sign(sized_binary(Msg), [Params, crypto:mpint(PubKey)]),
@@ -1132,3 +1135,24 @@ zero_bin(N) when is_integer(N) ->
<<0:N8/integer>>;
zero_bin(B) when is_binary(B) ->
zero_bin(size(B)).
+
+my_dss_verify(Data,[Sign|Tail],Key) ->
+ Res = my_dss_verify(Data,sized_binary(Sign),Key),
+ case Tail of
+ [] -> Res;
+ _ -> ?line Res = my_dss_verify(Data,Tail,Key)
+ end;
+my_dss_verify(Data,Sign,Key) ->
+ ?line Res = crypto:dss_verify(Data, Sign, Key),
+ ?line Res = crypto:dss_verify(sha, Data, Sign, Key),
+ ?line <<_:32,Raw/binary>> = Data,
+ ?line Res = crypto:dss_verify(none, crypto:sha(Raw), Sign, Key),
+ Res.
+
+my_dss_sign(Data,Key) ->
+ ?line S1 = crypto:dss_sign(Data, Key),
+ ?line S2 = crypto:dss_sign(sha, Data, Key),
+ ?line <<_:32,Raw/binary>> = Data,
+ ?line S3 = crypto:dss_sign(none, crypto:sha(Raw), Key),
+ [S1,S2,S3].
+