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

1.1       misho       1: /*
                      2:  * Copyright (C) 2012 Tobias Brunner
                      3:  * Copyright (C) 2005-2006 Martin Willi
                      4:  * Copyright (C) 2005 Jan Hutter
                      5:  * HSR Hochschule fuer Technik Rapperswil
                      6:  *
                      7:  * This program is free software; you can redistribute it and/or modify it
                      8:  * under the terms of the GNU General Public License as published by the
                      9:  * Free Software Foundation; either version 2 of the License, or (at your
                     10:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     11:  *
                     12:  * This program is distributed in the hope that it will be useful, but
                     13:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     14:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     15:  * for more details.
                     16:  */
                     17: 
                     18: #include "hmac.h"
                     19: 
                     20: #include <crypto/mac.h>
                     21: #include <crypto/prfs/mac_prf.h>
                     22: #include <crypto/signers/mac_signer.h>
                     23: 
                     24: typedef struct private_mac_t private_mac_t;
                     25: 
                     26: /**
                     27:  * Private data of a mac_t object.
                     28:  *
                     29:  * The variable names are the same as in the RFC.
                     30:  */
                     31: struct private_mac_t {
                     32: 
                     33:        /**
                     34:         * Implements mac_t interface
                     35:         */
                     36:        mac_t public;
                     37: 
                     38:        /**
                     39:         * Block size, as in RFC.
                     40:         */
                     41:        uint8_t b;
                     42: 
                     43:        /**
                     44:         * Hash function.
                     45:         */
                     46:        hasher_t *h;
                     47: 
                     48:        /**
                     49:         * Previously xor'ed key using opad.
                     50:         */
                     51:        chunk_t opaded_key;
                     52: 
                     53:        /**
                     54:         * Previously xor'ed key using ipad.
                     55:         */
                     56:        chunk_t ipaded_key;
                     57: };
                     58: 
                     59: METHOD(mac_t, get_mac, bool,
                     60:        private_mac_t *this, chunk_t data, uint8_t *out)
                     61: {
                     62:        /* H(K XOR opad, H(K XOR ipad, text))
                     63:         *
                     64:         * if out is NULL, we append text to the inner hash.
                     65:         * else, we complete the inner and do the outer.
                     66:         *
                     67:         */
                     68: 
                     69:        uint8_t buffer[this->h->get_hash_size(this->h)];
                     70:        chunk_t inner;
                     71: 
                     72:        if (out == NULL)
                     73:        {
                     74:                /* append data to inner */
                     75:                return this->h->get_hash(this->h, data, NULL);
                     76:        }
                     77: 
                     78:        /* append and do outer hash */
                     79:        inner.ptr = buffer;
                     80:        inner.len = this->h->get_hash_size(this->h);
                     81: 
                     82:        /* complete inner, do outer and reinit for next call */
                     83:        return this->h->get_hash(this->h, data, buffer) &&
                     84:                   this->h->get_hash(this->h, this->opaded_key, NULL) &&
                     85:                   this->h->get_hash(this->h, inner, out) &&
                     86:                   this->h->get_hash(this->h, this->ipaded_key, NULL);
                     87: }
                     88: 
                     89: METHOD(mac_t, get_mac_size, size_t,
                     90:        private_mac_t *this)
                     91: {
                     92:        return this->h->get_hash_size(this->h);
                     93: }
                     94: 
                     95: METHOD(mac_t, set_key, bool,
                     96:        private_mac_t *this, chunk_t key)
                     97: {
                     98:        int i;
                     99:        uint8_t buffer[this->b];
                    100: 
                    101:        memset(buffer, 0, this->b);
                    102: 
                    103:        if (key.len > this->b)
                    104:        {
                    105:                /* if key is too long, it will be hashed */
                    106:                if (!this->h->reset(this->h) ||
                    107:                        !this->h->get_hash(this->h, key, buffer))
                    108:                {
                    109:                        return FALSE;
                    110:                }
                    111:        }
                    112:        else
                    113:        {
                    114:                /* if not, just copy it in our pre-padded k */
                    115:                memcpy(buffer, key.ptr, key.len);
                    116:        }
                    117: 
                    118:        /* apply ipad and opad to key */
                    119:        for (i = 0; i < this->b; i++)
                    120:        {
                    121:                this->ipaded_key.ptr[i] = buffer[i] ^ 0x36;
                    122:                this->opaded_key.ptr[i] = buffer[i] ^ 0x5C;
                    123:        }
                    124: 
                    125:        /* begin hashing of inner pad */
                    126:        return this->h->reset(this->h) &&
                    127:                   this->h->get_hash(this->h, this->ipaded_key, NULL);
                    128: }
                    129: 
                    130: METHOD(mac_t, destroy, void,
                    131:        private_mac_t *this)
                    132: {
                    133:        this->h->destroy(this->h);
                    134:        chunk_clear(&this->opaded_key);
                    135:        chunk_clear(&this->ipaded_key);
                    136:        free(this);
                    137: }
                    138: 
                    139: /*
                    140:  * Creates an mac_t object
                    141:  */
                    142: static mac_t *hmac_create(hash_algorithm_t hash_algorithm)
                    143: {
                    144:        private_mac_t *this;
                    145: 
                    146:        INIT(this,
                    147:                .public = {
                    148:                        .get_mac = _get_mac,
                    149:                        .get_mac_size = _get_mac_size,
                    150:                        .set_key = _set_key,
                    151:                        .destroy = _destroy,
                    152:                },
                    153:        );
                    154: 
                    155:        /* set b, according to hasher */
                    156:        switch (hash_algorithm)
                    157:        {
                    158:                case HASH_SHA1:
                    159:                case HASH_MD5:
                    160:                case HASH_SHA256:
                    161:                        this->b = 64;
                    162:                        break;
                    163:                case HASH_SHA384:
                    164:                case HASH_SHA512:
                    165:                        this->b = 128;
                    166:                        break;
                    167:                default:
                    168:                        free(this);
                    169:                        return NULL;
                    170:        }
                    171: 
                    172:        this->h = lib->crypto->create_hasher(lib->crypto, hash_algorithm);
                    173:        if (this->h == NULL)
                    174:        {
                    175:                free(this);
                    176:                return NULL;
                    177:        }
                    178: 
                    179:        /* build ipad and opad */
                    180:        this->opaded_key.ptr = malloc(this->b);
                    181:        this->opaded_key.len = this->b;
                    182: 
                    183:        this->ipaded_key.ptr = malloc(this->b);
                    184:        this->ipaded_key.len = this->b;
                    185: 
                    186:        return &this->public;
                    187: }
                    188: 
                    189: /*
                    190:  * Described in header
                    191:  */
                    192: prf_t *hmac_prf_create(pseudo_random_function_t algo)
                    193: {
                    194:        mac_t *hmac;
                    195: 
                    196:        hmac = hmac_create(hasher_algorithm_from_prf(algo));
                    197:        if (hmac)
                    198:        {
                    199:                return mac_prf_create(hmac);
                    200:        }
                    201:        return NULL;
                    202: }
                    203: 
                    204: /*
                    205:  * Described in header
                    206:  */
                    207: signer_t *hmac_signer_create(integrity_algorithm_t algo)
                    208: {
                    209:        mac_t *hmac;
                    210:        size_t trunc;
                    211: 
                    212:        hmac = hmac_create(hasher_algorithm_from_integrity(algo, &trunc));
                    213:        if (hmac)
                    214:        {
                    215:                return mac_signer_create(hmac, trunc);
                    216:        }
                    217:        return NULL;
                    218: }

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