exponenta event banner

Отсутствует открытый ключ

Контекст, используемый для криптографии, связан с открытым ключом NULL или вообще не связан с открытым ключом

Описание

Этот дефект возникает при использовании объекта контекста для шифрования или проверки подлинности подписи, но ранее объект не был связан с открытым ключом, отличным от NULL.

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

ctx = EVP_PKEY_CTX_new(pkey, NULL);
...
ret = EVP_PKEY_encrypt_init(ctx);
...
ret = EVP_PKEY_encrypt(ctx, out, &out_len, in, in_len);

Аналогичная проверка Missing private key проверяет наличие закрытого ключа в операциях расшифровки и подписи.

Риск

Без открытого ключа этап шифрования или аутентификации подписи не выполняется. Избыточная операция часто указывает на ошибку кодирования.

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

Проверьте расположение операции (шифрование или аутентификация подписи). Если операция предназначена для выполнения, перед выполнением операции убедитесь, что выполнены следующие действия:

  • Вы создали открытый ключ, отличный от NULL.

    Например:

    EVP_PKEY *pkey = NULL;
    kctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
    
    EVP_PKEY_keygen_init(kctx);
    EVP_PKEY_CTX_set_rsa_keygen_bits(kctx, RSA_2048BITS);
    EVP_PKEY_keygen(kctx, &pkey);

  • Объект контекста, отличный от NULL, связан с открытым ключом.

    Например:

    ctx = EVP_PKEY_CTX_new(pkey, NULL);
    

    Примечание: Если вы используете EVP_PKEY_CTX_new_id вместо EVP_PKEY_CTX_new, объект контекста не связан с открытым ключом.

Примеры

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

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

#define fatal_error() exit(-1)

int ret;
unsigned char *out_buf;
size_t out_len;

int func(unsigned char *src, size_t len){
  EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
  if (ctx == NULL) fatal_error();

  ret = EVP_PKEY_encrypt_init(ctx);
  if (ret <= 0) fatal_error();
  return EVP_PKEY_encrypt(ctx, out_buf, &out_len, src, len); 
}

В этом примере объект контекста ctx инициализирован с помощью EVP_PKEY_CTX_new_id вместо EVP_PKEY_CTX_new. Функция EVP_PKEY_CTX_new_id не связывает объект контекста с ключом. Тем не менее, EVP_PKEY_encrypt использует этот объект для расшифровки.

Исправление - связывание открытого ключа с контекстом во время инициализации

Одной из возможных корректировок является использование EVP_PKEY_CTX_new для инициализации контекста и связывания открытого ключа с объектом контекста. В следующей корректировке открытый ключ pkey получается из внешнего источника и проверяется на значение NULL перед использованием.

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

#define fatal_error() exit(-1)

int ret;
unsigned char *out_buf;
size_t out_len;

int func(unsigned char *src, size_t len, EVP_PKEY *pkey){
  if (pkey == NULL) fatal_error(); 
  
  EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
  if (ctx == NULL) fatal_error();

  ret = EVP_PKEY_encrypt_init(ctx);
  if (ret <= 0) fatal_error();
  return EVP_PKEY_encrypt(ctx, out_buf, &out_len, src, len); 
}

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

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