Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2021-43085: CMAC encryption result error caused by wrong implementation of CMAC_Final() · Issue #16873 · openssl/openssl

An Insecure Permissions vulnerability exists in the OpenSSL Project 3.0 due to an error in the implementation of the CMAC_Final() function.

CVE
#vulnerability#ios#mac#git

Hello.
I found a wrong output of CMAC encryption when using OpenSSL 3.0.0. The testfile is as follows:

#include <openssl/cmac.h>
#include <iostream>
#include <cstdio>
#include <iomanip>

using namespace std;

void cmac_aes_128_ecb(){
    const EVP_CIPHER* cipher = EVP_aes_128_ecb();
    CMAC_CTX* cmac_ctx = CMAC_CTX_new();
    const uint8_t key[] =  {0x9b, 0xe8, 0x42, 0x04, 0xa7, 0x1e, 0x31, 0xeb, 0xf4, 0xe0, 0xb1, 0x1a, 0xe2, 0x5c, 0xac, 0x2f};
    const uint8_t msg[] =  {0x9b, 0x6b, 0x6a, 0x5c, 0x1f, 0x0c, 0x5b, 0x7b, 0x01, 0x9b, 0x6b, 0x6a, 0x5c, 0x1f, 0x0c, 0x5b, 0x7b, 0x01} ;

    if(!CMAC_Init(cmac_ctx,key,sizeof(key),cipher,0)){
        printf("err1\n");
        return;
    }
    if(!CMAC_Update(cmac_ctx,msg,sizeof(msg))){
        printf("err2\n");
        return;
    }
    uint8_t res[32]={0};
    size_t len = 0;
    if(!CMAC_Final(cmac_ctx, res, &len)){
        printf("err3\n");
        return;
    }
    for(int i = 0; i < sizeof(res); i++){
        printf("%02x ", res[i]);
    }
    printf("\n");
}

int main(){
    printf("OpenSSL result:\n");
    cmac_aes_128_ecb();
    return 0;
}   

The expected output and OpenSSL’s output are:

expected output: 77 ab ed ce eb 46 8f 03 17 7e 66 7f eb 4d 85 24
OpenSSL's output: 43 be 6f 41 19 8a 60 ea e5 33 7d fc 8b 83 ae 09

By reading the source code, I found that OpenSSL has an error in the implementation of the CMAC_Final() function. According to CMAC algorithm, the final encryption logic should be:
1634794565
However, the OpenSSL’s implementation is:
1634794584(1)
The wrong place is probably in line 220~230 of openssl/crypto/cmac/cmac.c. I have confirmed that this error still exists in the latest version of the code.
I tried the following modifications and found that I can get the correct output:

if (lb == bl) {
        for (i = 0; i < bl; i++)
            ctx->last_block[i] = ctx->last_block[i] ^ ctx->k1[i];
    } else {
        ctx->last_block[lb] = 0x80;
        if (bl - lb > 1)
        memset(ctx->last_block + lb + 1, 0, bl - lb - 1);
        for (i = 0; i < bl; i++)
            ctx->last_block[i] = ctx->last_block[i] ^ ctx->k2[i];
    }
    for (i = 0; i < bl; i++)
            ctx->last_block[i] = ctx->last_block[i] ^ ctx->tbl[i];

    if (!EVP_Cipher(ctx->cctx, ctx->tbl, ctx->last_block, bl)) {
        OPENSSL_cleanse(out, bl);
        return 0;
    }
    for (i = 0; i < bl; i++)
        out[i] = ctx->tbl[i];

I hope that you can check this issue and I’m looking forward to your reply.
Have a good day!

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda