问题描述
我正在尝试生成用于使用OpenSSL计算CMAC的密钥.
I am trying to generate key for computing the CMAC with OpenSSL.
但是,这些似乎失败,并复制了以下错误消息.有人可以指出问题出在哪里吗?有人用EVP_DigestSign*
呼叫完成了CMAC吗?
However, these seem to fail with the error message copied below. Can someone point out where the problem is?Has anybody done CMAC with EVP_DigestSign*
calls?
这是从 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");
这里是错误:
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:
在pmeth_lib.c中的第390行:
And at line 390 in pmeth_lib.c:
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
我正在使用OpenSSL 1.0.1e.
I am using OpenSSL 1.0.1e.
另请参见如何计算AES使用OpenSSL的CMAC_xxx函数的CMAC?
推荐答案
我设法使用EVP接口使CMAC正常工作.较早失败的密钥生成部分也可以使用.这是代码.如您所见,我以此处发布的示例为例:如何计算AES CMAC使用OpenSSL?,它使用OpenSSL的CMAC_Init/Update/Final接口,并尝试了各种NIST值来检查EVP接口是否适用于CMAC:这是代码段.密钥生成现在也可以使用.请让我知道是否有任何我忽略的事情.我在使用EVP时确实有评论.也请参见下面的备注部分.
I managed to get CMAC working using EVP interfaces. The key generation part which failed earlier also works. Here is the code. As you can see, I have taken the example posted here: How to calculate AES CMAC using OpenSSL? which uses the CMAC_Init/Update/Final interfaces of OpenSSL and tried various NIST values to check if the EVP interfaces work for CMAC: Here is the code snippet. The key generation also works now. Please let me know if there is anything that I have overlooked. I do have a remark while using EVP. Please see the remark section below as well.
/*
* 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;
}
备注:
从代码中可以看出,重要的是要注意,当使用EVP_DigestSignInit时,消息摘要信封结构(EVP_MD)不应被视为NULL,如OpenSSL Wiki(OpenSSL 1.0.2e的ATLEAST)所述.经过测试):
As seen in code, what is important is to note that when using EVP_DigestSignInit, the message digest envelope structure (EVP_MD) should not be taken as NULL as mentioned in the OpenSSL Wiki (ATLEAST for OpenSSL 1.0.2e which is where I tested):
如果传递了NULL,我将得到一个摘要为NULL的错误.似乎传递的内容不会影响CMAC的生成,因为此结构基本上被忽略了.我希望这里的OpenSSL人士可以澄清一下.谢谢!
If NULL is passed, I get an error that the digest is NULL.It seems like what is passed doesn't affect the CMAC generation as this struct is basically ignored. I hope the OpenSSL guys out here can clarify. Thanks!!
这篇关于使用OpenSSL EVP_DigestSign *生成CMAC密钥失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!