File 8654-crypto-generate_key-and-compute_key-error-ERR-error-.patch of Package erlang

From 8aa62ec02cd5cf5acd49f30dc532f9a3d3ae47d8 Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Wed, 9 Mar 2022 09:03:29 +0100
Subject: [PATCH 4/8] crypto:generate_key and compute_key error:ERR ->
 error:{ERR,FileInfo,Description}

---
 lib/crypto/c_src/crypto.c     |   2 +-
 lib/crypto/c_src/dh.c         | 101 ++++++++++++++++------------------
 lib/crypto/c_src/ec.c         |  22 ++++----
 lib/crypto/c_src/ec.h         |   2 +-
 lib/crypto/c_src/ecdh.c       |  41 ++++++--------
 lib/crypto/c_src/evp.c        |  67 +++++++++++-----------
 lib/crypto/doc/src/crypto.xml |   1 +
 lib/crypto/src/crypto.erl     |  46 ++++++++++------
 8 files changed, 141 insertions(+), 141 deletions(-)

diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 519d35b93f..042d122f53 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -109,7 +109,7 @@ static ErlNifFunc nif_funcs[] = {
     {"srp_user_secret_nif", 7, srp_user_secret_nif, 0},
     {"srp_host_secret_nif", 5, srp_host_secret_nif, 0},
 
-    {"ec_key_generate", 2, ec_key_generate, 0},
+    {"ec_generate_key_nif", 2, ec_generate_key_nif, 0},
     {"ecdh_compute_key_nif", 3, ecdh_compute_key_nif, 0},
 
     {"rand_seed_nif", 1, rand_seed_nif, 0},
diff --git a/lib/crypto/c_src/dh.c b/lib/crypto/c_src/dh.c
index 67be0c81f0..8d3f53d06e 100644
--- a/lib/crypto/c_src/dh.c
+++ b/lib/crypto/c_src/dh.c
@@ -45,43 +45,43 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
 
     if (argv[0] != atom_undefined) {
         if (!get_bn_from_bin(env, argv[0], &priv_key_in))
-            goto bad_arg;
+            assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Can't get bignum from binary"));
     }
     if (!enif_get_list_cell(env, argv[1], &head, &tail))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 1, "List with exactly two elements expected"));
     if (!get_bn_from_bin(env, head, &dh_p))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Can't get bignum from binary"));
 
     if (!enif_get_list_cell(env, tail, &head, &tail))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 1, "List with exactly two elements expected"));
     if (!get_bn_from_bin(env, head, &dh_g))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Can't get bignum from binary"));
 
     if (!enif_is_empty_list(env, tail))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 1, "List with exactly two elements expected"));
 
     if (!enif_get_uint(env, argv[2], &mpint))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Integer expected"));
     if (mpint != 0 && mpint != 4)
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Integer 0 or 4 expected"));
 
     if (!enif_get_ulong(env, argv[3], &len))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 3, "Integer expected"));
     if (len > LONG_MAX)
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 3, "Too big integer"));
 
     /* Load dh_params with values to use by the generator.
        Mem mgmnt transferred from dh_p etc to dh_params */
     if ((dh_params = DH_new()) == NULL)
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't do DH_new"));
     if (priv_key_in) {
         if (!DH_set0_key(dh_params, NULL, priv_key_in))
-            goto bad_arg;
+            assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Not accepted as private key"));
         /* On success, dh_params owns priv_key_in */
         priv_key_in = NULL;
     }
     if (!DH_set0_pqg(dh_params, dh_p, NULL, dh_g))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 1, "P and/or G not accepted"));
     dh_p_shared = dh_p; /* Don't free this because dh_params owns it */
     /* On success, dh_params owns dh_p and dh_g */
     dh_p = NULL;
@@ -91,56 +91,56 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
         int bn_len;
 
         if ((bn_len = BN_num_bits(dh_p_shared)) < 0)
-            goto bad_arg;
+            assign_goto(ret, err, EXCP_ERROR(env, "BN_num_bits < 0"));
         dh_p_shared = NULL;  /* dh_params owns the reference */
         if (len >= (size_t)bn_len)
-            goto bad_arg;
+            assign_goto(ret, err, EXCP_ERROR_N(env, 3, "Too big length"));
 
         if (!DH_set_length(dh_params, (long)len))
-            goto bad_arg;
+            assign_goto(ret, err, EXCP_ERROR_N(env, 3, "The length is not accepted"));
     }
 
 #if defined(HAS_EVP_PKEY_CTX) && (! DISABLE_EVP_DH)
     if ((params = EVP_PKEY_new()) == NULL)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_new"));
 
    /* set the key referenced by params to dh_params... */
     if (EVP_PKEY_set1_DH(params, dh_params) != 1)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_set1_DH"));
 
     if ((ctx = EVP_PKEY_CTX_new(params, NULL)) == NULL)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_CTX_new"));
 
     if (EVP_PKEY_keygen_init(ctx) != 1)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_keygen_init"));
 
     if ((dhkey = EVP_PKEY_new()) == NULL)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_new"));
 
     /* key gen op, key written to ppkey (=last arg) */
     if (EVP_PKEY_keygen(ctx, &dhkey) != 1)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_keygen"));
 
     DH_free(dh_params);
     if ((dh_params = EVP_PKEY_get1_DH(dhkey)) == NULL)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_get1_DH"));
 
 #else
     if (!DH_generate_key(dh_params))
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't DH_generate_key"));
 #endif
 
     DH_get0_key(dh_params, &pub_key_gen, &priv_key_gen);
 
     if ((pub_len = BN_num_bytes(pub_key_gen)) < 0)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't get public key length"));
     if ((prv_len = BN_num_bytes(priv_key_gen)) < 0)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't get private key length"));
 
     if ((pub_ptr = enif_make_new_binary(env, (size_t)pub_len+mpint, &ret_pub)) == NULL)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate pub_ptr"));
     if ((prv_ptr = enif_make_new_binary(env, (size_t)prv_len+mpint, &ret_prv)) == NULL)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate prv_ptr"));
 
     if (mpint) {
         put_uint32(pub_ptr, (unsigned int)pub_len);
@@ -151,9 +151,9 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
     }
 
     if (BN_bn2bin(pub_key_gen, pub_ptr) < 0)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't BN_bn2bin"));
     if (BN_bn2bin(priv_key_gen, prv_ptr) < 0)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't BN_bn2bin"));
 
     ERL_VALGRIND_MAKE_MEM_DEFINED(pub_ptr, pub_len);
     ERL_VALGRIND_MAKE_MEM_DEFINED(prv_ptr, prv_len);
@@ -161,13 +161,7 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
     ret = enif_make_tuple2(env, ret_pub, ret_prv);
     goto done;
 
- bad_arg:
-    ret = enif_make_badarg(env);
-    goto done;
-
  err:
-    ret = atom_error;
-
  done:
     if (priv_key_in)
         BN_free(priv_key_in);
@@ -216,22 +210,22 @@ ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
     ASSERT(argc == 3);
 
     if (!get_bn_from_bin(env, argv[0], &other_pub_key))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Can't get bignum from binary"));
     if (!get_bn_from_bin(env, argv[1], &priv_key))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Can't get bignum from binary"));
 
     if (!enif_get_list_cell(env, argv[2], &head, &tail))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 2, "List with exactly two elements expected"));
     if (!get_bn_from_bin(env, head, &dh_p))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Can't get bignum from binary"));
 
     if (!enif_get_list_cell(env, tail, &head, &tail))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 2, "List with exactly two elements expected"));
     if (!get_bn_from_bin(env, head, &dh_g))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Can't get bignum from binary"));
 
     if (!enif_is_empty_list(env, tail))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 2, "List with exactly two elements expected"));
 
     /* Note: DH_set0_key() does not allow setting only the
      * private key, although DH_compute_key() does not use the
@@ -239,48 +233,45 @@ ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
      * the public key to a copy of the private key.
      */
     if ((dummy_pub_key = BN_dup(priv_key)) == NULL)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't BN_dup"));
     if ((dh_priv = DH_new()) == NULL)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't DH_new"));
 
     if (!DH_set0_key(dh_priv, dummy_pub_key, priv_key))
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't DH_set0_key"));
     /* dh_priv owns dummy_pub_key and priv_key now */
     dummy_pub_key = NULL;
     priv_key = NULL;
 
     if (!DH_set0_pqg(dh_priv, dh_p, NULL, dh_g))
-        goto err;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 2, "P and/or G not accepted"));
     /* dh_priv owns dh_p and dh_g now */
     dh_p = NULL;
     dh_g = NULL;
 
     if ((dh_size = DH_size(dh_priv)) < 0)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't DH_size"));
     if (!enif_alloc_binary((size_t)dh_size, &ret_bin))
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't allcate binary"));
     ret_bin_alloc = 1;
 
     if ((size = DH_compute_key(ret_bin.data, other_pub_key, dh_priv)) < 0)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't DH_compute_key"));
     if (size == 0)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "size == 0"));
 
     if ((size_t)size != ret_bin.size) {
         if (!enif_realloc_binary(&ret_bin, (size_t)size))
-            goto err;
+            assign_goto(ret, err, EXCP_ERROR(env, "Can't realloc binary"));
     }
 
     ret = enif_make_binary(env, &ret_bin);
     ret_bin_alloc = 0;
     goto done;
 
- bad_arg:
  err:
     if (ret_bin_alloc)
         enif_release_binary(&ret_bin);
-    ret = enif_make_badarg(env);
-
  done:
     if (other_pub_key)
         BN_free(other_pub_key);
diff --git a/lib/crypto/c_src/ec.c b/lib/crypto/c_src/ec.c
index fd66ecfab4..a7497f014a 100644
--- a/lib/crypto/c_src/ec.c
+++ b/lib/crypto/c_src/ec.c
@@ -426,11 +426,9 @@ int get_ec_key_sz(ErlNifEnv* env,
     return 1;
 }
 
-#endif /* HAVE_EC */
 
-ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ERL_NIF_TERM ec_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
 { /* (Curve, PrivKey)  */
-#if defined(HAVE_EC)
     EC_KEY *key = NULL;
     const EC_GROUP *group;
     const EC_POINT *public_key;
@@ -440,11 +438,11 @@ ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
     size_t size;
 
     if (!get_ec_key_sz(env, argv[0], argv[1], atom_undefined, &key, &size))
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Couldn't get EC key"));
 
     if (argv[1] == atom_undefined) {
 	if (!EC_KEY_generate_key(key))
-            goto err;
+            assign_goto(ret, err, EXCP_ERROR(env, "Couldn't generate EC key"));
     }
 
     group = EC_KEY_get0_group(key);
@@ -463,15 +461,17 @@ ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
     goto done;
 
  err:
- bad_arg:
-    ret = make_badarg_maybe(env);
-
  done:
     if (key)
         EC_KEY_free(key);
     return ret;
+}
+#endif /* HAVE_EC */
 
-#else
-    return atom_notsup;
-#endif
+
+#if ! defined(HAVE_EC)
+ERL_NIF_TERM ec_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{ /* (Curve, PrivKey)  */
+    return EXCP_NOTSUP_N(env, 0, "EC not supported");
 }
+#endif
diff --git a/lib/crypto/c_src/ec.h b/lib/crypto/c_src/ec.h
index e7b885cb0f..96e02643c8 100644
--- a/lib/crypto/c_src/ec.h
+++ b/lib/crypto/c_src/ec.h
@@ -33,6 +33,6 @@ int term2point(ErlNifEnv* env, ERL_NIF_TERM term, EC_GROUP *group, EC_POINT **pp
 ERL_NIF_TERM make_badarg_maybe(ErlNifEnv* env);
 #endif
 
-ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM ec_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
 
 #endif /* E_EC_H__ */
diff --git a/lib/crypto/c_src/ecdh.c b/lib/crypto/c_src/ecdh.c
index 041c658808..9133878b58 100644
--- a/lib/crypto/c_src/ecdh.c
+++ b/lib/crypto/c_src/ecdh.c
@@ -29,7 +29,7 @@ ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
 /* (OtherPublicKey, Curve, My) */
 {
 #if defined(HAVE_EC)
-    ERL_NIF_TERM ret;
+    ERL_NIF_TERM ret = atom_undefined;
     unsigned char *p;
     EC_KEY* key = NULL;
     int degree;
@@ -39,44 +39,37 @@ ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
     EC_POINT *my_ecpoint = NULL;
     EC_KEY *other_ecdh = NULL;
 
-    ASSERT(argc == 3);
-
     if (!get_ec_key_sz(env, argv[1], argv[2], atom_undefined, &key, NULL)) // my priv key
-        goto bad_arg;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Couldn't get local key"));
+    
     if ((group = EC_GROUP_dup(EC_KEY_get0_group(key))) == NULL)
-        goto bad_arg;
+         assign_goto(ret, err, EXCP_ERROR(env, "Couldn't duplicate EC key"));
+
     priv_key = EC_KEY_get0_private_key(key);
 
-    if (!term2point(env, argv[0], group, &my_ecpoint)) {
-        goto err;
-    }
+    if (!term2point(env, argv[0], group, &my_ecpoint))
+        assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Couldn't get ecpoint"));
 
     if ((other_ecdh = EC_KEY_new()) == NULL)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Couldn't allocate EC_KEY"));
+    
     if (!EC_KEY_set_group(other_ecdh, group))
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Couldn't set group"));
+
     if (!EC_KEY_set_private_key(other_ecdh, priv_key))
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Couldn't set private key"));
 
     if ((degree = EC_GROUP_get_degree(group)) <= 0)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Couldn't get degree"));
 
     field_size = (size_t)degree;
     if ((p = enif_make_new_binary(env, (field_size+7)/8, &ret)) == NULL)
-        goto err;
-    if (ECDH_compute_key(p, (field_size+7)/8, my_ecpoint, other_ecdh, NULL) < 1)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Couldn't allocate binary"));
 
-    goto done;
-
- bad_arg:
-    ret = make_badarg_maybe(env);
-    goto done;
+    if (ECDH_compute_key(p, (field_size+7)/8, my_ecpoint, other_ecdh, NULL) < 1)
+        assign_goto(ret, err, EXCP_ERROR(env, "Couldn't compute key"));
 
  err:
-    ret = enif_make_badarg(env);
-
- done:
     if (group)
         EC_GROUP_free(group);
     if (my_ecpoint)
@@ -89,6 +82,6 @@ ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
     return ret;
 
 #else
-    return atom_notsup;
+    return EXCP_NOTSUP_N(env, 0, "EC not supported");
 #endif
 }
diff --git a/lib/crypto/c_src/evp.c b/lib/crypto/c_src/evp.c
index 7491db3d57..00a6fe16ed 100644
--- a/lib/crypto/c_src/evp.c
+++ b/lib/crypto/c_src/evp.c
@@ -34,43 +34,53 @@ ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
 
     ASSERT(argc == 3);
 
+    /* Arg 0, Curve */
     if (argv[0] == atom_x25519)
         type = EVP_PKEY_X25519;
     else if (argv[0] == atom_x448)
         type = EVP_PKEY_X448;
     else
-        goto bad_arg;
+        assign_goto(ret, bad_arg, EXCP_BADARG_N(env, 0, "Bad curve"));
 
-    if (!enif_inspect_binary(env, argv[1], &peer_bin))
-        goto bad_arg;
+    /* Arg 2, MyBin (My private key) */
     if (!enif_inspect_binary(env, argv[2], &my_bin))
-        goto bad_arg;
+        assign_goto(ret, bad_arg, EXCP_BADARG_N(env, 2, "Binary expected"));
 
     if ((my_key = EVP_PKEY_new_raw_private_key(type, NULL, my_bin.data, my_bin.size)) == NULL)
-        goto err;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Not a valid raw private key"));
+
     if ((ctx = EVP_PKEY_CTX_new(my_key, NULL)) == NULL)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR_N(env, 2, "Can't make context"));
 
     if (EVP_PKEY_derive_init(ctx) != 1)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_derive_init"));
+
+    /* Arg 1, PeerBin (Peer public key) */
+    if (!enif_inspect_binary(env, argv[1], &peer_bin))
+        assign_goto(ret, bad_arg, EXCP_BADARG_N(env, 1, "Binary expected"));
 
     if ((peer_key = EVP_PKEY_new_raw_public_key(type, NULL, peer_bin.data, peer_bin.size)) == NULL)
-        goto err;
+        assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Not a raw public peer key"));
+
     if (EVP_PKEY_derive_set_peer(ctx, peer_key) != 1)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR_N(env, 1, "Can't EVP_PKEY_derive_set_peer"));
 
+    /* Find max size of the common key */
     if (EVP_PKEY_derive(ctx, NULL, &max_size) != 1)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR_N(env, 1, "Can't get max size"));
 
     if (!enif_alloc_binary(max_size, &key_bin))
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate"));
+
     key_bin_alloc = 1;
+
+    /* Derive the common key */
     if (EVP_PKEY_derive(ctx, key_bin.data, &key_bin.size) != 1)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_derive"));
 
     if (key_bin.size < max_size) {
         if (!enif_realloc_binary(&key_bin, (size_t)key_bin.size))
-            goto err;
+            assign_goto(ret, err, EXCP_ERROR(env, "Can't shrink binary"));
     }
 
     ret = enif_make_binary(env, &key_bin);
@@ -81,7 +91,6 @@ ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
  err:
     if (key_bin_alloc)
         enif_release_binary(&key_bin);
-    ret = enif_make_badarg(env);
 
  done:
     if (my_key)
@@ -98,6 +107,7 @@ ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
 #endif
 }
 
+
 ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
 /* (Curve) */
 {
@@ -119,46 +129,41 @@ ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
     else if (argv[0] == atom_ed448)
         type = EVP_PKEY_ED448;
     else
-        goto bad_arg;
+        assign_goto(ret, bad_arg, EXCP_BADARG_N(env, 0, "Bad curve"));
 
     if (argv[1] == atom_undefined) {
         if ((ctx = EVP_PKEY_CTX_new_id(type, NULL)) == NULL)
-            goto bad_arg;
+            assign_goto(ret, err, EXCP_ERROR(env, "Can't make context"));
         if (EVP_PKEY_keygen_init(ctx) != 1)
-            goto err;
+            assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_keygen_init"));
         if (EVP_PKEY_keygen(ctx, &pkey) != 1)
-            goto err;
+            assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_keygen"));
     } else {
         if (!enif_inspect_binary(env, argv[1], &prv_key))
-            goto bad_arg;
+            assign_goto(ret, err, EXCP_ERROR_N(env, 1, "Can't get max size"));
         if ((pkey = EVP_PKEY_new_raw_private_key(type, NULL, prv_key.data, prv_key.size)) == NULL)
-            goto bad_arg;
+            assign_goto(ret, err, EXCP_ERROR_N(env, 1, "Can't EVP_PKEY_new_raw_private_key"));
     }
 
     if (EVP_PKEY_get_raw_public_key(pkey, NULL, &key_len) != 1)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR_N(env, 1, "Can't get max size"));
     if ((out_pub = enif_make_new_binary(env, key_len, &ret_pub)) == NULL)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate"));
     if (EVP_PKEY_get_raw_public_key(pkey, out_pub, &key_len) != 1)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_get_raw_public_key"));
 
     if (EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len) != 1)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR_N(env, 1, "Can't get max size"));
     if ((out_priv = enif_make_new_binary(env, key_len, &ret_prv)) == NULL)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate"));
     if (EVP_PKEY_get_raw_private_key(pkey, out_priv, &key_len) != 1)
-        goto err;
+        assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_get_raw_private_key"));
 
     ret = enif_make_tuple2(env, ret_pub, ret_prv);
     goto done;
 
  bad_arg:
-    ret = enif_make_badarg(env);
-    goto done;
-
  err:
-    ret = atom_error;
-
  done:
     if (pkey)
         EVP_PKEY_free(pkey);
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 0b20d715df..9ee2653c0c 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -1050,6 +1050,7 @@ end
       <name name="compute_key" arity="4" since="OTP R16B01"/>
       <fsummary>Computes the shared secret</fsummary>
       <desc>
+	<p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
 	<p>Computes the shared secret from the private key and the other party's public key.
 	 See also <seemfa marker="public_key:public_key#compute_key/2">public_key:compute_key/2</seemfa>
 	</p>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index bfdc8b784c..bffaacb043 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -1602,9 +1602,11 @@ generate_key(dh, DHParameters0, PrivateKey) ->
             [P,G,L] -> {[P,G], L};
             [P,G] -> {[P,G], 0}
         end,
-    dh_generate_key_nif(ensure_int_as_bin(PrivateKey),
-			map_ensure_int_as_bin(DHParameters),
-                        0, Len);
+    ?nif_call(dh_generate_key_nif(ensure_int_as_bin(PrivateKey),
+                                  map_ensure_int_as_bin(DHParameters),
+                                  0, Len),
+              {3, 2, -1, 2},
+              [dh, DHParameters0, PrivateKey]);
 
 generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, PrivArg)
   when is_binary(Verifier), is_binary(Generator), is_binary(Prime), is_atom(Version) ->
@@ -1648,14 +1650,20 @@ generate_key(ecdh, Curve, PrivKey) when Curve == x448 ;
     generate_key(eddh, Curve, PrivKey);
 generate_key(eddh, Curve, PrivKey) when Curve == x448 ;
                                         Curve == x25519 ->
-    evp_generate_key_nif(Curve, ensure_int_as_bin(PrivKey));
+    ?nif_call(evp_generate_key_nif(Curve, ensure_int_as_bin(PrivKey)),
+              {2, 3},
+              [eddh, Curve, PrivKey]
+             );
 
 generate_key(ecdh, Curve, PrivKey) ->
-    ec_key_generate(nif_curve_params(Curve), ensure_int_as_bin(PrivKey));
+    ?nif_call(ec_generate_key_nif(nif_curve_params(Curve), ensure_int_as_bin(PrivKey)));
 
 generate_key(eddsa, Curve, PrivKey) when Curve == ed448 ;
                                          Curve == ed25519 ->
-    evp_generate_key_nif(Curve, ensure_int_as_bin(PrivKey)).
+    ?nif_call(evp_generate_key_nif(Curve, ensure_int_as_bin(PrivKey)),
+              {2, 3},
+              [eddsa, Curve, PrivKey]
+             ).
 
 evp_generate_key_nif(_Curve, _PrivKey) -> ?nif_stub.
 
@@ -1670,13 +1678,11 @@ evp_generate_key_nif(_Curve, _PrivKey) -> ?nif_stub.
                                        .
 
 compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) ->
-    case dh_compute_key_nif(ensure_int_as_bin(OthersPublicKey),
-			    ensure_int_as_bin(MyPrivateKey),
-			    map_ensure_int_as_bin(DHParameters)) of
-	error -> erlang:error(computation_failed,
-			      [dh,OthersPublicKey,MyPrivateKey,DHParameters]);
-	Ret -> Ret
-    end;
+    ?nif_call(dh_compute_key_nif(ensure_int_as_bin(OthersPublicKey),
+                                 ensure_int_as_bin(MyPrivateKey),
+                                 map_ensure_int_as_bin(DHParameters)),
+              {2, 3, 4},
+              [dh, OthersPublicKey, MyPrivateKey, DHParameters]);
 
 compute_key(srp, HostPublic, {UserPublic, UserPrivate},
 	    {user, [DerivedKey, Prime, Generator, Version | ScramblerArg]}) when
@@ -1715,12 +1721,16 @@ compute_key(ecdh, Others, My, Curve) when Curve == x448 ;
 
 compute_key(eddh, Others, My, Curve) when Curve == x448 ;
                                           Curve == x25519 ->
-    evp_compute_key_nif(Curve, ensure_int_as_bin(Others), ensure_int_as_bin(My));
+    ?nif_call(evp_compute_key_nif(Curve, ensure_int_as_bin(Others), ensure_int_as_bin(My)),
+              {2, 3, 4},
+              [eddh, Others, My, Curve]);
 
 compute_key(ecdh, Others, My, Curve) ->
-    ecdh_compute_key_nif(ensure_int_as_bin(Others),
-			 nif_curve_params(Curve),
-			 ensure_int_as_bin(My)).
+    ?nif_call(ecdh_compute_key_nif(ensure_int_as_bin(Others),
+                                   nif_curve_params(Curve),
+                                   ensure_int_as_bin(My)),
+              {2, 4, 3},
+              [ecdh, Others, My, Curve]).
 
 
 evp_compute_key_nif(_Curve, _OthersBin, _MyBin) -> ?nif_stub.
@@ -2274,7 +2284,7 @@ dh_generate_key_nif(_PrivateKey, _DHParameters, _Mpint, _Length) -> ?nif_stub.
 %% MyPrivKey, OthersPublicKey = mpint()
 dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub.
 
-ec_key_generate(_Curve, _Key) -> ?nif_stub.
+ec_generate_key_nif(_Curve, _Key) -> ?nif_stub.
 
 ecdh_compute_key_nif(_Others, _Curve, _My) -> ?nif_stub.
 
-- 
2.34.1

openSUSE Build Service is sponsored by