Return to fips_prf.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / fips_prf |
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: }