メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

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

ダイジェスト操作に使用されるコンテキストが別のダイジェスト操作用に初期化されている

説明

この欠陥は、特定のダイジェスト操作用に EVP_MD_CTX コンテキスト オブジェクトを初期化したが、そのコンテキストを別の操作に使用した場合に発生します。

たとえば、メッセージ ダイジェストを作成するためだけにコンテキストを初期化します。

ret = EVP_DigestInit(ctx, EVP_sha256())
しかし、以下のように、署名の最終ステップを実行します。
ret = EVP_SignFinal(&ctx, out, &out_len, pkey);
このエラーは、最終ステップとコンテキストの初期化が整合していない場合のみ表示されます。中間の更新ステップに整合性がなくても、中間ステップは操作の性質に依存しないためエラーはトリガーされません。たとえば、EVP_DigestUpdateEVP_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 を使用して署名付きダイジェストの作成を試みています。

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

1 つの修正方法として、署名だけのためにコンテキスト オブジェクトを使用します。初期化ステップに合わせて最終ステップを 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
影響度: Medium

バージョン履歴

R2018a で導入