diff options
author | Doug Hogan <[email protected]> | 2019-01-03 15:36:39 -0800 |
---|---|---|
committer | Doug Hogan <[email protected]> | 2019-01-08 00:08:21 -0800 |
commit | 8dcf1c1b4d487f1822ba1d78a6de3ef3c465eead (patch) | |
tree | d1b3f0542f4cf74ac7013109ff5945f0a5ea25b4 | |
parent | a309fd02f97dbc35eb8b7d3bafdb219a7275f79b (diff) | |
download | otp-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.c | 60 |
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 |