2016-01-25 42 views
7

OpenSSLでCMACを計算するための鍵を生成しようとしています。OpenSSL EVP_DigestSignでのCMAC鍵生成が失敗する

ただし、これらは以下のエラーメッセージが表示されて失敗するようです。誰かが問題がどこにあるのかを指摘できますか? 誰でもEVP_DigestSign*コールでCMACを行ったことがありますか?ここでエラー

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, "") <= 0) 
    printf("Set the key data failed 1\n"); 

:pmeth_lib.cで

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: 

そしてライン390で:

ここ

https://wiki.openssl.org/index.php/EVP_Key_and_Parameter_Generationに例から構成されたコードの一部であります

EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); 

私はOpenSSL 1.0.1eを使用しています。

は、それがサポートされていないので、それが現在不可能だHow to calculate AES CMAC using OpenSSL's CMAC_xxx functions?

+0

["Signing"](https://wiki.openssl.org/index.php/EVP_Signing_and_Verifying#Signing_2)セクションの最後には、CMACが_1.1.0_ OpenSSLバージョンでのみサポートされていることが記載されています。 CMACはOpenSSLの(未だリリースされていない)バージョン1.1.0でのみサポートされていることに注意してください。ただし、EVP APIを使用しない場合でも、CMACを使用できるはずです。可能な例については、[here](http://rubenlaguna.com/wp/2015/02/05/compute-aes-cmac-using-openssl-slash-libcrypto/)を参照してください。 – Castaglia

答えて

1

も参照してください。

あなたが試みることができるのは、最新のOpenSSLを使用して同じことを試してみることですが、それはうまくいくとは思っていません。 EVPなしで試してみてください。

2

EVACインターフェイスを使用してCMACを動作させることができました。先に失敗した鍵生成部分も機能します。ここにコードがあります。ご覧のとおり、ここに掲載されている例はHow to calculate AES CMAC using OpenSSL?で、OpenSSLのCMAC_Init/Update/Finalインターフェイスを使用し、さまざまなNIST値を試してEVPインターフェイスがCMACで動作するかどうかを試しました。ここにコードスニペットがあります。キー生成も今でも機能します。私が見落としたことがあれば教えてください。私はEVPを使用している間に発言をする。以下の注意事項のセクションもご覧ください。

/* 
* 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を使用する場合にOpenSSLで述べたように、メッセージエンベロープ構造(EVP_MD)のダイジェストがNULLとして解釈されるべきではないことに注意することですウィキ(私がテストされたOpenSSL 1.0.2eのための少なくとも)は:NULLが渡された場合は

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 (NULL can be passed). Signing using the EVP_Sign* functions is very similar to the above example, except there is no support for MAC codes. Note that CMAC is only supported in the (as yet unreleased) version 1.1.0 of OpenSSL.

、私はダイジェストがNULLであることをエラーが発生します。 この構造体は基本的に無視されるので、渡されたものはCMAC生成に影響を与えないようです。ここにあるOpenSSLの人が明らかにできることを願っています。ありがとう!!

関連する問題