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