Annotation of embedaddon/strongswan/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2009 Martin Willi
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "gcrypt_crypter.h"
                     17: 
                     18: #include <gcrypt.h>
                     19: 
                     20: #include <utils/debug.h>
                     21: 
                     22: typedef struct private_gcrypt_crypter_t private_gcrypt_crypter_t;
                     23: 
                     24: /**
                     25:  * Private data of gcrypt_crypter_t
                     26:  */
                     27: struct private_gcrypt_crypter_t {
                     28: 
                     29:        /**
                     30:         * Public part of this class.
                     31:         */
                     32:        gcrypt_crypter_t public;
                     33: 
                     34:        /**
                     35:         * gcrypt cipher handle
                     36:         */
                     37:        gcry_cipher_hd_t h;
                     38: 
                     39:        /**
                     40:         * gcrypt algorithm identifier
                     41:         */
                     42:        int alg;
                     43: 
                     44:        /**
                     45:         * are we using counter mode?
                     46:         */
                     47:        bool ctr_mode;
                     48: 
                     49:        /**
                     50:         * counter state
                     51:         */
                     52:        struct {
                     53:                char nonce[4];
                     54:                char iv[8];
                     55:                uint32_t counter;
                     56:        } __attribute__((packed)) ctr;
                     57: };
                     58: 
                     59: /**
                     60:  * Set the IV for en/decryption
                     61:  */
                     62: static bool set_iv(private_gcrypt_crypter_t *this, chunk_t iv)
                     63: {
                     64:        if (this->ctr_mode)
                     65:        {
                     66:                memcpy(this->ctr.iv, iv.ptr, sizeof(this->ctr.iv));
                     67:                this->ctr.counter = htonl(1);
                     68:                return gcry_cipher_setctr(this->h, &this->ctr, sizeof(this->ctr)) == 0;
                     69:        }
                     70:        return gcry_cipher_setiv(this->h, iv.ptr, iv.len) == 0;
                     71: }
                     72: 
                     73: METHOD(crypter_t, decrypt, bool,
                     74:        private_gcrypt_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
                     75: {
                     76:        if (!set_iv(this, iv))
                     77:        {
                     78:                return FALSE;
                     79:        }
                     80:        if (dst)
                     81:        {
                     82:                *dst = chunk_alloc(data.len);
                     83:                return gcry_cipher_decrypt(this->h, dst->ptr, dst->len,
                     84:                                                                   data.ptr, data.len) == 0;
                     85:        }
                     86:        return gcry_cipher_decrypt(this->h, data.ptr, data.len, NULL, 0) == 0;
                     87: }
                     88: 
                     89: METHOD(crypter_t, encrypt, bool,
                     90:        private_gcrypt_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
                     91: {
                     92:        if (!set_iv(this, iv))
                     93:        {
                     94:                return FALSE;
                     95:        }
                     96:        if (dst)
                     97:        {
                     98:                *dst = chunk_alloc(data.len);
                     99:                return gcry_cipher_encrypt(this->h, dst->ptr, dst->len,
                    100:                                                                   data.ptr, data.len) == 0;
                    101:        }
                    102:        return gcry_cipher_encrypt(this->h, data.ptr, data.len, NULL, 0) == 0;
                    103: }
                    104: 
                    105: METHOD(crypter_t, get_block_size, size_t,
                    106:        private_gcrypt_crypter_t *this)
                    107: {
                    108:        size_t len = 0;
                    109: 
                    110:        if (this->ctr_mode)
                    111:        {       /* counter mode does not need any padding */
                    112:                return 1;
                    113:        }
                    114:        gcry_cipher_algo_info(this->alg, GCRYCTL_GET_BLKLEN, NULL, &len);
                    115:        return len;
                    116: }
                    117: 
                    118: METHOD(crypter_t, get_iv_size, size_t,
                    119:        private_gcrypt_crypter_t *this)
                    120: {
                    121:        size_t len = 0;
                    122: 
                    123:        if (this->ctr_mode)
                    124:        {
                    125:                return sizeof(this->ctr.iv);
                    126:        }
                    127:        gcry_cipher_algo_info(this->alg, GCRYCTL_GET_BLKLEN, NULL, &len);
                    128:        return len;
                    129: }
                    130: 
                    131: METHOD(crypter_t, get_key_size, size_t,
                    132:        private_gcrypt_crypter_t *this)
                    133: {
                    134:        size_t len = 0;
                    135: 
                    136:        gcry_cipher_algo_info(this->alg, GCRYCTL_GET_KEYLEN, NULL, &len);
                    137:        if (this->ctr_mode)
                    138:        {
                    139:                return len + sizeof(this->ctr.nonce);
                    140:        }
                    141:        return len;
                    142: }
                    143: 
                    144: METHOD(crypter_t, set_key, bool,
                    145:        private_gcrypt_crypter_t *this, chunk_t key)
                    146: {
                    147:        if (this->ctr_mode)
                    148:        {
                    149:                /* last 4 bytes are the nonce */
                    150:                memcpy(this->ctr.nonce, key.ptr + key.len - sizeof(this->ctr.nonce),
                    151:                           sizeof(this->ctr.nonce));
                    152:                key.len -= sizeof(this->ctr.nonce);
                    153:        }
                    154:        return gcry_cipher_setkey(this->h, key.ptr, key.len) == 0;
                    155: }
                    156: 
                    157: METHOD(crypter_t, destroy, void,
                    158:        private_gcrypt_crypter_t *this)
                    159: {
                    160:        gcry_cipher_close(this->h);
                    161:        free(this);
                    162: }
                    163: 
                    164: /*
                    165:  * Described in header
                    166:  */
                    167: gcrypt_crypter_t *gcrypt_crypter_create(encryption_algorithm_t algo,
                    168:                                                                                size_t key_size)
                    169: {
                    170:        private_gcrypt_crypter_t *this;
                    171:        int gcrypt_alg;
                    172:        int mode = GCRY_CIPHER_MODE_CBC;
                    173:        gcry_error_t err;
                    174: 
                    175:        switch (algo)
                    176:        {
                    177:                case ENCR_DES:
                    178:                        gcrypt_alg = GCRY_CIPHER_DES;
                    179:                        break;
                    180:                case ENCR_DES_ECB:
                    181:                        gcrypt_alg = GCRY_CIPHER_DES;
                    182:                        mode = GCRY_CIPHER_MODE_ECB;
                    183:                        break;
                    184:                case ENCR_3DES:
                    185:                        gcrypt_alg = GCRY_CIPHER_3DES;
                    186:                        break;
                    187:                case ENCR_IDEA:
                    188:                        /* currently not implemented in gcrypt */
                    189:                        return NULL;
                    190:                case ENCR_CAST:
                    191:                        gcrypt_alg = GCRY_CIPHER_CAST5;
                    192:                        break;
                    193:                case ENCR_BLOWFISH:
                    194:                        if (key_size != 16 && key_size != 0)
                    195:                        {       /* gcrypt currently supports 128 bit blowfish only */
                    196:                                return NULL;
                    197:                        }
                    198:                        gcrypt_alg = GCRY_CIPHER_BLOWFISH;
                    199:                        break;
                    200:                case ENCR_AES_CTR:
                    201:                case ENCR_AES_ECB:
                    202:                        mode = (algo == ENCR_AES_CTR) ? GCRY_CIPHER_MODE_CTR :
                    203:                                                                                        GCRY_CIPHER_MODE_ECB;
                    204:                        /* fall */
                    205:                case ENCR_AES_CBC:
                    206:                        switch (key_size)
                    207:                        {
                    208:                                case 0:
                    209:                                case 16:
                    210:                                        gcrypt_alg = GCRY_CIPHER_AES128;
                    211:                                        break;
                    212:                                case 24:
                    213:                                        gcrypt_alg = GCRY_CIPHER_AES192;
                    214:                                        break;
                    215:                                case 32:
                    216:                                        gcrypt_alg = GCRY_CIPHER_AES256;
                    217:                                        break;
                    218:                                default:
                    219:                                        return NULL;
                    220:                        }
                    221:                        break;
                    222:                case ENCR_CAMELLIA_CTR:
                    223:                        mode = GCRY_CIPHER_MODE_CTR;
                    224:                        /* fall */
                    225:                case ENCR_CAMELLIA_CBC:
                    226:                        switch (key_size)
                    227:                        {
                    228: #ifdef HAVE_GCRY_CIPHER_CAMELLIA
                    229:                                case 0:
                    230:                                case 16:
                    231:                                        gcrypt_alg = GCRY_CIPHER_CAMELLIA128;
                    232:                                        break;
                    233:                                case 24:
                    234:                                        gcrypt_alg = GCRY_CIPHER_CAMELLIA192;
                    235:                                        break;
                    236:                                case 32:
                    237:                                        gcrypt_alg = GCRY_CIPHER_CAMELLIA256;
                    238:                                        break;
                    239: #endif /* HAVE_GCRY_CIPHER_CAMELLIA */
                    240:                                default:
                    241:                                        return NULL;
                    242:                        }
                    243:                        break;
                    244:                case ENCR_SERPENT_CBC:
                    245:                        switch (key_size)
                    246:                        {
                    247:                                case 0:
                    248:                                case 16:
                    249:                                        gcrypt_alg = GCRY_CIPHER_SERPENT128;
                    250:                                        break;
                    251:                                case 24:
                    252:                                        gcrypt_alg = GCRY_CIPHER_SERPENT192;
                    253:                                        break;
                    254:                                case 32:
                    255:                                        gcrypt_alg = GCRY_CIPHER_SERPENT256;
                    256:                                        break;
                    257:                                default:
                    258:                                        return NULL;
                    259:                        }
                    260:                        break;
                    261:                case ENCR_TWOFISH_CBC:
                    262:                        switch (key_size)
                    263:                        {
                    264:                                case 0:
                    265:                                case 16:
                    266:                                        gcrypt_alg = GCRY_CIPHER_TWOFISH128;
                    267:                                        break;
                    268:                                case 32:
                    269:                                        gcrypt_alg = GCRY_CIPHER_TWOFISH;
                    270:                                        break;
                    271:                                default:
                    272:                                        return NULL;
                    273:                        }
                    274:                        break;
                    275:                default:
                    276:                        return NULL;
                    277:        }
                    278: 
                    279:        INIT(this,
                    280:                .public = {
                    281:                        .crypter = {
                    282:                                .encrypt = _encrypt,
                    283:                                .decrypt = _decrypt,
                    284:                                .get_block_size = _get_block_size,
                    285:                                .get_iv_size = _get_iv_size,
                    286:                                .get_key_size = _get_key_size,
                    287:                                .set_key = _set_key,
                    288:                                .destroy = _destroy,
                    289:                        },
                    290:                },
                    291:                .alg = gcrypt_alg,
                    292:                .ctr_mode = mode == GCRY_CIPHER_MODE_CTR,
                    293:        );
                    294: 
                    295:        err = gcry_cipher_open(&this->h, gcrypt_alg, mode, 0);
                    296:        if (err)
                    297:        {
                    298:                DBG1(DBG_LIB, "grcy_cipher_open(%N) failed: %s",
                    299:                         encryption_algorithm_names, algo, gpg_strerror(err));
                    300:                free(this);
                    301:                return NULL;
                    302:        }
                    303:        return &this->public;
                    304: }
                    305: 

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