Return to wolfssl_aead.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / wolfssl |
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