diff options
Diffstat (limited to 'lib/crypto/c_src/cmac.c')
-rw-r--r-- | lib/crypto/c_src/cmac.c | 91 |
1 files changed, 38 insertions, 53 deletions
diff --git a/lib/crypto/c_src/cmac.c b/lib/crypto/c_src/cmac.c index 49e67ccf29..a1564f6661 100644 --- a/lib/crypto/c_src/cmac.c +++ b/lib/crypto/c_src/cmac.c @@ -18,71 +18,56 @@ * %CopyrightEnd% */ -#include "cmac.h" -#include "cipher.h" +#include "common.h" -ERL_NIF_TERM cmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Type, Key, Data) */ -#if defined(HAVE_CMAC) - const struct cipher_type_t *cipherp; - const EVP_CIPHER *cipher; - CMAC_CTX *ctx = NULL; - ErlNifBinary key; - ErlNifBinary data; - ERL_NIF_TERM ret; - size_t ret_size; - unsigned char *outp; - int cipher_len; +/***************************************************************** + * + * This file has functions for compatibility with cryptolibs + * lacking the EVP_Digest API. + * + * See mac.c for the implementation using the EVP interface. + * + ****************************************************************/ - ASSERT(argc == 3); +#if defined(HAVE_CMAC) && !defined(HAVE_EVP_PKEY_new_CMAC_key) - 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 (cipherp->flags & (NON_EVP_CIPHER | AEAD_CIPHER)) - goto bad_arg; - if (!enif_inspect_iolist_as_binary(env, argv[2], &data)) - goto bad_arg; +#include "cmac.h" - if (FORBIDDEN_IN_FIPS(cipherp)) - return enif_raise_exception(env, atom_notsup); - if ((cipher = cipherp->cipher.p) == NULL) - return enif_raise_exception(env, atom_notsup); +int cmac_low_level(ErlNifEnv* env, + ErlNifBinary key_bin, const EVP_CIPHER* cipher, ErlNifBinary text, + ErlNifBinary *ret_bin, int *ret_bin_alloc, ERL_NIF_TERM *return_term) +{ + CMAC_CTX *ctx = NULL; + size_t size; 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; + goto local_err; - ASSERT(ret_size == (unsigned)EVP_CIPHER_block_size(cipher)); - CONSUME_REDS(env, data); - goto done; + if (!CMAC_Init(ctx, key_bin.data, key_bin.size, cipher, NULL)) + goto local_err; - bad_arg: - return enif_make_badarg(env); + if (!CMAC_Update(ctx, text.data, text.size)) + goto local_err; - err: - ret = atom_notsup; + if ((size = (size_t)EVP_CIPHER_block_size(cipher)) < 0) + goto local_err; - done: + if (!enif_alloc_binary(size, ret_bin)) + goto local_err; + *ret_bin_alloc = 1; + + if (!CMAC_Final(ctx, ret_bin->data, &ret_bin->size)) + goto local_err; + + CMAC_CTX_free(ctx); + return 1; + + local_err: 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 - * no longer maintained. */ - return atom_notsup; -#endif + *return_term = EXCP_ERROR(env,"Compat cmac"); + return 0; } +#endif |