File 2571-Add-crypto-pbkdf2_hmac-5-function.patch of Package erlang
From 96854a17c36c073bfe7e612bdefa5c65282bb9de Mon Sep 17 00:00:00 2001
From: gearnode <bryan@frimin.fr>
Date: Thu, 25 Nov 2021 12:37:26 +0100
Subject: [PATCH 1/4] Add crypto:pbkdf2_hmac/5 function
---
lib/crypto/c_src/Makefile.in | 4 +-
lib/crypto/c_src/crypto.c | 2 +
lib/crypto/c_src/pbkdf2_hmac.c | 103 +++++++++++++++++++++++++++++++
lib/crypto/c_src/pbkdf2_hmac.h | 29 +++++++++
lib/crypto/doc/src/crypto.xml | 13 ++++
lib/crypto/src/crypto.erl | 14 +++++
lib/crypto/test/crypto_SUITE.erl | 64 ++++++++++++++++++-
7 files changed, 227 insertions(+), 2 deletions(-)
create mode 100644 lib/crypto/c_src/pbkdf2_hmac.c
create mode 100644 lib/crypto/c_src/pbkdf2_hmac.h
diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in
index 92918b5d9f..683e4bdbe8 100644
--- a/lib/crypto/c_src/Makefile.in
+++ b/lib/crypto/c_src/Makefile.in
@@ -112,7 +112,8 @@ CRYPTO_OBJS = $(OBJDIR)/crypto$(TYPEMARKER).o \
$(OBJDIR)/rand$(TYPEMARKER).o \
$(OBJDIR)/rsa$(TYPEMARKER).o \
$(OBJDIR)/srp$(TYPEMARKER).o \
- $(OBJDIR)/hash_equals$(TYPEMARKER).o
+ $(OBJDIR)/hash_equals$(TYPEMARKER).o \
+ $(OBJDIR)/pbkdf2_hmac$(TYPEMARKER).o
CALLBACK_OBJS = $(OBJDIR)/crypto_callback$(TYPEMARKER).o
CRYPTO_STATIC_OBJS = $(patsubst $(OBJDIR)/%$(TYPEMARKER).o,$(OBJDIR)/%_static$(TYPEMARKER).o,$(CRYPTO_OBJS) $(CALLBACK_OBJS))
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 65804bf6fb..3397b767eb 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -46,6 +46,7 @@
#include "hmac.h"
#include "info.h"
#include "math.h"
+#include "pbkdf2_hmac.h"
#include "pkey.h"
#include "rand.h"
#include "rsa.h"
@@ -94,6 +95,7 @@ static ErlNifFunc nif_funcs[] = {
{"hash_equals_nif", 2, hash_equals_nif, 0},
+ {"pbkdf2_hmac_nif", 5, pbkdf2_hmac_nif, 0},
{"pkey_sign_nif", 5, pkey_sign_nif, 0},
{"pkey_verify_nif", 6, pkey_verify_nif, 0},
{"pkey_crypt_nif", 6, pkey_crypt_nif, 0},
diff --git a/lib/crypto/c_src/pbkdf2_hmac.c b/lib/crypto/c_src/pbkdf2_hmac.c
new file mode 100644
index 0000000000..aa9f27c93d
--- /dev/null
+++ b/lib/crypto/c_src/pbkdf2_hmac.c
@@ -0,0 +1,103 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+
+ */
+
+#include "common.h"
+#include "pbkdf2_hmac.h"
+#include "digest.h"
+
+ERL_NIF_TERM pbkdf2_hmac_nif(ErlNifEnv* env, int argc,
+ const ERL_NIF_TERM argv[])
+{
+#ifdef HAS_PKCS5_PBKDF2_HMAC
+ ErlNifBinary pass, salt, out;
+ ErlNifUInt64 iter, keylen;
+ struct digest_type_t* digp = NULL;
+ const EVP_MD* digest;
+
+ ASSERT(argc == 5);
+
+ if ((digp = get_digest_type(argv[0])) == NULL)
+ goto bad_arg;
+ if (digp->md.p == NULL)
+ goto bad_arg;
+
+ switch (EVP_MD_type(digp->md.p))
+ {
+ case NID_sha1:
+ digest = EVP_sha1();
+ break;
+#ifdef HAVE_SHA224
+ case NID_sha224:
+ digest = EVP_sha224();
+ break;
+#endif
+#ifdef HAVE_SHA256
+ case NID_sha256:
+ digest = EVP_sha256();
+ break;
+#endif
+#ifdef HAVE_SHA384
+ case NID_sha384:
+ digest = EVP_sha384();
+ break;
+#endif
+#ifdef HAVE_SHA512
+ case NID_sha512:
+ digest = EVP_sha512();
+ break;
+#endif
+ default:
+ goto err;
+ }
+
+ if (!enif_inspect_binary(env, argv[1], &pass))
+ goto bad_arg;
+ if (!enif_inspect_binary(env, argv[2], &salt))
+ goto bad_arg;
+ if (!enif_get_uint64(env, argv[3], &iter))
+ goto bad_arg;
+ if (!enif_get_uint64(env, argv[4], &keylen))
+ goto bad_arg;
+
+ if (iter < 1)
+ goto bad_arg;
+ if (keylen < 1)
+ goto bad_arg;
+
+ if (!enif_alloc_binary(keylen, &out))
+ goto err;
+
+ if (!PKCS5_PBKDF2_HMAC((const char *)pass.data, pass.size,
+ salt.data, salt.size, iter,
+ digest,
+ keylen, out.data)) {
+ enif_release_binary(&out);
+ goto err;
+ }
+
+ return enif_make_binary(env, &out);
+ bad_arg:
+ err:
+ return enif_make_badarg(env);
+#else
+ return EXCP_NOTSUP(env, "Unsupported CRYPTO_PKCS5_PBKDF2_HMAC");
+#endif
+}
diff --git a/lib/crypto/c_src/pbkdf2_hmac.h b/lib/crypto/c_src/pbkdf2_hmac.h
new file mode 100644
index 0000000000..90be790861
--- /dev/null
+++ b/lib/crypto/c_src/pbkdf2_hmac.h
@@ -0,0 +1,29 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#ifndef E_PBKDF2_HMAC_H__
+#define E_PBKDF2_HMAC_H__ 1
+
+#include "common.h"
+
+ERL_NIF_TERM pbkdf2_hmac_nif(ErlNifEnv* env, int argc,
+ const ERL_NIF_TERM argv[]);
+
+#endif /* E_PBKDF2_HMAC_H__ */
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index d6ff2247b2..b7d089a961 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -2056,6 +2056,19 @@ FloatValue = rand:uniform(). % again
</desc>
</func>
+ <func>
+ <name name="pbkdf2_hmac" arity="5" since=""/>
+ <fsummary>PBKDF2 in combination with HMAC</fsummary>
+ <desc>
+ <p>
+ PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in combination with HMAC.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ </p>
+ </desc>
+ </func>
+
</funcs>
<funcs>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 6e5e32dd96..1d1ad71639 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -43,6 +43,7 @@
-export([privkey_to_pubkey/2]).
-export([ec_curve/1, ec_curves/0]).
-export([rand_seed/1]).
+-export([pbkdf2_hmac/5]).
%%%----------------------------------------------------------------
%% Removed functions.
@@ -753,6 +754,18 @@ enable_fips_mode(Enable) ->
equal_const_time(_, _, _) ->
false.
+-spec pbkdf2_hmac(Digest, Pass, Salt, Iter, KeyLen) -> Result
+ when Digest :: sha | sha224 | sha256 | sha384 | sha512,
+ Pass :: binary(),
+ Salt :: binary(),
+ Iter :: pos_integer(),
+ KeyLen :: pos_integer(),
+ Result :: binary().
+pbkdf2_hmac(Digest, Pass, Salt, Iter, KeyLen) ->
+ pbkdf2_hmac_nif(Digest, Pass, Salt, Iter, KeyLen).
+
+pbkdf2_hmac_nif(_, _, _, _, _) -> ?nif_stub.
+
%%%================================================================
%%%
%%% Hashing
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 854a6e2ad4..182af02cb0 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -138,6 +138,8 @@
use_all_ec_sign_verify/1,
use_all_ecdh_generate_compute/1,
use_all_eddh_generate_compute/1,
+ pbkdf2_hmac/0,
+ pbkdf2_hmac/1,
privkey_to_pubkey/1,
%% Others:
@@ -239,7 +241,8 @@ all() ->
rand_plugin_s,
cipher_info,
hash_info,
- hash_equals
+ hash_equals,
+ pbkdf2_hmac
].
-define(NEW_CIPHER_TYPE_SCHEMA,
@@ -4841,6 +4841,65 @@ try_enable_fips_mode(Config) ->
{skip, "FIPS mode not supported"}
end.
+pbkdf2_hmac() ->
+ [{doc, "Test the pbkdf2_hmac function"}].
+pbkdf2_hmac(Config) when is_list(Config) ->
+ try
+ F = fun (A, B, C, D) ->
+ binary:encode_hex(crypto:pbkdf2_hmac(sha, A, B, C, D))
+ end,
+ %% RFC 6070
+ <<"0C60C80F961F0E71F3A9B524AF6012062FE037A6">> =
+ F(<<"password">>, <<"salt">>, 1, 20),
+ <<"EA6C014DC72D6F8CCD1ED92ACE1D41F0D8DE8957">> =
+ F(<<"password">>, <<"salt">>, 2, 20),
+ <<"4B007901B765489ABEAD49D926F721D065A429C1">> =
+ F(<<"password">>, <<"salt">>, 4096, 20),
+ <<"EEFE3D61CD4DA4E4E9945B3D6BA2158C2634E984">> =
+ F(<<"password">>, <<"salt">>, 16777216, 20),
+ <<"3D2EEC4FE41C849B80C8D83662C0E44A8B291A964CF2F07038">> =
+ F(<<"passwordPASSWORDpassword">>, <<"saltSALTsaltSALTsaltSALTsaltSALTsalt">>, 4096, 25),
+ <<"56FA6AA75548099DCC37D7F03425E0C3">> =
+ F(<<"pass\0word">>, <<"sa\0lt">>, 4096, 16),
+
+ %% RFC 3962
+ <<"CDEDB5281BB2F801565A1122B2563515">> =
+ F(<<"password">>, <<"ATHENA.MIT.EDUraeburn">>, 1, 16),
+ <<"CDEDB5281BB2F801565A1122B25635150AD1F7A04BB9F3A333ECC0E2E1F70837">> =
+ F(<<"password">>, <<"ATHENA.MIT.EDUraeburn">>, 1, 32),
+ <<"01DBEE7F4A9E243E988B62C73CDA935D">> =
+ F(<<"password">>, <<"ATHENA.MIT.EDUraeburn">>, 2, 16),
+ <<"01DBEE7F4A9E243E988B62C73CDA935DA05378B93244EC8F48A99E61AD799D86">> =
+ F(<<"password">>, <<"ATHENA.MIT.EDUraeburn">>, 2, 32),
+ <<"5C08EB61FDF71E4E4EC3CF6BA1F5512B">> =
+ F(<<"password">>, <<"ATHENA.MIT.EDUraeburn">>, 1200, 16),
+ <<"5C08EB61FDF71E4E4EC3CF6BA1F5512BA7E52DDBC5E5142F708A31E2E62B1E13">> =
+ F(<<"password">>, <<"ATHENA.MIT.EDUraeburn">>, 1200, 32),
+ <<"D1DAA78615F287E6A1C8B120D7062A49">> =
+ F(<<"password">>, binary:encode_unsigned(16#1234567878563412), 5, 16),
+ <<"D1DAA78615F287E6A1C8B120D7062A493F98D203E6BE49A6ADF4FA574B6E64EE">> =
+ F(<<"password">>, binary:encode_unsigned(16#1234567878563412), 5, 32),
+ <<"139C30C0966BC32BA55FDBF212530AC9">> =
+ F(<<"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">>,
+ <<"pass phrase equals block size">>, 1200, 16),
+ <<"139C30C0966BC32BA55FDBF212530AC9C5EC59F1A452F5CC9AD940FEA0598ED1">> =
+ F(<<"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">>,
+ <<"pass phrase equals block size">>, 1200, 32),
+ <<"9CCAD6D468770CD51B10E6A68721BE61">> =
+ F(<<"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">>,
+ <<"pass phrase exceeds block size">>, 1200, 16),
+ <<"9CCAD6D468770CD51B10E6A68721BE611A8B4D282601DB3B36BE9246915EC82A">> =
+ F(<<"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">>,
+ <<"pass phrase exceeds block size">>, 1200, 32),
+ <<"6B9CF26D45455A43A5B8BB276A403B39">> =
+ F(binary:encode_unsigned(16#f09d849e), <<"EXAMPLE.COMpianist">>, 50, 16),
+ <<"6B9CF26D45455A43A5B8BB276A403B39E7FE37A0C41E02C281FF3069E1E94F52">> =
+ F(binary:encode_unsigned(16#f09d849e), <<"EXAMPLE.COMpianist">>, 50, 32)
+ catch
+ error:{notsup,{"pbkdf2_hmac.c", _}, "Unsupported CRYPTO_PKCS5_PBKDF2_HMAC"} ->
+ {skip, "No Unsupported CRYPTO_PKCS5_PBKDF2_HMAC"}
+ end.
+
get_priv_pub_from_sign_verify(L) ->
lists:foldl(fun get_priv_pub/2, [], L).
--
2.31.1