wolfssl: Add wolfSSL plugin for cryptographic implementations
[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 {
51 #if !defined(NO_AES) && (!defined(NO_AES_CBC) || defined(WOLFSSL_AES_COUNTER))
52 Aes aes;
53 #endif
54 #ifdef HAVE_CAMELLIA
55 Camellia camellia;
56 #endif
57 #ifndef NO_DES3
58 Des des;
59 Des3 des3;
60 #endif
61 } cipher;
62
63 /**
64 * Encryption algorithm identifier
65 */
66 encryption_algorithm_t alg;
67
68 /**
69 * Private key
70 */
71 chunk_t key;
72
73 /**
74 * Salt value
75 */
76 char salt[CTR_SALT_LEN];
77
78 /**
79 * Length of the salt
80 */
81 size_t salt_len;
82
83 /**
84 * Size of key
85 */
86 size_t key_size;
87
88 /**
89 * Size of block
90 */
91 size_t block_size;
92
93 /**
94 * Size of IV
95 */
96 size_t iv_size;
97 };
98
99 METHOD(crypter_t, decrypt, bool,
100 private_wolfssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
101 {
102 u_char *out;
103 bool success = FALSE;
104 int ret;
105 u_char nonce[AES_BLOCK_SIZE] = {0};
106 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
107 chunk_t d = chunk_empty;
108 #endif
109
110 out = data.ptr;
111 if (dst)
112 {
113 *dst = chunk_alloc(data.len);
114 out = dst->ptr;
115 }
116
117 if (this->salt_len > 0)
118 {
119 memcpy(nonce, this->salt, this->salt_len);
120 memcpy(nonce + this->salt_len, iv.ptr, this->iv_size);
121 nonce[AES_BLOCK_SIZE - 1] = 1;
122 }
123
124 switch (this->alg)
125 {
126 case ENCR_NULL:
127 memcpy(out, data.ptr, data.len);
128 success = TRUE;
129 break;
130 #if !defined(NO_AES) && !defined(NO_AES_CBC)
131 case ENCR_AES_CBC:
132 ret = wc_AesSetKey(&this->cipher.aes, this->key.ptr, this->key.len,
133 iv.ptr, AES_DECRYPTION);
134 if (ret == 0)
135 {
136 ret = wc_AesCbcDecrypt(&this->cipher.aes, out, data.ptr,
137 data.len);
138 }
139 success = (ret == 0);
140 break;
141 #endif
142 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
143 case ENCR_AES_CTR:
144 if (out == data.ptr)
145 {
146 d = chunk_alloc(data.len);
147 out = d.ptr;
148 }
149 ret = wc_AesSetKeyDirect(&this->cipher.aes, this->key.ptr,
150 this->key.len, nonce, AES_ENCRYPTION);
151 if (ret == 0)
152 {
153 ret = wc_AesCtrEncrypt(&this->cipher.aes, out, data.ptr,
154 data.len);
155 }
156 if (ret == 0 && out == d.ptr)
157 {
158 memcpy(data.ptr, out, data.len);
159 }
160 chunk_free(&d);
161 success = (ret == 0);
162 break;
163 #endif
164 #ifdef HAVE_CAMELLIA
165 case ENCR_CAMELLIA_CBC:
166 ret = wc_CamelliaSetKey(&this->cipher.camellia, this->key.ptr,
167 this->key.len, iv.ptr);
168 if (ret == 0)
169 {
170 ret = wc_CamelliaCbcDecrypt(&this->cipher.camellia, out,
171 data.ptr, data.len);
172 }
173 success = (ret == 0);
174 break;
175 #endif
176 #ifndef NO_DES3
177 case ENCR_3DES:
178 ret = wc_Des3_SetKey(&this->cipher.des3, this->key.ptr, iv.ptr,
179 DES_DECRYPTION);
180 if (ret == 0)
181 {
182 ret = wc_Des3_CbcDecrypt(&this->cipher.des3, out, data.ptr,
183 data.len);
184 }
185 success = (ret == 0);
186 break;
187 case ENCR_DES:
188 ret = wc_Des_SetKey(&this->cipher.des, this->key.ptr, iv.ptr,
189 DES_DECRYPTION);
190 if (ret == 0)
191 {
192 ret = wc_Des_CbcDecrypt(&this->cipher.des, out, data.ptr,
193 data.len);
194 }
195 if (ret == 0)
196 success = TRUE;
197 break;
198 #ifdef WOLFSSL_DES_ECB
199 case ENCR_DES_ECB:
200 ret = wc_Des_SetKey(&this->cipher.des, this->key.ptr, iv.ptr,
201 DES_DECRYPTION);
202 if (ret == 0)
203 {
204 ret = wc_Des_EcbDecrypt(&this->cipher.des, out, data.ptr,
205 data.len);
206 }
207 success = (ret == 0);
208 break;
209 #endif
210 #endif
211 default:
212 break;
213 }
214
215 return success;
216 }
217
218 METHOD(crypter_t, encrypt, bool,
219 private_wolfssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
220 {
221 u_char *out;
222 bool success = FALSE;
223 int ret;
224 u_char nonce[AES_BLOCK_SIZE] = {0};
225 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
226 chunk_t d = chunk_empty;
227 #endif
228
229 out = data.ptr;
230 if (dst)
231 {
232 *dst = chunk_alloc(data.len);
233 out = dst->ptr;
234 }
235
236 if (this->salt_len > 0)
237 {
238 memcpy(nonce, this->salt, this->salt_len);
239 memcpy(nonce + this->salt_len, iv.ptr, this->iv_size);
240 nonce[AES_BLOCK_SIZE - 1] = 1;
241 }
242
243 switch (this->alg)
244 {
245 case ENCR_NULL:
246 memcpy(out, data.ptr, data.len);
247 success = TRUE;
248 break;
249 #if !defined(NO_AES) && !defined(NO_AES_CBC)
250 case ENCR_AES_CBC:
251 ret = wc_AesSetKey(&this->cipher.aes, this->key.ptr, this->key.len,
252 iv.ptr, AES_ENCRYPTION);
253 if (ret == 0)
254 {
255 ret = wc_AesCbcEncrypt(&this->cipher.aes, out, data.ptr,
256 data.len);
257 }
258 success = (ret == 0);
259 break;
260 #endif
261 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
262 case ENCR_AES_CTR:
263 if (out == data.ptr)
264 {
265 d = chunk_alloc(data.len);
266 out = d.ptr;
267 }
268 ret = wc_AesSetKeyDirect(&this->cipher.aes, this->key.ptr,
269 this->key.len, nonce, AES_ENCRYPTION);
270 if (ret == 0)
271 {
272 ret = wc_AesCtrEncrypt(&this->cipher.aes, out, data.ptr,
273 data.len);
274 }
275 if (ret == 0 && out == d.ptr)
276 {
277 memcpy(data.ptr, out, data.len);
278 }
279 chunk_free(&d);
280 success = (ret == 0);
281 break;
282 #endif
283 #ifdef HAVE_CAMELLIA
284 case ENCR_CAMELLIA_CBC:
285 ret = wc_CamelliaSetKey(&this->cipher.camellia, this->key.ptr,
286 this->key.len, iv.ptr);
287 if (ret == 0)
288 {
289 ret = wc_CamelliaCbcEncrypt(&this->cipher.camellia, out,
290 data.ptr, data.len);
291 }
292 success = (ret == 0);
293 break;
294 #endif
295 #ifndef NO_DES3
296 case ENCR_3DES:
297 ret = wc_Des3_SetKey(&this->cipher.des3, this->key.ptr, iv.ptr,
298 DES_ENCRYPTION);
299 if (ret == 0)
300 {
301 ret = wc_Des3_CbcEncrypt(&this->cipher.des3, out, data.ptr,
302 data.len);
303 }
304 success = (ret == 0);
305 break;
306 case ENCR_DES:
307 ret = wc_Des_SetKey(&this->cipher.des, this->key.ptr, iv.ptr,
308 DES_ENCRYPTION);
309 if (ret == 0)
310 {
311 ret = wc_Des_CbcEncrypt(&this->cipher.des, out, data.ptr,
312 data.len);
313 }
314 success = (ret == 0);
315 break;
316 #ifdef WOLFSSL_DES_ECB
317 case ENCR_DES_ECB:
318 ret = wc_Des_SetKey(&this->cipher.des, this->key.ptr, iv.ptr,
319 DES_ENCRYPTION);
320 if (ret == 0)
321 {
322 ret = wc_Des_EcbEncrypt(&this->cipher.des, out, data.ptr,
323 data.len);
324 }
325 success = (ret == 0);
326 break;
327 #endif
328 #endif
329 default:
330 break;
331 }
332
333 return success;
334 }
335
336 METHOD(crypter_t, get_block_size, size_t,
337 private_wolfssl_crypter_t *this)
338 {
339 return this->block_size;
340 }
341
342 METHOD(crypter_t, get_iv_size, size_t,
343 private_wolfssl_crypter_t *this)
344 {
345 return this->iv_size;
346 }
347
348 METHOD(crypter_t, get_key_size, size_t,
349 private_wolfssl_crypter_t *this)
350 {
351 return this->key.len + this->salt_len;
352 }
353
354 METHOD(crypter_t, set_key, bool,
355 private_wolfssl_crypter_t *this, chunk_t key)
356 {
357 if (key.len != get_key_size(this))
358 {
359 return FALSE;
360 }
361 memcpy(this->salt, key.ptr + key.len - this->salt_len, this->salt_len);
362 memcpy(this->key.ptr, key.ptr, this->key.len);
363 return TRUE;
364 }
365
366 METHOD(crypter_t, destroy, void,
367 private_wolfssl_crypter_t *this)
368 {
369 chunk_clear(&this->key);
370 switch (this->alg)
371 {
372 #if !defined(NO_AES) && !defined(NO_AES_CBC)
373 case ENCR_AES_CBC:
374 wc_AesFree(&this->cipher.aes);
375 break;
376 #endif
377 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
378 case ENCR_AES_CTR:
379 wc_AesFree(&this->cipher.aes);
380 break;
381 #endif
382 #ifdef HAVE_CAMELLIA
383 case ENCR_CAMELLIA_CBC:
384 break;
385 #endif
386 #ifndef NO_DES3
387 case ENCR_3DES:
388 wc_Des3Free(&this->cipher.des3);
389 break;
390 case ENCR_DES:
391 #ifdef WOLFSSL_DES_ECB
392 case ENCR_DES_ECB:
393 #endif
394 break;
395 #endif
396 default:
397 break;
398 }
399 free(this);
400 }
401
402 /*
403 * Described in header
404 */
405 wolfssl_crypter_t *wolfssl_crypter_create(encryption_algorithm_t algo,
406 size_t key_size)
407 {
408 private_wolfssl_crypter_t *this;
409 size_t block_size;
410 size_t iv_size;
411 size_t salt_len = 0;
412 int ret = 0;
413
414 switch (algo)
415 {
416 case ENCR_NULL:
417 key_size = 0;
418 block_size = 1;
419 iv_size = 0;
420 break;
421 #if !defined(NO_AES) && !defined(NO_AES_CBC)
422 case ENCR_AES_CBC:
423 switch (key_size)
424 {
425 case 0:
426 key_size = 16;
427 case 16:
428 case 24:
429 case 32:
430 block_size = AES_BLOCK_SIZE;
431 iv_size = AES_IV_SIZE;
432 break;
433 default:
434 return NULL;
435 }
436 break;
437 #endif
438 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
439 case ENCR_AES_CTR:
440 switch (key_size)
441 {
442 case 0:
443 key_size = 16;
444 case 16:
445 case 24:
446 case 32:
447 block_size = 1;
448 iv_size = 8;
449 salt_len = CTR_SALT_LEN;
450 break;
451 default:
452 return NULL;
453 }
454 break;
455 #endif
456 #ifdef HAVE_CAMELLIA
457 case ENCR_CAMELLIA_CBC:
458 switch (key_size)
459 {
460 case 0:
461 key_size = 16;
462 case 16:
463 case 24:
464 case 32:
465 block_size = CAMELLIA_BLOCK_SIZE;
466 iv_size = CAMELLIA_BLOCK_SIZE;
467 break;
468 default:
469 return NULL;
470 }
471 break;
472 #endif
473 #ifndef NO_DES3
474 case ENCR_3DES:
475 if (key_size != 24)
476 {
477 return NULL;
478 }
479 block_size = DES_BLOCK_SIZE;
480 iv_size = DES_BLOCK_SIZE;
481 break;
482 case ENCR_DES:
483 if (key_size != 8)
484 {
485 return NULL;
486 }
487 block_size = DES_BLOCK_SIZE;
488 iv_size = DES_BLOCK_SIZE;
489 break;
490 #ifdef WOLFSSL_DES_ECB
491 case ENCR_DES_ECB:
492 if (key_size != 8)
493 {
494 return NULL;
495 }
496 key_size = DES_BLOCK_SIZE;
497 block_size = DES_BLOCK_SIZE;
498 iv_size = DES_BLOCK_SIZE;
499 break;
500 #endif
501 #endif
502 default:
503 return NULL;
504 }
505
506 INIT(this,
507 .public = {
508 .crypter = {
509 .encrypt = _encrypt,
510 .decrypt = _decrypt,
511 .get_block_size = _get_block_size,
512 .get_iv_size = _get_iv_size,
513 .get_key_size = _get_key_size,
514 .set_key = _set_key,
515 .destroy = _destroy,
516 },
517 },
518 .alg = algo,
519 .key_size = key_size,
520 .block_size = block_size,
521 .iv_size = iv_size,
522 .salt_len = salt_len,
523 );
524
525 switch (algo)
526 {
527 #if !defined(NO_AES) && !defined(NO_AES_CBC)
528 case ENCR_AES_CBC:
529 ret = wc_AesInit(&this->cipher.aes, NULL, INVALID_DEVID);
530 break;
531 #endif
532 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
533 case ENCR_AES_CTR:
534 ret = wc_AesInit(&this->cipher.aes, NULL, INVALID_DEVID);
535 break;
536 #endif
537 #ifdef HAVE_CAMELLIA
538 case ENCR_CAMELLIA_CBC:
539 break;
540 #endif
541 #ifndef NO_DES3
542 case ENCR_3DES:
543 ret = wc_Des3Init(&this->cipher.des3, NULL, INVALID_DEVID);
544 break;
545 case ENCR_DES:
546 #ifdef WOLFSSL_DES_ECB
547 case ENCR_DES_ECB:
548 #endif
549 break;
550 #endif
551 default:
552 break;
553 }
554 if (ret != 0)
555 {
556 free(this);
557 return NULL;
558 }
559
560 this->key = chunk_alloc(key_size);
561
562 return &this->public;
563 }
564