List.mui: Update entries count prior to range change
[AROS.git] / workbench / network / WirelessManager / src / crypto / crypto_internal-cipher.c
blob75134f09a403fdfd2e73f44a34d4f2100fa218e3
1 /*
2 * Crypto wrapper for internal crypto implementation - Cipher wrappers
3 * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
12 * See README and COPYING for more details.
15 #include "includes.h"
17 #include "common.h"
18 #include "crypto.h"
19 #include "aes.h"
20 #include "des_i.h"
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;
50 struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
51 const u8 *iv, const u8 *key,
52 size_t key_len)
54 struct crypto_cipher *ctx;
56 ctx = os_zalloc(sizeof(*ctx));
57 if (ctx == NULL)
58 return NULL;
60 ctx->alg = alg;
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;
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;
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;
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;
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;
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;
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;
111 return ctx;
115 int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
116 u8 *crypt, size_t len)
118 size_t i, j, blocks;
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;
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;
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;
170 break;
171 default:
172 return -1;
175 return 0;
179 int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
180 u8 *plain, size_t len)
182 size_t i, j, blocks;
183 u8 tmp[32];
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;
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;
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;
234 break;
235 default:
236 return -1;
239 return 0;
243 void crypto_cipher_deinit(struct crypto_cipher *ctx)
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;
255 os_free(ctx);