00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "klone_conf.h"
00011 #include <u/libu.h>
00012 #include <klone/codec.h>
00013 #include <klone/ccipher.h>
00014 #include <klone/utils.h>
00015 #include <config.h>
00016 #include <types.h>
00017 #include <ctc_aes.h>
00018
00019 typedef void (*aes_op_t)(Aes*, byte*, const byte*, word32);
00020
00021 struct codec_cipher_s
00022 {
00023 codec_t codec;
00024 const EVP_CIPHER *cipher;
00025 u_buf_t *ubuf;
00026 Aes aes;
00027 aes_op_t op;
00028 int outready;
00029 size_t off;
00030 };
00031
00032
00033 typedef struct codec_cipher_s codec_cipher_t;
00034
00035 static ssize_t cipher_flush(codec_t *codec, char *dst, size_t *dcount)
00036 {
00037 codec_cipher_t *cc;
00038 size_t sz, len, orig_len, c;
00039 char *ptr, pad;
00040 char padding[AES_BLOCK_SIZE];
00041
00042 cc = (codec_cipher_t*)codec;
00043
00044 if(cc->outready == 0)
00045 {
00046 if(cc->op == AesCbcEncrypt)
00047 {
00048 len = (u_buf_len(cc->ubuf)/AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
00049 u_buf_reserve(cc->ubuf, len);
00050
00051 pad = len - u_buf_len(cc->ubuf);
00052
00053
00054 memset(padding, pad, AES_BLOCK_SIZE);
00055 dbg_err_if(u_buf_append(cc->ubuf, padding,
00056 len-u_buf_len(cc->ubuf)));
00057
00058 cc->op(&cc->aes, u_buf_ptr(cc->ubuf),
00059 u_buf_ptr(cc->ubuf), u_buf_len(cc->ubuf));
00060
00061 } else {
00062
00063 crit_err_if(u_buf_len(cc->ubuf) % AES_BLOCK_SIZE != 0);
00064
00065 cc->op(&cc->aes, u_buf_ptr(cc->ubuf),
00066 u_buf_ptr(cc->ubuf), u_buf_len(cc->ubuf));
00067
00068 ptr = u_buf_ptr(cc->ubuf);
00069
00070 pad = ptr[u_buf_len(cc->ubuf) -1];
00071
00072
00073 dbg_err_if(pad < 1 || pad > 16);
00074
00075
00076 len = u_buf_len(cc->ubuf) - pad;
00077
00078
00079
00080 for(c = len; c < u_buf_len(cc->ubuf); c++)
00081 dbg_err_if(ptr[c] != pad);
00082
00083 dbg_err_if(u_buf_shrink(cc->ubuf, len));
00084 }
00085
00086 cc->outready++;
00087 }
00088
00089 sz = U_MIN(*dcount, u_buf_len(cc->ubuf) - cc->off);
00090 if(sz)
00091 {
00092 ptr = (char*)u_buf_ptr(cc->ubuf) + cc->off;
00093 memcpy(dst, ptr, sz);
00094 cc->off += sz;
00095 }
00096
00097 *dcount = sz;
00098
00099 return *dcount == 0 ? CODEC_FLUSH_COMPLETE : CODEC_FLUSH_CHUNK;
00100 err:
00101 if(dcount)
00102 *dcount = 0;
00103 return -1;
00104 }
00105
00106 static ssize_t cipher_transform(codec_t *codec, char *dst, size_t *dcount,
00107 const char *src, size_t src_sz)
00108 {
00109 codec_cipher_t *cc;
00110
00111 cc = (codec_cipher_t*)codec;
00112
00113 dbg_err_if (src == NULL);
00114 dbg_err_if (dst == NULL);
00115 dbg_err_if (dcount == NULL || *dcount == 0);
00116 dbg_err_if (src_sz == 0);
00117
00118 *dcount = 0;
00119
00120
00121
00122 dbg_err_if(u_buf_append(cc->ubuf, src, src_sz));
00123
00124 return src_sz;
00125 err:
00126 return -1;
00127 }
00128
00129 static int cipher_free(codec_t *codec)
00130 {
00131 codec_cipher_t *cc;
00132
00133 nop_return_if (codec == NULL, 0);
00134
00135 cc = (codec_cipher_t*)codec;
00136
00137 if(cc->ubuf)
00138 u_buf_free(cc->ubuf);
00139
00140 U_FREE(cc);
00141
00142 return 0;
00143 }
00144
00166 int codec_cipher_create(int op, const EVP_CIPHER *cipher,
00167 unsigned char *key, unsigned char *iv, codec_t **pcc)
00168 {
00169 static unsigned char zero_iv[CODEC_CIPHER_IV_LEN];
00170 codec_cipher_t *cc = NULL;
00171
00172 dbg_return_if (cipher == NULL, ~0);
00173 dbg_return_if (key == NULL, ~0);
00174
00175 dbg_return_if (pcc == NULL, ~0);
00176
00177 if(iv == NULL)
00178 iv = zero_iv;
00179
00180 cc = u_zalloc(sizeof(codec_cipher_t));
00181 dbg_err_if(cc == NULL);
00182
00183 cc->codec.transform = cipher_transform;
00184 cc->codec.flush = cipher_flush;
00185 cc->codec.free = cipher_free;
00186
00187 cc->cipher = cipher;
00188
00189 dbg_err_if(u_buf_create(&cc->ubuf));
00190
00191
00192 switch(op)
00193 {
00194 case CIPHER_ENCRYPT:
00195 dbg_err_if(AesSetKey(&cc->aes, key, CODEC_CIPHER_KEY_LEN, iv,
00196 AES_ENCRYPTION));
00197
00198 cc->op = AesCbcEncrypt;
00199 break;
00200 case CIPHER_DECRYPT:
00201 dbg_err_if(AesSetKey(&cc->aes, key, CODEC_CIPHER_KEY_LEN, iv,
00202 AES_DECRYPTION));
00203 cc->op = AesCbcDecrypt;
00204 break;
00205 default:
00206 dbg_err_if("bad cipher op");
00207 }
00208
00209
00210 *pcc = (codec_t*)cc;
00211
00212 return 0;
00213 err:
00214 U_FREE(cc);
00215 return ~0;
00216 }
00217