Annotation of embedaddon/strongswan/src/libstrongswan/plugins/wolfssl/wolfssl_crypter.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_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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>