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>