aboutsummaryrefslogtreecommitdiffstats
path: root/lib/crypto
diff options
context:
space:
mode:
authorIngela Anderton Andin <[email protected]>2013-04-04 09:38:46 +0200
committerIngela Anderton Andin <[email protected]>2013-04-04 09:38:46 +0200
commitb8e72765305590eb7c89166ce261843d54c9bcde (patch)
tree1a2660241dccee3694a3c33d8f6e9969fb903030 /lib/crypto
parent8dba74ac7ff331a2c4870cc64b62dd4f168533eb (diff)
parent3f031c72a496e5b2af7fa9f07e25aec621dcf8f3 (diff)
downloadotp-b8e72765305590eb7c89166ce261843d54c9bcde.tar.gz
otp-b8e72765305590eb7c89166ce261843d54c9bcde.tar.bz2
otp-b8e72765305590eb7c89166ce261843d54c9bcde.zip
Merge branch 'ia/ssl/PSK-SRP' into maint
* ia/ssl/PSK-SRP: ssl: Use new SRP crypto API crypto: New SRP API CRYPTO: add algorithms/0 function that returns a list off compiled in crypto algorithms ssl: Add option to list all available ciper suites and enhanced documentation SSL: add documentation for PSK and SRP ciphers options SSL: enable hash_size values for sha224, sha384 and sha512 SSL: add tests for PSK and SRP ciphers SSL: add TLS-SRP (RFC 5054) cipher suites CRYPTO: add support for RFC-2945 SRP-3 and RFC-5054 SRP-6a authentication crypto: Refactor mod_exp_nif SSL: add TLS PSK (RFC 4279 and RFC 5487) cipher suites
Diffstat (limited to 'lib/crypto')
-rw-r--r--lib/crypto/c_src/crypto.c275
-rwxr-xr-xlib/crypto/doc/src/crypto.xml102
-rw-r--r--lib/crypto/src/crypto.erl244
-rw-r--r--lib/crypto/test/crypto_SUITE.erl731
4 files changed, 929 insertions, 423 deletions
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index e77e5fb8f0..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
@@ -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[]);
@@ -207,6 +208,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_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[]);
@@ -215,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,
@@ -247,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},
@@ -304,7 +310,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},
@@ -321,6 +327,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_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},
@@ -458,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
{
@@ -538,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">>}] */
@@ -1515,6 +1554,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;
@@ -1543,16 +1593,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 +1615,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);
@@ -2344,6 +2402,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) */
+/*
+ <premaster secret> = (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_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Verifier, b, u, A, Prime) */
+/*
+ <premaster secret> = (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..f30a058ca4 100755
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -63,6 +63,11 @@
<item>
<p>dss: Digital Signature Standard (FIPS 186-2)</p>
</item>
+ <item>
+ <p>srp: Secure Remote Password Protocol (RFC 2945)</p>
+ </item>
+
+
</list>
<p>The above publications can be found at <url href="http://csrc.nist.gov/publications">NIST publications</url>, at <url href="http://www.ietf.org">IETF</url>.
</p>
@@ -99,6 +104,14 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</desc>
</func>
<func>
+ <name>algorithms() -> [atom()]</name>
+ <fsummary>Provide a list of available crypto algorithms.</fsummary>
+ <desc>
+ <p>Provides the available crypto algorithms in terms of a list
+ of atoms.</p>
+ </desc>
+ </func>
+ <func>
<name>info_lib() -> [{Name,VerNum,VerStr}]</name>
<fsummary>Provides information about the libraries used by crypto.</fsummary>
<type>
@@ -973,7 +986,17 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
using the <c>crypto</c> library.</p>
</desc>
</func>
-
+ <func>
+ <name>mod_exp_prime(N, P, M) -> Result</name>
+ <fsummary>Computes the function: N^P mod M</fsummary>
+ <type>
+ <v>N, P, M = binary()</v>
+ <v>Result = binary() | error</v>
+ </type>
+ <desc>
+ <p>Computes the function <c>N^P mod M</c>.</p>
+ </desc>
+ </func>
<func>
<name>rsa_sign(DataOrDigest, Key) -> Signature</name>
<name>rsa_sign(DigestType, DataOrDigest, Key) -> Signature</name>
@@ -1256,8 +1279,85 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</desc>
</func>
+ <func>
+ <name>srp_generate_key(Generator, Prime, Version) -> {PublicKey, PrivateKey} </name>
+ <name>srp_generate_key(Generator, Prime, Version, Private) -> {PublicKey, PrivateKey} </name>
+ <name>srp_generate_key(Verifier, Generator, Prime, Version) -> {PublicKey, PrivateKey} </name>
+ <name>srp_generate_key(Verifier, Generator, Prime, Version, Private) -> {PublicKey, PrivateKey} </name>
+ <fsummary>Generates SRP public keys</fsummary>
+ <type>
+ <v>Verifier = binary()</v>
+ <d>Parameter v from <seealso marker="http://srp.stanford.edu/design.html">SRP design</seealso>
+ </d>
+ <v>Generator = binary() </v>
+ <d>Parameter g from <seealso marker="http://srp.stanford.edu/design.html">SRP design</seealso>
+ </d>
+ <v>Prime = binary() </v>
+ <d>Parameter N from <seealso marker="http://srp.stanford.edu/design.html">SRP design</seealso>
+ </d>
+ <v>Version = '3' | '6' | '6a' </v>
+ <d>SRP version, TLS SRP cipher suites uses '6a'.</d>
+ <v>PublicKey = binary()</v>
+ <d> Parameter A or B from <seealso marker="http://srp.stanford.edu/design.html">SRP design</seealso></d>
+ <v>PrivateKey = binary() - generated if not supplied</v>
+ <d>Parameter a or b from <seealso marker="http://srp.stanford.edu/design.html">SRP design</seealso></d>
+ </type>
+ <desc>
+ <p>Generates SRP public keys</p>
+ </desc>
+ </func>
<func>
+ <name>srp_compute_key(DerivedKey, Prime, Generator,
+ ClientPublic, ClientPrivate, ServerPublic, Version) -> SessionKey</name>
+ <name>srp_compute_key(DerivedKey, Prime, Generator,
+ ClientPublic, ClientPrivate, ServerPublic, Version, Scrambler) -> SessionKey</name>
+ <name>srp_compute_key(Verifier, Prime,
+ ClientPublic, ServerPublic, ServerPrivate, Version, Scrambler)-> SessionKey</name>
+ <name>srp_compute_key(Verifier, Prime,
+ ClientPublic, ServerPublic, ServerPrivate, Version) -> SessionKey</name>
+
+ <fsummary>Computes SRP session key</fsummary>
+ <type>
+ <v>DerivedKey = binary()</v>
+ <d>Parameter x from <url href="http://srp.stanford.edu/design.html">SRP design</url>
+ </d>
+ <v>Verifier = binary()</v>
+ <d>Parameter v from <url href="http://srp.stanford.edu/design.html">SRP design</url>
+ </d>
+ <v>Prime = binary() </v>
+ <d>Parameter N from <url href="http://srp.stanford.edu/design.html">SRP design</url>
+ </d>
+ <v>Generator = binary() </v>
+ <d>Parameter g from <url href="http://srp.stanford.edu/design.html">SRP design</url>
+ </d>
+ <v>ClientPublic = binary() </v>
+ <d>Parameter A from <url href="http://srp.stanford.edu/design.html">SRP design</url>
+ </d>
+ <v>ClientPrivate = binary() </v>
+ <d>Parameter a from <url href="http://srp.stanford.edu/design.html">SRP design</url>
+ </d>
+ <v>ServerPublic = binary() </v>
+ <d>Parameter B from <url href="http://srp.stanford.edu/design.html">SRP design</url>
+ </d>
+ <v>ServerPrivate = binary() </v>
+ <d>Parameter b from <url href="http://srp.stanford.edu/design.html">SRP design</url>
+ </d>
+ <v>Version = '3' | '6' | '6a' </v>
+ <d>SRP version, TLS SRP cipher suites uses '6a'.</d>
+ <v>SessionKey = binary()</v>
+ <d>Result K from <url href="http://srp.stanford.edu/design.html">SRP design</url>
+ </d>
+ </type>
+ <desc>
+ <p>
+ Computes the SRP session key (shared secret). Also used
+ as premaster secret by TLS-SRP ciher suites.
+ </p>
+ </desc>
+ </func>
+
+ <func>
<name>exor(Data1, Data2) -> Result</name>
<fsummary>XOR data</fsummary>
<type>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 1328a95e87..1d0a9943c3 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]).
@@ -57,7 +57,10 @@
-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_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]).
-export([aes_cbc_256_encrypt/3, aes_cbc_256_decrypt/3]).
@@ -88,7 +91,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,7 +112,8 @@
hash, hash_init, hash_update, hash_final,
hmac, hmac_init, hmac_update, hmac_final, hmac_final_n, info,
rc2_cbc_encrypt, rc2_cbc_decrypt,
- info_lib]).
+ srp_generate_key, srp_compute_key,
+ info_lib, algorithms]).
-type rsa_digest_type() :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'.
-type dss_digest_type() :: 'none' | 'sha'.
@@ -184,6 +188,8 @@ info() ->
info_lib() -> ?nif_stub.
+algorithms() -> ?nif_stub.
+
%% Crypto app version history:
%% (no version): Driver implementation
%% 2.0 : NIF implementation, requires OTP R14
@@ -783,21 +789,24 @@ 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) ->
- 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
- <<Len:32/integer, MSB, Rest/binary>> 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).
+
+-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;
+ R -> R
end.
-mod_exp_nif(_Base,_Exp,_Mod) -> ?nif_stub.
+
+mod_exp_nif(_Base,_Exp,_Mod,_bin_hdr) -> ?nif_stub.
%%
%% DSS, RSA - verify
@@ -1064,50 +1073,205 @@ dh_compute_key(OthersPublicKey, MyPrivateKey, DHParameters) ->
dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub.
+
+%%% 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).
+
%%
%% LOCAL FUNCTIONS
%%
+client_srp_gen_key(Private, Generator, Prime) ->
+ case mod_exp_prime(Generator, Private, Prime) of
+ error ->
+ error;
+ Public ->
+ {Public, Private}
+ end.
+
+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.
+
+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);
+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.
+ <<U:32/bits, _/binary>> = sha(ServerPublic),
+ U.
+
+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_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)
-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 ->
- <<?UINT32((I+1)), (list_to_binary([255|Ds]))/binary>>;
- true ->
- (<<?UINT32(I), (list_to_binary(Ds))/binary>>)
- 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),
+ <<?UINT32(Sz), Bin/binary>>.
-mpint_pos(0,I,Ds=[MSB|_]) ->
+mpint_pos(X) ->
+ Bin = int_to_bin_pos(X, []),
+ <<MSB,_/binary>> = Bin,
+ Sz = byte_size(Bin),
if MSB band 16#80 == 16#80 ->
- <<?UINT32((I+1)), (list_to_binary([0|Ds]))/binary>>;
+ <<?UINT32((Sz+1)), 0, Bin/binary>>;
true ->
- (<<?UINT32(I), (list_to_binary(Ds))/binary>>)
- end;
-mpint_pos(X,I,Ds) ->
- mpint_pos(X bsr 8,I+1,[(X band 255)|Ds]).
+ <<?UINT32(Sz), Bin/binary>>
+ 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),
+ <<Integer:Bits/integer>> = Bin,
+ Integer.
%% int from integer in a binary with 32bit length
erlint(<<MPIntSize:32/integer,MPIntValue/binary>>) ->
Bits= MPIntSize * 8,
<<Integer:Bits/integer>> = MPIntValue,
Integer.
+
+mpint_to_bin(<<Len:32, Bin:Len/binary>>) ->
+ 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 6f2df0f07b..08ecad3233 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,
@@ -72,6 +75,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,
@@ -93,14 +97,15 @@ 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,
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]}].
@@ -363,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"
@@ -386,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"
@@ -582,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. "
@@ -1025,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"),
@@ -1044,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(),
@@ -1063,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"),
@@ -1084,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(),
@@ -2017,6 +1847,161 @@ 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>>,
+ Version = '3',
+ Scrambler = hexstr2bin("02E2476A"),
+
+ %% X = hexstr2bin("96E54AB0CD4C5123EDCFA4A1502918AAD3C9E2A8"),
+ Verifier = hexstr2bin("96EB5F13621D911AA1CA405DE9C64217D4108EEEECAFFE500034FE0E"
+ "C031E42C8714667C161BCE0E7996F7DDE1B63824C130D2D7286C08C0"
+ "49758420735961347112AE102A3F23B3F687F8FEE0DF2BFAF933C608"
+ "D6FE5B5EEE3116FE54016E065BF8E8C9FDBBC08719231AC215149140"
+ "519E8FDD9AA4F410C28A58AF42974D2D"),
+ ClientPrivate = hexstr2bin("6411DE75538BED8170677D577D0608F39112BC95B503C447EB6AC945"
+ "49C75C7B"),
+ ServerPrivate = hexstr2bin("85E44A6F694DBE676145DB245A045CD37C99F05C562C7840A31F270D"
+ "9AADCF8B"),
+ ClientPublic = hexstr2bin("B22B1FFA2244B8CB94F3A9080F419CAEAB0DBA93EA1965B5E84587EE"
+ "55C79E7A118865DC59B9D0353362C2A8261E7C1B0D221A0E233C2AD1"
+ "640DACBB8664CBC9733EAC392DA7800142860380C3FC573C3C064329"
+ "CF54063FD114C7210E9CB3A611EA8002B1844B698F930D95D143899B"
+ "948A090E0C25938E5F84067D1883DC63"),
+ ServerPublic = hexstr2bin("93A8C4D8B7F7395ADCFD4ABA37B015124513D3F37B3E85EB23064BE5"
+ "F53C0AE32FFB9D8C0AA0DCFFA74D632DD67DEBB5C35AAE9812286CC8"
+ "C43CC176ECBC6D3F447594D9554E995B2509127BF88FADDDA4982D03"
+ "8EC3001320712D3B1269308CE70F319B2295FA57674F03A2D993CFB1"
+ "F84C35B7D0C012FA73CD4C8F7D5A71C7"),
+
+ SessionKey = hexstr2bin("C29A986C4D521BBC66428ED11D994CD7431574A6184B83CDCC345092"
+ "791E75748A1D38CAC4BD14760F0D2694B711236419240FF2F172454C"
+ "46ABF4FF39498DAFDD2C82924F7D7BD76CDFCE688C77D93F18A65409"
+ "9176A9192615DC0277AE7C12F1F6A7F6563FCA11675D809AF578BDE5"
+ "2B51E05D440B63099A017A0B45044801"),
+ UserPassHash = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]),
+ 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"];
+srp6(suite) -> [];
+srp6(Config) when is_list(Config) ->
+ Username = <<"alice">>,
+ Password = <<"password123">>,
+ Salt = hexstr2bin("2857827A19266A1F2BC6"),
+ Prime = hexstr2bin("EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C"
+ "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4"
+ "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29"
+ "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A"
+ "FD5138FE8376435B9FC61D2FC0EB06E3"),
+ Generator = <<2>>,
+ Version = '6',
+ Scrambler = hexstr2bin("0A2534C0BF52A0DA9001EEC62CF2A546AB0908A7"),
+ Verifier = hexstr2bin("96EB5F13621D911AA1CA405DE9C64217D4108EEEECAFFE500034FE0E"
+ "C031E42C8714667C161BCE0E7996F7DDE1B63824C130D2D7286C08C0"
+ "49758420735961347112AE102A3F23B3F687F8FEE0DF2BFAF933C608"
+ "D6FE5B5EEE3116FE54016E065BF8E8C9FDBBC08719231AC215149140"
+ "519E8FDD9AA4F410C28A58AF42974D2D"),
+ ClientPrivate = hexstr2bin("6411DE75538BED8170677D577D0608F39112BC95B503C447EB6AC945"
+ "49C75C7B"),
+ ServerPrivate = hexstr2bin("85E44A6F694DBE676145DB245A045CD37C99F05C562C7840A31F270D"
+ "9AADCF8B"),
+ ClientPublic = hexstr2bin("B22B1FFA2244B8CB94F3A9080F419CAEAB0DBA93EA1965B5E84587EE"
+ "55C79E7A118865DC59B9D0353362C2A8261E7C1B0D221A0E233C2AD1"
+ "640DACBB8664CBC9733EAC392DA7800142860380C3FC573C3C064329"
+ "CF54063FD114C7210E9CB3A611EA8002B1844B698F930D95D143899B"
+ "948A090E0C25938E5F84067D1883DC63"),
+ ServerPublic = hexstr2bin("D2D07845CE7ECDB9845DD36B10ACD3598CC29049DE9F467F84CE16B6"
+ "D97A6DC567AF8B0F9FEDF74962400AD5C357951E64E67B641246F264"
+ "C8DE6D9A72E554D6C8D3194548780A0C438A0FCC509CA88A14AA1DEB"
+ "C0F09E4B37A965D1545DB4AD361346F3189B0EA569C06D326C4E4797"
+ "9E381C748293B7C0591BE0BE419E053E"),
+
+ SessionKey = hexstr2bin("19D22C19612874EBF1F2581F8EFCFDC44C6FDA3B87B0A73823D7E962"
+ "554295D4E48D3A336523ADBDDD0EC8FB0F02687109E97E01C17C93CC"
+ "7216F9CD8A4AC39F0429857D8D1023066614BDFCBCB89F59A0FEB81C"
+ "72E992AAD89095A84B6A5FADA152369AB1E350A03693BEF044DF3EDF"
+ "0C34741F4696C30E9F675D09F58ACBEB"),
+ UserPassHash = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]),
+ 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."];
+srp6a(suite) -> [];
+srp6a(Config) when is_list(Config) ->
+ Username = <<"alice">>,
+ Password = <<"password123">>,
+ Salt = hexstr2bin("BEB25379D1A8581EB5A727673A2441EE"),
+ Prime = hexstr2bin("EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C"
+ "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4"
+ "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29"
+ "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A"
+ "FD5138FE8376435B9FC61D2FC0EB06E3"),
+ Generator = <<2>>,
+ Version = '6a',
+ Scrambler = hexstr2bin("CE38B9593487DA98554ED47D70A7AE5F462EF019"),
+ Verifier = hexstr2bin("7E273DE8696FFC4F4E337D05B4B375BEB0DDE1569E8FA00A9886D812"
+ "9BADA1F1822223CA1A605B530E379BA4729FDC59F105B4787E5186F5"
+ "C671085A1447B52A48CF1970B4FB6F8400BBF4CEBFBB168152E08AB5"
+ "EA53D15C1AFF87B2B9DA6E04E058AD51CC72BFC9033B564E26480D78"
+ "E955A5E29E7AB245DB2BE315E2099AFB"),
+ ClientPrivate = hexstr2bin("60975527035CF2AD1989806F0407210BC81EDC04E2762A56AFD529DD"
+ "DA2D4393"),
+ ServerPrivate = hexstr2bin("E487CB59D31AC550471E81F00F6928E01DDA08E974A004F49E61F5D1"
+ "05284D20"),
+ ClientPublic = hexstr2bin("61D5E490F6F1B79547B0704C436F523DD0E560F0C64115BB72557EC4"
+ "4352E8903211C04692272D8B2D1A5358A2CF1B6E0BFCF99F921530EC"
+ "8E39356179EAE45E42BA92AEACED825171E1E8B9AF6D9C03E1327F44"
+ "BE087EF06530E69F66615261EEF54073CA11CF5858F0EDFDFE15EFEA"
+ "B349EF5D76988A3672FAC47B0769447B"),
+ ServerPublic = hexstr2bin("BD0C61512C692C0CB6D041FA01BB152D4916A1E77AF46AE105393011"
+ "BAF38964DC46A0670DD125B95A981652236F99D9B681CBF87837EC99"
+ "6C6DA04453728610D0C6DDB58B318885D7D82C7F8DEB75CE7BD4FBAA"
+ "37089E6F9C6059F388838E7A00030B331EB76840910440B1B27AAEAE"
+ "EB4012B7D7665238A8E3FB004B117B58"),
+
+ SessionKey = hexstr2bin("B0DC82BABCF30674AE450C0287745E7990A3381F63B387AAF271A10D"
+ "233861E359B48220F7C4693C9AE12B0A6F67809F0876E2D013800D6C"
+ "41BB59B6D5979B5C00A172B4A2A5903A0BDCAF8A709585EB2AFAFA8F"
+ "3499B200210DCC1F10EB33943CD67FC88A2F39A4BE5BEC4EC0A3212D"
+ "C346D7E474B29EDE8A469FFECA686E5A"),
+ UserPassHash = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]),
+ 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) ->
@@ -2120,8 +2105,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]),
@@ -2256,10 +2241,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.