00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "klone_conf.h"
00012 #include <u/libu.h>
00013 #include <klone/codec.h>
00014 #include <klone/ccipher.h>
00015 #include <klone/utils.h>
00016
00017 enum { CODEC_CIPHER_MAX_INPUT = 4096 };
00018
00019 typedef int (*EVP_Update_t)(EVP_CIPHER_CTX *ctx, unsigned char *out,
00020 int *outl, const unsigned char *in, int inl);
00021 typedef int (*EVP_Final_ex_t)(EVP_CIPHER_CTX *ctx, unsigned char *out,
00022 int *outl);
00023
00024 struct codec_cipher_s
00025 {
00026 codec_t codec;
00027 const EVP_CIPHER *cipher;
00028 EVP_CIPHER_CTX cipher_ctx;
00029 char *cbuf;
00030 size_t coff, ccount, cbuf_size;
00031 EVP_Update_t update;
00032 EVP_Final_ex_t final;
00033 };
00034
00035 typedef struct codec_cipher_s codec_cipher_t;
00036
00037 static void codec_cbufcpy(codec_cipher_t *cc, char *dst, size_t *dcount)
00038 {
00039 size_t count;
00040
00041 count = U_MIN(*dcount, cc->ccount);
00042
00043 memcpy(dst, cc->cbuf + cc->coff, count);
00044 cc->ccount -= count;
00045 if(cc->ccount)
00046 cc->coff += count;
00047 else
00048 cc->coff = 0;
00049 *dcount = count;
00050 }
00051
00052 static ssize_t cipher_flush(codec_t *codec, char *dst, size_t *dcount)
00053 {
00054 codec_cipher_t *cc;
00055 int wr;
00056
00057 dbg_err_if (codec == NULL);
00058 dbg_err_if (dst == NULL);
00059 dbg_err_if (dcount == NULL);
00060
00061 cc = (codec_cipher_t*)codec;
00062
00063 for(;;)
00064 {
00065 if(cc->ccount)
00066 {
00067 codec_cbufcpy(cc, dst, dcount);
00068 return CODEC_FLUSH_CHUNK;
00069 }
00070
00071 if(cc->final)
00072 {
00073 wr = -1;
00074 dbg_err_if(!cc->final(&cc->cipher_ctx, cc->cbuf, &wr));
00075
00076 cc->ccount += wr;
00077 cc->final = NULL;
00078
00079 if(wr)
00080 continue;
00081 }
00082 break;
00083 }
00084
00085 *dcount = 0;
00086 return CODEC_FLUSH_COMPLETE;
00087 err:
00088 return -1;
00089 }
00090
00091 static ssize_t cipher_transform(codec_t *codec, char *dst, size_t *dcount,
00092 const char *src, size_t src_sz)
00093 {
00094 codec_cipher_t *cc;
00095 ssize_t c;
00096 int wr;
00097
00098 dbg_err_if (codec == NULL);
00099 dbg_err_if (src == NULL);
00100 dbg_err_if (dst == NULL);
00101 dbg_err_if (dcount == NULL || *dcount == 0);
00102 dbg_err_if (src_sz == 0);
00103
00104 cc = (codec_cipher_t*)codec;
00105
00106 c = 0;
00107 for(;;)
00108 {
00109 if(cc->ccount)
00110 {
00111 codec_cbufcpy(cc, dst, dcount);
00112 return c;
00113 }
00114
00115
00116
00117
00118 c = U_MIN(src_sz, CODEC_CIPHER_MAX_INPUT);
00119
00120 wr = -1;
00121 dbg_err_if(!cc->update(&cc->cipher_ctx, cc->cbuf, &wr, src, c));
00122 cc->ccount += wr;
00123
00124 if(wr == 0)
00125 {
00126 *dcount = 0;
00127 break;
00128 }
00129 }
00130
00131 dbg_err_if(c == 0 && *dcount == 0);
00132 return c;
00133 err:
00134 return -1;
00135 }
00136
00137 static int cipher_free(codec_t *codec)
00138 {
00139 codec_cipher_t *cc;
00140
00141 nop_return_if (codec == NULL, 0);
00142
00143 cc = (codec_cipher_t*)codec;
00144
00145 U_FREE(cc->cbuf);
00146 U_FREE(cc);
00147
00148 return 0;
00149 }
00150
00172 int codec_cipher_create(int op, const EVP_CIPHER *cipher,
00173 unsigned char *key, unsigned char *iv, codec_t **pcc)
00174 {
00175 codec_cipher_t *cc = NULL;
00176
00177 dbg_return_if (cipher == NULL, ~0);
00178 dbg_return_if (key == NULL, ~0);
00179
00180 dbg_return_if (pcc == NULL, ~0);
00181
00182 cc = u_zalloc(sizeof(codec_cipher_t));
00183 dbg_err_if(cc == NULL);
00184
00185 cc->codec.transform = cipher_transform;
00186 cc->codec.flush = cipher_flush;
00187 cc->codec.free = cipher_free;
00188
00189 cc->cipher = cipher;
00190
00191
00192 EVP_add_cipher(cc->cipher);
00193
00194 EVP_CIPHER_CTX_init(&cc->cipher_ctx);
00195
00196 cc->cbuf_size = CODEC_CIPHER_MAX_INPUT +
00197 EVP_CIPHER_block_size(cc->cipher) -1;
00198
00199 cc->cbuf = u_malloc(cc->cbuf_size);
00200 dbg_err_if(cc->cbuf == NULL);
00201
00202 switch(op)
00203 {
00204 case CIPHER_ENCRYPT:
00205 dbg_err_if(!EVP_EncryptInit_ex(&cc->cipher_ctx, cc->cipher, NULL,
00206 key, iv));
00207 cc->update = EVP_EncryptUpdate;
00208 cc->final = EVP_EncryptFinal_ex;
00209 break;
00210 case CIPHER_DECRYPT:
00211 dbg_err_if(!EVP_DecryptInit_ex(&cc->cipher_ctx, cc->cipher, NULL,
00212 key, iv));
00213 cc->update = EVP_DecryptUpdate;
00214 cc->final = EVP_DecryptFinal_ex;
00215 break;
00216 default:
00217 dbg_err_if("bad cipher op");
00218 }
00219
00220
00221 *pcc = (codec_t*)cc;
00222
00223 return 0;
00224 err:
00225 U_FREE(cc);
00226 return ~0;
00227 }
00228