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