From 46a101341ecb4cb800e685f5c1897ed474c4ab7b Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 06:43:10 -0800 Subject: Revamp evp_cipher_ctx_dtor() Make it NULL safe. --- lib/crypto/c_src/cipher.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/crypto/c_src/cipher.c b/lib/crypto/c_src/cipher.c index 6580cb183f..cda9b15291 100644 --- a/lib/crypto/c_src/cipher.c +++ b/lib/crypto/c_src/cipher.c @@ -74,7 +74,11 @@ static struct cipher_type_t cipher_types[] = ErlNifResourceType* evp_cipher_ctx_rtype; static void evp_cipher_ctx_dtor(ErlNifEnv* env, struct evp_cipher_ctx* ctx) { - EVP_CIPHER_CTX_free(ctx->ctx); + if (ctx == NULL) + return; + + if (ctx->ctx) + EVP_CIPHER_CTX_free(ctx->ctx); } #endif -- cgit v1.2.3 From 7e95687c086f833805d520c33fe96e7e42fc8f6c Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 06:43:32 -0800 Subject: Revamp engine_ctx_dtor() Make it NULL safe. --- lib/crypto/c_src/engine.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index dc8e1828ce..71552a0a89 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -32,6 +32,9 @@ static int get_engine_load_cmd_list(ErlNifEnv* env, const ERL_NIF_TERM term, cha static int zero_terminate(ErlNifBinary bin, char **buf); static void engine_ctx_dtor(ErlNifEnv* env, struct engine_ctx* ctx) { + if (ctx == NULL) + return; + PRINTF_ERR0("engine_ctx_dtor"); if(ctx->id) { PRINTF_ERR1(" non empty ctx->id=%s", ctx->id); -- cgit v1.2.3 From 5904d78fbea85c481dc595df1e279f068acf6d12 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 06:44:06 -0800 Subject: Revamp evp_md_ctx_dtor() Make it NULL safe. --- lib/crypto/c_src/hash.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/crypto/c_src/hash.c b/lib/crypto/c_src/hash.c index 52748dc933..c8835296ea 100644 --- a/lib/crypto/c_src/hash.c +++ b/lib/crypto/c_src/hash.c @@ -34,7 +34,11 @@ struct evp_md_ctx { static ErlNifResourceType* evp_md_ctx_rtype; static void evp_md_ctx_dtor(ErlNifEnv* env, struct evp_md_ctx *ctx) { - EVP_MD_CTX_free(ctx->ctx); + if (ctx == NULL) + return; + + if (ctx->ctx) + EVP_MD_CTX_free(ctx->ctx); } #endif -- cgit v1.2.3 From 0a04504f0eee025f02a405ff951f4ff5dea80345 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 06:44:29 -0800 Subject: Revamp hmac_context_dtor() Make it NULL safe. --- lib/crypto/c_src/hmac.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/crypto/c_src/hmac.c b/lib/crypto/c_src/hmac.c index 143cde90e1..6ddbd2c59a 100644 --- a/lib/crypto/c_src/hmac.c +++ b/lib/crypto/c_src/hmac.c @@ -84,11 +84,17 @@ ERL_NIF_TERM hmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context *obj) { + if (obj == NULL) + return; + if (obj->alive) { - HMAC_CTX_free(obj->ctx); + if (obj->ctx) + HMAC_CTX_free(obj->ctx); obj->alive = 0; } - enif_mutex_destroy(obj->mtx); + + if (obj->mtx != NULL) + enif_mutex_destroy(obj->mtx); } ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From a309fd02f97dbc35eb8b7d3bafdb219a7275f79b Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 23:55:25 -0800 Subject: Add limits.h to the common header A number of files will do bounds checking. --- lib/crypto/c_src/common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/crypto/c_src/common.h b/lib/crypto/c_src/common.h index 1259ba1f36..237073c194 100644 --- a/lib/crypto/c_src/common.h +++ b/lib/crypto/c_src/common.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "openssl_config.h" -- cgit v1.2.3 From 8dcf1c1b4d487f1822ba1d78a6de3ef3c465eead Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 15:36:39 -0800 Subject: Revamp cmac_nif() * Add error checking on all OpenSSL and Erlang calls. --- lib/crypto/c_src/cmac.c | 60 ++++++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/lib/crypto/c_src/cmac.c b/lib/crypto/c_src/cmac.c index 526de11a01..303b7af6eb 100644 --- a/lib/crypto/c_src/cmac.c +++ b/lib/crypto/c_src/cmac.c @@ -26,40 +26,54 @@ ERL_NIF_TERM cmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) #if defined(HAVE_CMAC) struct cipher_type_t *cipherp = NULL; const EVP_CIPHER *cipher; - CMAC_CTX *ctx; + CMAC_CTX *ctx = NULL; ErlNifBinary key; ErlNifBinary data; ERL_NIF_TERM ret; size_t ret_size; + unsigned char *outp; + int cipher_len; - if (!enif_inspect_iolist_as_binary(env, argv[1], &key) - || !(cipherp = get_cipher_type(argv[0], key.size)) - || !enif_inspect_iolist_as_binary(env, argv[2], &data)) { - return enif_make_badarg(env); - } - cipher = cipherp->cipher.p; - if (!cipher) { + if (argc != 3) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) + goto bad_arg; + if ((cipherp = get_cipher_type(argv[0], key.size)) == NULL) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[2], &data)) + goto bad_arg; + + if ((cipher = cipherp->cipher.p) == NULL) return enif_raise_exception(env, atom_notsup); - } - ctx = CMAC_CTX_new(); - if (!CMAC_Init(ctx, key.data, key.size, cipher, NULL)) { - CMAC_CTX_free(ctx); - return atom_notsup; - } + if ((ctx = CMAC_CTX_new()) == NULL) + goto err; + if (!CMAC_Init(ctx, key.data, key.size, cipher, NULL)) + goto err; + if (!CMAC_Update(ctx, data.data, data.size)) + goto err; + if ((cipher_len = EVP_CIPHER_block_size(cipher)) < 0) + goto err; + if ((outp = enif_make_new_binary(env, (size_t)cipher_len, &ret)) == NULL) + goto err; + if (!CMAC_Final(ctx, outp, &ret_size)) + goto err; - if (!CMAC_Update(ctx, data.data, data.size) || - !CMAC_Final(ctx, - enif_make_new_binary(env, EVP_CIPHER_block_size(cipher), &ret), - &ret_size)) { - CMAC_CTX_free(ctx); - return atom_notsup; - } ASSERT(ret_size == (unsigned)EVP_CIPHER_block_size(cipher)); - - CMAC_CTX_free(ctx); CONSUME_REDS(env, data); + goto done; + + bad_arg: + return enif_make_badarg(env); + + err: + ret = atom_notsup; + + done: + if (ctx) + CMAC_CTX_free(ctx); return ret; + #else /* The CMAC functionality was introduced in OpenSSL 1.0.1 * Although OTP requires at least version 0.9.8, the versions 0.9.8 and 1.0.0 are -- cgit v1.2.3 From a1660045fc9e88b8f6a2615f3941177fcaa5541d Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 15:45:34 -0800 Subject: Revamp do_exor() * Add additional error checking. --- lib/crypto/c_src/math.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/lib/crypto/c_src/math.c b/lib/crypto/c_src/math.c index 7d7d146ca9..a7a385e404 100644 --- a/lib/crypto/c_src/math.c +++ b/lib/crypto/c_src/math.c @@ -24,20 +24,30 @@ ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Data1, Data2) */ ErlNifBinary d1, d2; unsigned char* ret_ptr; - int i; + size_t i; ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env,argv[0], &d1) - || !enif_inspect_iolist_as_binary(env,argv[1], &d2) - || d1.size != d2.size) { - return enif_make_badarg(env); - } - ret_ptr = enif_make_new_binary(env, d1.size, &ret); + if (argc != 2) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[0], &d1)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &d2)) + goto bad_arg; + if (d1.size != d2.size) + goto bad_arg; + + if ((ret_ptr = enif_make_new_binary(env, d1.size, &ret)) == NULL) + goto err; for (i=0; i Date: Thu, 3 Jan 2019 15:56:32 -0800 Subject: Revamp get_eddsa_key() * pkey is only set on success. --- lib/crypto/c_src/eddsa.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/lib/crypto/c_src/eddsa.c b/lib/crypto/c_src/eddsa.c index 0fdada9677..0c89f9f6db 100644 --- a/lib/crypto/c_src/eddsa.c +++ b/lib/crypto/c_src/eddsa.c @@ -24,28 +24,40 @@ int get_eddsa_key(ErlNifEnv* env, int public, ERL_NIF_TERM key, EVP_PKEY **pkey) { /* key=[K] */ + EVP_PKEY *result; ERL_NIF_TERM head, tail, tail2, algo; ErlNifBinary bin; int type; - if (!enif_get_list_cell(env, key, &head, &tail) - || !enif_inspect_binary(env, head, &bin) - || !enif_get_list_cell(env, tail, &algo, &tail2) - || !enif_is_empty_list(env, tail2)) { - return 0; + if (!enif_get_list_cell(env, key, &head, &tail)) + goto err; + if (!enif_inspect_binary(env, head, &bin)) + goto err; + if (!enif_get_list_cell(env, tail, &algo, &tail2)) + goto err; + if (!enif_is_empty_list(env, tail2)) + goto err; + + if (algo == atom_ed25519) { + type = EVP_PKEY_ED25519; + } else if (algo == atom_ed448) { + type = EVP_PKEY_ED448; + } else { + goto err; } - if (algo == atom_ed25519) type = EVP_PKEY_ED25519; - else if (algo == atom_ed448) type = EVP_PKEY_ED448; - else - return 0; if (public) - *pkey = EVP_PKEY_new_raw_public_key(type, NULL, bin.data, bin.size); + result = EVP_PKEY_new_raw_public_key(type, NULL, bin.data, bin.size); else - *pkey = EVP_PKEY_new_raw_private_key(type, NULL, bin.data, bin.size); + result = EVP_PKEY_new_raw_private_key(type, NULL, bin.data, bin.size); + + if (result == NULL) + goto err; - if (!pkey) - return 0; + *pkey = result; return 1; + + err: + return 0; } #endif -- cgit v1.2.3 From 6b9ad247b06449d415e3085c20a2d2978d8ad981 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 17:51:25 -0800 Subject: Revamp rc4_set_key() * Bounds check key.size before casting. --- lib/crypto/c_src/rc4.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/crypto/c_src/rc4.c b/lib/crypto/c_src/rc4.c index 483c87b04b..d5b32d88bd 100644 --- a/lib/crypto/c_src/rc4.c +++ b/lib/crypto/c_src/rc4.c @@ -25,15 +25,27 @@ ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) #ifndef OPENSSL_NO_RC4 ErlNifBinary key; ERL_NIF_TERM ret; + RC4_KEY *rc4_key; CHECK_NO_FIPS_MODE(); - if (!enif_inspect_iolist_as_binary(env,argv[0], &key)) { - return enif_make_badarg(env); - } - RC4_set_key((RC4_KEY*)enif_make_new_binary(env, sizeof(RC4_KEY), &ret), - key.size, key.data); + if (argc != 1) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[0], &key)) + goto bad_arg; + if (key.size > INT_MAX) + goto bad_arg; + + if ((rc4_key = (RC4_KEY*)enif_make_new_binary(env, sizeof(RC4_KEY), &ret)) == NULL) + goto err; + + RC4_set_key(rc4_key, (int)key.size, key.data); return ret; + + bad_arg: + err: + return enif_make_badarg(env); + #else return enif_raise_exception(env, atom_notsup); #endif -- cgit v1.2.3 From 5727586180313ec6ea361fdadc2367b35e5b46a5 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 17:58:54 -0800 Subject: Revamp poly1305_nif() * Fix a possible memory leak where enif_alloc_binary() wasn't always converted into a term or freed in the error path. --- lib/crypto/c_src/poly1305.c | 68 ++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/lib/crypto/c_src/poly1305.c b/lib/crypto/c_src/poly1305.c index 3e2bcfa60e..da434e4eb9 100644 --- a/lib/crypto/c_src/poly1305.c +++ b/lib/crypto/c_src/poly1305.c @@ -25,54 +25,66 @@ ERL_NIF_TERM poly1305_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Key, Text) */ #ifdef HAVE_POLY1305 ErlNifBinary key_bin, text, ret_bin; - ERL_NIF_TERM ret = atom_error; + ERL_NIF_TERM ret; EVP_PKEY *key = NULL; EVP_MD_CTX *mctx = NULL; EVP_PKEY_CTX *pctx = NULL; const EVP_MD *md = NULL; size_t size; - int type; + int ret_bin_alloc = 0; - type = EVP_PKEY_POLY1305; + if (argc != 2) + goto bad_arg; + if (!enif_inspect_binary(env, argv[0], &key_bin)) + goto bad_arg; + if (key_bin.size != 32) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &text)) + goto bad_arg; - if (!enif_inspect_binary(env, argv[0], &key_bin) || - !(key_bin.size == 32) ) { - return enif_make_badarg(env); - } - - if (!enif_inspect_binary(env, argv[1], &text) ) { - return enif_make_badarg(env); - } - - key = EVP_PKEY_new_raw_private_key(type, /*engine*/ NULL, key_bin.data, key_bin.size); - - if (!key || - !(mctx = EVP_MD_CTX_new()) || - !EVP_DigestSignInit(mctx, &pctx, md, /*engine*/ NULL, key) || - !EVP_DigestSignUpdate(mctx, text.data, text.size)) { + if ((key = EVP_PKEY_new_raw_private_key(EVP_PKEY_POLY1305, /*engine*/ NULL, key_bin.data, key_bin.size)) == NULL) goto err; - } - if (!EVP_DigestSignFinal(mctx, NULL, &size) || - !enif_alloc_binary(size, &ret_bin) || - !EVP_DigestSignFinal(mctx, ret_bin.data, &size)) { + if ((mctx = EVP_MD_CTX_new()) == NULL) + goto err; + if (EVP_DigestSignInit(mctx, &pctx, md, /*engine*/ NULL, key) != 1) + goto err; + if (EVP_DigestSignUpdate(mctx, text.data, text.size) != 1) goto err; - } - if ((size != ret_bin.size) && - !enif_realloc_binary(&ret_bin, size)) { + if (EVP_DigestSignFinal(mctx, NULL, &size) != 1) + goto err; + if (!enif_alloc_binary(size, &ret_bin)) goto err; + ret_bin_alloc = 1; + if (EVP_DigestSignFinal(mctx, ret_bin.data, &size) != 1) + goto err; + + if (size != ret_bin.size) { + if (!enif_realloc_binary(&ret_bin, size)) + goto err; } ret = enif_make_binary(env, &ret_bin); + ret_bin_alloc = 0; + goto done; + + bad_arg: + return enif_make_badarg(env); err: - EVP_MD_CTX_free(mctx); - EVP_PKEY_free(key); + if (ret_bin_alloc) + enif_release_binary(&ret_bin); + ret = atom_error; + + done: + if (mctx) + EVP_MD_CTX_free(mctx); + if (key) + EVP_PKEY_free(key); return ret; #else return atom_notsup; #endif } - -- cgit v1.2.3 From bf063a86501f47cbfa89475aefe5bfacde56a3c9 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 18:09:20 -0800 Subject: Revamp chacha20_stream_init() * Check return values on all OpenSSL calls. * Remove trailing semicolon after function definition. --- lib/crypto/c_src/chacha20.c | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/lib/crypto/c_src/chacha20.c b/lib/crypto/c_src/chacha20.c index 8b21a0c7af..587c0cea53 100644 --- a/lib/crypto/c_src/chacha20.c +++ b/lib/crypto/c_src/chacha20.c @@ -25,33 +25,51 @@ ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM a {/* (Key, IV) */ #if defined(HAVE_CHACHA20) ErlNifBinary key_bin, ivec_bin; - struct evp_cipher_ctx *ctx; + struct evp_cipher_ctx *ctx = NULL; const EVP_CIPHER *cipher; ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) - || !enif_inspect_binary(env, argv[1], &ivec_bin) - || key_bin.size != 32 - || ivec_bin.size != 16) { - return enif_make_badarg(env); - } + if (argc != 2) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)) + goto bad_arg; + if (key_bin.size != 32) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &ivec_bin)) + goto bad_arg; + if (ivec_bin.size != 16) + goto bad_arg; cipher = EVP_chacha20(); - ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx)); - ctx->ctx = EVP_CIPHER_CTX_new(); + if ((ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx))) == NULL) + goto err; + if ((ctx->ctx = EVP_CIPHER_CTX_new()) == NULL) + goto err; + if (EVP_CipherInit_ex(ctx->ctx, cipher, NULL, + key_bin.data, ivec_bin.data, 1) != 1) + goto err; + if (EVP_CIPHER_CTX_set_padding(ctx->ctx, 0) != 1) + goto err; - EVP_CipherInit_ex(ctx->ctx, cipher, NULL, - key_bin.data, ivec_bin.data, 1); - EVP_CIPHER_CTX_set_padding(ctx->ctx, 0); ret = enif_make_resource(env, ctx); + goto done; + + bad_arg: + return enif_make_badarg(env); + + err: + ret = enif_make_badarg(env); + + done: enif_release_resource(ctx); return ret; + #else return enif_raise_exception(env, atom_notsup); #endif -}; +} ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (State, Data) */ -- cgit v1.2.3 From 10665143d538b0ed344d172655e174713da3a336 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 18:14:55 -0800 Subject: Revamp chacha20_stream_crypt() * Check return values on all OpenSSL and Erlang calls. * Remove trailing semicolon after function definition. --- lib/crypto/c_src/chacha20.c | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/lib/crypto/c_src/chacha20.c b/lib/crypto/c_src/chacha20.c index 587c0cea53..03b8589524 100644 --- a/lib/crypto/c_src/chacha20.c +++ b/lib/crypto/c_src/chacha20.c @@ -74,28 +74,49 @@ ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM a ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (State, Data) */ #if defined(HAVE_CHACHA20) - struct evp_cipher_ctx *ctx, *new_ctx; + struct evp_cipher_ctx *ctx = NULL, *new_ctx = NULL; ErlNifBinary data_bin; ERL_NIF_TERM ret, cipher_term; unsigned char *out; int outl = 0; - if (!enif_get_resource(env, argv[0], evp_cipher_ctx_rtype, (void**)&ctx) - || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { - return enif_make_badarg(env); - } - new_ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx)); - new_ctx->ctx = EVP_CIPHER_CTX_new(); - EVP_CIPHER_CTX_copy(new_ctx->ctx, ctx->ctx); - out = enif_make_new_binary(env, data_bin.size, &cipher_term); - EVP_CipherUpdate(new_ctx->ctx, out, &outl, data_bin.data, data_bin.size); + if (argc != 2) + goto bad_arg; + if (!enif_get_resource(env, argv[0], evp_cipher_ctx_rtype, (void**)&ctx)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) + goto bad_arg; + if (data_bin.size > INT_MAX) + goto bad_arg; + + if ((new_ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx))) == NULL) + goto err; + if ((new_ctx->ctx = EVP_CIPHER_CTX_new()) == NULL) + goto err; + + if (EVP_CIPHER_CTX_copy(new_ctx->ctx, ctx->ctx) != 1) + goto err; + if ((out = enif_make_new_binary(env, data_bin.size, &cipher_term)) == NULL) + goto err; + if (EVP_CipherUpdate(new_ctx->ctx, out, &outl, data_bin.data, (int)data_bin.size) != 1) + goto err; ASSERT(outl == data_bin.size); ret = enif_make_tuple2(env, enif_make_resource(env, new_ctx), cipher_term); + CONSUME_REDS(env, data_bin); + goto done; + + bad_arg: + return enif_make_badarg(env); + + err: + ret = enif_make_badarg(env); + + done: enif_release_resource(new_ctx); - CONSUME_REDS(env,data_bin); return ret; + #else return enif_raise_exception(env, atom_notsup); #endif -}; +} -- cgit v1.2.3 From e8813319d24ed1f8200b09969b015fb2311967f9 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 18:32:08 -0800 Subject: Revamp ecdh_compute_key_nif() * Bug fix: ECDH_compute_key was not being checked for failures - That function returns 0 on failure and never returns < 0. - Using <= 0 check because OpenSSL uses that internally and on their wiki. * Remove unnecessary variable i * Make the gotos always flow downward rather than jumping back. --- lib/crypto/c_src/ecdh.c | 66 ++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/lib/crypto/c_src/ecdh.c b/lib/crypto/c_src/ecdh.c index d458f3c48e..ee4b352730 100644 --- a/lib/crypto/c_src/ecdh.c +++ b/lib/crypto/c_src/ecdh.c @@ -32,48 +32,62 @@ ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a ERL_NIF_TERM ret; unsigned char *p; EC_KEY* key = NULL; - int field_size = 0; - int i; - EC_GROUP *group; + int degree; + size_t field_size; + EC_GROUP *group = NULL; const BIGNUM *priv_key; EC_POINT *my_ecpoint = NULL; EC_KEY *other_ecdh = NULL; + if (argc != 3) + goto bad_arg; if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key)) - return make_badarg_maybe(env); - - group = EC_GROUP_dup(EC_KEY_get0_group(key)); + goto bad_arg; + if ((group = EC_GROUP_dup(EC_KEY_get0_group(key))) == NULL) + goto bad_arg; priv_key = EC_KEY_get0_private_key(key); if (!term2point(env, argv[0], group, &my_ecpoint)) { - goto out_err; + goto err; } - if ((other_ecdh = EC_KEY_new()) == NULL - || !EC_KEY_set_group(other_ecdh, group) - || !EC_KEY_set_private_key(other_ecdh, priv_key)) - goto out_err; + if ((other_ecdh = EC_KEY_new()) == NULL) + goto err; + if (!EC_KEY_set_group(other_ecdh, group)) + goto err; + if (!EC_KEY_set_private_key(other_ecdh, priv_key)) + goto err; - field_size = EC_GROUP_get_degree(group); - if (field_size <= 0) - goto out_err; + if ((degree = EC_GROUP_get_degree(group)) <= 0) + goto err; - p = enif_make_new_binary(env, (field_size+7)/8, &ret); - i = ECDH_compute_key(p, (field_size+7)/8, my_ecpoint, other_ecdh, NULL); + 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; - if (i < 0) - goto out_err; -out: - if (group) EC_GROUP_free(group); - if (my_ecpoint) EC_POINT_free(my_ecpoint); - if (other_ecdh) EC_KEY_free(other_ecdh); - if (key) EC_KEY_free(key); + goto done; - return ret; + bad_arg: + ret = make_badarg_maybe(env); + goto done; -out_err: + err: ret = enif_make_badarg(env); - goto out; + + done: + if (group) + EC_GROUP_free(group); + if (my_ecpoint) + EC_POINT_free(my_ecpoint); + if (other_ecdh) + EC_KEY_free(other_ecdh); + if (key) + EC_KEY_free(key); + + return ret; + #else return atom_notsup; #endif -- cgit v1.2.3 From 74a4f7b390581859b798079484f4af2644d41ee2 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 18:41:37 -0800 Subject: Revamp get_dss_private_key() * Simplify logic by having incremental allocation and only free on error in one place. * Add error checking on all OpenSSL calls. * Make it explicit when you need to be careful with non-ref counted pointers. - set0 calls will save the pointer without reference counting. - On success, set pointers to NULL to avoid double frees since the struct is now responsible for freeing the resources. --- lib/crypto/c_src/dss.c | 71 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 20 deletions(-) diff --git a/lib/crypto/c_src/dss.c b/lib/crypto/c_src/dss.c index 9d39241382..934b33d87c 100644 --- a/lib/crypto/c_src/dss.c +++ b/lib/crypto/c_src/dss.c @@ -26,36 +26,67 @@ int get_dss_private_key(ErlNifEnv* env, ERL_NIF_TERM key, DSA *dsa) /* key=[P,Q,G,KEY] */ ERL_NIF_TERM head, tail; BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL; - BIGNUM *dummy_pub_key, *priv_key = NULL; + BIGNUM *dummy_pub_key = NULL, *priv_key = NULL; - if (!enif_get_list_cell(env, key, &head, &tail) - || !get_bn_from_bin(env, head, &dsa_p) - || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &dsa_q) - || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &dsa_g) - || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &priv_key) - || !enif_is_empty_list(env,tail)) { - if (dsa_p) BN_free(dsa_p); - if (dsa_q) BN_free(dsa_q); - if (dsa_g) BN_free(dsa_g); - if (priv_key) BN_free(priv_key); - return 0; - } + if (!enif_get_list_cell(env, key, &head, &tail)) + goto err; + if (!get_bn_from_bin(env, head, &dsa_p)) + goto err; + + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto err; + if (!get_bn_from_bin(env, head, &dsa_q)) + goto err; + + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto err; + if (!get_bn_from_bin(env, head, &dsa_g)) + goto err; + + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto err; + if (!get_bn_from_bin(env, head, &priv_key)) + goto err; + + if (!enif_is_empty_list(env, tail)) + goto err; /* Note: DSA_set0_key() does not allow setting only the * private key, although DSA_sign() does not use the * public key. Work around this limitation by setting * the public key to a copy of the private key. */ - dummy_pub_key = BN_dup(priv_key); + if ((dummy_pub_key = BN_dup(priv_key)) == NULL) + goto err; + + if (!DSA_set0_pqg(dsa, dsa_p, dsa_q, dsa_g)) + goto err; + /* dsa takes ownership on success */ + dsa_p = NULL; + dsa_q = NULL; + dsa_g = NULL; + + if (!DSA_set0_key(dsa, dummy_pub_key, priv_key)) + goto err; + /* dsa takes ownership on success */ + dummy_pub_key = NULL; + priv_key = NULL; - DSA_set0_pqg(dsa, dsa_p, dsa_q, dsa_g); - DSA_set0_key(dsa, dummy_pub_key, priv_key); return 1; -} + err: + if (dsa_p) + BN_free(dsa_p); + if (dsa_q) + BN_free(dsa_q); + if (dsa_g) + BN_free(dsa_g); + if (priv_key) + BN_free(priv_key); + if (dummy_pub_key) + BN_free(dummy_pub_key); + return 0; +} int get_dss_public_key(ErlNifEnv* env, ERL_NIF_TERM key, DSA *dsa) { -- cgit v1.2.3 From 7ad28fd1bd0b6504c78c5d76903878cebd5cd631 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 18:46:08 -0800 Subject: Revamp get_dss_public_key() * Simplify logic by having incremental allocation and only free on error on one place. * Add error checking on all OpenSSL calls. * Make it explicit when you need to be careful with non-reference counted pointers. - set0 calls will use the pointer values without ref counting. - On success, set pointers to NULL to avoid double frees since the struct is now responsible for freeing the resources. --- lib/crypto/c_src/dss.c | 64 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/lib/crypto/c_src/dss.c b/lib/crypto/c_src/dss.c index 934b33d87c..9bf8eb3ce0 100644 --- a/lib/crypto/c_src/dss.c +++ b/lib/crypto/c_src/dss.c @@ -94,23 +94,51 @@ int get_dss_public_key(ErlNifEnv* env, ERL_NIF_TERM key, DSA *dsa) ERL_NIF_TERM head, tail; BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_y = NULL; - if (!enif_get_list_cell(env, key, &head, &tail) - || !get_bn_from_bin(env, head, &dsa_p) - || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &dsa_q) - || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &dsa_g) - || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &dsa_y) - || !enif_is_empty_list(env,tail)) { - if (dsa_p) BN_free(dsa_p); - if (dsa_q) BN_free(dsa_q); - if (dsa_g) BN_free(dsa_g); - if (dsa_y) BN_free(dsa_y); - return 0; - } - - DSA_set0_pqg(dsa, dsa_p, dsa_q, dsa_g); - DSA_set0_key(dsa, dsa_y, NULL); + if (!enif_get_list_cell(env, key, &head, &tail)) + goto err; + if (!get_bn_from_bin(env, head, &dsa_p)) + goto err; + + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto err; + if (!get_bn_from_bin(env, head, &dsa_q)) + goto err; + + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto err; + if (!get_bn_from_bin(env, head, &dsa_g)) + goto err; + + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto err; + if (!get_bn_from_bin(env, head, &dsa_y)) + goto err; + + if (!enif_is_empty_list(env,tail)) + goto err; + + if (!DSA_set0_pqg(dsa, dsa_p, dsa_q, dsa_g)) + goto err; + /* dsa takes ownership on success */ + dsa_p = NULL; + dsa_q = NULL; + dsa_g = NULL; + + if (!DSA_set0_key(dsa, dsa_y, NULL)) + goto err; + /* dsa takes ownership on success */ + dsa_y = NULL; + return 1; + + err: + if (dsa_p) + BN_free(dsa_p); + if (dsa_q) + BN_free(dsa_q); + if (dsa_g) + BN_free(dsa_g); + if (dsa_y) + BN_free(dsa_y); + return 0; } -- cgit v1.2.3 From c41e0bb6d6981ab6fcf33365efa6ddd194fddd39 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 18:55:31 -0800 Subject: Revamp change_basename() * Change the parameter from int to size_t. - Only caller doesn't need to change since it was already passing sizeof(). * Add unsigned wrapping checks. --- lib/crypto/c_src/info.c | 21 +++++++++++++++------ lib/crypto/c_src/info.h | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/crypto/c_src/info.c b/lib/crypto/c_src/info.c index 3f3194081d..d4e230dffd 100644 --- a/lib/crypto/c_src/info.c +++ b/lib/crypto/c_src/info.c @@ -30,21 +30,30 @@ char *crypto_callback_name = "crypto_callback.valgrind"; char *crypto_callback_name = "crypto_callback"; # endif -int change_basename(ErlNifBinary* bin, char* buf, int bufsz, const char* newfile) +int change_basename(ErlNifBinary* bin, char* buf, size_t bufsz, const char* newfile) { - int i; + size_t i; + size_t newlen; for (i = bin->size; i > 0; i--) { if (bin->data[i-1] == '/') break; } - if (i + strlen(newfile) >= bufsz) { - PRINTF_ERR0("CRYPTO: lib name too long"); - return 0; - } + + newlen = strlen(newfile); + if (i > SIZE_MAX - newlen) + goto err; + + if (i + newlen >= bufsz) + goto err; + memcpy(buf, bin->data, i); strcpy(buf+i, newfile); + return 1; + + err: + return 0; } void error_handler(void* null, const char* errstr) diff --git a/lib/crypto/c_src/info.h b/lib/crypto/c_src/info.h index 4f8822ddd7..67690625c9 100644 --- a/lib/crypto/c_src/info.h +++ b/lib/crypto/c_src/info.h @@ -26,7 +26,7 @@ #ifdef HAVE_DYNAMIC_CRYPTO_LIB extern char *crypto_callback_name; -int change_basename(ErlNifBinary* bin, char* buf, int bufsz, const char* newfile); +int change_basename(ErlNifBinary* bin, char* buf, size_t bufsz, const char* newfile); void error_handler(void* null, const char* errstr); #endif -- cgit v1.2.3 From 03889bc9dda3cf7e6cbacc11ef8e964982cd296e Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 18:59:40 -0800 Subject: Revamp info_lib() * Add error checking and use enif_make_badarg() on error. * Use size_t when using sizeof(). * Move initialization away from declaration so it's not as easy to miss. --- lib/crypto/c_src/info.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/lib/crypto/c_src/info.c b/lib/crypto/c_src/info.c index d4e230dffd..2411968b95 100644 --- a/lib/crypto/c_src/info.c +++ b/lib/crypto/c_src/info.c @@ -62,16 +62,26 @@ void error_handler(void* null, const char* errstr) } #endif /* HAVE_DYNAMIC_CRYPTO_LIB */ -ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ +ERL_NIF_TERM info_lib(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{/* () */ /* [{<<"OpenSSL">>,9470143,<<"OpenSSL 0.9.8k 25 Mar 2009">>}] */ - static const char libname[] = "OpenSSL"; - unsigned name_sz = strlen(libname); - const char* ver = SSLeay_version(SSLEAY_VERSION); - unsigned ver_sz = strlen(ver); ERL_NIF_TERM name_term, ver_term; - int ver_num = OPENSSL_VERSION_NUMBER; + static const char libname[] = "OpenSSL"; + size_t name_sz; + const char* ver; + size_t ver_sz; + int ver_num; + unsigned char *out_name, *out_ver; + + if (argc != 0) + goto bad_arg; + + name_sz = strlen(libname); + ver = SSLeay_version(SSLEAY_VERSION); + ver_sz = strlen(ver); + ver_num = OPENSSL_VERSION_NUMBER; + /* R16: * Ignore library version number from SSLeay() and instead show header * version. Otherwise user might try to call a function that is implemented @@ -81,10 +91,19 @@ ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) * Version string is still from library though. */ - memcpy(enif_make_new_binary(env, name_sz, &name_term), libname, name_sz); - memcpy(enif_make_new_binary(env, ver_sz, &ver_term), ver, ver_sz); + if ((out_name = enif_make_new_binary(env, name_sz, &name_term)) == NULL) + goto err; + if ((out_ver = enif_make_new_binary(env, ver_sz, &ver_term)) == NULL) + goto err; + + memcpy(out_name, libname, name_sz); + memcpy(out_ver, ver, ver_sz); return enif_make_list1(env, enif_make_tuple3(env, name_term, enif_make_int(env, ver_num), ver_term)); + + bad_arg: + err: + return enif_make_badarg(env); } -- cgit v1.2.3 From 536f1fff1596de0c1591e9c796d0ab8b6caf21e7 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 19:12:39 -0800 Subject: Revamp strong_rand_bytes_nif() * Add bounds check before casting. --- lib/crypto/c_src/rand.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/lib/crypto/c_src/rand.c b/lib/crypto/c_src/rand.c index e71e202f36..37d4490fc4 100644 --- a/lib/crypto/c_src/rand.c +++ b/lib/crypto/c_src/rand.c @@ -27,15 +27,26 @@ ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned char* data; ERL_NIF_TERM ret; - if (!enif_get_uint(env, argv[0], &bytes)) { - return enif_make_badarg(env); - } - data = enif_make_new_binary(env, bytes, &ret); - if ( RAND_bytes(data, bytes) != 1) { - return atom_false; - } + if (argc != 1) + goto bad_arg; + if (!enif_get_uint(env, argv[0], &bytes)) + goto bad_arg; + if (bytes > INT_MAX) + goto bad_arg; + + if ((data = enif_make_new_binary(env, bytes, &ret)) == NULL) + goto err; + if (RAND_bytes(data, (int)bytes) != 1) + goto err; + ERL_VALGRIND_MAKE_MEM_DEFINED(data, bytes); return ret; + + bad_arg: + return enif_make_badarg(env); + + err: + return atom_false; } ERL_NIF_TERM strong_rand_range_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From ce0d975cde2d67c8e5dd3fa024559f4d0a2df7ad Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 19:15:46 -0800 Subject: Revamp strong_rand_range_nif() * Add error checking for all OpenSSL calls. --- lib/crypto/c_src/rand.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/lib/crypto/c_src/rand.c b/lib/crypto/c_src/rand.c index 37d4490fc4..4a8be4c55f 100644 --- a/lib/crypto/c_src/rand.c +++ b/lib/crypto/c_src/rand.c @@ -51,22 +51,33 @@ ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ERL_NIF_TERM strong_rand_range_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Range) */ - BIGNUM *bn_range, *bn_rand; + BIGNUM *bn_range = NULL, *bn_rand = NULL; ERL_NIF_TERM ret; - if(!get_bn_from_bin(env, argv[0], &bn_range)) { - return enif_make_badarg(env); - } + if (argc != 1) + goto bad_arg; + if (!get_bn_from_bin(env, argv[0], &bn_range)) + goto bad_arg; - bn_rand = BN_new(); - if (BN_rand_range(bn_rand, bn_range) != 1) { - ret = atom_false; - } - else { - ret = bin_from_bn(env, bn_rand); - } - BN_free(bn_rand); - BN_free(bn_range); + if ((bn_rand = BN_new()) == NULL) + goto err; + if (!BN_rand_range(bn_rand, bn_range)) + goto err; + + ret = bin_from_bn(env, bn_rand); + goto done; + + bad_arg: + return enif_make_badarg(env); + + err: + ret = atom_false; + + done: + if (bn_rand) + BN_free(bn_rand); + if (bn_range) + BN_free(bn_range); return ret; } -- cgit v1.2.3 From 96787650f6616db15b737627fff66feaf63a4f69 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 19:24:11 -0800 Subject: Revamp rand_uniform_nif() * Add error handling for all OpenSSL calls. --- lib/crypto/c_src/rand.c | 54 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/lib/crypto/c_src/rand.c b/lib/crypto/c_src/rand.c index 4a8be4c55f..4f3c8dd500 100644 --- a/lib/crypto/c_src/rand.c +++ b/lib/crypto/c_src/rand.c @@ -83,29 +83,49 @@ ERL_NIF_TERM strong_rand_range_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM 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; + BIGNUM *bn_from = NULL, *bn_to = NULL, *bn_rand = NULL; unsigned char* data; - unsigned dlen; + int dlen; ERL_NIF_TERM ret; - if (!get_bn_from_mpint(env, argv[0], &bn_from) - || !get_bn_from_mpint(env, argv[1], &bn_rand)) { - if (bn_from) BN_free(bn_from); - return enif_make_badarg(env); - } - - bn_to = BN_new(); - BN_sub(bn_to, bn_rand, bn_from); - BN_pseudo_rand_range(bn_rand, bn_to); - BN_add(bn_rand, bn_rand, bn_from); - dlen = BN_num_bytes(bn_rand); - data = enif_make_new_binary(env, dlen+4, &ret); + if (argc != 2) + goto bad_arg; + if (!get_bn_from_mpint(env, argv[0], &bn_from)) + goto bad_arg; + if (!get_bn_from_mpint(env, argv[1], &bn_rand)) + goto bad_arg; + + if ((bn_to = BN_new()) == NULL) + goto err; + + if (!BN_sub(bn_to, bn_rand, bn_from)) + goto err; + if (!BN_pseudo_rand_range(bn_rand, bn_to)) + goto err; + if (!BN_add(bn_rand, bn_rand, bn_from)) + goto err; + + if ((dlen = BN_num_bytes(bn_rand)) < 0) + goto err; + if ((data = enif_make_new_binary(env, (size_t)dlen+4, &ret)) == NULL) + goto err; + put_int32(data, dlen); BN_bn2bin(bn_rand, data+4); ERL_VALGRIND_MAKE_MEM_DEFINED(data+4, dlen); - BN_free(bn_rand); - BN_free(bn_from); - BN_free(bn_to); + goto done; + + bad_arg: + err: + ret = enif_make_badarg(env); + + done: + if (bn_rand) + BN_free(bn_rand); + if (bn_from) + BN_free(bn_from); + if (bn_to) + BN_free(bn_to); return ret; } -- cgit v1.2.3 From e084364e9e41cbc1933a5c0646ce6ad42f4ff8d1 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 19:27:59 -0800 Subject: Revamp rand_seed_nif() * Bounds check before casting. --- lib/crypto/c_src/rand.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/crypto/c_src/rand.c b/lib/crypto/c_src/rand.c index 4f3c8dd500..dd1a7a1600 100644 --- a/lib/crypto/c_src/rand.c +++ b/lib/crypto/c_src/rand.c @@ -130,12 +130,19 @@ ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ } ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ +{/* (Seed) */ ErlNifBinary seed_bin; + if (argc != 1) + goto bad_arg; if (!enif_inspect_binary(env, argv[0], &seed_bin)) - return enif_make_badarg(env); - RAND_seed(seed_bin.data,seed_bin.size); + goto bad_arg; + if (seed_bin.size > INT_MAX) + goto bad_arg; + + RAND_seed(seed_bin.data, (int)seed_bin.size); return atom_ok; -} + bad_arg: + return enif_make_badarg(env); +} -- cgit v1.2.3 From d48b585cc3b4b324f30785494d406c7082bf8fdb Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 19:31:14 -0800 Subject: Revamp get_bn_from_mpint() * Add bounds checking. * Add error checking for OpenSSL calls. * Only set argument *bnp on success. --- lib/crypto/c_src/bn.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/lib/crypto/c_src/bn.c b/lib/crypto/c_src/bn.c index b576c46e1e..a8112350dc 100644 --- a/lib/crypto/c_src/bn.c +++ b/lib/crypto/c_src/bn.c @@ -23,18 +23,31 @@ int get_bn_from_mpint(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp) { + BIGNUM *ret; ErlNifBinary bin; int sz; - if (!enif_inspect_binary(env,term,&bin)) { - return 0; - } + + if (!enif_inspect_binary(env, term, &bin)) + goto err; + if (bin.size > INT_MAX - 4) + goto err; + ERL_VALGRIND_ASSERT_MEM_DEFINED(bin.data, bin.size); - sz = bin.size - 4; - if (sz < 0 || get_int32(bin.data) != sz) { - return 0; - } - *bnp = BN_bin2bn(bin.data+4, sz, NULL); + + if (bin.size < 4) + goto err; + sz = (int)bin.size - 4; + if (get_int32(bin.data) != sz) + goto err; + + if ((ret = BN_bin2bn(bin.data+4, sz, NULL)) == NULL) + goto err; + + *bnp = ret; return 1; + + err: + return 0; } int get_bn_from_bin(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp) -- cgit v1.2.3 From 792e83f15c43771342b9f36d940d2c2bd1cfa336 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 19:33:40 -0800 Subject: Revamp get_bn_from_bin() * Add bounds checking. * Add error checking for OpenSSL calls. * Only set *bnp on success. --- lib/crypto/c_src/bn.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/crypto/c_src/bn.c b/lib/crypto/c_src/bn.c index a8112350dc..a111269539 100644 --- a/lib/crypto/c_src/bn.c +++ b/lib/crypto/c_src/bn.c @@ -52,13 +52,24 @@ int get_bn_from_mpint(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp) int get_bn_from_bin(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp) { + BIGNUM *ret; ErlNifBinary bin; - if (!enif_inspect_binary(env,term,&bin)) { - return 0; - } + + if (!enif_inspect_binary(env, term, &bin)) + goto err; + if (bin.size > INT_MAX) + goto err; + ERL_VALGRIND_ASSERT_MEM_DEFINED(bin.data, bin.size); - *bnp = BN_bin2bn(bin.data, bin.size, NULL); + + if ((ret = BN_bin2bn(bin.data, (int)bin.size, NULL)) == NULL) + goto err; + + *bnp = ret; return 1; + + err: + return 0; } ERL_NIF_TERM bin_from_bn(ErlNifEnv* env, const BIGNUM *bn) -- cgit v1.2.3 From 1ff19cc7870d14fc4ba946994162dfd0006e6459 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 19:36:18 -0800 Subject: Revamp bin_from_bn() * Add error handling for all OpenSSL calls - There was nothing returned on error before so use enif_make_badarg(). * Add bounds checking before casting. --- lib/crypto/c_src/bn.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/crypto/c_src/bn.c b/lib/crypto/c_src/bn.c index a111269539..75ddd4c2f2 100644 --- a/lib/crypto/c_src/bn.c +++ b/lib/crypto/c_src/bn.c @@ -79,11 +79,17 @@ ERL_NIF_TERM bin_from_bn(ErlNifEnv* env, const BIGNUM *bn) ERL_NIF_TERM term; /* Copy the bignum into an erlang binary. */ - bn_len = BN_num_bytes(bn); - bin_ptr = enif_make_new_binary(env, bn_len, &term); + if ((bn_len = BN_num_bytes(bn)) < 0) + goto err; + if ((bin_ptr = enif_make_new_binary(env, (size_t)bn_len, &term)) == NULL) + goto err; + BN_bn2bin(bn, bin_ptr); return term; + + err: + return enif_make_badarg(env); } ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From 890b16d224b082d8a077abd0a8a50dc2fc68cf7b Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 19:48:23 -0800 Subject: Revamp mod_exp_nif() * Add error checking for OpenSSL calls. * Change dlen from unsigned to signed since BN_num_bytes is int. * Add bounds checking before casting. * Consolidate all freeing to one location on error or success. --- lib/crypto/c_src/bn.c | 76 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/lib/crypto/c_src/bn.c b/lib/crypto/c_src/bn.c index 75ddd4c2f2..9a426f4f8d 100644 --- a/lib/crypto/c_src/bn.c +++ b/lib/crypto/c_src/bn.c @@ -94,41 +94,67 @@ ERL_NIF_TERM bin_from_bn(ErlNifEnv* env, const BIGNUM *bn) ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Base,Exponent,Modulo,bin_hdr) */ - BIGNUM *bn_base=NULL, *bn_exponent=NULL, *bn_modulo=NULL, *bn_result; - BN_CTX *bn_ctx; + BIGNUM *bn_base = NULL, *bn_exponent = NULL, *bn_modulo = NULL, *bn_result = NULL; + BN_CTX *bn_ctx = NULL; unsigned char* ptr; - unsigned dlen; + int dlen; unsigned bin_hdr; /* return type: 0=plain binary, 4: mpint */ unsigned extra_byte; ERL_NIF_TERM ret; - 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 (argc != 4) + goto bad_arg; + if (!get_bn_from_bin(env, argv[0], &bn_base)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[1], &bn_exponent)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[2], &bn_modulo)) + goto bad_arg; + if (!enif_get_uint(env, argv[3], &bin_hdr)) + goto bad_arg; + if (bin_hdr != 0 && bin_hdr != 4) + goto bad_arg; + + if ((bn_result = BN_new()) == NULL) + goto err; + if ((bn_ctx = BN_CTX_new()) == NULL) + goto err; + + if (!BN_mod_exp(bn_result, bn_base, bn_exponent, bn_modulo, bn_ctx)) + goto err; - if (bn_base) BN_free(bn_base); - if (bn_exponent) BN_free(bn_exponent); - if (bn_modulo) BN_free(bn_modulo); - return enif_make_badarg(env); - } - bn_result = BN_new(); - bn_ctx = BN_CTX_new(); - BN_mod_exp(bn_result, bn_base, bn_exponent, bn_modulo, bn_ctx); dlen = BN_num_bytes(bn_result); - 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 (dlen < 0 || dlen > INT_MAX / 8) + goto bad_arg; + extra_byte = bin_hdr && BN_is_bit_set(bn_result, dlen * 8 - 1); + + if ((ptr = enif_make_new_binary(env, bin_hdr + extra_byte + (unsigned int)dlen, &ret)) == NULL) + goto err; + 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; + put_int32(ptr, extra_byte + (unsigned int)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); - BN_free(bn_exponent); - BN_free(bn_base); + goto done; + + bad_arg: + err: + ret = enif_make_badarg(env); + + done: + if (bn_base) + BN_free(bn_base); + if (bn_exponent) + BN_free(bn_exponent); + if (bn_modulo) + BN_free(bn_modulo); + if (bn_result) + BN_free(bn_result); + if (bn_ctx) + BN_CTX_free(bn_ctx); return ret; } -- cgit v1.2.3 From 05c1ad8eff7ecd61f4e85161033b7cec84d82c1a Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 19:58:07 -0800 Subject: Revamp bn2term() * Add error handling for OpenSSL calls. * Change dlen to signed since BN_num_bytes() returns int. * Use enif_make_badarg() on error since it only returned undefined before in one type of error. --- lib/crypto/c_src/bn.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/crypto/c_src/bn.c b/lib/crypto/c_src/bn.c index 9a426f4f8d..67a6bb6279 100644 --- a/lib/crypto/c_src/bn.c +++ b/lib/crypto/c_src/bn.c @@ -161,17 +161,25 @@ ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) #ifdef HAVE_EC ERL_NIF_TERM bn2term(ErlNifEnv* env, const BIGNUM *bn) { - unsigned dlen; + int dlen; unsigned char* ptr; ERL_NIF_TERM ret; - if (!bn) - return atom_undefined; + if (bn == NULL) + return atom_undefined; dlen = BN_num_bytes(bn); - ptr = enif_make_new_binary(env, dlen, &ret); + if (dlen < 0) + goto err; + if ((ptr = enif_make_new_binary(env, (size_t)dlen, &ret)) == NULL) + goto err; + BN_bn2bin(bn, ptr); + ERL_VALGRIND_MAKE_MEM_DEFINED(ptr, dlen); return ret; + + err: + return enif_make_badarg(env); } #endif -- cgit v1.2.3 From 0367ea0bc6953ec81f6d86e2d66e3411348abac9 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 20:17:16 -0800 Subject: Revamp block_crypt_nif() * Simplify error checking. * Add bounds checking before casting. * Add error checking for all OpenSSL calls. --- lib/crypto/c_src/block.c | 104 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 71 insertions(+), 33 deletions(-) diff --git a/lib/crypto/c_src/block.c b/lib/crypto/c_src/block.c index 2ba3290e9f..3399b7b974 100644 --- a/lib/crypto/c_src/block.c +++ b/lib/crypto/c_src/block.c @@ -27,20 +27,27 @@ ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] struct cipher_type_t *cipherp = NULL; const EVP_CIPHER *cipher; ErlNifBinary key, ivec, text; - EVP_CIPHER_CTX* ctx; + EVP_CIPHER_CTX *ctx = NULL; ERL_NIF_TERM ret; unsigned char *out; int ivec_size, out_size = 0; + int cipher_len; - if (!enif_inspect_iolist_as_binary(env, argv[1], &key) - || !(cipherp = get_cipher_type(argv[0], key.size)) - || !enif_inspect_iolist_as_binary(env, argv[argc - 2], &text)) { - return enif_make_badarg(env); - } - cipher = cipherp->cipher.p; - if (!cipher) { + if (argc != 4 && argc != 5) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) + goto bad_arg; + if (key.size > INT_MAX) + goto bad_arg; + if ((cipherp = get_cipher_type(argv[0], key.size)) == NULL) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[argc - 2], &text)) + goto bad_arg; + if (text.size > INT_MAX) + goto bad_arg; + + if ((cipher = cipherp->cipher.p) == NULL) return enif_raise_exception(env, atom_notsup); - } if (argv[0] == atom_aes_cfb8 && (key.size == 24 || key.size == 32)) { @@ -64,42 +71,73 @@ ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] argv[0] == atom_des_ecb) ivec_size = 0; /* 0.9.8l returns faulty ivec_size */ #endif + if (ivec_size < 0) + goto bad_arg; - if (text.size % EVP_CIPHER_block_size(cipher) != 0 || - (ivec_size == 0 ? argc != 4 - : (argc != 5 || - !enif_inspect_iolist_as_binary(env, argv[2], &ivec) || - ivec.size != ivec_size))) { - return enif_make_badarg(env); + if ((cipher_len = EVP_CIPHER_block_size(cipher)) < 0) + goto bad_arg; + if (text.size % (size_t)cipher_len != 0) + goto bad_arg; + + if (ivec_size == 0) { + if (argc != 4) + goto bad_arg; + } else { + if (argc != 5) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[2], &ivec)) + goto bad_arg; + if (ivec.size != (size_t)ivec_size) + goto bad_arg; } - out = enif_make_new_binary(env, text.size, &ret); + if ((out = enif_make_new_binary(env, text.size, &ret)) == NULL) + goto err; + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) + goto err; - ctx = EVP_CIPHER_CTX_new(); if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, - (argv[argc - 1] == atom_true)) || - !EVP_CIPHER_CTX_set_key_length(ctx, key.size) || - !(EVP_CIPHER_type(cipher) != NID_rc2_cbc || - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, key.size * 8, NULL)) || - !EVP_CipherInit_ex(ctx, NULL, NULL, - key.data, ivec_size ? ivec.data : NULL, -1) || - !EVP_CIPHER_CTX_set_padding(ctx, 0)) { + (argv[argc - 1] == atom_true))) + goto err; + if (!EVP_CIPHER_CTX_set_key_length(ctx, (int)key.size)) + goto err; - EVP_CIPHER_CTX_free(ctx); - return enif_raise_exception(env, atom_notsup); + if (EVP_CIPHER_type(cipher) == NID_rc2_cbc) { + if (key.size > INT_MAX / 8) + goto err; + if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, (int)key.size * 8, NULL)) + goto err; } - if (text.size > 0 && /* OpenSSL 0.9.8h asserts text.size > 0 */ - (!EVP_CipherUpdate(ctx, out, &out_size, text.data, text.size) - || (ASSERT(out_size == text.size), 0) - || !EVP_CipherFinal_ex(ctx, out + out_size, &out_size))) { + if (!EVP_CipherInit_ex(ctx, NULL, NULL, key.data, + ivec_size ? ivec.data : NULL, -1)) + goto err; + if (!EVP_CIPHER_CTX_set_padding(ctx, 0)) + goto err; - EVP_CIPHER_CTX_free(ctx); - return enif_raise_exception(env, atom_notsup); + /* OpenSSL 0.9.8h asserts text.size > 0 */ + if (text.size > 0) { + if (!EVP_CipherUpdate(ctx, out, &out_size, text.data, (int)text.size)) + goto err; + if (ASSERT(out_size == text.size), 0) + goto err; + if (!EVP_CipherFinal_ex(ctx, out + out_size, &out_size)) + goto err; } + ASSERT(out_size == 0); - EVP_CIPHER_CTX_free(ctx); CONSUME_REDS(env, text); + goto done; + bad_arg: + ret = enif_make_badarg(env); + goto done; + + err: + ret = enif_raise_exception(env, atom_notsup); + + done: + if (ctx) + EVP_CIPHER_CTX_free(ctx); return ret; } -- cgit v1.2.3 From f46401d46f9ed331ff2a09bb6a99376707083c96 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 20:29:14 -0800 Subject: Revamp initialize() * Add error handling for all OpenSSL calls. - However, disable custom crypto mem functions for LibreSSL since it has never supported it. --- lib/crypto/c_src/crypto.c | 47 ++++++++++++++++++++------------------- lib/crypto/c_src/openssl_config.h | 5 +++++ 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index fde3d99fa8..d1ff551172 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -166,20 +166,24 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info) int vernum; ErlNifBinary lib_bin; char lib_buf[1000]; +#ifdef HAVE_DYNAMIC_CRYPTO_LIB + void *handle; +#endif if (!verify_lib_version()) return __LINE__; /* load_info: {302, <<"/full/path/of/this/library">>,true|false} */ - if (!enif_get_tuple(env, load_info, &tpl_arity, &tpl_array) - || tpl_arity != 3 - || !enif_get_int(env, tpl_array[0], &vernum) - || vernum != 302 - || !enif_inspect_binary(env, tpl_array[1], &lib_bin)) { - - PRINTF_ERR1("CRYPTO: Invalid load_info '%T'", load_info); - return __LINE__; - } + if (!enif_get_tuple(env, load_info, &tpl_arity, &tpl_array)) + return __LINE__; + if (tpl_arity != 3) + return __LINE__; + if (!enif_get_int(env, tpl_array[0], &vernum)) + return __LINE__; + if (vernum != 302) + return __LINE__; + if (!enif_inspect_binary(env, tpl_array[1], &lib_bin)) + return __LINE__; if (!init_hmac_ctx(env)) { return __LINE__; @@ -206,19 +210,13 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info) } #ifdef HAVE_DYNAMIC_CRYPTO_LIB - { - void* handle; - if (!change_basename(&lib_bin, lib_buf, sizeof(lib_buf), crypto_callback_name)) { - return __LINE__; - } - if (!(handle = enif_dlopen(lib_buf, &error_handler, NULL))) { - return __LINE__; - } - if (!(funcp = (get_crypto_callbacks_t*) enif_dlsym(handle, "get_crypto_callbacks", - &error_handler, NULL))) { - return __LINE__; - } - } + if (!change_basename(&lib_bin, lib_buf, sizeof(lib_buf), crypto_callback_name)) + return __LINE__; + if ((handle = enif_dlopen(lib_buf, &error_handler, NULL)) == NULL) + return __LINE__; + if ((funcp = (get_crypto_callbacks_t*) enif_dlsym(handle, "get_crypto_callbacks", + &error_handler, NULL)) == NULL) + return __LINE__; #else /* !HAVE_DYNAMIC_CRYPTO_LIB */ funcp = &get_crypto_callbacks; #endif @@ -238,7 +236,10 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info) return __LINE__; } - CRYPTO_set_mem_functions(ccb->crypto_alloc, ccb->crypto_realloc, ccb->crypto_free); +#ifdef HAS_CRYPTO_MEM_FUNCTIONS + if (!CRYPTO_set_mem_functions(ccb->crypto_alloc, ccb->crypto_realloc, ccb->crypto_free)) + return __LINE__; +#endif #ifdef OPENSSL_THREADS if (nlocks > 0) { diff --git a/lib/crypto/c_src/openssl_config.h b/lib/crypto/c_src/openssl_config.h index 2e5f5b22c1..e41d0c945e 100644 --- a/lib/crypto/c_src/openssl_config.h +++ b/lib/crypto/c_src/openssl_config.h @@ -89,6 +89,11 @@ # undef FIPS_SUPPORT # endif +/* LibreSSL has never supported the custom mem functions */ +#ifndef HAS_LIBRESSL +# define HAS_CRYPTO_MEM_FUNCTIONS +#endif + # if LIBRESSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION_PLAIN(2,7,0) /* LibreSSL wants the 1.0.1 API */ # define NEED_EVP_COMPATIBILITY_FUNCTIONS -- cgit v1.2.3 From 448cda0d1668a643f8bddf7b0d1c1615e6d952b7 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 20:32:43 -0800 Subject: Revamp get_engine_and_key_id() --- lib/crypto/c_src/engine.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 71552a0a89..95966508ec 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -49,16 +49,20 @@ int get_engine_and_key_id(ErlNifEnv *env, ERL_NIF_TERM key, char ** id, ENGINE * struct engine_ctx *ctx; ErlNifBinary key_id_bin; - if (!enif_get_map_value(env, key, atom_engine, &engine_res) || - !enif_get_resource(env, engine_res, engine_ctx_rtype, (void**)&ctx) || - !enif_get_map_value(env, key, atom_key_id, &key_id_term) || - !enif_inspect_binary(env, key_id_term, &key_id_bin)) { - return 0; - } - else { - *e = ctx->engine; - return zero_terminate(key_id_bin, id); - } + if (!enif_get_map_value(env, key, atom_engine, &engine_res)) + goto err; + if (!enif_get_resource(env, engine_res, engine_ctx_rtype, (void**)&ctx)) + goto err; + if (!enif_get_map_value(env, key, atom_key_id, &key_id_term)) + goto err; + if (!enif_inspect_binary(env, key_id_term, &key_id_bin)) + goto err; + + *e = ctx->engine; + return zero_terminate(key_id_bin, id); + + err: + return 0; } char *get_key_password(ErlNifEnv *env, ERL_NIF_TERM key) { -- cgit v1.2.3 From 03644ba9bcab05568870291ac5f4687c813688f5 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 20:34:11 -0800 Subject: Revamp get_key_password() --- lib/crypto/c_src/engine.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 95966508ec..56029638d4 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -69,11 +69,17 @@ char *get_key_password(ErlNifEnv *env, ERL_NIF_TERM key) { ERL_NIF_TERM tmp_term; ErlNifBinary pwd_bin; char *pwd = NULL; - if (enif_get_map_value(env, key, atom_password, &tmp_term) && - enif_inspect_binary(env, tmp_term, &pwd_bin) && - zero_terminate(pwd_bin, &pwd) - ) return pwd; + if (!enif_get_map_value(env, key, atom_password, &tmp_term)) + goto err; + if (!enif_inspect_binary(env, tmp_term, &pwd_bin)) + goto err; + if (!zero_terminate(pwd_bin, &pwd)) + goto err; + + return pwd; + + err: return NULL; } -- cgit v1.2.3 From afda6208baa01d86efa52a31504293af2e5ec1f5 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 20:36:58 -0800 Subject: Revamp zero_terminate() --- lib/crypto/c_src/engine.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 56029638d4..cec525fc80 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -84,12 +84,16 @@ char *get_key_password(ErlNifEnv *env, ERL_NIF_TERM key) { } static int zero_terminate(ErlNifBinary bin, char **buf) { - *buf = enif_alloc(bin.size+1); - if (!*buf) - return 0; + if ((*buf = enif_alloc(bin.size + 1)) == NULL) + goto err; + memcpy(*buf, bin.data, bin.size); - *(*buf+bin.size) = 0; + *(*buf + bin.size) = 0; + return 1; + + err: + return 0; } #endif /* HAS_ENGINE_SUPPORT */ -- cgit v1.2.3 From d444902aae3507b0f1256e4b3e0c7993f3da3b68 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 06:45:31 -0800 Subject: Revamp engine_by_id_nif() * Add error handling for all Erlang calls. --- lib/crypto/c_src/engine.c | 49 ++++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index cec525fc80..2384235a1e 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -115,37 +115,50 @@ int init_engine_ctx(ErlNifEnv *env) { ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (EngineId) */ #ifdef HAS_ENGINE_SUPPORT - ERL_NIF_TERM ret; + ERL_NIF_TERM ret, result; ErlNifBinary engine_id_bin; - char *engine_id; + char *engine_id = NULL; ENGINE *engine; - struct engine_ctx *ctx; + struct engine_ctx *ctx = NULL; // Get Engine Id - if(!enif_inspect_binary(env, argv[0], &engine_id_bin)) { - PRINTF_ERR0("engine_by_id_nif Leaved: badarg"); - return enif_make_badarg(env); - } else { - engine_id = enif_alloc(engine_id_bin.size+1); - (void) memcpy(engine_id, engine_id_bin.data, engine_id_bin.size); - engine_id[engine_id_bin.size] = '\0'; - } + if (argc != 1) + goto bad_arg; + if (!enif_inspect_binary(env, argv[0], &engine_id_bin)) + goto bad_arg; - engine = ENGINE_by_id(engine_id); - if(!engine) { - enif_free(engine_id); + if ((engine_id = enif_alloc(engine_id_bin.size+1)) == NULL) + goto err; + (void) memcpy(engine_id, engine_id_bin.data, engine_id_bin.size); + engine_id[engine_id_bin.size] = '\0'; + + if ((engine = ENGINE_by_id(engine_id)) == NULL) { PRINTF_ERR0("engine_by_id_nif Leaved: {error, bad_engine_id}"); - return enif_make_tuple2(env, atom_error, atom_bad_engine_id); + ret = enif_make_tuple2(env, atom_error, atom_bad_engine_id); + goto done; } - ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx)); + if ((ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx))) == NULL) + goto err; ctx->engine = engine; ctx->id = engine_id; + /* ctx now owns engine_id */ + engine_id = NULL; - ret = enif_make_resource(env, ctx); + result = enif_make_resource(env, ctx); + ret = enif_make_tuple2(env, atom_ok, result); + goto done; + + bad_arg: + err: + ret = enif_make_badarg(env); + + done: + if (engine_id) + enif_free(engine_id); enif_release_resource(ctx); + return ret; - return enif_make_tuple2(env, atom_ok, ret); #else return atom_notsup; #endif -- cgit v1.2.3 From f16e0061a9bdbab39bc25781efbae736710c76af Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 06:45:49 -0800 Subject: Revamp engine_init_nif() --- lib/crypto/c_src/engine.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 2384235a1e..1398e315aa 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -167,21 +167,22 @@ ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ERL_NIF_TERM engine_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Engine) */ #ifdef HAS_ENGINE_SUPPORT - ERL_NIF_TERM ret = atom_ok; struct engine_ctx *ctx; // Get Engine - if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) { - PRINTF_ERR0("engine_init_nif Leaved: Parameter not an engine resource object"); - return enif_make_badarg(env); - } - if (!ENGINE_init(ctx->engine)) { - //ERR_print_errors_fp(stderr); - PRINTF_ERR0("engine_init_nif Leaved: {error, engine_init_failed}"); + if (argc != 1) + goto bad_arg; + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) + goto bad_arg; + + if (!ENGINE_init(ctx->engine)) return enif_make_tuple2(env, atom_error, atom_engine_init_failed); - } - return ret; + return atom_ok; + + bad_arg: + return enif_make_badarg(env); + #else return atom_notsup; #endif -- cgit v1.2.3 From 8b2e00ca9c9a92b1088ddeb75a3764bf198ab19f Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 20:49:21 -0800 Subject: Revamp engine_free_nif() * Add error handling for all OpenSSL calls. --- lib/crypto/c_src/engine.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 1398e315aa..9a3793180d 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -194,13 +194,18 @@ ERL_NIF_TERM engine_free_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] struct engine_ctx *ctx; // Get Engine - if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) { - PRINTF_ERR0("engine_free_nif Leaved: Parameter not an engine resource object"); - return enif_make_badarg(env); - } + if (argc != 1) + goto bad_arg; + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) + goto bad_arg; - ENGINE_free(ctx->engine); + if (!ENGINE_free(ctx->engine)) + goto err; return atom_ok; + + bad_arg: + err: + return enif_make_badarg(env); #else return atom_notsup; #endif -- cgit v1.2.3 From 882a23aef3f2fe2dffbd0e69a780010f8deebb76 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Tue, 8 Jan 2019 00:27:31 -0800 Subject: Revamp engine_finish_nif() --- lib/crypto/c_src/engine.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 9a3793180d..fb28808cb5 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -217,13 +217,19 @@ ERL_NIF_TERM engine_finish_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv struct engine_ctx *ctx; // Get Engine - if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) { - PRINTF_ERR0("engine_finish_nif Leaved: Parameter not an engine resource object"); - return enif_make_badarg(env); - } + if (argc != 1) + goto bad_arg; + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) + goto bad_arg; - ENGINE_finish(ctx->engine); + if (!ENGINE_finish(ctx->engine)) + goto err; return atom_ok; + + bad_arg: + err: + return enif_make_badarg(env); + #else return atom_notsup; #endif -- cgit v1.2.3 From aeec8b23f3cbd238eb85c43eebbb1ce5cc1247d6 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Tue, 8 Jan 2019 00:27:46 -0800 Subject: Revamp engine_load_dynamic_nif() --- lib/crypto/c_src/engine.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index fb28808cb5..fd09d51a90 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -238,6 +238,9 @@ ERL_NIF_TERM engine_finish_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv ERL_NIF_TERM engine_load_dynamic_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* () */ #ifdef HAS_ENGINE_SUPPORT + if (argc != 0) + return enif_make_badarg(env); + ENGINE_load_dynamic(); return atom_ok; #else -- cgit v1.2.3 From 64515f3ba20a8edcfd2ffdf582828c8153ee5eb7 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 21:06:17 -0800 Subject: Revamp engine_ctrl_cmd_strings_nif() * Add bounds checks for allocation multiplication * Simplify the error handling by adding a flag for whether the strings were loaded. --- lib/crypto/c_src/engine.c | 75 +++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index fd09d51a90..a9f57772c8 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -251,38 +251,38 @@ ERL_NIF_TERM engine_load_dynamic_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Engine, Commands) */ #ifdef HAS_ENGINE_SUPPORT - ERL_NIF_TERM ret = atom_ok; + ERL_NIF_TERM ret; unsigned int cmds_len = 0; char **cmds = NULL; struct engine_ctx *ctx; - int i, optional = 0; + unsigned int i; + int optional = 0; + int cmds_loaded = 0; // Get Engine - if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) { - PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: Parameter not an engine resource object"); - return enif_make_badarg(env); - } + if (argc != 2) + goto bad_arg; + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) + goto bad_arg; PRINTF_ERR1("Engine Id: %s\r\n", ENGINE_get_id(ctx->engine)); - // Get Command List - if(!enif_get_list_length(env, argv[1], &cmds_len)) { - PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: Bad Command List"); - return enif_make_badarg(env); - } else { - cmds_len *= 2; // Key-Value list from erlang - cmds = enif_alloc((cmds_len+1)*sizeof(char*)); - if(get_engine_load_cmd_list(env, argv[1], cmds, 0)) { - PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: Couldn't read Command List"); - ret = enif_make_badarg(env); - goto error; - } - } + if (!enif_get_list_length(env, argv[1], &cmds_len)) + goto bad_arg; - if(!enif_get_int(env, argv[2], &optional)) { - PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: Parameter optional not an integer"); - return enif_make_badarg(env); - } + if (cmds_len > (UINT_MAX / 2) - 1) + goto err; + cmds_len *= 2; // Key-Value list from erlang + + if ((size_t)cmds_len + 1 > SIZE_MAX / sizeof(char*)) + goto err; + if ((cmds = enif_alloc((cmds_len + 1) * sizeof(char*))) == NULL) + goto err; + if (get_engine_load_cmd_list(env, argv[1], cmds, 0)) + goto err; + cmds_loaded = 1; + if (!enif_get_int(env, argv[2], &optional)) + goto err; for(i = 0; i < cmds_len; i+=2) { PRINTF_ERR2("Cmd: %s:%s\r\n", @@ -292,18 +292,31 @@ ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const ERL_NIF PRINTF_ERR2("Command failed: %s:%s\r\n", cmds[i] ? cmds[i] : "(NULL)", cmds[i+1] ? cmds[i+1] : "(NULL)"); - //ENGINE_free(ctx->engine); - ret = enif_make_tuple2(env, atom_error, atom_ctrl_cmd_failed); - PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: {error, ctrl_cmd_failed}"); - goto error; + goto cmd_failed; } } + ret = atom_ok; + goto done; + + bad_arg: + err: + ret = enif_make_badarg(env); + goto done; + + cmd_failed: + ret = enif_make_tuple2(env, atom_error, atom_ctrl_cmd_failed); + + done: + if (cmds_loaded) { + for (i = 0; cmds != NULL && cmds[i] != NULL; i++) + enif_free(cmds[i]); + } + + if (cmds != NULL) + enif_free(cmds); - error: - for(i = 0; cmds != NULL && cmds[i] != NULL; i++) - enif_free(cmds[i]); - enif_free(cmds); return ret; + #else return atom_notsup; #endif -- cgit v1.2.3 From b70c3ae28e9cad0ca19c7b8c427cfb5b70d8e3f2 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 21:11:51 -0800 Subject: Revamp engine_add_nif() --- lib/crypto/c_src/engine.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index a9f57772c8..b3a87cdd3d 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -328,16 +328,22 @@ ERL_NIF_TERM engine_add_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) struct engine_ctx *ctx; // Get Engine - if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) { - PRINTF_ERR0("engine_add_nif Leaved: Parameter not an engine resource object"); - return enif_make_badarg(env); - } + if (argc != 1) + goto bad_arg; + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) + goto bad_arg; + + if (!ENGINE_add(ctx->engine)) + goto failed; - if (!ENGINE_add(ctx->engine)) { - PRINTF_ERR0("engine_add_nif Leaved: {error, add_engine_failed}"); - return enif_make_tuple2(env, atom_error, atom_add_engine_failed); - } return atom_ok; + + bad_arg: + return enif_make_badarg(env); + + failed: + return enif_make_tuple2(env, atom_error, atom_add_engine_failed); + #else return atom_notsup; #endif -- cgit v1.2.3 From db48a4b67a5397ee9f4d910a3903159b1c7c79fd Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 21:12:29 -0800 Subject: Revamp engine_remove_nif() --- lib/crypto/c_src/engine.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index b3a87cdd3d..76f7503968 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -355,16 +355,21 @@ ERL_NIF_TERM engine_remove_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv struct engine_ctx *ctx; // Get Engine - if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) { - PRINTF_ERR0("engine_remove_nif Leaved: Parameter not an engine resource object"); - return enif_make_badarg(env); - } + if (argc != 1) + goto bad_arg; + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) + goto bad_arg; + + if (!ENGINE_remove(ctx->engine)) + goto failed; - if (!ENGINE_remove(ctx->engine)) { - PRINTF_ERR0("engine_remove_nif Leaved: {error, remove_engine_failed}"); - return enif_make_tuple2(env, atom_error, atom_remove_engine_failed); - } return atom_ok; + + bad_arg: + return enif_make_badarg(env); + + failed: + return enif_make_tuple2(env, atom_error, atom_remove_engine_failed); #else return atom_notsup; #endif -- cgit v1.2.3 From f7d64513a055dce87c050cffc578f641dc86258e Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 21:13:45 -0800 Subject: Revamp engine_register_nif() --- lib/crypto/c_src/engine.c | 50 +++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 76f7503968..7dc0151018 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -382,95 +382,99 @@ ERL_NIF_TERM engine_register_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar unsigned int method; // Get Engine - if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) { - PRINTF_ERR0("engine_register_nif Leaved: Parameter not an engine resource object"); - return enif_make_badarg(env); - } - // Get Method - if (!enif_get_uint(env, argv[1], &method)) { - PRINTF_ERR0("engine_register_nif Leaved: Parameter Method not an uint"); - return enif_make_badarg(env); - } + if (argc != 2) + goto bad_arg; + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) + goto bad_arg; + if (!enif_get_uint(env, argv[1], &method)) + goto bad_arg; switch(method) { #ifdef ENGINE_METHOD_RSA case ENGINE_METHOD_RSA: if (!ENGINE_register_RSA(ctx->engine)) - return enif_make_tuple2(env, atom_error, atom_register_engine_failed); + goto failed; break; #endif #ifdef ENGINE_METHOD_DSA case ENGINE_METHOD_DSA: if (!ENGINE_register_DSA(ctx->engine)) - return enif_make_tuple2(env, atom_error, atom_register_engine_failed); + goto failed; break; #endif #ifdef ENGINE_METHOD_DH case ENGINE_METHOD_DH: if (!ENGINE_register_DH(ctx->engine)) - return enif_make_tuple2(env, atom_error, atom_register_engine_failed); + goto failed; break; #endif #ifdef ENGINE_METHOD_RAND case ENGINE_METHOD_RAND: if (!ENGINE_register_RAND(ctx->engine)) - return enif_make_tuple2(env, atom_error, atom_register_engine_failed); + goto failed; break; #endif #ifdef ENGINE_METHOD_ECDH case ENGINE_METHOD_ECDH: if (!ENGINE_register_ECDH(ctx->engine)) - return enif_make_tuple2(env, atom_error, atom_register_engine_failed); + goto failed; break; #endif #ifdef ENGINE_METHOD_ECDSA case ENGINE_METHOD_ECDSA: if (!ENGINE_register_ECDSA(ctx->engine)) - return enif_make_tuple2(env, atom_error, atom_register_engine_failed); + goto failed; break; #endif #ifdef ENGINE_METHOD_STORE case ENGINE_METHOD_STORE: if (!ENGINE_register_STORE(ctx->engine)) - return enif_make_tuple2(env, atom_error, atom_register_engine_failed); + goto failed; break; #endif #ifdef ENGINE_METHOD_CIPHERS case ENGINE_METHOD_CIPHERS: if (!ENGINE_register_ciphers(ctx->engine)) - return enif_make_tuple2(env, atom_error, atom_register_engine_failed); + goto failed; break; #endif #ifdef ENGINE_METHOD_DIGESTS case ENGINE_METHOD_DIGESTS: if (!ENGINE_register_digests(ctx->engine)) - return enif_make_tuple2(env, atom_error, atom_register_engine_failed); + goto failed; break; #endif #ifdef ENGINE_METHOD_PKEY_METHS case ENGINE_METHOD_PKEY_METHS: if (!ENGINE_register_pkey_meths(ctx->engine)) - return enif_make_tuple2(env, atom_error, atom_register_engine_failed); + goto failed; break; #endif #ifdef ENGINE_METHOD_PKEY_ASN1_METHS case ENGINE_METHOD_PKEY_ASN1_METHS: if (!ENGINE_register_pkey_asn1_meths(ctx->engine)) - return enif_make_tuple2(env, atom_error, atom_register_engine_failed); + goto failed; break; #endif #ifdef ENGINE_METHOD_EC case ENGINE_METHOD_EC: if (!ENGINE_register_EC(ctx->engine)) - return enif_make_tuple2(env, atom_error, atom_register_engine_failed); + goto failed; break; #endif default: - return enif_make_tuple2(env, atom_error, atom_engine_method_not_supported); - break; + return enif_make_tuple2(env, atom_error, atom_engine_method_not_supported); } + return atom_ok; + + bad_arg: + return enif_make_badarg(env); + + failed: + return enif_make_tuple2(env, atom_error, atom_register_engine_failed); + #else return atom_notsup; #endif -- cgit v1.2.3 From 1ad4eb810f83a43c531eebafd8784a2c76d7869e Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 21:15:31 -0800 Subject: Revamp engine_unregister_nif() --- lib/crypto/c_src/engine.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 7dc0151018..5f742757e8 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -487,15 +487,12 @@ ERL_NIF_TERM engine_unregister_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned int method; // Get Engine - if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) { - PRINTF_ERR0("engine_unregister_nif Leaved: Parameter not an engine resource object"); - return enif_make_badarg(env); - } - // Get Method - if (!enif_get_uint(env, argv[1], &method)) { - PRINTF_ERR0("engine_unregister_nif Leaved: Parameter Method not an uint"); - return enif_make_badarg(env); - } + if (argc != 2) + goto bad_arg; + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) + goto bad_arg; + if (!enif_get_uint(env, argv[1], &method)) + goto bad_arg; switch(method) { @@ -562,7 +559,12 @@ ERL_NIF_TERM engine_unregister_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM default: break; } + return atom_ok; + + bad_arg: + return enif_make_badarg(env); + #else return atom_notsup; #endif -- cgit v1.2.3 From b645e20dac3b5c228316abde02bd7dedfd6bcf59 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 21:20:47 -0800 Subject: Revamp engine_get_first_nif() * Add error handling for all Erlang calls. --- lib/crypto/c_src/engine.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 5f742757e8..4cbb8dc683 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -573,26 +573,38 @@ ERL_NIF_TERM engine_unregister_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Engine) */ #ifdef HAS_ENGINE_SUPPORT - ERL_NIF_TERM ret; + ERL_NIF_TERM ret, result; ENGINE *engine; ErlNifBinary engine_bin; - struct engine_ctx *ctx; + struct engine_ctx *ctx = NULL; - engine = ENGINE_get_first(); - if(!engine) { - enif_alloc_binary(0, &engine_bin); + if (argc != 1) + goto bad_arg; + + if ((engine = ENGINE_get_first()) == NULL) { + if (!enif_alloc_binary(0, &engine_bin)) + goto err; engine_bin.size = 0; return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_bin)); } - ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx)); + if ((ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx))) == NULL) + goto err; ctx->engine = engine; ctx->id = NULL; - ret = enif_make_resource(env, ctx); + result = enif_make_resource(env, ctx); + ret = enif_make_tuple2(env, atom_ok, result); + goto done; + + bad_arg: + err: + ret = enif_make_badarg(env); + + done: enif_release_resource(ctx); + return ret; - return enif_make_tuple2(env, atom_ok, ret); #else return atom_notsup; #endif -- cgit v1.2.3 From c94b99aea4c7aaa296153c038117c9360a57ff50 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 21:25:30 -0800 Subject: Revamp engine_get_next_nif() * Add error handling for all Erlang calls. --- lib/crypto/c_src/engine.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 4cbb8dc683..5067f34eec 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -613,31 +613,41 @@ ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a ERL_NIF_TERM engine_get_next_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Engine) */ #ifdef HAS_ENGINE_SUPPORT - ERL_NIF_TERM ret; + ERL_NIF_TERM ret, result; ENGINE *engine; ErlNifBinary engine_bin; - struct engine_ctx *ctx, *next_ctx; + struct engine_ctx *ctx, *next_ctx = NULL; // Get Engine - if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) { - PRINTF_ERR0("engine_get_next_nif Leaved: Parameter not an engine resource object"); - return enif_make_badarg(env); - } - engine = ENGINE_get_next(ctx->engine); - if (!engine) { - enif_alloc_binary(0, &engine_bin); + if (argc != 1) + goto bad_arg; + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) + goto bad_arg; + + if ((engine = ENGINE_get_next(ctx->engine)) == NULL) { + if (!enif_alloc_binary(0, &engine_bin)) + goto err; engine_bin.size = 0; return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_bin)); } - next_ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx)); + if ((next_ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx))) == NULL) + goto err; next_ctx->engine = engine; next_ctx->id = NULL; - ret = enif_make_resource(env, next_ctx); + result = enif_make_resource(env, next_ctx); + ret = enif_make_tuple2(env, atom_ok, result); + goto done; + + bad_arg: + err: + ret = enif_make_badarg(env); + + done: enif_release_resource(next_ctx); + return ret; - return enif_make_tuple2(env, atom_ok, ret); #else return atom_notsup; #endif -- cgit v1.2.3 From b43336cffe8c90ad259a75aa79fa79637d83cc4e Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 21:32:05 -0800 Subject: Revamp engine_get_id_nif() * Add error handling for all Erlang calls. * Change size from int to size_t since it's assigned to sizeof(). --- lib/crypto/c_src/engine.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 5067f34eec..88471e7f91 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -658,28 +658,34 @@ ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv #ifdef HAS_ENGINE_SUPPORT ErlNifBinary engine_id_bin; const char *engine_id; - int size; - struct engine_ctx *ctx; + size_t size; + struct engine_ctx *ctx = NULL; // Get Engine - if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) { - PRINTF_ERR0("engine_get_id_nif Leaved: Parameter not an engine resource object"); - return enif_make_badarg(env); - } + if (argc != 1) + goto bad_arg; + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) + goto bad_arg; - engine_id = ENGINE_get_id(ctx->engine); - if (!engine_id) { - enif_alloc_binary(0, &engine_id_bin); + if ((engine_id = ENGINE_get_id(ctx->engine)) == NULL) { + if (!enif_alloc_binary(0, &engine_id_bin)) + goto err; engine_id_bin.size = 0; return enif_make_binary(env, &engine_id_bin); } size = strlen(engine_id); - enif_alloc_binary(size, &engine_id_bin); + if (!enif_alloc_binary(size, &engine_id_bin)) + goto err; engine_id_bin.size = size; memcpy(engine_id_bin.data, engine_id, size); return enif_make_binary(env, &engine_id_bin); + + bad_arg: + err: + return enif_make_badarg(env); + #else return atom_notsup; #endif -- cgit v1.2.3 From 262d1f56caeab592fa28ff78bdee3a9149d1b13b Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 21:33:27 -0800 Subject: Revamp engine_get_name_nif() * Add error handling for all Erlang calls. * Change size from int to size_t. --- lib/crypto/c_src/engine.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 88471e7f91..541e8beb9b 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -696,28 +696,34 @@ ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar #ifdef HAS_ENGINE_SUPPORT ErlNifBinary engine_name_bin; const char *engine_name; - int size; + size_t size; struct engine_ctx *ctx; // Get Engine - if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) { - PRINTF_ERR0("engine_get_id_nif Leaved: Parameter not an engine resource object"); - return enif_make_badarg(env); - } + if (argc != 1) + goto bad_arg; + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) + goto bad_arg; - engine_name = ENGINE_get_name(ctx->engine); - if (!engine_name) { - enif_alloc_binary(0, &engine_name_bin); + if ((engine_name = ENGINE_get_name(ctx->engine)) == NULL) { + if (!enif_alloc_binary(0, &engine_name_bin)) + goto err; engine_name_bin.size = 0; return enif_make_binary(env, &engine_name_bin); } size = strlen(engine_name); - enif_alloc_binary(size, &engine_name_bin); + if (!enif_alloc_binary(size, &engine_name_bin)) + goto err; engine_name_bin.size = size; memcpy(engine_name_bin.data, engine_name, size); return enif_make_binary(env, &engine_name_bin); + + bad_arg: + err: + return enif_make_badarg(env); + #else return atom_notsup; #endif -- cgit v1.2.3 From 998a8a4ad5939290e17c3963cdd7707c2a40e8b7 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 21:42:06 -0800 Subject: Revamp get_engine_load_cmd_list() * Restructure the code so it exits early * Check for allocation failures and free on partial result --- lib/crypto/c_src/engine.c | 80 +++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 541e8beb9b..6b3a696c31 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -736,46 +736,52 @@ static int get_engine_load_cmd_list(ErlNifEnv* env, const ERL_NIF_TERM term, cha const ERL_NIF_TERM *tmp_tuple; ErlNifBinary tmpbin; int arity; - char* tmpstr; - - if(!enif_is_empty_list(env, term)) { - if(!enif_get_list_cell(env, term, &head, &tail)) { - cmds[i] = NULL; - return -1; - } else { - if(!enif_get_tuple(env, head, &arity, &tmp_tuple) || arity != 2) { - cmds[i] = NULL; - return -1; - } else { - if(!enif_inspect_binary(env, tmp_tuple[0], &tmpbin)) { - cmds[i] = NULL; - return -1; - } else { - tmpstr = enif_alloc(tmpbin.size+1); - (void) memcpy(tmpstr, tmpbin.data, tmpbin.size); - tmpstr[tmpbin.size] = '\0'; - cmds[i++] = tmpstr; - } - if(!enif_inspect_binary(env, tmp_tuple[1], &tmpbin)) { - cmds[i] = NULL; - return -1; - } else { - if(tmpbin.size == 0) - cmds[i++] = NULL; - else { - tmpstr = enif_alloc(tmpbin.size+1); - (void) memcpy(tmpstr, tmpbin.data, tmpbin.size); - tmpstr[tmpbin.size] = '\0'; - cmds[i++] = tmpstr; - } - } - return get_engine_load_cmd_list(env, tail, cmds, i); - } - } - } else { + char *tuple1 = NULL, *tuple2 = NULL; + + if (enif_is_empty_list(env, term)) { cmds[i] = NULL; return 0; } + + if (!enif_get_list_cell(env, term, &head, &tail)) + goto err; + if (!enif_get_tuple(env, head, &arity, &tmp_tuple)) + goto err; + if (arity != 2) + goto err; + if (!enif_inspect_binary(env, tmp_tuple[0], &tmpbin)) + goto err; + + if ((tuple1 = enif_alloc(tmpbin.size + 1)) == NULL) + goto err; + + (void) memcpy(tuple1, tmpbin.data, tmpbin.size); + tuple1[tmpbin.size] = '\0'; + cmds[i] = tuple1; + i++; + + if (!enif_inspect_binary(env, tmp_tuple[1], &tmpbin)) + goto err; + + if (tmpbin.size == 0) { + cmds[i] = NULL; + } else { + if ((tuple2 = enif_alloc(tmpbin.size + 1)) == NULL) + goto err; + (void) memcpy(tuple2, tmpbin.data, tmpbin.size); + tuple2[tmpbin.size] = '\0'; + cmds[i] = tuple2; + } + i++; + return get_engine_load_cmd_list(env, tail, cmds, i); + + err: + if (tuple1 != NULL) { + i--; + enif_free(tuple1); + } + cmds[i] = NULL; + return -1; } #endif /* HAS_ENGINE_SUPPORT */ -- cgit v1.2.3 From b497b9d64bcf2c77f0fc82af57877b3465552c82 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 21:44:31 -0800 Subject: Revamp engine_get_all_methods_nif() --- lib/crypto/c_src/engine.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 6b3a696c31..4d75f6430b 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -789,7 +789,10 @@ ERL_NIF_TERM engine_get_all_methods_nif(ErlNifEnv* env, int argc, const ERL_NIF_ {/* () */ #ifdef HAS_ENGINE_SUPPORT ERL_NIF_TERM method_array[12]; - int i = 0; + unsigned int i = 0; + + if (argc != 0) + return enif_make_badarg(env); #ifdef ENGINE_METHOD_RSA method_array[i++] = atom_engine_method_rsa; -- cgit v1.2.3 From 74da892c736fda38179b1d166c9d4317ebdfa2b0 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 21:58:09 -0800 Subject: Revamp evp_compute_key_nif() * Bug fix: Some EVP_PKEY_* return <= 0 on failure and 1 on success. * Fix a possible memory leak where enif_alloc_binary() wasn't converted into a term or freed in all paths. --- lib/crypto/c_src/evp.c | 84 +++++++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/lib/crypto/c_src/evp.c b/lib/crypto/c_src/evp.c index 3c55ab630b..49e563f039 100644 --- a/lib/crypto/c_src/evp.c +++ b/lib/crypto/c_src/evp.c @@ -24,54 +24,76 @@ ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar /* (Curve, PeerBin, MyBin) */ { #ifdef HAVE_ED_CURVE_DH + ERL_NIF_TERM ret; int type; EVP_PKEY_CTX *ctx = NULL; ErlNifBinary peer_bin, my_bin, key_bin; EVP_PKEY *peer_key = NULL, *my_key = NULL; size_t max_size; + int key_bin_alloc = 0; - if (argv[0] == atom_x25519) type = EVP_PKEY_X25519; - else if (argv[0] == atom_x448) type = EVP_PKEY_X448; - else return enif_make_badarg(env); + if (argc != 3) + goto bad_arg; + + if (argv[0] == atom_x25519) + type = EVP_PKEY_X25519; + else if (argv[0] == atom_x448) + type = EVP_PKEY_X448; + else + goto bad_arg; - if (!enif_inspect_binary(env, argv[1], &peer_bin) || - !enif_inspect_binary(env, argv[2], &my_bin)) - goto return_badarg; + if (!enif_inspect_binary(env, argv[1], &peer_bin)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &my_bin)) + goto bad_arg; - if (!(my_key = EVP_PKEY_new_raw_private_key(type, NULL, my_bin.data, my_bin.size)) || - !(ctx = EVP_PKEY_CTX_new(my_key, NULL))) - goto return_badarg; + if ((my_key = EVP_PKEY_new_raw_private_key(type, NULL, my_bin.data, my_bin.size)) == NULL) + goto err; + if ((ctx = EVP_PKEY_CTX_new(my_key, NULL)) == NULL) + goto err; - if (!EVP_PKEY_derive_init(ctx)) - goto return_badarg; + if (EVP_PKEY_derive_init(ctx) != 1) + goto err; - if (!(peer_key = EVP_PKEY_new_raw_public_key(type, NULL, peer_bin.data, peer_bin.size)) || - !EVP_PKEY_derive_set_peer(ctx, peer_key)) - goto return_badarg; + if ((peer_key = EVP_PKEY_new_raw_public_key(type, NULL, peer_bin.data, peer_bin.size)) == NULL) + goto err; + if (EVP_PKEY_derive_set_peer(ctx, peer_key) != 1) + goto err; - if (!EVP_PKEY_derive(ctx, NULL, &max_size)) - goto return_badarg; + if (EVP_PKEY_derive(ctx, NULL, &max_size) != 1) + goto err; - if (!enif_alloc_binary(max_size, &key_bin) || - !EVP_PKEY_derive(ctx, key_bin.data, &key_bin.size)) - goto return_badarg; + if (!enif_alloc_binary(max_size, &key_bin)) + goto err; + key_bin_alloc = 1; + if (EVP_PKEY_derive(ctx, key_bin.data, &key_bin.size) != 1) + goto err; if (key_bin.size < max_size) { - size_t actual_size = key_bin.size; - if (!enif_realloc_binary(&key_bin, actual_size)) - goto return_badarg; + if (!enif_realloc_binary(&key_bin, (size_t)key_bin.size)) + goto err; } - EVP_PKEY_free(my_key); - EVP_PKEY_free(peer_key); - EVP_PKEY_CTX_free(ctx); - return enif_make_binary(env, &key_bin); + ret = enif_make_binary(env, &key_bin); + key_bin_alloc = 0; + goto done; + + bad_arg: + err: + if (key_bin_alloc) + enif_release_binary(&key_bin); + ret = enif_make_badarg(env); + + done: + if (my_key) + EVP_PKEY_free(my_key); + if (peer_key) + EVP_PKEY_free(peer_key); + if (ctx) + EVP_PKEY_CTX_free(ctx); + + return ret; -return_badarg: - if (my_key) EVP_PKEY_free(my_key); - if (peer_key) EVP_PKEY_free(peer_key); - if (ctx) EVP_PKEY_CTX_free(ctx); - return enif_make_badarg(env); #else return atom_notsup; #endif -- cgit v1.2.3 From 0ba6e8338bb1895075f20d8feaa6ad2cb8559ce4 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 22:03:48 -0800 Subject: Revamp evp_generate_key_nif() * Bug fix: Some EVP_PKEY_* calls return <= 0 on failure and 1 on success. --- lib/crypto/c_src/evp.c | 68 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/lib/crypto/c_src/evp.c b/lib/crypto/c_src/evp.c index 49e563f039..7aa4be1f9f 100644 --- a/lib/crypto/c_src/evp.c +++ b/lib/crypto/c_src/evp.c @@ -106,38 +106,58 @@ ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a int type; EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *pkey = NULL; - ERL_NIF_TERM ret_pub, ret_prv; + ERL_NIF_TERM ret_pub, ret_prv, ret; size_t key_len; + unsigned char *out_pub = NULL, *out_priv = NULL; - if (argv[0] == atom_x25519) type = EVP_PKEY_X25519; - else if (argv[0] == atom_x448) type = EVP_PKEY_X448; - else return enif_make_badarg(env); + if (argc != 1) + goto bad_arg; + + if (argv[0] == atom_x25519) + type = EVP_PKEY_X25519; + else if (argv[0] == atom_x448) + type = EVP_PKEY_X448; + else + goto bad_arg; + + if ((ctx = EVP_PKEY_CTX_new_id(type, NULL)) == NULL) + goto bad_arg; - if (!(ctx = EVP_PKEY_CTX_new_id(type, NULL))) return enif_make_badarg(env); + if (EVP_PKEY_keygen_init(ctx) != 1) + goto err; + if (EVP_PKEY_keygen(ctx, &pkey) != 1) + goto err; + + if (EVP_PKEY_get_raw_public_key(pkey, NULL, &key_len) != 1) + goto err; + if ((out_pub = enif_make_new_binary(env, key_len, &ret_pub)) == NULL) + goto err; + if (EVP_PKEY_get_raw_public_key(pkey, out_pub, &key_len) != 1) + goto err; - if (!EVP_PKEY_keygen_init(ctx)) goto return_error; - if (!EVP_PKEY_keygen(ctx, &pkey)) goto return_error; + if (EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len) != 1) + goto err; + if ((out_priv = enif_make_new_binary(env, key_len, &ret_prv)) == NULL) + goto err; + if (EVP_PKEY_get_raw_private_key(pkey, out_priv, &key_len) != 1) + goto err; - if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &key_len)) goto return_error; - if (!EVP_PKEY_get_raw_public_key(pkey, - enif_make_new_binary(env, key_len, &ret_pub), - &key_len)) - goto return_error; + ret = enif_make_tuple2(env, ret_pub, ret_prv); + goto done; - if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len)) goto return_error; - if (!EVP_PKEY_get_raw_private_key(pkey, - enif_make_new_binary(env, key_len, &ret_prv), - &key_len)) - goto return_error; + bad_arg: + ret = enif_make_badarg(env); + goto done; - EVP_PKEY_free(pkey); - EVP_PKEY_CTX_free(ctx); - return enif_make_tuple2(env, ret_pub, ret_prv); + err: + ret = atom_error; -return_error: - if (pkey) EVP_PKEY_free(pkey); - if (ctx) EVP_PKEY_CTX_free(ctx); - return atom_error; + done: + if (pkey) + EVP_PKEY_free(pkey); + if (ctx) + EVP_PKEY_CTX_free(ctx); + return ret; #else return atom_notsup; -- cgit v1.2.3 From 35d9cb839ea0ef764d266212d7f3419c8750b59d Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 22:14:12 -0800 Subject: Revamp hash_nif() --- lib/crypto/c_src/hash.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/lib/crypto/c_src/hash.c b/lib/crypto/c_src/hash.c index c8835296ea..34e6db6b66 100644 --- a/lib/crypto/c_src/hash.c +++ b/lib/crypto/c_src/hash.c @@ -64,28 +64,36 @@ ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ErlNifBinary data; ERL_NIF_TERM ret; unsigned ret_size; + unsigned char *outp; - digp = get_digest_type(argv[0]); - if (!digp || - !enif_inspect_iolist_as_binary(env, argv[1], &data)) { - return enif_make_badarg(env); - } - md = digp->md.p; - if (!md) { - return atom_notsup; - } + if (argc != 2) + goto bad_arg; + if ((digp = get_digest_type(argv[0])) == NULL) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &data)) + goto bad_arg; + + if ((md = digp->md.p) == NULL) + goto err; ret_size = (unsigned)EVP_MD_size(md); ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE); - if (!EVP_Digest(data.data, data.size, - enif_make_new_binary(env, ret_size, &ret), &ret_size, - md, NULL)) { - return atom_notsup; - } + + if ((outp = enif_make_new_binary(env, ret_size, &ret)) == NULL) + goto err; + if (EVP_Digest(data.data, data.size, outp, &ret_size, md, NULL) != 1) + goto err; + ASSERT(ret_size == (unsigned)EVP_MD_size(md)); CONSUME_REDS(env, data); return ret; + + bad_arg: + return enif_make_badarg(env); + + err: + return atom_notsup; } #if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0) -- cgit v1.2.3 From 2e31e2cdcab0de8e00e4b3103a92440d81541211 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 22:15:38 -0800 Subject: Revamp hash_init_nif() --- lib/crypto/c_src/hash.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/lib/crypto/c_src/hash.c b/lib/crypto/c_src/hash.c index 34e6db6b66..a2c53bcaaf 100644 --- a/lib/crypto/c_src/hash.c +++ b/lib/crypto/c_src/hash.c @@ -101,24 +101,33 @@ ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Type) */ struct digest_type_t *digp = NULL; - struct evp_md_ctx *ctx; + struct evp_md_ctx *ctx = NULL; ERL_NIF_TERM ret; - digp = get_digest_type(argv[0]); - if (!digp) { - return enif_make_badarg(env); - } - if (!digp->md.p) { - return atom_notsup; - } + if (argc != 1) + goto bad_arg; + if ((digp = get_digest_type(argv[0])) == NULL) + goto bad_arg; + if (digp->md.p == NULL) + goto err; + + if ((ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx))) == NULL) + goto err; + if ((ctx->ctx = EVP_MD_CTX_new()) == NULL) + goto err; + if (EVP_DigestInit(ctx->ctx, digp->md.p) != 1) + goto err; - ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx)); - ctx->ctx = EVP_MD_CTX_new(); - if (!EVP_DigestInit(ctx->ctx, digp->md.p)) { - enif_release_resource(ctx); - return atom_notsup; - } ret = enif_make_resource(env, ctx); + goto done; + + bad_arg: + return enif_make_badarg(env); + + err: + ret = atom_notsup; + + done: enif_release_resource(ctx); return ret; } -- cgit v1.2.3 From a23b898f54b9601872c130ccfc7b2a86f6124e4f Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 22:18:09 -0800 Subject: Revamp hash_update_nif() * Add error handling for all OpenSSL and Erlang calls. --- lib/crypto/c_src/hash.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/lib/crypto/c_src/hash.c b/lib/crypto/c_src/hash.c index a2c53bcaaf..482a3e1a12 100644 --- a/lib/crypto/c_src/hash.c +++ b/lib/crypto/c_src/hash.c @@ -134,26 +134,38 @@ ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Context, Data) */ - struct evp_md_ctx *ctx, *new_ctx; + struct evp_md_ctx *ctx, *new_ctx = NULL; ErlNifBinary data; ERL_NIF_TERM ret; - if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx) || - !enif_inspect_iolist_as_binary(env, argv[1], &data)) { - return enif_make_badarg(env); - } + if (argc != 2) + goto bad_arg; + if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &data)) + goto bad_arg; - new_ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx)); - new_ctx->ctx = EVP_MD_CTX_new(); - if (!EVP_MD_CTX_copy(new_ctx->ctx, ctx->ctx) || - !EVP_DigestUpdate(new_ctx->ctx, data.data, data.size)) { - enif_release_resource(new_ctx); - return atom_notsup; - } + if ((new_ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx))) == NULL) + goto err; + if ((new_ctx->ctx = EVP_MD_CTX_new()) == NULL) + goto err; + if (EVP_MD_CTX_copy(new_ctx->ctx, ctx->ctx) != 1) + goto err; + if (EVP_DigestUpdate(new_ctx->ctx, data.data, data.size) != 1) + goto err; ret = enif_make_resource(env, new_ctx); - enif_release_resource(new_ctx); CONSUME_REDS(env, data); + goto done; + + bad_arg: + return enif_make_badarg(env); + + err: + ret = atom_notsup; + + done: + enif_release_resource(new_ctx); return ret; } -- cgit v1.2.3 From 12f1147428dc3160c50a6642aba96f01008eeb71 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 22:20:01 -0800 Subject: Revamp hash_final_nif() * Add error handling for all OpenSSL calls. --- lib/crypto/c_src/hash.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/lib/crypto/c_src/hash.c b/lib/crypto/c_src/hash.c index 482a3e1a12..ee7a589b49 100644 --- a/lib/crypto/c_src/hash.c +++ b/lib/crypto/c_src/hash.c @@ -175,25 +175,37 @@ ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) EVP_MD_CTX *new_ctx; ERL_NIF_TERM ret; unsigned ret_size; + unsigned char *outp; - if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx)) { - return enif_make_badarg(env); - } + if (argc != 1) + goto bad_arg; + if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx)) + goto bad_arg; ret_size = (unsigned)EVP_MD_CTX_size(ctx->ctx); ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE); - new_ctx = EVP_MD_CTX_new(); - if (!EVP_MD_CTX_copy(new_ctx, ctx->ctx) || - !EVP_DigestFinal(new_ctx, - enif_make_new_binary(env, ret_size, &ret), - &ret_size)) { - EVP_MD_CTX_free(new_ctx); - return atom_notsup; - } - EVP_MD_CTX_free(new_ctx); + if ((new_ctx = EVP_MD_CTX_new()) == NULL) + goto err; + if (EVP_MD_CTX_copy(new_ctx, ctx->ctx) != 1) + goto err; + if ((outp = enif_make_new_binary(env, ret_size, &ret)) == NULL) + goto err; + if (EVP_DigestFinal(new_ctx, outp, &ret_size) != 1) + goto err; + ASSERT(ret_size == (unsigned)EVP_MD_CTX_size(ctx->ctx)); + goto done; + bad_arg: + return enif_make_badarg(env); + + err: + ret = atom_notsup; + + done: + if (new_ctx) + EVP_MD_CTX_free(new_ctx); return ret; } -- cgit v1.2.3 From 24481a0cb35c3965ff498fa33f3d05763f49087e Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Tue, 8 Jan 2019 00:28:35 -0800 Subject: Revamp non-EVP hash_init_nif() --- lib/crypto/c_src/hash.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/lib/crypto/c_src/hash.c b/lib/crypto/c_src/hash.c index ee7a589b49..258f127b4a 100644 --- a/lib/crypto/c_src/hash.c +++ b/lib/crypto/c_src/hash.c @@ -218,14 +218,14 @@ ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ERL_NIF_TERM ctx; size_t ctx_size = 0; init_fun ctx_init = 0; + unsigned char *outp; - digp = get_digest_type(argv[0]); - if (!digp) { - return enif_make_badarg(env); - } - if (!digp->md.p) { - return atom_notsup; - } + if (argc != 1) + goto bad_arg; + if ((digp = get_digest_type(argv[0])) == NULL) + goto bad_arg; + if (digp->md.p == NULL) + goto err; switch (EVP_MD_type(digp->md.p)) { @@ -270,13 +270,24 @@ ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) break; #endif default: - return atom_notsup; + goto err; } ASSERT(ctx_size); ASSERT(ctx_init); - ctx_init(enif_make_new_binary(env, ctx_size, &ctx)); + if ((outp = enif_make_new_binary(env, ctx_size, &ctx)) == NULL) + goto err; + + if (ctx_init(outp) != 1) + goto err; + return enif_make_tuple2(env, argv[0], ctx); + + bad_arg: + return enif_make_badarg(env); + + err: + return atom_notsup; } ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From c0c0505e337da0c1e2e501135b4b0fb3af60d2b6 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 22:24:27 -0800 Subject: Revamp non-EVP hash_update_nif() * Add error handling for all OpenSSL calls. --- lib/crypto/c_src/hash.c | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/lib/crypto/c_src/hash.c b/lib/crypto/c_src/hash.c index 258f127b4a..f25d59e9ab 100644 --- a/lib/crypto/c_src/hash.c +++ b/lib/crypto/c_src/hash.c @@ -302,16 +302,21 @@ ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] size_t ctx_size = 0; update_fun ctx_update = 0; - if (!enif_get_tuple(env, argv[0], &arity, &tuple) || - arity != 2 || - !(digp = get_digest_type(tuple[0])) || - !enif_inspect_binary(env, tuple[1], &ctx) || - !enif_inspect_iolist_as_binary(env, argv[1], &data)) { - return enif_make_badarg(env); - } - if (!digp->md.p) { - return atom_notsup; - } + if (argc != 2) + goto bad_arg; + if (!enif_get_tuple(env, argv[0], &arity, &tuple)) + goto bad_arg; + if (arity != 2) + goto bad_arg; + if ((digp = get_digest_type(tuple[0])) == NULL) + goto bad_arg; + if (!enif_inspect_binary(env, tuple[1], &ctx)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &data)) + goto bad_arg; + + if (digp->md.p == NULL) + goto err; switch (EVP_MD_type(digp->md.p)) { @@ -356,21 +361,29 @@ ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] break; #endif default: - return atom_notsup; + goto err; } ASSERT(ctx_size); ASSERT(ctx_update); - if (ctx.size != ctx_size) { - return enif_make_badarg(env); - } + if (ctx.size != ctx_size) + goto bad_arg; - ctx_buff = enif_make_new_binary(env, ctx_size, &new_ctx); + if ((ctx_buff = enif_make_new_binary(env, ctx_size, &new_ctx)) == NULL) + goto err; memcpy(ctx_buff, ctx.data, ctx_size); - ctx_update(ctx_buff, data.data, data.size); + + if (ctx_update(ctx_buff, data.data, data.size) != 1) + goto err; CONSUME_REDS(env, data); return enif_make_tuple2(env, tuple[0], new_ctx); + + bad_arg: + return enif_make_badarg(env); + + err: + return atom_notsup; } ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From 409caa2110638391f25a10e9146fe193bec36cf8 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Tue, 8 Jan 2019 00:19:31 -0800 Subject: Revamp non-EVP hash_final_nif() --- lib/crypto/c_src/hash.c | 57 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/lib/crypto/c_src/hash.c b/lib/crypto/c_src/hash.c index f25d59e9ab..c9fcd35ca2 100644 --- a/lib/crypto/c_src/hash.c +++ b/lib/crypto/c_src/hash.c @@ -395,20 +395,24 @@ ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) int arity; struct digest_type_t *digp = NULL; const EVP_MD *md; - void *new_ctx; + void *new_ctx = NULL; size_t ctx_size = 0; final_fun ctx_final = 0; + unsigned char *outp; - if (!enif_get_tuple(env, argv[0], &arity, &tuple) || - arity != 2 || - !(digp = get_digest_type(tuple[0])) || - !enif_inspect_binary(env, tuple[1], &ctx)) { - return enif_make_badarg(env); - } - md = digp->md.p; - if (!md) { - return atom_notsup; - } + if (argc != 1) + goto bad_arg; + if (!enif_get_tuple(env, argv[0], &arity, &tuple)) + goto bad_arg; + if (arity != 2) + goto bad_arg; + if ((digp = get_digest_type(tuple[0])) == NULL) + goto bad_arg; + if (!enif_inspect_binary(env, tuple[1], &ctx)) + goto bad_arg; + + if ((md = digp->md.p) == NULL) + goto err; switch (EVP_MD_type(md)) { @@ -453,21 +457,36 @@ ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) break; #endif default: - return atom_notsup; + goto err; } ASSERT(ctx_size); ASSERT(ctx_final); - if (ctx.size != ctx_size) { - return enif_make_badarg(env); - } + if (ctx.size != ctx_size) + goto bad_arg; + + if ((new_ctx = enif_alloc(ctx_size)) == NULL) + goto err; - new_ctx = enif_alloc(ctx_size); memcpy(new_ctx, ctx.data, ctx_size); - ctx_final(enif_make_new_binary(env, (size_t)EVP_MD_size(md), &ret), - new_ctx); - enif_free(new_ctx); + if ((outp = enif_make_new_binary(env, (size_t)EVP_MD_size(md), &ret)) == NULL) + goto err; + + if (ctx_final(outp, new_ctx) != 1) + goto err; + + goto done; + + bad_arg: + return enif_make_badarg(env); + + err: + ret = atom_notsup; + + done: + if (new_ctx) + enif_free(new_ctx); return ret; } -- cgit v1.2.3 From 7dd82475ac2c5d479e43442c88be2920af755acc Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 22:35:26 -0800 Subject: Revamp hmac_nif() * Add error handling for all Erlang calls. * Add sanity check via bounds checking --- lib/crypto/c_src/hmac.c | 60 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/lib/crypto/c_src/hmac.c b/lib/crypto/c_src/hmac.c index 6ddbd2c59a..ca39771cc7 100644 --- a/lib/crypto/c_src/hmac.c +++ b/lib/crypto/c_src/hmac.c @@ -51,35 +51,53 @@ ERL_NIF_TERM hmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) unsigned char buff[EVP_MAX_MD_SIZE]; unsigned size = 0, req_size = 0; ERL_NIF_TERM ret; - - digp = get_digest_type(argv[0]); - if (!digp || - !enif_inspect_iolist_as_binary(env, argv[1], &key) || - !enif_inspect_iolist_as_binary(env, argv[2], &data) || - (argc == 4 && !enif_get_uint(env, argv[3], &req_size))) { - return enif_make_badarg(env); + unsigned char *outp; + + if (argc != 3 && argc != 4) + goto bad_arg; + + if ((digp = get_digest_type(argv[0])) == NULL) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) + goto bad_arg; + if (key.size > INT_MAX) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[2], &data)) + goto bad_arg; + if (argc == 4) { + if (!enif_get_uint(env, argv[3], &req_size)) + goto bad_arg; } - if (!digp->md.p || - !HMAC(digp->md.p, - key.data, key.size, - data.data, data.size, - buff, &size)) { - return atom_notsup; - } + if (digp->md.p == NULL) + goto err; + if (HMAC(digp->md.p, + key.data, (int)key.size, + data.data, data.size, + buff, &size) == NULL) + goto err; + ASSERT(0 < size && size <= EVP_MAX_MD_SIZE); CONSUME_REDS(env, data); if (argc == 4) { - if (req_size <= size) { - size = req_size; - } - else { - return enif_make_badarg(env); - } + if (req_size > size) + goto bad_arg; + + size = req_size; } - memcpy(enif_make_new_binary(env, size, &ret), buff, size); + + if ((outp = enif_make_new_binary(env, size, &ret)) == NULL) + goto err; + + memcpy(outp, buff, size); return ret; + + bad_arg: + return enif_make_badarg(env); + + err: + return atom_notsup; } static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context *obj) -- cgit v1.2.3 From 092f5ce536e9643c0152b57c56b6012f15eaac00 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 18:40:56 -0800 Subject: Revamp hmac_init_nif() --- lib/crypto/c_src/hmac.c | 53 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/lib/crypto/c_src/hmac.c b/lib/crypto/c_src/hmac.c index ca39771cc7..00362fce75 100644 --- a/lib/crypto/c_src/hmac.c +++ b/lib/crypto/c_src/hmac.c @@ -120,33 +120,52 @@ ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) struct digest_type_t *digp = NULL; ErlNifBinary key; ERL_NIF_TERM ret; - struct hmac_context *obj; + struct hmac_context *obj = NULL; - digp = get_digest_type(argv[0]); - if (!digp || - !enif_inspect_iolist_as_binary(env, argv[1], &key)) { - return enif_make_badarg(env); - } - if (!digp->md.p) { - return atom_notsup; - } + if (argc != 2) + goto bad_arg; + if ((digp = get_digest_type(argv[0])) == NULL) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) + goto bad_arg; + if (key.size > INT_MAX) + goto bad_arg; + + if (digp->md.p == NULL) + goto err; + + if ((obj = enif_alloc_resource(hmac_context_rtype, sizeof(struct hmac_context))) == NULL) + goto err; + obj->ctx = NULL; + obj->mtx = NULL; + obj->alive = 0; - obj = enif_alloc_resource(hmac_context_rtype, sizeof(struct hmac_context)); - obj->mtx = enif_mutex_create("crypto.hmac"); + if ((obj->ctx = HMAC_CTX_new()) == NULL) + goto err; obj->alive = 1; - obj->ctx = HMAC_CTX_new(); + if ((obj->mtx = enif_mutex_create("crypto.hmac")) == NULL) + goto err; + #if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0) // Check the return value of HMAC_Init: it may fail in FIPS mode // for disabled algorithms - if (!HMAC_Init_ex(obj->ctx, key.data, key.size, digp->md.p, NULL)) { - enif_release_resource(obj); - return atom_notsup; - } + if (!HMAC_Init_ex(obj->ctx, key.data, (int)key.size, digp->md.p, NULL)) + goto err; #else - HMAC_Init_ex(obj->ctx, key.data, key.size, digp->md.p, NULL); + // In ancient versions of OpenSSL, this was a void function. + HMAC_Init_ex(obj->ctx, key.data, (int)key.size, digp->md.p, NULL); #endif ret = enif_make_resource(env, obj); + goto done; + + bad_arg: + return enif_make_badarg(env); + + err: + ret = atom_notsup; + + done: enif_release_resource(obj); return ret; } -- cgit v1.2.3 From 7ce4de4668b0b472d54da1b99687fd3fcd643402 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 22:45:42 -0800 Subject: Revamp hmac_update_nif() * Add error checking for OpenSSL calls. --- lib/crypto/c_src/hmac.c | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/lib/crypto/c_src/hmac.c b/lib/crypto/c_src/hmac.c index 00362fce75..d95ce5cd01 100644 --- a/lib/crypto/c_src/hmac.c +++ b/lib/crypto/c_src/hmac.c @@ -172,23 +172,42 @@ ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ERL_NIF_TERM hmac_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Context, Data) */ + ERL_NIF_TERM ret; ErlNifBinary data; - struct hmac_context* obj; + struct hmac_context *obj = NULL; + + if (argc != 2) + goto bad_arg; + if (!enif_get_resource(env, argv[0], hmac_context_rtype, (void**)&obj)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &data)) + goto bad_arg; - if (!enif_get_resource(env, argv[0], hmac_context_rtype, (void**)&obj) - || !enif_inspect_iolist_as_binary(env, argv[1], &data)) { - return enif_make_badarg(env); - } enif_mutex_lock(obj->mtx); - if (!obj->alive) { - enif_mutex_unlock(obj->mtx); - return enif_make_badarg(env); - } + if (!obj->alive) + goto err; + +#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0) + if (!HMAC_Update(obj->ctx, data.data, data.size)) + goto err; +#else + // In ancient versions of OpenSSL, this was a void function. HMAC_Update(obj->ctx, data.data, data.size); - enif_mutex_unlock(obj->mtx); +#endif CONSUME_REDS(env,data); - return argv[0]; + ret = argv[0]; + goto done; + + bad_arg: + return enif_make_badarg(env); + + err: + ret = enif_make_badarg(env); + + done: + enif_mutex_unlock(obj->mtx); + return ret; } ERL_NIF_TERM hmac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From a8ff8b19b82876b838f3701fb4adaf3a4a0d55d3 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 22:47:26 -0800 Subject: Revamp hmac_final_nif() * Add error handling for all OpenSSL calls. --- lib/crypto/c_src/hmac.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/lib/crypto/c_src/hmac.c b/lib/crypto/c_src/hmac.c index d95ce5cd01..08d9049caa 100644 --- a/lib/crypto/c_src/hmac.c +++ b/lib/crypto/c_src/hmac.c @@ -219,29 +219,49 @@ ERL_NIF_TERM hmac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) unsigned int req_len = 0; unsigned int mac_len; - if (!enif_get_resource(env,argv[0],hmac_context_rtype, (void**)&obj) - || (argc == 2 && !enif_get_uint(env, argv[1], &req_len))) { - return enif_make_badarg(env); + if (argc != 1 && argc != 2) + goto bad_arg; + if (!enif_get_resource(env, argv[0], hmac_context_rtype, (void**)&obj)) + goto bad_arg; + if (argc == 2) { + if (!enif_get_uint(env, argv[1], &req_len)) + goto bad_arg; } enif_mutex_lock(obj->mtx); - if (!obj->alive) { - enif_mutex_unlock(obj->mtx); - return enif_make_badarg(env); - } + if (!obj->alive) + goto err; +#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0) + if (!HMAC_Final(obj->ctx, mac_buf, &mac_len)) + goto err; +#else + // In ancient versions of OpenSSL, this was a void function. HMAC_Final(obj->ctx, mac_buf, &mac_len); - HMAC_CTX_free(obj->ctx); +#endif + + if (obj->ctx) + HMAC_CTX_free(obj->ctx); obj->alive = 0; - enif_mutex_unlock(obj->mtx); if (argc == 2 && req_len < mac_len) { /* Only truncate to req_len bytes if asked. */ mac_len = req_len; } - mac_bin = enif_make_new_binary(env, mac_len, &ret); + if ((mac_bin = enif_make_new_binary(env, mac_len, &ret)) == NULL) + goto err; + memcpy(mac_bin, mac_buf, mac_len); + goto done; + + bad_arg: + return enif_make_badarg(env); + + err: + ret = enif_make_badarg(env); + done: + enif_mutex_unlock(obj->mtx); return ret; } -- cgit v1.2.3 From 3c50a76d8a3b9c2568e4e0291eccf5491dc9b770 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 23:03:31 -0800 Subject: Revamp get_rsa_private_key() * Add error checking for all OpenSSL calls. --- lib/crypto/c_src/rsa.c | 113 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 30 deletions(-) diff --git a/lib/crypto/c_src/rsa.c b/lib/crypto/c_src/rsa.c index 92867671fb..ee0c8272a7 100644 --- a/lib/crypto/c_src/rsa.c +++ b/lib/crypto/c_src/rsa.c @@ -29,38 +29,91 @@ int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa) { /* key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C] */ ERL_NIF_TERM head, tail; - BIGNUM *e, *n, *d; - BIGNUM *p, *q; - BIGNUM *dmp1, *dmq1, *iqmp; + BIGNUM *e = NULL, *n = NULL, *d = NULL; + BIGNUM *p = NULL, *q = NULL; + BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; + + if (!enif_get_list_cell(env, key, &head, &tail)) + goto bad_arg; + if (!get_bn_from_bin(env, head, &e)) + goto bad_arg; + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto bad_arg; + if (!get_bn_from_bin(env, head, &n)) + goto bad_arg; + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto bad_arg; + if (!get_bn_from_bin(env, head, &d)) + goto bad_arg; + + if (!RSA_set0_key(rsa, n, e, d)) + goto err; + /* rsa now owns n, e, and d */ + n = NULL; + e = NULL; + d = NULL; + + if (enif_is_empty_list(env, tail)) + return 1; + + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto bad_arg; + if (!get_bn_from_bin(env, head, &p)) + goto bad_arg; + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto bad_arg; + if (!get_bn_from_bin(env, head, &q)) + goto bad_arg; + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto bad_arg; + if (!get_bn_from_bin(env, head, &dmp1)) + goto bad_arg; + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto bad_arg; + if (!get_bn_from_bin(env, head, &dmq1)) + goto bad_arg; + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto bad_arg; + if (!get_bn_from_bin(env, head, &iqmp)) + goto bad_arg; + if (!enif_is_empty_list(env, tail)) + goto bad_arg; + + if (!RSA_set0_factors(rsa, p, q)) + goto err; + /* rsa now owns p and q */ + p = NULL; + q = NULL; + + if (!RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp)) + goto err; + /* rsa now owns dmp1, dmq1, and iqmp */ + dmp1 = NULL; + dmq1 = NULL; + iqmp = NULL; - if (!enif_get_list_cell(env, key, &head, &tail) - || !get_bn_from_bin(env, head, &e) - || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &n) - || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &d)) { - return 0; - } - (void) RSA_set0_key(rsa, n, e, d); - if (enif_is_empty_list(env, tail)) { - return 1; - } - if (!enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &p) - || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &q) - || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &dmp1) - || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &dmq1) - || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &iqmp) - || !enif_is_empty_list(env, tail)) { - return 0; - } - (void) RSA_set0_factors(rsa, p, q); - (void) RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp); return 1; + + bad_arg: + err: + if (e) + BN_free(e); + if (n) + BN_free(n); + if (d) + BN_free(d); + if (p) + BN_free(p); + if (q) + BN_free(q); + if (dmp1) + BN_free(dmp1); + if (dmq1) + BN_free(dmq1); + if (iqmp) + BN_free(iqmp); + + return 0; } int get_rsa_public_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa) -- cgit v1.2.3 From 9452fdea68a51adad8c9934cf1dbc2d2b71cb5d6 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 23:07:02 -0800 Subject: Revamp get_rsa_public_key() * Added error checking for all OpenSSL calls --- lib/crypto/c_src/rsa.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/lib/crypto/c_src/rsa.c b/lib/crypto/c_src/rsa.c index ee0c8272a7..cfee30c678 100644 --- a/lib/crypto/c_src/rsa.c +++ b/lib/crypto/c_src/rsa.c @@ -120,18 +120,35 @@ int get_rsa_public_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa) { /* key=[E,N] */ ERL_NIF_TERM head, tail; - BIGNUM *e, *n; + BIGNUM *e = NULL, *n = NULL; - if (!enif_get_list_cell(env, key, &head, &tail) - || !get_bn_from_bin(env, head, &e) - || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &n) - || !enif_is_empty_list(env, tail)) { - return 0; - } + if (!enif_get_list_cell(env, key, &head, &tail)) + goto bad_arg; + if (!get_bn_from_bin(env, head, &e)) + goto bad_arg; + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto bad_arg; + if (!get_bn_from_bin(env, head, &n)) + goto bad_arg; + if (!enif_is_empty_list(env, tail)) + goto bad_arg; + + if (!RSA_set0_key(rsa, n, e, NULL)) + goto err; + /* rsa now owns n and e */ + n = NULL; + e = NULL; - (void) RSA_set0_key(rsa, n, e, NULL); return 1; + + bad_arg: + err: + if (e) + BN_free(e); + if (n) + BN_free(n); + + return 0; } /* Creates a term which can be parsed by get_rsa_private_key(). This is a list of plain integer binaries (not mpints). */ -- cgit v1.2.3 From bec8be4ccdf3859861a86eaf5622cf0e04cd2459 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 23:11:44 -0800 Subject: Change bin_from_bn to return atom_error on error. * Add error checking for OpenSSL call. --- lib/crypto/c_src/bn.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/crypto/c_src/bn.c b/lib/crypto/c_src/bn.c index 67a6bb6279..ef69c84679 100644 --- a/lib/crypto/c_src/bn.c +++ b/lib/crypto/c_src/bn.c @@ -84,12 +84,13 @@ ERL_NIF_TERM bin_from_bn(ErlNifEnv* env, const BIGNUM *bn) if ((bin_ptr = enif_make_new_binary(env, (size_t)bn_len, &term)) == NULL) goto err; - BN_bn2bin(bn, bin_ptr); + if (BN_bn2bin(bn, bin_ptr) < 0) + goto err; return term; err: - return enif_make_badarg(env); + return atom_error; } ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From 6e2f0721fdf4ead9871bd89a0a395d2bf4f53a48 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 23:13:48 -0800 Subject: Change strong_rand_range_nif() to check for atom_error from bin_from_bn --- lib/crypto/c_src/rand.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/crypto/c_src/rand.c b/lib/crypto/c_src/rand.c index dd1a7a1600..12e0a53493 100644 --- a/lib/crypto/c_src/rand.c +++ b/lib/crypto/c_src/rand.c @@ -64,7 +64,8 @@ ERL_NIF_TERM strong_rand_range_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM if (!BN_rand_range(bn_rand, bn_range)) goto err; - ret = bin_from_bn(env, bn_rand); + if ((ret = bin_from_bn(env, bn_rand)) == atom_error) + goto err; goto done; bad_arg: -- cgit v1.2.3 From c9a142cfcb27c5697adfe5bb6e622f7e4cf3fd26 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 23:15:15 -0800 Subject: Revamp put_rsa_public_key() * Check for new atom_error from bin_from_bn on error. --- lib/crypto/c_src/rsa.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/lib/crypto/c_src/rsa.c b/lib/crypto/c_src/rsa.c index cfee30c678..d2005e6701 100644 --- a/lib/crypto/c_src/rsa.c +++ b/lib/crypto/c_src/rsa.c @@ -155,33 +155,41 @@ int get_rsa_public_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa) static ERL_NIF_TERM put_rsa_private_key(ErlNifEnv* env, const RSA *rsa) { ERL_NIF_TERM result[8]; - const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp; + const BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL, *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; /* Return at least [E,N,D] */ - n = NULL; e = NULL; d = NULL; RSA_get0_key(rsa, &n, &e, &d); - result[0] = bin_from_bn(env, e); // Exponent E - result[1] = bin_from_bn(env, n); // Modulus N = p*q - result[2] = bin_from_bn(env, d); // Exponent D + if ((result[0] = bin_from_bn(env, e)) == atom_error) // Exponent E + goto err; + if ((result[1] = bin_from_bn(env, n)) == atom_error) // Modulus N = p*q + goto err; + if ((result[2] = bin_from_bn(env, d)) == atom_error) // Exponent D + goto err; /* Check whether the optional additional parameters are available */ - p = NULL; q = NULL; RSA_get0_factors(rsa, &p, &q); - dmp1 = NULL; dmq1 = NULL; iqmp = NULL; RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); if (p && q && dmp1 && dmq1 && iqmp) { - result[3] = bin_from_bn(env, p); // Factor p - result[4] = bin_from_bn(env, q); // Factor q - result[5] = bin_from_bn(env, dmp1); // D mod (p-1) - result[6] = bin_from_bn(env, dmq1); // D mod (q-1) - result[7] = bin_from_bn(env, iqmp); // (1/q) mod p + if ((result[3] = bin_from_bn(env, p)) == atom_error) // Factor p + goto err; + if ((result[4] = bin_from_bn(env, q)) == atom_error) // Factor q + goto err; + if ((result[5] = bin_from_bn(env, dmp1)) == atom_error) // D mod (p-1) + goto err; + if ((result[6] = bin_from_bn(env, dmq1)) == atom_error) // D mod (q-1) + goto err; + if ((result[7] = bin_from_bn(env, iqmp)) == atom_error) // (1/q) mod p + goto err; return enif_make_list_from_array(env, result, 8); } else { return enif_make_list_from_array(env, result, 3); } + + err: + return enif_make_badarg(env); } static int check_erlang_interrupt(int maj, int min, BN_GENCB *ctxt) -- cgit v1.2.3 From 66da4f65ae5b42e981487af44f4d1b5dce92d983 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 23:21:54 -0800 Subject: Revamp rsa_generate_key() * Add error handling for all OpenSSL calls. --- lib/crypto/c_src/rsa.c | 77 ++++++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/lib/crypto/c_src/rsa.c b/lib/crypto/c_src/rsa.c index d2005e6701..540bc1b54d 100644 --- a/lib/crypto/c_src/rsa.c +++ b/lib/crypto/c_src/rsa.c @@ -205,62 +205,71 @@ static int check_erlang_interrupt(int maj, int min, BN_GENCB *ctxt) static ERL_NIF_TERM rsa_generate_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (ModulusSize, PublicExponent) */ + ERL_NIF_TERM ret; int modulus_bits; - BIGNUM *pub_exp, *three; - RSA *rsa; - int success; - ERL_NIF_TERM result; - BN_GENCB *intr_cb; + BIGNUM *pub_exp = NULL, *three = NULL; + RSA *rsa = NULL; + BN_GENCB *intr_cb = NULL; #ifndef HAVE_OPAQUE_BN_GENCB BN_GENCB intr_cb_buf; #endif - if (!enif_get_int(env, argv[0], &modulus_bits) || modulus_bits < 256) { - return enif_make_badarg(env); - } - - if (!get_bn_from_bin(env, argv[1], &pub_exp)) { - return enif_make_badarg(env); - } + if (argc != 2) + goto bad_arg; + if (!enif_get_int(env, argv[0], &modulus_bits)) + goto bad_arg; + if (modulus_bits < 256) + goto bad_arg; + if (!get_bn_from_bin(env, argv[1], &pub_exp)) + goto bad_arg; /* Make sure the public exponent is large enough (at least 3). * Without this, RSA_generate_key_ex() can run forever. */ - three = BN_new(); - BN_set_word(three, 3); - success = BN_cmp(pub_exp, three); - BN_free(three); - if (success < 0) { - BN_free(pub_exp); - return enif_make_badarg(env); - } + if ((three = BN_new()) == NULL) + goto err; + if (!BN_set_word(three, 3)) + goto err; + if (BN_cmp(pub_exp, three) < 0) + goto err; /* For large keys, prime generation can take many seconds. Set up * the callback which we use to test whether the process has been * interrupted. */ #ifdef HAVE_OPAQUE_BN_GENCB - intr_cb = BN_GENCB_new(); + if ((intr_cb = BN_GENCB_new()) == NULL) + goto err; #else intr_cb = &intr_cb_buf; #endif BN_GENCB_set(intr_cb, check_erlang_interrupt, env); - rsa = RSA_new(); - success = RSA_generate_key_ex(rsa, modulus_bits, pub_exp, intr_cb); - BN_free(pub_exp); + if ((rsa = RSA_new()) == NULL) + goto err; -#ifdef HAVE_OPAQUE_BN_GENCB - BN_GENCB_free(intr_cb); -#endif + if (!RSA_generate_key_ex(rsa, modulus_bits, pub_exp, intr_cb)) + goto err; - if (!success) { - RSA_free(rsa); - return atom_error; - } + ret = put_rsa_private_key(env, rsa); + goto done; + + bad_arg: + return enif_make_badarg(env); - result = put_rsa_private_key(env, rsa); - RSA_free(rsa); + err: + ret = atom_error; - return result; + done: + if (pub_exp) + BN_free(pub_exp); + if (three) + BN_free(three); +#ifdef HAVE_OPAQUE_BN_GENCB + if (intr_cb) + BN_GENCB_free(intr_cb); +#endif + if (rsa) + RSA_free(rsa); + return ret; } ERL_NIF_TERM rsa_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From 700715c7911d43a52afa94ad15d847331d84671e Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 23:26:45 -0800 Subject: Revamp srp_value_B_nif() * Add error handling for all OpenSSL calls. * Simplify freeing resources on failure or success. * Change dlen to int. --- lib/crypto/c_src/srp.c | 102 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 36 deletions(-) diff --git a/lib/crypto/c_src/srp.c b/lib/crypto/c_src/srp.c index 1552bc8cc1..18b03206e0 100644 --- a/lib/crypto/c_src/srp.c +++ b/lib/crypto/c_src/srp.c @@ -24,57 +24,87 @@ 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 = NULL, *bn_generator = NULL, *bn_prime = NULL, *bn_multiplier = NULL, *bn_result; - BN_CTX *bn_ctx; + BIGNUM *bn_exponent = NULL, *bn_generator = NULL, *bn_prime = NULL, *bn_multiplier = NULL, *bn_result = NULL; + BN_CTX *bn_ctx = NULL; unsigned char* ptr; - unsigned dlen; + int dlen; ERL_NIF_TERM ret; CHECK_NO_FIPS_MODE(); - 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_generator) BN_free(bn_generator); - if (bn_exponent) BN_free(bn_exponent); - if (bn_prime) BN_free(bn_prime); - return enif_make_badarg(env); - } - - bn_result = BN_new(); - bn_ctx = BN_CTX_new(); + if (argc != 5) + goto bad_arg; + + if (!get_bn_from_bin(env, argv[0], &bn_multiplier)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[1], &bn_verifier)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[2], &bn_generator)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[3], &bn_exponent)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[4], &bn_prime)) + goto bad_arg; + + if ((bn_result = BN_new()) == NULL) + goto err; + if ((bn_ctx = BN_CTX_new()) == NULL) + goto err; /* B = k*v + g^b % N */ /* k * v */ - BN_mod_mul(bn_multiplier, bn_multiplier, bn_verifier, bn_prime, bn_ctx); + if (!BN_mod_mul(bn_multiplier, bn_multiplier, bn_verifier, bn_prime, bn_ctx)) + goto err; /* g^b % N */ - BN_mod_exp(bn_result, bn_generator, bn_exponent, bn_prime, bn_ctx); + if (!BN_mod_exp(bn_result, bn_generator, bn_exponent, bn_prime, bn_ctx)) + goto err; /* k*v + g^b % N */ - BN_mod_add(bn_result, bn_result, bn_multiplier, bn_prime, bn_ctx); + if (!BN_mod_add(bn_result, bn_result, bn_multiplier, bn_prime, bn_ctx)) + goto err; /* 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); + if (!BN_nnmod(bn_multiplier, bn_result, bn_prime, bn_ctx)) + goto err; + + if (BN_is_zero(bn_multiplier)) + goto err; + + if ((dlen = BN_num_bytes(bn_result)) < 0) + goto err; + if ((ptr = enif_make_new_binary(env, (size_t)dlen, &ret)) == NULL) + goto err; + + if (BN_bn2bin(bn_result, ptr) < 0) + goto err; + + goto done; + + bad_arg: + ret = enif_make_badarg(env); + goto done; + + err: + ret = atom_error; + + done: + if (bn_multiplier) + BN_free(bn_multiplier); + if (bn_verifier) + BN_free(bn_verifier); + if (bn_generator) + BN_free(bn_generator); + if (bn_exponent) + BN_free(bn_exponent); + if (bn_prime) + BN_free(bn_prime); + if (bn_result) + BN_free(bn_result); + if (bn_ctx) + BN_CTX_free(bn_ctx); + return ret; } -- cgit v1.2.3 From 0eab42611349dace5a596fcbd495bd5e1ddf1d19 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 23:32:07 -0800 Subject: Revamp srp_user_secret_nif() * Add error handling for all OpenSSL calls. * Consolidate freeing resources in both success and failure path. --- lib/crypto/c_src/srp.c | 145 +++++++++++++++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 59 deletions(-) diff --git a/lib/crypto/c_src/srp.c b/lib/crypto/c_src/srp.c index 18b03206e0..e5ef72af08 100644 --- a/lib/crypto/c_src/srp.c +++ b/lib/crypto/c_src/srp.c @@ -114,80 +114,107 @@ ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar = (B - (k * g^x)) ^ (a + (u * x)) % N */ BIGNUM *bn_exponent = NULL, *bn_a = NULL; - BIGNUM *bn_u = NULL, *bn_multiplier = NULL, *bn_exp2, - *bn_base, *bn_prime = NULL, *bn_generator = NULL, - *bn_B = NULL, *bn_result; - BN_CTX *bn_ctx; - unsigned char* ptr; - unsigned dlen; + BIGNUM *bn_u = NULL, *bn_multiplier = NULL, *bn_exp2 = NULL; + BIGNUM *bn_base = NULL, *bn_prime = NULL, *bn_generator = NULL; + BIGNUM *bn_B = NULL, *bn_result = NULL; + BN_CTX *bn_ctx = NULL; + unsigned char *ptr; + int dlen; ERL_NIF_TERM ret; CHECK_NO_FIPS_MODE(); - 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); - } + if (argc != 7) + goto bad_arg; + if (!get_bn_from_bin(env, argv[0], &bn_a)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[1], &bn_u)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[2], &bn_B)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[3], &bn_multiplier)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[4], &bn_generator)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[5], &bn_exponent)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[6], &bn_prime)) + goto bad_arg; - bn_ctx = BN_CTX_new(); - bn_result = BN_new(); + if ((bn_ctx = BN_CTX_new()) == NULL) + goto err; + if ((bn_result = BN_new()) == NULL) + goto err; /* 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; - } + if (!BN_nnmod(bn_result, bn_B, bn_prime, bn_ctx)) + goto err; + if (BN_is_zero(bn_result)) + goto err; /* (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); + if ((bn_base = BN_new()) == NULL) + goto err; + if (!BN_mod_exp(bn_result, bn_generator, bn_exponent, bn_prime, bn_ctx)) + goto err; + if (!BN_mod_mul(bn_result, bn_multiplier, bn_result, bn_prime, bn_ctx)) + goto err; + if (!BN_mod_sub(bn_base, bn_B, bn_result, bn_prime, bn_ctx)) + goto err; /* a + (u * x) */ - bn_exp2 = BN_new(); - BN_mul(bn_result, bn_u, bn_exponent, bn_ctx); - BN_add(bn_exp2, bn_a, bn_result); + if ((bn_exp2 = BN_new()) == NULL) + goto err; + if (!BN_mul(bn_result, bn_u, bn_exponent, bn_ctx)) + goto err; + if (!BN_add(bn_exp2, bn_a, bn_result)) + goto err; /* (B - (k * g^x)) ^ (a + (u * x)) % N */ - BN_mod_exp(bn_result, bn_base, bn_exp2, bn_prime, bn_ctx); + if (!BN_mod_exp(bn_result, bn_base, bn_exp2, bn_prime, bn_ctx)) + goto err; - 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); + if ((dlen = BN_num_bytes(bn_result)) < 0) + goto err; + if ((ptr = enif_make_new_binary(env, (size_t)dlen, &ret)) == NULL) + goto err; + + if (BN_bn2bin(bn_result, ptr) < 0) + goto err; + + goto done; + + bad_arg: + ret = enif_make_badarg(env); + goto done; + + err: + ret = atom_error; + + done: + 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_exponent) + BN_free(bn_exponent); + if (bn_prime) + BN_free(bn_prime); + if (bn_ctx) + BN_CTX_free(bn_ctx); + if (bn_result) + BN_free(bn_result); + if (bn_base) + BN_free(bn_base); + if (bn_exp2) + BN_free(bn_exp2); - 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; } -- cgit v1.2.3 From 7040f760cb41639024b114f15e4f6d28a154864c Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 23:35:17 -0800 Subject: Revamp srp_host_secret_nif() * Add error checking on all OpenSSL calls. * Change dlen to int. * Consolidate all of the freeing of resources into a common path. --- lib/crypto/c_src/srp.c | 116 +++++++++++++++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 47 deletions(-) diff --git a/lib/crypto/c_src/srp.c b/lib/crypto/c_src/srp.c index e5ef72af08..5a49a1c1b4 100644 --- a/lib/crypto/c_src/srp.c +++ b/lib/crypto/c_src/srp.c @@ -224,63 +224,85 @@ ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar = (A * v^u) ^ b % N */ BIGNUM *bn_b = NULL, *bn_verifier = NULL; - BIGNUM *bn_prime = NULL, *bn_A = NULL, *bn_u = NULL, *bn_base, *bn_result; - BN_CTX *bn_ctx; - unsigned char* ptr; - unsigned dlen; + BIGNUM *bn_prime = NULL, *bn_A = NULL, *bn_u = NULL, *bn_base = NULL, *bn_result = NULL; + BN_CTX *bn_ctx = NULL; + unsigned char *ptr; + int dlen; ERL_NIF_TERM ret; CHECK_NO_FIPS_MODE(); - 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(); + if (argc != 5) + goto bad_arg; + if (!get_bn_from_bin(env, argv[0], &bn_verifier)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[1], &bn_b)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[2], &bn_u)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[3], &bn_A)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[4], &bn_prime)) + goto bad_arg; - /* 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); + if ((bn_ctx = BN_CTX_new()) == NULL) + goto err; + if ((bn_result = BN_new()) == NULL) + goto err; - return atom_error; - } + /* check that A % N != 0 */ + if (!BN_nnmod(bn_result, bn_A, bn_prime, bn_ctx)) + goto err; + if (BN_is_zero(bn_result)) + goto err; /* (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); + if ((bn_base = BN_new()) == NULL) + goto err; + if (!BN_mod_exp(bn_base, bn_verifier, bn_u, bn_prime, bn_ctx)) + goto err; + if (!BN_mod_mul(bn_base, bn_A, bn_base, bn_prime, bn_ctx)) + goto err; /* (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); + if (!BN_mod_exp(bn_result, bn_base, bn_b, bn_prime, bn_ctx)) + goto err; + + if ((dlen = BN_num_bytes(bn_result)) < 0) + goto err; + if ((ptr = enif_make_new_binary(env, (size_t)dlen, &ret)) == NULL) + goto err; + + if (BN_bn2bin(bn_result, ptr) < 0) + goto err; + + goto done; + + bad_arg: + ret = enif_make_badarg(env); + goto done; + + err: + ret = atom_error; + + done: + 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); + if (bn_ctx) + BN_CTX_free(bn_ctx); + if (bn_result) + BN_free(bn_result); + if (bn_base) + BN_free(bn_base); + return ret; } -- cgit v1.2.3 From 2ef1ceab5d3c24b82be6a8bb737c7a61b223f593 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 23:42:58 -0800 Subject: Revamp aead_encrypt() * Add error handling for all OpenSSL calls. * Add bounds check and casting where appropriate. --- lib/crypto/c_src/aead.c | 178 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 120 insertions(+), 58 deletions(-) diff --git a/lib/crypto/c_src/aead.c b/lib/crypto/c_src/aead.c index b7ed06e3bc..44a662c991 100644 --- a/lib/crypto/c_src/aead.c +++ b/lib/crypto/c_src/aead.c @@ -24,101 +24,163 @@ ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Type,Key,Iv,AAD,In) */ #if defined(HAVE_AEAD) - EVP_CIPHER_CTX *ctx; + EVP_CIPHER_CTX *ctx = NULL; const EVP_CIPHER *cipher = NULL; ErlNifBinary key, iv, aad, in; unsigned int tag_len; unsigned char *outp, *tagp; - ERL_NIF_TERM type, out, out_tag; + ERL_NIF_TERM type, out, out_tag, ret; int len, ctx_ctrl_set_ivlen, ctx_ctrl_get_tag; type = argv[0]; - if (!enif_is_atom(env, type) - || !enif_inspect_iolist_as_binary(env, argv[1], &key) - || !enif_inspect_binary(env, argv[2], &iv) - || !enif_inspect_iolist_as_binary(env, argv[3], &aad) - || !enif_inspect_iolist_as_binary(env, argv[4], &in) - || !enif_get_uint(env, argv[5], &tag_len)) { - return enif_make_badarg(env); - } + if (argc != 6) + goto bad_arg; + if (!enif_is_atom(env, type)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &iv)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[3], &aad)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[4], &in)) + goto bad_arg; + if (!enif_get_uint(env, argv[5], &tag_len)) + goto bad_arg; + + if (tag_len > INT_MAX + || iv.size > INT_MAX + || in.size > INT_MAX + || aad.size > INT_MAX) + goto bad_arg; /* Use cipher_type some day. Must check block_encrypt|decrypt first */ #if defined(HAVE_GCM) if (type == atom_aes_gcm) { - if ((iv.size > 0) - && (1 <= tag_len && tag_len <= 16)) { - ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN; - ctx_ctrl_get_tag = EVP_CTRL_GCM_GET_TAG; - if (key.size == 16) cipher = EVP_aes_128_gcm(); - else if (key.size == 24) cipher = EVP_aes_192_gcm(); - else if (key.size == 32) cipher = EVP_aes_256_gcm(); - else enif_make_badarg(env); - } else - enif_make_badarg(env); + if (iv.size == 0) + goto bad_arg; + if (tag_len < 1 || tag_len > 16) + goto bad_arg; + + ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN; + ctx_ctrl_get_tag = EVP_CTRL_GCM_GET_TAG; + + switch (key.size) { + case 16: + cipher = EVP_aes_128_gcm(); + break; + case 24: + cipher = EVP_aes_192_gcm(); + break; + case 32: + cipher = EVP_aes_256_gcm(); + break; + default: + goto bad_arg; + } } else #endif #if defined(HAVE_CCM) if (type == atom_aes_ccm) { - if ((7 <= iv.size && iv.size <= 13) - && (4 <= tag_len && tag_len <= 16) - && ((tag_len & 1) == 0) - ) { - ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN; - ctx_ctrl_get_tag = EVP_CTRL_CCM_GET_TAG; - if (key.size == 16) cipher = EVP_aes_128_ccm(); - else if (key.size == 24) cipher = EVP_aes_192_ccm(); - else if (key.size == 32) cipher = EVP_aes_256_ccm(); - else enif_make_badarg(env); - } else - enif_make_badarg(env); + if (iv.size < 7 || iv.size > 13) + goto bad_arg; + if (tag_len < 4 || tag_len > 16) + goto bad_arg; + if ((tag_len & 1) != 0) + goto bad_arg; + + ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN; + ctx_ctrl_get_tag = EVP_CTRL_CCM_GET_TAG; + + switch (key.size) { + case 16: + cipher = EVP_aes_128_ccm(); + break; + case 24: + cipher = EVP_aes_192_ccm(); + break; + case 32: + cipher = EVP_aes_256_ccm(); + break; + default: + goto bad_arg; + } } else #endif #if defined(HAVE_CHACHA20_POLY1305) if (type == atom_chacha20_poly1305) { - if ((key.size == 32) - && (1 <= iv.size && iv.size <= 16) - && (tag_len == 16) - ) { - ctx_ctrl_set_ivlen = EVP_CTRL_AEAD_SET_IVLEN; - ctx_ctrl_get_tag = EVP_CTRL_AEAD_GET_TAG, - cipher = EVP_chacha20_poly1305(); - } else enif_make_badarg(env); + if (key.size != 32) + goto bad_arg; + if (iv.size < 1 || iv.size > 16) + goto bad_arg; + if (tag_len != 16) + goto bad_arg; + + ctx_ctrl_set_ivlen = EVP_CTRL_AEAD_SET_IVLEN; + ctx_ctrl_get_tag = EVP_CTRL_AEAD_GET_TAG; + + cipher = EVP_chacha20_poly1305(); + } else #endif return enif_raise_exception(env, atom_notsup); - ctx = EVP_CIPHER_CTX_new(); - if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) goto out_err; - if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, iv.size, NULL) != 1) goto out_err; + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) + goto err; + + if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) + goto err; + if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, (int)iv.size, NULL) != 1) + goto err; #if defined(HAVE_CCM) if (type == atom_aes_ccm) { - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_len, NULL) != 1) goto out_err; - if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err; - if (EVP_EncryptUpdate(ctx, NULL, &len, NULL, in.size) != 1) goto out_err; + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, (int)tag_len, NULL) != 1) + goto err; + if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) + goto err; + if (EVP_EncryptUpdate(ctx, NULL, &len, NULL, (int)in.size) != 1) + goto err; } else #endif - if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err; + { + if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) + goto err; + } - if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) goto out_err; + if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, (int)aad.size) != 1) + goto err; - outp = enif_make_new_binary(env, in.size, &out); + if ((outp = enif_make_new_binary(env, in.size, &out)) == NULL) + goto err; - if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1) goto out_err; - if (EVP_EncryptFinal_ex(ctx, outp/*+len*/, &len) != 1) goto out_err; + if (EVP_EncryptUpdate(ctx, outp, &len, in.data, (int)in.size) != 1) + goto err; + if (EVP_EncryptFinal_ex(ctx, outp/*+len*/, &len) != 1) + goto err; - tagp = enif_make_new_binary(env, tag_len, &out_tag); + if ((tagp = enif_make_new_binary(env, tag_len, &out_tag)) == NULL) + goto err; - if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_get_tag, tag_len, tagp) != 1) goto out_err; + if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_get_tag, (int)tag_len, tagp) != 1) + goto err; - EVP_CIPHER_CTX_free(ctx); CONSUME_REDS(env, in); - return enif_make_tuple2(env, out, out_tag); + ret = enif_make_tuple2(env, out, out_tag); + goto done; -out_err: - EVP_CIPHER_CTX_free(ctx); - return atom_error; + bad_arg: + ret = enif_make_badarg(env); + goto done; + + err: + ret = atom_error; + + done: + if (ctx) + EVP_CIPHER_CTX_free(ctx); + return ret; #else return enif_raise_exception(env, atom_notsup); -- cgit v1.2.3 From 121f1302e6fe5e1c265501f9f98b2834f7250497 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 23:47:56 -0800 Subject: Revamp aead_decrypt() * Add bounds checks and casting where appropriate. --- lib/crypto/c_src/aead.c | 161 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 109 insertions(+), 52 deletions(-) diff --git a/lib/crypto/c_src/aead.c b/lib/crypto/c_src/aead.c index 44a662c991..f33056b74c 100644 --- a/lib/crypto/c_src/aead.c +++ b/lib/crypto/c_src/aead.c @@ -190,105 +190,162 @@ ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Type,Key,Iv,AAD,In,Tag) */ #if defined(HAVE_AEAD) - EVP_CIPHER_CTX *ctx; + EVP_CIPHER_CTX *ctx = NULL; const EVP_CIPHER *cipher = NULL; ErlNifBinary key, iv, aad, in, tag; unsigned char *outp; - ERL_NIF_TERM type, out; + ERL_NIF_TERM type, out, ret; int len, ctx_ctrl_set_ivlen, ctx_ctrl_set_tag; + if (argc != 6) + goto bad_arg; + type = argv[0]; #if defined(HAVE_GCM_EVP_DECRYPT_BUG) if (type == atom_aes_gcm) return aes_gcm_decrypt_NO_EVP(env, argc, argv); #endif - if (!enif_is_atom(env, type) - || !enif_inspect_iolist_as_binary(env, argv[1], &key) - || !enif_inspect_binary(env, argv[2], &iv) - || !enif_inspect_iolist_as_binary(env, argv[3], &aad) - || !enif_inspect_iolist_as_binary(env, argv[4], &in) - || !enif_inspect_iolist_as_binary(env, argv[5], &tag)) { - return enif_make_badarg(env); - } + if (!enif_is_atom(env, type)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &iv)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[3], &aad)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[4], &in)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[5], &tag)) + goto bad_arg; + + if (tag.size > INT_MAX + || key.size > INT_MAX + || iv.size > INT_MAX + || in.size > INT_MAX + || aad.size > INT_MAX) + goto bad_arg; /* Use cipher_type some day. Must check block_encrypt|decrypt first */ #if defined(HAVE_GCM) if (type == atom_aes_gcm) { - if (iv.size > 0) { - ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN; - ctx_ctrl_set_tag = EVP_CTRL_GCM_SET_TAG; - if (key.size == 16) cipher = EVP_aes_128_gcm(); - else if (key.size == 24) cipher = EVP_aes_192_gcm(); - else if (key.size == 32) cipher = EVP_aes_256_gcm(); - else enif_make_badarg(env); - } else - enif_make_badarg(env); + if (iv.size == 0) + goto bad_arg; + + ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN; + ctx_ctrl_set_tag = EVP_CTRL_GCM_SET_TAG; + + switch (key.size) { + case 16: + cipher = EVP_aes_128_gcm(); + break; + case 24: + cipher = EVP_aes_192_gcm(); + break; + case 32: + cipher = EVP_aes_256_gcm(); + break; + default: + goto bad_arg; + } } else #endif #if defined(HAVE_CCM) if (type == atom_aes_ccm) { - if (iv.size > 0) { - ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN; - if (key.size == 16) cipher = EVP_aes_128_ccm(); - else if (key.size == 24) cipher = EVP_aes_192_ccm(); - else if (key.size == 32) cipher = EVP_aes_256_ccm(); - else enif_make_badarg(env); - } else - enif_make_badarg(env); + if (iv.size == 0) + goto bad_arg; + + ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN; + ctx_ctrl_set_tag = EVP_CTRL_CCM_SET_TAG; + + switch (key.size) { + case 16: + cipher = EVP_aes_128_ccm(); + break; + case 24: + cipher = EVP_aes_192_ccm(); + break; + case 32: + cipher = EVP_aes_256_ccm(); + break; + default: + goto bad_arg; + } } else #endif #if defined(HAVE_CHACHA20_POLY1305) if (type == atom_chacha20_poly1305) { - if ((key.size == 32) - && (1 <= iv.size && iv.size <= 16) - && tag.size == 16 - ) { - ctx_ctrl_set_ivlen = EVP_CTRL_AEAD_SET_IVLEN; - ctx_ctrl_set_tag = EVP_CTRL_AEAD_SET_TAG; - cipher = EVP_chacha20_poly1305(); - } else enif_make_badarg(env); + if (key.size != 32) + goto bad_arg; + if (iv.size < 1 || iv.size > 16) + goto bad_arg; + if (tag.size != 16) + goto bad_arg; + + ctx_ctrl_set_ivlen = EVP_CTRL_AEAD_SET_IVLEN; + ctx_ctrl_set_tag = EVP_CTRL_AEAD_SET_TAG; + + cipher = EVP_chacha20_poly1305(); } else #endif return enif_raise_exception(env, atom_notsup); - outp = enif_make_new_binary(env, in.size, &out); + if ((outp = enif_make_new_binary(env, in.size, &out)) == NULL) + goto err; - ctx = EVP_CIPHER_CTX_new(); - if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) goto out_err; - if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, iv.size, NULL) != 1) goto out_err; + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) + goto err; + if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) + goto err; + if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, (int)iv.size, NULL) != 1) + goto err; #if defined(HAVE_CCM) if (type == atom_aes_ccm) { - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag.size, tag.data) != 1) goto out_err; + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, (int)tag.size, tag.data) != 1) + goto err; } #endif - if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err; + if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) + goto err; #if defined(HAVE_CCM) if (type == atom_aes_ccm) { - if (1 != EVP_DecryptUpdate(ctx, NULL, &len, NULL, in.size)) goto out_err; + if (EVP_DecryptUpdate(ctx, NULL, &len, NULL, (int)in.size) != 1) + goto err; } #endif - if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) goto out_err; - if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1) goto out_err; + if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, (int)aad.size) != 1) + goto err; + if (EVP_DecryptUpdate(ctx, outp, &len, in.data, (int)in.size) != 1) + goto err; #if defined(HAVE_GCM) || defined(HAVE_CHACHA20_POLY1305) if (type == atom_aes_gcm) { - if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_tag, tag.size, tag.data) != 1) goto out_err; - if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1) goto out_err; + if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_tag, (int)tag.size, tag.data) != 1) + goto err; + if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1) + goto err; } #endif - EVP_CIPHER_CTX_free(ctx); - CONSUME_REDS(env, in); - return out; + ret = out; + goto done; + + bad_arg: + ret = enif_make_badarg(env); + goto done; + + err: + ret = atom_error; + + done: + if (ctx) + EVP_CIPHER_CTX_free(ctx); + return ret; -out_err: - EVP_CIPHER_CTX_free(ctx); - return atom_error; #else return enif_raise_exception(env, atom_notsup); #endif -- cgit v1.2.3 From 353d0b59b3a80df1d2549c98961bb475b50c47b3 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 23:50:51 -0800 Subject: Reavmp aes_cfb_8_crypt() * Add error checking for OpenSSL calls. * Note when an unusual OpenSSL API return value is checked. --- lib/crypto/c_src/aes.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/crypto/c_src/aes.c b/lib/crypto/c_src/aes.c index 36cd02933f..b2bf6f53b8 100644 --- a/lib/crypto/c_src/aes.c +++ b/lib/crypto/c_src/aes.c @@ -28,24 +28,41 @@ ERL_NIF_TERM aes_cfb_8_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] unsigned char ivec_clone[16]; /* writable copy */ int new_ivlen = 0; ERL_NIF_TERM ret; + unsigned char *outp; CHECK_NO_FIPS_MODE(); - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) - || !(key.size == 16 || key.size == 24 || key.size == 32) - || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16 - || !enif_inspect_iolist_as_binary(env, argv[2], &text)) { - return enif_make_badarg(env); - } + if (argc != 4) + goto bad_arg; + + if (!enif_inspect_iolist_as_binary(env, argv[0], &key)) + goto bad_arg; + if (key.size != 16 && key.size != 24 && key.size != 32) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &ivec)) + goto bad_arg; + if (ivec.size != 16) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[2], &text)) + goto bad_arg; memcpy(ivec_clone, ivec.data, 16); - AES_set_encrypt_key(key.data, key.size * 8, &aes_key); + + /* NOTE: This function returns 0 on success unlike most OpenSSL functions */ + if (AES_set_encrypt_key(key.data, (int)key.size * 8, &aes_key) != 0) + goto err; + if ((outp = enif_make_new_binary(env, text.size, &ret)) == NULL) + goto err; AES_cfb8_encrypt((unsigned char *) text.data, - enif_make_new_binary(env, text.size, &ret), + outp, text.size, &aes_key, ivec_clone, &new_ivlen, (argv[3] == atom_true)); CONSUME_REDS(env,text); return ret; + + bad_arg: + err: + return enif_make_badarg(env); } ERL_NIF_TERM aes_cfb_128_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From 076e9c82063207378aedd9fecc73b98f17976b5c Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 23:53:05 -0800 Subject: Revamp aes_cfb_128_crypt_nif() * Mention where an OpenSSL call uses 0 on success. --- lib/crypto/c_src/aes.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/crypto/c_src/aes.c b/lib/crypto/c_src/aes.c index b2bf6f53b8..b0eabca0db 100644 --- a/lib/crypto/c_src/aes.c +++ b/lib/crypto/c_src/aes.c @@ -72,22 +72,39 @@ ERL_NIF_TERM aes_cfb_128_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned char ivec_clone[16]; /* writable copy */ int new_ivlen = 0; ERL_NIF_TERM ret; + unsigned char *outp; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) - || !(key.size == 16 || key.size == 24 || key.size == 32) - || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16 - || !enif_inspect_iolist_as_binary(env, argv[2], &text)) { - return enif_make_badarg(env); - } + if (argc != 4) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[0], &key)) + goto bad_arg; + if (key.size != 16 && key.size != 24 && key.size != 32) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &ivec)) + goto bad_arg; + if (ivec.size != 16) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[2], &text)) + goto bad_arg; memcpy(ivec_clone, ivec.data, 16); - AES_set_encrypt_key(key.data, key.size * 8, &aes_key); + + /* NOTE: This function returns 0 on success unlike most OpenSSL functions */ + if (AES_set_encrypt_key(key.data, (int)key.size * 8, &aes_key) != 0) + goto err; + + if ((outp = enif_make_new_binary(env, text.size, &ret)) == NULL) + goto err; AES_cfb128_encrypt((unsigned char *) text.data, - enif_make_new_binary(env, text.size, &ret), + outp, text.size, &aes_key, ivec_clone, &new_ivlen, (argv[3] == atom_true)); CONSUME_REDS(env,text); return ret; + + bad_arg: + err: + return enif_make_badarg(env); } ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From 1af9e202a35bf7ed2057d69131a73158681fbfdd Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Tue, 8 Jan 2019 00:38:27 -0800 Subject: Revamp aes_ige_crypt_nif() * Mention when OpenSSL uses 0 for success. * Add casting to match the types. --- lib/crypto/c_src/aes.c | 50 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/lib/crypto/c_src/aes.c b/lib/crypto/c_src/aes.c index b0eabca0db..51c2266987 100644 --- a/lib/crypto/c_src/aes.c +++ b/lib/crypto/c_src/aes.c @@ -113,36 +113,54 @@ ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv ErlNifBinary key_bin, ivec_bin, data_bin; AES_KEY aes_key; unsigned char ivec[32]; - int i; + int type; unsigned char* ret_ptr; ERL_NIF_TERM ret; CHECK_NO_FIPS_MODE(); - if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) - || (key_bin.size != 16 && key_bin.size != 32) - || !enif_inspect_binary(env, argv[1], &ivec_bin) - || ivec_bin.size != 32 - || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin) - || data_bin.size % 16 != 0) { - - return enif_make_badarg(env); - } + if (argc != 4) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)) + goto bad_arg; + if (key_bin.size != 16 && key_bin.size != 32) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &ivec_bin)) + goto bad_arg; + if (ivec_bin.size != 32) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[2], &data_bin)) + goto bad_arg; + if (data_bin.size % 16 != 0) + goto bad_arg; if (argv[3] == atom_true) { - i = AES_ENCRYPT; - AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key); + type = AES_ENCRYPT; + /* NOTE: This function returns 0 on success unlike most OpenSSL functions */ + if (AES_set_encrypt_key(key_bin.data, (int)key_bin.size * 8, &aes_key) != 0) + goto err; } else { - i = AES_DECRYPT; - AES_set_decrypt_key(key_bin.data, key_bin.size*8, &aes_key); + type = AES_DECRYPT; + /* NOTE: This function returns 0 on success unlike most OpenSSL functions */ + if (AES_set_decrypt_key(key_bin.data, (int)key_bin.size * 8, &aes_key) != 0) + goto err; } - ret_ptr = enif_make_new_binary(env, data_bin.size, &ret); + if ((ret_ptr = enif_make_new_binary(env, data_bin.size, &ret)) == NULL) + goto err; + memcpy(ivec, ivec_bin.data, 32); /* writable copy */ - AES_ige_encrypt(data_bin.data, ret_ptr, data_bin.size, &aes_key, ivec, i); + + AES_ige_encrypt(data_bin.data, ret_ptr, data_bin.size, &aes_key, ivec, type); + CONSUME_REDS(env,data_bin); return ret; + + bad_arg: + err: + return enif_make_badarg(env); + #else return atom_notsup; #endif -- cgit v1.2.3 From 46f66eae9471c0218f79bcb81b6b8678d1ca5069 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Thu, 3 Jan 2019 23:58:02 -0800 Subject: Revamp aes_ctr_stream_init() * Add error handling for all OpenSSL calls. --- lib/crypto/c_src/aes.c | 56 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/lib/crypto/c_src/aes.c b/lib/crypto/c_src/aes.c index 51c2266987..624e9427fb 100644 --- a/lib/crypto/c_src/aes.c +++ b/lib/crypto/c_src/aes.c @@ -173,30 +173,56 @@ ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Key, IVec) */ ErlNifBinary key_bin, ivec_bin; - struct evp_cipher_ctx *ctx; + struct evp_cipher_ctx *ctx = NULL; const EVP_CIPHER *cipher; ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) - || !enif_inspect_binary(env, argv[1], &ivec_bin) - || ivec_bin.size != 16) { - return enif_make_badarg(env); - } + if (argc != 2) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &ivec_bin)) + goto bad_arg; + if (ivec_bin.size != 16) + goto bad_arg; switch (key_bin.size) { - case 16: cipher = EVP_aes_128_ctr(); break; - case 24: cipher = EVP_aes_192_ctr(); break; - case 32: cipher = EVP_aes_256_ctr(); break; - default: return enif_make_badarg(env); + case 16: + cipher = EVP_aes_128_ctr(); + break; + case 24: + cipher = EVP_aes_192_ctr(); + break; + case 32: + cipher = EVP_aes_256_ctr(); + break; + default: + goto bad_arg; } - ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx)); - ctx->ctx = EVP_CIPHER_CTX_new(); - EVP_CipherInit_ex(ctx->ctx, cipher, NULL, - key_bin.data, ivec_bin.data, 1); - EVP_CIPHER_CTX_set_padding(ctx->ctx, 0); + if ((ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx))) == NULL) + goto err; + if ((ctx->ctx = EVP_CIPHER_CTX_new()) == NULL) + goto err; + + if (EVP_CipherInit_ex(ctx->ctx, cipher, NULL, + key_bin.data, ivec_bin.data, 1) != 1) + goto err; + + if (EVP_CIPHER_CTX_set_padding(ctx->ctx, 0) != 1) + goto err; + ret = enif_make_resource(env, ctx); + goto done; + + bad_arg: + return enif_make_badarg(env); + + err: + ret = enif_make_badarg(env); + + done: enif_release_resource(ctx); return ret; } -- cgit v1.2.3 From 1e792cb2f5c29413476f5149fb1e5bd677cfe1ea Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 00:00:28 -0800 Subject: Revamp aes_ctr_stream_encrypt() * Add error handling for all OpenSSL and Erlang calls. --- lib/crypto/c_src/aes.c | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/lib/crypto/c_src/aes.c b/lib/crypto/c_src/aes.c index 624e9427fb..530b64fea0 100644 --- a/lib/crypto/c_src/aes.c +++ b/lib/crypto/c_src/aes.c @@ -229,26 +229,48 @@ ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Context, Data) */ - struct evp_cipher_ctx *ctx, *new_ctx; + struct evp_cipher_ctx *ctx = NULL, *new_ctx = NULL; ErlNifBinary data_bin; ERL_NIF_TERM ret, cipher_term; unsigned char *out; int outl = 0; - if (!enif_get_resource(env, argv[0], evp_cipher_ctx_rtype, (void**)&ctx) - || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { - return enif_make_badarg(env); - } - new_ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx)); - new_ctx->ctx = EVP_CIPHER_CTX_new(); - EVP_CIPHER_CTX_copy(new_ctx->ctx, ctx->ctx); - out = enif_make_new_binary(env, data_bin.size, &cipher_term); - EVP_CipherUpdate(new_ctx->ctx, out, &outl, data_bin.data, data_bin.size); + if (argc != 2) + goto bad_arg; + if (!enif_get_resource(env, argv[0], evp_cipher_ctx_rtype, (void**)&ctx)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) + goto bad_arg; + if (data_bin.size > INT_MAX) + goto bad_arg; + + if ((new_ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx))) == NULL) + goto err; + if ((new_ctx->ctx = EVP_CIPHER_CTX_new()) == NULL) + goto err; + + if (EVP_CIPHER_CTX_copy(new_ctx->ctx, ctx->ctx) != 1) + goto err; + + if ((out = enif_make_new_binary(env, data_bin.size, &cipher_term)) == NULL) + goto err; + + if (EVP_CipherUpdate(new_ctx->ctx, out, &outl, data_bin.data, (int)data_bin.size) != 1) + goto err; ASSERT(outl == data_bin.size); ret = enif_make_tuple2(env, enif_make_resource(env, new_ctx), cipher_term); - enif_release_resource(new_ctx); CONSUME_REDS(env,data_bin); + goto done; + + bad_arg: + return enif_make_badarg(env); + + err: + ret = enif_make_badarg(env); + + done: + enif_release_resource(new_ctx); return ret; } -- cgit v1.2.3 From 73961f5219fd1ddf6181a05134a0ddceb6d99510 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 00:02:05 -0800 Subject: Revamp non-EVP aes_ctr_stream_init() --- lib/crypto/c_src/aes.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/crypto/c_src/aes.c b/lib/crypto/c_src/aes.c index 530b64fea0..3c0f1d8d2a 100644 --- a/lib/crypto/c_src/aes.c +++ b/lib/crypto/c_src/aes.c @@ -280,17 +280,29 @@ ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar {/* (Key, IVec) */ ErlNifBinary key_bin, ivec_bin; ERL_NIF_TERM ecount_bin; + unsigned char *outp; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) - || !enif_inspect_binary(env, argv[1], &ivec_bin) - || !(key_bin.size == 16 || key_bin.size == 24 || key_bin.size ==32) - || ivec_bin.size != 16) { - return enif_make_badarg(env); - } + if (argc != 2) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)) + goto bad_arg; + if (key_bin.size != 16 && key_bin.size != 24 && key_bin.size != 32) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &ivec_bin)) + goto bad_arg; + if (ivec_bin.size != 16) + goto bad_arg; + + if ((outp = enif_make_new_binary(env, AES_BLOCK_SIZE, &ecount_bin)) == NULL) + goto err; + + memset(outp, 0, AES_BLOCK_SIZE); - memset(enif_make_new_binary(env, AES_BLOCK_SIZE, &ecount_bin), - 0, AES_BLOCK_SIZE); return enif_make_tuple4(env, argv[0], argv[1], ecount_bin, enif_make_int(env, 0)); + + bad_arg: + err: + return enif_make_badarg(env); } ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From 80627dc43b81951bb62f9bd66c03275e5939239a Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 00:07:04 -0800 Subject: Revamp non-EVP aes_ctr_stream_encrypt() * Moved AES_set_encrypt_key() call until after all arguments are parsed. * Added bounds check before casting. * Added error handling for all OpenSSL calls. * Noted when unusual OpenSSL API call returns 0 on success. --- lib/crypto/c_src/aes.c | 52 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/lib/crypto/c_src/aes.c b/lib/crypto/c_src/aes.c index 3c0f1d8d2a..665467bc2c 100644 --- a/lib/crypto/c_src/aes.c +++ b/lib/crypto/c_src/aes.c @@ -315,26 +315,48 @@ ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM const ERL_NIF_TERM *state_term; unsigned char * ivec2_buf; unsigned char * ecount2_buf; + unsigned char *outp; - if (!enif_get_tuple(env, argv[0], &state_arity, &state_term) - || state_arity != 4 - || !enif_inspect_iolist_as_binary(env, state_term[0], &key_bin) - || AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key) != 0 - || !enif_inspect_binary(env, state_term[1], &ivec_bin) || ivec_bin.size != 16 - || !enif_inspect_binary(env, state_term[2], &ecount_bin) || ecount_bin.size != AES_BLOCK_SIZE - || !enif_get_uint(env, state_term[3], &num) - || !enif_inspect_iolist_as_binary(env, argv[1], &text_bin)) { - return enif_make_badarg(env); - } + if (argc != 2) + goto bad_arg; + if (!enif_get_tuple(env, argv[0], &state_arity, &state_term)) + goto bad_arg; + if (state_arity != 4) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, state_term[0], &key_bin)) + goto bad_arg; + if (key_bin.size > INT_MAX / 8) + goto bad_arg; + if (!enif_inspect_binary(env, state_term[1], &ivec_bin)) + goto bad_arg; + if (ivec_bin.size != 16) + goto bad_arg; + if (!enif_inspect_binary(env, state_term[2], &ecount_bin)) + goto bad_arg; + if (ecount_bin.size != AES_BLOCK_SIZE) + goto bad_arg; + if (!enif_get_uint(env, state_term[3], &num)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &text_bin)) + goto bad_arg; - ivec2_buf = enif_make_new_binary(env, ivec_bin.size, &ivec2_term); - ecount2_buf = enif_make_new_binary(env, ecount_bin.size, &ecount2_term); + /* NOTE: This function returns 0 on success unlike most OpenSSL functions */ + if (AES_set_encrypt_key(key_bin.data, (int)key_bin.size * 8, &aes_key) != 0) + goto bad_arg; + + if ((ivec2_buf = enif_make_new_binary(env, ivec_bin.size, &ivec2_term)) == NULL) + goto err; + if ((ecount2_buf = enif_make_new_binary(env, ecount_bin.size, &ecount2_term)) == NULL) + goto err; memcpy(ivec2_buf, ivec_bin.data, 16); memcpy(ecount2_buf, ecount_bin.data, ecount_bin.size); + if ((outp = enif_make_new_binary(env, text_bin.size, &cipher_term)) == NULL) + goto err; + AES_ctr128_encrypt((unsigned char *) text_bin.data, - enif_make_new_binary(env, text_bin.size, &cipher_term), + outp, text_bin.size, &aes_key, ivec2_buf, ecount2_buf, &num); num2_term = enif_make_uint(env, num); @@ -342,6 +364,10 @@ ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ret = enif_make_tuple2(env, new_state_term, cipher_term); CONSUME_REDS(env,text_bin); return ret; + + bad_arg: + err: + return enif_make_badarg(env); } #endif /* !HAVE_EVP_AES_CTR */ -- cgit v1.2.3 From 202b22f5af173029f4c66a7e77026f0d3f8e8766 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 00:14:19 -0800 Subject: Revamp aes_gcm_decrypt_NO_EVP() * Add casts where appropriate and use bounds checking. * Mention where OpenSSL APIs use 0 for success. --- lib/crypto/c_src/aes.c | 74 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 26 deletions(-) diff --git a/lib/crypto/c_src/aes.c b/lib/crypto/c_src/aes.c index 665467bc2c..94b874298e 100644 --- a/lib/crypto/c_src/aes.c +++ b/lib/crypto/c_src/aes.c @@ -374,47 +374,69 @@ ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM #ifdef HAVE_GCM_EVP_DECRYPT_BUG ERL_NIF_TERM aes_gcm_decrypt_NO_EVP(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Type,Key,Iv,AAD,In,Tag) */ - GCM128_CONTEXT *ctx; + GCM128_CONTEXT *ctx = NULL; ErlNifBinary key, iv, aad, in, tag; AES_KEY aes_key; unsigned char *outp; - ERL_NIF_TERM out; - - if (!enif_inspect_iolist_as_binary(env, argv[1], &key) - || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0 - || !enif_inspect_binary(env, argv[2], &iv) || iv.size == 0 - || !enif_inspect_iolist_as_binary(env, argv[3], &aad) - || !enif_inspect_iolist_as_binary(env, argv[4], &in) - || !enif_inspect_iolist_as_binary(env, argv[5], &tag)) { - return enif_make_badarg(env); - } + ERL_NIF_TERM out, ret; - if (!(ctx = CRYPTO_gcm128_new(&aes_key, (block128_f)AES_encrypt))) - return atom_error; + if (argc != 6) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) + goto bad_arg; + if (key.size > INT_MAX / 8) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &iv)) + goto bad_arg; + if (iv.size == 0) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[3], &aad)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[4], &in)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[5], &tag)) + goto bad_arg; + + /* NOTE: This function returns 0 on success unlike most OpenSSL functions */ + if (AES_set_encrypt_key(key.data, (int)key.size * 8, &aes_key) != 0) + goto bad_arg; + + if ((ctx = CRYPTO_gcm128_new(&aes_key, (block128_f)AES_encrypt)) == NULL) + goto err; CRYPTO_gcm128_setiv(ctx, iv.data, iv.size); - if (CRYPTO_gcm128_aad(ctx, aad.data, aad.size)) - goto out_err; + /* NOTE: This function returns 0 on success unlike most OpenSSL functions */ + if (CRYPTO_gcm128_aad(ctx, aad.data, aad.size) != 0) + goto err; - outp = enif_make_new_binary(env, in.size, &out); + if ((outp = enif_make_new_binary(env, in.size, &out)) == NULL) + goto err; - /* decrypt */ - if (CRYPTO_gcm128_decrypt(ctx, in.data, outp, in.size)) - goto out_err; + /* NOTE: This function returns 0 on success unlike most OpenSSL functions */ + if (CRYPTO_gcm128_decrypt(ctx, in.data, outp, in.size) != 0) + goto err; /* calculate and check the tag */ - if (CRYPTO_gcm128_finish(ctx, tag.data, tag.size)) - goto out_err; + /* NOTE: This function returns 0 on success unlike most OpenSSL functions */ + if (CRYPTO_gcm128_finish(ctx, tag.data, tag.size) != 0) + goto err; - CRYPTO_gcm128_release(ctx); CONSUME_REDS(env, in); + ret = out; + goto done; - return out; + bad_arg: + ret = enif_make_badarg(env); + goto done; -out_err: - CRYPTO_gcm128_release(ctx); - return atom_error; + err: + ret = atom_error; + + done: + if (ctx) + CRYPTO_gcm128_release(ctx); + return ret; } #endif /* HAVE_GCM_EVP_DECRYPT_BUG */ -- cgit v1.2.3 From b80f8543e2e8c27550341d1c337076d7ce3e4290 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 00:17:21 -0800 Subject: Revamp crypto_alloc() --- lib/crypto/c_src/crypto_callback.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c index 0cc7dd609d..ae14e5768c 100644 --- a/lib/crypto/c_src/crypto_callback.c +++ b/lib/crypto/c_src/crypto_callback.c @@ -64,11 +64,16 @@ static void nomem(size_t size, const char* op) static void* crypto_alloc(size_t size CCB_FILE_LINE_ARGS) { - void *ret = enif_alloc(size); + void *ret; - if (!ret && size) - nomem(size, "allocate"); + if ((ret = enif_alloc(size)) == NULL) + goto err; return ret; + + err: + if (size) + nomem(size, "allocate"); + return NULL; } static void* crypto_realloc(void* ptr, size_t size CCB_FILE_LINE_ARGS) { -- cgit v1.2.3 From c1c98585b05f82a41d81aa24b20936be931a7082 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 00:20:15 -0800 Subject: Revamp crypto_realloc() --- lib/crypto/c_src/crypto_callback.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c index ae14e5768c..dda8b32deb 100644 --- a/lib/crypto/c_src/crypto_callback.c +++ b/lib/crypto/c_src/crypto_callback.c @@ -77,12 +77,18 @@ static void* crypto_alloc(size_t size CCB_FILE_LINE_ARGS) } static void* crypto_realloc(void* ptr, size_t size CCB_FILE_LINE_ARGS) { - void* ret = enif_realloc(ptr, size); + void* ret; - if (!ret && size) - nomem(size, "reallocate"); + if ((ret = enif_realloc(ptr, size)) == NULL) + goto err; return ret; + + err: + if (size) + nomem(size, "reallocate"); + return NULL; } + static void crypto_free(void* ptr CCB_FILE_LINE_ARGS) { enif_free(ptr); -- cgit v1.2.3 From a8382439ac61e942bd36c228e533864814f53666 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 00:24:10 -0800 Subject: Revamp get_crypto_callbacks() * Add sanity overflow check --- lib/crypto/c_src/crypto_callback.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c index dda8b32deb..ed5a1a6226 100644 --- a/lib/crypto/c_src/crypto_callback.c +++ b/lib/crypto/c_src/crypto_callback.c @@ -171,19 +171,26 @@ DLLEXPORT struct crypto_callbacks* get_crypto_callbacks(int nlocks) #ifdef OPENSSL_THREADS if (nlocks > 0) { int i; - lock_vec = enif_alloc(nlocks*sizeof(*lock_vec)); - if (lock_vec==NULL) return NULL; - memset(lock_vec, 0, nlocks*sizeof(*lock_vec)); - + + if ((size_t)nlocks > SIZE_MAX / sizeof(*lock_vec)) + goto err; + if ((lock_vec = enif_alloc((size_t)nlocks * sizeof(*lock_vec))) == NULL) + goto err; + + memset(lock_vec, 0, (size_t)nlocks * sizeof(*lock_vec)); + for (i=nlocks-1; i>=0; --i) { - lock_vec[i] = enif_rwlock_create("crypto_stat"); - if (lock_vec[i]==NULL) return NULL; + if ((lock_vec[i] = enif_rwlock_create("crypto_stat")) == NULL) + goto err; } } #endif is_initialized = 1; } return &the_struct; + + err: + return NULL; } #ifdef HAVE_DYNAMIC_CRYPTO_LIB -- cgit v1.2.3 From fba65fa791a44b5d0226bd150e8d9accab1e442a Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 00:39:03 -0800 Subject: Revamp ec_key_new() --- lib/crypto/c_src/ec.c | 290 +++++++++++++++++++++++++++----------------------- 1 file changed, 158 insertions(+), 132 deletions(-) diff --git a/lib/crypto/c_src/ec.c b/lib/crypto/c_src/ec.c index 6d831ec9d2..98d3007f13 100644 --- a/lib/crypto/c_src/ec.c +++ b/lib/crypto/c_src/ec.c @@ -50,157 +50,183 @@ static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg) BIGNUM *cofactor = NULL; EC_GROUP *group = NULL; EC_POINT *point = NULL; + int f_arity = -1; + const ERL_NIF_TERM *field; + int p_arity = -1; + const ERL_NIF_TERM *prime; + long field_bits; /* {Field, Prime, Point, Order, CoFactor} = Curve */ - if (enif_get_tuple(env,curve_arg,&c_arity,&curve) - && c_arity == 5 - && get_bn_from_bin(env, curve[3], &bn_order) - && (curve[4] != atom_none && get_bn_from_bin(env, curve[4], &cofactor))) { - - int f_arity = -1; - const ERL_NIF_TERM* field; - int p_arity = -1; - const ERL_NIF_TERM* prime; - - long field_bits; - - /* {A, B, Seed} = Prime */ - if (!enif_get_tuple(env,curve[1],&p_arity,&prime) - || !get_bn_from_bin(env, prime[0], &a) - || !get_bn_from_bin(env, prime[1], &b)) - goto out_err; - - if (!enif_get_tuple(env,curve[0],&f_arity,&field)) - goto out_err; - - if (f_arity == 2 && field[0] == atom_prime_field) { - /* {prime_field, Prime} */ - - if (!get_bn_from_bin(env, field[1], &p)) - goto out_err; - - if (BN_is_negative(p) || BN_is_zero(p)) - goto out_err; - - field_bits = BN_num_bits(p); - if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) - goto out_err; - - /* create the EC_GROUP structure */ - group = EC_GROUP_new_curve_GFp(p, a, b, NULL); + if (!enif_get_tuple(env, curve_arg, &c_arity, &curve)) + goto err; + if (c_arity != 5) + goto err; + if (!get_bn_from_bin(env, curve[3], &bn_order)) + goto err; + if (curve[4] != atom_none) { + if (!get_bn_from_bin(env, curve[4], &cofactor)) + goto err; + } - } else if (f_arity == 3 && field[0] == atom_characteristic_two_field) { + /* {A, B, Seed} = Prime */ + if (!enif_get_tuple(env, curve[1], &p_arity, &prime)) + goto err; + if (!get_bn_from_bin(env, prime[0], &a)) + goto err; + if (!get_bn_from_bin(env, prime[1], &b)) + goto err; + + if (!enif_get_tuple(env, curve[0], &f_arity, &field)) + goto err; + + if (f_arity == 2 && field[0] == atom_prime_field) { + /* {prime_field, Prime} */ + if (!get_bn_from_bin(env, field[1], &p)) + goto err; + if (BN_is_negative(p)) + goto err; + if (BN_is_zero(p)) + goto err; + + field_bits = BN_num_bits(p); + if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) + goto err; + + /* create the EC_GROUP structure */ + if ((group = EC_GROUP_new_curve_GFp(p, a, b, NULL)) == NULL) + goto err; + + } else if (f_arity == 3 && field[0] == atom_characteristic_two_field) { #if defined(OPENSSL_NO_EC2M) - enif_raise_exception(env, atom_notsup); - goto out_err; + enif_raise_exception(env, atom_notsup); + goto out_err; #else - /* {characteristic_two_field, M, Basis} */ - - int b_arity = -1; - const ERL_NIF_TERM* basis; - unsigned int k1, k2, k3; - - if ((p = BN_new()) == NULL) - goto out_err; - - if (!enif_get_long(env, field[1], &field_bits) - || field_bits > OPENSSL_ECC_MAX_FIELD_BITS) - goto out_err; - - if (enif_get_tuple(env,field[2],&b_arity,&basis)) { - if (b_arity == 2 - && basis[0] == atom_tpbasis - && enif_get_uint(env, basis[1], &k1)) { - /* {tpbasis, k} = Basis */ - - if (!(field_bits > k1 && k1 > 0)) - goto out_err; - - /* create the polynomial */ - if (!BN_set_bit(p, (int)field_bits) - || !BN_set_bit(p, (int)k1) - || !BN_set_bit(p, 0)) - goto out_err; - - } else if (b_arity == 4 - && basis[0] == atom_ppbasis - && enif_get_uint(env, basis[1], &k1) - && enif_get_uint(env, basis[2], &k2) - && enif_get_uint(env, basis[3], &k3)) { - /* {ppbasis, k1, k2, k3} = Basis */ - - if (!(field_bits > k3 && k3 > k2 && k2 > k1 && k1 > 0)) - goto out_err; - - /* create the polynomial */ - if (!BN_set_bit(p, (int)field_bits) - || !BN_set_bit(p, (int)k1) - || !BN_set_bit(p, (int)k2) - || !BN_set_bit(p, (int)k3) - || !BN_set_bit(p, 0)) - goto out_err; - - } else - goto out_err; - } else if (field[2] == atom_onbasis) { - /* onbasis = Basis */ - /* no parameters */ - goto out_err; - - } else - goto out_err; - - group = EC_GROUP_new_curve_GF2m(p, a, b, NULL); + /* {characteristic_two_field, M, Basis} */ + int b_arity = -1; + const ERL_NIF_TERM* basis; + + if ((p = BN_new()) == NULL) + goto err; + if (!enif_get_long(env, field[1], &field_bits)) + goto err; + if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS || field_bits > INT_MAX) + goto err; + + if (enif_get_tuple(env, field[2], &b_arity, &basis)) { + if (b_arity == 2) { + unsigned int k1; + + if (basis[0] != atom_tpbasis) + goto err; + if (!enif_get_uint(env, basis[1], &k1)) + goto err; + + /* {tpbasis, k} = Basis */ + if (field_bits <= k1 || k1 == 0 || k1 > INT_MAX) + goto err; + + /* create the polynomial */ + if (!BN_set_bit(p, (int)field_bits)) + goto err; + if (!BN_set_bit(p, (int)k1)) + goto err; + if (!BN_set_bit(p, 0)) + goto err; + + } else if (b_arity == 4) { + unsigned int k1, k2, k3; + + if (basis[0] != atom_ppbasis) + goto err; + if (!enif_get_uint(env, basis[1], &k1)) + goto err; + if (!enif_get_uint(env, basis[2], &k2)) + goto err; + if (!enif_get_uint(env, basis[3], &k3)) + goto err; + + /* {ppbasis, k1, k2, k3} = Basis */ + if (field_bits <= k3 || k3 <= k2 || k2 <= k1 || k1 == 0 || k3 > INT_MAX || k2 > INT_MAX || k1 > INT_MAX) + goto err; + + /* create the polynomial */ + if (!BN_set_bit(p, (int)field_bits)) + goto err; + if (!BN_set_bit(p, (int)k1)) + goto err; + if (!BN_set_bit(p, (int)k2)) + goto err; + if (!BN_set_bit(p, (int)k3)) + goto err; + if (!BN_set_bit(p, 0)) + goto err; + + } else + goto err; + } else if (field[2] == atom_onbasis) { + /* onbasis = Basis */ + /* no parameters */ + goto err; + + } else + goto err; + + if ((group = EC_GROUP_new_curve_GF2m(p, a, b, NULL)) == NULL) + goto err; #endif - } else - goto out_err; - - if (!group) - goto out_err; + } else + goto err; - if (enif_inspect_binary(env, prime[2], &seed)) { - EC_GROUP_set_seed(group, seed.data, seed.size); - } + if (enif_inspect_binary(env, prime[2], &seed)) { + if (!EC_GROUP_set_seed(group, seed.data, seed.size)) + goto err; + } - if (!term2point(env, curve[2], group, &point)) - goto out_err; + if (!term2point(env, curve[2], group, &point)) + goto err; - if (BN_is_negative(bn_order) - || BN_is_zero(bn_order) - || BN_num_bits(bn_order) > (int)field_bits + 1) - goto out_err; + if (BN_is_negative(bn_order)) + goto err; + if (BN_is_zero(bn_order)) + goto err; + if (BN_num_bits(bn_order) > (int)field_bits + 1) + goto err; - if (!EC_GROUP_set_generator(group, point, bn_order, cofactor)) - goto out_err; + if (!EC_GROUP_set_generator(group, point, bn_order, cofactor)) + goto err; - EC_GROUP_set_asn1_flag(group, 0x0); + EC_GROUP_set_asn1_flag(group, 0x0); - key = EC_KEY_new(); - if (!key) - goto out_err; - EC_KEY_set_group(key, group); - } - else { - goto out_err; - } + if ((key = EC_KEY_new()) == NULL) + goto err; + if (!EC_KEY_set_group(key, group)) + goto err; - goto out; + goto done; -out_err: - if (key) EC_KEY_free(key); + err: + if (key) + EC_KEY_free(key); key = NULL; -out: + done: /* some OpenSSL structures are mem-dup'ed into the key, so we have to free our copies here */ - if (p) BN_free(p); - if (a) BN_free(a); - if (b) BN_free(b); - if (bn_order) BN_free(bn_order); - if (cofactor) BN_free(cofactor); - if (group) EC_GROUP_free(group); - if (point) EC_POINT_free(point); + if (bn_order) + BN_free(bn_order); + if (cofactor) + BN_free(cofactor); + if (a) + BN_free(a); + if (b) + BN_free(b); + if (p) + BN_free(p); + if (group) + EC_GROUP_free(group); + if (point) + EC_POINT_free(point); return key; } -- cgit v1.2.3 From 9b0739fd44adfc1a7d5b5b5f26df883cca8b9c41 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 00:39:19 -0800 Subject: Revamp point2term() --- lib/crypto/c_src/ec.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/lib/crypto/c_src/ec.c b/lib/crypto/c_src/ec.c index 98d3007f13..51da577cd0 100644 --- a/lib/crypto/c_src/ec.c +++ b/lib/crypto/c_src/ec.c @@ -236,22 +236,34 @@ static ERL_NIF_TERM point2term(ErlNifEnv* env, const EC_POINT *point, point_conversion_form_t form) { - unsigned dlen; + ERL_NIF_TERM ret; + size_t dlen; ErlNifBinary bin; + int bin_alloc = 0; - dlen = EC_POINT_point2oct(group, point, form, NULL, 0, NULL); - if (dlen == 0) + if ((dlen = EC_POINT_point2oct(group, point, form, NULL, 0, NULL)) == 0) return atom_undefined; if (!enif_alloc_binary(dlen, &bin)) - return enif_make_badarg(env); + goto err; + bin_alloc = 1; + + if (!EC_POINT_point2oct(group, point, form, bin.data, bin.size, NULL)) + goto err; - if (!EC_POINT_point2oct(group, point, form, bin.data, bin.size, NULL)) { - enif_release_binary(&bin); - return enif_make_badarg(env); - } ERL_VALGRIND_MAKE_MEM_DEFINED(bin.data, bin.size); - return enif_make_binary(env, &bin); + + ret = enif_make_binary(env, &bin); + bin_alloc = 0; + goto done; + + err: + if (bin_alloc) + enif_release_binary(&bin); + ret = enif_make_badarg(env); + + done: + return ret; } int term2point(ErlNifEnv* env, ERL_NIF_TERM term, EC_GROUP *group, EC_POINT **pptr) -- cgit v1.2.3 From e4ecb3fd94ebae8eac89dbfb9376d78a5ac9a508 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 00:46:08 -0800 Subject: Revamp term2point() * Only set pptr on success --- lib/crypto/c_src/ec.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/crypto/c_src/ec.c b/lib/crypto/c_src/ec.c index 51da577cd0..4fb9229edb 100644 --- a/lib/crypto/c_src/ec.c +++ b/lib/crypto/c_src/ec.c @@ -268,29 +268,29 @@ static ERL_NIF_TERM point2term(ErlNifEnv* env, int term2point(ErlNifEnv* env, ERL_NIF_TERM term, EC_GROUP *group, EC_POINT **pptr) { - int ret = 0; ErlNifBinary bin; - EC_POINT *point; + EC_POINT *point = NULL; - if (!enif_inspect_binary(env,term,&bin)) { - return 0; - } + if (!enif_inspect_binary(env, term, &bin)) + goto err; - if ((*pptr = point = EC_POINT_new(group)) == NULL) { - return 0; - } + if ((point = EC_POINT_new(group)) == NULL) + goto err; /* set the point conversion form */ EC_GROUP_set_point_conversion_form(group, (point_conversion_form_t)(bin.data[0] & ~0x01)); /* extract the ec point */ - if (!EC_POINT_oct2point(group, point, bin.data, bin.size, NULL)) { - EC_POINT_free(point); - *pptr = NULL; - } else - ret = 1; + if (!EC_POINT_oct2point(group, point, bin.data, bin.size, NULL)) + goto err; - return ret; + *pptr = point; + return 1; + + err: + if (point) + EC_POINT_free(point); + return 0; } int get_ec_key(ErlNifEnv* env, -- cgit v1.2.3 From 3838f0a85cb0fd299dd2460673b64cd4e319b387 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 00:50:27 -0800 Subject: Revamp get_ec_key() --- lib/crypto/c_src/ec.c | 86 +++++++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 40 deletions(-) diff --git a/lib/crypto/c_src/ec.c b/lib/crypto/c_src/ec.c index 4fb9229edb..78bdee318c 100644 --- a/lib/crypto/c_src/ec.c +++ b/lib/crypto/c_src/ec.c @@ -302,58 +302,64 @@ int get_ec_key(ErlNifEnv* env, EC_POINT *pub_key = NULL; EC_GROUP *group = NULL; - if (!(priv == atom_undefined || get_bn_from_bin(env, priv, &priv_key)) - || !(pub == atom_undefined || enif_is_binary(env, pub))) { - goto out_err; + if (priv != atom_undefined) { + if (!get_bn_from_bin(env, priv, &priv_key)) + goto err; } - - key = ec_key_new(env, curve); - - if (!key) { - goto out_err; + if (pub != atom_undefined) { + if (!enif_is_binary(env, pub)) + goto err; } - if (!group) - group = EC_GROUP_dup(EC_KEY_get0_group(key)); + if ((key = ec_key_new(env, curve)) == NULL) + goto err; + + if ((group = EC_GROUP_dup(EC_KEY_get0_group(key))) == NULL) + goto err; if (term2point(env, pub, group, &pub_key)) { - if (!EC_KEY_set_public_key(key, pub_key)) { - goto out_err; - } - } - if (priv != atom_undefined - && !BN_is_zero(priv_key)) { - if (!EC_KEY_set_private_key(key, priv_key)) - goto out_err; - - /* calculate public key (if necessary) */ - if (EC_KEY_get0_public_key(key) == NULL) - { - /* the public key was not included in the SEC1 private - * key => calculate the public key */ - pub_key = EC_POINT_new(group); - if (pub_key == NULL - || !EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group)) - || !EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL) - || !EC_KEY_set_public_key(key, pub_key)) - goto out_err; - } + if (!EC_KEY_set_public_key(key, pub_key)) + goto err; } - goto out; + if (priv != atom_undefined && !BN_is_zero(priv_key)) { + if (!EC_KEY_set_private_key(key, priv_key)) + goto err; -out_err: - if (key) EC_KEY_free(key); + /* calculate public key (if necessary) */ + if (EC_KEY_get0_public_key(key) == NULL) { + /* the public key was not included in the SEC1 private + * key => calculate the public key */ + if ((pub_key = EC_POINT_new(group)) == NULL) + goto err; + if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) + goto err; + if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) + goto err; + if (!EC_KEY_set_public_key(key, pub_key)) + goto err; + } + } + goto done; + + err: + if (key) + EC_KEY_free(key); key = NULL; -out: + done: /* some OpenSSL structures are mem-dup'ed into the key, so we have to free our copies here */ - if (priv_key) BN_clear_free(priv_key); - if (pub_key) EC_POINT_free(pub_key); - if (group) EC_GROUP_free(group); - if (!key) - return 0; + if (priv_key) + BN_clear_free(priv_key); + if (group) + EC_GROUP_free(group); + if (pub_key) + EC_POINT_free(pub_key); + + if (key == NULL) + return 0; + *res = key; return 1; } -- cgit v1.2.3 From a2e0b92ca13984a89f261aa1e10820252e505e84 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 18:45:58 -0800 Subject: Revamp ec_key_generate --- lib/crypto/c_src/ec.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/lib/crypto/c_src/ec.c b/lib/crypto/c_src/ec.c index 78bdee318c..6da262e6a5 100644 --- a/lib/crypto/c_src/ec.c +++ b/lib/crypto/c_src/ec.c @@ -373,31 +373,41 @@ ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] const EC_GROUP *group; const EC_POINT *public_key; ERL_NIF_TERM priv_key; - ERL_NIF_TERM pub_key = atom_undefined; + ERL_NIF_TERM pub_key; + ERL_NIF_TERM ret; if (!get_ec_key(env, argv[0], argv[1], atom_undefined, &key)) - goto badarg; + goto bad_arg; if (argv[1] == atom_undefined) { if (!EC_KEY_generate_key(key)) - goto badarg; + goto err; } group = EC_KEY_get0_group(key); public_key = EC_KEY_get0_public_key(key); - if (group && public_key) { - pub_key = point2term(env, group, public_key, - EC_KEY_get_conv_form(key)); + if (group == NULL || public_key == NULL) { + pub_key = atom_undefined; + + } else { + pub_key = point2term(env, group, public_key, + EC_KEY_get_conv_form(key)); } + priv_key = bn2term(env, EC_KEY_get0_private_key(key)); - EC_KEY_free(key); - return enif_make_tuple2(env, pub_key, priv_key); + ret = enif_make_tuple2(env, pub_key, priv_key); + goto done; -badarg: + err: + bad_arg: + ret = make_badarg_maybe(env); + + done: if (key) - EC_KEY_free(key); - return make_badarg_maybe(env); + EC_KEY_free(key); + return ret; + #else return atom_notsup; #endif -- cgit v1.2.3 From 1c540d41740945322f3aaf7b0ee66dda09d258f2 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 18:46:53 -0800 Subject: Revamp dh_generate_key_nif() --- lib/crypto/c_src/dh.c | 244 +++++++++++++++++++++++++++++--------------------- 1 file changed, 143 insertions(+), 101 deletions(-) diff --git a/lib/crypto/c_src/dh.c b/lib/crypto/c_src/dh.c index 0c18ad7a3f..10fd122658 100644 --- a/lib/crypto/c_src/dh.c +++ b/lib/crypto/c_src/dh.c @@ -24,122 +24,164 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (PrivKey|undefined, DHParams=[P,G], Mpint, Len|0) */ DH *dh_params = NULL; - int mpint; /* 0 or 4 */ + unsigned int mpint; /* 0 or 4 */ + ERL_NIF_TERM head, tail; + BIGNUM *dh_p = NULL; + BIGNUM *dh_g = NULL; + BIGNUM *priv_key_in = NULL; + unsigned long len = 0; + unsigned char *pub_ptr, *prv_ptr; + int pub_len, prv_len; + ERL_NIF_TERM ret_pub, ret_prv, ret; + const BIGNUM *pub_key_gen, *priv_key_gen; +#ifdef HAS_EVP_PKEY_CTX + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *dhkey = NULL, *params = NULL; +#endif - { - ERL_NIF_TERM head, tail; - BIGNUM - *dh_p = NULL, - *dh_g = NULL, - *priv_key_in = NULL; - unsigned long - len = 0; - - if (!(get_bn_from_bin(env, argv[0], &priv_key_in) - || argv[0] == atom_undefined) - || !enif_get_list_cell(env, argv[1], &head, &tail) - || !get_bn_from_bin(env, head, &dh_p) - || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &dh_g) - || !enif_is_empty_list(env, tail) - || !enif_get_int(env, argv[2], &mpint) || (mpint & ~4) - || !enif_get_ulong(env, argv[3], &len) - - /* Load dh_params with values to use by the generator. - Mem mgmnt transfered from dh_p etc to dh_params */ - || !(dh_params = DH_new()) - || (priv_key_in && !DH_set0_key(dh_params, NULL, priv_key_in)) - || !DH_set0_pqg(dh_params, dh_p, NULL, dh_g) - ) { - if (priv_key_in) BN_free(priv_key_in); - if (dh_p) BN_free(dh_p); - if (dh_g) BN_free(dh_g); - if (dh_params) DH_free(dh_params); - return enif_make_badarg(env); - } + if (argc != 4) + goto bad_arg; - if (len) { - if (len < BN_num_bits(dh_p)) - DH_set_length(dh_params, len); - else { - if (priv_key_in) BN_free(priv_key_in); - if (dh_p) BN_free(dh_p); - if (dh_g) BN_free(dh_g); - if (dh_params) DH_free(dh_params); - return enif_make_badarg(env); - } - } + if (argv[0] != atom_undefined) { + if (!get_bn_from_bin(env, argv[0], &priv_key_in)) + goto bad_arg; + } + if (!enif_get_list_cell(env, argv[1], &head, &tail)) + goto bad_arg; + if (!get_bn_from_bin(env, head, &dh_p)) + goto bad_arg; + + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto bad_arg; + if (!get_bn_from_bin(env, head, &dh_g)) + goto bad_arg; + + if (!enif_is_empty_list(env, tail)) + goto bad_arg; + + if (!enif_get_uint(env, argv[2], &mpint)) + goto bad_arg; + if (mpint != 0 && mpint != 4) + goto bad_arg; + + if (!enif_get_ulong(env, argv[3], &len)) + goto bad_arg; + if (len > LONG_MAX) + goto bad_arg; + + /* Load dh_params with values to use by the generator. + Mem mgmnt transfered from dh_p etc to dh_params */ + if ((dh_params = DH_new()) == NULL) + goto err; + if (priv_key_in) { + if (!DH_set0_key(dh_params, NULL, priv_key_in)) + goto err; + /* On success, dh_params owns priv_key_in */ + priv_key_in = NULL; + } + if (!DH_set0_pqg(dh_params, dh_p, NULL, dh_g)) + goto err; + /* On success, dh_params owns dh_p and dh_g */ + dh_p = NULL; + dh_g = NULL; + + if (len) { + int bn_len; + + if ((bn_len = BN_num_bits(dh_p)) < 0) + goto bad_arg; + if (len >= (size_t)bn_len) + goto bad_arg; + + if (!DH_set_length(dh_params, (long)len)) + goto err; } #ifdef HAS_EVP_PKEY_CTX - { - EVP_PKEY_CTX *ctx; - EVP_PKEY *dhkey, *params; - int success; + if ((params = EVP_PKEY_new()) == NULL) + goto err; - params = EVP_PKEY_new(); - success = EVP_PKEY_set1_DH(params, dh_params); /* set the key referenced by params to dh_params... */ - DH_free(dh_params); /* ...dh_params (and params) must be freed */ - if (!success) return atom_error; + /* set the key referenced by params to dh_params... */ + if (EVP_PKEY_set1_DH(params, dh_params) != 1) + goto err; - ctx = EVP_PKEY_CTX_new(params, NULL); - EVP_PKEY_free(params); - if (!ctx) { - return atom_error; - } + if ((ctx = EVP_PKEY_CTX_new(params, NULL)) == NULL) + goto err; - if (!EVP_PKEY_keygen_init(ctx)) { - /* EVP_PKEY_CTX_free(ctx); */ - return atom_error; - } + if (EVP_PKEY_keygen_init(ctx) != 1) + goto err; - dhkey = EVP_PKEY_new(); - if (!EVP_PKEY_keygen(ctx, &dhkey)) { /* "performs a key generation operation, the ... */ - /*... generated key is written to ppkey." (=last arg) */ - /* EVP_PKEY_CTX_free(ctx); */ - /* EVP_PKEY_free(dhkey); */ - return atom_error; - } + if ((dhkey = EVP_PKEY_new()) == NULL) + goto err; + + /* key gen op, key written to ppkey (=last arg) */ + if (EVP_PKEY_keygen(ctx, &dhkey) != 1) + goto err; + + DH_free(dh_params); + if ((dh_params = EVP_PKEY_get1_DH(dhkey)) == NULL) + goto err; - dh_params = EVP_PKEY_get1_DH(dhkey); /* return the referenced key. dh_params and dhkey must be freed */ - EVP_PKEY_free(dhkey); - if (!dh_params) { - /* EVP_PKEY_CTX_free(ctx); */ - return atom_error; - } - EVP_PKEY_CTX_free(ctx); - } #else - if (!DH_generate_key(dh_params)) return atom_error; + if (!DH_generate_key(dh_params)) + goto err; #endif - { - unsigned char *pub_ptr, *prv_ptr; - int pub_len, prv_len; - ERL_NIF_TERM ret_pub, ret_prv; - const BIGNUM *pub_key_gen, *priv_key_gen; - - DH_get0_key(dh_params, - &pub_key_gen, &priv_key_gen); /* Get pub_key_gen and priv_key_gen. - "The values point to the internal representation of - the public key and private key values. This memory - should not be freed directly." says man */ - pub_len = BN_num_bytes(pub_key_gen); - prv_len = BN_num_bytes(priv_key_gen); - pub_ptr = enif_make_new_binary(env, pub_len+mpint, &ret_pub); - prv_ptr = enif_make_new_binary(env, prv_len+mpint, &ret_prv); - if (mpint) { - put_int32(pub_ptr, pub_len); pub_ptr += 4; - put_int32(prv_ptr, prv_len); prv_ptr += 4; - } - BN_bn2bin(pub_key_gen, pub_ptr); - BN_bn2bin(priv_key_gen, prv_ptr); - ERL_VALGRIND_MAKE_MEM_DEFINED(pub_ptr, pub_len); - ERL_VALGRIND_MAKE_MEM_DEFINED(prv_ptr, prv_len); - DH_free(dh_params); + DH_get0_key(dh_params, &pub_key_gen, &priv_key_gen); + + if ((pub_len = BN_num_bytes(pub_key_gen)) < 0) + goto err; + if ((prv_len = BN_num_bytes(priv_key_gen)) < 0) + goto err; - return enif_make_tuple2(env, ret_pub, ret_prv); + if ((pub_ptr = enif_make_new_binary(env, (size_t)pub_len+mpint, &ret_pub)) == NULL) + goto err; + if ((prv_ptr = enif_make_new_binary(env, (size_t)prv_len+mpint, &ret_prv)) == NULL) + goto err; + + if (mpint) { + put_int32(pub_ptr, pub_len); + pub_ptr += 4; + + put_int32(prv_ptr, prv_len); + prv_ptr += 4; } + + if (BN_bn2bin(pub_key_gen, pub_ptr) < 0) + goto err; + if (BN_bn2bin(priv_key_gen, prv_ptr) < 0) + goto err; + + ERL_VALGRIND_MAKE_MEM_DEFINED(pub_ptr, pub_len); + ERL_VALGRIND_MAKE_MEM_DEFINED(prv_ptr, prv_len); + + ret = enif_make_tuple2(env, ret_pub, ret_prv); + goto done; + + bad_arg: + err: + ret = enif_make_badarg(env); + + done: + if (priv_key_in) + BN_free(priv_key_in); + if (dh_p) + BN_free(dh_p); + if (dh_g) + BN_free(dh_g); + if (dh_params) + DH_free(dh_params); + +#ifdef HAS_EVP_PKEY_CTX + if (ctx) + EVP_PKEY_CTX_free(ctx); + if (dhkey) + EVP_PKEY_free(dhkey); + if (params) + EVP_PKEY_free(params); +#endif + + return ret; } ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From cfd08eb130fe9cdadd3d291526f761359b84bd1e Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 18:47:16 -0800 Subject: Revamp dh_compute_key_nif() --- lib/crypto/c_src/dh.c | 134 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 89 insertions(+), 45 deletions(-) diff --git a/lib/crypto/c_src/dh.c b/lib/crypto/c_src/dh.c index 10fd122658..e3b5b11e9c 100644 --- a/lib/crypto/c_src/dh.c +++ b/lib/crypto/c_src/dh.c @@ -186,61 +186,105 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (OthersPublicKey, MyPrivateKey, DHParams=[P,G]) */ - BIGNUM *other_pub_key = NULL, - *dh_p = NULL, - *dh_g = NULL; - DH *dh_priv = DH_new(); + BIGNUM *other_pub_key = NULL; + BIGNUM *dh_p = NULL; + BIGNUM *dh_g = NULL; + BIGNUM *dummy_pub_key = NULL; + BIGNUM *priv_key = NULL; + DH *dh_priv = NULL; + ERL_NIF_TERM head, tail, ret; + ErlNifBinary ret_bin; + int size; + int ret_bin_alloc = 0; + int dh_size; /* Check the arguments and get my private key (dh_priv), the peer's public key (other_pub_key), the parameters p & q */ + if (argc != 3) + goto bad_arg; + + if (!get_bn_from_bin(env, argv[0], &other_pub_key)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[1], &priv_key)) + goto bad_arg; + + if (!enif_get_list_cell(env, argv[2], &head, &tail)) + goto bad_arg; + if (!get_bn_from_bin(env, head, &dh_p)) + goto bad_arg; + + if (!enif_get_list_cell(env, tail, &head, &tail)) + goto bad_arg; + if (!get_bn_from_bin(env, head, &dh_g)) + goto bad_arg; + + if (!enif_is_empty_list(env, tail)) + goto bad_arg; - { - BIGNUM *dummy_pub_key = NULL, - *priv_key = NULL; - ERL_NIF_TERM head, tail; - - if (!get_bn_from_bin(env, argv[0], &other_pub_key) - || !get_bn_from_bin(env, argv[1], &priv_key) - || !enif_get_list_cell(env, argv[2], &head, &tail) - || !get_bn_from_bin(env, head, &dh_p) - || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_bin(env, head, &dh_g) - || !enif_is_empty_list(env, tail) - - /* Note: DH_set0_key() does not allow setting only the - * private key, although DH_compute_key() does not use the - * public key. Work around this limitation by setting - * the public key to a copy of the private key. - */ - || !(dummy_pub_key = BN_dup(priv_key)) - || !DH_set0_key(dh_priv, dummy_pub_key, priv_key) - || !DH_set0_pqg(dh_priv, dh_p, NULL, dh_g) - ) { - if (dh_p) BN_free(dh_p); - if (dh_g) BN_free(dh_g); - if (other_pub_key) BN_free(other_pub_key); - if (dummy_pub_key) BN_free(dummy_pub_key); - if (priv_key) BN_free(priv_key); - return enif_make_badarg(env); - } + /* Note: DH_set0_key() does not allow setting only the + * private key, although DH_compute_key() does not use the + * public key. Work around this limitation by setting + * the public key to a copy of the private key. + */ + if ((dummy_pub_key = BN_dup(priv_key)) == NULL) + goto err; + if ((dh_priv = DH_new()) == NULL) + goto err; + + if (!DH_set0_key(dh_priv, dummy_pub_key, priv_key)) + goto err; + /* 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; + /* 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; + if (!enif_alloc_binary((size_t)dh_size, &ret_bin)) + goto err; + ret_bin_alloc = 1; + + if ((size = DH_compute_key(ret_bin.data, other_pub_key, dh_priv)) < 0) + goto err; + if (size == 0) + goto err; + + if ((size_t)size != ret_bin.size) { + if (!enif_realloc_binary(&ret_bin, (size_t)size)) + goto err; } - { - ErlNifBinary ret_bin; - int size; - enif_alloc_binary(DH_size(dh_priv), &ret_bin); - size = DH_compute_key(ret_bin.data, other_pub_key, dh_priv); + 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); + if (priv_key) + BN_free(priv_key); + if (dh_p) + BN_free(dh_p); + if (dh_g) + BN_free(dh_g); + if (dummy_pub_key) + BN_free(dummy_pub_key); + if (dh_priv) DH_free(dh_priv); - if (size<=0) { - enif_release_binary(&ret_bin); - return atom_error; - } - if (size != ret_bin.size) enif_realloc_binary(&ret_bin, size); - return enif_make_binary(env, &ret_bin); - } + return ret; } -- cgit v1.2.3 From 9b1a6e47ce5989eac129100280279f50ccef6b46 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 01:20:09 -0800 Subject: Revamp algorithms() * Switch from signed to unsigned int since the Erlang call uses unsigned anyway. --- lib/crypto/c_src/algorithms.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/lib/crypto/c_src/algorithms.c b/lib/crypto/c_src/algorithms.c index a6e61cc9b2..6318c8ad5a 100644 --- a/lib/crypto/c_src/algorithms.c +++ b/lib/crypto/c_src/algorithms.c @@ -20,17 +20,17 @@ #include "algorithms.h" -static int algo_hash_cnt, algo_hash_fips_cnt; +static unsigned int algo_hash_cnt, algo_hash_fips_cnt; static ERL_NIF_TERM algo_hash[12]; /* increase when extending the list */ -static int algo_pubkey_cnt, algo_pubkey_fips_cnt; +static unsigned int algo_pubkey_cnt, algo_pubkey_fips_cnt; static ERL_NIF_TERM algo_pubkey[12]; /* increase when extending the list */ -static int algo_cipher_cnt, algo_cipher_fips_cnt; +static unsigned int algo_cipher_cnt, algo_cipher_fips_cnt; static ERL_NIF_TERM algo_cipher[25]; /* increase when extending the list */ -static int algo_mac_cnt, algo_mac_fips_cnt; +static unsigned int algo_mac_cnt, algo_mac_fips_cnt; static ERL_NIF_TERM algo_mac[3]; /* increase when extending the list */ -static int algo_curve_cnt, algo_curve_fips_cnt; +static unsigned int algo_curve_cnt, algo_curve_fips_cnt; static ERL_NIF_TERM algo_curve[89]; /* increase when extending the list */ -static int algo_rsa_opts_cnt, algo_rsa_opts_fips_cnt; +static unsigned int algo_rsa_opts_cnt, algo_rsa_opts_fips_cnt; static ERL_NIF_TERM algo_rsa_opts[11]; /* increase when extending the list */ void init_algorithms_types(ErlNifEnv* env) @@ -295,19 +295,20 @@ ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { #ifdef FIPS_SUPPORT int fips_mode = FIPS_mode(); - int hash_cnt = fips_mode ? algo_hash_fips_cnt : algo_hash_cnt; - int pubkey_cnt = fips_mode ? algo_pubkey_fips_cnt : algo_pubkey_cnt; - int cipher_cnt = fips_mode ? algo_cipher_fips_cnt : algo_cipher_cnt; - int mac_cnt = fips_mode ? algo_mac_fips_cnt : algo_mac_cnt; - int curve_cnt = fips_mode ? algo_curve_fips_cnt : algo_curve_cnt; - int rsa_opts_cnt = fips_mode ? algo_rsa_opts_fips_cnt : algo_rsa_opts_cnt; + + unsigned int hash_cnt = fips_mode ? algo_hash_fips_cnt : algo_hash_cnt; + unsigned int pubkey_cnt = fips_mode ? algo_pubkey_fips_cnt : algo_pubkey_cnt; + unsigned int cipher_cnt = fips_mode ? algo_cipher_fips_cnt : algo_cipher_cnt; + unsigned int mac_cnt = fips_mode ? algo_mac_fips_cnt : algo_mac_cnt; + unsigned int curve_cnt = fips_mode ? algo_curve_fips_cnt : algo_curve_cnt; + unsigned int rsa_opts_cnt = fips_mode ? algo_rsa_opts_fips_cnt : algo_rsa_opts_cnt; #else - int hash_cnt = algo_hash_cnt; - int pubkey_cnt = algo_pubkey_cnt; - int cipher_cnt = algo_cipher_cnt; - int mac_cnt = algo_mac_cnt; - int curve_cnt = algo_curve_cnt; - int rsa_opts_cnt = algo_rsa_opts_cnt; + unsigned int hash_cnt = algo_hash_cnt; + unsigned int pubkey_cnt = algo_pubkey_cnt; + unsigned int cipher_cnt = algo_cipher_cnt; + unsigned int mac_cnt = algo_mac_cnt; + unsigned int curve_cnt = algo_curve_cnt; + unsigned int rsa_opts_cnt = algo_rsa_opts_cnt; #endif return enif_make_tuple6(env, enif_make_list_from_array(env, algo_hash, hash_cnt), -- cgit v1.2.3 From 83fc1366cfd005b3fb8ce18e40af83f5f6f2818f Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 01:22:37 -0800 Subject: Revamp evp_compat HMAC_CTX_new() * Add error handling for OpenSSL call. --- lib/crypto/c_src/evp_compat.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/crypto/c_src/evp_compat.h b/lib/crypto/c_src/evp_compat.h index 98c861c45e..c81d1e35ee 100644 --- a/lib/crypto/c_src/evp_compat.h +++ b/lib/crypto/c_src/evp_compat.h @@ -37,7 +37,11 @@ static INLINE void HMAC_CTX_free(HMAC_CTX *ctx); static INLINE HMAC_CTX *HMAC_CTX_new() { - HMAC_CTX *ctx = CRYPTO_malloc(sizeof(HMAC_CTX), __FILE__, __LINE__); + HMAC_CTX *ctx; + + if ((ctx = CRYPTO_malloc(sizeof(HMAC_CTX), __FILE__, __LINE__)) == NULL) + return NULL; + HMAC_CTX_init(ctx); return ctx; } -- cgit v1.2.3 From 142c109909e43606312885dad233fc1a74a547d4 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 01:23:26 -0800 Subject: Revamp evp_compat HMAC_CTX_free() * Allow for calling with NULL. --- lib/crypto/c_src/evp_compat.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/crypto/c_src/evp_compat.h b/lib/crypto/c_src/evp_compat.h index c81d1e35ee..e289ce5e76 100644 --- a/lib/crypto/c_src/evp_compat.h +++ b/lib/crypto/c_src/evp_compat.h @@ -48,6 +48,9 @@ static INLINE HMAC_CTX *HMAC_CTX_new() static INLINE void HMAC_CTX_free(HMAC_CTX *ctx) { + if (ctx == NULL) + return; + HMAC_CTX_cleanup(ctx); CRYPTO_free(ctx); } -- cgit v1.2.3 From 6c8560e288ef430ffa8d0baa567013a64f500e8e Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 01:24:04 -0800 Subject: Revamp EVP_MD_CTX_free() * Mention that these were renamed (and aliased) in 1.1.0. * Use extra paren around macro argument when expanding. --- lib/crypto/c_src/evp_compat.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/crypto/c_src/evp_compat.h b/lib/crypto/c_src/evp_compat.h index e289ce5e76..996985799a 100644 --- a/lib/crypto/c_src/evp_compat.h +++ b/lib/crypto/c_src/evp_compat.h @@ -55,8 +55,9 @@ static INLINE void HMAC_CTX_free(HMAC_CTX *ctx) CRYPTO_free(ctx); } +/* Renamed in 1.1.0 */ #define EVP_MD_CTX_new() EVP_MD_CTX_create() -#define EVP_MD_CTX_free(ctx) EVP_MD_CTX_destroy(ctx) +#define EVP_MD_CTX_free(ctx) EVP_MD_CTX_destroy((ctx)) static INLINE void *BN_GENCB_get_arg(BN_GENCB *cb); -- cgit v1.2.3 From cee4b0518cb4a543e419c62d1b83bee7ae14f1af Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 01:25:54 -0800 Subject: Revamp DSA_get0_pqg() * Whitespace --- lib/crypto/c_src/evp_compat.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/crypto/c_src/evp_compat.h b/lib/crypto/c_src/evp_compat.h index 996985799a..7ad9fb95d2 100644 --- a/lib/crypto/c_src/evp_compat.h +++ b/lib/crypto/c_src/evp_compat.h @@ -149,8 +149,11 @@ DSA_get0_pqg(const DSA *dsa, const BIGNUM **p, const BIGNUM **q, const BIGNUM ** static INLINE void DSA_get0_key(const DSA *dsa, const BIGNUM **pub_key, const BIGNUM **priv_key) { - if (pub_key) *pub_key = dsa->pub_key; - if (priv_key) *priv_key = dsa->priv_key; + if (pub_key) + *pub_key = dsa->pub_key; + + if (priv_key) + *priv_key = dsa->priv_key; } -- cgit v1.2.3 From b4b8f69a507770b7a0031c79d01bd58cc27763ef Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 01:26:22 -0800 Subject: Revamp DH_get0_key() * Whitespace --- lib/crypto/c_src/evp_compat.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/crypto/c_src/evp_compat.h b/lib/crypto/c_src/evp_compat.h index 7ad9fb95d2..dc94a61d8e 100644 --- a/lib/crypto/c_src/evp_compat.h +++ b/lib/crypto/c_src/evp_compat.h @@ -200,8 +200,11 @@ DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) static INLINE void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) { - if (pub_key) *pub_key = dh->pub_key; - if (priv_key) *priv_key = dh->priv_key; + if (pub_key) + *pub_key = dh->pub_key; + + if (priv_key) + *priv_key = dh->priv_key; } #endif /* E_EVP_COMPAT_H__ */ -- cgit v1.2.3 From 420161f96effc135a52bb590a1b4bea717466449 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 01:29:33 -0800 Subject: Revamp get_pkey_digest_type() * Whitespace --- lib/crypto/c_src/pkey.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/crypto/c_src/pkey.c b/lib/crypto/c_src/pkey.c index bd56b2d977..d67163468d 100644 --- a/lib/crypto/c_src/pkey.c +++ b/lib/crypto/c_src/pkey.c @@ -68,13 +68,16 @@ static int get_pkey_digest_type(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_ struct digest_type_t *digp = NULL; *md = NULL; - if (type == atom_none && algorithm == atom_rsa) return PKEY_OK; + if (type == atom_none && algorithm == atom_rsa) + return PKEY_OK; #ifdef HAVE_EDDSA - if (algorithm == atom_eddsa) return PKEY_OK; + if (algorithm == atom_eddsa) + return PKEY_OK; #endif - digp = get_digest_type(type); - if (!digp) return PKEY_BADARG; - if (!digp->md.p) return PKEY_NOTSUP; + if ((digp = get_digest_type(type)) == NULL) + return PKEY_BADARG; + if (digp->md.p == NULL) + return PKEY_NOTSUP; *md = digp->md.p; return PKEY_OK; -- cgit v1.2.3 From 0b1d14b9ee271503d33f6aa1cbae5293cf978df6 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 01:34:29 -0800 Subject: Revamp get_pkey_sign_digest() * Add bounds checking and casts where appropriate --- lib/crypto/c_src/pkey.c | 92 +++++++++++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 38 deletions(-) diff --git a/lib/crypto/c_src/pkey.c b/lib/crypto/c_src/pkey.c index d67163468d..6e0ac1f19b 100644 --- a/lib/crypto/c_src/pkey.c +++ b/lib/crypto/c_src/pkey.c @@ -88,67 +88,83 @@ static int get_pkey_sign_digest(ErlNifEnv *env, ERL_NIF_TERM algorithm, unsigned char *md_value, const EVP_MD **mdp, unsigned char **tbsp, size_t *tbslenp) { - int i; + int i, ret; const ERL_NIF_TERM *tpl_terms; int tpl_arity; ErlNifBinary tbs_bin; - EVP_MD_CTX *mdctx; - const EVP_MD *md = *mdp; - unsigned char *tbs = *tbsp; - size_t tbslen = *tbslenp; + EVP_MD_CTX *mdctx = NULL; + const EVP_MD *md; + unsigned char *tbs; + size_t tbslen; unsigned int tbsleni; - if ((i = get_pkey_digest_type(env, algorithm, type, &md)) != PKEY_OK) { - return i; - } + md = *mdp; + tbs = *tbsp; + tbslen = *tbslenp; + + if ((i = get_pkey_digest_type(env, algorithm, type, &md)) != PKEY_OK) + return i; + if (enif_get_tuple(env, data, &tpl_arity, &tpl_terms)) { - if (tpl_arity != 2 || tpl_terms[0] != atom_digest - || !enif_inspect_binary(env, tpl_terms[1], &tbs_bin) - || (md != NULL && tbs_bin.size != EVP_MD_size(md))) { - return PKEY_BADARG; - } + if (tpl_arity != 2) + goto bad_arg; + if (tpl_terms[0] != atom_digest) + goto bad_arg; + if (!enif_inspect_binary(env, tpl_terms[1], &tbs_bin)) + goto bad_arg; + if (tbs_bin.size > INT_MAX) + goto bad_arg; + if (md != NULL) { + if ((int)tbs_bin.size != EVP_MD_size(md)) + goto bad_arg; + } + /* We have a digest (= hashed text) in tbs_bin */ tbs = tbs_bin.data; tbslen = tbs_bin.size; } else if (md == NULL) { - if (!enif_inspect_binary(env, data, &tbs_bin)) { - return PKEY_BADARG; - } + if (!enif_inspect_binary(env, data, &tbs_bin)) + goto bad_arg; + /* md == NULL, that is no hashing because DigestType argument was atom_none */ tbs = tbs_bin.data; tbslen = tbs_bin.size; } else { - if (!enif_inspect_binary(env, data, &tbs_bin)) { - return PKEY_BADARG; - } + if (!enif_inspect_binary(env, data, &tbs_bin)) + goto bad_arg; + /* We have the cleartext in tbs_bin and the hash algo info in md */ tbs = md_value; - mdctx = EVP_MD_CTX_create(); - if (!mdctx) { - return PKEY_BADARG; - } + + if ((mdctx = EVP_MD_CTX_create()) == NULL) + goto err; + /* Looks well, now hash the plain text into a digest according to md */ - if (EVP_DigestInit_ex(mdctx, md, NULL) <= 0) { - EVP_MD_CTX_destroy(mdctx); - return PKEY_BADARG; - } - if (EVP_DigestUpdate(mdctx, tbs_bin.data, tbs_bin.size) <= 0) { - EVP_MD_CTX_destroy(mdctx); - return PKEY_BADARG; - } - if (EVP_DigestFinal_ex(mdctx, tbs, &tbsleni) <= 0) { - EVP_MD_CTX_destroy(mdctx); - return PKEY_BADARG; - } - tbslen = (size_t)(tbsleni); - EVP_MD_CTX_destroy(mdctx); + if (EVP_DigestInit_ex(mdctx, md, NULL) != 1) + goto err; + if (EVP_DigestUpdate(mdctx, tbs_bin.data, tbs_bin.size) != 1) + goto err; + if (EVP_DigestFinal_ex(mdctx, tbs, &tbsleni) != 1) + goto err; + + tbslen = (size_t)tbsleni; } *mdp = md; *tbsp = tbs; *tbslenp = tbslen; - return PKEY_OK; + ret = PKEY_OK; + goto done; + + bad_arg: + err: + ret = PKEY_BADARG; + + done: + if (mdctx) + EVP_MD_CTX_destroy(mdctx); + return ret; } static int get_pkey_sign_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM options, -- cgit v1.2.3 From 4fb0cea158d9657ade89b7c20468d3fe66f60688 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 01:37:10 -0800 Subject: Revamp get_pkey_sign_options() * Exit early to reduce the nesting. --- lib/crypto/c_src/pkey.c | 100 ++++++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 46 deletions(-) diff --git a/lib/crypto/c_src/pkey.c b/lib/crypto/c_src/pkey.c index 6e0ac1f19b..787c75d22d 100644 --- a/lib/crypto/c_src/pkey.c +++ b/lib/crypto/c_src/pkey.c @@ -174,11 +174,9 @@ static int get_pkey_sign_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF const ERL_NIF_TERM *tpl_terms; int tpl_arity; const EVP_MD *opt_md; - int i; - if (!enif_is_list(env, options)) { - return PKEY_BADARG; - } + if (!enif_is_list(env, options)) + goto bad_arg; /* defaults */ if (algorithm == atom_rsa) { @@ -187,56 +185,66 @@ static int get_pkey_sign_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF opt->rsa_pss_saltlen = -2; } - if (enif_is_empty_list(env, options)) { + if (enif_is_empty_list(env, options)) return PKEY_OK; - } - if (algorithm == atom_rsa) { - tail = options; - while (enif_get_list_cell(env, tail, &head, &tail)) { - if (enif_get_tuple(env, head, &tpl_arity, &tpl_terms) && tpl_arity == 2) { - if (tpl_terms[0] == atom_rsa_mgf1_md && enif_is_atom(env, tpl_terms[1])) { - i = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md); - if (i != PKEY_OK) { - return i; - } - opt->rsa_mgf1_md = opt_md; - } else if (tpl_terms[0] == atom_rsa_padding) { - if (tpl_terms[1] == atom_rsa_pkcs1_padding) { - opt->rsa_padding = RSA_PKCS1_PADDING; - } else if (tpl_terms[1] == atom_rsa_pkcs1_pss_padding) { + if (algorithm != atom_rsa) + goto bad_arg; + + tail = options; + while (enif_get_list_cell(env, tail, &head, &tail)) { + if (!enif_get_tuple(env, head, &tpl_arity, &tpl_terms)) + goto bad_arg; + if (tpl_arity != 2) + goto bad_arg; + + if (tpl_terms[0] == atom_rsa_mgf1_md && enif_is_atom(env, tpl_terms[1])) { + int result; + + result = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md); + if (result != PKEY_OK) + return result; + + opt->rsa_mgf1_md = opt_md; + + } else if (tpl_terms[0] == atom_rsa_padding) { + if (tpl_terms[1] == atom_rsa_pkcs1_padding) { + opt->rsa_padding = RSA_PKCS1_PADDING; + + } else if (tpl_terms[1] == atom_rsa_pkcs1_pss_padding) { #ifdef HAVE_RSA_PKCS1_PSS_PADDING - opt->rsa_padding = RSA_PKCS1_PSS_PADDING; - if (opt->rsa_mgf1_md == NULL) { - opt->rsa_mgf1_md = md; - } + opt->rsa_padding = RSA_PKCS1_PSS_PADDING; + if (opt->rsa_mgf1_md == NULL) + opt->rsa_mgf1_md = md; #else - return PKEY_NOTSUP; + return PKEY_NOTSUP; #endif - } else if (tpl_terms[1] == atom_rsa_x931_padding) { - opt->rsa_padding = RSA_X931_PADDING; - } else if (tpl_terms[1] == atom_rsa_no_padding) { - opt->rsa_padding = RSA_NO_PADDING; - } else { - return PKEY_BADARG; - } - } else if (tpl_terms[0] == atom_rsa_pss_saltlen) { - if (!enif_get_int(env, tpl_terms[1], &(opt->rsa_pss_saltlen)) - || opt->rsa_pss_saltlen < -2) { - return PKEY_BADARG; - } - } else { - return PKEY_BADARG; - } - } else { - return PKEY_BADARG; - } - } - } else { - return PKEY_BADARG; + + } else if (tpl_terms[1] == atom_rsa_x931_padding) { + opt->rsa_padding = RSA_X931_PADDING; + + } else if (tpl_terms[1] == atom_rsa_no_padding) { + opt->rsa_padding = RSA_NO_PADDING; + + } else { + goto bad_arg; + } + + } else if (tpl_terms[0] == atom_rsa_pss_saltlen) { + if (!enif_get_int(env, tpl_terms[1], &(opt->rsa_pss_saltlen))) + goto bad_arg; + if (opt->rsa_pss_saltlen < -2) + goto bad_arg; + + } else { + goto bad_arg; + } } return PKEY_OK; + + bad_arg: + return PKEY_BADARG; } static int get_pkey_private_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM key, EVP_PKEY **pkey) -- cgit v1.2.3 From 16568308bdcad880df33cdaaa725a52111fb16b3 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 01:41:57 -0800 Subject: Revamp get_pkey_private_key() * Add error handling for all OpenSSL calls. * Free all resources in the same path. * Only set *pkey on success. --- lib/crypto/c_src/pkey.c | 131 ++++++++++++++++++++++++++++++------------------ 1 file changed, 81 insertions(+), 50 deletions(-) diff --git a/lib/crypto/c_src/pkey.c b/lib/crypto/c_src/pkey.c index 787c75d22d..1dd4a403be 100644 --- a/lib/crypto/c_src/pkey.c +++ b/lib/crypto/c_src/pkey.c @@ -249,88 +249,119 @@ static int get_pkey_sign_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF static int get_pkey_private_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM key, EVP_PKEY **pkey) { + EVP_PKEY *result = NULL; + RSA *rsa = NULL; + DSA *dsa = NULL; +#if defined(HAVE_EC) + EC_KEY *ec = NULL; +#endif + char *id = NULL; + char *password = NULL; + if (enif_is_map(env, key)) { #ifdef HAS_ENGINE_SUPPORT /* Use key stored in engine */ ENGINE *e; - char *id = NULL; - char *password; if (!get_engine_and_key_id(env, key, &id, &e)) - return PKEY_BADARG; + goto err; + password = get_key_password(env, key); - *pkey = ENGINE_load_private_key(e, id, NULL, password); - if (password) enif_free(password); - enif_free(id); - if (!*pkey) - return PKEY_BADARG; + result = ENGINE_load_private_key(e, id, NULL, password); + #else return PKEY_BADARG; #endif - } - else if (algorithm == atom_rsa) { - RSA *rsa = RSA_new(); + } else if (algorithm == atom_rsa) { + if ((rsa = RSA_new()) == NULL) + goto err; - if (!get_rsa_private_key(env, key, rsa)) { - RSA_free(rsa); - return PKEY_BADARG; - } + if (!get_rsa_private_key(env, key, rsa)) + goto err; + if ((result = EVP_PKEY_new()) == NULL) + goto err; + if (EVP_PKEY_assign_RSA(result, rsa) != 1) + goto err; + /* On success, result owns rsa */ + rsa = NULL; - *pkey = EVP_PKEY_new(); - if (!EVP_PKEY_assign_RSA(*pkey, rsa)) { - EVP_PKEY_free(*pkey); - RSA_free(rsa); - return PKEY_BADARG; - } } else if (algorithm == atom_ecdsa) { #if defined(HAVE_EC) - EC_KEY *ec = NULL; const ERL_NIF_TERM *tpl_terms; int tpl_arity; - if (enif_get_tuple(env, key, &tpl_arity, &tpl_terms) && tpl_arity == 2 - && enif_is_tuple(env, tpl_terms[0]) && enif_is_binary(env, tpl_terms[1]) - && get_ec_key(env, tpl_terms[0], tpl_terms[1], atom_undefined, &ec)) { + if (!enif_get_tuple(env, key, &tpl_arity, &tpl_terms)) + goto err; + if (tpl_arity != 2) + goto err; + if (!enif_is_tuple(env, tpl_terms[0])) + goto err; + if (!enif_is_binary(env, tpl_terms[1])) + goto err; + if (!get_ec_key(env, tpl_terms[0], tpl_terms[1], atom_undefined, &ec)) + goto err; + + if ((result = EVP_PKEY_new()) == NULL) + goto err; + if (EVP_PKEY_assign_EC_KEY(result, ec) != 1) + goto err; + /* On success, result owns ec */ + ec = NULL; - *pkey = EVP_PKEY_new(); - if (!EVP_PKEY_assign_EC_KEY(*pkey, ec)) { - EVP_PKEY_free(*pkey); - EC_KEY_free(ec); - return PKEY_BADARG; - } - } else { - return PKEY_BADARG; - } #else return PKEY_NOTSUP; #endif } else if (algorithm == atom_eddsa) { #if defined(HAVE_EDDSA) - if (!get_eddsa_key(env, 0, key, pkey)) { - return PKEY_BADARG; - } + if (!get_eddsa_key(env, 0, key, &result)) + goto err; #else - return PKEY_NOTSUP; + return PKEY_NOTSUP; #endif } else if (algorithm == atom_dss) { - DSA *dsa = DSA_new(); + if ((dsa = DSA_new()) == NULL) + goto err; + if (!get_dss_private_key(env, key, dsa)) + goto err; - if (!get_dss_private_key(env, key, dsa)) { - DSA_free(dsa); - return PKEY_BADARG; - } + if ((result = EVP_PKEY_new()) == NULL) + goto err; + if (EVP_PKEY_assign_DSA(result, dsa) != 1) + goto err; + /* On success, result owns dsa */ + dsa = NULL; - *pkey = EVP_PKEY_new(); - if (!EVP_PKEY_assign_DSA(*pkey, dsa)) { - EVP_PKEY_free(*pkey); - DSA_free(dsa); - return PKEY_BADARG; - } } else { return PKEY_BADARG; } - return PKEY_OK; + goto done; + + err: + if (result) + EVP_PKEY_free(result); + result = NULL; + + done: + if (password) + enif_free(password); + if (id) + enif_free(id); + if (rsa) + RSA_free(rsa); + if (dsa) + DSA_free(dsa); +#ifdef HAVE_EC + if (ec) + EC_KEY_free(ec); +#endif + + if (result == NULL) { + return PKEY_BADARG; + } else { + *pkey = result; + return PKEY_OK; + } } static int get_pkey_public_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM key, -- cgit v1.2.3 From 8525132a7d30f7ac6135a35b8b8af04245ded38c Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 01:47:39 -0800 Subject: Revamp get_pkey_public_key() * Add error handling for all OpenSSL calls. * Only set *pkey on success. * Consolidate all of the freeing of resources into one path. --- lib/crypto/c_src/pkey.c | 132 ++++++++++++++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 48 deletions(-) diff --git a/lib/crypto/c_src/pkey.c b/lib/crypto/c_src/pkey.c index 1dd4a403be..5093efccb5 100644 --- a/lib/crypto/c_src/pkey.c +++ b/lib/crypto/c_src/pkey.c @@ -367,87 +367,123 @@ static int get_pkey_private_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_ static int get_pkey_public_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM key, EVP_PKEY **pkey) { + EVP_PKEY *result = NULL; + RSA *rsa = NULL; + DSA *dsa = NULL; +#if defined(HAVE_EC) + EC_KEY *ec = NULL; +#endif + char *id = NULL; + char *password = NULL; + if (enif_is_map(env, key)) { #ifdef HAS_ENGINE_SUPPORT /* Use key stored in engine */ ENGINE *e; - char *id = NULL; - char *password; if (!get_engine_and_key_id(env, key, &id, &e)) - return PKEY_BADARG; + goto err; + password = get_key_password(env, key); - *pkey = ENGINE_load_public_key(e, id, NULL, password); - if (password) enif_free(password); - enif_free(id); - if (!pkey) - return PKEY_BADARG; + result = ENGINE_load_public_key(e, id, NULL, password); + #else return PKEY_BADARG; #endif } else if (algorithm == atom_rsa) { - RSA *rsa = RSA_new(); + if ((rsa = RSA_new()) == NULL) + goto err; - if (!get_rsa_public_key(env, key, rsa)) { - RSA_free(rsa); - return PKEY_BADARG; - } + if (!get_rsa_public_key(env, key, rsa)) + goto err; + + if ((result = EVP_PKEY_new()) == NULL) + goto err; + if (EVP_PKEY_assign_RSA(result, rsa) != 1) + goto err; + /* On success, result owns rsa */ + rsa = NULL; - *pkey = EVP_PKEY_new(); - if (!EVP_PKEY_assign_RSA(*pkey, rsa)) { - EVP_PKEY_free(*pkey); - RSA_free(rsa); - return PKEY_BADARG; - } } else if (algorithm == atom_ecdsa) { #if defined(HAVE_EC) - EC_KEY *ec = NULL; const ERL_NIF_TERM *tpl_terms; int tpl_arity; - if (enif_get_tuple(env, key, &tpl_arity, &tpl_terms) && tpl_arity == 2 - && enif_is_tuple(env, tpl_terms[0]) && enif_is_binary(env, tpl_terms[1]) - && get_ec_key(env, tpl_terms[0], atom_undefined, tpl_terms[1], &ec)) { + if (!enif_get_tuple(env, key, &tpl_arity, &tpl_terms)) + goto err; + if (tpl_arity != 2) + goto err; + if (!enif_is_tuple(env, tpl_terms[0])) + goto err; + if (!enif_is_binary(env, tpl_terms[1])) + goto err; + if (!get_ec_key(env, tpl_terms[0], atom_undefined, tpl_terms[1], &ec)) + goto err; + + if ((result = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_EC_KEY(result, ec) != 1) + goto err; + /* On success, result owns ec */ + ec = NULL; - *pkey = EVP_PKEY_new(); - if (!EVP_PKEY_assign_EC_KEY(*pkey, ec)) { - EVP_PKEY_free(*pkey); - EC_KEY_free(ec); - return PKEY_BADARG; - } - } else { - return PKEY_BADARG; - } #else return PKEY_NOTSUP; #endif } else if (algorithm == atom_eddsa) { #if defined(HAVE_EDDSA) - if (!get_eddsa_key(env, 1, key, pkey)) { - return PKEY_BADARG; - } + if (!get_eddsa_key(env, 1, key, &result)) + goto err; + #else - return PKEY_NOTSUP; + return PKEY_NOTSUP; #endif } else if (algorithm == atom_dss) { - DSA *dsa = DSA_new(); + if ((dsa = DSA_new()) == NULL) + goto err; - if (!get_dss_public_key(env, key, dsa)) { - DSA_free(dsa); - return PKEY_BADARG; - } + if (!get_dss_public_key(env, key, dsa)) + goto err; + + if ((result = EVP_PKEY_new()) == NULL) + goto err; + if (EVP_PKEY_assign_DSA(result, dsa) != 1) + goto err; + /* On success, result owns dsa */ + dsa = NULL; - *pkey = EVP_PKEY_new(); - if (!EVP_PKEY_assign_DSA(*pkey, dsa)) { - EVP_PKEY_free(*pkey); - DSA_free(dsa); - return PKEY_BADARG; - } } else { return PKEY_BADARG; } - return PKEY_OK; + goto done; + + err: + if (result) + EVP_PKEY_free(result); + result = NULL; + + done: + if (password) + enif_free(password); + if (id) + enif_free(id); + if (rsa) + RSA_free(rsa); + if (dsa) + DSA_free(dsa); +#ifdef HAVE_EC + if (ec) + EC_KEY_free(ec); +#endif + + if (result == NULL) { + return PKEY_BADARG; + } else { + *pkey = result; + return PKEY_OK; + } } ERL_NIF_TERM pkey_sign_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From a66517a2e9dd53958811ed0abc51868706b2da30 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 01:55:54 -0800 Subject: Revamp pkey_sign_nif() * Add error handling for all Erlang calls. --- lib/crypto/c_src/pkey.c | 241 ++++++++++++++++++++++++++++++------------------ 1 file changed, 150 insertions(+), 91 deletions(-) diff --git a/lib/crypto/c_src/pkey.c b/lib/crypto/c_src/pkey.c index 5093efccb5..53dec8a083 100644 --- a/lib/crypto/c_src/pkey.c +++ b/lib/crypto/c_src/pkey.c @@ -489,19 +489,30 @@ static int get_pkey_public_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_T ERL_NIF_TERM pkey_sign_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {/* (Algorithm, Type, Data|{digest,Digest}, Key|#{}, Options) */ int i; + int sig_bin_alloc = 0; + ERL_NIF_TERM ret; const EVP_MD *md = NULL; unsigned char md_value[EVP_MAX_MD_SIZE]; - EVP_PKEY *pkey; + EVP_PKEY *pkey = NULL; +#ifdef HAVE_EDDSA + EVP_MD_CTX *mdctx = NULL; +#endif #ifdef HAS_EVP_PKEY_CTX - EVP_PKEY_CTX *ctx; + EVP_PKEY_CTX *ctx = NULL; size_t siglen; #else - unsigned len, siglen; + int len; + unsigned int siglen; #endif PKeySignOptions sig_opt; ErlNifBinary sig_bin; /* signature */ unsigned char *tbs; /* data to be signed */ size_t tbslen; + RSA *rsa = NULL; + DSA *dsa = NULL; +#if defined(HAVE_EC) + EC_KEY *ec = NULL; +#endif /*char buf[1024]; enif_get_atom(env,argv[0],buf,1024,ERL_NIF_LATIN1); printf("algo=%s ",buf); enif_get_atom(env,argv[1],buf,1024,ERL_NIF_LATIN1); printf("hash=%s ",buf); @@ -509,148 +520,196 @@ printf("\r\n"); */ #ifndef HAS_ENGINE_SUPPORT - if (enif_is_map(env, argv[3])) { + if (enif_is_map(env, argv[3])) return atom_notsup; - } #endif i = get_pkey_sign_digest(env, argv[0], argv[1], argv[2], md_value, &md, &tbs, &tbslen); - if (i != PKEY_OK) { - if (i == PKEY_NOTSUP) - return atom_notsup; - else - return enif_make_badarg(env); + switch (i) { + case PKEY_OK: + break; + case PKEY_NOTSUP: + goto notsup; + default: + goto bad_arg; } i = get_pkey_sign_options(env, argv[0], argv[4], md, &sig_opt); - if (i != PKEY_OK) { - if (i == PKEY_NOTSUP) - return atom_notsup; - else - return enif_make_badarg(env); + switch (i) { + case PKEY_OK: + break; + case PKEY_NOTSUP: + goto notsup; + default: + goto bad_arg; } - if (get_pkey_private_key(env, argv[0], argv[3], &pkey) != PKEY_OK) { - return enif_make_badarg(env); - } + if (get_pkey_private_key(env, argv[0], argv[3], &pkey) != PKEY_OK) + goto bad_arg; #ifdef HAS_EVP_PKEY_CTX - ctx = EVP_PKEY_CTX_new(pkey, NULL); - if (!ctx) goto badarg; + if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) + goto err; if (argv[0] != atom_eddsa) { - if (EVP_PKEY_sign_init(ctx) <= 0) goto badarg; - if (md != NULL && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) goto badarg; + if (EVP_PKEY_sign_init(ctx) != 1) + goto err; + if (md != NULL) { + if (EVP_PKEY_CTX_set_signature_md(ctx, md) != 1) + goto err; + } } if (argv[0] == atom_rsa) { - if (EVP_PKEY_CTX_set_rsa_padding(ctx, sig_opt.rsa_padding) <= 0) goto badarg; + if (EVP_PKEY_CTX_set_rsa_padding(ctx, sig_opt.rsa_padding) != 1) + goto err; # ifdef HAVE_RSA_PKCS1_PSS_PADDING if (sig_opt.rsa_padding == RSA_PKCS1_PSS_PADDING) { if (sig_opt.rsa_mgf1_md != NULL) { # ifdef HAVE_RSA_MGF1_MD - if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sig_opt.rsa_mgf1_md) <= 0) goto badarg; + if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sig_opt.rsa_mgf1_md) != 1) + goto err; # else - EVP_PKEY_CTX_free(ctx); - EVP_PKEY_free(pkey); - return atom_notsup; + goto notsup; # endif } - if (sig_opt.rsa_pss_saltlen > -2 - && EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sig_opt.rsa_pss_saltlen) <= 0) - goto badarg; - } + if (sig_opt.rsa_pss_saltlen > -2) { + if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sig_opt.rsa_pss_saltlen) != 1) + goto err; + } + } #endif } if (argv[0] == atom_eddsa) { #ifdef HAVE_EDDSA - EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); - if (!EVP_DigestSignInit(mdctx, NULL, NULL, NULL, pkey)) { - if (mdctx) EVP_MD_CTX_free(mdctx); - goto badarg; - } + if ((mdctx = EVP_MD_CTX_new()) == NULL) + goto err; - if (!EVP_DigestSign(mdctx, NULL, &siglen, tbs, tbslen)) { - EVP_MD_CTX_free(mdctx); - goto badarg; - } - enif_alloc_binary(siglen, &sig_bin); + if (EVP_DigestSignInit(mdctx, NULL, NULL, NULL, pkey) != 1) + goto err; + if (EVP_DigestSign(mdctx, NULL, &siglen, tbs, tbslen) != 1) + goto err; + if (!enif_alloc_binary(siglen, &sig_bin)) + goto err; + sig_bin_alloc = 1; - if (!EVP_DigestSign(mdctx, sig_bin.data, &siglen, tbs, tbslen)) { - EVP_MD_CTX_free(mdctx); - goto badarg; - } - EVP_MD_CTX_free(mdctx); + if (EVP_DigestSign(mdctx, sig_bin.data, &siglen, tbs, tbslen) != 1) + goto bad_key; #else - goto badarg; + goto bad_arg; #endif - } - else - { - if (EVP_PKEY_sign(ctx, NULL, &siglen, tbs, tbslen) <= 0) goto badarg; - enif_alloc_binary(siglen, &sig_bin); + } else { + if (EVP_PKEY_sign(ctx, NULL, &siglen, tbs, tbslen) != 1) + goto err; + if (!enif_alloc_binary(siglen, &sig_bin)) + goto err; + sig_bin_alloc = 1; if (md != NULL) { ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, EVP_MD_size(md)); } - i = EVP_PKEY_sign(ctx, sig_bin.data, &siglen, tbs, tbslen); + if (EVP_PKEY_sign(ctx, sig_bin.data, &siglen, tbs, tbslen) != 1) + goto bad_key; } - - EVP_PKEY_CTX_free(ctx); #else /*printf("Old interface\r\n"); */ if (argv[0] == atom_rsa) { - RSA *rsa = EVP_PKEY_get1_RSA(pkey); - enif_alloc_binary(RSA_size(rsa), &sig_bin); - len = EVP_MD_size(md); - ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len); - i = RSA_sign(md->type, tbs, len, sig_bin.data, &siglen, rsa); - RSA_free(rsa); + if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) + goto err; + if ((len = RSA_size(rsa)) < 0) + goto err; + if (!enif_alloc_binary((size_t)len, &sig_bin)) + goto err; + sig_bin_alloc = 1; + + if ((len = EVP_MD_size(md)) < 0) + goto err; + ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len); + + if (RSA_sign(md->type, tbs, (unsigned int)len, sig_bin.data, &siglen, rsa) != 1) + goto bad_key; } else if (argv[0] == atom_dss) { - DSA *dsa = EVP_PKEY_get1_DSA(pkey); - enif_alloc_binary(DSA_size(dsa), &sig_bin); - len = EVP_MD_size(md); - ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len); - i = DSA_sign(md->type, tbs, len, sig_bin.data, &siglen, dsa); - DSA_free(dsa); + if ((dsa = EVP_PKEY_get1_DSA(pkey)) == NULL) + goto err; + if ((len = DSA_size(dsa)) < 0) + goto err; + if (!enif_alloc_binary((size_t)len, &sig_bin)) + goto err; + sig_bin_alloc = 1; + + if ((len = EVP_MD_size(md)) < 0) + goto err; + ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len); + + if (DSA_sign(md->type, tbs, len, sig_bin.data, &siglen, dsa) != 1) + goto bad_key; } else if (argv[0] == atom_ecdsa) { #if defined(HAVE_EC) - EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pkey); - enif_alloc_binary(ECDSA_size(ec), &sig_bin); - len = EVP_MD_size(md); - ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len); - i = ECDSA_sign(md->type, tbs, len, sig_bin.data, &siglen, ec); - EC_KEY_free(ec); + if ((ec = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) + goto err; + if ((len = ECDSA_size(ec)) < 0) + goto err; + if (!enif_alloc_binary((size_t)len, &sig_bin)) + goto err; + sig_bin_alloc = 1; + + len = EVP_MD_size(md); + ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len); + + if (ECDSA_sign(md->type, tbs, len, sig_bin.data, &siglen, ec) != 1) + goto bad_key; #else - EVP_PKEY_free(pkey); - return atom_notsup; + goto notsup; #endif } else { - goto badarg; + goto bad_arg; } #endif - EVP_PKEY_free(pkey); - if (i == 1) { - ERL_VALGRIND_MAKE_MEM_DEFINED(sig_bin.data, siglen); - if (siglen != sig_bin.size) { - enif_realloc_binary(&sig_bin, siglen); - ERL_VALGRIND_ASSERT_MEM_DEFINED(sig_bin.data, siglen); - } - return enif_make_binary(env, &sig_bin); - } else { - enif_release_binary(&sig_bin); - return atom_error; + ERL_VALGRIND_MAKE_MEM_DEFINED(sig_bin.data, siglen); + if (siglen != sig_bin.size) { + if (!enif_realloc_binary(&sig_bin, siglen)) + goto err; + ERL_VALGRIND_ASSERT_MEM_DEFINED(sig_bin.data, siglen); } + ret = enif_make_binary(env, &sig_bin); + sig_bin_alloc = 0; + goto done; - badarg: + bad_key: + ret = atom_error; + goto done; + + notsup: + ret = atom_notsup; + goto done; + + bad_arg: + err: + ret = enif_make_badarg(env); + goto done; + + done: + if (sig_bin_alloc) + enif_release_binary(&sig_bin); + if (rsa) + RSA_free(rsa); + if (dsa) + DSA_free(dsa); +#ifdef HAVE_EC + if (ec) + EC_KEY_free(ec); +#endif #ifdef HAS_EVP_PKEY_CTX - EVP_PKEY_CTX_free(ctx); + if (ctx) + EVP_PKEY_CTX_free(ctx); #endif - EVP_PKEY_free(pkey); - return enif_make_badarg(env); + if (pkey) + EVP_PKEY_free(pkey); + + return ret; } ERL_NIF_TERM pkey_verify_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From 27384474899f24a96c76a7978f4943cfa05ae33d Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 02:01:38 -0800 Subject: Revamp pkey_verify_nif() --- lib/crypto/c_src/pkey.c | 175 ++++++++++++++++++++++++++++-------------------- 1 file changed, 104 insertions(+), 71 deletions(-) diff --git a/lib/crypto/c_src/pkey.c b/lib/crypto/c_src/pkey.c index 53dec8a083..4cad9b6003 100644 --- a/lib/crypto/c_src/pkey.c +++ b/lib/crypto/c_src/pkey.c @@ -715,139 +715,172 @@ printf("\r\n"); ERL_NIF_TERM pkey_verify_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {/* (Algorithm, Type, Data|{digest,Digest}, Signature, Key, Options) */ int i; + int result; const EVP_MD *md = NULL; unsigned char md_value[EVP_MAX_MD_SIZE]; - EVP_PKEY *pkey; + EVP_PKEY *pkey = NULL; #ifdef HAS_EVP_PKEY_CTX - EVP_PKEY_CTX *ctx; + EVP_PKEY_CTX *ctx = NULL; #else #endif PKeySignOptions sig_opt; ErlNifBinary sig_bin; /* signature */ unsigned char *tbs; /* data to be signed */ size_t tbslen; + ERL_NIF_TERM ret; + RSA *rsa = NULL; + DSA *dsa = NULL; +#ifdef HAVE_EC + EC_KEY *ec = NULL; +#endif +#ifdef HAVE_EDDSA + EVP_MD_CTX *mdctx = NULL; +#endif #ifndef HAS_ENGINE_SUPPORT - if (enif_is_map(env, argv[4])) { + if (enif_is_map(env, argv[4])) return atom_notsup; - } #endif - if (!enif_inspect_binary(env, argv[3], &sig_bin)) { + if (!enif_inspect_binary(env, argv[3], &sig_bin)) return enif_make_badarg(env); - } i = get_pkey_sign_digest(env, argv[0], argv[1], argv[2], md_value, &md, &tbs, &tbslen); - if (i != PKEY_OK) { - if (i == PKEY_NOTSUP) - return atom_notsup; - else - return enif_make_badarg(env); + switch (i) { + case PKEY_OK: + break; + case PKEY_NOTSUP: + goto notsup; + default: + goto bad_arg; } i = get_pkey_sign_options(env, argv[0], argv[5], md, &sig_opt); - if (i != PKEY_OK) { - if (i == PKEY_NOTSUP) - return atom_notsup; - else - return enif_make_badarg(env); + switch (i) { + case PKEY_OK: + break; + case PKEY_NOTSUP: + goto notsup; + default: + goto bad_arg; } if (get_pkey_public_key(env, argv[0], argv[4], &pkey) != PKEY_OK) { - return enif_make_badarg(env); + goto bad_arg; } #ifdef HAS_EVP_PKEY_CTX /* printf("EVP interface\r\n"); */ - ctx = EVP_PKEY_CTX_new(pkey, NULL); - if (!ctx) goto badarg; + if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) + goto err; if (argv[0] != atom_eddsa) { - if (EVP_PKEY_verify_init(ctx) <= 0) goto badarg; - if (md != NULL && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) goto badarg; + if (EVP_PKEY_verify_init(ctx) != 1) + goto err; + if (md != NULL) { + if (EVP_PKEY_CTX_set_signature_md(ctx, md) != 1) + goto err; + } } if (argv[0] == atom_rsa) { - if (EVP_PKEY_CTX_set_rsa_padding(ctx, sig_opt.rsa_padding) <= 0) goto badarg; - if (sig_opt.rsa_padding == RSA_PKCS1_PSS_PADDING) { + if (EVP_PKEY_CTX_set_rsa_padding(ctx, sig_opt.rsa_padding) != 1) + goto err; + if (sig_opt.rsa_padding == RSA_PKCS1_PSS_PADDING) { if (sig_opt.rsa_mgf1_md != NULL) { # ifdef HAVE_RSA_MGF1_MD - if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sig_opt.rsa_mgf1_md) <= 0) goto badarg; + if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sig_opt.rsa_mgf1_md) != 1) + goto err; # else - EVP_PKEY_CTX_free(ctx); - EVP_PKEY_free(pkey); - return atom_notsup; + goto notsup; # endif } - if (sig_opt.rsa_pss_saltlen > -2 - && EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sig_opt.rsa_pss_saltlen) <= 0) - goto badarg; - } + if (sig_opt.rsa_pss_saltlen > -2) { + if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sig_opt.rsa_pss_saltlen) != 1) + goto err; + } + } } - if (argv[0] == atom_eddsa) { + if (argv[0] == atom_eddsa) { #ifdef HAVE_EDDSA - EVP_MD_CTX* mdctx = EVP_MD_CTX_create(); + if ((mdctx = EVP_MD_CTX_new()) == NULL) + goto err; - if (!EVP_DigestVerifyInit(mdctx, NULL, NULL, NULL, pkey)) { - if (mdctx) EVP_MD_CTX_destroy(mdctx); - goto badarg; - } + if (EVP_DigestVerifyInit(mdctx, NULL, NULL, NULL, pkey) != 1) + goto err; - i = EVP_DigestVerify(mdctx, sig_bin.data, sig_bin.size, tbs, tbslen); - EVP_MD_CTX_destroy(mdctx); + result = EVP_DigestVerify(mdctx, sig_bin.data, sig_bin.size, tbs, tbslen); #else - goto badarg; + goto bad_arg; #endif + } else { + if (md != NULL) { + ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, EVP_MD_size(md)); } - else - { - if (md != NULL) { - ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, EVP_MD_size(md)); - } - i = EVP_PKEY_verify(ctx, sig_bin.data, sig_bin.size, tbs, tbslen); - } - - EVP_PKEY_CTX_free(ctx); + result = EVP_PKEY_verify(ctx, sig_bin.data, sig_bin.size, tbs, tbslen); + } #else /*printf("Old interface\r\n"); */ + if (tbslen > INT_MAX) + goto bad_arg; + if (sig_bin.size > INT_MAX) + goto bad_arg; if (argv[0] == atom_rsa) { - RSA *rsa = EVP_PKEY_get1_RSA(pkey); - i = RSA_verify(md->type, tbs, tbslen, sig_bin.data, sig_bin.size, rsa); - RSA_free(rsa); + if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) + goto err; + result = RSA_verify(md->type, tbs, (unsigned int)tbslen, sig_bin.data, (unsigned int)sig_bin.size, rsa); } else if (argv[0] == atom_dss) { - DSA *dsa = EVP_PKEY_get1_DSA(pkey); - i = DSA_verify(0, tbs, tbslen, sig_bin.data, sig_bin.size, dsa); - DSA_free(dsa); + if ((dsa = EVP_PKEY_get1_DSA(pkey)) == NULL) + goto err; + result = DSA_verify(0, tbs, (int)tbslen, sig_bin.data, (int)sig_bin.size, dsa); } else if (argv[0] == atom_ecdsa) { #if defined(HAVE_EC) - EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pkey); - i = ECDSA_verify(EVP_MD_type(md), tbs, tbslen, sig_bin.data, sig_bin.size, ec); - EC_KEY_free(ec); + if ((ec = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) + goto err; + result = ECDSA_verify(EVP_MD_type(md), tbs, (int)tbslen, sig_bin.data, (int)sig_bin.size, ec); #else - EVP_PKEY_free(pkey); - return atom_notsup; + goto notsup; #endif } else { - goto badarg; + goto bad_arg; } #endif - EVP_PKEY_free(pkey); - if (i == 1) { - return atom_true; - } else { - return atom_false; - } + ret = (result == 1 ? atom_true : atom_false); + goto done; - badarg: + bad_arg: + err: + ret = enif_make_badarg(env); + goto done; + + notsup: + ret = atom_notsup; + + done: #ifdef HAS_EVP_PKEY_CTX - EVP_PKEY_CTX_free(ctx); + if (ctx) + EVP_PKEY_CTX_free(ctx); #endif - EVP_PKEY_free(pkey); - return enif_make_badarg(env); +#ifdef HAVE_EDDSA + if (mdctx) + EVP_MD_CTX_free(mdctx); +#endif + if (pkey) + EVP_PKEY_free(pkey); + if (rsa) + RSA_free(rsa); + if (dsa) + DSA_free(dsa); +#ifdef HAVE_EC + if (ec) + EC_KEY_free(ec); +#endif + + return ret; } static int get_pkey_crypt_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM options, -- cgit v1.2.3 From 9e96731b2e1b67f3d8ed816cab670806c23fd261 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 06:23:41 -0800 Subject: Revamp get_pkey_crypt_options() --- lib/crypto/c_src/pkey.c | 137 ++++++++++++++++++++++++++---------------------- 1 file changed, 75 insertions(+), 62 deletions(-) diff --git a/lib/crypto/c_src/pkey.c b/lib/crypto/c_src/pkey.c index 4cad9b6003..acaa8abb7e 100644 --- a/lib/crypto/c_src/pkey.c +++ b/lib/crypto/c_src/pkey.c @@ -890,11 +890,9 @@ static int get_pkey_crypt_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NI const ERL_NIF_TERM *tpl_terms; int tpl_arity; const EVP_MD *opt_md; - int i; - if (!enif_is_list(env, options)) { - return PKEY_BADARG; - } + if (!enif_is_list(env, options)) + goto bad_arg; /* defaults */ if (algorithm == atom_rsa) { @@ -906,79 +904,94 @@ static int get_pkey_crypt_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NI opt->signature_md = NULL; } - if (enif_is_empty_list(env, options)) { - return PKEY_OK; - } + if (enif_is_empty_list(env, options)) + return PKEY_OK; + + if (algorithm != atom_rsa) + goto bad_arg; + + tail = options; + while (enif_get_list_cell(env, tail, &head, &tail)) { + if (!enif_get_tuple(env, head, &tpl_arity, &tpl_terms)) + goto bad_arg; + if (tpl_arity != 2) + goto bad_arg; + + if (tpl_terms[0] == atom_rsa_padding + || tpl_terms[0] == atom_rsa_pad /* Compatibility */ + ) { + if (tpl_terms[1] == atom_rsa_pkcs1_padding) { + opt->rsa_padding = RSA_PKCS1_PADDING; - if (algorithm == atom_rsa) { - tail = options; - while (enif_get_list_cell(env, tail, &head, &tail)) { - if (enif_get_tuple(env, head, &tpl_arity, &tpl_terms) && tpl_arity == 2) { - if (tpl_terms[0] == atom_rsa_padding - || tpl_terms[0] == atom_rsa_pad /* Compatibility */ - ) { - if (tpl_terms[1] == atom_rsa_pkcs1_padding) { - opt->rsa_padding = RSA_PKCS1_PADDING; #ifdef HAVE_RSA_OAEP_PADDING - } else if (tpl_terms[1] == atom_rsa_pkcs1_oaep_padding) { - opt->rsa_padding = RSA_PKCS1_OAEP_PADDING; + } else if (tpl_terms[1] == atom_rsa_pkcs1_oaep_padding) { + opt->rsa_padding = RSA_PKCS1_OAEP_PADDING; #endif + #ifdef HAVE_RSA_SSLV23_PADDING - } else if (tpl_terms[1] == atom_rsa_sslv23_padding) { - opt->rsa_padding = RSA_SSLV23_PADDING; + } else if (tpl_terms[1] == atom_rsa_sslv23_padding) { + opt->rsa_padding = RSA_SSLV23_PADDING; #endif - } else if (tpl_terms[1] == atom_rsa_x931_padding) { - opt->rsa_padding = RSA_X931_PADDING; - } else if (tpl_terms[1] == atom_rsa_no_padding) { - opt->rsa_padding = RSA_NO_PADDING; - } else { - return PKEY_BADARG; - } - } else if (tpl_terms[0] == atom_signature_md && enif_is_atom(env, tpl_terms[1])) { - i = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md); - if (i != PKEY_OK) { - return i; - } - opt->signature_md = opt_md; - } else if (tpl_terms[0] == atom_rsa_mgf1_md && enif_is_atom(env, tpl_terms[1])) { + + } else if (tpl_terms[1] == atom_rsa_x931_padding) { + opt->rsa_padding = RSA_X931_PADDING; + + } else if (tpl_terms[1] == atom_rsa_no_padding) { + opt->rsa_padding = RSA_NO_PADDING; + + } else { + goto bad_arg; + } + + } else if (tpl_terms[0] == atom_signature_md && enif_is_atom(env, tpl_terms[1])) { + int i; + i = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md); + if (i != PKEY_OK) { + return i; + } + opt->signature_md = opt_md; + + } else if (tpl_terms[0] == atom_rsa_mgf1_md && enif_is_atom(env, tpl_terms[1])) { + int i; #ifndef HAVE_RSA_MGF1_MD - if (tpl_terms[1] != atom_sha) - return PKEY_NOTSUP; + if (tpl_terms[1] != atom_sha) + return PKEY_NOTSUP; #endif - i = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md); - if (i != PKEY_OK) { - return i; - } - opt->rsa_mgf1_md = opt_md; - } else if (tpl_terms[0] == atom_rsa_oaep_label - && enif_inspect_binary(env, tpl_terms[1], &(opt->rsa_oaep_label))) { + i = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md); + if (i != PKEY_OK) { + return i; + } + opt->rsa_mgf1_md = opt_md; + + } else if (tpl_terms[0] == atom_rsa_oaep_label + && enif_inspect_binary(env, tpl_terms[1], &(opt->rsa_oaep_label))) { #ifdef HAVE_RSA_OAEP_MD - continue; + continue; #else - return PKEY_NOTSUP; + return PKEY_NOTSUP; #endif - } else if (tpl_terms[0] == atom_rsa_oaep_md && enif_is_atom(env, tpl_terms[1])) { + + } else if (tpl_terms[0] == atom_rsa_oaep_md && enif_is_atom(env, tpl_terms[1])) { + int i; #ifndef HAVE_RSA_OAEP_MD - if (tpl_terms[1] != atom_sha) - return PKEY_NOTSUP; + if (tpl_terms[1] != atom_sha) + return PKEY_NOTSUP; #endif - i = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md); - if (i != PKEY_OK) { - return i; - } - opt->rsa_oaep_md = opt_md; - } else { - return PKEY_BADARG; - } - } else { - return PKEY_BADARG; - } - } - } else { - return PKEY_BADARG; + i = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md); + if (i != PKEY_OK) { + return i; + } + opt->rsa_oaep_md = opt_md; + + } else { + goto bad_arg; + } } return PKEY_OK; + + bad_arg: + return PKEY_BADARG; } static size_t size_of_RSA(EVP_PKEY *pkey) { -- cgit v1.2.3 From a62cd2fde09cc7b58b7cfdb2ac9fde720e37e285 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 06:23:51 -0800 Subject: Revamp size_of_RSA() --- lib/crypto/c_src/pkey.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/crypto/c_src/pkey.c b/lib/crypto/c_src/pkey.c index acaa8abb7e..d37806b653 100644 --- a/lib/crypto/c_src/pkey.c +++ b/lib/crypto/c_src/pkey.c @@ -995,12 +995,18 @@ static int get_pkey_crypt_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NI } static size_t size_of_RSA(EVP_PKEY *pkey) { - size_t tmplen; - RSA *rsa = EVP_PKEY_get1_RSA(pkey); - if (rsa == NULL) return 0; - tmplen = RSA_size(rsa); - RSA_free(rsa); - return tmplen; + int ret = 0; + RSA *rsa = NULL; + + if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) + goto err; + ret = RSA_size(rsa); + + err: + if (rsa) + RSA_free(rsa); + + return (ret < 0) ? 0 : (size_t)ret; } ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From 1dfcdeed78f6cf8ffbb82cc6e41c1a3ef106a278 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 02:19:15 -0800 Subject: Revamp pkey_crypt_nif() --- lib/crypto/c_src/pkey.c | 394 ++++++++++++++++++++++++++---------------------- 1 file changed, 217 insertions(+), 177 deletions(-) diff --git a/lib/crypto/c_src/pkey.c b/lib/crypto/c_src/pkey.c index d37806b653..a30f98b841 100644 --- a/lib/crypto/c_src/pkey.c +++ b/lib/crypto/c_src/pkey.c @@ -1011,12 +1011,17 @@ static size_t size_of_RSA(EVP_PKEY *pkey) { ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {/* (Algorithm, Data, PublKey=[E,N]|[E,N,D]|[E,N,D,P1,P2,E1,E2,C], Options, IsPrivate, IsEncrypt) */ + ERL_NIF_TERM ret; int i; - EVP_PKEY *pkey; + int result = 0; + int tmp_bin_alloc = 0; + int out_bin_alloc = 0; + EVP_PKEY *pkey = NULL; #ifdef HAS_EVP_PKEY_CTX - EVP_PKEY_CTX *ctx; + EVP_PKEY_CTX *ctx = NULL; #else - RSA *rsa; + int len; + RSA *rsa = NULL; #endif PKeyCryptOptions crypt_opt; ErlNifBinary in_bin, out_bin, tmp_bin; @@ -1024,164 +1029,175 @@ ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) #ifdef HAVE_RSA_SSLV23_PADDING size_t tmplen; #endif - int is_private = (argv[4] == atom_true), - is_encrypt = (argv[5] == atom_true); + int is_private, is_encrypt; int algo_init = 0; + unsigned char *label_copy = NULL; + + if (argc != 6) + goto bad_arg; + + is_private = (argv[4] == atom_true); + is_encrypt = (argv[5] == atom_true); /* char algo[1024]; */ #ifndef HAS_ENGINE_SUPPORT - if (enif_is_map(env, argv[2])) { + if (enif_is_map(env, argv[2])) return atom_notsup; - } #endif - if (!enif_inspect_binary(env, argv[1], &in_bin)) { - return enif_make_badarg(env); - } + if (!enif_inspect_binary(env, argv[1], &in_bin)) + goto bad_arg; i = get_pkey_crypt_options(env, argv[0], argv[3], &crypt_opt); - if (i != PKEY_OK) { - if (i == PKEY_NOTSUP) - return atom_notsup; - else - return enif_make_badarg(env); + switch (i) { + case PKEY_OK: + break; + case PKEY_NOTSUP: + goto notsup; + default: + goto bad_arg; } if (is_private) { - if (get_pkey_private_key(env, argv[0], argv[2], &pkey) != PKEY_OK) { - return enif_make_badarg(env); - } + if (get_pkey_private_key(env, argv[0], argv[2], &pkey) != PKEY_OK) + goto bad_arg; } else { - if (get_pkey_public_key(env, argv[0], argv[2], &pkey) != PKEY_OK) { - return enif_make_badarg(env); - } + if (get_pkey_public_key(env, argv[0], argv[2], &pkey) != PKEY_OK) + goto bad_arg; } - out_bin.data = NULL; - out_bin.size = 0; - tmp_bin.data = NULL; - tmp_bin.size = 0; - #ifdef HAS_EVP_PKEY_CTX - ctx = EVP_PKEY_CTX_new(pkey, NULL); - if (!ctx) goto badarg; + if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) + goto err; /* enif_get_atom(env,argv[0],algo,1024,ERL_NIF_LATIN1); */ if (is_private) { if (is_encrypt) { /* private encrypt */ - if ((algo_init=EVP_PKEY_sign_init(ctx)) <= 0) { - /* fprintf(stderr,"BADARG %s private encrypt algo_init=%d %s:%d\r\n", algo, algo_init, __FILE__, __LINE__); */ - goto badarg; - } + if ((algo_init = EVP_PKEY_sign_init(ctx)) != 1) + goto bad_arg; } else { /* private decrypt */ - if ((algo_init=EVP_PKEY_decrypt_init(ctx)) <= 0) { - /* fprintf(stderr,"BADARG %s private decrypt algo_init=%d %s:%d\r\n", algo, algo_init, __FILE__, __LINE__); */ - goto badarg; - } + if ((algo_init = EVP_PKEY_decrypt_init(ctx)) != 1) + goto bad_arg; } } else { if (is_encrypt) { /* public encrypt */ - if ((algo_init=EVP_PKEY_encrypt_init(ctx)) <= 0) { - /* fprintf(stderr,"BADARG %s public encrypt algo_init=%d %s:%d\r\n", algo,algo_init,__FILE__, __LINE__); */ - goto badarg; - } + if ((algo_init = EVP_PKEY_encrypt_init(ctx)) != 1) + goto bad_arg; } else { /* public decrypt */ - if ((algo_init=EVP_PKEY_verify_recover_init(ctx)) <= 0) { - /* fprintf(stderr,"BADARG %s public decrypt algo_init=%d %s:%d\r\n", algo,algo_init,__FILE__, __LINE__); */ - goto badarg; - } + if ((algo_init = EVP_PKEY_verify_recover_init(ctx)) != 1) + goto bad_arg; } } if (argv[0] == atom_rsa) { - if (crypt_opt.signature_md != NULL - && EVP_PKEY_CTX_set_signature_md(ctx, crypt_opt.signature_md) <= 0) - goto badarg; + if (crypt_opt.signature_md != NULL) { + if (EVP_PKEY_CTX_set_signature_md(ctx, crypt_opt.signature_md) != 1) + goto bad_arg; + } + #ifdef HAVE_RSA_SSLV23_PADDING - if (crypt_opt.rsa_padding == RSA_SSLV23_PADDING) { - if (is_encrypt) { + if (crypt_opt.rsa_padding == RSA_SSLV23_PADDING) { + if (is_encrypt) { tmplen = size_of_RSA(pkey); - if (tmplen == 0) goto badarg; - if (!enif_alloc_binary(tmplen, &tmp_bin)) goto badarg; - if (RSA_padding_add_SSLv23(tmp_bin.data, tmplen, in_bin.data, in_bin.size) <= 0) - goto badarg; - in_bin = tmp_bin; - } - if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) <= 0) goto badarg; - } else + if (tmplen < 1 || tmplen > INT_MAX) + goto err; + if (!enif_alloc_binary(tmplen, &tmp_bin)) + goto err; + tmp_bin_alloc = 1; + if (in_bin.size > INT_MAX) + goto err; + if (!RSA_padding_add_SSLv23(tmp_bin.data, (int)tmplen, in_bin.data, (int)in_bin.size)) + goto err; + in_bin = tmp_bin; + } + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) != 1) + goto err; + } else #endif - { - if (EVP_PKEY_CTX_set_rsa_padding(ctx, crypt_opt.rsa_padding) <= 0) goto badarg; + { + if (EVP_PKEY_CTX_set_rsa_padding(ctx, crypt_opt.rsa_padding) != 1) + goto err; } + #ifdef HAVE_RSA_OAEP_MD - if (crypt_opt.rsa_padding == RSA_PKCS1_OAEP_PADDING) { - if (crypt_opt.rsa_oaep_md != NULL - && EVP_PKEY_CTX_set_rsa_oaep_md(ctx, crypt_opt.rsa_oaep_md) <= 0) - goto badarg; - if (crypt_opt.rsa_mgf1_md != NULL - && EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, crypt_opt.rsa_mgf1_md) <= 0) goto badarg; - if (crypt_opt.rsa_oaep_label.data != NULL && crypt_opt.rsa_oaep_label.size > 0) { - unsigned char *label_copy = NULL; - label_copy = OPENSSL_malloc(crypt_opt.rsa_oaep_label.size); - if (label_copy == NULL) goto badarg; - memcpy((void *)(label_copy), (const void *)(crypt_opt.rsa_oaep_label.data), - crypt_opt.rsa_oaep_label.size); - if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label_copy, - crypt_opt.rsa_oaep_label.size) <= 0) { - OPENSSL_free(label_copy); - label_copy = NULL; - goto badarg; - } - } - } + if (crypt_opt.rsa_padding == RSA_PKCS1_OAEP_PADDING) { + if (crypt_opt.rsa_oaep_md != NULL) { + if (EVP_PKEY_CTX_set_rsa_oaep_md(ctx, crypt_opt.rsa_oaep_md) != 1) + goto err; + } + + if (crypt_opt.rsa_mgf1_md != NULL) { + if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, crypt_opt.rsa_mgf1_md) != 1) + goto err; + } + + if (crypt_opt.rsa_oaep_label.data != NULL && crypt_opt.rsa_oaep_label.size > 0) { + if (crypt_opt.rsa_oaep_label.size > INT_MAX) + goto err; + if ((label_copy = OPENSSL_malloc(crypt_opt.rsa_oaep_label.size)) == NULL) + goto err; + + memcpy((void *)(label_copy), (const void *)(crypt_opt.rsa_oaep_label.data), + crypt_opt.rsa_oaep_label.size); + + if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label_copy, + (int)crypt_opt.rsa_oaep_label.size) != 1) + goto err; + /* On success, label_copy is owned by ctx */ + label_copy = NULL; + } + } #endif } if (is_private) { - if (is_encrypt) { - /* private_encrypt */ - i = EVP_PKEY_sign(ctx, NULL, &outlen, in_bin.data, in_bin.size); - } else { - /* private_decrypt */ - i = EVP_PKEY_decrypt(ctx, NULL, &outlen, in_bin.data, in_bin.size); - } + if (is_encrypt) { + /* private_encrypt */ + result = EVP_PKEY_sign(ctx, NULL, &outlen, in_bin.data, in_bin.size); + } else { + /* private_decrypt */ + result = EVP_PKEY_decrypt(ctx, NULL, &outlen, in_bin.data, in_bin.size); + } } else { - if (is_encrypt) { - /* public_encrypt */ - i = EVP_PKEY_encrypt(ctx, NULL, &outlen, in_bin.data, in_bin.size); - } else { - /* public_decrypt */ - i = EVP_PKEY_verify_recover(ctx, NULL, &outlen, in_bin.data, in_bin.size); - } + if (is_encrypt) { + /* public_encrypt */ + result = EVP_PKEY_encrypt(ctx, NULL, &outlen, in_bin.data, in_bin.size); + } else { + /* public_decrypt */ + result = EVP_PKEY_verify_recover(ctx, NULL, &outlen, in_bin.data, in_bin.size); + } } /* fprintf(stderr,"i = %d %s:%d\r\n", i, __FILE__, __LINE__); */ - if (i != 1) goto badarg; + if (result != 1) + goto err; - enif_alloc_binary(outlen, &out_bin); + if (!enif_alloc_binary(outlen, &out_bin)) + goto err; + out_bin_alloc = 1; if (is_private) { - if (is_encrypt) { - /* private_encrypt */ - i = EVP_PKEY_sign(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size); - } else { - /* private_decrypt */ - i = EVP_PKEY_decrypt(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size); - } + if (is_encrypt) { + /* private_encrypt */ + result = EVP_PKEY_sign(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size); + } else { + /* private_decrypt */ + result = EVP_PKEY_decrypt(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size); + } } else { - if (is_encrypt) { - /* public_encrypt */ - i = EVP_PKEY_encrypt(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size); - } else { - /* public_decrypt */ - i = EVP_PKEY_verify_recover(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size); - } + if (is_encrypt) { + /* public_encrypt */ + result = EVP_PKEY_encrypt(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size); + } else { + /* public_decrypt */ + result = EVP_PKEY_verify_recover(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size); + } } #else @@ -1189,112 +1205,136 @@ ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) if (argv[0] != atom_rsa) { algo_init = -2; /* exitcode: notsup */ - goto badarg; + goto bad_arg; } - rsa = EVP_PKEY_get1_RSA(pkey); - enif_alloc_binary(RSA_size(rsa), &out_bin); + if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) + goto err; + if ((len = RSA_size(rsa)) < 0) + goto err; + if (!enif_alloc_binary((size_t)len, &out_bin)) + goto err; + out_bin_alloc = 1; + + if (in_bin.size > INT_MAX) + goto err; if (is_private) { if (is_encrypt) { /* non-evp rsa private encrypt */ ERL_VALGRIND_ASSERT_MEM_DEFINED(in_bin.data,in_bin.size); - i = RSA_private_encrypt(in_bin.size, in_bin.data, + result = RSA_private_encrypt((int)in_bin.size, in_bin.data, out_bin.data, rsa, crypt_opt.rsa_padding); - if (i > 0) { - ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i); + if (result > 0) { + ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, result); } } else { /* non-evp rsa private decrypt */ - i = RSA_private_decrypt(in_bin.size, in_bin.data, + result = RSA_private_decrypt((int)in_bin.size, in_bin.data, out_bin.data, rsa, crypt_opt.rsa_padding); - if (i > 0) { - ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i); - enif_realloc_binary(&out_bin, i); + if (result > 0) { + ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, result); + if (!enif_realloc_binary(&out_bin, (size_t)result)) + goto err; } } } else { if (is_encrypt) { /* non-evp rsa public encrypt */ ERL_VALGRIND_ASSERT_MEM_DEFINED(in_bin.data,in_bin.size); - i = RSA_public_encrypt(in_bin.size, in_bin.data, + result = RSA_public_encrypt((int)in_bin.size, in_bin.data, out_bin.data, rsa, crypt_opt.rsa_padding); - if (i > 0) { - ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i); - } + if (result > 0) { + ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, result); + } } else { /* non-evp rsa public decrypt */ - i = RSA_public_decrypt(in_bin.size, in_bin.data, + result = RSA_public_decrypt((int)in_bin.size, in_bin.data, out_bin.data, rsa, crypt_opt.rsa_padding); - if (i > 0) { - ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i); - enif_realloc_binary(&out_bin, i); + if (result > 0) { + ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, result); + if (!enif_realloc_binary(&out_bin, (size_t)result)) + goto err; } } } - outlen = i; - RSA_free(rsa); + outlen = (size_t)result; #endif - if ((i > 0) && argv[0] == atom_rsa && !is_encrypt) { + if ((result > 0) && argv[0] == atom_rsa && !is_encrypt) { #ifdef HAVE_RSA_SSLV23_PADDING - if (crypt_opt.rsa_padding == RSA_SSLV23_PADDING) { - unsigned char *p; + if (crypt_opt.rsa_padding == RSA_SSLV23_PADDING) { + unsigned char *p; + tmplen = size_of_RSA(pkey); - if (tmplen == 0) goto badarg; - if (!enif_alloc_binary(tmplen, &tmp_bin)) - goto badarg; - p = out_bin.data; - p++; - i = RSA_padding_check_SSLv23(tmp_bin.data, tmplen, p, out_bin.size - 1, tmplen); - if (i >= 0) { - outlen = i; - in_bin = out_bin; - out_bin = tmp_bin; - tmp_bin = in_bin; - i = 1; - } - } -#endif - } + if (tmplen < 1 || tmplen > INT_MAX) + goto err; + if (!enif_alloc_binary(tmplen, &tmp_bin)) + goto err; + tmp_bin_alloc = 1; + if (out_bin.size > INT_MAX) + goto err; - if (tmp_bin.data != NULL) { - enif_release_binary(&tmp_bin); - } + p = out_bin.data; + p++; -#ifdef HAS_EVP_PKEY_CTX - EVP_PKEY_CTX_free(ctx); -#else + result = RSA_padding_check_SSLv23(tmp_bin.data, (int)tmplen, p, (int)out_bin.size - 1, (int)tmplen); + if (result >= 0) { + outlen = (size_t)result; + in_bin = out_bin; + out_bin = tmp_bin; + tmp_bin = in_bin; + result = 1; + } + } #endif - EVP_PKEY_free(pkey); - if (i > 0) { - ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, outlen); - if (outlen != out_bin.size) { - enif_realloc_binary(&out_bin, outlen); - ERL_VALGRIND_ASSERT_MEM_DEFINED(out_bin.data, outlen); - } - return enif_make_binary(env, &out_bin); - } else { - enif_release_binary(&out_bin); - return atom_error; } - badarg: - if (out_bin.data != NULL) { - enif_release_binary(&out_bin); - } - if (tmp_bin.data != NULL) { - enif_release_binary(&tmp_bin); + if (result > 0) { + ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, outlen); + if (outlen != out_bin.size) { + if (!enif_realloc_binary(&out_bin, outlen)) + goto err; + ERL_VALGRIND_ASSERT_MEM_DEFINED(out_bin.data, outlen); + } + ret = enif_make_binary(env, &out_bin); + out_bin_alloc = 0; + } else { + ret = atom_error; } + goto done; + + notsup: + ret = atom_notsup; + goto done; + + bad_arg: + err: + if (algo_init == -2) + ret = atom_notsup; + else + ret = enif_make_badarg(env); + + done: + if (out_bin_alloc) + enif_release_binary(&out_bin); + if (tmp_bin_alloc) + enif_release_binary(&tmp_bin); + #ifdef HAS_EVP_PKEY_CTX - EVP_PKEY_CTX_free(ctx); + if (ctx) + EVP_PKEY_CTX_free(ctx); #else + if (rsa) + RSA_free(rsa); #endif - EVP_PKEY_free(pkey); - if (algo_init == -2) - return atom_notsup; - else - return enif_make_badarg(env); + if (pkey) + EVP_PKEY_free(pkey); + + if (label_copy) + OPENSSL_free(label_copy); + + return ret; } ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From 10b24fc72ffe49dac252176adfc35f76918626b1 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 02:21:52 -0800 Subject: Revamp privkey_to_pubkey_nif() --- lib/crypto/c_src/pkey.c | 88 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 29 deletions(-) diff --git a/lib/crypto/c_src/pkey.c b/lib/crypto/c_src/pkey.c index a30f98b841..33905e7753 100644 --- a/lib/crypto/c_src/pkey.c +++ b/lib/crypto/c_src/pkey.c @@ -1339,39 +1339,53 @@ ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { /* (Algorithm, PrivKey | KeyMap) */ - EVP_PKEY *pkey; - ERL_NIF_TERM alg = argv[0]; + ERL_NIF_TERM ret; + EVP_PKEY *pkey = NULL; + RSA *rsa = NULL; + DSA *dsa = NULL; ERL_NIF_TERM result[8]; - if (get_pkey_private_key(env, alg, argv[1], &pkey) != PKEY_OK) { - return enif_make_badarg(env); - } - if (alg == atom_rsa) { + if (argc != 2) + goto bad_arg; + if (get_pkey_private_key(env, argv[0], argv[1], &pkey) != PKEY_OK) + goto bad_arg; + + if (argv[0] == atom_rsa) { const BIGNUM *n = NULL, *e = NULL, *d = NULL; - RSA *rsa = EVP_PKEY_get1_RSA(pkey); - if (rsa) { - RSA_get0_key(rsa, &n, &e, &d); - result[0] = bin_from_bn(env, e); // Exponent E - result[1] = bin_from_bn(env, n); // Modulus N = p*q - RSA_free(rsa); - EVP_PKEY_free(pkey); - return enif_make_list_from_array(env, result, 2); - } + + if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) + goto err; + + RSA_get0_key(rsa, &n, &e, &d); + + // Exponent E + if ((result[0] = bin_from_bn(env, e)) == atom_error) + goto err; + // Modulus N = p*q + if ((result[1] = bin_from_bn(env, n)) == atom_error) + goto err; + + ret = enif_make_list_from_array(env, result, 2); } else if (argv[0] == atom_dss) { const BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL; - DSA *dsa = EVP_PKEY_get1_DSA(pkey); - if (dsa) { - DSA_get0_pqg(dsa, &p, &q, &g); - DSA_get0_key(dsa, &pub_key, NULL); - result[0] = bin_from_bn(env, p); - result[1] = bin_from_bn(env, q); - result[2] = bin_from_bn(env, g); - result[3] = bin_from_bn(env, pub_key); - DSA_free(dsa); - EVP_PKEY_free(pkey); - return enif_make_list_from_array(env, result, 4); - } + + if ((dsa = EVP_PKEY_get1_DSA(pkey)) == NULL) + goto err; + + DSA_get0_pqg(dsa, &p, &q, &g); + DSA_get0_key(dsa, &pub_key, NULL); + + if ((result[0] = bin_from_bn(env, p)) == atom_error) + goto err; + if ((result[1] = bin_from_bn(env, q)) == atom_error) + goto err; + if ((result[2] = bin_from_bn(env, g)) == atom_error) + goto err; + if ((result[3] = bin_from_bn(env, pub_key)) == atom_error) + goto err; + + ret = enif_make_list_from_array(env, result, 4); } else if (argv[0] == atom_ecdsa) { #if defined(HAVE_EC) @@ -1408,8 +1422,24 @@ ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM return enif_make_list_from_array(env, ..., ...); */ #endif + goto bad_arg; + } else { + goto bad_arg; } - if (pkey) EVP_PKEY_free(pkey); - return enif_make_badarg(env); + goto done; + + bad_arg: + err: + ret = enif_make_badarg(env); + + done: + if (rsa) + RSA_free(rsa); + if (dsa) + DSA_free(dsa); + if (pkey) + EVP_PKEY_free(pkey); + + return ret; } -- cgit v1.2.3 From 7e8f28265c746f2a8993e34159cc0f4c3363832b Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Fri, 4 Jan 2019 02:26:24 -0800 Subject: Revamp rc4_encrypt_with_state() --- lib/crypto/c_src/rc4.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/lib/crypto/c_src/rc4.c b/lib/crypto/c_src/rc4.c index d5b32d88bd..63f8000839 100644 --- a/lib/crypto/c_src/rc4.c +++ b/lib/crypto/c_src/rc4.c @@ -57,20 +57,34 @@ ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary state, data; RC4_KEY* rc4_key; ERL_NIF_TERM new_state, new_data; + unsigned char *outp; CHECK_NO_FIPS_MODE(); - if (!enif_inspect_iolist_as_binary(env,argv[0], &state) - || state.size != sizeof(RC4_KEY) - || !enif_inspect_iolist_as_binary(env,argv[1], &data)) { - return enif_make_badarg(env); - } - rc4_key = (RC4_KEY*)enif_make_new_binary(env, sizeof(RC4_KEY), &new_state); + if (argc != 2) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[0], &state)) + goto bad_arg; + if (state.size != sizeof(RC4_KEY)) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[1], &data)) + goto bad_arg; + + if ((rc4_key = (RC4_KEY*)enif_make_new_binary(env, sizeof(RC4_KEY), &new_state)) == NULL) + goto err; + if ((outp = enif_make_new_binary(env, data.size, &new_data)) == NULL) + goto err; + memcpy(rc4_key, state.data, sizeof(RC4_KEY)); - RC4(rc4_key, data.size, data.data, - enif_make_new_binary(env, data.size, &new_data)); - CONSUME_REDS(env,data); - return enif_make_tuple2(env,new_state,new_data); + RC4(rc4_key, data.size, data.data, outp); + + CONSUME_REDS(env, data); + return enif_make_tuple2(env, new_state, new_data); + + bad_arg: + err: + return enif_make_badarg(env); + #else return enif_raise_exception(env, atom_notsup); #endif -- cgit v1.2.3 From faf4389df139dd17a410066d077811953edbede3 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 12:24:24 -0800 Subject: Revamp init_cipher_ctx() --- lib/crypto/c_src/cipher.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/crypto/c_src/cipher.c b/lib/crypto/c_src/cipher.c index cda9b15291..175d927ef5 100644 --- a/lib/crypto/c_src/cipher.c +++ b/lib/crypto/c_src/cipher.c @@ -88,13 +88,15 @@ int init_cipher_ctx(ErlNifEnv *env) { (ErlNifResourceDtor*) evp_cipher_ctx_dtor, ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER, NULL); - if (evp_cipher_ctx_rtype == NULL) { - PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_CIPHER_CTX'"); - return 0; - } + if (evp_cipher_ctx_rtype == NULL) + goto err; #endif return 1; + + err: + PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_CIPHER_CTX'"); + return 0; } void init_cipher_types(ErlNifEnv* env) -- cgit v1.2.3 From 4e3bc5e7cdb7427a3b6c892fe30e56c63d0b570c Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 12:32:18 -0800 Subject: Revamp init_engine_ctx() --- lib/crypto/c_src/engine.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 4d75f6430b..44648280b4 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -103,13 +103,15 @@ int init_engine_ctx(ErlNifEnv *env) { (ErlNifResourceDtor*) engine_ctx_dtor, ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER, NULL); - if (engine_ctx_rtype == NULL) { - PRINTF_ERR0("CRYPTO: Could not open resource type 'ENGINE_CTX'"); - return 0; - } + if (engine_ctx_rtype == NULL) + goto err; #endif return 1; + + err: + PRINTF_ERR0("CRYPTO: Could not open resource type 'ENGINE_CTX'"); + return 0; } ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From 70b61618b7001c03111c0ff8dfceaeead0173b69 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 12:35:55 -0800 Subject: Revamp init_hash_ctx() --- lib/crypto/c_src/hash.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/crypto/c_src/hash.c b/lib/crypto/c_src/hash.c index c9fcd35ca2..a90957f1a7 100644 --- a/lib/crypto/c_src/hash.c +++ b/lib/crypto/c_src/hash.c @@ -48,13 +48,15 @@ int init_hash_ctx(ErlNifEnv* env) { (ErlNifResourceDtor*) evp_md_ctx_dtor, ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER, NULL); - if (evp_md_ctx_rtype == NULL) { - PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_MD_CTX'"); - return 0; - } + if (evp_md_ctx_rtype == NULL) + goto err; #endif return 1; + + err: + PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_MD_CTX'"); + return 0; } ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From adc780e8b1a2c9fd555f6435de851ed0ab609094 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 12:36:29 -0800 Subject: Revamp init_hmac_ctx() --- lib/crypto/c_src/hmac.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/crypto/c_src/hmac.c b/lib/crypto/c_src/hmac.c index 08d9049caa..a5ff35c706 100644 --- a/lib/crypto/c_src/hmac.c +++ b/lib/crypto/c_src/hmac.c @@ -37,11 +37,14 @@ int init_hmac_ctx(ErlNifEnv *env) { (ErlNifResourceDtor*) hmac_context_dtor, ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER, NULL); - if (hmac_context_rtype == NULL) { - PRINTF_ERR0("CRYPTO: Could not open resource type 'hmac_context'"); - return 0; - } + if (hmac_context_rtype == NULL) + goto err; + return 1; + + err: + PRINTF_ERR0("CRYPTO: Could not open resource type 'hmac_context'"); + return 0; } ERL_NIF_TERM hmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From d28469e30e4ceb6df579eefb7ae6e637b29b2616 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 12:37:44 -0800 Subject: Revamp test_init() --- lib/crypto/c_src/otp_test_engine.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c index 2c8cce094e..59a2287e6c 100644 --- a/lib/crypto/c_src/otp_test_engine.c +++ b/lib/crypto/c_src/otp_test_engine.c @@ -87,13 +87,12 @@ static int test_init(ENGINE *e) { printf("OTP Test Engine Initializatzion!\r\n"); #if defined(FAKE_RSA_IMPL) - if ( !RSA_meth_set_finish(test_rsa_method, test_rsa_free) - || !RSA_meth_set_sign(test_rsa_method, test_rsa_sign) - || !RSA_meth_set_verify(test_rsa_method, test_rsa_verify) - ) { - fprintf(stderr, "Setup RSA_METHOD failed\r\n"); - return 0; - } + if (!RSA_meth_set_finish(test_rsa_method, test_rsa_free)) + goto err; + if (!RSA_meth_set_sign(test_rsa_method, test_rsa_sign)) + goto err; + if (!RSA_meth_set_verify(test_rsa_method, test_rsa_verify)) + goto err; #endif /* if defined(FAKE_RSA_IMPL) */ /* Load all digest and cipher algorithms. Needed for password protected private keys */ @@ -101,6 +100,10 @@ static int test_init(ENGINE *e) { OpenSSL_add_all_digests(); return 111; + + err: + fprintf(stderr, "Setup RSA_METHOD failed\r\n"); + return 0; } static void add_test_data(unsigned char *md, unsigned int len) -- cgit v1.2.3 From 42adba07051941d0093c34044d4d25159edf70ba Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 12:38:13 -0800 Subject: Revamp test_engine_md5_final() --- lib/crypto/c_src/otp_test_engine.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c index 59a2287e6c..94f88fed79 100644 --- a/lib/crypto/c_src/otp_test_engine.c +++ b/lib/crypto/c_src/otp_test_engine.c @@ -155,15 +155,15 @@ static int test_engine_md5_update(EVP_MD_CTX *ctx,const void *data, size_t count static int test_engine_md5_final(EVP_MD_CTX *ctx,unsigned char *md) { #ifdef OLD - int ret; - fprintf(stderr, "MD5 final size of EVP_MD: %lu\r\n", sizeof(EVP_MD)); - ret = MD5_Final(md, data(ctx)); + if (!MD5_Final(md, data(ctx))) + goto err; - if (ret > 0) { - add_test_data(md, MD5_DIGEST_LENGTH); - } - return ret; + add_test_data(md, MD5_DIGEST_LENGTH); + return 1; + + err: + return 0; #else fprintf(stderr, "MD5 final\r\n"); add_test_data(md, MD5_DIGEST_LENGTH); -- cgit v1.2.3 From 10daa24171419ae740afc00342832d434fc8d3ff Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 12:39:32 -0800 Subject: Revamp test_engine_digest_selector() --- lib/crypto/c_src/otp_test_engine.c | 55 ++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c index 94f88fed79..59fd61bee2 100644 --- a/lib/crypto/c_src/otp_test_engine.c +++ b/lib/crypto/c_src/otp_test_engine.c @@ -193,7 +193,6 @@ static int test_digest_ids[] = {NID_md5}; static int test_engine_digest_selector(ENGINE *e, const EVP_MD **digest, const int **nids, int nid) { - int ok = 1; if (!digest) { *nids = test_digest_ids; fprintf(stderr, "Digest is empty! Nid:%d\r\n", nid); @@ -204,33 +203,43 @@ static int test_engine_digest_selector(ENGINE *e, const EVP_MD **digest, #ifdef OLD *digest = &test_engine_md5_method; #else - EVP_MD *md = EVP_MD_meth_new(NID_md5, NID_undef); - if (!md || - !EVP_MD_meth_set_result_size(md, MD5_DIGEST_LENGTH) || - !EVP_MD_meth_set_flags(md, 0) || - !EVP_MD_meth_set_init(md, test_engine_md5_init) || - !EVP_MD_meth_set_update(md, test_engine_md5_update) || - !EVP_MD_meth_set_final(md, test_engine_md5_final) || - !EVP_MD_meth_set_copy(md, NULL) || - !EVP_MD_meth_set_cleanup(md, NULL) || - !EVP_MD_meth_set_input_blocksize(md, MD5_CBLOCK) || - !EVP_MD_meth_set_app_datasize(md, sizeof(EVP_MD *) + sizeof(MD5_CTX)) || - !EVP_MD_meth_set_ctrl(md, NULL)) - { - ok = 0; - *digest = NULL; - } else - { - *digest = md; - } + EVP_MD *md; + + if ((md = EVP_MD_meth_new(NID_md5, NID_undef)) == NULL) + goto err; + if (EVP_MD_meth_set_result_size(md, MD5_DIGEST_LENGTH) != 1) + goto err; + if (EVP_MD_meth_set_flags(md, 0) != 1) + goto err; + if (EVP_MD_meth_set_init(md, test_engine_md5_init) != 1) + goto err; + if (EVP_MD_meth_set_update(md, test_engine_md5_update) != 1) + goto err; + if (EVP_MD_meth_set_final(md, test_engine_md5_final) != 1) + goto err; + if (EVP_MD_meth_set_copy(md, NULL) != 1) + goto err; + if (EVP_MD_meth_set_cleanup(md, NULL) != 1) + goto err; + if (EVP_MD_meth_set_input_blocksize(md, MD5_CBLOCK) != 1) + goto err; + if (EVP_MD_meth_set_app_datasize(md, sizeof(EVP_MD *) + sizeof(MD5_CTX)) != 1) + goto err; + if (EVP_MD_meth_set_ctrl(md, NULL) != 1) + goto err; + + *digest = md; #endif } else { - ok = 0; - *digest = NULL; + goto err; } - return ok; + return 1; + + err: + *digest = NULL; + return 0; } static int bind_helper(ENGINE * e, const char *id) -- cgit v1.2.3 From bd895dd8f486dd740a267436b04e96a75a70f510 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 12:40:02 -0800 Subject: Revamp bind_helper() --- lib/crypto/c_src/otp_test_engine.c | 42 +++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c index 59fd61bee2..014a1055c4 100644 --- a/lib/crypto/c_src/otp_test_engine.c +++ b/lib/crypto/c_src/otp_test_engine.c @@ -245,32 +245,40 @@ static int test_engine_digest_selector(ENGINE *e, const EVP_MD **digest, static int bind_helper(ENGINE * e, const char *id) { #if defined(FAKE_RSA_IMPL) - test_rsa_method = RSA_meth_new("OTP test RSA method", 0); - if (test_rsa_method == NULL) { + if ((test_rsa_method = RSA_meth_new("OTP test RSA method", 0)) == NULL) { fprintf(stderr, "RSA_meth_new failed\r\n"); - return 0; + goto err; } #endif /* if defined(FAKE_RSA_IMPL) */ - if (!ENGINE_set_id(e, test_engine_id) - || !ENGINE_set_name(e, test_engine_name) - || !ENGINE_set_init_function(e, test_init) - || !ENGINE_set_digests(e, &test_engine_digest_selector) - /* For testing of key storage in an Engine: */ - || !ENGINE_set_load_privkey_function(e, &test_privkey_load) - || !ENGINE_set_load_pubkey_function(e, &test_pubkey_load) - ) - return 0; + if (!ENGINE_set_id(e, test_engine_id)) + goto err; + if (!ENGINE_set_name(e, test_engine_name)) + goto err; + if (!ENGINE_set_init_function(e, test_init)) + goto err; + if (!ENGINE_set_digests(e, &test_engine_digest_selector)) + goto err; + /* For testing of key storage in an Engine: */ + if (!ENGINE_set_load_privkey_function(e, &test_privkey_load)) + goto err; + if (!ENGINE_set_load_pubkey_function(e, &test_pubkey_load)) + goto err; #if defined(FAKE_RSA_IMPL) - if ( !ENGINE_set_RSA(e, test_rsa_method) ) { - RSA_meth_free(test_rsa_method); - test_rsa_method = NULL; - return 0; - } + if (!ENGINE_set_RSA(e, test_rsa_method)) + goto err; #endif /* if defined(FAKE_RSA_IMPL) */ return 1; + + err: +#if defined(FAKE_RSA_IMPL) + if (test_rsa_method) + RSA_meth_free(test_rsa_method); + test_rsa_method = NULL; +#endif + return 0; } IMPLEMENT_DYNAMIC_CHECK_FN(); -- cgit v1.2.3 From 3db8a92c7ebb057574b65ac7ce041319da5d59a0 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 13:40:05 -0800 Subject: Revamp CONSUME_REDS() --- lib/crypto/c_src/openssl_config.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/crypto/c_src/openssl_config.h b/lib/crypto/c_src/openssl_config.h index e41d0c945e..7ea8c320ae 100644 --- a/lib/crypto/c_src/openssl_config.h +++ b/lib/crypto/c_src/openssl_config.h @@ -308,11 +308,16 @@ #define MAX_BYTES_TO_NIF 20000 #define CONSUME_REDS(NifEnv, Ibin) \ -do { \ - int _cost = ((Ibin).size * 100) / MAX_BYTES_TO_NIF;\ +do { \ + size_t _cost = (Ibin).size; \ + if (_cost > SIZE_MAX / 100) \ + _cost = 100; \ + else \ + _cost = (_cost * 100) / MAX_BYTES_TO_NIF; \ + \ if (_cost) { \ (void) enif_consume_timeslice((NifEnv), \ - (_cost > 100) ? 100 : _cost); \ + (_cost > 100) ? 100 : (int)_cost); \ } \ } while (0) -- cgit v1.2.3 From 5f8f5ea331fac053ae6ffeaa50dc3cf816cc3074 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 13:40:34 -0800 Subject: Revamp test_key_load() --- lib/crypto/c_src/otp_test_engine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c index 014a1055c4..3b228b8663 100644 --- a/lib/crypto/c_src/otp_test_engine.c +++ b/lib/crypto/c_src/otp_test_engine.c @@ -324,7 +324,7 @@ EVP_PKEY* test_key_load(ENGINE *eng, const char *id, UI_METHOD *ui_method, void fprintf(stderr, "Contents of file \"%s\":\r\n",id); f = fopen(id, "r"); { /* Print the contents of the key file */ - char c; + int c; while (!feof(f)) { switch (c=fgetc(f)) { case '\n': -- cgit v1.2.3 From 89d0f344ae30864a626a3af9db7953af8f38f499 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 13:40:58 -0800 Subject: Revamp pem_passwd_cb_fun() --- lib/crypto/c_src/otp_test_engine.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c index 3b228b8663..d0d4f7741d 100644 --- a/lib/crypto/c_src/otp_test_engine.c +++ b/lib/crypto/c_src/otp_test_engine.c @@ -21,8 +21,10 @@ #ifdef _WIN32 #define OPENSSL_OPT_WINDLL #endif + #include #include +#include #include #include @@ -344,23 +346,28 @@ EVP_PKEY* test_key_load(ENGINE *eng, const char *id, UI_METHOD *ui_method, void int pem_passwd_cb_fun(char *buf, int size, int rwflag, void *password) { - int i; + size_t i; + + if (size < 0) + return 0; fprintf(stderr, "In pem_passwd_cb_fun\r\n"); if (!password) return 0; i = strlen(password); - if (i < size) { - /* whole pwd (incl terminating 0) fits */ - fprintf(stderr, "Got FULL pwd %d(%d) chars\r\n", i, size); - memcpy(buf, (char*)password, i+1); - return i+1; - } else { - fprintf(stderr, "Got TO LONG pwd %d(%d) chars\r\n", i, size); - /* meaningless with a truncated password */ - return 0; - } + if (i >= (size_t)size || i > INT_MAX - 1) + goto err; + + /* whole pwd (incl terminating 0) fits */ + fprintf(stderr, "Got FULL pwd %zu(%d) chars\r\n", i, size); + memcpy(buf, (char*)password, i+1); + return (int)i+1; + + err: + fprintf(stderr, "Got TO LONG pwd %zu(%d) chars\r\n", i, size); + /* meaningless with a truncated password */ + return 0; } #endif -- cgit v1.2.3 From 30c7fa8f5a6b7874d5ab144665bb560f2c89e9a1 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 13:41:23 -0800 Subject: Revamp fake_flag so it's static --- lib/crypto/c_src/otp_test_engine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c index d0d4f7741d..26a64161dc 100644 --- a/lib/crypto/c_src/otp_test_engine.c +++ b/lib/crypto/c_src/otp_test_engine.c @@ -376,7 +376,7 @@ int pem_passwd_cb_fun(char *buf, int size, int rwflag, void *password) /* RSA sign. This returns a fixed string so the test case can test that it was called instead of the cryptolib default RSA sign */ -unsigned char fake_flag[] = {255,3,124,180,35,10,180,151,101,247,62,59,80,122,220, +static unsigned char fake_flag[] = {255,3,124,180,35,10,180,151,101,247,62,59,80,122,220, 142,24,180,191,34,51,150,112,27,43,142,195,60,245,213,80,179}; int test_rsa_sign(int dtype, -- cgit v1.2.3 From f03e582f0cdc2518ecd3b231c721d45b48381fed Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 13:42:34 -0800 Subject: Revamp test_rsa_sign() --- lib/crypto/c_src/otp_test_engine.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c index 26a64161dc..f971dbc3ca 100644 --- a/lib/crypto/c_src/otp_test_engine.c +++ b/lib/crypto/c_src/otp_test_engine.c @@ -387,11 +387,10 @@ int test_rsa_sign(int dtype, /* The key */ const RSA *rsa) { - int slen; fprintf(stderr, "test_rsa_sign (dtype=%i) called m_len=%u *siglen=%u\r\n", dtype, m_len, *siglen); if (!sigret) { fprintf(stderr, "sigret = NULL\r\n"); - return -1; + goto err; } /* {int i; @@ -403,14 +402,20 @@ int test_rsa_sign(int dtype, if ((sizeof(fake_flag) == m_len) && bcmp(m,fake_flag,m_len) == 0) { + int slen; + printf("To be faked\r\n"); /* To be faked */ - slen = RSA_size(rsa); - add_test_data(sigret, slen); /* The signature is 0,1,2...255,0,1... */ - *siglen = slen; /* Must set this. Why? */ + if ((slen = RSA_size(rsa)) < 0) + goto err; + add_test_data(sigret, (unsigned int)slen); /* The signature is 0,1,2...255,0,1... */ + *siglen = (unsigned int)slen; /* Must set this. Why? */ return 1; /* 1 = success */ } return 0; + + err: + return -1; } int test_rsa_verify(int dtype, -- cgit v1.2.3 From 85e979749ad60c7c3ddd160ca2673a8bf8a581e7 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 13:42:54 -0800 Subject: Revamp test_rsa_verify() --- lib/crypto/c_src/otp_test_engine.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c index f971dbc3ca..4557eaa877 100644 --- a/lib/crypto/c_src/otp_test_engine.c +++ b/lib/crypto/c_src/otp_test_engine.c @@ -430,8 +430,13 @@ int test_rsa_verify(int dtype, if ((sizeof(fake_flag) == m_len) && bcmp(m,fake_flag,m_len) == 0) { + int size; + + if ((size = RSA_size(rsa)) < 0) + return 0; + printf("To be faked\r\n"); - return (siglen == RSA_size(rsa)) + return (siglen == (unsigned int)size) && chk_test_data(sigret, siglen); } return 0; -- cgit v1.2.3 From 0b1fda0dc6b11b0d20b6254b0e8ad155c96232e9 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 13:48:41 -0800 Subject: Initialize all fields for ErlNifFunc in nif_funcs --- lib/crypto/c_src/crypto.c | 140 +++++++++++++++++++++++----------------------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index d1ff551172..03f11c9059 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -62,76 +62,76 @@ static int library_refc = 0; /* number of users of this dynamic library */ static int library_initialized = 0; static ErlNifFunc nif_funcs[] = { - {"info_lib", 0, info_lib}, - {"info_fips", 0, info_fips}, - {"enable_fips_mode", 1, enable_fips_mode}, - {"algorithms", 0, algorithms}, - {"hash_nif", 2, hash_nif}, - {"hash_init_nif", 1, hash_init_nif}, - {"hash_update_nif", 2, hash_update_nif}, - {"hash_final_nif", 1, hash_final_nif}, - {"hmac_nif", 3, hmac_nif}, - {"hmac_nif", 4, hmac_nif}, - {"hmac_init_nif", 2, hmac_init_nif}, - {"hmac_update_nif", 2, hmac_update_nif}, - {"hmac_final_nif", 1, hmac_final_nif}, - {"hmac_final_nif", 2, hmac_final_nif}, - {"cmac_nif", 3, cmac_nif}, - {"block_crypt_nif", 5, block_crypt_nif}, - {"block_crypt_nif", 4, block_crypt_nif}, - {"aes_ige_crypt_nif", 4, aes_ige_crypt_nif}, - {"aes_ctr_stream_init", 2, aes_ctr_stream_init}, - {"aes_ctr_stream_encrypt", 2, aes_ctr_stream_encrypt}, - {"aes_ctr_stream_decrypt", 2, aes_ctr_stream_encrypt}, - {"strong_rand_bytes_nif", 1, strong_rand_bytes_nif}, - {"strong_rand_range_nif", 1, strong_rand_range_nif}, - {"rand_uniform_nif", 2, rand_uniform_nif}, - {"mod_exp_nif", 4, mod_exp_nif}, - {"do_exor", 2, do_exor}, - {"rc4_set_key", 1, rc4_set_key}, - {"rc4_encrypt_with_state", 2, rc4_encrypt_with_state}, - {"pkey_sign_nif", 5, pkey_sign_nif}, - {"pkey_verify_nif", 6, pkey_verify_nif}, - {"pkey_crypt_nif", 6, pkey_crypt_nif}, - {"rsa_generate_key_nif", 2, rsa_generate_key_nif}, - {"dh_generate_key_nif", 4, dh_generate_key_nif}, - {"dh_compute_key_nif", 3, dh_compute_key_nif}, - {"evp_compute_key_nif", 3, evp_compute_key_nif}, - {"evp_generate_key_nif", 1, evp_generate_key_nif}, - {"privkey_to_pubkey_nif", 2, privkey_to_pubkey_nif}, - {"srp_value_B_nif", 5, srp_value_B_nif}, - {"srp_user_secret_nif", 7, srp_user_secret_nif}, - {"srp_host_secret_nif", 5, srp_host_secret_nif}, - - {"ec_key_generate", 2, ec_key_generate}, - {"ecdh_compute_key_nif", 3, ecdh_compute_key_nif}, - - {"rand_seed_nif", 1, rand_seed_nif}, - - {"aead_encrypt", 6, aead_encrypt}, - {"aead_decrypt", 6, aead_decrypt}, - - {"chacha20_stream_init", 2, chacha20_stream_init}, - {"chacha20_stream_encrypt", 2, chacha20_stream_crypt}, - {"chacha20_stream_decrypt", 2, chacha20_stream_crypt}, - - {"poly1305_nif", 2, poly1305_nif}, - - {"engine_by_id_nif", 1, engine_by_id_nif}, - {"engine_init_nif", 1, engine_init_nif}, - {"engine_finish_nif", 1, engine_finish_nif}, - {"engine_free_nif", 1, engine_free_nif}, - {"engine_load_dynamic_nif", 0, engine_load_dynamic_nif}, - {"engine_ctrl_cmd_strings_nif", 3, engine_ctrl_cmd_strings_nif}, - {"engine_register_nif", 2, engine_register_nif}, - {"engine_unregister_nif", 2, engine_unregister_nif}, - {"engine_add_nif", 1, engine_add_nif}, - {"engine_remove_nif", 1, engine_remove_nif}, - {"engine_get_first_nif", 0, engine_get_first_nif}, - {"engine_get_next_nif", 1, engine_get_next_nif}, - {"engine_get_id_nif", 1, engine_get_id_nif}, - {"engine_get_name_nif", 1, engine_get_name_nif}, - {"engine_get_all_methods_nif", 0, engine_get_all_methods_nif} + {"info_lib", 0, info_lib, 0}, + {"info_fips", 0, info_fips, 0}, + {"enable_fips_mode", 1, enable_fips_mode, 0}, + {"algorithms", 0, algorithms, 0}, + {"hash_nif", 2, hash_nif, 0}, + {"hash_init_nif", 1, hash_init_nif, 0}, + {"hash_update_nif", 2, hash_update_nif, 0}, + {"hash_final_nif", 1, hash_final_nif, 0}, + {"hmac_nif", 3, hmac_nif, 0}, + {"hmac_nif", 4, hmac_nif, 0}, + {"hmac_init_nif", 2, hmac_init_nif, 0}, + {"hmac_update_nif", 2, hmac_update_nif, 0}, + {"hmac_final_nif", 1, hmac_final_nif, 0}, + {"hmac_final_nif", 2, hmac_final_nif, 0}, + {"cmac_nif", 3, cmac_nif, 0}, + {"block_crypt_nif", 5, block_crypt_nif, 0}, + {"block_crypt_nif", 4, block_crypt_nif, 0}, + {"aes_ige_crypt_nif", 4, aes_ige_crypt_nif, 0}, + {"aes_ctr_stream_init", 2, aes_ctr_stream_init, 0}, + {"aes_ctr_stream_encrypt", 2, aes_ctr_stream_encrypt, 0}, + {"aes_ctr_stream_decrypt", 2, aes_ctr_stream_encrypt, 0}, + {"strong_rand_bytes_nif", 1, strong_rand_bytes_nif, 0}, + {"strong_rand_range_nif", 1, strong_rand_range_nif, 0}, + {"rand_uniform_nif", 2, rand_uniform_nif, 0}, + {"mod_exp_nif", 4, mod_exp_nif, 0}, + {"do_exor", 2, do_exor, 0}, + {"rc4_set_key", 1, rc4_set_key, 0}, + {"rc4_encrypt_with_state", 2, rc4_encrypt_with_state, 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}, + {"rsa_generate_key_nif", 2, rsa_generate_key_nif, 0}, + {"dh_generate_key_nif", 4, dh_generate_key_nif, 0}, + {"dh_compute_key_nif", 3, dh_compute_key_nif, 0}, + {"evp_compute_key_nif", 3, evp_compute_key_nif, 0}, + {"evp_generate_key_nif", 1, evp_generate_key_nif, 0}, + {"privkey_to_pubkey_nif", 2, privkey_to_pubkey_nif, 0}, + {"srp_value_B_nif", 5, srp_value_B_nif, 0}, + {"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}, + {"ecdh_compute_key_nif", 3, ecdh_compute_key_nif, 0}, + + {"rand_seed_nif", 1, rand_seed_nif, 0}, + + {"aead_encrypt", 6, aead_encrypt, 0}, + {"aead_decrypt", 6, aead_decrypt, 0}, + + {"chacha20_stream_init", 2, chacha20_stream_init, 0}, + {"chacha20_stream_encrypt", 2, chacha20_stream_crypt, 0}, + {"chacha20_stream_decrypt", 2, chacha20_stream_crypt, 0}, + + {"poly1305_nif", 2, poly1305_nif, 0}, + + {"engine_by_id_nif", 1, engine_by_id_nif, 0}, + {"engine_init_nif", 1, engine_init_nif, 0}, + {"engine_finish_nif", 1, engine_finish_nif, 0}, + {"engine_free_nif", 1, engine_free_nif, 0}, + {"engine_load_dynamic_nif", 0, engine_load_dynamic_nif, 0}, + {"engine_ctrl_cmd_strings_nif", 3, engine_ctrl_cmd_strings_nif, 0}, + {"engine_register_nif", 2, engine_register_nif, 0}, + {"engine_unregister_nif", 2, engine_unregister_nif, 0}, + {"engine_add_nif", 1, engine_add_nif, 0}, + {"engine_remove_nif", 1, engine_remove_nif, 0}, + {"engine_get_first_nif", 0, engine_get_first_nif, 0}, + {"engine_get_next_nif", 1, engine_get_next_nif, 0}, + {"engine_get_id_nif", 1, engine_get_id_nif, 0}, + {"engine_get_name_nif", 1, engine_get_name_nif, 0}, + {"engine_get_all_methods_nif", 0, engine_get_all_methods_nif, 0} }; -- cgit v1.2.3 From 6adfb6fad528c5f716a9186f95959b468652ba1d Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 13:52:59 -0800 Subject: Explicitly initialize all of the fields in cipher_types --- lib/crypto/c_src/cipher.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/crypto/c_src/cipher.c b/lib/crypto/c_src/cipher.c index 175d927ef5..5d306b80dd 100644 --- a/lib/crypto/c_src/cipher.c +++ b/lib/crypto/c_src/cipher.c @@ -34,40 +34,40 @@ static struct cipher_type_t cipher_types[] = #else {NULL} #endif - }, - {{"des_cbc"}, {COND_NO_DES_PTR(&EVP_des_cbc)}}, - {{"des_cfb"}, {COND_NO_DES_PTR(&EVP_des_cfb8)}}, - {{"des_ecb"}, {COND_NO_DES_PTR(&EVP_des_ecb)}}, - {{"des_ede3_cbc"}, {COND_NO_DES_PTR(&EVP_des_ede3_cbc)}}, + ,0}, + {{"des_cbc"}, {COND_NO_DES_PTR(&EVP_des_cbc)}, 0}, + {{"des_cfb"}, {COND_NO_DES_PTR(&EVP_des_cfb8)}, 0}, + {{"des_ecb"}, {COND_NO_DES_PTR(&EVP_des_ecb)}, 0}, + {{"des_ede3_cbc"}, {COND_NO_DES_PTR(&EVP_des_ede3_cbc)}, 0}, {{"des_ede3_cbf"}, /* Misspelled, retained */ #ifdef HAVE_DES_ede3_cfb_encrypt {COND_NO_DES_PTR(&EVP_des_ede3_cfb8)} #else {NULL} #endif - }, + ,0}, {{"des_ede3_cfb"}, #ifdef HAVE_DES_ede3_cfb_encrypt {COND_NO_DES_PTR(&EVP_des_ede3_cfb8)} #else {NULL} #endif - }, - {{"blowfish_cbc"}, {&EVP_bf_cbc}}, - {{"blowfish_cfb64"}, {&EVP_bf_cfb64}}, - {{"blowfish_ofb64"}, {&EVP_bf_ofb}}, - {{"blowfish_ecb"}, {&EVP_bf_ecb}}, + ,0}, + {{"blowfish_cbc"}, {&EVP_bf_cbc}, 0}, + {{"blowfish_cfb64"}, {&EVP_bf_cfb64}, 0}, + {{"blowfish_ofb64"}, {&EVP_bf_ofb}, 0}, + {{"blowfish_ecb"}, {&EVP_bf_ecb}, 0}, {{"aes_cbc"}, {&EVP_aes_128_cbc}, 16}, {{"aes_cbc"}, {&EVP_aes_192_cbc}, 24}, {{"aes_cbc"}, {&EVP_aes_256_cbc}, 32}, - {{"aes_cbc128"}, {&EVP_aes_128_cbc}}, - {{"aes_cbc256"}, {&EVP_aes_256_cbc}}, - {{"aes_cfb8"}, {&EVP_aes_128_cfb8}}, - {{"aes_cfb128"}, {&EVP_aes_128_cfb128}}, + {{"aes_cbc128"}, {&EVP_aes_128_cbc}, 0}, + {{"aes_cbc256"}, {&EVP_aes_256_cbc}, 0}, + {{"aes_cfb8"}, {&EVP_aes_128_cfb8}, 0}, + {{"aes_cfb128"}, {&EVP_aes_128_cfb128}, 0}, {{"aes_ecb"}, {&EVP_aes_128_ecb}, 16}, {{"aes_ecb"}, {&EVP_aes_192_ecb}, 24}, {{"aes_ecb"}, {&EVP_aes_256_ecb}, 32}, - {{NULL}} + {{NULL},{NULL},0} }; #ifdef HAVE_EVP_AES_CTR -- cgit v1.2.3 From 5d74968a66fa50d5f813ece1e52b7f4fa1c29765 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 5 Jan 2019 13:53:27 -0800 Subject: Explicitly set all of the fields in digest_types --- lib/crypto/c_src/digest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/crypto/c_src/digest.c b/lib/crypto/c_src/digest.c index 9e6199030d..00ba65bf54 100644 --- a/lib/crypto/c_src/digest.c +++ b/lib/crypto/c_src/digest.c @@ -83,7 +83,7 @@ static struct digest_type_t digest_types[] = #endif }, - {{NULL}} + {{NULL}, {NULL}} }; void init_digest_types(ErlNifEnv* env) -- cgit v1.2.3 From 2451a8156b3e612ecdd95aa25c1d0c3d894a682b Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 19:19:47 -0800 Subject: Convert put_int32 to put_uint32 --- lib/crypto/c_src/bn.c | 2 +- lib/crypto/c_src/dh.c | 4 ++-- lib/crypto/c_src/openssl_config.h | 10 +++++----- lib/crypto/c_src/rand.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/crypto/c_src/bn.c b/lib/crypto/c_src/bn.c index ef69c84679..d884a75f80 100644 --- a/lib/crypto/c_src/bn.c +++ b/lib/crypto/c_src/bn.c @@ -133,7 +133,7 @@ ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) goto err; if (bin_hdr) { - put_int32(ptr, extra_byte + (unsigned int)dlen); + put_uint32(ptr, extra_byte + (unsigned int)dlen); ptr[4] = 0; /* extra zeroed byte to ensure a positive mpint */ ptr += bin_hdr + extra_byte; } diff --git a/lib/crypto/c_src/dh.c b/lib/crypto/c_src/dh.c index e3b5b11e9c..bb87080d7b 100644 --- a/lib/crypto/c_src/dh.c +++ b/lib/crypto/c_src/dh.c @@ -140,10 +140,10 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar goto err; if (mpint) { - put_int32(pub_ptr, pub_len); + put_uint32(pub_ptr, (unsigned int)pub_len); pub_ptr += 4; - put_int32(prv_ptr, prv_len); + put_uint32(prv_ptr, (unsigned int)prv_len); prv_ptr += 4; } diff --git a/lib/crypto/c_src/openssl_config.h b/lib/crypto/c_src/openssl_config.h index 7ea8c320ae..65290cdfdf 100644 --- a/lib/crypto/c_src/openssl_config.h +++ b/lib/crypto/c_src/openssl_config.h @@ -296,11 +296,11 @@ (((unsigned char*) (s))[2] << 8) | \ (((unsigned char*) (s))[3])) -#define put_int32(s,i) \ -{ (s)[0] = (char)(((i) >> 24) & 0xff);\ - (s)[1] = (char)(((i) >> 16) & 0xff);\ - (s)[2] = (char)(((i) >> 8) & 0xff);\ - (s)[3] = (char)((i) & 0xff);\ +#define put_uint32(s,i) \ +{ (s)[0] = (unsigned char)(((i) >> 24) & 0xff);\ + (s)[1] = (unsigned char)(((i) >> 16) & 0xff);\ + (s)[2] = (unsigned char)(((i) >> 8) & 0xff);\ + (s)[3] = (unsigned char)((i) & 0xff);\ } /* This shall correspond to the similar macro in crypto.erl */ diff --git a/lib/crypto/c_src/rand.c b/lib/crypto/c_src/rand.c index 12e0a53493..cf793a7aac 100644 --- a/lib/crypto/c_src/rand.c +++ b/lib/crypto/c_src/rand.c @@ -111,7 +111,7 @@ ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ if ((data = enif_make_new_binary(env, (size_t)dlen+4, &ret)) == NULL) goto err; - put_int32(data, dlen); + put_uint32(data, (unsigned int)dlen); BN_bn2bin(bn_rand, data+4); ERL_VALGRIND_MAKE_MEM_DEFINED(data+4, dlen); goto done; -- cgit v1.2.3 From bc83ebbc2a34def8ffad02ddf2a4976e408c5e31 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Tue, 8 Jan 2019 01:51:13 -0800 Subject: Add Coccinelle scripts that I used to verify API calls --- lib/crypto/c_src/check_erlang.cocci | 174 ++++++++++++++++++++++ lib/crypto/c_src/check_openssl.cocci | 281 +++++++++++++++++++++++++++++++++++ 2 files changed, 455 insertions(+) create mode 100644 lib/crypto/c_src/check_erlang.cocci create mode 100644 lib/crypto/c_src/check_openssl.cocci diff --git a/lib/crypto/c_src/check_erlang.cocci b/lib/crypto/c_src/check_erlang.cocci new file mode 100644 index 0000000000..bdb99d5bb0 --- /dev/null +++ b/lib/crypto/c_src/check_erlang.cocci @@ -0,0 +1,174 @@ +// %CopyrightBegin% +// +// Copyright Doug Hogan 2019. 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% + +// Coccinelle script to help verify Erlang calls. +// http://coccinelle.lip6.fr +// https://github.com/coccinelle/coccinelle +// +// These work with the Erlang code because it has a rigid coding pattern. +// $ spatch.opt --all-includes -sp_file check_erlang.cocci -dir . + +// Make sure resources are cleaned up properly in all paths. +// Need 'strict' so it's also checked in error handling paths. +@enif_alloc_resource@ +type T; +identifier CTX, L; +identifier virtual.enif_alloc_resource, virtual.enif_release_resource; +position p; +@@ + + T *CTX = NULL; + + ... + if ((CTX = enif_alloc_resource(...)@p) == NULL) + goto L; + + ... when strict, forall + enif_release_resource(CTX) + + +// After calling enif_alloc_binary(), you must either release it with +// enif_release_binary() or transfer ownership to Erlang via enif_make_binary(). +@enif_alloc_binary@ +expression SZ; +identifier BIN, RET, ENV, X, L; +identifier TUPLE =~ "^enif_make_tuple[0-9]+$"; +identifier virtual.enif_alloc_binary, virtual.enif_make_binary; +identifier virtual.enif_release_binary; +position pa, pm, pr; +@@ + +// This construct is used in engine.c +( + if (!enif_alloc_binary(SZ, &BIN)@pa) + goto L; + + ... when strict, forall + return +( + enif_make_binary(ENV, &BIN)@pm +| + TUPLE(..., enif_make_binary(ENV, &BIN)@pm)@pm +); + +| +// This is the typical way we allocate and use binaries. + int X = 0; + + ... + if (!enif_alloc_binary(SZ, &BIN)@pa) + goto L; + X = 1; + + ... when strict, forall +( + RET = enif_make_binary(ENV, &BIN)@pm; + X = 0; +| + if (X) + enif_release_binary(&BIN)@pr; +| + return enif_make_binary(ENV, &BIN)@pm; +) +) + +// TODO: These don't have single checks that handle all cases. +// +// enif_consume_timeslice returns 1 if exhausted or else 0 +// enif_has_pending_exception returns true if exception pending + +@erlang_check_void@ +identifier FUNCVOID =~ "^(enif_free|enif_mutex_destroy|enif_mutex_lock|enif_mutex_unlock|enif_release_binary|enif_release_resource|enif_rwlock_destroy|enif_rwlock_rlock|enif_rwlock_runlock|enif_rwlock_rwlock|enif_rwlock_rwunlock|enif_system_info)$"; +position p; +@@ + + FUNCVOID(...)@p; + + +@erlang_check_null@ +expression X; +identifier L; +identifier FUNCNULL =~ "^(enif_alloc|enif_alloc_resource|enif_dlopen|enif_dlsym|enif_make_new_binary|enif_mutex_create|enif_open_resource_type|enif_realloc|enif_rwlock_create)$"; +position p; +@@ + +( + if ((X = FUNCNULL(...)@p) == NULL) + goto L; +| + X = FUNCNULL(...)@p; + if (X == NULL) + goto L; +| + return FUNCNULL(...)@p; +) + + +@erlang_check_not@ +identifier L; +identifier FUNCNOT =~ "^(enif_alloc_binary|enif_get_int|enif_get_list_cell|enif_get_list_length|enif_get_long|enif_get_map_value|enif_get_resource|enif_get_tuple|enif_get_uint|enif_get_ulong|enif_inspect_binary|enif_inspect_iolist_as_binary|enif_is_atom|enif_is_binary|enif_is_current_process_alive|enif_is_empty_list|enif_is_list|enif_is_map|enif_is_tuple|enif_realloc_binary)$"; +position p; +@@ + +( + if (!FUNCNOT(...)@p) + goto L; +| + return FUNCNOT(...)@p; +) + + +@erlang_check_new@ +expression RET; +identifier FUNCNEW =~ "^(enif_make_atom|enif_make_badarg|enif_make_binary|enif_make_int|enif_make_list|enif_make_list_from_array|enif_make_resource|enif_make_tuple|enif_raise_exception|enif_schedule_nif|enif_thread_self)$"; +position p; +@@ + +( + RET = FUNCNEW(...)@p; +| + return FUNCNEW(...)@p; +) + + +// Flag any calls that aren't part of the above pattern. +@enif_alloc_not_free@ + +identifier FUNCVOID =~ "^(enif_free|enif_mutex_destroy|enif_mutex_lock|enif_mutex_unlock|enif_release_binary|enif_release_resource|enif_rwlock_destroy|enif_rwlock_rlock|enif_rwlock_runlock|enif_rwlock_rwlock|enif_rwlock_rwunlock|enif_system_info)$"; +position pvoid != {erlang_check_void.p,enif_alloc_binary.pr}; + +identifier FUNCNULL =~ "^(enif_alloc|enif_alloc_resource|enif_dlopen|enif_dlsym|enif_make_new_binary|enif_mutex_create|enif_open_resource_type|enif_realloc|enif_rwlock_create)$"; +position pnull != {erlang_check_null.p,enif_alloc_resource.p}; + +identifier FUNCNOT =~ "^(enif_alloc_binary|enif_get_int|enif_get_list_cell|enif_get_list_length|enif_get_long|enif_get_map_value|enif_get_resource|enif_get_tuple|enif_get_uint|enif_get_ulong|enif_inspect_binary|enif_inspect_iolist_as_binary|enif_is_atom|enif_is_binary|enif_is_current_process_alive|enif_is_empty_list|enif_is_list|enif_is_map|enif_is_tuple|enif_realloc_binary)$"; +position pnot != {erlang_check_not.p,enif_alloc_binary.pa}; + +identifier FUNCNEW =~ "^(enif_make_atom|enif_make_badarg|enif_make_binary|enif_make_int|enif_make_list|enif_make_list_from_array|enif_make_resource|enif_make_tuple|enif_raise_exception|enif_schedule_nif|enif_thread_self)$"; +position pnew != {erlang_check_new.p,enif_alloc_binary.pm}; + +@@ + +( +* FUNCVOID(...)@pvoid +| +* FUNCNULL(...)@pnull +| +* FUNCNOT(...)@pnot +| +* FUNCNEW(...)@pnew +) diff --git a/lib/crypto/c_src/check_openssl.cocci b/lib/crypto/c_src/check_openssl.cocci new file mode 100644 index 0000000000..75d1a6e44b --- /dev/null +++ b/lib/crypto/c_src/check_openssl.cocci @@ -0,0 +1,281 @@ +// %CopyrightBegin% +// +// Copyright Doug Hogan 2019. 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% + +// Coccinelle script to help verify the subset of OpenSSL calls used by Erlang. +// http://coccinelle.lip6.fr +// https://github.com/coccinelle/coccinelle +// +// These work with the Erlang code because it has a rigid coding pattern. +// $ spatch.opt --all-includes -sp_file check_openssl.cocci -dir . + +// TODO: These APIs may not have a single check that covers all cases +// or may not be necessary to check. +// +// BN_GENCB_get_arg +// BN_bn2bin +// BN_cmp +// BN_is_bit_set +// BN_is_negative +// BN_is_zero +// BN_num_bits +// DH_get0_key +// DH_size +// EC_GROUP_get_degree +// EC_KEY_get0_group +// EC_KEY_get0_private_key +// EC_KEY_get0_public_key +// EC_KEY_get_conv_form +// EVP_CIPHER_block_size +// EVP_CIPHER_iv_length +// EVP_CIPHER_type +// EVP_MD_CTX_md +// EVP_MD_size +// EVP_aes_128_cbc +// EVP_aes_128_ccm +// EVP_aes_128_cfb128 +// EVP_aes_128_cfb8 +// EVP_aes_128_ctr +// EVP_aes_128_ecb +// EVP_aes_128_gcm +// EVP_aes_192_cbc +// EVP_aes_192_ccm +// EVP_aes_192_ctr +// EVP_aes_192_ecb +// EVP_aes_192_gcm +// EVP_aes_256_cbc +// EVP_aes_256_ccm +// EVP_aes_256_ctr +// EVP_aes_256_ecb +// EVP_aes_256_gcm +// EVP_bf_cbc +// EVP_bf_cfb64 +// EVP_bf_ecb +// EVP_bf_ofb +// EVP_chacha20 +// EVP_chacha20_poly1305 +// EVP_des_cbc +// EVP_des_cfb8 +// EVP_des_ecb +// EVP_des_ede3_cbc +// EVP_des_ede3_cfb8 +// EVP_md4 +// EVP_md5 +// EVP_rc2_cbc +// EVP_ripemd160 +// EVP_sha1 +// EVP_sha224 +// EVP_sha256 +// EVP_sha384 +// EVP_sha3_224 +// EVP_sha3_256 +// EVP_sha3_384 +// EVP_sha3_512 +// EVP_sha512 +// OpenSSL_version +// OpenSSL_version_num +// PEM_read_PrivateKey +// PEM_read_PUBKEY +// RSA_size + +// Unusual API for OpenSSL: 0 or positive on success and negative value(s) on error. +@openssl_check_negative@ +identifier FUNCNEG =~ "^(DH_compute_key|RSA_padding_check_SSLv23)$"; +expression X; +identifier L; +position p; +@@ + + if ( +( + FUNCNEG(...)@p < 0 +| + (X = FUNCNEG(...)@p) < 0 +) + ) + goto L; + +// Unusual API for OpenSSL: positive on success or else error +@openssl_check_positive@ +identifier FUNCPOS =~ "^(ECDH_compute_key|EVP_CIPHER_asn1_to_param|EVP_CIPHER_param_to_asn1|EVP_PKEY_CTX_ctrl|RSA_pkey_ctx_ctrl)$"; +identifier L; +expression X; +position p; +@@ + + if ( +( + FUNCPOS(...)@p < 1 +| + (X = FUNCPOS(...)@p) < 1 +) + ) + goto L; + +// Unusual API for OpenSSL: 0=success. +@openssl_check_0@ +identifier L; +expression X; +identifier FUNC0 =~ "^(AES_set_decrypt_key|AES_set_encrypt_key|CRYPTO_gcm128_aad|CRYPTO_gcm128_decrypt|CRYPTO_gcm128_finish)$"; +position p; +@@ + + if ( +( + FUNC0(...)@p != 0 +| + (X = FUNC0(...)@p) != 0 +) + ) + goto L; + +// These do not necessarily allocate resources but they may return NULL. +@openssl_check_null@ +expression X; +identifier L; +identifier FUNCNULL =~ "^(BN_CTX_new|BN_GENCB_new|BN_MONT_CTX_new|BN_bin2bn|BN_dup|BN_generate_prime|BN_new|CMAC_CTX_new|CRYPTO_clear_realloc|CRYPTO_gcm128_new|CRYPTO_malloc|CRYPTO_realloc|CRYPTO_zalloc|DH_generate_parameters|DH_new|DSA_new|EC_GROUP_dup|EC_GROUP_get0_generator|EC_GROUP_method_of|EC_GROUP_new_curve_GFm|EC_GROUP_new_curve_GFp|EC_KEY_copy|EC_KEY_dup|EC_KEY_get0_engine|EC_KEY_new|EC_KEY_new_by_curve_name|EC_POINT_bn2point|EC_POINT_dup|EC_POINT_new|EC_POINT_point2bn|ENGINE_by_id|ENGINE_get_cipher_engine|ENGINE_get_default_DH|ENGINE_get_default_DSA|ENGINE_get_default_RAND|ENGINE_get_default_RSA|ENGINE_get_digest_engine|ENGINE_get_first|ENGINE_get_id|ENGINE_get_last|ENGINE_get_name|ENGINE_get_next|ENGINE_get_prev|ENGINE_load_private_key|ENGINE_load_public_key|ENGINE_new|EVP_CIPHER_CTX_new|EVP_MAC_CTX_new|EVP_MAC_CTX_new_id|EVP_MD_CTX_new|EVP_MD_meth_new|EVP_PKEY_CTX_new|EVP_PKEY_CTX_new_id|EVP_PKEY_get1_DH|EVP_PKEY_get1_DSA|EVP_PKEY_get1_EC_KEY|EVP_PKEY_get1_RSA|EVP_PKEY_new|EVP_PKEY_new_raw_private_key|EVP_PKEY_new_raw_public_key|EVP_get_cipherbyname|EVP_get_cipherbynid|EVP_get_cipherbyobj|EVP_get_macbyname|EVP_get_macbynid|EVP_get_macbyobj|HMAC|HMAC_CTX_new|OPENSSL_buf2hexstr|OPENSSL_clear_realloc|OPENSSL_hexstr2buf|OPENSSL_malloc|OPENSSL_realloc|OPENSSL_strdup|OPENSSL_strndup|OPENSSL_zalloc|RSA_meth_dup|RSA_meth_new|RSA_new)$"; +position p; +@@ + +( + if ((X = FUNCNULL(...)@p) == NULL) + goto L; +| + X = FUNCNULL(...)@p; + if (X == NULL) + goto L; +) + +// non-zero=success, 0=failure. These can be safely used with ! +@openssl_check_not@ +expression X; +identifier L; +identifier FUNCNOT =~ "^(BN_add|BN_div|BN_exp|BN_from_montgomery|BN_gcd|BN_generate_prime_ex|BN_mod|BN_mod_add|BN_mod_exp|BN_mod_mul|BN_mod_mul_montgomery|BN_mod_sqr|BN_mod_sub|BN_mul|BN_nnmod|BN_priv_rand|BN_priv_rand_range|BN_pseudo_rand|BN_pseudo_rand_range|BN_rand|BN_rand_range|BN_set_bit|BN_set_word|BN_sqr|BN_sub|BN_to_montgomery|CMAC_Final|CMAC_Init|CMAC_Update|CRYPTO_set_mem_debug|CRYPTO_set_mem_functions|DH_check|DH_check_ex|DH_check_params|DH_check_pub_key_ex|DH_generate_key|DH_generate_parameters_ex|DH_set0_key|DH_set0_pqg|DH_set_length|DSA_set0_key|DSA_set0_pqg|EC_GROUP_check|EC_GROUP_check_discriminant|EC_GROUP_copy|EC_GROUP_get_curve_name|EC_GROUP_get_pentanomial_basis|EC_GROUP_get_trinomial_basis|EC_GROUP_precompute_mult|EC_GROUP_set_generator|EC_GROUP_set_seed|EC_KEY_check_key|EC_KEY_generate_key|EC_KEY_key2buf|EC_KEY_oct2key|EC_KEY_oct2priv|EC_KEY_precompute_mult|EC_KEY_priv2buf|EC_KEY_priv2oct|EC_KEY_set_group|EC_KEY_set_private_key|EC_KEY_set_public_key|EC_KEY_set_public_key_affine_coordinates|EC_KEY_up_ref|EC_POINT_add|EC_POINT_copy|EC_POINT_dbl|EC_POINT_get_Jprojective_coordinates_GFp|EC_POINT_get_affine_coordinates_GF2m|EC_POINT_get_affine_coordinates_GFp|EC_POINT_invert|EC_POINT_make_affine|EC_POINT_mul|EC_POINT_oct2point|EC_POINT_point2oct|EC_POINT_set_Jprojective_coordinates_GFp|EC_POINT_set_affine_coordinates_GF2m|EC_POINT_set_affine_coordinates_GFp|EC_POINT_set_compressed_coordinates_GF2m|EC_POINT_set_compressed_coordinates_GFp|EC_POINT_set_to_infinity|EC_POINTs_make_affine|EC_POINTs_mul|ENGINE_add|ENGINE_ctrl_cmd|ENGINE_ctrl_cmd_string|ENGINE_finish|ENGINE_free|ENGINE_init|ENGINE_register_DH|ENGINE_register_DSA|ENGINE_register_EC|ENGINE_register_RAND|ENGINE_register_RSA|ENGINE_register_all_complete|ENGINE_register_ciphers|ENGINE_register_complete|ENGINE_register_digests|ENGINE_register_pkey_asn1_meths|ENGINE_register_pkey_meths|ENGINE_remove|ENGINE_set_RSA|ENGINE_set_default|ENGINE_set_default_DH|ENGINE_set_default_DSA|ENGINE_set_default_EC|ENGINE_set_default_RAND|ENGINE_set_default_RSA|ENGINE_set_digests|ENGINE_set_id|ENGINE_set_init_function|ENGINE_set_load_privkey_function|ENGINE_set_load_pubkey_function|ENGINE_set_name|ENGINE_up_ref|HMAC_CTX_copy|HMAC_CTX_reset|HMAC_Final|HMAC_Init_ex|HMAC_Update|MD2_Init|MD2_Update|MD2_Final|MD4_Init|MD4_Update|MD4_Final|MD5_Init|MD5_Update|MD5_Final|OPENSSL_init_crypto|OPENSSL_mem_debug_pop|OPENSSL_mem_debug_push|RSA_generate_key_ex|RSA_generate_multi_prime_key|RSA_meth_set_finish|RSA_meth_set_sign|RSA_meth_set_verify|RSA_padding_add_SSLv23|RSA_set0_crt_params|RSA_set0_factors|RSA_set0_key|RSA_set0_multi_prime_params)$"; +position p; +@@ + + if ( +( + !FUNCNOT(...)@p +| + !(X = FUNCNOT)@p +) + ) + goto L; + +// 1=success. These may have == 0 or <= 0 or non-one failure so we explicitly check for success. +// Since some EVP_* functions use failure == 0 and others use <= 0, we consolidate all +// EVP_* calls into here so it's less error prone. In such cases, they all use 1 for success. +@openssl_check_1@ +expression X; +identifier L; +identifier FUNC1 =~ "^(EVP_CIPHER_CTX_copy|EVP_CIPHER_CTX_ctrl|EVP_CIPHER_CTX_rand_key|EVP_CIPHER_CTX_reset|EVP_CIPHER_CTX_set_key_length|EVP_CIPHER_CTX_set_padding|EVP_CipherFinal_ex|EVP_CipherInit_ex|EVP_CipherUpdate|EVP_DecryptFinal_ex|EVP_DecryptInit_ex|EVP_DecryptUpdate|EVP_Digest|EVP_DigestFinal|EVP_DigestFinal_ex|EVP_DigestInit|EVP_DigestInit_ex|EVP_DigestSign|EVP_DigestSignInit|EVP_DigestSignUpdate|EVP_DigestSignaFinal|EVP_DigestUpdate|EVP_DigestVerify|EVP_DigestVerifyInit|EVP_EncryptFinal_ex|EVP_EncryptInit_ex|EVP_EncryptUpdate|EVP_MAC_CTX_copy|EVP_MAC_ctrl|EVP_MAC_ctrl_str|EVP_MAC_hex2ctrl|EVP_MAC_init|EVP_MAC_reset|EVP_MAC_str2ctrl|EVP_MAC_update|EVP_MD_CTX_copy|EVP_MD_CTX_copy_ex|EVP_MD_CTX_ctrl|EVP_MD_meth_set_app_datasize|EVP_MD_meth_set_cleanup|EVP_MD_meth_set_copy|EVP_MD_meth_set_ctrl|EVP_MD_meth_set_final|EVP_MD_meth_set_flags|EVP_MD_meth_set_init|EVP_MD_meth_set_input_blocksize|EVP_MD_meth_set_result_size|EVP_MD_meth_set_update|EVP_PKEY_CTX_set_rsa_mgf1_md|EVP_PKEY_CTX_set_rsa_padding|EVP_PKEY_CTX_set_rsa_pss_saltlen|EVP_PKEY_CTX_set_signature|EVP_PKEY_assign|EVP_PKEY_assign_DSA|EVP_PKEY_assign_EC_KEY|EVP_PKEY_assign_RSA|EVP_PKEY_decrypt|EVP_PKEY_decrypt_init|EVP_PKEY_derive|EVP_PKEY_derive_init|EVP_PKEY_derive_set_peer|EVP_PKEY_encrypt|EVP_PKEY_encrypt_init|EVP_PKEY_get1_DH|EVP_PKEY_get_raw_private_key|EVP_PKEY_get_raw_public_key|EVP_PKEY_keygen|EVP_PKEY_keygen_init|EVP_PKEY_set1_DH|EVP_PKEY_sign|EVP_PKEY_sign_init|EVP_PKEY_verify|EVP_PKEY_verify_init|EVP_PKEY_verify_recover|EVP_PKEY_verify_recover_init|EVP_add_mac|RAND_bytes|RAND_priv_bytes)$"; +position p; +@@ + + if ( +( + FUNC1(...)@p != 1 +| + (X = FUNC1(...)@p) != 1 +) + ) + goto L; + + +// These are void but here for completeness +@openssl_void@ +identifier FUNCVOID =~ "^(AES_cfb128_encrypt|AES_cfb8_encrypt|AES_ige_encrypt|BN_GENCB_set|DSA_get0_key|DSA_get0_pqg|EC_GROUP_set_asn1_flag|EC_GROUP_set_point_conversion_form|ENGINE_get_static_state|ENGINE_unregister_DH|ENGINE_unregister_DSA|ENGINE_unregister_EC|ENGINE_unregister_RAND|ENGINE_unregister_RSA|ENGINE_unregister_ciphers|ENGINE_unregister_digests|ENGINE_unregister_pkey_asn1_meths|ENGINE_unregister_pkey_meths|OpenSSL_add_all_ciphers|OpenSSL_add_all_digests|RAND_seed|RC4|RC4_set_key|RSA_get0_crt_params|RSA_get0_factors|RSA_get0_key)$"; +position p; +@@ + + FUNCVOID(...)@p; + + +// Traditionally, OpenSSL didn't adhere to the semantics of free() calls +// allowing for NULL. However, they have been changing it over time. +// Since Erlang allows for unmaintained versions of OpenSSL, be conservative +// and assume the worst. +@openssl_free@ +expression X; +identifier FUNCFREE =~ "^(BN_CTX_free|BN_GENCB_free|BN_clear_free|BN_free|CMAC_CTX_free|CRYPTO_free|DH_free|DSA_free|EC_GROUP_free|EC_KEY_free|EC_POINT_free|EVP_CIPHER_CTX_free|EVP_MD_CTX_free|EVP_PKEY_CTX_free|EVP_PKEY_free|HMAC_CTX_free|RSA_free|RSA_meth_free)$"; +position p; +@@ + + if ( +( + X +| + X != NULL +) + ) + FUNCFREE(X)@p; + + +// NOTE: Keep these in sync with the above definitions! +// +// Find all of the cases that we haven't marked safe positions of. +// +// This will flag a few false positives because the code isn't using the +// standard pattern. +// +// NOTE: You have to copy the regexps because there doesn't appear to be a way in +// coccinelle to reference a regexp identifier from another rule properly. +@openssl_check_NOT_SAFE@ + +identifier FUNCNEG =~ "^(DH_compute_key|RSA_padding_check_SSLv23)$"; +position pneg != openssl_check_negative.p; + +identifier FUNCPOS =~ "^(ECDH_compute_key|EVP_CIPHER_asn1_to_param|EVP_CIPHER_param_to_asn1|EVP_PKEY_CTX_ctrl|RSA_pkey_ctx_ctrl)$"; +position ppos != openssl_check_positive.p; + +identifier FUNC0 =~ "^(AES_set_decrypt_key|AES_set_encrypt_key|CRYPTO_gcm128_aad|CRYPTO_gcm128_decrypt|CRYPTO_gcm128_finish)$"; +position p0 != openssl_check_0.p; + +identifier FUNCNULL =~ "^(BN_CTX_new|BN_GENCB_new|BN_MONT_CTX_new|BN_bin2bn|BN_dup|BN_generate_prime|BN_new|CMAC_CTX_new|CRYPTO_clear_realloc|CRYPTO_gcm128_new|CRYPTO_malloc|CRYPTO_realloc|CRYPTO_zalloc|DH_generate_parameters|DH_new|DSA_new|EC_GROUP_dup|EC_GROUP_get0_generator|EC_GROUP_method_of|EC_GROUP_new_curve_GFm|EC_GROUP_new_curve_GFp|EC_KEY_copy|EC_KEY_dup|EC_KEY_get0_engine|EC_KEY_new|EC_KEY_new_by_curve_name|EC_POINT_bn2point|EC_POINT_dup|EC_POINT_new|EC_POINT_point2bn|ENGINE_by_id|ENGINE_get_cipher_engine|ENGINE_get_default_DH|ENGINE_get_default_DSA|ENGINE_get_default_RAND|ENGINE_get_default_RSA|ENGINE_get_digest_engine|ENGINE_get_first|ENGINE_get_id|ENGINE_get_last|ENGINE_get_name|ENGINE_get_next|ENGINE_get_prev|ENGINE_load_private_key|ENGINE_load_public_key|ENGINE_new|EVP_CIPHER_CTX_new|EVP_MAC_CTX_new|EVP_MAC_CTX_new_id|EVP_MD_CTX_new|EVP_MD_meth_new|EVP_PKEY_CTX_new|EVP_PKEY_CTX_new_id|EVP_PKEY_get1_DH|EVP_PKEY_get1_DSA|EVP_PKEY_get1_EC_KEY|EVP_PKEY_get1_RSA|EVP_PKEY_new|EVP_PKEY_new_raw_private_key|EVP_PKEY_new_raw_public_key|EVP_get_cipherbyname|EVP_get_cipherbynid|EVP_get_cipherbyobj|EVP_get_macbyname|EVP_get_macbynid|EVP_get_macbyobj|HMAC|HMAC_CTX_new|OPENSSL_buf2hexstr|OPENSSL_clear_realloc|OPENSSL_hexstr2buf|OPENSSL_malloc|OPENSSL_realloc|OPENSSL_strdup|OPENSSL_strndup|OPENSSL_zalloc|RSA_meth_dup|RSA_meth_new|RSA_new)$"; +position pnull != openssl_check_null.p; + +identifier FUNCNOT =~ "^(BN_add|BN_div|BN_exp|BN_from_montgomery|BN_gcd|BN_generate_prime_ex|BN_mod|BN_mod_add|BN_mod_exp|BN_mod_mul|BN_mod_mul_montgomery|BN_mod_sqr|BN_mod_sub|BN_mul|BN_nnmod|BN_priv_rand|BN_priv_rand_range|BN_pseudo_rand|BN_pseudo_rand_range|BN_rand|BN_rand_range|BN_set_bit|BN_set_word|BN_sqr|BN_sub|BN_to_montgomery|CMAC_Final|CMAC_Init|CMAC_Update|CRYPTO_set_mem_debug|CRYPTO_set_mem_functions|DH_check|DH_check_ex|DH_check_params|DH_check_pub_key_ex|DH_generate_key|DH_generate_parameters_ex|DH_set0_key|DH_set0_pqg|DH_set_length|DSA_set0_key|DSA_set0_pqg|EC_GROUP_check|EC_GROUP_check_discriminant|EC_GROUP_copy|EC_GROUP_get_curve_name|EC_GROUP_get_pentanomial_basis|EC_GROUP_get_trinomial_basis|EC_GROUP_precompute_mult|EC_GROUP_set_generator|EC_GROUP_set_seed|EC_KEY_check_key|EC_KEY_generate_key|EC_KEY_key2buf|EC_KEY_oct2key|EC_KEY_oct2priv|EC_KEY_precompute_mult|EC_KEY_priv2buf|EC_KEY_priv2oct|EC_KEY_set_group|EC_KEY_set_private_key|EC_KEY_set_public_key|EC_KEY_set_public_key_affine_coordinates|EC_KEY_up_ref|EC_POINT_add|EC_POINT_copy|EC_POINT_dbl|EC_POINT_get_Jprojective_coordinates_GFp|EC_POINT_get_affine_coordinates_GF2m|EC_POINT_get_affine_coordinates_GFp|EC_POINT_invert|EC_POINT_make_affine|EC_POINT_mul|EC_POINT_oct2point|EC_POINT_point2oct|EC_POINT_set_Jprojective_coordinates_GFp|EC_POINT_set_affine_coordinates_GF2m|EC_POINT_set_affine_coordinates_GFp|EC_POINT_set_compressed_coordinates_GF2m|EC_POINT_set_compressed_coordinates_GFp|EC_POINT_set_to_infinity|EC_POINTs_make_affine|EC_POINTs_mul|ENGINE_add|ENGINE_ctrl_cmd|ENGINE_ctrl_cmd_string|ENGINE_finish|ENGINE_free|ENGINE_init|ENGINE_register_DH|ENGINE_register_DSA|ENGINE_register_EC|ENGINE_register_RAND|ENGINE_register_RSA|ENGINE_register_all_complete|ENGINE_register_ciphers|ENGINE_register_complete|ENGINE_register_digests|ENGINE_register_pkey_asn1_meths|ENGINE_register_pkey_meths|ENGINE_remove|ENGINE_set_RSA|ENGINE_set_default|ENGINE_set_default_DH|ENGINE_set_default_DSA|ENGINE_set_default_EC|ENGINE_set_default_RAND|ENGINE_set_default_RSA|ENGINE_set_digests|ENGINE_set_id|ENGINE_set_init_function|ENGINE_set_load_privkey_function|ENGINE_set_load_pubkey_function|ENGINE_set_name|ENGINE_up_ref|HMAC_CTX_copy|HMAC_CTX_reset|HMAC_Final|HMAC_Init_ex|HMAC_Update|MD2_Init|MD2_Update|MD2_Final|MD4_Init|MD4_Update|MD4_Final|MD5_Init|MD5_Update|MD5_Final|OPENSSL_init_crypto|OPENSSL_mem_debug_pop|OPENSSL_mem_debug_push|RSA_generate_key_ex|RSA_generate_multi_prime_key|RSA_meth_set_finish|RSA_meth_set_sign|RSA_meth_set_verify|RSA_padding_add_SSLv23|RSA_set0_crt_params|RSA_set0_factors|RSA_set0_key|RSA_set0_multi_prime_params)$"; +position pnot != openssl_check_not.p; + +identifier FUNC1 =~ "^(EVP_CIPHER_CTX_copy|EVP_CIPHER_CTX_ctrl|EVP_CIPHER_CTX_rand_key|EVP_CIPHER_CTX_reset|EVP_CIPHER_CTX_set_key_length|EVP_CIPHER_CTX_set_padding|EVP_CipherFinal_ex|EVP_CipherInit_ex|EVP_CipherUpdate|EVP_DecryptFinal_ex|EVP_DecryptInit_ex|EVP_DecryptUpdate|EVP_Digest|EVP_DigestFinal|EVP_DigestFinal_ex|EVP_DigestInit|EVP_DigestInit_ex|EVP_DigestSign|EVP_DigestSignInit|EVP_DigestSignUpdate|EVP_DigestSignaFinal|EVP_DigestUpdate|EVP_DigestVerify|EVP_DigestVerifyInit|EVP_EncryptFinal_ex|EVP_EncryptInit_ex|EVP_EncryptUpdate|EVP_MAC_CTX_copy|EVP_MAC_ctrl|EVP_MAC_ctrl_str|EVP_MAC_hex2ctrl|EVP_MAC_init|EVP_MAC_reset|EVP_MAC_str2ctrl|EVP_MAC_update|EVP_MD_CTX_copy|EVP_MD_CTX_copy_ex|EVP_MD_CTX_ctrl|EVP_MD_meth_set_app_datasize|EVP_MD_meth_set_cleanup|EVP_MD_meth_set_copy|EVP_MD_meth_set_ctrl|EVP_MD_meth_set_final|EVP_MD_meth_set_flags|EVP_MD_meth_set_init|EVP_MD_meth_set_input_blocksize|EVP_MD_meth_set_result_size|EVP_MD_meth_set_update|EVP_PKEY_CTX_set_rsa_mgf1_md|EVP_PKEY_CTX_set_rsa_padding|EVP_PKEY_CTX_set_rsa_pss_saltlen|EVP_PKEY_CTX_set_signature|EVP_PKEY_assign|EVP_PKEY_assign_DSA|EVP_PKEY_assign_EC_KEY|EVP_PKEY_assign_RSA|EVP_PKEY_decrypt|EVP_PKEY_decrypt_init|EVP_PKEY_derive|EVP_PKEY_derive_init|EVP_PKEY_derive_set_peer|EVP_PKEY_encrypt|EVP_PKEY_encrypt_init|EVP_PKEY_get1_DH|EVP_PKEY_get_raw_private_key|EVP_PKEY_get_raw_public_key|EVP_PKEY_keygen|EVP_PKEY_keygen_init|EVP_PKEY_set1_DH|EVP_PKEY_sign|EVP_PKEY_sign_init|EVP_PKEY_verify|EVP_PKEY_verify_init|EVP_PKEY_verify_recover|EVP_PKEY_verify_recover_init|EVP_add_mac|RAND_bytes|RAND_priv_bytes)$"; +position p1 != openssl_check_1.p; + +identifier FUNCVOID =~ "^(AES_cfb128_encrypt|AES_cfb8_encrypt|AES_ige_encrypt|BN_GENCB_set|DSA_get0_key|DSA_get0_pqg|EC_GROUP_set_asn1_flag|EC_GROUP_set_point_conversion_form|ENGINE_get_static_state|ENGINE_unregister_DH|ENGINE_unregister_DSA|ENGINE_unregister_EC|ENGINE_unregister_RAND|ENGINE_unregister_RSA|ENGINE_unregister_ciphers|ENGINE_unregister_digests|ENGINE_unregister_pkey_asn1_meths|ENGINE_unregister_pkey_meths|OpenSSL_add_all_ciphers|OpenSSL_add_all_digests|RAND_seed|RC4|RC4_set_key|RSA_get0_crt_params|RSA_get0_factors|RSA_get0_key)$"; +position pvoid != openssl_void.p; + +identifier FUNCFREE =~ "^(BN_CTX_free|BN_GENCB_free|BN_clear_free|BN_free|CMAC_CTX_free|CRYPTO_free|DH_free|DSA_free|EC_GROUP_free|EC_KEY_free|EC_POINT_free|EVP_CIPHER_CTX_free|EVP_MD_CTX_free|EVP_PKEY_CTX_free|EVP_PKEY_free|HMAC_CTX_free|RSA_free|RSA_meth_free)$"; +position pfree != openssl_free.p; +@@ + +( +* FUNCNEG(...)@pneg +| +* FUNCPOS(...)@ppos +| +* FUNCNULL(...)@pnull +| +* FUNC0(...)@p0 +| +* FUNC1(...)@p1 +| +* FUNCNOT(...)@pnot +| +* FUNCVOID(...)@pvoid +| +* FUNCFREE(...)@pfree +) -- cgit v1.2.3 From 9bd2429c7e847d9767cec58707e6fba5f7ced767 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 12 Jan 2019 16:36:44 -0800 Subject: Add missing header --- lib/crypto/c_src/common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/crypto/c_src/common.h b/lib/crypto/c_src/common.h index 237073c194..2bc8bdd73c 100644 --- a/lib/crypto/c_src/common.h +++ b/lib/crypto/c_src/common.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "openssl_config.h" -- cgit v1.2.3 From c91aecddbd0b1d0aac889da5cf4f8aed8d75637c Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Sat, 12 Jan 2019 16:53:39 -0800 Subject: Also include stdint for code that doesn't pull in common.h --- lib/crypto/c_src/crypto_callback.c | 1 + lib/crypto/c_src/otp_test_engine.c | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c index ed5a1a6226..c0ca18e2ce 100644 --- a/lib/crypto/c_src/crypto_callback.c +++ b/lib/crypto/c_src/crypto_callback.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "crypto_callback.h" diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c index 4557eaa877..fdc60f3bbc 100644 --- a/lib/crypto/c_src/otp_test_engine.c +++ b/lib/crypto/c_src/otp_test_engine.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From 3b51e7933ba42b3299ba0678ce1b4d8a844064cd Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 14 Jan 2019 21:44:49 -0800 Subject: enif_release_resource is not NULL safe * Add if checks and update coccinelle script. --- lib/crypto/c_src/aes.c | 6 ++++-- lib/crypto/c_src/chacha20.c | 6 ++++-- lib/crypto/c_src/check_erlang.cocci | 28 +++++++++++++++++++++++++--- lib/crypto/c_src/engine.c | 9 ++++++--- lib/crypto/c_src/hash.c | 6 ++++-- lib/crypto/c_src/hmac.c | 3 ++- 6 files changed, 45 insertions(+), 13 deletions(-) diff --git a/lib/crypto/c_src/aes.c b/lib/crypto/c_src/aes.c index 94b874298e..205cb8b058 100644 --- a/lib/crypto/c_src/aes.c +++ b/lib/crypto/c_src/aes.c @@ -223,7 +223,8 @@ ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar ret = enif_make_badarg(env); done: - enif_release_resource(ctx); + if (ctx) + enif_release_resource(ctx); return ret; } @@ -270,7 +271,8 @@ ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ret = enif_make_badarg(env); done: - enif_release_resource(new_ctx); + if (new_ctx) + enif_release_resource(new_ctx); return ret; } diff --git a/lib/crypto/c_src/chacha20.c b/lib/crypto/c_src/chacha20.c index 03b8589524..51a24a43e9 100644 --- a/lib/crypto/c_src/chacha20.c +++ b/lib/crypto/c_src/chacha20.c @@ -63,7 +63,8 @@ ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM a ret = enif_make_badarg(env); done: - enif_release_resource(ctx); + if (ctx) + enif_release_resource(ctx); return ret; #else @@ -113,7 +114,8 @@ ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ret = enif_make_badarg(env); done: - enif_release_resource(new_ctx); + if (new_ctx) + enif_release_resource(new_ctx); return ret; #else diff --git a/lib/crypto/c_src/check_erlang.cocci b/lib/crypto/c_src/check_erlang.cocci index bdb99d5bb0..eba0e3935c 100644 --- a/lib/crypto/c_src/check_erlang.cocci +++ b/lib/crypto/c_src/check_erlang.cocci @@ -39,7 +39,8 @@ position p; goto L; ... when strict, forall - enif_release_resource(CTX) + if (CTX) + enif_release_resource(CTX); // After calling enif_alloc_binary(), you must either release it with @@ -93,7 +94,7 @@ position pa, pm, pr; // enif_has_pending_exception returns true if exception pending @erlang_check_void@ -identifier FUNCVOID =~ "^(enif_free|enif_mutex_destroy|enif_mutex_lock|enif_mutex_unlock|enif_release_binary|enif_release_resource|enif_rwlock_destroy|enif_rwlock_rlock|enif_rwlock_runlock|enif_rwlock_rwlock|enif_rwlock_rwunlock|enif_system_info)$"; +identifier FUNCVOID =~ "^(enif_free|enif_mutex_destroy|enif_mutex_lock|enif_mutex_unlock|enif_release_binary|enif_rwlock_destroy|enif_rwlock_rlock|enif_rwlock_runlock|enif_rwlock_rwlock|enif_rwlock_rwunlock|enif_system_info)$"; position p; @@ @@ -133,6 +134,22 @@ position p; ) +@erlang_check_null_free@ +expression X; +identifier FUNCFREE =~ "^(enif_release_resource)$"; +position p; +@@ + + if ( +( + X +| + X != NULL +) + ) + FUNCFREE(X)@p; + + @erlang_check_new@ expression RET; identifier FUNCNEW =~ "^(enif_make_atom|enif_make_badarg|enif_make_binary|enif_make_int|enif_make_list|enif_make_list_from_array|enif_make_resource|enif_make_tuple|enif_raise_exception|enif_schedule_nif|enif_thread_self)$"; @@ -149,7 +166,7 @@ position p; // Flag any calls that aren't part of the above pattern. @enif_alloc_not_free@ -identifier FUNCVOID =~ "^(enif_free|enif_mutex_destroy|enif_mutex_lock|enif_mutex_unlock|enif_release_binary|enif_release_resource|enif_rwlock_destroy|enif_rwlock_rlock|enif_rwlock_runlock|enif_rwlock_rwlock|enif_rwlock_rwunlock|enif_system_info)$"; +identifier FUNCVOID =~ "^(enif_free|enif_mutex_destroy|enif_mutex_lock|enif_mutex_unlock|enif_release_binary|enif_rwlock_destroy|enif_rwlock_rlock|enif_rwlock_runlock|enif_rwlock_rwlock|enif_rwlock_rwunlock|enif_system_info)$"; position pvoid != {erlang_check_void.p,enif_alloc_binary.pr}; identifier FUNCNULL =~ "^(enif_alloc|enif_alloc_resource|enif_dlopen|enif_dlsym|enif_make_new_binary|enif_mutex_create|enif_open_resource_type|enif_realloc|enif_rwlock_create)$"; @@ -161,6 +178,9 @@ position pnot != {erlang_check_not.p,enif_alloc_binary.pa}; identifier FUNCNEW =~ "^(enif_make_atom|enif_make_badarg|enif_make_binary|enif_make_int|enif_make_list|enif_make_list_from_array|enif_make_resource|enif_make_tuple|enif_raise_exception|enif_schedule_nif|enif_thread_self)$"; position pnew != {erlang_check_new.p,enif_alloc_binary.pm}; +identifier FUNCFREE =~ "^(enif_release_resource)$"; +position pfree != {enif_alloc_resource.p,erlang_check_null_free.p}; + @@ ( @@ -171,4 +191,6 @@ position pnew != {erlang_check_new.p,enif_alloc_binary.pm}; * FUNCNOT(...)@pnot | * FUNCNEW(...)@pnew +| +* FUNCFREE(...)@pfree ) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 44648280b4..90fc8b66cd 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -158,7 +158,8 @@ ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ done: if (engine_id) enif_free(engine_id); - enif_release_resource(ctx); + if (ctx) + enif_release_resource(ctx); return ret; #else @@ -604,7 +605,8 @@ ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a ret = enif_make_badarg(env); done: - enif_release_resource(ctx); + if (ctx) + enif_release_resource(ctx); return ret; #else @@ -647,7 +649,8 @@ ERL_NIF_TERM engine_get_next_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar ret = enif_make_badarg(env); done: - enif_release_resource(next_ctx); + if (next_ctx) + enif_release_resource(next_ctx); return ret; #else diff --git a/lib/crypto/c_src/hash.c b/lib/crypto/c_src/hash.c index a90957f1a7..000eae047a 100644 --- a/lib/crypto/c_src/hash.c +++ b/lib/crypto/c_src/hash.c @@ -130,7 +130,8 @@ ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ret = atom_notsup; done: - enif_release_resource(ctx); + if (ctx) + enif_release_resource(ctx); return ret; } @@ -167,7 +168,8 @@ ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] ret = atom_notsup; done: - enif_release_resource(new_ctx); + if (new_ctx) + enif_release_resource(new_ctx); return ret; } diff --git a/lib/crypto/c_src/hmac.c b/lib/crypto/c_src/hmac.c index a5ff35c706..9418e7950e 100644 --- a/lib/crypto/c_src/hmac.c +++ b/lib/crypto/c_src/hmac.c @@ -169,7 +169,8 @@ ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ret = atom_notsup; done: - enif_release_resource(obj); + if (obj) + enif_release_resource(obj); return ret; } -- cgit v1.2.3 From 4f0403027dfd109276823d32f10d85d7b3478ca8 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 14 Jan 2019 22:37:15 -0800 Subject: dh_p is referenced after dh_params owns it * Need to keep a reference even though ownership was transfered to dh_params. * Also, be more conservative and return atom_error where the original code did. --- lib/crypto/c_src/dh.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/crypto/c_src/dh.c b/lib/crypto/c_src/dh.c index bb87080d7b..d077007a52 100644 --- a/lib/crypto/c_src/dh.c +++ b/lib/crypto/c_src/dh.c @@ -27,6 +27,7 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar unsigned int mpint; /* 0 or 4 */ ERL_NIF_TERM head, tail; BIGNUM *dh_p = NULL; + BIGNUM *dh_p_shared; BIGNUM *dh_g = NULL; BIGNUM *priv_key_in = NULL; unsigned long len = 0; @@ -72,15 +73,16 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar /* Load dh_params with values to use by the generator. Mem mgmnt transfered from dh_p etc to dh_params */ if ((dh_params = DH_new()) == NULL) - goto err; + goto bad_arg; if (priv_key_in) { if (!DH_set0_key(dh_params, NULL, priv_key_in)) - goto err; + goto bad_arg; /* On success, dh_params owns priv_key_in */ priv_key_in = NULL; } if (!DH_set0_pqg(dh_params, dh_p, NULL, dh_g)) - goto err; + goto bad_arg; + 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; dh_g = NULL; @@ -88,13 +90,14 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar if (len) { int bn_len; - if ((bn_len = BN_num_bits(dh_p)) < 0) + if ((bn_len = BN_num_bits(dh_p_shared)) < 0) goto bad_arg; + dh_p_shared = NULL; /* dh_params owns the reference */ if (len >= (size_t)bn_len) goto bad_arg; if (!DH_set_length(dh_params, (long)len)) - goto err; + goto bad_arg; } #ifdef HAS_EVP_PKEY_CTX @@ -159,8 +162,11 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar goto done; bad_arg: - err: ret = enif_make_badarg(env); + goto done; + + err: + ret = atom_error; done: if (priv_key_in) -- cgit v1.2.3 From 866f36b4b32712682cfdb0ec4225f7edff93e624 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 14 Jan 2019 23:05:17 -0800 Subject: Fix documentation and argc check in engine_get_first_nif() * This was documented as sending in an argument but it doesn't read argv. --- lib/crypto/c_src/engine.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 90fc8b66cd..ae23747cbf 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -574,14 +574,14 @@ ERL_NIF_TERM engine_unregister_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM } ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Engine) */ +{/* () */ #ifdef HAS_ENGINE_SUPPORT ERL_NIF_TERM ret, result; ENGINE *engine; ErlNifBinary engine_bin; struct engine_ctx *ctx = NULL; - if (argc != 1) + if (argc != 0) goto bad_arg; if ((engine = ENGINE_get_first()) == NULL) { -- cgit v1.2.3 From 825c73a0f8fdd27a37971a7bd7090356d2900565 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 14 Jan 2019 23:22:24 -0800 Subject: Add more Erlang functions that are not NULL safe to coccinelle --- lib/crypto/c_src/check_erlang.cocci | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/crypto/c_src/check_erlang.cocci b/lib/crypto/c_src/check_erlang.cocci index eba0e3935c..cfcc0517cb 100644 --- a/lib/crypto/c_src/check_erlang.cocci +++ b/lib/crypto/c_src/check_erlang.cocci @@ -94,7 +94,7 @@ position pa, pm, pr; // enif_has_pending_exception returns true if exception pending @erlang_check_void@ -identifier FUNCVOID =~ "^(enif_free|enif_mutex_destroy|enif_mutex_lock|enif_mutex_unlock|enif_release_binary|enif_rwlock_destroy|enif_rwlock_rlock|enif_rwlock_runlock|enif_rwlock_rwlock|enif_rwlock_rwunlock|enif_system_info)$"; +identifier FUNCVOID =~ "^(enif_mutex_destroy|enif_mutex_lock|enif_mutex_unlock|enif_rwlock_destroy|enif_rwlock_rlock|enif_rwlock_runlock|enif_rwlock_rwlock|enif_rwlock_rwunlock|enif_system_info)$"; position p; @@ @@ -136,7 +136,7 @@ position p; @erlang_check_null_free@ expression X; -identifier FUNCFREE =~ "^(enif_release_resource)$"; +identifier FUNCFREE =~ "^(enif_free|enif_free_env|enif_free_iovec|enif_release_binary|enif_release_resource)$"; position p; @@ @@ -166,7 +166,7 @@ position p; // Flag any calls that aren't part of the above pattern. @enif_alloc_not_free@ -identifier FUNCVOID =~ "^(enif_free|enif_mutex_destroy|enif_mutex_lock|enif_mutex_unlock|enif_release_binary|enif_rwlock_destroy|enif_rwlock_rlock|enif_rwlock_runlock|enif_rwlock_rwlock|enif_rwlock_rwunlock|enif_system_info)$"; +identifier FUNCVOID =~ "^(enif_mutex_destroy|enif_mutex_lock|enif_mutex_unlock|enif_rwlock_destroy|enif_rwlock_rlock|enif_rwlock_runlock|enif_rwlock_rwlock|enif_rwlock_rwunlock|enif_system_info)$"; position pvoid != {erlang_check_void.p,enif_alloc_binary.pr}; identifier FUNCNULL =~ "^(enif_alloc|enif_alloc_resource|enif_dlopen|enif_dlsym|enif_make_new_binary|enif_mutex_create|enif_open_resource_type|enif_realloc|enif_rwlock_create)$"; @@ -178,7 +178,7 @@ position pnot != {erlang_check_not.p,enif_alloc_binary.pa}; identifier FUNCNEW =~ "^(enif_make_atom|enif_make_badarg|enif_make_binary|enif_make_int|enif_make_list|enif_make_list_from_array|enif_make_resource|enif_make_tuple|enif_raise_exception|enif_schedule_nif|enif_thread_self)$"; position pnew != {erlang_check_new.p,enif_alloc_binary.pm}; -identifier FUNCFREE =~ "^(enif_release_resource)$"; +identifier FUNCFREE =~ "^(enif_free|enif_free_env|enif_free_iovec|enif_release_binary|enif_release_resource)$"; position pfree != {enif_alloc_resource.p,erlang_check_null_free.p}; @@ -- cgit v1.2.3 From 9ef96d08df6a55912dfbb8de2e460f719f5a6728 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 14 Jan 2019 23:24:28 -0800 Subject: Make crypto_free() NULL safe --- lib/crypto/c_src/crypto_callback.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c index c0ca18e2ce..0141ccd840 100644 --- a/lib/crypto/c_src/crypto_callback.c +++ b/lib/crypto/c_src/crypto_callback.c @@ -92,6 +92,9 @@ static void* crypto_realloc(void* ptr, size_t size CCB_FILE_LINE_ARGS) static void crypto_free(void* ptr CCB_FILE_LINE_ARGS) { + if (ptr == NULL) + return; + enif_free(ptr); } -- cgit v1.2.3 From 7c80625748a1d95a20754c0927e13c00423c1277 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 14 Jan 2019 23:38:34 -0800 Subject: Reference all of the free/release call positions in cocci file --- lib/crypto/c_src/check_erlang.cocci | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/crypto/c_src/check_erlang.cocci b/lib/crypto/c_src/check_erlang.cocci index cfcc0517cb..b2a981f2ac 100644 --- a/lib/crypto/c_src/check_erlang.cocci +++ b/lib/crypto/c_src/check_erlang.cocci @@ -29,7 +29,7 @@ type T; identifier CTX, L; identifier virtual.enif_alloc_resource, virtual.enif_release_resource; -position p; +position p, pr; @@ T *CTX = NULL; @@ -40,7 +40,7 @@ position p; ... when strict, forall if (CTX) - enif_release_resource(CTX); + enif_release_resource(CTX)@pr; // After calling enif_alloc_binary(), you must either release it with @@ -179,7 +179,7 @@ identifier FUNCNEW =~ "^(enif_make_atom|enif_make_badarg|enif_make_binary|enif_m position pnew != {erlang_check_new.p,enif_alloc_binary.pm}; identifier FUNCFREE =~ "^(enif_free|enif_free_env|enif_free_iovec|enif_release_binary|enif_release_resource)$"; -position pfree != {enif_alloc_resource.p,erlang_check_null_free.p}; +position pfree != {enif_alloc_resource.pr,enif_alloc_binary.pr,erlang_check_null_free.p}; @@ -- cgit v1.2.3 From 0256606e5e366e2fbf92a5893b7c888210b95e40 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Tue, 15 Jan 2019 05:32:52 -0800 Subject: Fix documentation and argc check for engine_ctrl_cmd_strings_nif --- lib/crypto/c_src/engine.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index ae23747cbf..715d9bed40 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -252,7 +252,7 @@ ERL_NIF_TERM engine_load_dynamic_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER } ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Engine, Commands) */ +{/* (Engine, Commands, Optional) */ #ifdef HAS_ENGINE_SUPPORT ERL_NIF_TERM ret; unsigned int cmds_len = 0; @@ -263,7 +263,7 @@ ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const ERL_NIF int cmds_loaded = 0; // Get Engine - if (argc != 2) + if (argc != 3) goto bad_arg; if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) goto bad_arg; -- cgit v1.2.3 From b36527d7bee7c264bfac9b36fd6dc58b2f15a7f0 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Tue, 15 Jan 2019 05:33:47 -0800 Subject: Make it easier to turn on debug output --- lib/crypto/c_src/openssl_config.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/crypto/c_src/openssl_config.h b/lib/crypto/c_src/openssl_config.h index 65290cdfdf..c0ce1a59fe 100644 --- a/lib/crypto/c_src/openssl_config.h +++ b/lib/crypto/c_src/openssl_config.h @@ -327,15 +327,15 @@ do { \ # define HAVE_OPAQUE_BN_GENCB #endif -/* -#define PRINTF_ERR0(FMT) enif_fprintf(stderr, FMT "\n") -#define PRINTF_ERR1(FMT, A1) enif_fprintf(stderr, FMT "\n", A1) -#define PRINTF_ERR2(FMT, A1, A2) enif_fprintf(stderr, FMT "\n", A1, A2) -*/ - -#define PRINTF_ERR0(FMT) -#define PRINTF_ERR1(FMT,A1) -#define PRINTF_ERR2(FMT,A1,A2) +#if 0 +# define PRINTF_ERR0(FMT) enif_fprintf(stderr, FMT "\n") +# define PRINTF_ERR1(FMT, A1) enif_fprintf(stderr, FMT "\n", A1) +# define PRINTF_ERR2(FMT, A1, A2) enif_fprintf(stderr, FMT "\n", A1, A2) +#else +# define PRINTF_ERR0(FMT) +# define PRINTF_ERR1(FMT,A1) +# define PRINTF_ERR2(FMT,A1,A2) +#endif #ifdef FIPS_SUPPORT /* In FIPS mode non-FIPS algorithms are disabled and return badarg. */ -- cgit v1.2.3 From 7cb2e25a026e6d9ff2cdb078504163de5f71c29a Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Tue, 15 Jan 2019 08:04:32 -0800 Subject: Convert argc checks to ASSERTs per PR --- lib/crypto/c_src/aead.c | 7 +++--- lib/crypto/c_src/aes.c | 31 ++++++++++++------------ lib/crypto/c_src/block.c | 4 ++-- lib/crypto/c_src/bn.c | 4 ++-- lib/crypto/c_src/chacha20.c | 8 +++---- lib/crypto/c_src/cmac.c | 4 ++-- lib/crypto/c_src/dh.c | 6 ++--- lib/crypto/c_src/ecdh.c | 4 ++-- lib/crypto/c_src/engine.c | 58 +++++++++++++++++++++------------------------ lib/crypto/c_src/evp.c | 6 ++--- lib/crypto/c_src/hash.c | 28 +++++++++++----------- lib/crypto/c_src/hmac.c | 15 ++++++------ lib/crypto/c_src/info.c | 4 +--- lib/crypto/c_src/math.c | 4 ++-- lib/crypto/c_src/pkey.c | 7 +++--- lib/crypto/c_src/poly1305.c | 4 ++-- lib/crypto/c_src/rand.c | 16 ++++++------- lib/crypto/c_src/rc4.c | 8 +++---- lib/crypto/c_src/rsa.c | 4 ++-- lib/crypto/c_src/srp.c | 11 ++++----- 20 files changed, 109 insertions(+), 124 deletions(-) diff --git a/lib/crypto/c_src/aead.c b/lib/crypto/c_src/aead.c index f33056b74c..c6f4cf52b1 100644 --- a/lib/crypto/c_src/aead.c +++ b/lib/crypto/c_src/aead.c @@ -34,8 +34,8 @@ ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) type = argv[0]; - if (argc != 6) - goto bad_arg; + ASSERT(argc == 6); + if (!enif_is_atom(env, type)) goto bad_arg; if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) @@ -197,8 +197,7 @@ ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ERL_NIF_TERM type, out, ret; int len, ctx_ctrl_set_ivlen, ctx_ctrl_set_tag; - if (argc != 6) - goto bad_arg; + ASSERT(argc == 6); type = argv[0]; #if defined(HAVE_GCM_EVP_DECRYPT_BUG) diff --git a/lib/crypto/c_src/aes.c b/lib/crypto/c_src/aes.c index 205cb8b058..2df123e44e 100644 --- a/lib/crypto/c_src/aes.c +++ b/lib/crypto/c_src/aes.c @@ -32,8 +32,7 @@ ERL_NIF_TERM aes_cfb_8_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] CHECK_NO_FIPS_MODE(); - if (argc != 4) - goto bad_arg; + ASSERT(argc == 4); if (!enif_inspect_iolist_as_binary(env, argv[0], &key)) goto bad_arg; @@ -74,8 +73,8 @@ ERL_NIF_TERM aes_cfb_128_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ERL_NIF_TERM ret; unsigned char *outp; - if (argc != 4) - goto bad_arg; + ASSERT(argc == 4); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key)) goto bad_arg; if (key.size != 16 && key.size != 24 && key.size != 32) @@ -119,8 +118,8 @@ ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv CHECK_NO_FIPS_MODE(); - if (argc != 4) - goto bad_arg; + ASSERT(argc == 4); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)) goto bad_arg; if (key_bin.size != 16 && key_bin.size != 32) @@ -177,8 +176,8 @@ ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar const EVP_CIPHER *cipher; ERL_NIF_TERM ret; - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)) goto bad_arg; if (!enif_inspect_binary(env, argv[1], &ivec_bin)) @@ -236,8 +235,8 @@ ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned char *out; int outl = 0; - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!enif_get_resource(env, argv[0], evp_cipher_ctx_rtype, (void**)&ctx)) goto bad_arg; if (!enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) @@ -284,8 +283,8 @@ ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar ERL_NIF_TERM ecount_bin; unsigned char *outp; - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)) goto bad_arg; if (key_bin.size != 16 && key_bin.size != 24 && key_bin.size != 32) @@ -319,8 +318,8 @@ ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned char * ecount2_buf; unsigned char *outp; - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!enif_get_tuple(env, argv[0], &state_arity, &state_term)) goto bad_arg; if (state_arity != 4) @@ -382,8 +381,8 @@ ERL_NIF_TERM aes_gcm_decrypt_NO_EVP(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned char *outp; ERL_NIF_TERM out, ret; - if (argc != 6) - goto bad_arg; + ASSERT(argc == 6); + if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) goto bad_arg; if (key.size > INT_MAX / 8) diff --git a/lib/crypto/c_src/block.c b/lib/crypto/c_src/block.c index 3399b7b974..d88ee8dba7 100644 --- a/lib/crypto/c_src/block.c +++ b/lib/crypto/c_src/block.c @@ -33,8 +33,8 @@ ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] int ivec_size, out_size = 0; int cipher_len; - if (argc != 4 && argc != 5) - goto bad_arg; + ASSERT(argc == 4 || argc == 5); + if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) goto bad_arg; if (key.size > INT_MAX) diff --git a/lib/crypto/c_src/bn.c b/lib/crypto/c_src/bn.c index d884a75f80..34ed4f7ebc 100644 --- a/lib/crypto/c_src/bn.c +++ b/lib/crypto/c_src/bn.c @@ -103,8 +103,8 @@ ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) unsigned extra_byte; ERL_NIF_TERM ret; - if (argc != 4) - goto bad_arg; + ASSERT(argc == 4); + if (!get_bn_from_bin(env, argv[0], &bn_base)) goto bad_arg; if (!get_bn_from_bin(env, argv[1], &bn_exponent)) diff --git a/lib/crypto/c_src/chacha20.c b/lib/crypto/c_src/chacha20.c index 51a24a43e9..5761383c95 100644 --- a/lib/crypto/c_src/chacha20.c +++ b/lib/crypto/c_src/chacha20.c @@ -29,8 +29,8 @@ ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM a const EVP_CIPHER *cipher; ERL_NIF_TERM ret; - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)) goto bad_arg; if (key_bin.size != 32) @@ -81,8 +81,8 @@ ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned char *out; int outl = 0; - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!enif_get_resource(env, argv[0], evp_cipher_ctx_rtype, (void**)&ctx)) goto bad_arg; if (!enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) diff --git a/lib/crypto/c_src/cmac.c b/lib/crypto/c_src/cmac.c index 303b7af6eb..196b7476e3 100644 --- a/lib/crypto/c_src/cmac.c +++ b/lib/crypto/c_src/cmac.c @@ -34,8 +34,8 @@ ERL_NIF_TERM cmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) unsigned char *outp; int cipher_len; - if (argc != 3) - goto bad_arg; + ASSERT(argc == 3); + if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) goto bad_arg; if ((cipherp = get_cipher_type(argv[0], key.size)) == NULL) diff --git a/lib/crypto/c_src/dh.c b/lib/crypto/c_src/dh.c index d077007a52..38eb534d99 100644 --- a/lib/crypto/c_src/dh.c +++ b/lib/crypto/c_src/dh.c @@ -40,8 +40,7 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar EVP_PKEY *dhkey = NULL, *params = NULL; #endif - if (argc != 4) - goto bad_arg; + ASSERT(argc == 4); if (argv[0] != atom_undefined) { if (!get_bn_from_bin(env, argv[0], &priv_key_in)) @@ -209,8 +208,7 @@ ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg the peer's public key (other_pub_key), the parameters p & q */ - if (argc != 3) - goto bad_arg; + ASSERT(argc == 3); if (!get_bn_from_bin(env, argv[0], &other_pub_key)) goto bad_arg; diff --git a/lib/crypto/c_src/ecdh.c b/lib/crypto/c_src/ecdh.c index ee4b352730..9e3f460519 100644 --- a/lib/crypto/c_src/ecdh.c +++ b/lib/crypto/c_src/ecdh.c @@ -39,8 +39,8 @@ 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; - if (argc != 3) - goto bad_arg; + ASSERT(argc == 3); + if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key)) goto bad_arg; if ((group = EC_GROUP_dup(EC_KEY_get0_group(key))) == NULL) diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c index 715d9bed40..6692ccd734 100644 --- a/lib/crypto/c_src/engine.c +++ b/lib/crypto/c_src/engine.c @@ -124,8 +124,8 @@ ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ struct engine_ctx *ctx = NULL; // Get Engine Id - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if (!enif_inspect_binary(env, argv[0], &engine_id_bin)) goto bad_arg; @@ -173,8 +173,8 @@ ERL_NIF_TERM engine_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] struct engine_ctx *ctx; // Get Engine - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) goto bad_arg; @@ -197,8 +197,8 @@ ERL_NIF_TERM engine_free_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] struct engine_ctx *ctx; // Get Engine - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) goto bad_arg; @@ -220,8 +220,8 @@ ERL_NIF_TERM engine_finish_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv struct engine_ctx *ctx; // Get Engine - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) goto bad_arg; @@ -241,8 +241,7 @@ ERL_NIF_TERM engine_finish_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv ERL_NIF_TERM engine_load_dynamic_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* () */ #ifdef HAS_ENGINE_SUPPORT - if (argc != 0) - return enif_make_badarg(env); + ASSERT(argc == 0); ENGINE_load_dynamic(); return atom_ok; @@ -263,8 +262,8 @@ ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const ERL_NIF int cmds_loaded = 0; // Get Engine - if (argc != 3) - goto bad_arg; + ASSERT(argc == 3); + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) goto bad_arg; @@ -331,8 +330,8 @@ ERL_NIF_TERM engine_add_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) struct engine_ctx *ctx; // Get Engine - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) goto bad_arg; @@ -358,8 +357,8 @@ ERL_NIF_TERM engine_remove_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv struct engine_ctx *ctx; // Get Engine - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) goto bad_arg; @@ -385,8 +384,8 @@ ERL_NIF_TERM engine_register_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar unsigned int method; // Get Engine - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) goto bad_arg; if (!enif_get_uint(env, argv[1], &method)) @@ -490,8 +489,8 @@ ERL_NIF_TERM engine_unregister_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned int method; // Get Engine - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) goto bad_arg; if (!enif_get_uint(env, argv[1], &method)) @@ -581,8 +580,7 @@ ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a ErlNifBinary engine_bin; struct engine_ctx *ctx = NULL; - if (argc != 0) - goto bad_arg; + ASSERT(argc == 0); if ((engine = ENGINE_get_first()) == NULL) { if (!enif_alloc_binary(0, &engine_bin)) @@ -600,7 +598,6 @@ ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a ret = enif_make_tuple2(env, atom_ok, result); goto done; - bad_arg: err: ret = enif_make_badarg(env); @@ -623,8 +620,8 @@ ERL_NIF_TERM engine_get_next_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar struct engine_ctx *ctx, *next_ctx = NULL; // Get Engine - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) goto bad_arg; @@ -667,8 +664,8 @@ ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv struct engine_ctx *ctx = NULL; // Get Engine - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) goto bad_arg; @@ -705,8 +702,8 @@ ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar struct engine_ctx *ctx; // Get Engine - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) goto bad_arg; @@ -796,8 +793,7 @@ ERL_NIF_TERM engine_get_all_methods_nif(ErlNifEnv* env, int argc, const ERL_NIF_ ERL_NIF_TERM method_array[12]; unsigned int i = 0; - if (argc != 0) - return enif_make_badarg(env); + ASSERT(argc == 0); #ifdef ENGINE_METHOD_RSA method_array[i++] = atom_engine_method_rsa; diff --git a/lib/crypto/c_src/evp.c b/lib/crypto/c_src/evp.c index 7aa4be1f9f..3bf66bfffe 100644 --- a/lib/crypto/c_src/evp.c +++ b/lib/crypto/c_src/evp.c @@ -32,8 +32,7 @@ ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar size_t max_size; int key_bin_alloc = 0; - if (argc != 3) - goto bad_arg; + ASSERT(argc == 3); if (argv[0] == atom_x25519) type = EVP_PKEY_X25519; @@ -110,8 +109,7 @@ ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a size_t key_len; unsigned char *out_pub = NULL, *out_priv = NULL; - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); if (argv[0] == atom_x25519) type = EVP_PKEY_X25519; diff --git a/lib/crypto/c_src/hash.c b/lib/crypto/c_src/hash.c index 000eae047a..d67e68f857 100644 --- a/lib/crypto/c_src/hash.c +++ b/lib/crypto/c_src/hash.c @@ -68,8 +68,8 @@ ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) unsigned ret_size; unsigned char *outp; - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if ((digp = get_digest_type(argv[0])) == NULL) goto bad_arg; if (!enif_inspect_iolist_as_binary(env, argv[1], &data)) @@ -106,8 +106,8 @@ ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) struct evp_md_ctx *ctx = NULL; ERL_NIF_TERM ret; - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if ((digp = get_digest_type(argv[0])) == NULL) goto bad_arg; if (digp->md.p == NULL) @@ -141,8 +141,8 @@ ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] ErlNifBinary data; ERL_NIF_TERM ret; - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx)) goto bad_arg; if (!enif_inspect_iolist_as_binary(env, argv[1], &data)) @@ -181,8 +181,8 @@ ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) unsigned ret_size; unsigned char *outp; - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx)) goto bad_arg; @@ -224,8 +224,8 @@ ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) init_fun ctx_init = 0; unsigned char *outp; - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if ((digp = get_digest_type(argv[0])) == NULL) goto bad_arg; if (digp->md.p == NULL) @@ -306,8 +306,8 @@ ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] size_t ctx_size = 0; update_fun ctx_update = 0; - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!enif_get_tuple(env, argv[0], &arity, &tuple)) goto bad_arg; if (arity != 2) @@ -404,8 +404,8 @@ ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) final_fun ctx_final = 0; unsigned char *outp; - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if (!enif_get_tuple(env, argv[0], &arity, &tuple)) goto bad_arg; if (arity != 2) diff --git a/lib/crypto/c_src/hmac.c b/lib/crypto/c_src/hmac.c index 9418e7950e..c41e50eb35 100644 --- a/lib/crypto/c_src/hmac.c +++ b/lib/crypto/c_src/hmac.c @@ -56,8 +56,7 @@ ERL_NIF_TERM hmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ERL_NIF_TERM ret; unsigned char *outp; - if (argc != 3 && argc != 4) - goto bad_arg; + ASSERT(argc == 3 || argc == 4); if ((digp = get_digest_type(argv[0])) == NULL) goto bad_arg; @@ -125,8 +124,8 @@ ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ERL_NIF_TERM ret; struct hmac_context *obj = NULL; - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if ((digp = get_digest_type(argv[0])) == NULL) goto bad_arg; if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) @@ -180,8 +179,8 @@ ERL_NIF_TERM hmac_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] ErlNifBinary data; struct hmac_context *obj = NULL; - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!enif_get_resource(env, argv[0], hmac_context_rtype, (void**)&obj)) goto bad_arg; if (!enif_inspect_iolist_as_binary(env, argv[1], &data)) @@ -223,8 +222,8 @@ ERL_NIF_TERM hmac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) unsigned int req_len = 0; unsigned int mac_len; - if (argc != 1 && argc != 2) - goto bad_arg; + ASSERT(argc == 1 || argc == 2); + if (!enif_get_resource(env, argv[0], hmac_context_rtype, (void**)&obj)) goto bad_arg; if (argc == 2) { diff --git a/lib/crypto/c_src/info.c b/lib/crypto/c_src/info.c index 2411968b95..42f477fead 100644 --- a/lib/crypto/c_src/info.c +++ b/lib/crypto/c_src/info.c @@ -74,8 +74,7 @@ ERL_NIF_TERM info_lib(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) int ver_num; unsigned char *out_name, *out_ver; - if (argc != 0) - goto bad_arg; + ASSERT(argc == 0); name_sz = strlen(libname); ver = SSLeay_version(SSLEAY_VERSION); @@ -103,7 +102,6 @@ ERL_NIF_TERM info_lib(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) enif_make_int(env, ver_num), ver_term)); - bad_arg: err: return enif_make_badarg(env); } diff --git a/lib/crypto/c_src/math.c b/lib/crypto/c_src/math.c index a7a385e404..85494bbc93 100644 --- a/lib/crypto/c_src/math.c +++ b/lib/crypto/c_src/math.c @@ -27,8 +27,8 @@ ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) size_t i; ERL_NIF_TERM ret; - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!enif_inspect_iolist_as_binary(env, argv[0], &d1)) goto bad_arg; if (!enif_inspect_iolist_as_binary(env, argv[1], &d2)) diff --git a/lib/crypto/c_src/pkey.c b/lib/crypto/c_src/pkey.c index 33905e7753..4e76f817bc 100644 --- a/lib/crypto/c_src/pkey.c +++ b/lib/crypto/c_src/pkey.c @@ -1033,8 +1033,7 @@ ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) int algo_init = 0; unsigned char *label_copy = NULL; - if (argc != 6) - goto bad_arg; + ASSERT(argc == 6); is_private = (argv[4] == atom_true); is_encrypt = (argv[5] == atom_true); @@ -1345,8 +1344,8 @@ ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM DSA *dsa = NULL; ERL_NIF_TERM result[8]; - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (get_pkey_private_key(env, argv[0], argv[1], &pkey) != PKEY_OK) goto bad_arg; diff --git a/lib/crypto/c_src/poly1305.c b/lib/crypto/c_src/poly1305.c index da434e4eb9..db3433dce3 100644 --- a/lib/crypto/c_src/poly1305.c +++ b/lib/crypto/c_src/poly1305.c @@ -33,8 +33,8 @@ ERL_NIF_TERM poly1305_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) size_t size; int ret_bin_alloc = 0; - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!enif_inspect_binary(env, argv[0], &key_bin)) goto bad_arg; if (key_bin.size != 32) diff --git a/lib/crypto/c_src/rand.c b/lib/crypto/c_src/rand.c index cf793a7aac..3812ae0991 100644 --- a/lib/crypto/c_src/rand.c +++ b/lib/crypto/c_src/rand.c @@ -27,8 +27,8 @@ ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned char* data; ERL_NIF_TERM ret; - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if (!enif_get_uint(env, argv[0], &bytes)) goto bad_arg; if (bytes > INT_MAX) @@ -54,8 +54,8 @@ ERL_NIF_TERM strong_rand_range_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM BIGNUM *bn_range = NULL, *bn_rand = NULL; ERL_NIF_TERM ret; - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if (!get_bn_from_bin(env, argv[0], &bn_range)) goto bad_arg; @@ -89,8 +89,8 @@ ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ int dlen; ERL_NIF_TERM ret; - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!get_bn_from_mpint(env, argv[0], &bn_from)) goto bad_arg; if (!get_bn_from_mpint(env, argv[1], &bn_rand)) @@ -134,8 +134,8 @@ ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Seed) */ ErlNifBinary seed_bin; - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if (!enif_inspect_binary(env, argv[0], &seed_bin)) goto bad_arg; if (seed_bin.size > INT_MAX) diff --git a/lib/crypto/c_src/rc4.c b/lib/crypto/c_src/rc4.c index 63f8000839..e423661097 100644 --- a/lib/crypto/c_src/rc4.c +++ b/lib/crypto/c_src/rc4.c @@ -29,8 +29,8 @@ ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) CHECK_NO_FIPS_MODE(); - if (argc != 1) - goto bad_arg; + ASSERT(argc == 1); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key)) goto bad_arg; if (key.size > INT_MAX) @@ -61,8 +61,8 @@ ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM CHECK_NO_FIPS_MODE(); - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!enif_inspect_iolist_as_binary(env, argv[0], &state)) goto bad_arg; if (state.size != sizeof(RC4_KEY)) diff --git a/lib/crypto/c_src/rsa.c b/lib/crypto/c_src/rsa.c index 540bc1b54d..e9f29aa496 100644 --- a/lib/crypto/c_src/rsa.c +++ b/lib/crypto/c_src/rsa.c @@ -214,8 +214,8 @@ static ERL_NIF_TERM rsa_generate_key(ErlNifEnv* env, int argc, const ERL_NIF_TER BN_GENCB intr_cb_buf; #endif - if (argc != 2) - goto bad_arg; + ASSERT(argc == 2); + if (!enif_get_int(env, argv[0], &modulus_bits)) goto bad_arg; if (modulus_bits < 256) diff --git a/lib/crypto/c_src/srp.c b/lib/crypto/c_src/srp.c index 5a49a1c1b4..2979048006 100644 --- a/lib/crypto/c_src/srp.c +++ b/lib/crypto/c_src/srp.c @@ -32,8 +32,7 @@ ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] CHECK_NO_FIPS_MODE(); - if (argc != 5) - goto bad_arg; + ASSERT(argc == 5); if (!get_bn_from_bin(env, argv[0], &bn_multiplier)) goto bad_arg; @@ -124,8 +123,8 @@ ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar CHECK_NO_FIPS_MODE(); - if (argc != 7) - goto bad_arg; + ASSERT(argc == 7); + if (!get_bn_from_bin(env, argv[0], &bn_a)) goto bad_arg; if (!get_bn_from_bin(env, argv[1], &bn_u)) @@ -232,8 +231,8 @@ ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar CHECK_NO_FIPS_MODE(); - if (argc != 5) - goto bad_arg; + ASSERT(argc == 5); + if (!get_bn_from_bin(env, argv[0], &bn_verifier)) goto bad_arg; if (!get_bn_from_bin(env, argv[1], &bn_b)) -- cgit v1.2.3 From f60984150457bbf3c600f8b241a49765a04b76c2 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Tue, 15 Jan 2019 08:58:48 -0800 Subject: When using DEBUG, avoid comparison of different signs --- lib/crypto/c_src/aes.c | 2 +- lib/crypto/c_src/chacha20.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/crypto/c_src/aes.c b/lib/crypto/c_src/aes.c index 2df123e44e..2f30ec8a58 100644 --- a/lib/crypto/c_src/aes.c +++ b/lib/crypto/c_src/aes.c @@ -257,7 +257,7 @@ ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM if (EVP_CipherUpdate(new_ctx->ctx, out, &outl, data_bin.data, (int)data_bin.size) != 1) goto err; - ASSERT(outl == data_bin.size); + ASSERT(outl >= 0 && (size_t)outl == data_bin.size); ret = enif_make_tuple2(env, enif_make_resource(env, new_ctx), cipher_term); CONSUME_REDS(env,data_bin); diff --git a/lib/crypto/c_src/chacha20.c b/lib/crypto/c_src/chacha20.c index 5761383c95..cfcc395dca 100644 --- a/lib/crypto/c_src/chacha20.c +++ b/lib/crypto/c_src/chacha20.c @@ -101,7 +101,7 @@ ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM goto err; if (EVP_CipherUpdate(new_ctx->ctx, out, &outl, data_bin.data, (int)data_bin.size) != 1) goto err; - ASSERT(outl == data_bin.size); + ASSERT(outl >= 0 && (size_t)outl == data_bin.size); ret = enif_make_tuple2(env, enif_make_resource(env, new_ctx), cipher_term); CONSUME_REDS(env, data_bin); -- cgit v1.2.3 From 0b67f754bd6e0f22b1b7e1c9b2270f8118a66f38 Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Wed, 16 Jan 2019 07:29:30 -0800 Subject: Fix label s/out_err/err/ in OPENSSL_NO_EC2M case per PR comment --- lib/crypto/c_src/ec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/crypto/c_src/ec.c b/lib/crypto/c_src/ec.c index 6da262e6a5..51a3547694 100644 --- a/lib/crypto/c_src/ec.c +++ b/lib/crypto/c_src/ec.c @@ -99,7 +99,7 @@ static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg) } else if (f_arity == 3 && field[0] == atom_characteristic_two_field) { #if defined(OPENSSL_NO_EC2M) enif_raise_exception(env, atom_notsup); - goto out_err; + goto err; #else /* {characteristic_two_field, M, Basis} */ int b_arity = -1; -- cgit v1.2.3