mycipher.c
最終更新:2009/10/19
001: /* mycipher.c 002: * EVP 関数による暗号化・復号のサンプル 003: */ 004: 005: #define DEBUG 1 006: 007: /* 008: cipher_alg = "camellia-128-cbc" 009: */ 010: 011: #include "apr_general.h" 012: #include "apr_buckets.h" 013: #include <openssl/evp.h> 014: #include "mybb.h" 015: #include "mycipher.h" 016: 017: #define NOT_USE_FLUSH_FUNC NULL 018: 019: /* 020: * mycipher.c の初期化 021: * 022: */ 023: void init_mycipher() { 024: OpenSSL_add_all_ciphers(); 025: } 026: 027: /* 028: * ストリームを暗号化・復号する関数 029: * 返り値: 030: * 暗号化したバイト数 031: * 失敗時は0 032: * メモ: 033: * ・ENCDEC_BUFF_SIZE は鍵長の倍数になるように設定すること。 034: * ・終了時には、入力ストリームは空になり、出力ストリームには暗号化データが末尾に追加されることに注意。 035: */ 036: 037: int kencdec_from_bb_to_bb( 038: char *cipher_alg /* IN:暗号アルゴリズム。OpenSSL の指定に基づく。暗号名+"-"+鍵長+"-"+暗号モード */ 039: , unsigned char *keyData /* IN:暗号鍵のオクテット列 */ 040: , int keyLen /* IN:暗号鍵の長さ(オクテット長) */ 041: , unsigned char *ivData /* IN:初期化ベクトルのオクテット列 */ 042: , int ivLen /* IN:初期化ベクトルの長さ(オクテット長) */ 043: , int num_in /* IN:暗号対象データのサイズ */ 044: , apr_bucket_brigade *bbIn /* IN:入力ストリーム */ 045: , apr_bucket_brigade *bbOut/* OUT:出力ストリーム */ 046: , int type /* IN:処理タイプ。1:暗号化、0:復号 */ 047: ) { 048: int result = 1; 049: int remain = num_in; 050: 051: const EVP_CIPHER *evp_cipher = NULL; 052: EVP_CIPHER_CTX ctx; 053: 054: unsigned char inBuf[ENCDEC_BUFF_SIZE]; 055: unsigned char outBuf[ENCDEC_BUFF_SIZE]; 056: 057: apr_size_t inLen = 0; 058: int outLen=0; 059: int encLen = 0; 060: 061: apr_bucket_brigade *tmpbb = NULL; 062: 063: if (NULL == cipher_alg || NULL == bbIn || NULL == bbOut) { 064: #ifdef DEBUG 065: fprintf (stderr, "ERROR: kencdec_from_bb_to_bb: argument null. cipher_alg=[%d], bbIn=[%d], bbOut=[%d]\n", cipher_alg, bbIn, bbOut); 066: #endif 067: return 0; 068: } 069: 070: /* 暗号アルゴリズムを取得 */ 071: if (NULL == (evp_cipher = EVP_get_cipherbyname(cipher_alg))) { 072: #ifdef DEBUG 073: fprintf(stderr, "ERROR: kencdec_from_bb_to_bb: EVP_get_cipherbyname [%s]\n", cipher_alg); 074: #endif 075: return 0; 076: } 077: 078: /* 暗号用コンテキストの初期化 */ 079: 080: EVP_CIPHER_CTX_init(&ctx); 081: 082: /* 暗号用コンテキストに鍵と初期化ベクトルを設定 */ 083: 084: if (!EVP_CipherInit(&ctx, evp_cipher, keyData, ivData, type/*ENCRYPT:1,DECRYPT:0*/)) { 085: #ifdef DEBUG 086: fprintf(stderr, "ERROR: kencdec_from_bb_to_bb: EVP_CipherInit\n"); 087: #endif 088: result = 0; 089: goto _FINALLY_; 090: } 091: 092: /* 暗号用コンテキストにパディングを設定 */ 093: 094: EVP_CIPHER_CTX_set_padding(&ctx, 1); 095: 096: /* 一時ストリームを用意 */ 097: 098: tmpbb = apr_brigade_create(bbIn->p, bbIn->bucket_alloc); 099: 100: /* 入力ストリームから ENCDEC_BUFF_SIZE バイトを切り出して一時ストリームに */ 101: 102: remain = num_in; 103: 104: while (remain > 0) { 105: apr_size_t len = 0; 106: apr_size_t read_size = (remain>ENCDEC_BUFF_SIZE)?ENCDEC_BUFF_SIZE:remain; 107: 108: 109: len = move_bytes_from_bb (bbIn, read_size, tmpbb); 110: outLen = 0; 111: 112: if (len <= 0) { 113: break; 114: } 115: 116: remain -= len; 117: 118: /* 一時ストリームからデータを取得 */ 119: 120: if (APR_SUCCESS == apr_brigade_flatten(tmpbb, inBuf, &len)) { 121: 122: /* データを暗号化 */ 123: 124: if (EVP_CipherUpdate(&ctx, outBuf, &outLen, inBuf, len)) { 125: 126: /* 暗号化データを出力ストリームに */ 127: 128: apr_brigade_write(bbOut, NOT_USE_FLUSH_FUNC, NULL, outBuf, outLen); 129: 130: } else { 131: #ifdef DEBUG 132: fprintf(stderr, "ERROR: kencdec_from_bb_to_bb: EVP_CipherUpdate\n"); 133: #endif 134: result = 0; 135: goto _FINALLY_; 136: } 137: } 138: 139: encLen += outLen; 140: /* 一時ストリームを空に */ 141: apr_brigade_cleanup(tmpbb); 142: } 143: 144: /* 最終ブロックを出力ストリームに */ 145: outLen = 0; 146: if (EVP_CipherFinal(&ctx, outBuf, &outLen)) { 147: apr_brigade_write(bbOut, NOT_USE_FLUSH_FUNC, NULL, outBuf, outLen); 148: encLen += outLen; 149: } else { 150: #ifdef DEBUG 151: fprintf(stderr, "ERROR: kencdec_from_bb_to_bb: EVP_CipherFinal\n"); 152: #endif 153: result = 0; 154: } 155: 156: _FINALLY_: 157: 158: /* 一時ストリームを解放 */ 159: if(tmpbb) { 160: apr_brigade_destroy(tmpbb); 161: } 162: 163: /* 暗号用コンテクストを解放 */ 164: EVP_CIPHER_CTX_cleanup(&ctx); 165: 166: if (result) 167: return encLen; 168: 169: return 0; 170: } 171:
![]() | KAKU PROJECT (2009) |