Encryption 在openssl中为aad使用EVP_aes_128_gcm,大小不超过16倍

Encryption 在openssl中为aad使用EVP_aes_128_gcm,大小不超过16倍,encryption,openssl,aes-gcm,evp-cipher,Encryption,Openssl,Aes Gcm,Evp Cipher,我试图使用openssl EVP(EVP_aes_128_gcm)作为GMAC的接口。我正在根据NIST的CAVP GCM测试向量()测试代码。 问题是:当aad大小是16的倍数时,代码可以给出正确的GMAC标记。但如果大小不是16的倍数,则结果是错误的。有什么问题吗 代码是: #include <openssl/bn.h> #include <openssl/rsa.h> #include <openssl/pem.h> #include <opens

我试图使用openssl EVP(EVP_aes_128_gcm)作为GMAC的接口。我正在根据NIST的CAVP GCM测试向量()测试代码。 问题是:当aad大小是16的倍数时,代码可以给出正确的GMAC标记。但如果大小不是16的倍数,则结果是错误的。有什么问题吗

代码是:

#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/engine.h>

#include <assert.h>
#include <stdio.h>

void dump(const void *p, size_t len)
{
    const unsigned char *a = p;
    size_t i;
    for (i = 0; i < len; i++) {
        printf("%02x", a[i]);
    }
    puts("");
}

void main(void){

    /*
    // key = 16; aad = 20; WRONG tag computed
    u_char key[] = {0x2f,0xb4,0x5e,0x5b,0x8f,0x99,0x3a,0x2b,0xfe,0xbc,0x4b,0x15,0xb5,0x33,0xe0,0xb4};
    u_char iv[] =  {0x5b,0x05,0x75,0x5f,0x98,0x4d,0x2b,0x90,0xf9,0x4b,0x80,0x27};
    u_char aad[] = {0xe8,0x54,0x91,0xb2,0x20,0x2c,0xaf,0x1d,0x7d,0xce,0x03,0xb9,0x7e,0x09,0x33,0x1c,
                    0x32,0x47,0x39,0x41};
    u_char tag[16] = {};
    u_char exp[] =   {0xc7,0x5b,0x78,0x32,0xb2,0xa2,0xd9,0xbd,0x82,0x74,0x12,0xb6,0xef,0x57,0x69,0xdb}; // expected result
    */

    // key = 16; aad = 48; CORRECTED tag computed
    u_char key[] = {0x99,0xe3,0xe8,0x79,0x3e,0x68,0x6e,0x57,0x1d,0x82,0x85,0xc5,0x64,0xf7,0x5e,0x2b};
    u_char iv[] =  {0xc2,0xdd,0x0a,0xb8,0x68,0xda,0x6a,0xa8,0xad,0x9c,0x0d,0x23};
    u_char aad[] = {0xb6,0x68,0xe4,0x2d,0x4e,0x44,0x4c,0xa8,0xb2,0x3c,0xfd,0xd9,0x5a,0x9f,0xed,0xd5,
                    0x17,0x8a,0xa5,0x21,0x14,0x48,0x90,0xb0,0x93,0x73,0x3c,0xf5,0xcf,0x22,0x52,0x6c,
                    0x59,0x17,0xee,0x47,0x65,0x41,0x80,0x9a,0xc6,0x86,0x7a,0x8c,0x39,0x93,0x09,0xfc};

    u_char tag[16] = {};
    u_char exp[] =   {0x3f,0x4f,0xba,0x10,0x0e,0xaf,0x1f,0x34,0xb0,0xba,0xad,0xaa,0xe9,0x99,0x5d,0x85}; // expected result


    int rc = 0, unused;
    unsigned int i;
    EVP_CIPHER_CTX *ctx = NULL;

    ctx = EVP_CIPHER_CTX_new();
    assert(ctx != NULL);

    rc = EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
    assert(rc == 1);

    rc = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, sizeof(iv), NULL);
    assert(rc == 1);

    rc = EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv);
    assert(rc == 1);

    rc = EVP_EncryptUpdate(ctx, NULL, &unused, aad, sizeof(aad));
    assert(rc == 1);

    rc = EVP_EncryptFinal_ex(ctx, NULL, &unused);
    assert(rc == 1);

    rc = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, sizeof(tag), tag);
    assert(rc == 1);

    EVP_CIPHER_CTX_free(ctx);

    printf("should be: ");
    dump(exp, sizeof(exp));
    printf("result is: ");
    dump(tag, sizeof(tag));

}
输出错误

should be: c75b7832b2a2d9bd827412b6ef5769db
result is: e5fb99cb5b9658aa5d2caa3308e0ce6c
对于测试向量:

[Keylen = 128]
[IVlen = 96]
[PTlen = 0]
[AADlen = 384]
[Taglen = 128]

Count = 0
Key = 99e3e8793e686e571d8285c564f75e2b
IV = c2dd0ab868da6aa8ad9c0d23
PT = 
AAD = b668e42d4e444ca8b23cfdd95a9fedd5178aa521144890b093733cf5cf22526c5917ee476541809ac6867a8c399309fc
CT = 
Tag = 3f4fba100eaf1f34b0baadaae9995d85
输出正确:

should be: 3f4fba100eaf1f34b0baadaae9995d85
result is: 3f4fba100eaf1f34b0baadaae9995d85
我使用的版本是:
OpenSSL 1.0.1 2012年3月14日

我下载了最新的OpenSSL(OpenSSL 1.0.1j 2014年10月15日)。给出了修正后的结果。 Ubuntu 12.04LTS中的库存openssl(openssl 1.0.1 2012年3月14日)在这个特定的GMAC应用程序上可能有一些bug

非常感谢@owlstead!用于确认代码是否正确


顺便说一句。实际上我可能还有另一个问题,我们如何知道哪个openssl版本适合使用?

有趣的是,如果您不提供任何密文,可能是填充计算不正确。你能给我们看一下实际不正确的输出吗?我还没有直接提供与openssl兼容的RT。您能否提供OpenSSL的版本号,可能是一个bug。。。哦,使用的测试向量是什么?很抱歉打扰您:)我看不出您的代码有任何直接的问题,Java生成了预期的值……非常感谢您的快速回复!您是否尝试过AAD长度不等于键长度的情况?是的,该情况在Java上运行良好。如果没有得到更多的响应,我将自己尝试研究OpenSSL实现。仅使用AAD的测试,AAD.length为%n!=0未通过OpenSSL测试。我也会试试OpenSSL邮件列表。问题解决了!我下载了最新的openssl。此版本“OpenSSL 1.0.1j 2014年10月15日”给出了正确的结果。非常感谢你的帮助!对于安全库,唯一好的答案是“最新”版本(无需重新设计)。有时,您可以选择一个只应用了安全修复的版本,这可能也适用。使您的应用程序保持最新。并尝试使用运行时(如Java),将安全性置于功能和速度之上。我当然不会对OpenSSL的表现印象深刻(不过NSS可能更糟)。
should be: 3f4fba100eaf1f34b0baadaae9995d85
result is: 3f4fba100eaf1f34b0baadaae9995d85