Main Content

Missing final step after hashing update operation

Hash is incomplete or non-secure

Since R2020a

Description

The defect occurs when, after an update operation on a message digest context, you do not perform a final step before you clean up or reinitialize the context.

When you use message digest functions, you typically initialize a message digest context and perform at least one update step to add data into the context. You then sign, verify, or retrieve the data in the context as a final step.

Risk

A missing final step might indicate that the hash is incomplete or is non-secure.

Fix

Perform a final step to sign, verify, or retrieve date from the message digest context before you clean up or reinitialize the context.

Examples

expand all


#include <stdlib.h>
#include <openssl/evp.h>


void func(unsigned char* src, int len, EVP_PKEY* pkey)
{
    int ret;

    EVP_MD_CTX ctx;
    EVP_MD_CTX_init(&ctx);

    ret = EVP_DigestVerifyInit(&ctx, NULL, EVP_sha256(), NULL, pkey);
    if (ret != 1) handle_error();

    ret = EVP_DigestVerifyUpdate(&ctx, src, len);
    if (ret != 1) handle_error();

    EVP_MD_CTX_cleanup(&ctx);
}

In this example, a verification context ctx is initialized and updated with data. The context is then cleaned up without being verified in a final step. Typically, you create a verification context to validate a previously signed message. Without the final step the signature on the message cannot be validated.

Correction — Perform Final Step Before Context Cleanup

One possible correction is to perform a final step to verify the signature of the verification context before you clean up the context.


#include <stdlib.h>
#include <openssl/evp.h>

unsigned char out_buf[EVP_MAX_MD_SIZE];
unsigned int out_len;

void handle_error()
{
    exit(-1);
}


void func(unsigned char* src, int len, EVP_PKEY* pkey)
{
    int ret;

    EVP_MD_CTX ctx;
    EVP_MD_CTX_init(&ctx);

    ret = EVP_DigestVerifyInit(&ctx, NULL, EVP_sha256(), NULL, pkey);
    if (ret != 1) handle_error();

    ret = EVP_DigestVerifyUpdate(&ctx, src, len);
    if (ret != 1) handle_error();

    ret = EVP_DigestVerifyFinal(&ctx, out_buf, out_len);
    if (ret != 1) handle_error();

    EVP_MD_CTX_cleanup(&ctx);
} 

Result Information

Group: Cryptography
Language: C | C++
Default: Off
Command-Line Syntax: CRYPTO_MD_NO_FINAL
Impact: Medium

Version History

Introduced in R2020a