CMAC key generation with OpenSSL EVP_DigestSign * does not work

I am trying to generate a key to calculate CMAC using OpenSSL.

However, they seem to fail with the error message copied below. Can anyone indicate where the problem is? Has anyone done CMAC with EVP_DigestSign* calls?

Here is the piece of code that was built from the example at https://wiki.openssl.org/index.php/EVP_Key_and_Parameter_Generation :

 BIO *out = NULL; out = BIO_new(BIO_s_file()); if (out == NULL) return -1; BIO_set_fp(out, stdout, BIO_NOCLOSE); EVP_MD_CTX* rctx = NULL; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *kctx = NULL; rctx = EVP_MD_CTX_create(); if(rctx == NULL) { printf("EVP_MD_CTX_create failed\n"); } if(!EVP_PKEY_keygen_init(kctx)){ printf("EVP_PKEY_keygen_init failed\n"); } if (EVP_PKEY_CTX_ctrl(kctx, -1, EVP_PKEY_OP_KEYGEN,EVP_PKEY_CTRL_CIPHER,0, (void *)EVP_aes_256_ecb()) <= 0) printf("EVP_PKEY_CTX_ctrl 1 failed\n"); if (EVP_PKEY_CTX_ctrl(kctx, -1, EVP_PKEY_OP_KEYGEN,EVP_PKEY_CTRL_SET_MAC_KEY,/*key length*/32, "01234567890123456789012345678901") <= 0) printf("Set the key data failed 1\n"); 

Here's the error:

 EVP_PKEY_CTX_ctrl failed 3073898120:error:06093096:lib(6):func(147):reason(150):pmeth_gn.c:122: 3073898120:error:06089093:lib(6):func(137):reason(147):pmeth_lib.c:390: 

And on line 390 in pmeth_lib.c:

 EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); 

I am using OpenSSL 1.0.1e.

See also How to calculate AES CMAC using CMAC_xxx OpenSSL functions?

+7
openssl cmac
source share
2 answers

I managed to get CMAC to work using EVP interfaces. In addition, the key generation part that previously did not work is working. Here is the code. As you can see, I gave an example posted here: How to calculate AES CMAC using OpenSSL? Which uses OpenACL CMAC_Init / Update / Final interfaces and tried various NIST values ​​to check if the EVP interfaces for CMAC work: Here is a code snippet. The key generation is also working now. Please let me know if there is something that I missed. I have a comment when using EVP. See also section below.

 /* * CMACSiging.c */ #include <stdio.h> #include <openssl/cmac.h> #include <openssl/err.h> #include <stdio.h> #include <stdlib.h> #include <openssl/evp.h> #include <string.h> typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; void printBytes(unsigned char *buf, size_t len) { int i; for(i=0; i<len; i++) { printf("%02x", buf[i]); } printf("\n"); } EVP_PKEY *generate_key(int type) { EVP_PKEY_CTX *pctx = NULL, *kctx = NULL; EVP_PKEY *params = NULL, *key = NULL; unsigned char k[] = {0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4}; /* Create context for the key generation */ if(!(kctx = EVP_PKEY_CTX_new_id(type, NULL))) goto err; /* Generate the key */ if(!EVP_PKEY_keygen_init(kctx)) goto err; if(type == EVP_PKEY_CMAC) { if (EVP_PKEY_CTX_ctrl(kctx, -1, EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_CIPHER, 0, (void *)EVP_aes_256_cbc()) <= 0) goto err; if (EVP_PKEY_CTX_ctrl(kctx, -1, EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_SET_MAC_KEY, sizeof(k), k) <= 0) goto err; } if (!EVP_PKEY_keygen(kctx, &key)) goto err; goto end; err: end: if(pctx) EVP_PKEY_CTX_free(pctx); if(params) EVP_PKEY_free(params); if(kctx) EVP_PKEY_CTX_free(kctx); return key; } void trial(uint8_t *msg, uint8_t mlen, uint8_t *key, uint8_t keylen, uint8_t **sig, uint8_t *slen) { //16 byte msg with 32 byte key with aes 256 cbc based CMAC if(!msg || !mlen || !key) { //handleError } if(*sig) OPENSSL_free(*sig); *sig = NULL; *slen = 0; EVP_MD_CTX* ctx = NULL; EVP_PKEY *pkey = NULL; const EVP_MD* md = NULL; OpenSSL_add_all_digests(); do { ctx = EVP_MD_CTX_create(); if(ctx == NULL) { printf("EVP_MD_CTX_create failed\n"); break; // failed } if(!(md = EVP_get_digestbyname("SHA256"))) printf("EVP_get_digestbyname failed\n"); printf("Over to EVP calls \n"); if(!(pkey = generate_key(EVP_PKEY_CMAC))) printf("Error 5 \n"); int rc ; rc = EVP_DigestSignInit(ctx, NULL, md, NULL, pkey); if(rc != 1) { printf("EVP_DigestSignInit failed\n"); ERR_print_errors_fp(stdout); break; } rc = EVP_DigestSignUpdate(ctx, msg, mlen); if(rc != 1) { printf("EVP_DigestSignUpdate failed\n"); ERR_print_errors_fp(stdout); break; } size_t req = 0; rc = EVP_DigestSignFinal(ctx, NULL, &req); if(rc != 1) { printf("EVP_DigestSignFinal failed\n"); ERR_print_errors_fp(stdout); break; } if(!(req > 0)) { printf("EVP_DigestSignFinal failed (2)\n"); break; } *sig = OPENSSL_malloc(req); if(*sig == NULL) { printf("OPENSSL_malloc failed, error \n"); break; } *slen = req; rc = EVP_DigestSignFinal(ctx, *sig, slen); if(rc != 1) { printf("EVP_DigestSignFinal failed (3)\n"); ERR_print_errors_fp(stdout); break; } } while(0); if(ctx) { EVP_MD_CTX_destroy(ctx); ctx = NULL; } } int main(int argc, char *argv[]) { // https://tools.ietf.org/html/rfc4493 // K, M and T from // http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf // D.1 AES-128 // K: 2b7e1516 28aed2a6 abf71588 09cf4f3c unsigned char key[] = {0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4}; // M: 6bc1bee2 2e409f96 e93d7e11 7393172a Mlen: 128 unsigned char message[] = { 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a }; unsigned char mact[16] = {0}; size_t mactlen; CMAC_CTX *ctx = CMAC_CTX_new(); CMAC_Init(ctx, key, 32, EVP_aes_256_cbc(), NULL); printf("message length = %lu bytes (%lu bits)\n",sizeof(message), sizeof(message)*8); CMAC_Update(ctx, message, sizeof(message)); CMAC_Final(ctx, mact, &mactlen); printBytes(mact, mactlen); //expected result T = 070a16b4 6b4d4144 f79bdd9d d04a287c CMAC_CTX_free(ctx); uint8_t key_len = sizeof(key); uint8_t mlen = sizeof(message); uint8_t *dgst = NULL; size_t dlen; trial( message, mlen, key, key_len, &dgst, &dlen); printf("length of sig = %d\n", dlen); printf("CMAC returned from trial is: "); int i; for(i = 0; i < dlen; i++) printf("%02x", dgst[i]); printf("\n"); return 0; } 

Comment:

As you can see from the code, it is important to note that when using EVP_DigestSignInit, the structure of the envelope of the message digest (EVP_MD) should not be interpreted as NULL, as indicated in the OpenSSL Wiki (ATLEAST for OpenSSL 1.0.2e, where I tested):

Note. There is no difference in the API between signing using an asymmetric algorithm and generating a MAC code. In the case of CMAC, no message digest function is required (can be passed NULL). signing using EVP_Sign * functions is very similar to the above example, except for the support of MAC codes. Please note that CMAC is only supported in the (not yet released) version 1.1.0 of OpenSSL.

If NULL is passed, I get a NULL error message. It seems that what is transmitted does not affect the generation of CMAC, since this structure is mostly ignored. I hope the guys from OpenSSL can clarify. Thanks!!

+2
source share

This is currently not possible because it is not supported.

The only thing you can try is to use the latest OpenSSL and try the same thing, but I doubt it will work. Try it without EVP.

+1
source share

All Articles