Annotation of embedaddon/strongswan/src/libstrongswan/plugins/af_alg/af_alg_prf.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2010 Martin Willi
                      3:  * Copyright (C) 2010 revosec AG
                      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 "af_alg_prf.h"
                     17: #include "af_alg_ops.h"
                     18: 
                     19: typedef struct private_af_alg_prf_t private_af_alg_prf_t;
                     20: 
                     21: /**
                     22:  * Private data of a af_alg_prf_t object.
                     23:  */
                     24: struct private_af_alg_prf_t {
                     25: 
                     26:        /**
                     27:         * Public af_alg_prf_t interface.
                     28:         */
                     29:        af_alg_prf_t public;
                     30: 
                     31:        /**
                     32:         * AF_ALG operations
                     33:         */
                     34:        af_alg_ops_t *ops;
                     35: 
                     36:        /**
                     37:         * Size of the PRF output
                     38:         */
                     39:        size_t block_size;
                     40: 
                     41:        /**
                     42:         * Default key size
                     43:         */
                     44:        size_t key_size;
                     45: 
                     46:        /**
                     47:         * Using an XCBC algorithm?
                     48:         */
                     49:        bool xcbc;
                     50: };
                     51: 
                     52: /**
                     53:  * Algorithm database
                     54:  */
                     55: static struct {
                     56:        pseudo_random_function_t id;
                     57:        char *name;
                     58:        size_t block_size;
                     59:        bool xcbc;
                     60: } algs[AF_ALG_PRF] = {
                     61:        {PRF_HMAC_SHA1,                 "hmac(sha1)",           20,             FALSE,  },
                     62:        {PRF_HMAC_SHA2_256,             "hmac(sha256)",         32,             FALSE,  },
                     63:        {PRF_HMAC_MD5,                  "hmac(md5)",            16,             FALSE,  },
                     64:        {PRF_HMAC_SHA2_384,             "hmac(sha384)",         48,             FALSE,  },
                     65:        {PRF_HMAC_SHA2_512,             "hmac(sha512)",         64,             FALSE,  },
                     66:        {PRF_AES128_XCBC,               "xcbc(aes)",            16,             TRUE,   },
                     67:        {PRF_CAMELLIA128_XCBC,  "xcbc(camellia)",       16,             TRUE,   },
                     68: };
                     69: 
                     70: /**
                     71:  * See header.
                     72:  */
                     73: void af_alg_prf_probe(plugin_feature_t *features, int *pos)
                     74: {
                     75:        af_alg_ops_t *ops;
                     76:        int i;
                     77: 
                     78:        for (i = 0; i < countof(algs); i++)
                     79:        {
                     80:                ops = af_alg_ops_create("hash", algs[i].name);
                     81:                if (ops)
                     82:                {
                     83:                        ops->destroy(ops);
                     84:                        features[(*pos)++] = PLUGIN_PROVIDE(PRF, algs[i].id);
                     85:                }
                     86:        }
                     87: }
                     88: 
                     89: /**
                     90:  * Get the kernel algorithm string and block size for our identifier
                     91:  */
                     92: static size_t lookup_alg(pseudo_random_function_t algo, char **name, bool *xcbc)
                     93: {
                     94:        int i;
                     95: 
                     96:        for (i = 0; i < countof(algs); i++)
                     97:        {
                     98:                if (algs[i].id == algo)
                     99:                {
                    100:                        *name = algs[i].name;
                    101:                        *xcbc = algs[i].xcbc;
                    102:                        return algs[i].block_size;
                    103:                }
                    104:        }
                    105:        return 0;
                    106: }
                    107: 
                    108: METHOD(prf_t, get_bytes, bool,
                    109:        private_af_alg_prf_t *this, chunk_t seed, uint8_t *buffer)
                    110: {
                    111:        return this->ops->hash(this->ops, seed, buffer, this->block_size);
                    112: }
                    113: 
                    114: METHOD(prf_t, allocate_bytes, bool,
                    115:        private_af_alg_prf_t *this, chunk_t seed, chunk_t *chunk)
                    116: {
                    117:        if (chunk)
                    118:        {
                    119:                *chunk = chunk_alloc(this->block_size);
                    120:                return get_bytes(this, seed, chunk->ptr);
                    121:        }
                    122:        return get_bytes(this, seed, NULL);
                    123: }
                    124: 
                    125: METHOD(prf_t, get_block_size, size_t,
                    126:        private_af_alg_prf_t *this)
                    127: {
                    128:        return this->block_size;
                    129: }
                    130: 
                    131: METHOD(prf_t, get_key_size, size_t,
                    132:        private_af_alg_prf_t *this)
                    133: {
                    134:        return this->block_size;
                    135: }
                    136: 
                    137: METHOD(prf_t, set_key, bool,
                    138:        private_af_alg_prf_t *this, chunk_t key)
                    139: {
                    140:        char buf[this->block_size];
                    141: 
                    142:        this->ops->reset(this->ops);
                    143:        if (this->xcbc)
                    144:        {
                    145:                /* The kernel currently does not support variable length XCBC keys,
                    146:                 * do RFC4434 key padding/reduction manually. */
                    147:                if (key.len < this->block_size)
                    148:                {
                    149:                        memset(buf, 0, this->block_size);
                    150:                        memcpy(buf, key.ptr, key.len);
                    151:                        key = chunk_from_thing(buf);
                    152:                }
                    153:                else if (key.len > this->block_size)
                    154:                {
                    155:                        memset(buf, 0, this->block_size);
                    156:                        if (!this->ops->set_key(this->ops, chunk_from_thing(buf)) ||
                    157:                                !this->ops->hash(this->ops, key, buf, this->block_size))
                    158:                        {
                    159:                                return FALSE;
                    160:                        }
                    161:                        key = chunk_from_thing(buf);
                    162:                }
                    163:        }
                    164:        return this->ops->set_key(this->ops, key);
                    165: }
                    166: 
                    167: METHOD(prf_t, destroy, void,
                    168:        private_af_alg_prf_t *this)
                    169: {
                    170:        this->ops->destroy(this->ops);
                    171:        free(this);
                    172: }
                    173: 
                    174: /*
                    175:  * Described in header.
                    176:  */
                    177: af_alg_prf_t *af_alg_prf_create(pseudo_random_function_t algo)
                    178: {
                    179:        private_af_alg_prf_t *this;
                    180:        size_t block_size;
                    181:        bool xcbc;
                    182:        char *name;
                    183: 
                    184:        block_size = lookup_alg(algo, &name, &xcbc);
                    185:        if (!block_size)
                    186:        {       /* not supported by kernel */
                    187:                return NULL;
                    188:        }
                    189: 
                    190:        INIT(this,
                    191:                .public = {
                    192:                        .prf = {
                    193:                                .get_bytes = _get_bytes,
                    194:                                .allocate_bytes = _allocate_bytes,
                    195:                                .get_block_size = _get_block_size,
                    196:                                .get_key_size = _get_key_size,
                    197:                                .set_key = _set_key,
                    198:                                .destroy = _destroy,
                    199:                        },
                    200:                },
                    201:                .ops = af_alg_ops_create("hash", name),
                    202:                .block_size = block_size,
                    203:                .xcbc = xcbc,
                    204:        );
                    205:        if (!this->ops)
                    206:        {
                    207:                free(this);
                    208:                return NULL;
                    209:        }
                    210:        return &this->public;
                    211: }

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