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
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			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
43struct 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
103int 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
166int 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
230void 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