exponenta event banner

Неправильно инициализирован контекст для операции дайджеста

Контекст, используемый для операции дайджеста, инициализирован для другой операции дайджеста

Описание

Этот дефект возникает при инициализации EVP_MD_CTX объект контекста для конкретной операции дайджеста, но использовать контекст для другой операции.

Например, инициализируется контекст только для создания дайджеста сообщений.

ret = EVP_DigestInit(ctx, EVP_sha256())
Однако для подписания необходимо выполнить последний шаг:
ret = EVP_SignFinal(&ctx, out, &out_len, pkey);
Ошибка отображается только в том случае, если последний шаг не согласуется с инициализацией контекста. Если промежуточные шаги обновления несогласованны, это не приводит к возникновению ошибки, поскольку промежуточные шаги не зависят от характера операции. Например, EVP_DigestUpdate работает идентично EVP_SignUpdate.

Риск

Смешение различных операций в одном контексте может привести к затемнению кода. На первый взгляд трудно определить, используется ли текущий объект для создания, подписания или проверки дайджеста сообщений. Смешение также может привести к сбою в работе или неожиданному дайджесту сообщений.

Зафиксировать

После настройки контекста для определенного семейства операций используйте контекст только для этого семейства операций. Например, используйте эти пары функций для инициализации и финальных шагов.

  • EVP_DigestInit : EVP_DigestFinal

  • EVP_DigestInit_ex : EVP_DigestFinal_ex

  • EVP_DigestSignInit : EVP_DigestSignFinal

Если необходимо повторно использовать существующий объект контекста для другого семейства операций, повторно инициализируйте контекст.

Примеры

развернуть все

#include <openssl/evp.h>

#define fatal_error() exit(-1)

int ret;
unsigned char *out_buf16;
unsigned int out_len16;

void func(unsigned char *src, size_t len){
  EVP_MD_CTX* ctx = EVP_MD_CTX_create();

  ret = EVP_SignInit_ex(ctx, EVP_sha256(), NULL);
  if (ret != 1) fatal_error();

  ret = EVP_SignUpdate(ctx, src, len);
  if (ret != 1) fatal_error();

  ret = EVP_DigestSignFinal(ctx, out_buf16, (size_t*) out_len16);

  if (ret != 1) fatal_error();
}

В этом примере объект контекста инициализируется только для подписи с помощью EVP_SignInit но последний шаг пытается создать подписанный дайджест с EVP_DigestSignFinal.

Исправление - Использование одного семейства операций

Одной из возможных корректировок является использование объекта контекста только для подписи. Изменить последний шаг на EVP_SignFinal в соответствии с этапом инициализации.

#include <openssl/evp.h>

#define fatal_error() exit(-1)

int ret;
unsigned char *out_buf16;
unsigned int out_len16;

void corrected_cryptomdbadfunction(unsigned char *src, size_t len, EVP_PKEY* pkey){
  EVP_MD_CTX* ctx = EVP_MD_CTX_create();

  ret = EVP_SignInit_ex(ctx, EVP_sha256(), NULL); 
  if (ret != 1) fatal_error();

  ret = EVP_SignUpdate(ctx, src, len);
  if (ret != 1) fatal_error();

  ret = EVP_SignFinal(ctx, out_buf16, &out_len16, pkey); 
  if (ret != 1) fatal_error();
}

Информация о результатах

Группа: Криптография
Язык: C | C++
По умолчанию: Откл.
Синтаксис командной строки: CRYPTO_MD_BAD_FUNCTION
Воздействие: среднее
CWE ID: 310, 353, 354, 372, 573, 664
Представлен в R2018a