]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libstrongswan/plugins/wolfssl/wolfssl_crypter.c
wolfssl: Fixes, code style changes and some refactorings
[thirdparty/strongswan.git] / src / libstrongswan / plugins / wolfssl / wolfssl_crypter.c
1 /*
2 * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23 #include "wolfssl_crypter.h"
24
25 #include "wolfssl_common.h"
26 #include <wolfssl/wolfcrypt/aes.h>
27 #include <wolfssl/wolfcrypt/camellia.h>
28 #include <wolfssl/wolfcrypt/des3.h>
29
30 #include <utils/debug.h>
31
32 typedef struct private_wolfssl_crypter_t private_wolfssl_crypter_t;
33
34 #define CTR_SALT_LEN 4
35
36 /**
37 * Private data of wolfssl_crypter_t
38 */
39 struct private_wolfssl_crypter_t {
40
41 /**
42 * Public part of this class.
43 */
44 wolfssl_crypter_t public;
45
46 /**
47 * wolfSSL cipher
48 */
49 union {
50 #if !defined(NO_AES) && (!defined(NO_AES_CBC) || defined(WOLFSSL_AES_COUNTER))
51 Aes aes;
52 #endif
53 #ifdef HAVE_CAMELLIA
54 Camellia camellia;
55 #endif
56 #ifndef NO_DES3
57 Des des;
58 Des3 des3;
59 #endif
60 } cipher;
61
62 /**
63 * Encryption algorithm identifier
64 */
65 encryption_algorithm_t alg;
66
67 /**
68 * Private key
69 */
70 chunk_t key;
71
72 /**
73 * Salt value
74 */
75 chunk_t salt;
76
77 /**
78 * Size of block
79 */
80 size_t block_size;
81
82 /**
83 * Size of IV
84 */
85 size_t iv_size;
86 };
87
88 METHOD(crypter_t, decrypt, bool,
89 private_wolfssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
90 {
91 u_char *out;
92 bool success = FALSE;
93 int ret;
94 u_char nonce[AES_BLOCK_SIZE] = {0};
95 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
96 chunk_t d = chunk_empty;
97 #endif
98
99 out = data.ptr;
100 if (dst)
101 {
102 *dst = chunk_alloc(data.len);
103 out = dst->ptr;
104 }
105
106 if (this->salt.len > 0)
107 {
108 memcpy(nonce, this->salt.ptr, this->salt.len);
109 memcpy(nonce + this->salt.len, iv.ptr, this->iv_size);
110 nonce[AES_BLOCK_SIZE - 1] = 1;
111 }
112
113 switch (this->alg)
114 {
115 case ENCR_NULL:
116 memcpy(out, data.ptr, data.len);
117 success = TRUE;
118 break;
119 #if !defined(NO_AES) && !defined(NO_AES_CBC)
120 case ENCR_AES_CBC:
121 ret = wc_AesSetKey(&this->cipher.aes, this->key.ptr, this->key.len,
122 iv.ptr, AES_DECRYPTION);
123 if (ret == 0)
124 {
125 ret = wc_AesCbcDecrypt(&this->cipher.aes, out, data.ptr,
126 data.len);
127 }
128 success = (ret == 0);
129 break;
130 #endif
131 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
132 case ENCR_AES_CTR:
133 if (out == data.ptr)
134 {
135 d = chunk_alloc(data.len);
136 out = d.ptr;
137 }
138 ret = wc_AesSetKeyDirect(&this->cipher.aes, this->key.ptr,
139 this->key.len, nonce, AES_ENCRYPTION);
140 if (ret == 0)
141 {
142 ret = wc_AesCtrEncrypt(&this->cipher.aes, out, data.ptr,
143 data.len);
144 }
145 if (ret == 0 && out == d.ptr)
146 {
147 memcpy(data.ptr, out, data.len);
148 }
149 chunk_free(&d);
150 success = (ret == 0);
151 break;
152 #endif
153 #ifdef HAVE_CAMELLIA
154 case ENCR_CAMELLIA_CBC:
155 ret = wc_CamelliaSetKey(&this->cipher.camellia, this->key.ptr,
156 this->key.len, iv.ptr);
157 if (ret == 0)
158 {
159 ret = wc_CamelliaCbcDecrypt(&this->cipher.camellia, out,
160 data.ptr, data.len);
161 }
162 success = (ret == 0);
163 break;
164 #endif
165 #ifndef NO_DES3
166 case ENCR_3DES:
167 ret = wc_Des3_SetKey(&this->cipher.des3, this->key.ptr, iv.ptr,
168 DES_DECRYPTION);
169 if (ret == 0)
170 {
171 ret = wc_Des3_CbcDecrypt(&this->cipher.des3, out, data.ptr,
172 data.len);
173 }
174 success = (ret == 0);
175 break;
176 case ENCR_DES:
177 ret = wc_Des_SetKey(&this->cipher.des, this->key.ptr, iv.ptr,
178 DES_DECRYPTION);
179 if (ret == 0)
180 {
181 ret = wc_Des_CbcDecrypt(&this->cipher.des, out, data.ptr,
182 data.len);
183 }
184 if (ret == 0)
185 success = TRUE;
186 break;
187 #ifdef WOLFSSL_DES_ECB
188 case ENCR_DES_ECB:
189 ret = wc_Des_SetKey(&this->cipher.des, this->key.ptr, iv.ptr,
190 DES_DECRYPTION);
191 if (ret == 0)
192 {
193 ret = wc_Des_EcbDecrypt(&this->cipher.des, out, data.ptr,
194 data.len);
195 }
196 success = (ret == 0);
197 break;
198 #endif
199 #endif
200 default:
201 break;
202 }
203
204 memwipe(nonce, sizeof(nonce));
205 return success;
206 }
207
208 METHOD(crypter_t, encrypt, bool,
209 private_wolfssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
210 {
211 u_char *out;
212 bool success = FALSE;
213 int ret;
214 u_char nonce[AES_BLOCK_SIZE] = {0};
215 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
216 chunk_t d = chunk_empty;
217 #endif
218
219 out = data.ptr;
220 if (dst)
221 {
222 *dst = chunk_alloc(data.len);
223 out = dst->ptr;
224 }
225
226 if (this->salt.len > 0)
227 {
228 memcpy(nonce, this->salt.ptr, this->salt.len);
229 memcpy(nonce + this->salt.len, iv.ptr, this->iv_size);
230 nonce[AES_BLOCK_SIZE - 1] = 1;
231 }
232
233 switch (this->alg)
234 {
235 case ENCR_NULL:
236 memcpy(out, data.ptr, data.len);
237 success = TRUE;
238 break;
239 #if !defined(NO_AES) && !defined(NO_AES_CBC)
240 case ENCR_AES_CBC:
241 ret = wc_AesSetKey(&this->cipher.aes, this->key.ptr, this->key.len,
242 iv.ptr, AES_ENCRYPTION);
243 if (ret == 0)
244 {
245 ret = wc_AesCbcEncrypt(&this->cipher.aes, out, data.ptr,
246 data.len);
247 }
248 success = (ret == 0);
249 break;
250 #endif
251 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
252 case ENCR_AES_CTR:
253 if (out == data.ptr)
254 {
255 d = chunk_alloc(data.len);
256 out = d.ptr;
257 }
258 ret = wc_AesSetKeyDirect(&this->cipher.aes, this->key.ptr,
259 this->key.len, nonce, AES_ENCRYPTION);
260 if (ret == 0)
261 {
262 ret = wc_AesCtrEncrypt(&this->cipher.aes, out, data.ptr,
263 data.len);
264 }
265 if (ret == 0 && out == d.ptr)
266 {
267 memcpy(data.ptr, out, data.len);
268 }
269 chunk_free(&d);
270 success = (ret == 0);
271 break;
272 #endif
273 #ifdef HAVE_CAMELLIA
274 case ENCR_CAMELLIA_CBC:
275 ret = wc_CamelliaSetKey(&this->cipher.camellia, this->key.ptr,
276 this->key.len, iv.ptr);
277 if (ret == 0)
278 {
279 ret = wc_CamelliaCbcEncrypt(&this->cipher.camellia, out,
280 data.ptr, data.len);
281 }
282 success = (ret == 0);
283 break;
284 #endif
285 #ifndef NO_DES3
286 case ENCR_3DES:
287 ret = wc_Des3_SetKey(&this->cipher.des3, this->key.ptr, iv.ptr,
288 DES_ENCRYPTION);
289 if (ret == 0)
290 {
291 ret = wc_Des3_CbcEncrypt(&this->cipher.des3, out, data.ptr,
292 data.len);
293 }
294 success = (ret == 0);
295 break;
296 case ENCR_DES:
297 ret = wc_Des_SetKey(&this->cipher.des, this->key.ptr, iv.ptr,
298 DES_ENCRYPTION);
299 if (ret == 0)
300 {
301 ret = wc_Des_CbcEncrypt(&this->cipher.des, out, data.ptr,
302 data.len);
303 }
304 success = (ret == 0);
305 break;
306 #ifdef WOLFSSL_DES_ECB
307 case ENCR_DES_ECB:
308 ret = wc_Des_SetKey(&this->cipher.des, this->key.ptr, iv.ptr,
309 DES_ENCRYPTION);
310 if (ret == 0)
311 {
312 ret = wc_Des_EcbEncrypt(&this->cipher.des, out, data.ptr,
313 data.len);
314 }
315 success = (ret == 0);
316 break;
317 #endif
318 #endif
319 default:
320 break;
321 }
322
323 return success;
324 }
325
326 METHOD(crypter_t, get_block_size, size_t,
327 private_wolfssl_crypter_t *this)
328 {
329 return this->block_size;
330 }
331
332 METHOD(crypter_t, get_iv_size, size_t,
333 private_wolfssl_crypter_t *this)
334 {
335 return this->iv_size;
336 }
337
338 METHOD(crypter_t, get_key_size, size_t,
339 private_wolfssl_crypter_t *this)
340 {
341 return this->key.len + this->salt.len;
342 }
343
344 METHOD(crypter_t, set_key, bool,
345 private_wolfssl_crypter_t *this, chunk_t key)
346 {
347 if (key.len != get_key_size(this))
348 {
349 return FALSE;
350 }
351 memcpy(this->salt.ptr, key.ptr + key.len - this->salt.len, this->salt.len);
352 memcpy(this->key.ptr, key.ptr, this->key.len);
353 return TRUE;
354 }
355
356 METHOD(crypter_t, destroy, void,
357 private_wolfssl_crypter_t *this)
358 {
359 chunk_clear(&this->key);
360 chunk_clear(&this->salt);
361 switch (this->alg)
362 {
363 #if !defined(NO_AES) && !defined(NO_AES_CBC)
364 case ENCR_AES_CBC:
365 wc_AesFree(&this->cipher.aes);
366 break;
367 #endif
368 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
369 case ENCR_AES_CTR:
370 wc_AesFree(&this->cipher.aes);
371 break;
372 #endif
373 #ifndef NO_DES3
374 case ENCR_3DES:
375 wc_Des3Free(&this->cipher.des3);
376 break;
377 #endif
378 default:
379 break;
380 }
381 free(this);
382 }
383
384 /*
385 * Described in header
386 */
387 wolfssl_crypter_t *wolfssl_crypter_create(encryption_algorithm_t algo,
388 size_t key_size)
389 {
390 private_wolfssl_crypter_t *this;
391 size_t block_size;
392 size_t iv_size;
393 size_t salt_len = 0;
394 int ret = 0;
395
396 switch (algo)
397 {
398 case ENCR_NULL:
399 key_size = 0;
400 block_size = 1;
401 iv_size = 0;
402 break;
403 #if !defined(NO_AES) && !defined(NO_AES_CBC)
404 case ENCR_AES_CBC:
405 switch (key_size)
406 {
407 case 0:
408 key_size = 16;
409 /* fall-through */
410 case 16:
411 case 24:
412 case 32:
413 block_size = AES_BLOCK_SIZE;
414 iv_size = AES_IV_SIZE;
415 break;
416 default:
417 return NULL;
418 }
419 break;
420 #endif
421 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
422 case ENCR_AES_CTR:
423 switch (key_size)
424 {
425 case 0:
426 key_size = 16;
427 /* fall-through */
428 case 16:
429 case 24:
430 case 32:
431 block_size = 1;
432 iv_size = 8;
433 salt_len = CTR_SALT_LEN;
434 break;
435 default:
436 return NULL;
437 }
438 break;
439 #endif
440 #ifdef HAVE_CAMELLIA
441 case ENCR_CAMELLIA_CBC:
442 switch (key_size)
443 {
444 case 0:
445 key_size = 16;
446 /* fall-through */
447 case 16:
448 case 24:
449 case 32:
450 block_size = CAMELLIA_BLOCK_SIZE;
451 iv_size = CAMELLIA_BLOCK_SIZE;
452 break;
453 default:
454 return NULL;
455 }
456 break;
457 #endif
458 #ifndef NO_DES3
459 case ENCR_3DES:
460 if (key_size != 24)
461 {
462 return NULL;
463 }
464 block_size = DES_BLOCK_SIZE;
465 iv_size = DES_BLOCK_SIZE;
466 break;
467 case ENCR_DES:
468 #ifdef WOLFSSL_DES_ECB
469 case ENCR_DES_ECB:
470 #endif
471 if (key_size != 8)
472 {
473 return NULL;
474 }
475 block_size = DES_BLOCK_SIZE;
476 iv_size = DES_BLOCK_SIZE;
477 break;
478 #endif
479 default:
480 return NULL;
481 }
482
483 INIT(this,
484 .public = {
485 .crypter = {
486 .encrypt = _encrypt,
487 .decrypt = _decrypt,
488 .get_block_size = _get_block_size,
489 .get_iv_size = _get_iv_size,
490 .get_key_size = _get_key_size,
491 .set_key = _set_key,
492 .destroy = _destroy,
493 },
494 },
495 .alg = algo,
496 .block_size = block_size,
497 .iv_size = iv_size,
498 );
499
500 switch (algo)
501 {
502 #if !defined(NO_AES) && !defined(NO_AES_CBC)
503 case ENCR_AES_CBC:
504 ret = wc_AesInit(&this->cipher.aes, NULL, INVALID_DEVID);
505 break;
506 #endif
507 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
508 case ENCR_AES_CTR:
509 ret = wc_AesInit(&this->cipher.aes, NULL, INVALID_DEVID);
510 break;
511 #endif
512 #ifndef NO_DES3
513 case ENCR_3DES:
514 ret = wc_Des3Init(&this->cipher.des3, NULL, INVALID_DEVID);
515 break;
516 #endif
517 default:
518 break;
519 }
520 if (ret != 0)
521 {
522 free(this);
523 return NULL;
524 }
525
526 this->key = chunk_alloc(key_size);
527 this->salt = chunk_alloc(salt_len);
528
529 return &this->public;
530 }