Annotation of embedaddon/strongswan/src/libstrongswan/plugins/wolfssl/wolfssl_crypter.c, revision 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>