メインコンテンツ

コンテキストが暗号化操作用に正しく初期化されていません

公開鍵の暗号化操作に使用されるコンテキストが別の操作用に初期化されている

説明

この欠陥は、特定の公開鍵暗号化操作用に EVP_PKEY_CTX オブジェクトを初期化したが、そのオブジェクトを別の操作に使用した場合に発生します。

たとえば、暗号化用にコンテキストを初期化します。

ret = EVP_PKEY_encrypt_init(ctx);
しかし、このコンテキストを、再初期化せずに復号化するために使用します。
ret = EVP_PKEY_decrypt(ctx, out, &out_len, in, in_len);

チェッカーでは、次の関数で使用されているコンテキスト オブジェクトが、対応する初期化関数を使用して初期化されているかどうかを検出します。EVP_PKEY_paramgenEVP_PKEY_keygenEVP_PKEY_encryptEVP_PKEY_verifyEVP_PKEY_verify_recoverEVP_PKEY_decryptEVP_PKEY_signEVP_PKEY_derive および EVP_PKEY_derive_set_peer

リスク

同じコンテキストに対してさまざまな操作を混在させると、コードがわかりにくくなる可能性があります。現在のオブジェクトを暗号化、復号化、署名、または別の操作のどれに使用しているか、ひとめで判断するのは難しくなります。また、混在により、操作の失敗や予期しない暗号文につながる可能性もあります。

修正方法

操作の特定のファミリに対してコンテキストを設定した後は、その操作のファミリにのみそのコンテキストを使用します。たとえば、EVP_PKEY_CTX コンテキスト オブジェクトを初期化および使用するために、以下のペアの関数を使用します。

  • EVP_PKEY_encrypt を使用して暗号化を行う場合は、コンテキストの初期化に EVP_PKEY_encrypt_init を使用する。

  • EVP_PKEY_verify を使用して署名検証を行う場合は、コンテキストの初期化に EVP_PKEY_verify_init を使用する。

  • EVP_PKEY_keygen を使用してキー生成を行う場合は、コンテキストの初期化に EVP_PKEY_keygen_init を使用する。

操作の別のファミリに対して既存のコンテキスト オブジェクトを再利用する場合は、そのコンテキストを再初期化します。

すべて展開する

#include <openssl/evp.h>

#define fatal_error() exit(-1)

int ret;
unsigned char *out_buf10;
size_t out_len10;
int func(unsigned char *src, size_t len, EVP_PKEY_CTX *ctx){
  if (ctx == NULL) fatal_error(); 

  ret = EVP_PKEY_decrypt_init(ctx); 
  if (ret <= 0) fatal_error();
  return EVP_PKEY_encrypt(ctx, out_buf10, &out_len10, src, len);
}

この例では、復号化するために初期化したコンテキストを暗号化に使用しています。

修正 — 操作の 1 つのファミリを使用

1 つの修正方法として、オブジェクトを暗号化のために初期化します。

#include <openssl/evp.h>

#define fatal_error() exit(-1)

int ret;
unsigned char *out_buf10;
size_t out_len10;
int func(unsigned char *src, size_t len, EVP_PKEY_CTX *ctx){
  if (ctx == NULL) fatal_error(); 

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

結果情報

グループ: 暗号化
言語: C | C++
既定値: オフ
コマンド ライン構文: CRYPTO_PKEY_INCORRECT_INIT
影響度: Medium

バージョン履歴

R2018a で導入