automake build system
[mech_eap.orig] / src / crypto / crypto_internal-cipher.c
1 /*
2  * Crypto wrapper for internal crypto implementation - Cipher wrappers
3  * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "crypto.h"
19 #include "aes.h"
20 #include "des_i.h"
21
22
23 struct crypto_cipher {
24         enum crypto_cipher_alg alg;
25         union {
26                 struct {
27                         size_t used_bytes;
28                         u8 key[16];
29                         size_t keylen;
30                 } rc4;
31                 struct {
32                         u8 cbc[32];
33                         size_t block_size;
34                         void *ctx_enc;
35                         void *ctx_dec;
36                 } aes;
37                 struct {
38                         struct des3_key_s key;
39                         u8 cbc[8];
40                 } des3;
41                 struct {
42                         u32 ek[32];
43                         u32 dk[32];
44                         u8 cbc[8];
45                 } des;
46         } u;
47 };
48
49
50 struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
51                                           const u8 *iv, const u8 *key,
52                                           size_t key_len)
53 {
54         struct crypto_cipher *ctx;
55
56         ctx = os_zalloc(sizeof(*ctx));
57         if (ctx == NULL)
58                 return NULL;
59
60         ctx->alg = alg;
61
62         switch (alg) {
63         case CRYPTO_CIPHER_ALG_RC4:
64                 if (key_len > sizeof(ctx->u.rc4.key)) {
65                         os_free(ctx);
66                         return NULL;
67                 }
68                 ctx->u.rc4.keylen = key_len;
69                 os_memcpy(ctx->u.rc4.key, key, key_len);
70                 break;
71         case CRYPTO_CIPHER_ALG_AES:
72                 if (key_len > sizeof(ctx->u.aes.cbc)) {
73                         os_free(ctx);
74                         return NULL;
75                 }
76                 ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len);
77                 if (ctx->u.aes.ctx_enc == NULL) {
78                         os_free(ctx);
79                         return NULL;
80                 }
81                 ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len);
82                 if (ctx->u.aes.ctx_dec == NULL) {
83                         aes_encrypt_deinit(ctx->u.aes.ctx_enc);
84                         os_free(ctx);
85                         return NULL;
86                 }
87                 ctx->u.aes.block_size = key_len;
88                 os_memcpy(ctx->u.aes.cbc, iv, ctx->u.aes.block_size);
89                 break;
90         case CRYPTO_CIPHER_ALG_3DES:
91                 if (key_len != 24) {
92                         os_free(ctx);
93                         return NULL;
94                 }
95                 des3_key_setup(key, &ctx->u.des3.key);
96                 os_memcpy(ctx->u.des3.cbc, iv, 8);
97                 break;
98         case CRYPTO_CIPHER_ALG_DES:
99                 if (key_len != 8) {
100                         os_free(ctx);
101                         return NULL;
102                 }
103                 des_key_setup(key, ctx->u.des.ek, ctx->u.des.dk);
104                 os_memcpy(ctx->u.des.cbc, iv, 8);
105                 break;
106         default:
107                 os_free(ctx);
108                 return NULL;
109         }
110
111         return ctx;
112 }
113
114
115 int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
116                           u8 *crypt, size_t len)
117 {
118         size_t i, j, blocks;
119
120         switch (ctx->alg) {
121         case CRYPTO_CIPHER_ALG_RC4:
122                 if (plain != crypt)
123                         os_memcpy(crypt, plain, len);
124                 rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
125                          ctx->u.rc4.used_bytes, crypt, len);
126                 ctx->u.rc4.used_bytes += len;
127                 break;
128         case CRYPTO_CIPHER_ALG_AES:
129                 if (len % ctx->u.aes.block_size)
130                         return -1;
131                 blocks = len / ctx->u.aes.block_size;
132                 for (i = 0; i < blocks; i++) {
133                         for (j = 0; j < ctx->u.aes.block_size; j++)
134                                 ctx->u.aes.cbc[j] ^= plain[j];
135                         aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc,
136                                     ctx->u.aes.cbc);
137                         os_memcpy(crypt, ctx->u.aes.cbc,
138                                   ctx->u.aes.block_size);
139                         plain += ctx->u.aes.block_size;
140                         crypt += ctx->u.aes.block_size;
141                 }
142                 break;
143         case CRYPTO_CIPHER_ALG_3DES:
144                 if (len % 8)
145                         return -1;
146                 blocks = len / 8;
147                 for (i = 0; i < blocks; i++) {
148                         for (j = 0; j < 8; j++)
149                                 ctx->u.des3.cbc[j] ^= plain[j];
150                         des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key,
151                                      ctx->u.des3.cbc);
152                         os_memcpy(crypt, ctx->u.des3.cbc, 8);
153                         plain += 8;
154                         crypt += 8;
155                 }
156                 break;
157         case CRYPTO_CIPHER_ALG_DES:
158                 if (len % 8)
159                         return -1;
160                 blocks = len / 8;
161                 for (i = 0; i < blocks; i++) {
162                         for (j = 0; j < 8; j++)
163                                 ctx->u.des3.cbc[j] ^= plain[j];
164                         des_block_encrypt(ctx->u.des.cbc, ctx->u.des.ek,
165                                           ctx->u.des.cbc);
166                         os_memcpy(crypt, ctx->u.des.cbc, 8);
167                         plain += 8;
168                         crypt += 8;
169                 }
170                 break;
171         default:
172                 return -1;
173         }
174
175         return 0;
176 }
177
178
179 int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
180                           u8 *plain, size_t len)
181 {
182         size_t i, j, blocks;
183         u8 tmp[32];
184
185         switch (ctx->alg) {
186         case CRYPTO_CIPHER_ALG_RC4:
187                 if (plain != crypt)
188                         os_memcpy(plain, crypt, len);
189                 rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
190                          ctx->u.rc4.used_bytes, plain, len);
191                 ctx->u.rc4.used_bytes += len;
192                 break;
193         case CRYPTO_CIPHER_ALG_AES:
194                 if (len % ctx->u.aes.block_size)
195                         return -1;
196                 blocks = len / ctx->u.aes.block_size;
197                 for (i = 0; i < blocks; i++) {
198                         os_memcpy(tmp, crypt, ctx->u.aes.block_size);
199                         aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain);
200                         for (j = 0; j < ctx->u.aes.block_size; j++)
201                                 plain[j] ^= ctx->u.aes.cbc[j];
202                         os_memcpy(ctx->u.aes.cbc, tmp, ctx->u.aes.block_size);
203                         plain += ctx->u.aes.block_size;
204                         crypt += ctx->u.aes.block_size;
205                 }
206                 break;
207         case CRYPTO_CIPHER_ALG_3DES:
208                 if (len % 8)
209                         return -1;
210                 blocks = len / 8;
211                 for (i = 0; i < blocks; i++) {
212                         os_memcpy(tmp, crypt, 8);
213                         des3_decrypt(crypt, &ctx->u.des3.key, plain);
214                         for (j = 0; j < 8; j++)
215                                 plain[j] ^= ctx->u.des3.cbc[j];
216                         os_memcpy(ctx->u.des3.cbc, tmp, 8);
217                         plain += 8;
218                         crypt += 8;
219                 }
220                 break;
221         case CRYPTO_CIPHER_ALG_DES:
222                 if (len % 8)
223                         return -1;
224                 blocks = len / 8;
225                 for (i = 0; i < blocks; i++) {
226                         os_memcpy(tmp, crypt, 8);
227                         des_block_decrypt(crypt, ctx->u.des.dk, plain);
228                         for (j = 0; j < 8; j++)
229                                 plain[j] ^= ctx->u.des.cbc[j];
230                         os_memcpy(ctx->u.des.cbc, tmp, 8);
231                         plain += 8;
232                         crypt += 8;
233                 }
234                 break;
235         default:
236                 return -1;
237         }
238
239         return 0;
240 }
241
242
243 void crypto_cipher_deinit(struct crypto_cipher *ctx)
244 {
245         switch (ctx->alg) {
246         case CRYPTO_CIPHER_ALG_AES:
247                 aes_encrypt_deinit(ctx->u.aes.ctx_enc);
248                 aes_decrypt_deinit(ctx->u.aes.ctx_dec);
249                 break;
250         case CRYPTO_CIPHER_ALG_3DES:
251                 break;
252         default:
253                 break;
254         }
255         os_free(ctx);
256 }