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

1.1       misho       1: /*
                      2:  * Copyright (C) 2006 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 "fips_prf.h"
                     17: 
                     18: #include <utils/debug.h>
                     19: 
                     20: typedef struct private_fips_prf_t private_fips_prf_t;
                     21: 
                     22: /**
                     23:  * Private data of a fips_prf_t object.
                     24:  */
                     25: struct private_fips_prf_t {
                     26:        /**
                     27:         * Public fips_prf_t interface.
                     28:         */
                     29:        fips_prf_t public;
                     30: 
                     31:        /**
                     32:         * key of prf function, "b" long
                     33:         */
                     34:        uint8_t *key;
                     35: 
                     36:        /**
                     37:         * size of "b" in bytes
                     38:         */
                     39:        size_t b;
                     40: 
                     41:        /**
                     42:         * Keyed SHA1 prf: It does not use SHA1Final operation
                     43:         */
                     44:        prf_t *keyed_prf;
                     45: 
                     46:        /**
                     47:         * G function, either SHA1 or DES
                     48:         */
                     49:        bool (*g)(private_fips_prf_t *this, chunk_t c, uint8_t res[]);
                     50: };
                     51: 
                     52: /**
                     53:  * sum = (a + b) mod 2 ^ (length * 8)
                     54:  */
                     55: static void add_mod(size_t length, uint8_t a[], uint8_t b[], uint8_t sum[])
                     56: {
                     57:        int i, c = 0;
                     58: 
                     59:        for(i = length - 1; i >= 0; i--)
                     60:        {
                     61:                uint32_t tmp;
                     62: 
                     63:                tmp = a[i] + b[i] + c;
                     64:                sum[i] = 0xff & tmp;
                     65:                c = tmp >> 8;
                     66:        }
                     67: }
                     68: 
                     69: /**
                     70:  * calculate "chunk mod 2^(length*8)" and save it into buffer
                     71:  */
                     72: static void chunk_mod(size_t length, chunk_t chunk, uint8_t buffer[])
                     73: {
                     74:        if (chunk.len < length)
                     75:        {
                     76:                /* apply seed as least significant bits, others are zero */
                     77:                memset(buffer, 0, length - chunk.len);
                     78:                memcpy(buffer + length - chunk.len, chunk.ptr, chunk.len);
                     79:        }
                     80:        else
                     81:        {
                     82:                /* use least significant bytes from seed, as we use mod 2^b */
                     83:                memcpy(buffer, chunk.ptr + chunk.len - length, length);
                     84:        }
                     85: }
                     86: 
                     87: /**
                     88:  * Implementation of prf_t.get_bytes.
                     89:  *
                     90:  * Test vector:
                     91:  *
                     92:  * key:
                     93:  * 0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b,
                     94:  * 0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f,
                     95:  * 0xeb, 0x5a, 0x38, 0xb6
                     96:  *
                     97:  * seed:
                     98:  * 0x00
                     99:  *
                    100:  * result:
                    101:  * 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f,
                    102:  * 0xde, 0x1c, 0x0f, 0xfc, 0x7b, 0x2e, 0x3b, 0x49,
                    103:  * 0x8b, 0x26, 0x06, 0x14, 0x3c, 0x6c, 0x18, 0xba,
                    104:  * 0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78,
                    105:  * 0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16
                    106:  */
                    107: METHOD(prf_t, get_bytes, bool,
                    108:        private_fips_prf_t *this, chunk_t seed, uint8_t w[])
                    109: {
                    110:        int i;
                    111:        uint8_t xval[this->b];
                    112:        uint8_t xseed[this->b];
                    113:        uint8_t sum[this->b];
                    114:        uint8_t *xkey = this->key;
                    115:        uint8_t one[this->b];
                    116: 
                    117:        if (!w)
                    118:        {
                    119:                /* append mode is not supported */
                    120:                return FALSE;
                    121:        }
                    122: 
                    123:        memset(one, 0, this->b);
                    124:        one[this->b - 1] = 0x01;
                    125: 
                    126:        /* 3.1 */
                    127:        chunk_mod(this->b, seed, xseed);
                    128: 
                    129:        /* 3.2 */
                    130:        for (i = 0; i < 2; i++) /* twice */
                    131:        {
                    132:                /* a. XVAL = (XKEY + XSEED j) mod 2^b */
                    133:                add_mod(this->b, xkey, xseed, xval);
                    134:                DBG3(DBG_LIB, "XVAL %b", xval, (u_int)this->b);
                    135:                /* b. wi = G(t, XVAL ) */
                    136:                this->g(this, chunk_create(xval, this->b), &w[i * this->b]);
                    137:                DBG3(DBG_LIB, "w[%d] %b", i, &w[i * this->b], (u_int)this->b);
                    138:                /* c. XKEY = (1 + XKEY + wi) mod 2b */
                    139:                add_mod(this->b, xkey, &w[i * this->b], sum);
                    140:                add_mod(this->b, sum, one, xkey);
                    141:                DBG3(DBG_LIB, "XKEY %b", xkey, (u_int)this->b);
                    142:        }
                    143: 
                    144:        /* 3.3 done already, mod q not used */
                    145: 
                    146:        return TRUE;
                    147: }
                    148: 
                    149: METHOD(prf_t, get_block_size, size_t,
                    150:        private_fips_prf_t *this)
                    151: {
                    152:        return 2 * this->b;
                    153: }
                    154: METHOD(prf_t, allocate_bytes, bool,
                    155:        private_fips_prf_t *this, chunk_t seed, chunk_t *chunk)
                    156: {
                    157:        *chunk = chunk_alloc(get_block_size(this));
                    158:        return get_bytes(this, seed, chunk->ptr);
                    159: }
                    160: 
                    161: METHOD(prf_t, get_key_size, size_t,
                    162:        private_fips_prf_t *this)
                    163: {
                    164:        return this->b;
                    165: }
                    166: 
                    167: METHOD(prf_t, set_key, bool,
                    168:        private_fips_prf_t *this, chunk_t key)
                    169: {
                    170:        /* save key as "key mod 2^b" */
                    171:        chunk_mod(this->b, key, this->key);
                    172:        return TRUE;
                    173: }
                    174: 
                    175: /**
                    176:  * Implementation of the G() function based on SHA1
                    177:  */
                    178: static bool g_sha1(private_fips_prf_t *this, chunk_t c, uint8_t res[])
                    179: {
                    180:        uint8_t buf[64];
                    181: 
                    182:        if (c.len < sizeof(buf))
                    183:        {
                    184:                /* pad c with zeros */
                    185:                memset(buf, 0, sizeof(buf));
                    186:                memcpy(buf, c.ptr, c.len);
                    187:                c.ptr = buf;
                    188:                c.len = sizeof(buf);
                    189:        }
                    190:        else
                    191:        {
                    192:                /* not more than 512 bits can be G()-ed */
                    193:                c.len = sizeof(buf);
                    194:        }
                    195: 
                    196:        /* use the keyed hasher, but use an empty key to use SHA1 IV */
                    197:        if (!this->keyed_prf->set_key(this->keyed_prf, chunk_empty) ||
                    198:                !this->keyed_prf->get_bytes(this->keyed_prf, c, res))
                    199:        {
                    200:                return FALSE;
                    201:        }
                    202:        return TRUE;
                    203: }
                    204: 
                    205: METHOD(prf_t, destroy, void,
                    206:        private_fips_prf_t *this)
                    207: {
                    208:        this->keyed_prf->destroy(this->keyed_prf);
                    209:        free(this->key);
                    210:        free(this);
                    211: }
                    212: 
                    213: /*
                    214:  * Described in header.
                    215:  */
                    216: fips_prf_t *fips_prf_create(pseudo_random_function_t algo)
                    217: {
                    218:        private_fips_prf_t *this;
                    219: 
                    220:        INIT(this,
                    221:                .public = {
                    222:                        .prf_interface = {
                    223:                                .get_bytes = _get_bytes,
                    224:                                .allocate_bytes = _allocate_bytes,
                    225:                                .get_block_size = _get_block_size,
                    226:                                .get_key_size = _get_key_size,
                    227:                                .set_key = _set_key,
                    228:                                .destroy = _destroy,
                    229:                        },
                    230:                },
                    231:        );
                    232: 
                    233:        switch (algo)
                    234:        {
                    235:                case PRF_FIPS_SHA1_160:
                    236:                {
                    237:                        this->g = g_sha1;
                    238:                        this->b = 20;
                    239:                        this->keyed_prf = lib->crypto->create_prf(lib->crypto, PRF_KEYED_SHA1);
                    240:                        if (this->keyed_prf == NULL)
                    241:                        {
                    242:                                free(this);
                    243:                                return NULL;
                    244:                        }
                    245:                        break;
                    246:                }
                    247:                case PRF_FIPS_DES:
                    248:                        /* not implemented yet */
                    249:                default:
                    250:                        free(this);
                    251:                        return NULL;
                    252:        }
                    253:        this->key = malloc(this->b);
                    254: 
                    255:        return &this->public;
                    256: }

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