erlang/otp-0014-crypto-Fix-get_ossl_BN_param_from_bin_sz-to-not-abus.patch

103 lines
4.0 KiB
Diff
Raw Normal View History

From: Sverker Eriksson <sverker@erlang.org>
Date: Wed, 7 Jun 2023 18:50:23 +0200
Subject: [PATCH] crypto: Fix get_ossl_BN_param_from_bin_sz() to not abuse
ErlNifBinary
It is not allowed to write to the binary buffer returned by
enif_inspect_binary() (even if you created the binary yourself).
In DEBUG built VM such abuse will be punished with:
"Readonly data written by NIF, checksums differ 8000425 != 25040008
ABORTING"
Instead use enif_make_new_binary() to create a writable binary buffer.
diff --git a/lib/crypto/c_src/bn.c b/lib/crypto/c_src/bn.c
index f06ed9002e..5e9fec5093 100644
--- a/lib/crypto/c_src/bn.c
+++ b/lib/crypto/c_src/bn.c
@@ -212,23 +212,38 @@ int get_ossl_BN_param_from_bin(ErlNifEnv* env, char* key, ERL_NIF_TERM bin, OSSL
return get_ossl_BN_param_from_bin_sz(env, key, bin, dest, NULL);
}
-int get_ossl_BN_param_from_bin_sz(ErlNifEnv* env, char* key, ERL_NIF_TERM bin, OSSL_PARAM *dest, size_t *size)
+int get_ossl_BN_param_from_bin_sz(ErlNifEnv* env, char* key, ERL_NIF_TERM bin,
+ OSSL_PARAM *dest, size_t *size)
{
BIGNUM *bn = NULL;
- ErlNifBinary tmp;
+ int ok = 0;
- if (!get_bn_from_bin_sz(env, bin, &bn, size) ||
- !enif_inspect_binary(env, bin_from_bn(env,bn), &tmp) || // Allocate buf
- BN_bn2nativepad(bn, tmp.data, tmp.size) < 0) {// Fill with BN in right endianity
- if (bn) BN_free(bn);
+ if (!get_bn_from_bin_sz(env, bin, &bn, size))
return 0;
- }
-
- *dest = OSSL_PARAM_construct_BN(key, tmp.data, tmp.size);
- if (bn) BN_free(bn);
+
+ ok = get_ossl_BN_param_from_bn(env, key, bn, dest);
+ BN_free(bn);
+ return ok;
+}
+
+int get_ossl_BN_param_from_bn(ErlNifEnv* env, char* key, const BIGNUM* bn,
+ OSSL_PARAM *dest)
+{
+ const size_t bn_sz = BN_num_bytes(bn);
+ unsigned char* tmp_buf;
+ ERL_NIF_TERM dummy_term;
+
+ /* Create a binary term just as a convenient tmp buffer */
+ tmp_buf = enif_make_new_binary(env, bn_sz, &dummy_term);
+ if (BN_bn2nativepad(bn, tmp_buf, bn_sz) < 0) // Fill with BN in right endianity
+ return 0;
+
+ *dest = OSSL_PARAM_construct_BN(key, tmp_buf, bn_sz);
return 1;
}
+
+
int get_ossl_param_from_bin_in_list(ErlNifEnv* env, char* key, ERL_NIF_TERM *listcell, OSSL_PARAM *dest)
{
ERL_NIF_TERM head;
diff --git a/lib/crypto/c_src/bn.h b/lib/crypto/c_src/bn.h
index 5e207aed2d..662a32dc29 100644
--- a/lib/crypto/c_src/bn.h
+++ b/lib/crypto/c_src/bn.h
@@ -38,6 +38,7 @@ int get_bn_from_bin_sz(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp, size_t*
int get_ossl_octet_string_param_from_bin(ErlNifEnv* env, char* key, ERL_NIF_TERM bin, OSSL_PARAM *dest);
int get_ossl_BN_param_from_bin(ErlNifEnv* env, char* key, ERL_NIF_TERM bin, OSSL_PARAM *dest);
int get_ossl_BN_param_from_bin_sz(ErlNifEnv* env, char* key, ERL_NIF_TERM bin, OSSL_PARAM *dest, size_t *size);
+int get_ossl_BN_param_from_bn(ErlNifEnv* env, char* key, const BIGNUM* bn, OSSL_PARAM *dest);
int get_ossl_param_from_bin_in_list(ErlNifEnv* env, char* key, ERL_NIF_TERM *listcell, OSSL_PARAM *dest);
#endif
diff --git a/lib/crypto/c_src/ec.c b/lib/crypto/c_src/ec.c
index 852f3ba79c..af5f5d6f4a 100644
--- a/lib/crypto/c_src/ec.c
+++ b/lib/crypto/c_src/ec.c
@@ -189,15 +189,8 @@ int get_curve_definition(ErlNifEnv* env, ERL_NIF_TERM *ret, ERL_NIF_TERM def,
} else
assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad last field"));
- {
- ErlNifBinary tmp;
-
- if (!enif_inspect_binary(env, bin_from_bn(env,p), &tmp) || // Allocate buf
- BN_bn2nativepad(p, tmp.data, tmp.size) < 0) {// Fill with BN in right endianity
- assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "BN padding failed"));
- }
- params[(*i)++] = OSSL_PARAM_construct_BN("p", tmp.data, tmp.size);
- }
+ if (!get_ossl_BN_param_from_bn(env, "p", p, &params[(*i)++]))
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "BN padding failed"));
# endif
}
else