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) |