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>