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

openSUSE Build Service is sponsored by