From 9dea5a397111f1e049f10b9e1a2d6f70a9db6a95 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 21 Mar 2013 11:59:42 +0100 Subject: crypto: Refactor mod_exp_nif As a preparation for the new mod_exp_prime and in the quest to reduce to use of the old mpint format. --- lib/crypto/c_src/crypto.c | 24 +++++++++----- lib/crypto/src/crypto.erl | 79 ++++++++++++++++++++++++++--------------------- 2 files changed, 60 insertions(+), 43 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index e77e5fb8f0..8139b331bf 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -304,7 +304,7 @@ static ErlNifFunc nif_funcs[] = { {"rand_bytes", 3, rand_bytes_3}, {"strong_rand_mpint_nif", 3, strong_rand_mpint_nif}, {"rand_uniform_nif", 2, rand_uniform_nif}, - {"mod_exp_nif", 3, mod_exp_nif}, + {"mod_exp_nif", 4, mod_exp_nif}, {"dss_verify", 4, dss_verify}, {"rsa_verify_nif", 4, rsa_verify_nif}, {"aes_cbc_crypt", 4, aes_cbc_crypt}, @@ -1543,16 +1543,19 @@ static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER } static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Base,Exponent,Modulo) */ +{/* (Base,Exponent,Modulo,bin_hdr) */ BIGNUM *bn_base=NULL, *bn_exponent=NULL, *bn_modulo, *bn_result; BN_CTX *bn_ctx; unsigned char* ptr; unsigned dlen; + unsigned bin_hdr; /* return type: 0=plain binary, 4: mpint */ + unsigned extra_byte; ERL_NIF_TERM ret; - if (!get_bn_from_mpint(env, argv[0], &bn_base) - || !get_bn_from_mpint(env, argv[1], &bn_exponent) - || !get_bn_from_mpint(env, argv[2], &bn_modulo)) { + if (!get_bn_from_bin(env, argv[0], &bn_base) + || !get_bn_from_bin(env, argv[1], &bn_exponent) + || !get_bn_from_bin(env, argv[2], &bn_modulo) + || !enif_get_uint(env,argv[3],&bin_hdr) || (bin_hdr & ~4)) { if (bn_base) BN_free(bn_base); if (bn_exponent) BN_free(bn_exponent); @@ -1562,9 +1565,14 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg bn_ctx = BN_CTX_new(); BN_mod_exp(bn_result, bn_base, bn_exponent, bn_modulo, bn_ctx); dlen = BN_num_bytes(bn_result); - ptr = enif_make_new_binary(env, dlen+4, &ret); - put_int32(ptr, dlen); - BN_bn2bin(bn_result, ptr+4); + extra_byte = bin_hdr && BN_is_bit_set(bn_result, dlen*8-1); + ptr = enif_make_new_binary(env, bin_hdr+extra_byte+dlen, &ret); + if (bin_hdr) { + put_int32(ptr, extra_byte+dlen); + ptr[4] = 0; /* extra zeroed byte to ensure a positive mpint */ + ptr += bin_hdr + extra_byte; + } + BN_bn2bin(bn_result, ptr); BN_free(bn_result); BN_CTX_free(bn_ctx); BN_free(bn_modulo); diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 1328a95e87..f5c1cd2845 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -787,17 +787,15 @@ rand_uniform_nif(_From,_To) -> ?nif_stub. %% mod_exp(Base, Exponent, Modulo) when is_integer(Base), is_integer(Exponent), is_integer(Modulo) -> - erlint(mod_exp(mpint(Base), mpint(Exponent), mpint(Modulo))); + bin_to_int(mod_exp_nif(int_to_bin(Base), int_to_bin(Exponent), int_to_bin(Modulo), 0)); mod_exp(Base, Exponent, Modulo) -> - case mod_exp_nif(Base,Exponent,Modulo) of - <> when MSB > 127 -> - <<(Len + 1):32/integer, 0, MSB, Rest/binary>>; - Whatever -> - Whatever + mod_exp_nif(mpint_to_bin(Base),mpint_to_bin(Exponent),mpint_to_bin(Modulo), 4). + end. -mod_exp_nif(_Base,_Exp,_Mod) -> ?nif_stub. + +mod_exp_nif(_Base,_Exp,_Mod,_bin_hdr) -> ?nif_stub. %% %% DSS, RSA - verify @@ -1071,43 +1069,54 @@ dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub. %% large integer in a binary with 32bit length %% MP representaion (SSH2) -mpint(X) when X < 0 -> - case X of - -1 -> - <<0,0,0,1,16#ff>>; - _ -> - mpint_neg(X,0,[]) - end; -mpint(X) -> - case X of - 0 -> - <<0,0,0,0>>; - _ -> - mpint_pos(X,0,[]) - end. +mpint(X) when X < 0 -> mpint_neg(X); +mpint(X) -> mpint_pos(X). -define(UINT32(X), X:32/unsigned-big-integer). -mpint_neg(-1,I,Ds=[MSB|_]) -> - if MSB band 16#80 =/= 16#80 -> - <>; - true -> - (<>) - end; -mpint_neg(X,I,Ds) -> - mpint_neg(X bsr 8,I+1,[(X band 255)|Ds]). + +mpint_neg(X) -> + Bin = int_to_bin_neg(X, []), + Sz = byte_size(Bin), + <>. -mpint_pos(0,I,Ds=[MSB|_]) -> +mpint_pos(X) -> + Bin = int_to_bin_pos(X, []), + <> = Bin, + Sz = byte_size(Bin), if MSB band 16#80 == 16#80 -> - <>; + <>; true -> - (<>) - end; -mpint_pos(X,I,Ds) -> - mpint_pos(X bsr 8,I+1,[(X band 255)|Ds]). + <> + end. + +int_to_bin(X) when X < 0 -> int_to_bin_neg(X, []); +int_to_bin(X) -> int_to_bin_pos(X, []). + +int_to_bin_pos(X) when X >= 0 -> + int_to_bin_pos(X, []). + +int_to_bin_pos(0,Ds=[_|_]) -> + list_to_binary(Ds); +int_to_bin_pos(X,Ds) -> + int_to_bin_pos(X bsr 8, [(X band 255)|Ds]). + +int_to_bin_neg(-1, Ds=[MSB|_]) when MSB >= 16#80 -> + list_to_binary(Ds); +int_to_bin_neg(X,Ds) -> + int_to_bin_neg(X bsr 8, [(X band 255)|Ds]). + + +bin_to_int(Bin) -> + Bits = bit_size(Bin), + <> = Bin, + Integer. %% int from integer in a binary with 32bit length erlint(<>) -> Bits= MPIntSize * 8, <> = MPIntValue, Integer. + +mpint_to_bin(<>) -> + Bin. -- cgit v1.2.3 From d8144ef38f7e18230349100bbdee1da4c723fd94 Mon Sep 17 00:00:00 2001 From: Andreas Schultz Date: Wed, 12 Sep 2012 20:57:01 +0200 Subject: CRYPTO: add support for RFC-2945 SRP-3 and RFC-5054 SRP-6a authentication --- lib/crypto/c_src/crypto.c | 216 +++++++++++++++++++++++++++++++++++++++ lib/crypto/doc/src/crypto.xml | 88 +++++++++++++++- lib/crypto/src/crypto.erl | 71 ++++++++++++- lib/crypto/test/crypto_SUITE.erl | 154 +++++++++++++++++++++++++++- 4 files changed, 524 insertions(+), 5 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 8139b331bf..7853ef3291 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -207,6 +207,9 @@ static ERL_NIF_TERM dh_generate_parameters_nif(ErlNifEnv* env, int argc, const E static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM srp_client_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM srp_server_secret(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -321,6 +324,9 @@ static ErlNifFunc nif_funcs[] = { {"dh_check", 1, dh_check}, {"dh_generate_key_nif", 2, dh_generate_key_nif}, {"dh_compute_key_nif", 3, dh_compute_key_nif}, + {"srp_value_B_nif", 5, srp_value_B_nif}, + {"srp_client_secret_nif", 7, srp_client_secret_nif}, + {"srp_server_secret", 5, srp_server_secret}, {"bf_cfb64_crypt", 4, bf_cfb64_crypt}, {"bf_cbc_crypt", 4, bf_cbc_crypt}, {"bf_ecb_crypt", 3, bf_ecb_crypt}, @@ -1515,6 +1521,17 @@ static int get_bn_from_mpint(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp) return 1; } +static int get_bn_from_bin(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp) +{ + ErlNifBinary bin; + if (!enif_inspect_binary(env,term,&bin)) { + return 0; + } + ERL_VALGRIND_ASSERT_MEM_DEFINED(bin.data, bin.size); + *bnp = BN_bin2bn(bin.data, bin.size, NULL); + return 1; +} + static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Lo,Hi) */ BIGNUM *bn_from = NULL, *bn_to, *bn_rand; @@ -2352,6 +2369,205 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T return ret; } +static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Multiplier, Verifier, Generator, Exponent, Prime) */ + BIGNUM *bn_verifier = NULL; + BIGNUM *bn_exponent, *bn_generator, *bn_prime, *bn_multiplier, *bn_result; + BN_CTX *bn_ctx; + unsigned char* ptr; + unsigned dlen; + ERL_NIF_TERM ret; + + if (!get_bn_from_bin(env, argv[0], &bn_multiplier) + || !get_bn_from_bin(env, argv[1], &bn_verifier) + || !get_bn_from_bin(env, argv[2], &bn_generator) + || !get_bn_from_bin(env, argv[3], &bn_exponent) + || !get_bn_from_bin(env, argv[4], &bn_prime)) { + if (bn_multiplier) BN_free(bn_multiplier); + if (bn_verifier) BN_free(bn_verifier); + if (bn_verifier) BN_free(bn_generator); + if (bn_verifier) BN_free(bn_exponent); + if (bn_verifier) BN_free(bn_prime); + return enif_make_badarg(env); + } + + bn_result = BN_new(); + bn_ctx = BN_CTX_new(); + + /* B = k*v + g^b % N */ + + /* k * v */ + BN_mod_mul(bn_multiplier, bn_multiplier, bn_verifier, bn_prime, bn_ctx); + + /* g^b % N */ + BN_mod_exp(bn_result, bn_generator, bn_exponent, bn_prime, bn_ctx); + + /* k*v + g^b % N */ + BN_mod_add(bn_result, bn_result, bn_multiplier, bn_prime, bn_ctx); + + /* check that B % N != 0, reuse bn_multiplier */ + BN_nnmod(bn_multiplier, bn_result, bn_prime, bn_ctx); + if (BN_is_zero(bn_multiplier)) { + ret = atom_error; + } else { + dlen = BN_num_bytes(bn_result); + ptr = enif_make_new_binary(env, dlen, &ret); + BN_bn2bin(bn_result, ptr); + } + BN_free(bn_result); + BN_CTX_free(bn_ctx); + BN_free(bn_prime); + BN_free(bn_generator); + BN_free(bn_multiplier); + BN_free(bn_exponent); + BN_free(bn_verifier); + return ret; +} + +static ERL_NIF_TERM srp_client_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (a, u, B, Multiplier, Prime, Exponent, Generator) */ +/* + = (B - (k * g^x)) ^ (a + (u * x)) % N +*/ + BIGNUM *bn_exponent = NULL, *bn_a = NULL; + BIGNUM *bn_u, *bn_multiplier, *bn_exp2, *bn_base, + *bn_prime, *bn_generator, *bn_B, *bn_result; + BN_CTX *bn_ctx; + unsigned char* ptr; + unsigned dlen; + ERL_NIF_TERM ret; + + if (!get_bn_from_bin(env, argv[0], &bn_a) + || !get_bn_from_bin(env, argv[1], &bn_u) + || !get_bn_from_bin(env, argv[2], &bn_B) + || !get_bn_from_bin(env, argv[3], &bn_multiplier) + || !get_bn_from_bin(env, argv[4], &bn_generator) + || !get_bn_from_bin(env, argv[5], &bn_exponent) + || !get_bn_from_bin(env, argv[6], &bn_prime)) + { + if (bn_exponent) BN_free(bn_exponent); + if (bn_a) BN_free(bn_a); + if (bn_u) BN_free(bn_u); + if (bn_B) BN_free(bn_B); + if (bn_multiplier) BN_free(bn_multiplier); + if (bn_generator) BN_free(bn_generator); + if (bn_prime) BN_free(bn_prime); + return enif_make_badarg(env); + } + + bn_ctx = BN_CTX_new(); + bn_result = BN_new(); + + /* check that B % N != 0 */ + BN_nnmod(bn_result, bn_B, bn_prime, bn_ctx); + if (BN_is_zero(bn_result)) { + BN_free(bn_exponent); + BN_free(bn_a); + BN_free(bn_generator); + BN_free(bn_prime); + BN_free(bn_u); + BN_free(bn_B); + BN_CTX_free(bn_ctx); + + return atom_error; + } + + /* (B - (k * g^x)) */ + bn_base = BN_new(); + BN_mod_exp(bn_result, bn_generator, bn_exponent, bn_prime, bn_ctx); + BN_mod_mul(bn_result, bn_multiplier, bn_result, bn_prime, bn_ctx); + BN_mod_sub(bn_base, bn_B, bn_result, bn_prime, bn_ctx); + + /* a + (u * x) */ + bn_exp2 = BN_new(); + BN_mod_mul(bn_result, bn_u, bn_exponent, bn_prime, bn_ctx); + BN_mod_add(bn_exp2, bn_a, bn_result, bn_prime, bn_ctx); + + /* (B - (k * g^x)) ^ (a + (u * x)) % N */ + BN_mod_exp(bn_result, bn_base, bn_exp2, bn_prime, bn_ctx); + + dlen = BN_num_bytes(bn_result); + ptr = enif_make_new_binary(env, dlen, &ret); + BN_bn2bin(bn_result, ptr); + BN_free(bn_result); + BN_CTX_free(bn_ctx); + + BN_free(bn_multiplier); + BN_free(bn_exp2); + BN_free(bn_u); + BN_free(bn_exponent); + BN_free(bn_a); + BN_free(bn_B); + BN_free(bn_base); + BN_free(bn_generator); + BN_free(bn_prime); + return ret; +} + +static ERL_NIF_TERM srp_server_secret(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Verifier, b, u, A, Prime) */ +/* + = (A * v^u) ^ b % N +*/ + BIGNUM *bn_b = NULL, *bn_verifier = NULL; + BIGNUM *bn_prime, *bn_A, *bn_u, *bn_base, *bn_result; + BN_CTX *bn_ctx; + unsigned char* ptr; + unsigned dlen; + ERL_NIF_TERM ret; + + if (!get_bn_from_bin(env, argv[0], &bn_verifier) + || !get_bn_from_bin(env, argv[1], &bn_b) + || !get_bn_from_bin(env, argv[2], &bn_u) + || !get_bn_from_bin(env, argv[3], &bn_A) + || !get_bn_from_bin(env, argv[4], &bn_prime)) + { + if (bn_verifier) BN_free(bn_verifier); + if (bn_b) BN_free(bn_b); + if (bn_u) BN_free(bn_u); + if (bn_A) BN_free(bn_A); + if (bn_prime) BN_free(bn_prime); + return enif_make_badarg(env); + } + + bn_ctx = BN_CTX_new(); + bn_result = BN_new(); + + /* check that A % N != 0 */ + BN_nnmod(bn_result, bn_A, bn_prime, bn_ctx); + if (BN_is_zero(bn_result)) { + BN_free(bn_b); + BN_free(bn_verifier); + BN_free(bn_prime); + BN_free(bn_A); + BN_CTX_free(bn_ctx); + + return atom_error; + } + + /* (A * v^u) */ + bn_base = BN_new(); + BN_mod_exp(bn_base, bn_verifier, bn_u, bn_prime, bn_ctx); + BN_mod_mul(bn_base, bn_A, bn_base, bn_prime, bn_ctx); + + /* (A * v^u) ^ b % N */ + BN_mod_exp(bn_result, bn_base, bn_b, bn_prime, bn_ctx); + + dlen = BN_num_bytes(bn_result); + ptr = enif_make_new_binary(env, dlen, &ret); + BN_bn2bin(bn_result, ptr); + BN_free(bn_result); + BN_CTX_free(bn_ctx); + + BN_free(bn_u); + BN_free(bn_base); + BN_free(bn_verifier); + BN_free(bn_prime); + BN_free(bn_A); + BN_free(bn_b); + return ret; +} + static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Key, Ivec, Data, IsEncrypt) */ ErlNifBinary key_bin, ivec_bin, data_bin; diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index 6b9b2ef207..d4224e773c 100755 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -973,7 +973,17 @@ Mpint() = >]]> using the crypto library.

- + + mod_exp_prime(N, P, M) -> Result + Computes the function: N^P mod M + + N, P, M = binary() + Result = binary() | error + + +

Computes the function N^P mod M.

+
+
rsa_sign(DataOrDigest, Key) -> Signature rsa_sign(DigestType, DataOrDigest, Key) -> Signature @@ -1256,6 +1266,82 @@ Mpint() = >]]> + + srp_value_B(Multiplier, Verifier, Generator, Exponent, Prime) -> ValueB + Computes the SRP function: B = k*v + g^b % N + + Verifier (v), Generator (g), Exponent (b), Prime (N), ValueB (B) = binary() + Multiplier (k) = integer() | binary() + + +

Computes the SRP value B according to RFC-2945, Sect. 3 and RFC-5054, Sect. 2.5.3

+

B = k*v + g^b % N

+
+
+ + + srp_client_secret(A, U, B, Multiplier, Generator, Exponent, Prime) -> Secret + Computes the SRP client secret + + A (a), U (u), B, Multiplier (k), Generator (g), Exponent (x), Prime (N), Secret = binary() + Multiplier (k) = integer() | binary() + + +

Computes the SRP client secret according to RFC-2945, Sect. 3 and RFC-5054, Sect. 2.6

+

Secret = (B - (k * g^x)) ^ (a + (u * x)) % N

+
+
+ + + srp_server_secret(Verifier, B, U, A, Prime) -> Secret + Computes the SRP host secret + + Verifier (v), B (b), U (u), A, Prime (N), Secret = binary() + + +

Computes the SRP host secret according to RFC-2945, Sect. 3 and RFC-5054, Sect. 2.6

+

Secret = (A * v^u) ^ b % N

+
+
+ + + srp3_value_u(B) -> Result + Computes the SRP3-SHA value u + + B = binary() + Result = integer() + + +

Computes the SRP-3 value u according to RFC-2945, Sect. 3 +

+
+
+ + + srp6_value_u(A, B, Prime) -> Result + Computes the SRP6a value u as u = SHA1(PAD(A) | PAD(B)) + + A, B, Prime = binary() + Result = integer() + + +

Computes the SRP-6 value u according to RFC-5054, Sect. 2.6 +

+
+
+ + + srp6a_multiplier(Generator, Prime) -> Result + Computes the SRP-SHA function: k = SHA1(N | PAD(g)) + + Generator, Prime = binary() + Result = integer() + + +

Computes the SRP-6a function SHA1(N | PAD(g)) as the multiplier +

+
+
exor(Data1, Data2) -> Result diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index f5c1cd2845..0a0ebc05c4 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -57,7 +57,11 @@ -export([dh_generate_key/1, dh_generate_key/2, dh_compute_key/3]). -export([rand_bytes/1, rand_bytes/3, rand_uniform/2]). -export([strong_rand_bytes/1, strong_rand_mpint/3]). --export([mod_exp/3, mpint/1, erlint/1]). +-export([mod_exp/3, mod_exp_prime/3, mpint/1, erlint/1]). +-export([srp_value_B/5]). +-export([srp3_value_u/1, srp6_value_u/3, srp6a_multiplier/2]). +-export([srp_client_secret/7, srp_server_secret/5]). + %% -export([idea_cbc_encrypt/3, idea_cbc_decrypt/3]). -export([aes_cbc_128_encrypt/3, aes_cbc_128_decrypt/3]). -export([aes_cbc_256_encrypt/3, aes_cbc_256_decrypt/3]). @@ -88,7 +92,7 @@ strong_rand_bytes, strong_rand_mpint, rand_uniform, - mod_exp, + mod_exp, mod_exp_prime, dss_verify,dss_sign, rsa_verify,rsa_sign, rsa_public_encrypt,rsa_private_decrypt, @@ -109,6 +113,9 @@ hash, hash_init, hash_update, hash_final, hmac, hmac_init, hmac_update, hmac_final, hmac_final_n, info, rc2_cbc_encrypt, rc2_cbc_decrypt, + srp_value_B, + srp3_value_u, srp6_value_u, srp6a_multiplier, + srp_client_secret, srp_server_secret, info_lib]). -type rsa_digest_type() :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'. @@ -783,7 +790,7 @@ rand_uniform_pos(_,_) -> rand_uniform_nif(_From,_To) -> ?nif_stub. %% -%% mod_exp - utility for rsa generation +%% mod_exp - utility for rsa generation and SRP %% mod_exp(Base, Exponent, Modulo) when is_integer(Base), is_integer(Exponent), is_integer(Modulo) -> @@ -792,6 +799,11 @@ mod_exp(Base, Exponent, Modulo) mod_exp(Base, Exponent, Modulo) -> mod_exp_nif(mpint_to_bin(Base),mpint_to_bin(Exponent),mpint_to_bin(Modulo), 4). +-spec mod_exp_prime(binary(), binary(), binary()) -> binary(). +mod_exp_prime(Base, Exponent, Prime) -> + case mod_exp_nif(Base, Exponent, Prime, 0) of + <<0>> -> error; + R -> R end. @@ -1062,10 +1074,63 @@ dh_compute_key(OthersPublicKey, MyPrivateKey, DHParameters) -> dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub. + +-spec srp_value_B(binary(), integer(), binary(), binary(), binary()) -> binary(). +srp_value_B(Multiplier, Verifier, Generator, Exponent, Prime) -> + srp_value_B_nif(srp_multiplier(Multiplier), Verifier, Generator, Exponent, Prime). + +srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub. + +-spec srp_client_secret(binary(), binary(), binary(), integer()|binary(), binary(), binary(), binary()) -> binary(). +srp_client_secret(A, U, B, Multiplier, Generator, Exponent, Prime) -> + srp_client_secret_nif(A, U, B, srp_multiplier(Multiplier), Generator, Exponent, Prime). + +srp_client_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?nif_stub. + +-spec srp_server_secret(binary(), binary(), binary(), binary(), binary()) -> binary(). +srp_server_secret(_Verifier, _B, _U, _A, _Prime) -> ?nif_stub. + +-spec srp6a_multiplier(binary(), binary()) -> binary(). +srp6a_multiplier(Generator, Prime) -> + %% k = SHA1(N | PAD(g)) + C0 = sha_init(), + C1 = sha_update(C0, Prime), + C2 = sha_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)), + sha_final(C2). + +-spec srp3_value_u(binary()) -> binary(). +srp3_value_u(B) -> + %% The parameter u is a 32-bit unsigned integer which takes its value + %% from the first 32 bits of the SHA1 hash of B, MSB first. + <> = sha(B), + U. + +-spec srp6_value_u(binary(), binary(), binary()) -> binary(). +srp6_value_u(A, B, Prime) -> + %% SHA1(PAD(A) | PAD(B)) + PadLength = erlang:byte_size(Prime), + C0 = sha_init(), + C1 = sha_update(C0, srp_pad_to(PadLength, A)), + C2 = sha_update(C1, srp_pad_to(PadLength, B)), + sha_final(C2). + %% %% LOCAL FUNCTIONS %% +srp_pad_length(Width, Length) -> + (Width - Length rem Width) rem Width. + +srp_pad_to(Width, Binary) -> + case srp_pad_length(Width, size(Binary)) of + 0 -> Binary; + N -> << 0:(N*8), Binary/binary>> + end. + +srp_multiplier(Multiplier) when is_binary(Multiplier) -> + Multiplier; +srp_multiplier(Multiplier) when is_integer(Multiplier) -> + int_to_bin_pos(Multiplier). %% large integer in a binary with 32bit length %% MP representaion (SSH2) diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 6f2df0f07b..4cfd3544f2 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -72,6 +72,7 @@ dsa_sign_hash_test/1, rsa_encrypt_decrypt/1, dh/1, + srp3/1, srp6/1, srp6a/1, exor_test/1, rc4_test/1, rc4_stream_test/1, @@ -100,7 +101,7 @@ groups() -> rand_uniform_test, strong_rand_test, rsa_verify_test, dsa_verify_test, rsa_sign_test, rsa_sign_hash_test, dsa_sign_test, dsa_sign_hash_test, - rsa_encrypt_decrypt, dh, exor_test, + rsa_encrypt_decrypt, dh, srp3, srp6, srp6a, exor_test, rc4_test, rc4_stream_test, mod_exp_test, blowfish_cfb64, smp]}]. @@ -2017,6 +2018,157 @@ dh(Config) when is_list(Config) -> exit(Pid, kill) end. +srp3(doc) -> + ["SRP-3 test vectors generated by http://srp.stanford.edu/demo/demo.html"]; +srp3(suite) -> []; +srp3(Config) when is_list(Config) -> + Username = <<"alice">>, + Password = <<"password123">>, + Salt = hexstr2bin("2857827A19266A1F2BC6"), + Prime = hexstr2bin("EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C" + "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4" + "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29" + "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A" + "FD5138FE8376435B9FC61D2FC0EB06E3"), + Generator = <<2>>, + Multiplier = 1, + %% X = hexstr2bin("96E54AB0CD4C5123EDCFA4A1502918AAD3C9E2A8"), + Verifier = hexstr2bin("96EB5F13621D911AA1CA405DE9C64217D4108EEEECAFFE500034FE0E" + "C031E42C8714667C161BCE0E7996F7DDE1B63824C130D2D7286C08C0" + "49758420735961347112AE102A3F23B3F687F8FEE0DF2BFAF933C608" + "D6FE5B5EEE3116FE54016E065BF8E8C9FDBBC08719231AC215149140" + "519E8FDD9AA4F410C28A58AF42974D2D"), + ClntPriv = hexstr2bin("6411DE75538BED8170677D577D0608F39112BC95B503C447EB6AC945" + "49C75C7B"), + SrvrPriv = hexstr2bin("85E44A6F694DBE676145DB245A045CD37C99F05C562C7840A31F270D" + "9AADCF8B"), + ClntPub = hexstr2bin("B22B1FFA2244B8CB94F3A9080F419CAEAB0DBA93EA1965B5E84587EE" + "55C79E7A118865DC59B9D0353362C2A8261E7C1B0D221A0E233C2AD1" + "640DACBB8664CBC9733EAC392DA7800142860380C3FC573C3C064329" + "CF54063FD114C7210E9CB3A611EA8002B1844B698F930D95D143899B" + "948A090E0C25938E5F84067D1883DC63"), + SrvrPub = hexstr2bin("93A8C4D8B7F7395ADCFD4ABA37B015124513D3F37B3E85EB23064BE5" + "F53C0AE32FFB9D8C0AA0DCFFA74D632DD67DEBB5C35AAE9812286CC8" + "C43CC176ECBC6D3F447594D9554E995B2509127BF88FADDDA4982D03" + "8EC3001320712D3B1269308CE70F319B2295FA57674F03A2D993CFB1" + "F84C35B7D0C012FA73CD4C8F7D5A71C7"), + U = hexstr2bin("02E2476A"), + + PremasterSecret = hexstr2bin("C29A986C4D521BBC66428ED11D994CD7431574A6184B83CDCC345092" + "791E75748A1D38CAC4BD14760F0D2694B711236419240FF2F172454C" + "46ABF4FF39498DAFDD2C82924F7D7BD76CDFCE688C77D93F18A65409" + "9176A9192615DC0277AE7C12F1F6A7F6563FCA11675D809AF578BDE5" + "2B51E05D440B63099A017A0B45044801"), + UserPassHash = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]), + m(crypto:mod_exp_prime(Generator, UserPassHash, Prime), Verifier), + m(crypto:mod_exp_prime(Generator, ClntPriv, Prime), ClntPub), + m(crypto:srp3_value_u(SrvrPub), U), + m(crypto:srp_value_B(Multiplier, Verifier, Generator, SrvrPriv, Prime), SrvrPub), + m(crypto:srp_client_secret(ClntPriv, U, SrvrPub, Multiplier, Generator, UserPassHash, Prime), PremasterSecret), + m(crypto:srp_server_secret(Verifier, SrvrPriv, U, ClntPub, Prime), PremasterSecret), + ok. + +srp6(doc) -> + ["SRP-6 test vectors generated by http://srp.stanford.edu/demo/demo.html"]; +srp6(suite) -> []; +srp6(Config) when is_list(Config) -> + Username = <<"alice">>, + Password = <<"password123">>, + Salt = hexstr2bin("2857827A19266A1F2BC6"), + Prime = hexstr2bin("EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C" + "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4" + "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29" + "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A" + "FD5138FE8376435B9FC61D2FC0EB06E3"), + Generator = <<2>>, + Multiplier = 3, + %% X = hexstr2bin("96E54AB0CD4C5123EDCFA4A1502918AAD3C9E2A8"), + Verifier = hexstr2bin("96EB5F13621D911AA1CA405DE9C64217D4108EEEECAFFE500034FE0E" + "C031E42C8714667C161BCE0E7996F7DDE1B63824C130D2D7286C08C0" + "49758420735961347112AE102A3F23B3F687F8FEE0DF2BFAF933C608" + "D6FE5B5EEE3116FE54016E065BF8E8C9FDBBC08719231AC215149140" + "519E8FDD9AA4F410C28A58AF42974D2D"), + ClntPriv = hexstr2bin("6411DE75538BED8170677D577D0608F39112BC95B503C447EB6AC945" + "49C75C7B"), + SrvrPriv = hexstr2bin("85E44A6F694DBE676145DB245A045CD37C99F05C562C7840A31F270D" + "9AADCF8B"), + ClntPub = hexstr2bin("B22B1FFA2244B8CB94F3A9080F419CAEAB0DBA93EA1965B5E84587EE" + "55C79E7A118865DC59B9D0353362C2A8261E7C1B0D221A0E233C2AD1" + "640DACBB8664CBC9733EAC392DA7800142860380C3FC573C3C064329" + "CF54063FD114C7210E9CB3A611EA8002B1844B698F930D95D143899B" + "948A090E0C25938E5F84067D1883DC63"), + SrvrPub = hexstr2bin("D2D07845CE7ECDB9845DD36B10ACD3598CC29049DE9F467F84CE16B6" + "D97A6DC567AF8B0F9FEDF74962400AD5C357951E64E67B641246F264" + "C8DE6D9A72E554D6C8D3194548780A0C438A0FCC509CA88A14AA1DEB" + "C0F09E4B37A965D1545DB4AD361346F3189B0EA569C06D326C4E4797" + "9E381C748293B7C0591BE0BE419E053E"), + U = hexstr2bin("0A2534C0BF52A0DA9001EEC62CF2A546AB0908A7"), + + PremasterSecret = hexstr2bin("19D22C19612874EBF1F2581F8EFCFDC44C6FDA3B87B0A73823D7E962" + "554295D4E48D3A336523ADBDDD0EC8FB0F02687109E97E01C17C93CC" + "7216F9CD8A4AC39F0429857D8D1023066614BDFCBCB89F59A0FEB81C" + "72E992AAD89095A84B6A5FADA152369AB1E350A03693BEF044DF3EDF" + "0C34741F4696C30E9F675D09F58ACBEB"), + UserPassHash = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]), + m(crypto:mod_exp_prime(Generator, UserPassHash, Prime), Verifier), + m(crypto:mod_exp_prime(Generator, ClntPriv, Prime), ClntPub), + m(crypto:srp6_value_u(ClntPub, SrvrPub, Prime), U), + m(crypto:srp_value_B(Multiplier, Verifier, Generator, SrvrPriv, Prime), SrvrPub), + m(crypto:srp_client_secret(ClntPriv, U, SrvrPub, Multiplier, Generator, UserPassHash, Prime), PremasterSecret), + m(crypto:srp_server_secret(Verifier, SrvrPriv, U, ClntPub, Prime), PremasterSecret), + ok. + +srp6a(doc) -> + ["SRP-6a test vectors from RFC5054."]; +srp6a(suite) -> []; +srp6a(Config) when is_list(Config) -> + Username = <<"alice">>, + Password = <<"password123">>, + Salt = hexstr2bin("BEB25379D1A8581EB5A727673A2441EE"), + Prime = hexstr2bin("EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C" + "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4" + "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29" + "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A" + "FD5138FE8376435B9FC61D2FC0EB06E3"), + Generator = <<2>>, + Multiplier = hexstr2bin("7556AA045AEF2CDD07ABAF0F665C3E818913186F"), + %% X = hexstr2bin("94B7555AABE9127CC58CCF4993DB6CF84D16C124"), + Verifier = hexstr2bin("7E273DE8696FFC4F4E337D05B4B375BEB0DDE1569E8FA00A9886D812" + "9BADA1F1822223CA1A605B530E379BA4729FDC59F105B4787E5186F5" + "C671085A1447B52A48CF1970B4FB6F8400BBF4CEBFBB168152E08AB5" + "EA53D15C1AFF87B2B9DA6E04E058AD51CC72BFC9033B564E26480D78" + "E955A5E29E7AB245DB2BE315E2099AFB"), + ClntPriv = hexstr2bin("60975527035CF2AD1989806F0407210BC81EDC04E2762A56AFD529DD" + "DA2D4393"), + SrvrPriv = hexstr2bin("E487CB59D31AC550471E81F00F6928E01DDA08E974A004F49E61F5D1" + "05284D20"), + ClntPub = hexstr2bin("61D5E490F6F1B79547B0704C436F523DD0E560F0C64115BB72557EC4" + "4352E8903211C04692272D8B2D1A5358A2CF1B6E0BFCF99F921530EC" + "8E39356179EAE45E42BA92AEACED825171E1E8B9AF6D9C03E1327F44" + "BE087EF06530E69F66615261EEF54073CA11CF5858F0EDFDFE15EFEA" + "B349EF5D76988A3672FAC47B0769447B"), + SrvrPub = hexstr2bin("BD0C61512C692C0CB6D041FA01BB152D4916A1E77AF46AE105393011" + "BAF38964DC46A0670DD125B95A981652236F99D9B681CBF87837EC99" + "6C6DA04453728610D0C6DDB58B318885D7D82C7F8DEB75CE7BD4FBAA" + "37089E6F9C6059F388838E7A00030B331EB76840910440B1B27AAEAE" + "EB4012B7D7665238A8E3FB004B117B58"), + U = hexstr2bin("CE38B9593487DA98554ED47D70A7AE5F462EF019"), + + PremasterSecret = hexstr2bin("B0DC82BABCF30674AE450C0287745E7990A3381F63B387AAF271A10D" + "233861E359B48220F7C4693C9AE12B0A6F67809F0876E2D013800D6C" + "41BB59B6D5979B5C00A172B4A2A5903A0BDCAF8A709585EB2AFAFA8F" + "3499B200210DCC1F10EB33943CD67FC88A2F39A4BE5BEC4EC0A3212D" + "C346D7E474B29EDE8A469FFECA686E5A"), + UserPassHash = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]), + m(crypto:mod_exp_prime(Generator, UserPassHash, Prime), Verifier), + m(crypto:mod_exp_prime(Generator, ClntPriv, Prime), ClntPub), + m(crypto:srp6a_multiplier(Generator, Prime), Multiplier), + m(crypto:srp6_value_u(ClntPub, SrvrPub, Prime), U), + m(crypto:srp_value_B(Multiplier, Verifier, Generator, SrvrPriv, Prime), SrvrPub), + m(crypto:srp_client_secret(ClntPriv, U, SrvrPub, Multiplier, Generator, UserPassHash, Prime), PremasterSecret), + m(crypto:srp_server_secret(Verifier, SrvrPriv, U, ClntPub, Prime), PremasterSecret), + ok. + %% %% exor_test(doc) -> -- cgit v1.2.3 From 71f8eb83a9088ebedc2b557ae7f86b3db71d1a13 Mon Sep 17 00:00:00 2001 From: Andreas Schultz Date: Tue, 19 Feb 2013 17:36:57 +0100 Subject: CRYPTO: add algorithms/0 function that returns a list off compiled in crypto algorithms add algorithms/0 function that returns a list off compiled in crypto algorithms and make tests suites with SHA226, SHA256, SHA384 and SHA512 conditional based on that --- lib/crypto/c_src/crypto.c | 33 +++ lib/crypto/doc/src/crypto.xml | 8 + lib/crypto/src/crypto.erl | 6 +- lib/crypto/test/crypto_SUITE.erl | 573 ++++++++++++++------------------------- 4 files changed, 246 insertions(+), 374 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 7853ef3291..47a577085c 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -136,6 +136,7 @@ static void unload(ErlNifEnv* env, void* priv_data); /* The NIFs: */ static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -218,6 +219,7 @@ static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_N /* helpers */ +static void init_algorithms_types(void); static void init_digest_types(ErlNifEnv* env); static void hmac_md5(unsigned char *key, int klen, unsigned char *dbuf, int dlen, @@ -250,6 +252,7 @@ static int library_refc = 0; /* number of users of this dynamic library */ static ErlNifFunc nif_funcs[] = { {"info_lib", 0, info_lib}, + {"algorithms", 0, algorithms}, {"md5", 1, md5}, {"md5_init", 0, md5_init}, {"md5_update", 2, md5_update}, @@ -464,6 +467,7 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) atom_digest = enif_make_atom(env,"digest"); init_digest_types(env); + init_algorithms_types(); #ifdef HAVE_DYNAMIC_CRYPTO_LIB { @@ -544,6 +548,35 @@ static void unload(ErlNifEnv* env, void* priv_data) --library_refc; } +static int algos_cnt; +static ERL_NIF_TERM algos[7]; /* increase when extending the list */ + +static void init_algorithms_types(void) +{ + algos_cnt = 0; + + algos[algos_cnt++] = atom_md5; + algos[algos_cnt++] = atom_sha; + algos[algos_cnt++] = atom_ripemd160; +#ifdef HAVE_SHA224 + algos[algos_cnt++] = atom_sha224; +#endif +#ifdef HAVE_SHA256 + algos[algos_cnt++] = atom_sha256; +#endif +#ifdef HAVE_SHA384 + algos[algos_cnt++] = atom_sha384; +#endif +#ifdef HAVE_SHA512 + algos[algos_cnt++] = atom_sha512; +#endif +} + +static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + return enif_make_list_from_array(env, algos, algos_cnt); +} + static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { /* [{<<"OpenSSL">>,9470143,<<"OpenSSL 0.9.8k 25 Mar 2009">>}] */ diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index d4224e773c..e27cc486ec 100755 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -98,6 +98,14 @@ Mpint() = >]]> of atoms.

+ + algorithms() -> [atom()] + Provide a list of available crypto algorithms. + +

Provides the available crypto algorithms in terms of a list + of atoms.

+
+
info_lib() -> [{Name,VerNum,VerStr}] Provides information about the libraries used by crypto. diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 0a0ebc05c4..e8867236ac 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -21,7 +21,7 @@ -module(crypto). --export([start/0, stop/0, info/0, info_lib/0, version/0]). +-export([start/0, stop/0, info/0, info_lib/0, algorithms/0, version/0]). -export([hash/2, hash_init/1, hash_update/2, hash_final/1]). -export([md4/1, md4_init/0, md4_update/2, md4_final/1]). -export([md5/1, md5_init/0, md5_update/2, md5_final/1]). @@ -116,7 +116,7 @@ srp_value_B, srp3_value_u, srp6_value_u, srp6a_multiplier, srp_client_secret, srp_server_secret, - info_lib]). + info_lib, algorithms]). -type rsa_digest_type() :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'. -type dss_digest_type() :: 'none' | 'sha'. @@ -191,6 +191,8 @@ info() -> info_lib() -> ?nif_stub. +algorithms() -> ?nif_stub. + %% Crypto app version history: %% (no version): Driver implementation %% 2.0 : NIF implementation, requires OTP R14 diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 4cfd3544f2..92d16a438d 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -39,7 +39,10 @@ hmac_update_md5_io/1, hmac_update_md5_n/1, hmac_rfc2202/1, - hmac_rfc4231/1, + hmac_rfc4231_sha224/1, + hmac_rfc4231_sha256/1, + hmac_rfc4231_sha384/1, + hmac_rfc4231_sha512/1, ripemd160/1, ripemd160_update/1, sha256/1, @@ -94,7 +97,8 @@ groups() -> sha256, sha256_update, sha512, sha512_update, hmac_update_sha, hmac_update_sha_n, hmac_update_sha256, hmac_update_sha512, hmac_update_md5_n, hmac_update_md5_io, hmac_update_md5, - hmac_rfc2202, hmac_rfc4231, + hmac_rfc2202, hmac_rfc4231_sha224, hmac_rfc4231_sha256, + hmac_rfc4231_sha384, hmac_rfc4231_sha512, des_cbc, aes_cfb, aes_cbc, des_cfb, des_cfb_iter, des3_cbc, des3_cfb, rc2_cbc, aes_cbc_iter, aes_ctr, aes_ctr_stream, des_cbc_iter, des_ecb, @@ -364,8 +368,7 @@ hmac_update_sha256(doc) -> hmac_update_sha256(suite) -> []; hmac_update_sha256(Config) when is_list(Config) -> - if_098(fun() -> hmac_update_sha256_do() end). - + if_supported(sha256, fun() -> hmac_update_sha256_do() end). hmac_update_sha256_do() -> ?line Key = hexstr2bin("00010203101112132021222330313233" @@ -387,7 +390,7 @@ hmac_update_sha512(doc) -> hmac_update_sha512(suite) -> []; hmac_update_sha512(Config) when is_list(Config) -> - if_098(fun() -> hmac_update_sha512_do() end). + if_supported(sha512, fun() -> hmac_update_sha512_do() end). hmac_update_sha512_do() -> ?line Key = hexstr2bin("00010203101112132021222330313233" @@ -583,366 +586,192 @@ hmac_rfc2202_sha() -> ?line m(Case7Exp, Case7Mac_1), ?line m(Case7Exp, Case7Mac_2). -hmac_rfc4231(doc) -> - ["Generate an HMAC using crypto:shaXXX_mac, hmac, and hmac_init, hmac_update, and hmac_final. " +hmac_rfc4231_sha224(doc) -> + ["Generate an HMAC using crypto:sha224_mac, hmac, and hmac_init, hmac_update, and hmac_final. " "Testvectors are take from RFC4231." ]; -hmac_rfc4231(suite) -> +hmac_rfc4231_sha224(suite) -> []; -hmac_rfc4231(Config) when is_list(Config) -> - if_098(fun() -> hmac_rfc4231_do() end). +hmac_rfc4231_sha224(Config) when is_list(Config) -> + if_supported(sha224, fun() -> hmac_rfc4231_sha224_do() end). -hmac_rfc4231_do() -> - %% Test Case 1 - Case1Key = binary:copy(<<16#0b>>, 20), - Case1Data = <<"Hi There">>, - Case1Exp224 = hexstr2bin("896fb1128abbdf196832107cd49df33f" - "47b4b1169912ba4f53684b22"), - Case1Exp256 = hexstr2bin("b0344c61d8db38535ca8afceaf0bf12b" - "881dc200c9833da726e9376c2e32cff7"), - Case1Exp384 = hexstr2bin("afd03944d84895626b0825f4ab46907f" - "15f9dadbe4101ec682aa034c7cebc59c" - "faea9ea9076ede7f4af152e8b2fa9cb6"), - Case1Exp512 = hexstr2bin("87aa7cdea5ef619d4ff0b4241a1d6cb0" - "2379f4e2ce4ec2787ad0b30545e17cde" - "daa833b7d6b8a702038b274eaea3f4e4" - "be9d914eeb61f1702e696c203a126854"), - - ?line Case1Ctx224 = crypto:hmac_init(sha224, Case1Key), - ?line Case1Ctx224_2 = crypto:hmac_update(Case1Ctx224, Case1Data), - ?line Case1Mac224_1 = crypto:hmac_final(Case1Ctx224_2), - ?line Case1Mac224_2 = crypto:sha224_mac(Case1Key, Case1Data), - ?line Case1Mac224_3 = crypto:hmac(sha224, Case1Key, Case1Data), - ?line m(Case1Exp224, Case1Mac224_1), - ?line m(Case1Exp224, Case1Mac224_2), - ?line m(Case1Exp224, Case1Mac224_3), - - ?line Case1Ctx256 = crypto:hmac_init(sha256, Case1Key), - ?line Case1Ctx256_2 = crypto:hmac_update(Case1Ctx256, Case1Data), - ?line Case1Mac256_1 = crypto:hmac_final(Case1Ctx256_2), - ?line Case1Mac256_2 = crypto:sha256_mac(Case1Key, Case1Data), - ?line Case1Mac256_3 = crypto:hmac(sha256, Case1Key, Case1Data), - ?line m(Case1Exp256, Case1Mac256_1), - ?line m(Case1Exp256, Case1Mac256_2), - ?line m(Case1Exp256, Case1Mac256_3), - - ?line Case1Ctx384 = crypto:hmac_init(sha384, Case1Key), - ?line Case1Ctx384_2 = crypto:hmac_update(Case1Ctx384, Case1Data), - ?line Case1Mac384_1 = crypto:hmac_final(Case1Ctx384_2), - ?line Case1Mac384_2 = crypto:sha384_mac(Case1Key, Case1Data), - ?line Case1Mac384_3 = crypto:hmac(sha384, Case1Key, Case1Data), - ?line m(Case1Exp384, Case1Mac384_1), - ?line m(Case1Exp384, Case1Mac384_2), - ?line m(Case1Exp384, Case1Mac384_3), - - ?line Case1Ctx512 = crypto:hmac_init(sha512, Case1Key), - ?line Case1Ctx512_2 = crypto:hmac_update(Case1Ctx512, Case1Data), - ?line Case1Mac512_1 = crypto:hmac_final(Case1Ctx512_2), - ?line Case1Mac512_2 = crypto:sha512_mac(Case1Key, Case1Data), - ?line Case1Mac512_3 = crypto:hmac(sha512, Case1Key, Case1Data), - ?line m(Case1Exp512, Case1Mac512_1), - ?line m(Case1Exp512, Case1Mac512_2), - ?line m(Case1Exp512, Case1Mac512_3), - - %% Test Case 2 - Case2Key = <<"Jefe">>, - Case2Data = <<"what do ya want for nothing?">>, - Case2Exp224 = hexstr2bin("a30e01098bc6dbbf45690f3a7e9e6d0f" - "8bbea2a39e6148008fd05e44"), - Case2Exp256 = hexstr2bin("5bdcc146bf60754e6a042426089575c7" - "5a003f089d2739839dec58b964ec3843"), - Case2Exp384 = hexstr2bin("af45d2e376484031617f78d2b58a6b1b" - "9c7ef464f5a01b47e42ec3736322445e" - "8e2240ca5e69e2c78b3239ecfab21649"), - Case2Exp512 = hexstr2bin("164b7a7bfcf819e2e395fbe73b56e0a3" - "87bd64222e831fd610270cd7ea250554" - "9758bf75c05a994a6d034f65f8f0e6fd" - "caeab1a34d4a6b4b636e070a38bce737"), - - ?line Case2Ctx224 = crypto:hmac_init(sha224, Case2Key), - ?line Case2Ctx224_2 = crypto:hmac_update(Case2Ctx224, Case2Data), - ?line Case2Mac224_1 = crypto:hmac_final(Case2Ctx224_2), - ?line Case2Mac224_2 = crypto:sha224_mac(Case2Key, Case2Data), - ?line Case2Mac224_3 = crypto:hmac(sha224, Case2Key, Case2Data), - ?line m(Case2Exp224, Case2Mac224_1), - ?line m(Case2Exp224, Case2Mac224_2), - ?line m(Case2Exp224, Case2Mac224_3), - - ?line Case2Ctx256 = crypto:hmac_init(sha256, Case2Key), - ?line Case2Ctx256_2 = crypto:hmac_update(Case2Ctx256, Case2Data), - ?line Case2Mac256_1 = crypto:hmac_final(Case2Ctx256_2), - ?line Case2Mac256_2 = crypto:sha256_mac(Case2Key, Case2Data), - ?line Case2Mac256_3 = crypto:hmac(sha256, Case2Key, Case2Data), - ?line m(Case2Exp256, Case2Mac256_1), - ?line m(Case2Exp256, Case2Mac256_2), - ?line m(Case2Exp256, Case2Mac256_3), - - ?line Case2Ctx384 = crypto:hmac_init(sha384, Case2Key), - ?line Case2Ctx384_2 = crypto:hmac_update(Case2Ctx384, Case2Data), - ?line Case2Mac384_1 = crypto:hmac_final(Case2Ctx384_2), - ?line Case2Mac384_2 = crypto:sha384_mac(Case2Key, Case2Data), - ?line Case2Mac384_3 = crypto:hmac(sha384, Case2Key, Case2Data), - ?line m(Case2Exp384, Case2Mac384_1), - ?line m(Case2Exp384, Case2Mac384_2), - ?line m(Case2Exp384, Case2Mac384_3), - - ?line Case2Ctx512 = crypto:hmac_init(sha512, Case2Key), - ?line Case2Ctx512_2 = crypto:hmac_update(Case2Ctx512, Case2Data), - ?line Case2Mac512_1 = crypto:hmac_final(Case2Ctx512_2), - ?line Case2Mac512_2 = crypto:sha512_mac(Case2Key, Case2Data), - ?line Case2Mac512_3 = crypto:hmac(sha512, Case2Key, Case2Data), - ?line m(Case2Exp512, Case2Mac512_1), - ?line m(Case2Exp512, Case2Mac512_2), - ?line m(Case2Exp512, Case2Mac512_3), - - %% Test Case 3 - Case3Key = binary:copy(<<16#aa>>, 20), - Case3Data = binary:copy(<<16#dd>>, 50), - Case3Exp224 = hexstr2bin("7fb3cb3588c6c1f6ffa9694d7d6ad264" - "9365b0c1f65d69d1ec8333ea"), - Case3Exp256 = hexstr2bin("773ea91e36800e46854db8ebd09181a7" - "2959098b3ef8c122d9635514ced565fe"), - Case3Exp384 = hexstr2bin("88062608d3e6ad8a0aa2ace014c8a86f" - "0aa635d947ac9febe83ef4e55966144b" - "2a5ab39dc13814b94e3ab6e101a34f27"), - Case3Exp512 = hexstr2bin("fa73b0089d56a284efb0f0756c890be9" - "b1b5dbdd8ee81a3655f83e33b2279d39" - "bf3e848279a722c806b485a47e67c807" - "b946a337bee8942674278859e13292fb"), - - ?line Case3Ctx224 = crypto:hmac_init(sha224, Case3Key), - ?line Case3Ctx224_2 = crypto:hmac_update(Case3Ctx224, Case3Data), - ?line Case3Mac224_1 = crypto:hmac_final(Case3Ctx224_2), - ?line Case3Mac224_2 = crypto:sha224_mac(Case3Key, Case3Data), - ?line Case3Mac224_3 = crypto:hmac(sha224, Case3Key, Case3Data), - ?line m(Case3Exp224, Case3Mac224_1), - ?line m(Case3Exp224, Case3Mac224_2), - ?line m(Case3Exp224, Case3Mac224_3), - - ?line Case3Ctx256 = crypto:hmac_init(sha256, Case3Key), - ?line Case3Ctx256_2 = crypto:hmac_update(Case3Ctx256, Case3Data), - ?line Case3Mac256_1 = crypto:hmac_final(Case3Ctx256_2), - ?line Case3Mac256_2 = crypto:sha256_mac(Case3Key, Case3Data), - ?line Case3Mac256_3 = crypto:hmac(sha256, Case3Key, Case3Data), - ?line m(Case3Exp256, Case3Mac256_1), - ?line m(Case3Exp256, Case3Mac256_2), - ?line m(Case3Exp256, Case3Mac256_3), - - ?line Case3Ctx384 = crypto:hmac_init(sha384, Case3Key), - ?line Case3Ctx384_2 = crypto:hmac_update(Case3Ctx384, Case3Data), - ?line Case3Mac384_1 = crypto:hmac_final(Case3Ctx384_2), - ?line Case3Mac384_2 = crypto:sha384_mac(Case3Key, Case3Data), - ?line Case3Mac384_3 = crypto:hmac(sha384, Case3Key, Case3Data), - ?line m(Case3Exp384, Case3Mac384_1), - ?line m(Case3Exp384, Case3Mac384_2), - ?line m(Case3Exp384, Case3Mac384_3), - - ?line Case3Ctx512 = crypto:hmac_init(sha512, Case3Key), - ?line Case3Ctx512_2 = crypto:hmac_update(Case3Ctx512, Case3Data), - ?line Case3Mac512_1 = crypto:hmac_final(Case3Ctx512_2), - ?line Case3Mac512_2 = crypto:sha512_mac(Case3Key, Case3Data), - ?line Case3Mac512_3 = crypto:hmac(sha512, Case3Key, Case3Data), - ?line m(Case3Exp512, Case3Mac512_1), - ?line m(Case3Exp512, Case3Mac512_2), - ?line m(Case3Exp512, Case3Mac512_3), - - %% Test Case 4 - Case4Key = list_to_binary(lists:seq(1, 16#19)), - Case4Data = binary:copy(<<16#cd>>, 50), - Case4Exp224 = hexstr2bin("6c11506874013cac6a2abc1bb382627c" - "ec6a90d86efc012de7afec5a"), - Case4Exp256 = hexstr2bin("82558a389a443c0ea4cc819899f2083a" - "85f0faa3e578f8077a2e3ff46729665b"), - Case4Exp384 = hexstr2bin("3e8a69b7783c25851933ab6290af6ca7" - "7a9981480850009cc5577c6e1f573b4e" - "6801dd23c4a7d679ccf8a386c674cffb"), - Case4Exp512 = hexstr2bin("b0ba465637458c6990e5a8c5f61d4af7" - "e576d97ff94b872de76f8050361ee3db" - "a91ca5c11aa25eb4d679275cc5788063" - "a5f19741120c4f2de2adebeb10a298dd"), - - ?line Case4Ctx224 = crypto:hmac_init(sha224, Case4Key), - ?line Case4Ctx224_2 = crypto:hmac_update(Case4Ctx224, Case4Data), - ?line Case4Mac224_1 = crypto:hmac_final(Case4Ctx224_2), - ?line Case4Mac224_2 = crypto:sha224_mac(Case4Key, Case4Data), - ?line Case4Mac224_3 = crypto:hmac(sha224, Case4Key, Case4Data), - ?line m(Case4Exp224, Case4Mac224_1), - ?line m(Case4Exp224, Case4Mac224_2), - ?line m(Case4Exp224, Case4Mac224_3), - - ?line Case4Ctx256 = crypto:hmac_init(sha256, Case4Key), - ?line Case4Ctx256_2 = crypto:hmac_update(Case4Ctx256, Case4Data), - ?line Case4Mac256_1 = crypto:hmac_final(Case4Ctx256_2), - ?line Case4Mac256_2 = crypto:sha256_mac(Case4Key, Case4Data), - ?line Case4Mac256_3 = crypto:hmac(sha256, Case4Key, Case4Data), - ?line m(Case4Exp256, Case4Mac256_1), - ?line m(Case4Exp256, Case4Mac256_2), - ?line m(Case4Exp256, Case4Mac256_3), - - ?line Case4Ctx384 = crypto:hmac_init(sha384, Case4Key), - ?line Case4Ctx384_2 = crypto:hmac_update(Case4Ctx384, Case4Data), - ?line Case4Mac384_1 = crypto:hmac_final(Case4Ctx384_2), - ?line Case4Mac384_2 = crypto:sha384_mac(Case4Key, Case4Data), - ?line Case4Mac384_3 = crypto:hmac(sha384, Case4Key, Case4Data), - ?line m(Case4Exp384, Case4Mac384_1), - ?line m(Case4Exp384, Case4Mac384_2), - ?line m(Case4Exp384, Case4Mac384_3), - - ?line Case4Ctx512 = crypto:hmac_init(sha512, Case4Key), - ?line Case4Ctx512_2 = crypto:hmac_update(Case4Ctx512, Case4Data), - ?line Case4Mac512_1 = crypto:hmac_final(Case4Ctx512_2), - ?line Case4Mac512_2 = crypto:sha512_mac(Case4Key, Case4Data), - ?line Case4Mac512_3 = crypto:hmac(sha512, Case4Key, Case4Data), - ?line m(Case4Exp512, Case4Mac512_1), - ?line m(Case4Exp512, Case4Mac512_2), - ?line m(Case4Exp512, Case4Mac512_3), - - %% Test Case 5 - Case5Key = binary:copy(<<16#0c>>, 20), - Case5Data = <<"Test With Truncation">>, - Case5Exp224 = hexstr2bin("0e2aea68a90c8d37c988bcdb9fca6fa8"), - Case5Exp256 = hexstr2bin("a3b6167473100ee06e0c796c2955552b"), - Case5Exp384 = hexstr2bin("3abf34c3503b2a23a46efc619baef897"), - Case5Exp512 = hexstr2bin("415fad6271580a531d4179bc891d87a6"), - - ?line Case5Ctx224 = crypto:hmac_init(sha224, Case5Key), - ?line Case5Ctx224_2 = crypto:hmac_update(Case5Ctx224, Case5Data), - ?line Case5Mac224_1 = crypto:hmac_final_n(Case5Ctx224_2, 16), - ?line Case5Mac224_2 = crypto:sha224_mac(Case5Key, Case5Data, 16), - ?line Case5Mac224_3 = crypto:hmac(sha224, Case5Key, Case5Data, 16), - ?line m(Case5Exp224, Case5Mac224_1), - ?line m(Case5Exp224, Case5Mac224_2), - ?line m(Case5Exp224, Case5Mac224_3), - - ?line Case5Ctx256 = crypto:hmac_init(sha256, Case5Key), - ?line Case5Ctx256_2 = crypto:hmac_update(Case5Ctx256, Case5Data), - ?line Case5Mac256_1 = crypto:hmac_final_n(Case5Ctx256_2, 16), - ?line Case5Mac256_2 = crypto:sha256_mac(Case5Key, Case5Data, 16), - ?line Case5Mac256_3 = crypto:hmac(sha256, Case5Key, Case5Data, 16), - ?line m(Case5Exp256, Case5Mac256_1), - ?line m(Case5Exp256, Case5Mac256_2), - ?line m(Case5Exp256, Case5Mac256_3), - - ?line Case5Ctx384 = crypto:hmac_init(sha384, Case5Key), - ?line Case5Ctx384_2 = crypto:hmac_update(Case5Ctx384, Case5Data), - ?line Case5Mac384_1 = crypto:hmac_final_n(Case5Ctx384_2, 16), - ?line Case5Mac384_2 = crypto:sha384_mac(Case5Key, Case5Data, 16), - ?line Case5Mac384_3 = crypto:hmac(sha384, Case5Key, Case5Data, 16), - ?line m(Case5Exp384, Case5Mac384_1), - ?line m(Case5Exp384, Case5Mac384_2), - ?line m(Case5Exp384, Case5Mac384_3), - - ?line Case5Ctx512 = crypto:hmac_init(sha512, Case5Key), - ?line Case5Ctx512_2 = crypto:hmac_update(Case5Ctx512, Case5Data), - ?line Case5Mac512_1 = crypto:hmac_final_n(Case5Ctx512_2, 16), - ?line Case5Mac512_2 = crypto:sha512_mac(Case5Key, Case5Data, 16), - ?line Case5Mac512_3 = crypto:hmac(sha512, Case5Key, Case5Data, 16), - ?line m(Case5Exp512, Case5Mac512_1), - ?line m(Case5Exp512, Case5Mac512_2), - ?line m(Case5Exp512, Case5Mac512_3), - - %% Test Case 6 - Case6Key = binary:copy(<<16#aa>>, 131), - Case6Data = <<"Test Using Larger Than Block-Size Key - Hash Key First">>, - Case6Exp224 = hexstr2bin("95e9a0db962095adaebe9b2d6f0dbce2" - "d499f112f2d2b7273fa6870e"), - Case6Exp256 = hexstr2bin("60e431591ee0b67f0d8a26aacbf5b77f" - "8e0bc6213728c5140546040f0ee37f54"), - Case6Exp384 = hexstr2bin("4ece084485813e9088d2c63a041bc5b4" - "4f9ef1012a2b588f3cd11f05033ac4c6" - "0c2ef6ab4030fe8296248df163f44952"), - Case6Exp512 = hexstr2bin("80b24263c7c1a3ebb71493c1dd7be8b4" - "9b46d1f41b4aeec1121b013783f8f352" - "6b56d037e05f2598bd0fd2215d6a1e52" - "95e64f73f63f0aec8b915a985d786598"), - - ?line Case6Ctx224 = crypto:hmac_init(sha224, Case6Key), - ?line Case6Ctx224_2 = crypto:hmac_update(Case6Ctx224, Case6Data), - ?line Case6Mac224_1 = crypto:hmac_final(Case6Ctx224_2), - ?line Case6Mac224_2 = crypto:sha224_mac(Case6Key, Case6Data), - ?line Case6Mac224_3 = crypto:hmac(sha224, Case6Key, Case6Data), - ?line m(Case6Exp224, Case6Mac224_1), - ?line m(Case6Exp224, Case6Mac224_2), - ?line m(Case6Exp224, Case6Mac224_3), - - ?line Case6Ctx256 = crypto:hmac_init(sha256, Case6Key), - ?line Case6Ctx256_2 = crypto:hmac_update(Case6Ctx256, Case6Data), - ?line Case6Mac256_1 = crypto:hmac_final(Case6Ctx256_2), - ?line Case6Mac256_2 = crypto:sha256_mac(Case6Key, Case6Data), - ?line Case6Mac256_3 = crypto:hmac(sha256, Case6Key, Case6Data), - ?line m(Case6Exp256, Case6Mac256_1), - ?line m(Case6Exp256, Case6Mac256_2), - ?line m(Case6Exp256, Case6Mac256_3), - - ?line Case6Ctx384 = crypto:hmac_init(sha384, Case6Key), - ?line Case6Ctx384_2 = crypto:hmac_update(Case6Ctx384, Case6Data), - ?line Case6Mac384_1 = crypto:hmac_final(Case6Ctx384_2), - ?line Case6Mac384_2 = crypto:sha384_mac(Case6Key, Case6Data), - ?line Case6Mac384_3 = crypto:hmac(sha384, Case6Key, Case6Data), - ?line m(Case6Exp384, Case6Mac384_1), - ?line m(Case6Exp384, Case6Mac384_2), - ?line m(Case6Exp384, Case6Mac384_3), - - ?line Case6Ctx512 = crypto:hmac_init(sha512, Case6Key), - ?line Case6Ctx512_2 = crypto:hmac_update(Case6Ctx512, Case6Data), - ?line Case6Mac512_1 = crypto:hmac_final(Case6Ctx512_2), - ?line Case6Mac512_2 = crypto:sha512_mac(Case6Key, Case6Data), - ?line Case6Mac512_3 = crypto:hmac(sha512, Case6Key, Case6Data), - ?line m(Case6Exp512, Case6Mac512_1), - ?line m(Case6Exp512, Case6Mac512_2), - ?line m(Case6Exp512, Case6Mac512_3), - +hmac_rfc4231_sha256(doc) -> + ["Generate an HMAC using crypto:sha256_mac, hmac, and hmac_init, hmac_update, and hmac_final. " + "Testvectors are take from RFC4231." ]; +hmac_rfc4231_sha256(suite) -> + []; +hmac_rfc4231_sha256(Config) when is_list(Config) -> + if_supported(sha256, fun() -> hmac_rfc4231_sha256_do() end). + +hmac_rfc4231_sha384(doc) -> + ["Generate an HMAC using crypto:sha384_mac, hmac, and hmac_init, hmac_update, and hmac_final. " + "Testvectors are take from RFC4231." ]; +hmac_rfc4231_sha384(suite) -> + []; +hmac_rfc4231_sha384(Config) when is_list(Config) -> + if_supported(sha384, fun() -> hmac_rfc4231_sha384_do() end). + +hmac_rfc4231_sha512(doc) -> + ["Generate an HMAC using crypto:sha512_mac, hmac, and hmac_init, hmac_update, and hmac_final. " + "Testvectors are take from RFC4231." ]; +hmac_rfc4231_sha512(suite) -> + []; +hmac_rfc4231_sha512(Config) when is_list(Config) -> + if_supported(sha512, fun() -> hmac_rfc4231_sha512_do() end). + +hmac_rfc4231_case(Hash, HashFun, case1, Exp) -> + %% Test 1 + Key = binary:copy(<<16#0b>>, 20), + Data = <<"Hi There">>, + hmac_rfc4231_case(Hash, HashFun, Key, Data, Exp); + +hmac_rfc4231_case(Hash, HashFun, case2, Exp) -> + %% Test 2 + Key = <<"Jefe">>, + Data = <<"what do ya want for nothing?">>, + hmac_rfc4231_case(Hash, HashFun, Key, Data, Exp); + +hmac_rfc4231_case(Hash, HashFun, case3, Exp) -> + %% Test 3 + Key = binary:copy(<<16#aa>>, 20), + Data = binary:copy(<<16#dd>>, 50), + hmac_rfc4231_case(Hash, HashFun, Key, Data, Exp); + +hmac_rfc4231_case(Hash, HashFun, case4, Exp) -> + %% Test 4 + Key = list_to_binary(lists:seq(1, 16#19)), + Data = binary:copy(<<16#cd>>, 50), + hmac_rfc4231_case(Hash, HashFun, Key, Data, Exp); + +hmac_rfc4231_case(Hash, HashFun, case5, Exp) -> + %% Test 5 + Key = binary:copy(<<16#0c>>, 20), + Data = <<"Test With Truncation">>, + hmac_rfc4231_case(Hash, HashFun, Key, Data, 16, Exp); + +hmac_rfc4231_case(Hash, HashFun, case6, Exp) -> + %% Test 6 + Key = binary:copy(<<16#aa>>, 131), + Data = <<"Test Using Larger Than Block-Size Key - Hash Key First">>, + hmac_rfc4231_case(Hash, HashFun, Key, Data, Exp); + +hmac_rfc4231_case(Hash, HashFun, case7, Exp) -> %% Test Case 7 - Case7Key = binary:copy(<<16#aa>>, 131), - Case7Data = <<"This is a test using a larger than block-size key and a larger t", - "han block-size data. The key needs to be hashed before being use", - "d by the HMAC algorithm.">>, - Case7Exp224 = hexstr2bin("3a854166ac5d9f023f54d517d0b39dbd" - "946770db9c2b95c9f6f565d1"), - Case7Exp256 = hexstr2bin("9b09ffa71b942fcb27635fbcd5b0e944" - "bfdc63644f0713938a7f51535c3a35e2"), - Case7Exp384 = hexstr2bin("6617178e941f020d351e2f254e8fd32c" - "602420feb0b8fb9adccebb82461e99c5" - "a678cc31e799176d3860e6110c46523e"), - Case7Exp512 = hexstr2bin("e37b6a775dc87dbaa4dfa9f96e5e3ffd" - "debd71f8867289865df5a32d20cdc944" - "b6022cac3c4982b10d5eeb55c3e4de15" - "134676fb6de0446065c97440fa8c6a58"), - - ?line Case7Ctx224 = crypto:hmac_init(sha224, Case7Key), - ?line Case7Ctx224_2 = crypto:hmac_update(Case7Ctx224, Case7Data), - ?line Case7Mac224_1 = crypto:hmac_final(Case7Ctx224_2), - ?line Case7Mac224_2 = crypto:sha224_mac(Case7Key, Case7Data), - ?line Case7Mac224_3 = crypto:hmac(sha224, Case7Key, Case7Data), - ?line m(Case7Exp224, Case7Mac224_1), - ?line m(Case7Exp224, Case7Mac224_2), - ?line m(Case7Exp224, Case7Mac224_3), - - ?line Case7Ctx256 = crypto:hmac_init(sha256, Case7Key), - ?line Case7Ctx256_2 = crypto:hmac_update(Case7Ctx256, Case7Data), - ?line Case7Mac256_1 = crypto:hmac_final(Case7Ctx256_2), - ?line Case7Mac256_2 = crypto:sha256_mac(Case7Key, Case7Data), - ?line Case7Mac256_3 = crypto:hmac(sha256, Case7Key, Case7Data), - ?line m(Case7Exp256, Case7Mac256_1), - ?line m(Case7Exp256, Case7Mac256_2), - ?line m(Case7Exp256, Case7Mac256_3), - - ?line Case7Ctx384 = crypto:hmac_init(sha384, Case7Key), - ?line Case7Ctx384_2 = crypto:hmac_update(Case7Ctx384, Case7Data), - ?line Case7Mac384_1 = crypto:hmac_final(Case7Ctx384_2), - ?line Case7Mac384_2 = crypto:sha384_mac(Case7Key, Case7Data), - ?line Case7Mac384_3 = crypto:hmac(sha384, Case7Key, Case7Data), - ?line m(Case7Exp384, Case7Mac384_1), - ?line m(Case7Exp384, Case7Mac384_2), - ?line m(Case7Exp384, Case7Mac384_3), - - ?line Case7Ctx512 = crypto:hmac_init(sha512, Case7Key), - ?line Case7Ctx512_2 = crypto:hmac_update(Case7Ctx512, Case7Data), - ?line Case7Mac512_1 = crypto:hmac_final(Case7Ctx512_2), - ?line Case7Mac512_2 = crypto:sha512_mac(Case7Key, Case7Data), - ?line Case7Mac512_3 = crypto:hmac(sha512, Case7Key, Case7Data), - ?line m(Case7Exp512, Case7Mac512_1), - ?line m(Case7Exp512, Case7Mac512_2), - ?line m(Case7Exp512, Case7Mac512_3). + Key = binary:copy(<<16#aa>>, 131), + Data = <<"This is a test using a larger than block-size key and a larger t", + "han block-size data. The key needs to be hashed before being use", + "d by the HMAC algorithm.">>, + hmac_rfc4231_case(Hash, HashFun, Key, Data, Exp). + +hmac_rfc4231_case(Hash, HashFun, Key, Data, Exp) -> + ?line Ctx = crypto:hmac_init(Hash, Key), + ?line Ctx2 = crypto:hmac_update(Ctx, Data), + ?line Mac1 = crypto:hmac_final(Ctx2), + ?line Mac2 = crypto:HashFun(Key, Data), + ?line Mac3 = crypto:hmac(Hash, Key, Data), + ?line m(Exp, Mac1), + ?line m(Exp, Mac2), + ?line m(Exp, Mac3). + +hmac_rfc4231_case(Hash, HashFun, Key, Data, Trunc, Exp) -> + ?line Ctx = crypto:hmac_init(Hash, Key), + ?line Ctx2 = crypto:hmac_update(Ctx, Data), + ?line Mac1 = crypto:hmac_final_n(Ctx2, Trunc), + ?line Mac2 = crypto:HashFun(Key, Data, Trunc), + ?line Mac3 = crypto:hmac(Hash, Key, Data, Trunc), + ?line m(Exp, Mac1), + ?line m(Exp, Mac2), + ?line m(Exp, Mac3). + +hmac_rfc4231_sha224_do() -> + Case1 = hexstr2bin("896fb1128abbdf196832107cd49df33f" + "47b4b1169912ba4f53684b22"), + Case2 = hexstr2bin("a30e01098bc6dbbf45690f3a7e9e6d0f" + "8bbea2a39e6148008fd05e44"), + Case3 = hexstr2bin("7fb3cb3588c6c1f6ffa9694d7d6ad264" + "9365b0c1f65d69d1ec8333ea"), + Case4 = hexstr2bin("6c11506874013cac6a2abc1bb382627c" + "ec6a90d86efc012de7afec5a"), + Case5 = hexstr2bin("0e2aea68a90c8d37c988bcdb9fca6fa8"), + Case6 = hexstr2bin("95e9a0db962095adaebe9b2d6f0dbce2" + "d499f112f2d2b7273fa6870e"), + Case7 = hexstr2bin("3a854166ac5d9f023f54d517d0b39dbd" + "946770db9c2b95c9f6f565d1"), + hmac_rfc4231_cases_do(sha224, sha224_mac, [Case1, Case2, Case3, Case4, Case5, Case6, Case7]). + +hmac_rfc4231_sha256_do() -> + Case1 = hexstr2bin("b0344c61d8db38535ca8afceaf0bf12b" + "881dc200c9833da726e9376c2e32cff7"), + Case2 = hexstr2bin("5bdcc146bf60754e6a042426089575c7" + "5a003f089d2739839dec58b964ec3843"), + Case3 = hexstr2bin("773ea91e36800e46854db8ebd09181a7" + "2959098b3ef8c122d9635514ced565fe"), + Case4 = hexstr2bin("82558a389a443c0ea4cc819899f2083a" + "85f0faa3e578f8077a2e3ff46729665b"), + Case5 = hexstr2bin("a3b6167473100ee06e0c796c2955552b"), + Case6 = hexstr2bin("60e431591ee0b67f0d8a26aacbf5b77f" + "8e0bc6213728c5140546040f0ee37f54"), + Case7 = hexstr2bin("9b09ffa71b942fcb27635fbcd5b0e944" + "bfdc63644f0713938a7f51535c3a35e2"), + hmac_rfc4231_cases_do(sha256, sha256_mac, [Case1, Case2, Case3, Case4, Case5, Case6, Case7]). + +hmac_rfc4231_sha384_do() -> + Case1 = hexstr2bin("afd03944d84895626b0825f4ab46907f" + "15f9dadbe4101ec682aa034c7cebc59c" + "faea9ea9076ede7f4af152e8b2fa9cb6"), + Case2 = hexstr2bin("af45d2e376484031617f78d2b58a6b1b" + "9c7ef464f5a01b47e42ec3736322445e" + "8e2240ca5e69e2c78b3239ecfab21649"), + Case3 = hexstr2bin("88062608d3e6ad8a0aa2ace014c8a86f" + "0aa635d947ac9febe83ef4e55966144b" + "2a5ab39dc13814b94e3ab6e101a34f27"), + Case4 = hexstr2bin("3e8a69b7783c25851933ab6290af6ca7" + "7a9981480850009cc5577c6e1f573b4e" + "6801dd23c4a7d679ccf8a386c674cffb"), + Case5 = hexstr2bin("3abf34c3503b2a23a46efc619baef897"), + Case6 = hexstr2bin("4ece084485813e9088d2c63a041bc5b4" + "4f9ef1012a2b588f3cd11f05033ac4c6" + "0c2ef6ab4030fe8296248df163f44952"), + Case7 = hexstr2bin("6617178e941f020d351e2f254e8fd32c" + "602420feb0b8fb9adccebb82461e99c5" + "a678cc31e799176d3860e6110c46523e"), + hmac_rfc4231_cases_do(sha384, sha384_mac, [Case1, Case2, Case3, Case4, Case5, Case6, Case7]). + +hmac_rfc4231_sha512_do() -> + Case1 = hexstr2bin("87aa7cdea5ef619d4ff0b4241a1d6cb0" + "2379f4e2ce4ec2787ad0b30545e17cde" + "daa833b7d6b8a702038b274eaea3f4e4" + "be9d914eeb61f1702e696c203a126854"), + Case2 = hexstr2bin("164b7a7bfcf819e2e395fbe73b56e0a3" + "87bd64222e831fd610270cd7ea250554" + "9758bf75c05a994a6d034f65f8f0e6fd" + "caeab1a34d4a6b4b636e070a38bce737"), + Case3 = hexstr2bin("fa73b0089d56a284efb0f0756c890be9" + "b1b5dbdd8ee81a3655f83e33b2279d39" + "bf3e848279a722c806b485a47e67c807" + "b946a337bee8942674278859e13292fb"), + Case4 = hexstr2bin("b0ba465637458c6990e5a8c5f61d4af7" + "e576d97ff94b872de76f8050361ee3db" + "a91ca5c11aa25eb4d679275cc5788063" + "a5f19741120c4f2de2adebeb10a298dd"), + Case5 = hexstr2bin("415fad6271580a531d4179bc891d87a6"), + Case6 = hexstr2bin("80b24263c7c1a3ebb71493c1dd7be8b4" + "9b46d1f41b4aeec1121b013783f8f352" + "6b56d037e05f2598bd0fd2215d6a1e52" + "95e64f73f63f0aec8b915a985d786598"), + Case7 = hexstr2bin("e37b6a775dc87dbaa4dfa9f96e5e3ffd" + "debd71f8867289865df5a32d20cdc944" + "b6022cac3c4982b10d5eeb55c3e4de15" + "134676fb6de0446065c97440fa8c6a58"), + hmac_rfc4231_cases_do(sha512, sha512_mac, [Case1, Case2, Case3, Case4, Case5, Case6, Case7]). + +hmac_rfc4231_cases_do(Hash, HashFun, CasesData) -> + hmac_rfc4231_cases_do(Hash, HashFun, [case1, case2, case3, case4, case5, case6, case7], CasesData). + +hmac_rfc4231_cases_do(_Hash, _HashFun, _, []) -> + ok; +hmac_rfc4231_cases_do(Hash, HashFun, [C|Cases], [D|CasesData]) -> + hmac_rfc4231_case(Hash, HashFun, C, D), + hmac_rfc4231_cases_do(Hash, HashFun, Cases, CasesData). hmac_update_md5_io(doc) -> ["Generate an MD5 HMAC using hmac_init, hmac_update, and hmac_final. " @@ -1026,7 +855,7 @@ sha256(doc) -> sha256(suite) -> []; sha256(Config) when is_list(Config) -> - if_098(fun() -> sha256_do() end). + if_supported(sha256, fun() -> sha256_do() end). sha256_do() -> ?line m(crypto:sha256("abc"), @@ -1045,7 +874,7 @@ sha256_update(doc) -> sha256_update(suite) -> []; sha256_update(Config) when is_list(Config) -> - if_098(fun() -> sha256_update_do() end). + if_supported(sha256, fun() -> sha256_update_do() end). sha256_update_do() -> ?line Ctx = crypto:sha256_init(), @@ -1064,7 +893,7 @@ sha512(doc) -> sha512(suite) -> []; sha512(Config) when is_list(Config) -> - if_098(fun() -> sha512_do() end). + if_supported(sha512, fun() -> sha512_do() end). sha512_do() -> ?line m(crypto:sha512("abc"), @@ -1085,7 +914,7 @@ sha512_update(doc) -> sha512_update(suite) -> []; sha512_update(Config) when is_list(Config) -> - if_098(fun() -> sha512_update_do() end). + if_supported(sha512, fun() -> sha512_update_do() end). sha512_update_do() -> ?line Ctx = crypto:sha512_init(), @@ -2272,8 +2101,8 @@ worker_loop(N, Config) -> aes_cfb, aes_cbc, des_cbc_iter, rand_uniform_test, strong_rand_test, rsa_verify_test, exor_test, rc4_test, rc4_stream_test, mod_exp_test, hmac_update_md5, hmac_update_sha, hmac_update_sha256, hmac_update_sha512, - hmac_rfc2202, hmac_rfc4231, - aes_ctr_stream }, + hmac_rfc2202, hmac_rfc4231_sha224, hmac_rfc4231_sha256, hmac_rfc4231_sha384, + hmac_rfc4231_sha512, aes_ctr_stream }, F = element(random:uniform(size(Funcs)),Funcs), %%io:format("worker ~p calling ~p\n",[self(),F]), @@ -2408,10 +2237,10 @@ openssl_version() -> undefined end. -if_098(Fun) -> - case openssl_version() of - V when V < 16#908000 -> - {skipped,"OpenSSL version too old"}; +if_supported(Algorithm, Fun) -> + case proplists:get_bool(Algorithm, crypto:algorithms()) of + true -> + Fun(); _ -> - Fun() + {skipped, io:format("~s not spupported", [Algorithm])} end. -- cgit v1.2.3 From 45bbae42ef31a478487c8be19ddb44f34823fe57 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 27 Mar 2013 10:29:57 +0100 Subject: crypto: New SRP API Adjust API to better fit in with similar funtions in crypto --- lib/crypto/c_src/crypto.c | 8 +- lib/crypto/doc/src/crypto.xml | 138 +++++++++++++++--------------- lib/crypto/src/crypto.erl | 178 +++++++++++++++++++++++++++++---------- lib/crypto/test/crypto_SUITE.erl | 112 ++++++++++++------------ 4 files changed, 267 insertions(+), 169 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 47a577085c..fac77308f6 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2010-2012. All Rights Reserved. + * Copyright Ericsson AB 2010-2013. 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 @@ -210,7 +210,7 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM srp_client_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM srp_server_secret(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM srp_server_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -329,7 +329,7 @@ static ErlNifFunc nif_funcs[] = { {"dh_compute_key_nif", 3, dh_compute_key_nif}, {"srp_value_B_nif", 5, srp_value_B_nif}, {"srp_client_secret_nif", 7, srp_client_secret_nif}, - {"srp_server_secret", 5, srp_server_secret}, + {"srp_server_secret_nif", 5, srp_server_secret_nif}, {"bf_cfb64_crypt", 4, bf_cfb64_crypt}, {"bf_cbc_crypt", 4, bf_cbc_crypt}, {"bf_ecb_crypt", 3, bf_ecb_crypt}, @@ -2537,7 +2537,7 @@ static ERL_NIF_TERM srp_client_secret_nif(ErlNifEnv* env, int argc, const ERL_NI return ret; } -static ERL_NIF_TERM srp_server_secret(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static ERL_NIF_TERM srp_server_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Verifier, b, u, A, Prime) */ /* = (A * v^u) ^ b % N diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index e27cc486ec..f30a058ca4 100755 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -63,6 +63,11 @@

dss: Digital Signature Standard (FIPS 186-2)

+ +

srp: Secure Remote Password Protocol (RFC 2945)

+
+ +

The above publications can be found at NIST publications, at IETF.

@@ -1275,82 +1280,83 @@ Mpint() = >]]>
- srp_value_B(Multiplier, Verifier, Generator, Exponent, Prime) -> ValueB - Computes the SRP function: B = k*v + g^b % N - - Verifier (v), Generator (g), Exponent (b), Prime (N), ValueB (B) = binary() - Multiplier (k) = integer() | binary() - - -

Computes the SRP value B according to RFC-2945, Sect. 3 and RFC-5054, Sect. 2.5.3

-

B = k*v + g^b % N

-
-
- - - srp_client_secret(A, U, B, Multiplier, Generator, Exponent, Prime) -> Secret - Computes the SRP client secret - - A (a), U (u), B, Multiplier (k), Generator (g), Exponent (x), Prime (N), Secret = binary() - Multiplier (k) = integer() | binary() - - -

Computes the SRP client secret according to RFC-2945, Sect. 3 and RFC-5054, Sect. 2.6

-

Secret = (B - (k * g^x)) ^ (a + (u * x)) % N

-
-
- - - srp_server_secret(Verifier, B, U, A, Prime) -> Secret - Computes the SRP host secret - - Verifier (v), B (b), U (u), A, Prime (N), Secret = binary() - - -

Computes the SRP host secret according to RFC-2945, Sect. 3 and RFC-5054, Sect. 2.6

-

Secret = (A * v^u) ^ b % N

-
-
- - - srp3_value_u(B) -> Result - Computes the SRP3-SHA value u - - B = binary() - Result = integer() - - -

Computes the SRP-3 value u according to RFC-2945, Sect. 3 -

-
-
- - - srp6_value_u(A, B, Prime) -> Result - Computes the SRP6a value u as u = SHA1(PAD(A) | PAD(B)) + srp_generate_key(Generator, Prime, Version) -> {PublicKey, PrivateKey} + srp_generate_key(Generator, Prime, Version, Private) -> {PublicKey, PrivateKey} + srp_generate_key(Verifier, Generator, Prime, Version) -> {PublicKey, PrivateKey} + srp_generate_key(Verifier, Generator, Prime, Version, Private) -> {PublicKey, PrivateKey} + Generates SRP public keys - A, B, Prime = binary() - Result = integer() + Verifier = binary() + Parameter v from SRP design + + Generator = binary() + Parameter g from SRP design + + Prime = binary() + Parameter N from SRP design + + Version = '3' | '6' | '6a' + SRP version, TLS SRP cipher suites uses '6a'. + PublicKey = binary() + Parameter A or B from SRP design + PrivateKey = binary() - generated if not supplied + Parameter a or b from SRP design -

Computes the SRP-6 value u according to RFC-5054, Sect. 2.6 -

+

Generates SRP public keys

- srp6a_multiplier(Generator, Prime) -> Result - Computes the SRP-SHA function: k = SHA1(N | PAD(g)) - - Generator, Prime = binary() - Result = integer() - - -

Computes the SRP-6a function SHA1(N | PAD(g)) as the multiplier + srp_compute_key(DerivedKey, Prime, Generator, + ClientPublic, ClientPrivate, ServerPublic, Version) -> SessionKey + srp_compute_key(DerivedKey, Prime, Generator, + ClientPublic, ClientPrivate, ServerPublic, Version, Scrambler) -> SessionKey + srp_compute_key(Verifier, Prime, + ClientPublic, ServerPublic, ServerPrivate, Version, Scrambler)-> SessionKey + srp_compute_key(Verifier, Prime, + ClientPublic, ServerPublic, ServerPrivate, Version) -> SessionKey + + Computes SRP session key + + DerivedKey = binary() + Parameter x from SRP design + + Verifier = binary() + Parameter v from SRP design + + Prime = binary() + Parameter N from SRP design + + Generator = binary() + Parameter g from SRP design + + ClientPublic = binary() + Parameter A from SRP design + + ClientPrivate = binary() + Parameter a from SRP design + + ServerPublic = binary() + Parameter B from SRP design + + ServerPrivate = binary() + Parameter b from SRP design + + Version = '3' | '6' | '6a' + SRP version, TLS SRP cipher suites uses '6a'. + SessionKey = binary() + Result K from SRP design + + + +

+ Computes the SRP session key (shared secret). Also used + as premaster secret by TLS-SRP ciher suites.

- + exor(Data1, Data2) -> Result XOR data diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index e8867236ac..1d0a9943c3 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -58,9 +58,8 @@ -export([rand_bytes/1, rand_bytes/3, rand_uniform/2]). -export([strong_rand_bytes/1, strong_rand_mpint/3]). -export([mod_exp/3, mod_exp_prime/3, mpint/1, erlint/1]). --export([srp_value_B/5]). --export([srp3_value_u/1, srp6_value_u/3, srp6a_multiplier/2]). --export([srp_client_secret/7, srp_server_secret/5]). +-export([srp_generate_key/4, srp_generate_key/3, + srp_generate_key/5, srp_compute_key/6, srp_compute_key/7, srp_compute_key/8]). %% -export([idea_cbc_encrypt/3, idea_cbc_decrypt/3]). -export([aes_cbc_128_encrypt/3, aes_cbc_128_decrypt/3]). @@ -113,9 +112,7 @@ hash, hash_init, hash_update, hash_final, hmac, hmac_init, hmac_update, hmac_final, hmac_final_n, info, rc2_cbc_encrypt, rc2_cbc_decrypt, - srp_value_B, - srp3_value_u, srp6_value_u, srp6a_multiplier, - srp_client_secret, srp_server_secret, + srp_generate_key, srp_compute_key, info_lib, algorithms]). -type rsa_digest_type() :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'. @@ -801,7 +798,7 @@ mod_exp(Base, Exponent, Modulo) mod_exp(Base, Exponent, Modulo) -> mod_exp_nif(mpint_to_bin(Base),mpint_to_bin(Exponent),mpint_to_bin(Modulo), 4). --spec mod_exp_prime(binary(), binary(), binary()) -> binary(). +-spec mod_exp_prime(binary(), binary(), binary()) -> binary() | error. mod_exp_prime(Base, Exponent, Prime) -> case mod_exp_nif(Base, Exponent, Prime, 0) of <<0>> -> error; @@ -1077,49 +1074,130 @@ dh_compute_key(OthersPublicKey, MyPrivateKey, DHParameters) -> dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub. --spec srp_value_B(binary(), integer(), binary(), binary(), binary()) -> binary(). -srp_value_B(Multiplier, Verifier, Generator, Exponent, Prime) -> - srp_value_B_nif(srp_multiplier(Multiplier), Verifier, Generator, Exponent, Prime). +%%% SRP +-spec srp_generate_key(binary(), binary(), atom() | binary(), atom() | binary() ) -> {Public::binary(), Private::binary()}. +srp_generate_key(Verifier, Generator, Prime, Version) when is_binary(Verifier), + is_binary(Generator), + is_binary(Prime), + is_atom(Version) -> + Private = random_bytes(32), + server_srp_gen_key(Private, Verifier, Generator, Prime, Version); + +srp_generate_key(Generator, Prime, Version, Private) when is_binary(Generator), + is_binary(Prime), + is_atom(Version), + is_binary(Private) -> + client_srp_gen_key(Private, Generator, Prime). + +-spec srp_generate_key(binary(), binary(), binary(), atom(), binary()) -> {Public::binary(), Private::binary()}. +srp_generate_key(Verifier, Generator, Prime, Version, Private) when is_binary(Verifier), + is_binary(Generator), + is_binary(Prime), + is_atom(Version), + is_binary(Private) + -> + server_srp_gen_key(Private, Verifier, Generator, Prime, Version). + +-spec srp_generate_key(binary(), binary(), atom()) -> {Public::binary(), Private::binary()}. +srp_generate_key(Generator, Prime, Version) when is_binary(Generator), + is_binary(Prime), + is_atom(Version) -> + Private = random_bytes(32), + client_srp_gen_key(Private, Generator, Prime). + +-spec srp_compute_key(binary(), binary(), binary(), binary(), binary(), atom()| binary(), atom() | binary() ) -> binary(). +srp_compute_key(DerivedKey, Prime, Generator, ClientPublic, ClientPrivate, ServerPublic, Version) when + is_binary(Prime), + is_binary(Generator), + is_binary(ClientPublic), + is_binary(ClientPrivate), + is_binary(ServerPublic), + is_atom(Version) -> + Multiplier = srp_multiplier(Version, Generator, Prime), + Scrambler = srp_scrambler(Version, ClientPublic, ServerPublic, Prime), + srp_client_secret_nif(ClientPrivate, Scrambler, ServerPublic, Multiplier, + Generator, DerivedKey, Prime); + +srp_compute_key(Verifier, Prime, ClientPublic, ServerPublic, ServerPrivate, Version, Scrambler) when + is_binary(Verifier), + is_binary(Prime), + is_binary(ClientPublic), + is_binary(ServerPublic), + is_binary(ServerPrivate), + is_atom(Version), + is_binary(Scrambler) -> + srp_server_secret_nif(Verifier, ServerPrivate, Scrambler, ClientPublic, Prime). + +-spec srp_compute_key(binary(), binary(), binary(), binary(), binary(), binary(), atom(), binary()) -> binary(). +srp_compute_key(DerivedKey, Prime, Generator, ClientPublic, ClientPrivate, + ServerPublic, Version, Scrambler) when is_binary(DerivedKey), + is_binary(Prime), + is_binary(Generator), + is_binary(ClientPublic), + is_binary(ClientPrivate), + is_binary(ServerPublic), + is_atom(Version), + is_binary(Scrambler) -> + Multiplier = srp_multiplier(Version, Generator, Prime), + srp_client_secret_nif(ClientPrivate, Scrambler, ServerPublic, Multiplier, + Generator, DerivedKey, Prime). + +-spec srp_compute_key(binary(), binary(), binary(), binary(), binary(), atom()) -> binary(). +srp_compute_key(Verifier, Prime, ClientPublic, ServerPublic, ServerPrivate, Version) when + is_binary(Verifier), + is_binary(Prime), + is_binary(ClientPublic), + is_binary(ServerPublic), + is_binary(ServerPrivate), + is_atom(Version) -> + Scrambler = srp_scrambler(Version, ClientPublic, ServerPublic, Prime), + srp_server_secret_nif(Verifier, ServerPrivate, Scrambler, ClientPublic, Prime). -srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub. - --spec srp_client_secret(binary(), binary(), binary(), integer()|binary(), binary(), binary(), binary()) -> binary(). -srp_client_secret(A, U, B, Multiplier, Generator, Exponent, Prime) -> - srp_client_secret_nif(A, U, B, srp_multiplier(Multiplier), Generator, Exponent, Prime). +%% +%% LOCAL FUNCTIONS +%% -srp_client_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?nif_stub. +client_srp_gen_key(Private, Generator, Prime) -> + case mod_exp_prime(Generator, Private, Prime) of + error -> + error; + Public -> + {Public, Private} + end. --spec srp_server_secret(binary(), binary(), binary(), binary(), binary()) -> binary(). -srp_server_secret(_Verifier, _B, _U, _A, _Prime) -> ?nif_stub. +server_srp_gen_key(Private, Verifier, Generator, Prime, Version) -> + Multiplier = srp_multiplier(Version, Generator, Prime), + case srp_value_B_nif(Multiplier, Verifier, Generator, Private, Prime) of + error -> + error; + Public -> + {Public, Private} + end. --spec srp6a_multiplier(binary(), binary()) -> binary(). -srp6a_multiplier(Generator, Prime) -> - %% k = SHA1(N | PAD(g)) +srp_multiplier('6a', Generator, Prime) -> + %% k = SHA1(N | PAD(g)) from http://srp.stanford.edu/design.html C0 = sha_init(), C1 = sha_update(C0, Prime), C2 = sha_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)), - sha_final(C2). - --spec srp3_value_u(binary()) -> binary(). -srp3_value_u(B) -> + sha_final(C2); +srp_multiplier('6', _, _) -> + <<3/integer>>; +srp_multiplier('3', _, _) -> + <<1/integer>>. + +srp_scrambler(Version, ClientPublic, ServerPublic, Prime) when Version == '6'; Version == '6a'-> + %% SHA1(PAD(A) | PAD(B)) from http://srp.stanford.edu/design.html + PadLength = erlang:byte_size(Prime), + C0 = sha_init(), + C1 = sha_update(C0, srp_pad_to(PadLength, ClientPublic)), + C2 = sha_update(C1, srp_pad_to(PadLength, ServerPublic)), + sha_final(C2); +srp_scrambler('3', _, ServerPublic, _Prime) -> %% The parameter u is a 32-bit unsigned integer which takes its value %% from the first 32 bits of the SHA1 hash of B, MSB first. - <> = sha(B), + <> = sha(ServerPublic), U. --spec srp6_value_u(binary(), binary(), binary()) -> binary(). -srp6_value_u(A, B, Prime) -> - %% SHA1(PAD(A) | PAD(B)) - PadLength = erlang:byte_size(Prime), - C0 = sha_init(), - C1 = sha_update(C0, srp_pad_to(PadLength, A)), - C2 = sha_update(C1, srp_pad_to(PadLength, B)), - sha_final(C2). - -%% -%% LOCAL FUNCTIONS -%% - srp_pad_length(Width, Length) -> (Width - Length rem Width) rem Width. @@ -1129,10 +1207,11 @@ srp_pad_to(Width, Binary) -> N -> << 0:(N*8), Binary/binary>> end. -srp_multiplier(Multiplier) when is_binary(Multiplier) -> - Multiplier; -srp_multiplier(Multiplier) when is_integer(Multiplier) -> - int_to_bin_pos(Multiplier). +srp_server_secret_nif(_Verifier, _B, _U, _A, _Prime) -> ?nif_stub. + +srp_client_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?nif_stub. + +srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub. %% large integer in a binary with 32bit length %% MP representaion (SSH2) @@ -1160,8 +1239,8 @@ mpint_pos(X) -> int_to_bin(X) when X < 0 -> int_to_bin_neg(X, []); int_to_bin(X) -> int_to_bin_pos(X, []). -int_to_bin_pos(X) when X >= 0 -> - int_to_bin_pos(X, []). +%%int_to_bin_pos(X) when X >= 0 -> +%% int_to_bin_pos(X, []). int_to_bin_pos(0,Ds=[_|_]) -> list_to_binary(Ds); @@ -1187,3 +1266,12 @@ erlint(<>) -> mpint_to_bin(<>) -> Bin. + +random_bytes(N) -> + try strong_rand_bytes(N) of + RandBytes -> + RandBytes + catch + error:low_entropy -> + rand_bytes(N) + end. diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 92d16a438d..08ecad3233 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -1860,42 +1860,45 @@ srp3(Config) when is_list(Config) -> "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A" "FD5138FE8376435B9FC61D2FC0EB06E3"), Generator = <<2>>, - Multiplier = 1, + Version = '3', + Scrambler = hexstr2bin("02E2476A"), + %% X = hexstr2bin("96E54AB0CD4C5123EDCFA4A1502918AAD3C9E2A8"), Verifier = hexstr2bin("96EB5F13621D911AA1CA405DE9C64217D4108EEEECAFFE500034FE0E" "C031E42C8714667C161BCE0E7996F7DDE1B63824C130D2D7286C08C0" "49758420735961347112AE102A3F23B3F687F8FEE0DF2BFAF933C608" "D6FE5B5EEE3116FE54016E065BF8E8C9FDBBC08719231AC215149140" "519E8FDD9AA4F410C28A58AF42974D2D"), - ClntPriv = hexstr2bin("6411DE75538BED8170677D577D0608F39112BC95B503C447EB6AC945" + ClientPrivate = hexstr2bin("6411DE75538BED8170677D577D0608F39112BC95B503C447EB6AC945" "49C75C7B"), - SrvrPriv = hexstr2bin("85E44A6F694DBE676145DB245A045CD37C99F05C562C7840A31F270D" + ServerPrivate = hexstr2bin("85E44A6F694DBE676145DB245A045CD37C99F05C562C7840A31F270D" "9AADCF8B"), - ClntPub = hexstr2bin("B22B1FFA2244B8CB94F3A9080F419CAEAB0DBA93EA1965B5E84587EE" + ClientPublic = hexstr2bin("B22B1FFA2244B8CB94F3A9080F419CAEAB0DBA93EA1965B5E84587EE" "55C79E7A118865DC59B9D0353362C2A8261E7C1B0D221A0E233C2AD1" "640DACBB8664CBC9733EAC392DA7800142860380C3FC573C3C064329" "CF54063FD114C7210E9CB3A611EA8002B1844B698F930D95D143899B" "948A090E0C25938E5F84067D1883DC63"), - SrvrPub = hexstr2bin("93A8C4D8B7F7395ADCFD4ABA37B015124513D3F37B3E85EB23064BE5" + ServerPublic = hexstr2bin("93A8C4D8B7F7395ADCFD4ABA37B015124513D3F37B3E85EB23064BE5" "F53C0AE32FFB9D8C0AA0DCFFA74D632DD67DEBB5C35AAE9812286CC8" "C43CC176ECBC6D3F447594D9554E995B2509127BF88FADDDA4982D03" "8EC3001320712D3B1269308CE70F319B2295FA57674F03A2D993CFB1" "F84C35B7D0C012FA73CD4C8F7D5A71C7"), - U = hexstr2bin("02E2476A"), - PremasterSecret = hexstr2bin("C29A986C4D521BBC66428ED11D994CD7431574A6184B83CDCC345092" - "791E75748A1D38CAC4BD14760F0D2694B711236419240FF2F172454C" - "46ABF4FF39498DAFDD2C82924F7D7BD76CDFCE688C77D93F18A65409" - "9176A9192615DC0277AE7C12F1F6A7F6563FCA11675D809AF578BDE5" - "2B51E05D440B63099A017A0B45044801"), + SessionKey = hexstr2bin("C29A986C4D521BBC66428ED11D994CD7431574A6184B83CDCC345092" + "791E75748A1D38CAC4BD14760F0D2694B711236419240FF2F172454C" + "46ABF4FF39498DAFDD2C82924F7D7BD76CDFCE688C77D93F18A65409" + "9176A9192615DC0277AE7C12F1F6A7F6563FCA11675D809AF578BDE5" + "2B51E05D440B63099A017A0B45044801"), UserPassHash = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]), - m(crypto:mod_exp_prime(Generator, UserPassHash, Prime), Verifier), - m(crypto:mod_exp_prime(Generator, ClntPriv, Prime), ClntPub), - m(crypto:srp3_value_u(SrvrPub), U), - m(crypto:srp_value_B(Multiplier, Verifier, Generator, SrvrPriv, Prime), SrvrPub), - m(crypto:srp_client_secret(ClntPriv, U, SrvrPub, Multiplier, Generator, UserPassHash, Prime), PremasterSecret), - m(crypto:srp_server_secret(Verifier, SrvrPriv, U, ClntPub, Prime), PremasterSecret), - ok. + Verifier = crypto:mod_exp_prime(Generator, UserPassHash, Prime), + ClientPublic = crypto:mod_exp_prime(Generator, ClientPrivate, Prime), + + {ClientPublic, ClientPrivate} = crypto:srp_generate_key(Generator, Prime, Version, ClientPrivate), + {ServerPublic, ServerPrivate} = crypto:srp_generate_key(Verifier, Generator, Prime, Version, ServerPrivate), + SessionKey = crypto:srp_compute_key(UserPassHash, Prime, Generator, ClientPublic, + ClientPrivate, ServerPublic, Version, Scrambler), + SessionKey = crypto:srp_compute_key(Verifier, Prime, ClientPublic, + ServerPublic, ServerPrivate, Version, Scrambler). srp6(doc) -> ["SRP-6 test vectors generated by http://srp.stanford.edu/demo/demo.html"]; @@ -1910,42 +1913,43 @@ srp6(Config) when is_list(Config) -> "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A" "FD5138FE8376435B9FC61D2FC0EB06E3"), Generator = <<2>>, - Multiplier = 3, - %% X = hexstr2bin("96E54AB0CD4C5123EDCFA4A1502918AAD3C9E2A8"), + Version = '6', + Scrambler = hexstr2bin("0A2534C0BF52A0DA9001EEC62CF2A546AB0908A7"), Verifier = hexstr2bin("96EB5F13621D911AA1CA405DE9C64217D4108EEEECAFFE500034FE0E" "C031E42C8714667C161BCE0E7996F7DDE1B63824C130D2D7286C08C0" "49758420735961347112AE102A3F23B3F687F8FEE0DF2BFAF933C608" "D6FE5B5EEE3116FE54016E065BF8E8C9FDBBC08719231AC215149140" "519E8FDD9AA4F410C28A58AF42974D2D"), - ClntPriv = hexstr2bin("6411DE75538BED8170677D577D0608F39112BC95B503C447EB6AC945" + ClientPrivate = hexstr2bin("6411DE75538BED8170677D577D0608F39112BC95B503C447EB6AC945" "49C75C7B"), - SrvrPriv = hexstr2bin("85E44A6F694DBE676145DB245A045CD37C99F05C562C7840A31F270D" + ServerPrivate = hexstr2bin("85E44A6F694DBE676145DB245A045CD37C99F05C562C7840A31F270D" "9AADCF8B"), - ClntPub = hexstr2bin("B22B1FFA2244B8CB94F3A9080F419CAEAB0DBA93EA1965B5E84587EE" + ClientPublic = hexstr2bin("B22B1FFA2244B8CB94F3A9080F419CAEAB0DBA93EA1965B5E84587EE" "55C79E7A118865DC59B9D0353362C2A8261E7C1B0D221A0E233C2AD1" "640DACBB8664CBC9733EAC392DA7800142860380C3FC573C3C064329" "CF54063FD114C7210E9CB3A611EA8002B1844B698F930D95D143899B" "948A090E0C25938E5F84067D1883DC63"), - SrvrPub = hexstr2bin("D2D07845CE7ECDB9845DD36B10ACD3598CC29049DE9F467F84CE16B6" + ServerPublic = hexstr2bin("D2D07845CE7ECDB9845DD36B10ACD3598CC29049DE9F467F84CE16B6" "D97A6DC567AF8B0F9FEDF74962400AD5C357951E64E67B641246F264" "C8DE6D9A72E554D6C8D3194548780A0C438A0FCC509CA88A14AA1DEB" "C0F09E4B37A965D1545DB4AD361346F3189B0EA569C06D326C4E4797" "9E381C748293B7C0591BE0BE419E053E"), - U = hexstr2bin("0A2534C0BF52A0DA9001EEC62CF2A546AB0908A7"), - PremasterSecret = hexstr2bin("19D22C19612874EBF1F2581F8EFCFDC44C6FDA3B87B0A73823D7E962" + SessionKey = hexstr2bin("19D22C19612874EBF1F2581F8EFCFDC44C6FDA3B87B0A73823D7E962" "554295D4E48D3A336523ADBDDD0EC8FB0F02687109E97E01C17C93CC" "7216F9CD8A4AC39F0429857D8D1023066614BDFCBCB89F59A0FEB81C" "72E992AAD89095A84B6A5FADA152369AB1E350A03693BEF044DF3EDF" "0C34741F4696C30E9F675D09F58ACBEB"), UserPassHash = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]), - m(crypto:mod_exp_prime(Generator, UserPassHash, Prime), Verifier), - m(crypto:mod_exp_prime(Generator, ClntPriv, Prime), ClntPub), - m(crypto:srp6_value_u(ClntPub, SrvrPub, Prime), U), - m(crypto:srp_value_B(Multiplier, Verifier, Generator, SrvrPriv, Prime), SrvrPub), - m(crypto:srp_client_secret(ClntPriv, U, SrvrPub, Multiplier, Generator, UserPassHash, Prime), PremasterSecret), - m(crypto:srp_server_secret(Verifier, SrvrPriv, U, ClntPub, Prime), PremasterSecret), - ok. + Verifier = crypto:mod_exp_prime(Generator, UserPassHash, Prime), + ClientPublic = crypto:mod_exp_prime(Generator, ClientPrivate, Prime), + + {ClientPublic, ClientPrivate} = crypto:srp_generate_key(Generator, Prime, Version, ClientPrivate), + {ServerPublic, ServerPrivate} = crypto:srp_generate_key(Verifier, Generator, Prime, Version, ServerPrivate), + SessionKey = crypto:srp_compute_key(UserPassHash, Prime, Generator, ClientPublic, + ClientPrivate, ServerPublic, Version, Scrambler), + SessionKey = crypto:srp_compute_key(Verifier, Prime, ClientPublic, + ServerPublic, ServerPrivate, Version, Scrambler). srp6a(doc) -> ["SRP-6a test vectors from RFC5054."]; @@ -1960,44 +1964,44 @@ srp6a(Config) when is_list(Config) -> "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A" "FD5138FE8376435B9FC61D2FC0EB06E3"), Generator = <<2>>, - Multiplier = hexstr2bin("7556AA045AEF2CDD07ABAF0F665C3E818913186F"), - %% X = hexstr2bin("94B7555AABE9127CC58CCF4993DB6CF84D16C124"), + Version = '6a', + Scrambler = hexstr2bin("CE38B9593487DA98554ED47D70A7AE5F462EF019"), Verifier = hexstr2bin("7E273DE8696FFC4F4E337D05B4B375BEB0DDE1569E8FA00A9886D812" "9BADA1F1822223CA1A605B530E379BA4729FDC59F105B4787E5186F5" "C671085A1447B52A48CF1970B4FB6F8400BBF4CEBFBB168152E08AB5" "EA53D15C1AFF87B2B9DA6E04E058AD51CC72BFC9033B564E26480D78" "E955A5E29E7AB245DB2BE315E2099AFB"), - ClntPriv = hexstr2bin("60975527035CF2AD1989806F0407210BC81EDC04E2762A56AFD529DD" + ClientPrivate = hexstr2bin("60975527035CF2AD1989806F0407210BC81EDC04E2762A56AFD529DD" "DA2D4393"), - SrvrPriv = hexstr2bin("E487CB59D31AC550471E81F00F6928E01DDA08E974A004F49E61F5D1" + ServerPrivate = hexstr2bin("E487CB59D31AC550471E81F00F6928E01DDA08E974A004F49E61F5D1" "05284D20"), - ClntPub = hexstr2bin("61D5E490F6F1B79547B0704C436F523DD0E560F0C64115BB72557EC4" + ClientPublic = hexstr2bin("61D5E490F6F1B79547B0704C436F523DD0E560F0C64115BB72557EC4" "4352E8903211C04692272D8B2D1A5358A2CF1B6E0BFCF99F921530EC" "8E39356179EAE45E42BA92AEACED825171E1E8B9AF6D9C03E1327F44" "BE087EF06530E69F66615261EEF54073CA11CF5858F0EDFDFE15EFEA" "B349EF5D76988A3672FAC47B0769447B"), - SrvrPub = hexstr2bin("BD0C61512C692C0CB6D041FA01BB152D4916A1E77AF46AE105393011" + ServerPublic = hexstr2bin("BD0C61512C692C0CB6D041FA01BB152D4916A1E77AF46AE105393011" "BAF38964DC46A0670DD125B95A981652236F99D9B681CBF87837EC99" "6C6DA04453728610D0C6DDB58B318885D7D82C7F8DEB75CE7BD4FBAA" "37089E6F9C6059F388838E7A00030B331EB76840910440B1B27AAEAE" "EB4012B7D7665238A8E3FB004B117B58"), - U = hexstr2bin("CE38B9593487DA98554ED47D70A7AE5F462EF019"), - - PremasterSecret = hexstr2bin("B0DC82BABCF30674AE450C0287745E7990A3381F63B387AAF271A10D" - "233861E359B48220F7C4693C9AE12B0A6F67809F0876E2D013800D6C" - "41BB59B6D5979B5C00A172B4A2A5903A0BDCAF8A709585EB2AFAFA8F" - "3499B200210DCC1F10EB33943CD67FC88A2F39A4BE5BEC4EC0A3212D" - "C346D7E474B29EDE8A469FFECA686E5A"), + + SessionKey = hexstr2bin("B0DC82BABCF30674AE450C0287745E7990A3381F63B387AAF271A10D" + "233861E359B48220F7C4693C9AE12B0A6F67809F0876E2D013800D6C" + "41BB59B6D5979B5C00A172B4A2A5903A0BDCAF8A709585EB2AFAFA8F" + "3499B200210DCC1F10EB33943CD67FC88A2F39A4BE5BEC4EC0A3212D" + "C346D7E474B29EDE8A469FFECA686E5A"), UserPassHash = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]), - m(crypto:mod_exp_prime(Generator, UserPassHash, Prime), Verifier), - m(crypto:mod_exp_prime(Generator, ClntPriv, Prime), ClntPub), - m(crypto:srp6a_multiplier(Generator, Prime), Multiplier), - m(crypto:srp6_value_u(ClntPub, SrvrPub, Prime), U), - m(crypto:srp_value_B(Multiplier, Verifier, Generator, SrvrPriv, Prime), SrvrPub), - m(crypto:srp_client_secret(ClntPriv, U, SrvrPub, Multiplier, Generator, UserPassHash, Prime), PremasterSecret), - m(crypto:srp_server_secret(Verifier, SrvrPriv, U, ClntPub, Prime), PremasterSecret), - ok. + Verifier = crypto:mod_exp_prime(Generator, UserPassHash, Prime), + {ClientPublic, ClientPrivate} = crypto:srp_generate_key(Generator, Prime, Version, ClientPrivate), + {ServerPublic, ServerPrivate} = crypto:srp_generate_key(Verifier, Generator, Prime, Version, ServerPrivate), + + SessionKey = crypto:srp_compute_key(UserPassHash, Prime, Generator, ClientPublic, + ClientPrivate, ServerPublic, Version, Scrambler), + SessionKey = crypto:srp_compute_key(Verifier, Prime, ClientPublic, + ServerPublic, ServerPrivate, Version, Scrambler). + %% %% exor_test(doc) -> -- cgit v1.2.3