Annotation of embedaddon/strongswan/src/libstrongswan/plugins/fips_prf/fips_prf.c, revision 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>