Context initialized incorrectly for digest operation

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

Описание

Этот дефект возникает при инициализации 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++
По умолчанию: Off
Синтаксис командной строки : CRYPTO_MD_BAD_FUNCTION
Влияние: Средний
ИДЕНТИФИКАТОР CWE: 310, 353, 354, 372, 573, 664
Введенный в R2018a