aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoug Hogan <[email protected]>2019-01-03 15:36:39 -0800
committerDoug Hogan <[email protected]>2019-01-08 00:08:21 -0800
commit8dcf1c1b4d487f1822ba1d78a6de3ef3c465eead (patch)
treed1b3f0542f4cf74ac7013109ff5945f0a5ea25b4
parenta309fd02f97dbc35eb8b7d3bafdb219a7275f79b (diff)
downloadotp-8dcf1c1b4d487f1822ba1d78a6de3ef3c465eead.tar.gz
otp-8dcf1c1b4d487f1822ba1d78a6de3ef3c465eead.tar.bz2
otp-8dcf1c1b4d487f1822ba1d78a6de3ef3c465eead.zip
Revamp cmac_nif()
* Add error checking on all OpenSSL and Erlang calls.
-rw-r--r--lib/crypto/c_src/cmac.c60
1 files 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