diff options
-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 |