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

1.1       misho       1: /*
                      2:  * Copyright (C) 2013-2016 Andreas Steffen
                      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 "mgf1_xof.h"
                     17: 
                     18: #include "crypto/hashers/hasher.h"
                     19: #include "utils/debug.h"
                     20: 
                     21: typedef struct private_mgf1_xof_t private_mgf1_xof_t;
                     22: 
                     23: /**
                     24:  * Private data of an mgf1_xof_t object.
                     25:  */
                     26: struct private_mgf1_xof_t {
                     27: 
                     28:        /**
                     29:         * Public mgf1_xof_t interface.
                     30:         */
                     31:        mgf1_xof_t public;
                     32: 
                     33:        /**
                     34:         * XOF type of the MGF1 Mask Generation Function
                     35:         */
                     36:        ext_out_function_t type;
                     37: 
                     38:        /**
                     39:         * Hasher the MGF1 Mask Generation Function is based on
                     40:         */
                     41:        hasher_t *hasher;
                     42: 
                     43:        /**
                     44:         * Is the seed hashed before using it as a seed for MGF1 ?
                     45:         */
                     46:        bool hash_seed;
                     47: 
                     48:        /**
                     49:         * Counter
                     50:         */
                     51:        uint32_t counter;
                     52: 
                     53:        /**
                     54:         * Set if counter has reached 2^32
                     55:         */
                     56:        bool overflow;
                     57: 
                     58:        /**
                     59:         * Current state to be hashed
                     60:         */
                     61:        chunk_t state;
                     62: 
                     63:        /**
                     64:         * Position of the 4 octet counter string
                     65:         */
                     66:        uint8_t *ctr_str;
                     67: 
                     68:        /**
                     69:         * Latest hash block
                     70:         */
                     71:        uint8_t buf[HASH_SIZE_SHA512];
                     72: 
                     73:        /**
                     74:         * Index pointing to the current position in the hash block
                     75:         */
                     76:        size_t buf_index;
                     77: 
                     78: };
                     79: 
                     80: METHOD(xof_t, get_type, ext_out_function_t,
                     81:        private_mgf1_xof_t *this)
                     82: {
                     83:        return this->type;
                     84: }
                     85: 
                     86: static bool get_next_block(private_mgf1_xof_t *this, uint8_t *buffer)
                     87: {
                     88:        /* detect overflow, set counter string and increment counter */
                     89:        if (this->overflow)
                     90:        {
                     91:                DBG1(DBG_LIB, "MGF1 overflow occurred");
                     92:                return FALSE;
                     93:        }
                     94:        htoun32(this->ctr_str, this->counter++);
                     95:        if (this->counter == 0)
                     96:        {
                     97:                this->overflow = TRUE;
                     98:        }
                     99: 
                    100:        /* get the next block from the hash function */
                    101:        if (!this->hasher->get_hash(this->hasher, this->state, buffer))
                    102:        {
                    103:                return FALSE;
                    104:        }
                    105: 
                    106:        return TRUE;
                    107: }
                    108: 
                    109: METHOD(xof_t, get_bytes, bool,
                    110:        private_mgf1_xof_t *this, size_t out_len, uint8_t *buffer)
                    111: {
                    112:        size_t index = 0, blocks, len, hash_size;
                    113: 
                    114:        hash_size = this->hasher->get_hash_size(this->hasher);
                    115: 
                    116:        /* empty the current hash block buffer first */
                    117:        len = min(out_len, hash_size - this->buf_index);
                    118:        if (len)
                    119:        {
                    120:                memcpy(buffer, this->buf + this->buf_index, len);
                    121:                index += len;
                    122:                this->buf_index += len;
                    123:        }
                    124: 
                    125:        /* copy whole hash blocks directly to output buffer */
                    126:        blocks = (out_len - index) / hash_size;
                    127:        while (blocks--)
                    128:        {
                    129:                if (!get_next_block(this, buffer + index))
                    130:                {
                    131:                        return FALSE;
                    132:                }
                    133:                index += hash_size;
                    134:        }
                    135: 
                    136:        /* get another hash block if some more output bytes are needed */
                    137:        len = out_len - index;
                    138:        if (len)
                    139:        {
                    140:                if (!get_next_block(this, this->buf))
                    141:                {
                    142:                        return FALSE;
                    143:                }
                    144:                memcpy(buffer + index, this->buf, len);
                    145:                this->buf_index = len;
                    146:        }
                    147: 
                    148:        return TRUE;
                    149: }
                    150: 
                    151: METHOD(xof_t, allocate_bytes, bool,
                    152:        private_mgf1_xof_t *this, size_t out_len, chunk_t *chunk)
                    153: {
                    154:        *chunk = chunk_alloc(out_len);
                    155: 
                    156:        if (!get_bytes(this, out_len, chunk->ptr))
                    157:        {
                    158:                chunk_free(chunk);
                    159:                return FALSE;
                    160:        }
                    161: 
                    162:        return TRUE;
                    163: }
                    164: 
                    165: METHOD(xof_t, get_block_size, size_t,
                    166:        private_mgf1_xof_t *this)
                    167: {
                    168:        return this->hasher->get_hash_size(this->hasher);
                    169: }
                    170: 
                    171: METHOD(xof_t, get_seed_size, size_t,
                    172:        private_mgf1_xof_t *this)
                    173: {
                    174:        return this->hasher->get_hash_size(this->hasher);
                    175: }
                    176: 
                    177: METHOD(xof_t, set_seed, bool,
                    178:        private_mgf1_xof_t *this, chunk_t seed)
                    179: {
                    180:        size_t hash_size, state_len;
                    181: 
                    182:        if (seed.len == 0)
                    183:        {
                    184:                DBG1(DBG_LIB, "empty seed for MGF1");
                    185:                return FALSE;
                    186:        }
                    187: 
                    188:        /* determine state size and allocate space accordingly */
                    189:        hash_size = this->hasher->get_hash_size(this->hasher);
                    190:        state_len = (this->hash_seed ? hash_size : seed.len) + 4;
                    191:        chunk_clear(&this->state);
                    192:        this->state = chunk_alloc(state_len);
                    193: 
                    194:        /* hash block buffer is empty */
                    195:        this->buf_index = hash_size;
                    196: 
                    197:        /* reset counter */
                    198:        this->counter = 0;
                    199: 
                    200:        /* determine position of the 4 octet counter string */
                    201:        this->ctr_str = this->state.ptr + state_len - 4;
                    202: 
                    203:        if (this->hash_seed)
                    204:        {
                    205:                if (!this->hasher->get_hash(this->hasher, seed, this->state.ptr))
                    206:                {
                    207:                        DBG1(DBG_LIB, "failed to hash seed for MGF1");
                    208:                        return FALSE;
                    209:                }
                    210:        }
                    211:        else
                    212:        {
                    213:                memcpy(this->state.ptr, seed.ptr, seed.len);
                    214:        }
                    215: 
                    216:        return TRUE;
                    217: }
                    218: 
                    219: METHOD(xof_t, destroy, void,
                    220:        private_mgf1_xof_t *this)
                    221: {
                    222:        this->hasher->destroy(this->hasher);
                    223:        chunk_clear(&this->state);
                    224:        free(this);
                    225: }
                    226: 
                    227: METHOD(mgf1_t, set_hash_seed, void,
                    228:        private_mgf1_xof_t *this, bool yes)
                    229: {
                    230:        this->hash_seed = yes;
                    231: }
                    232: 
                    233: /*
                    234:  * Described in header.
                    235:  */
                    236: mgf1_xof_t *mgf1_xof_create(ext_out_function_t algorithm)
                    237: {
                    238:        private_mgf1_xof_t *this;
                    239:        hash_algorithm_t hash_alg;
                    240:        hasher_t *hasher;
                    241: 
                    242:        switch (algorithm)
                    243:        {
                    244:                case XOF_MGF1_SHA1:
                    245:                        hash_alg = HASH_SHA1;
                    246:                        break;
                    247:                case XOF_MGF1_SHA224:
                    248:                        hash_alg = HASH_SHA224;
                    249:                        break;
                    250:                case XOF_MGF1_SHA256:
                    251:                        hash_alg = HASH_SHA256;
                    252:                        break;
                    253:                case XOF_MGF1_SHA384:
                    254:                        hash_alg = HASH_SHA384;
                    255:                        break;
                    256:                case XOF_MGF1_SHA512:
                    257:                        hash_alg = HASH_SHA512;
                    258:                        break;
                    259:                default:
                    260:                        return NULL;
                    261:        }
                    262: 
                    263:        hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
                    264:        if (!hasher)
                    265:        {
                    266:                DBG1(DBG_LIB, "failed to create %N hasher for MGF1",
                    267:                         hash_algorithm_names, hash_alg);
                    268:                return NULL;
                    269:        }
                    270: 
                    271:        INIT(this,
                    272:                .public = {
                    273:                        .mgf1_interface = {
                    274:                                .xof_interface = {
                    275:                                        .get_type = _get_type,
                    276:                                        .get_bytes = _get_bytes,
                    277:                                        .allocate_bytes = _allocate_bytes,
                    278:                                        .get_block_size = _get_block_size,
                    279:                                        .get_seed_size = _get_seed_size,
                    280:                                        .set_seed = _set_seed,
                    281:                                        .destroy = _destroy,
                    282:                                },
                    283:                                .set_hash_seed = _set_hash_seed,
                    284:                        },
                    285:                },
                    286:                .type = algorithm,
                    287:                .hasher = hasher,
                    288:        );
                    289: 
                    290:        return &this->public;
                    291: }

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