xref: /freebsd/contrib/wpa/src/crypto/crypto_internal-cipher.c (revision a03411e84728e9b267056fd31c7d1d9d1dc1b01e)
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 
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 
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 
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 
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