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