Annotation of embedaddon/strongswan/src/libstrongswan/plugins/wolfssl/wolfssl_aead.c, revision 1.1.1.1
1.1 misho 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_common.h"
24:
25: #if (!defined(NO_AES) && (defined(HAVE_AESGCM) || defined(HAVE_AESCCM))) || \
26: (defined(HAVE_CHACHA) && defined(HAVE_POLY1305))
27:
28: #include "wolfssl_aead.h"
29:
30: #include <wolfssl/wolfcrypt/aes.h>
31: #include <wolfssl/wolfcrypt/chacha.h>
32: #include <wolfssl/wolfcrypt/chacha20_poly1305.h>
33: #include <crypto/iv/iv_gen_seq.h>
34:
35: /** as defined in RFC 4106 */
36: #define IV_LEN 8
37: #define GCM_SALT_LEN 4
38: #define GCM_NONCE_LEN (GCM_SALT_LEN + IV_LEN)
39:
40: #define CCM_SALT_LEN 3
41: #define CCM_NONCE_LEN (CCM_SALT_LEN + IV_LEN)
42:
43: typedef struct private_aead_t private_aead_t;
44:
45: /**
46: * Private data of aead_t
47: */
48: struct private_aead_t {
49:
50: /**
51: * Public interface
52: */
53: aead_t public;
54:
55: /**
56: * The encryption key
57: */
58: chunk_t key;
59:
60: /**
61: * Salt value
62: */
63: chunk_t salt;
64:
65: /**
66: * Size of the integrity check value
67: */
68: size_t icv_size;
69:
70: /**
71: * IV generator
72: */
73: iv_gen_t *iv_gen;
74:
75: /**
76: * The cipher to use
77: */
78: union {
79: #if !defined(NO_AES) && (defined(HAVE_AESGCM) || defined(HAVE_AESCCM))
80: Aes aes;
81: #endif
82: } cipher;
83:
84: /**
85: * The cipher to use
86: */
87: encryption_algorithm_t alg;
88: };
89:
90: METHOD(aead_t, encrypt, bool,
91: private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
92: chunk_t *encrypted)
93: {
94: chunk_t nonce;
95: u_char *out;
96: bool success = FALSE;
97: int ret;
98:
99: out = plain.ptr;
100: if (encrypted)
101: {
102: *encrypted = chunk_alloc(plain.len + this->icv_size);
103: out = encrypted->ptr;
104: }
105:
106: nonce = chunk_cata("cc", this->salt, iv);
107:
108: switch (this->alg)
109: {
110: #if !defined(NO_AES) && defined(HAVE_AESGCM)
111: case ENCR_AES_GCM_ICV8:
112: case ENCR_AES_GCM_ICV12:
113: case ENCR_AES_GCM_ICV16:
114: ret = wc_AesGcmSetKey(&this->cipher.aes, this->key.ptr,
115: this->key.len);
116: if (ret == 0)
117: {
118: ret = wc_AesGcmEncrypt(&this->cipher.aes, out, plain.ptr,
119: plain.len, nonce.ptr, GCM_NONCE_LEN, out + plain.len,
120: this->icv_size, assoc.ptr, assoc.len);
121: }
122: success = (ret == 0);
123: break;
124: #endif
125: #if !defined(NO_AES) && defined(HAVE_AESCCM)
126: case ENCR_AES_CCM_ICV8:
127: case ENCR_AES_CCM_ICV12:
128: case ENCR_AES_CCM_ICV16:
129: /* wc_AesCcmEncrypt fails if the pointer is NULL */
130: if (!plain.ptr && !plain.len)
131: {
132: plain.ptr = nonce.ptr;
133: }
134: ret = wc_AesCcmSetKey(&this->cipher.aes, this->key.ptr,
135: this->key.len);
136: if (ret == 0)
137: {
138: ret = wc_AesCcmEncrypt(&this->cipher.aes, out, plain.ptr,
139: plain.len, nonce.ptr, CCM_NONCE_LEN, out + plain.len,
140: this->icv_size, assoc.ptr, assoc.len);
141: }
142: success = (ret == 0);
143: break;
144: #endif
145: #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
146: case ENCR_CHACHA20_POLY1305:
147: ret = wc_ChaCha20Poly1305_Encrypt(this->key.ptr, nonce.ptr,
148: assoc.ptr, assoc.len, plain.ptr, plain.len, out,
149: out + plain.len);
150: success = (ret == 0);
151: break;
152: #endif
153: default:
154: break;
155: }
156:
157: memwipe(nonce.ptr, nonce.len);
158: return success;
159: }
160:
161: METHOD(aead_t, decrypt, bool,
162: private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
163: chunk_t *plain)
164: {
165: chunk_t nonce;
166: u_char *out;
167: bool success = FALSE;
168: int ret = 0;
169:
170: if (encrypted.len < this->icv_size)
171: {
172: return FALSE;
173: }
174: encrypted.len -= this->icv_size;
175:
176: out = encrypted.ptr;
177: if (plain)
178: {
179: *plain = chunk_alloc(encrypted.len);
180: out = plain->ptr;
181: }
182:
183: nonce = chunk_cata("cc", this->salt, iv);
184:
185: switch (this->alg)
186: {
187: #if !defined(NO_AES) && defined(HAVE_AESGCM)
188: case ENCR_AES_GCM_ICV8:
189: case ENCR_AES_GCM_ICV12:
190: case ENCR_AES_GCM_ICV16:
191: ret = wc_AesGcmSetKey(&this->cipher.aes, this->key.ptr,
192: this->key.len);
193: if (ret == 0)
194: {
195: ret = wc_AesGcmDecrypt(&this->cipher.aes, out, encrypted.ptr,
196: encrypted.len, nonce.ptr, GCM_NONCE_LEN,
197: encrypted.ptr + encrypted.len, this->icv_size,
198: assoc.ptr, assoc.len);
199: }
200: success = (ret == 0);
201: break;
202: #endif
203: #if !defined(NO_AES) && defined(HAVE_AESCCM)
204: case ENCR_AES_CCM_ICV8:
205: case ENCR_AES_CCM_ICV12:
206: case ENCR_AES_CCM_ICV16:
207: /* wc_AesCcmDecrypt() fails if the pointers are NULL */
208: if (!encrypted.ptr && !encrypted.len)
209: {
210: encrypted.ptr = nonce.ptr;
211: }
212: if (!out && !encrypted.len)
213: {
214: out = nonce.ptr;
215: }
216: ret = wc_AesCcmSetKey(&this->cipher.aes, this->key.ptr,
217: this->key.len);
218: if (ret == 0)
219: {
220: ret = wc_AesCcmDecrypt(&this->cipher.aes, out, encrypted.ptr,
221: encrypted.len, nonce.ptr, CCM_NONCE_LEN,
222: encrypted.ptr + encrypted.len, this->icv_size,
223: assoc.ptr, assoc.len);
224: }
225: success = (ret == 0);
226: break;
227: #endif
228: #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
229: case ENCR_CHACHA20_POLY1305:
230: ret = wc_ChaCha20Poly1305_Decrypt(this->key.ptr, nonce.ptr,
231: assoc.ptr, assoc.len, encrypted.ptr, encrypted.len,
232: encrypted.ptr + encrypted.len, out);
233: success = (ret == 0);
234: break;
235: #endif
236: default:
237: break;
238: }
239:
240: memwipe(nonce.ptr, nonce.len);
241: return success;
242: }
243:
244: METHOD(aead_t, get_block_size, size_t,
245: private_aead_t *this)
246: {
247: /* all AEAD algorithms are streaming */
248: return 1;
249: }
250:
251: METHOD(aead_t, get_icv_size, size_t,
252: private_aead_t *this)
253: {
254: return this->icv_size;
255: }
256:
257: METHOD(aead_t, get_iv_size, size_t,
258: private_aead_t *this)
259: {
260: return IV_LEN;
261: }
262:
263: METHOD(aead_t, get_iv_gen, iv_gen_t*,
264: private_aead_t *this)
265: {
266: return this->iv_gen;
267: }
268:
269: METHOD(aead_t, get_key_size, size_t,
270: private_aead_t *this)
271: {
272: return this->key.len + this->salt.len;
273: }
274:
275: METHOD(aead_t, set_key, bool,
276: private_aead_t *this, chunk_t key)
277: {
278: if (key.len != get_key_size(this))
279: {
280: return FALSE;
281: }
282: memcpy(this->salt.ptr, key.ptr + key.len - this->salt.len, this->salt.len);
283: memcpy(this->key.ptr, key.ptr, this->key.len);
284: return TRUE;
285: }
286:
287: METHOD(aead_t, destroy, void,
288: private_aead_t *this)
289: {
290: chunk_clear(&this->key);
291: chunk_clear(&this->salt);
292: switch (this->alg)
293: {
294: #if !defined(NO_AES) && defined(HAVE_AESGCM)
295: case ENCR_AES_GCM_ICV8:
296: case ENCR_AES_GCM_ICV12:
297: case ENCR_AES_GCM_ICV16:
298: wc_AesFree(&this->cipher.aes);
299: break;
300: #endif
301: #if !defined(NO_AES) && defined(HAVE_AESCCM)
302: case ENCR_AES_CCM_ICV8:
303: case ENCR_AES_CCM_ICV12:
304: case ENCR_AES_CCM_ICV16:
305: wc_AesFree(&this->cipher.aes);
306: break;
307: #endif
308: default:
309: break;
310: }
311: this->iv_gen->destroy(this->iv_gen);
312: free(this);
313: }
314:
315: /*
316: * Described in header
317: */
318: aead_t *wolfssl_aead_create(encryption_algorithm_t algo,
319: size_t key_size, size_t salt_size)
320: {
321: private_aead_t *this;
322: size_t expected_salt_size;
323:
324: INIT(this,
325: .public = {
326: .encrypt = _encrypt,
327: .decrypt = _decrypt,
328: .get_block_size = _get_block_size,
329: .get_icv_size = _get_icv_size,
330: .get_iv_size = _get_iv_size,
331: .get_iv_gen = _get_iv_gen,
332: .get_key_size = _get_key_size,
333: .set_key = _set_key,
334: .destroy = _destroy,
335: },
336: .alg = algo,
337: );
338:
339: switch (algo)
340: {
341: #if !defined(NO_AES) && defined(HAVE_AESGCM)
342: #if WOLFSSL_MIN_AUTH_TAG_SZ <= 8
343: case ENCR_AES_GCM_ICV8:
344: this->icv_size = 8;
345: break;
346: #endif
347: #if WOLFSSL_MIN_AUTH_TAG_SZ <= 12
348: case ENCR_AES_GCM_ICV12:
349: this->icv_size = 12;
350: break;
351: #endif
352: case ENCR_AES_GCM_ICV16:
353: this->icv_size = 16;
354: break;
355: #endif
356: #if !defined(NO_AES) && defined(HAVE_AESCCM)
357: case ENCR_AES_CCM_ICV8:
358: this->icv_size = 8;
359: break;
360: case ENCR_AES_CCM_ICV12:
361: this->icv_size = 12;
362: break;
363: case ENCR_AES_CCM_ICV16:
364: this->icv_size = 16;
365: break;
366: #endif
367: #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
368: case ENCR_CHACHA20_POLY1305:
369: this->icv_size = 16;
370: break;
371: #endif
372: default:
373: free(this);
374: return NULL;
375: }
376:
377: switch (algo)
378: {
379: #if !defined(NO_AES) && defined(HAVE_AESGCM)
380: case ENCR_AES_GCM_ICV8:
381: case ENCR_AES_GCM_ICV12:
382: case ENCR_AES_GCM_ICV16:
383: switch (key_size)
384: {
385: case 0:
386: key_size = 16;
387: /* FALL */
388: case 16:
389: case 24:
390: case 32:
391: expected_salt_size = GCM_SALT_LEN;
392: if (wc_AesInit(&this->cipher.aes, NULL, INVALID_DEVID) != 0)
393: {
394: DBG1(DBG_LIB, "AES Init failed, aead create failed");
395: free(this);
396: return NULL;
397: }
398: break;
399: default:
400: free(this);
401: return NULL;
402: }
403: break;
404: #endif
405: #if !defined(NO_AES) && defined(HAVE_AESCCM)
406: case ENCR_AES_CCM_ICV8:
407: case ENCR_AES_CCM_ICV12:
408: case ENCR_AES_CCM_ICV16:
409: switch (key_size)
410: {
411: case 0:
412: key_size = 16;
413: /* FALL */
414: case 16:
415: case 24:
416: case 32:
417: expected_salt_size = CCM_SALT_LEN;
418: if (wc_AesInit(&this->cipher.aes, NULL, INVALID_DEVID) != 0)
419: {
420: DBG1(DBG_LIB, "AES Init failed, aead create failed");
421: free(this);
422: return NULL;
423: }
424: break;
425: default:
426: free(this);
427: return NULL;
428: }
429: break;
430: #endif
431: #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
432: case ENCR_CHACHA20_POLY1305:
433: switch (key_size)
434: {
435: case 0:
436: key_size = 32;
437: /* FALL */
438: case 32:
439: expected_salt_size = 4;
440: break;
441: default:
442: free(this);
443: return NULL;
444: }
445: break;
446: #endif
447: default:
448: free(this);
449: return NULL;
450: }
451:
452: if (salt_size && salt_size != expected_salt_size)
453: {
454: /* currently not supported */
455: free(this);
456: return NULL;
457: }
458:
459: this->key = chunk_alloc(key_size);
460: this->salt = chunk_alloc(expected_salt_size);
461: this->iv_gen = iv_gen_seq_create();
462:
463: return &this->public;
464: }
465:
466: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>