メインコンテンツ

処理する暗号データがありません

前に更新ステップを行わずに、暗号化または復号化の最終ステップを実行している

説明

この欠陥は、ブロック暗号の暗号化または復号化の最終ステップを不適切に実行した場合に発生します。

たとえば、次のいずれかを行います。

  • 最終ステップを実行する前に、データの暗号化または復号化の更新ステップを実行していない。

    /* Initialization of cipher context */
    ret = EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);
    ...
    /* Missing update step */
    ...
    /* Final step */
    ret = EVP_EncryptFinal_ex(ctx, out_buf, &out_len);
  • 初期化と更新のステップを挟まずに、連続して最終ステップを実行している。

    /* Initialization of cipher context */
    ret = EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);
    ...
    /* Update step(s) */
    ret = EVP_EncryptUpdate(ctx, out_buf, &out_len, src, len);
    ...
    /* Final step */
    ret = EVP_EncryptFinal_ex(ctx, out_buf, &out_len);
    ...
    /* Missing initialization and update */
    ...
    /* Second final step */
    ret = EVP_EncryptFinal_ex(ctx, out_buf, &out_len);
  • 暗号コンテキストのクリーンアップを実行してから、最終ステップを実行している。

    /* Initialization of cipher context */
    ret = EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);
    ...
    /* Update step(s) */
    ret = EVP_EncryptUpdate(ctx, out_buf, &out_len, src, len);
    ...
    /* Cleanup of cipher context */
    EVP_CIPHER_CTX_cleanup(ctx);
    ...
    /* Second final step */
    ret = EVP_EncryptFinal_ex(ctx, out_buf, &out_len);

リスク

ブロック暗号は、データを固定サイズのブロックに分割します。暗号化または復号化時は、更新ステップでブロック内のデータの暗号化または復号化が行われます。最終ステップでは、残りのデータがある場合にそのデータの暗号化または復号化が行われます。最終ステップでは、1 ブロックが埋まるように残りのデータにパディングが追加され、パディング後のデータの暗号化または復号化が行われます。

最終ステップを更新ステップの前に実行したり、処理するデータが存在しないときに最終ステップを実行する場合、未定義の動作になります。また、ランタイム エラーが発生する可能性もあります。

修正方法

次の順序で暗号化または復号化を実行します。

  • 暗号コンテキストの初期化

  • 更新ステップ

  • 最終ステップ

  • コンテキストのクリーンアップ

すべて展開する


#include <openssl/evp.h>
#include <stdlib.h>
#define SIZE16 16

unsigned char *out_buf;
int out_len;
unsigned char key[SIZE16];
unsigned char iv[SIZE16];

void func(void) {
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    EVP_CIPHER_CTX_init(ctx);

    /* Initialization of cipher context */
    EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);
    
    /* Missing update steps for encryption */
    
    /* Final encryption step */
    EVP_EncryptFinal_ex(ctx, out_buf, &out_len);           
}

この例には、暗号コンテキストを初期化後、データを暗号化する更新ステップがありません。更新ステップではデータの 1 つ以上のブロックを暗号化しなければなりません。最後の部分ブロックに残ったデータは最終ステップで暗号化します。最終ステップの前に更新ステップを実行しない場合、未定義の動作になります。

修正 — 最終ステップの前に暗号化の更新ステップを実行

最終ステップの前に暗号化の更新ステップを実行します。修正した次のコードでは、ルーチン EVP_EncryptUpdate が更新ステップを実行します。


#include <openssl/evp.h>
#include <stdlib.h>
#define SIZE16 16

unsigned char *out_buf;
int out_len;
unsigned char key[SIZE16];
unsigned char iv[SIZE16];

void func(unsigned char *src, int len) {
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    EVP_CIPHER_CTX_init(ctx);

    /* Initialization of cipher context */
    EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);
    
    /* Update steps for encryption */
    EVP_EncryptUpdate(ctx, out_buf, &out_len, src, len);   
    
    /* Final encryption step */
    EVP_EncryptFinal_ex(ctx, out_buf, &out_len);           
}

結果情報

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

バージョン履歴

R2017a で導入