mycipher.c

最終更新:2009/10/19

mycipher.c

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: 
Copyright (C) KAKU PROJECT (2009)KAKU PROJECT (2009)