fixed carry bug in FIPS prf
[strongswan.git] / src / libstrongswan / crypto / prfs / fips_prf.c
1 /**
2 * @file fips_prf.c
3 *
4 * @brief Implementation for fips_prf_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include "fips_prf.h"
24
25 #include <arpa/inet.h>
26
27 #include <debug.h>
28
29 typedef struct private_fips_prf_t private_fips_prf_t;
30
31 /**
32 * Private data of a fips_prf_t object.
33 */
34 struct private_fips_prf_t {
35 /**
36 * Public fips_prf_t interface.
37 */
38 fips_prf_t public;
39
40 /**
41 * key of prf function, "b" long
42 */
43 u_int8_t *key;
44
45 /**
46 * size of "b" in bytes
47 */
48 size_t b;
49
50 /**
51 * G function, either SHA1 or DES
52 */
53 void (*g)(u_int8_t t[], chunk_t c, u_int8_t res[]);
54 };
55
56 /**
57 * t used in G(), equals to initial SHA1 value
58 */
59 static u_int8_t t[] = {
60 0x67,0x45,0x23,0x01,0xEF,0xCD,0xAB,0x89,0x98,0xBA,
61 0xDC,0xFE,0x10,0x32,0x54,0x76,0xC3,0xD2,0xE1,0xF0,
62 };
63
64 /**
65 * sum = (a + b) mod 2 ^ (length * 8)
66 */
67 static void add_mod(size_t length, u_int8_t a[], u_int8_t b[], u_int8_t sum[])
68 {
69 int i, c = 0;
70
71 for(i = length - 1; i >= 0; i--)
72 {
73 u_int32_t tmp;
74
75 tmp = a[i] + b[i] + c;
76 sum[i] = 0xff & tmp;
77 c = tmp >> 8;
78 }
79 }
80
81 /**
82 * calculate "chunk mod 2^(length*8)" and save it into buffer
83 */
84 static void chunk_mod(size_t length, chunk_t chunk, u_int8_t buffer[])
85 {
86 if (chunk.len < length)
87 {
88 /* apply seed as least significant bits, others are zero */
89 memset(buffer, 0, length - chunk.len);
90 memcpy(buffer + length - chunk.len, chunk.ptr, chunk.len);
91 }
92 else
93 {
94 /* use least significant bytes from seed, as we use mod 2^b */
95 memcpy(buffer, chunk.ptr + chunk.len - length, length);
96 }
97 }
98
99 /**
100 * Implementation of prf_t.get_bytes.
101 *
102 * Test vector:
103 *
104 * key:
105 * 0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b,
106 * 0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f,
107 * 0xeb, 0x5a, 0x38, 0xb6
108 *
109 * seed:
110 * 0x00
111 *
112 * result:
113 * 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f,
114 * 0xde, 0x1c, 0x0f, 0xfc, 0x7b, 0x2e, 0x3b, 0x49,
115 * 0x8b, 0x26, 0x06, 0x14, 0x3c, 0x6c, 0x18, 0xba,
116 * 0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78,
117 * 0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16
118 */
119 static void get_bytes(private_fips_prf_t *this, chunk_t seed, u_int8_t w[])
120 {
121 int i;
122 u_int8_t xval[this->b];
123 u_int8_t xseed[this->b];
124 u_int8_t sum[this->b];
125 u_int8_t *xkey = this->key;
126 u_int8_t one[this->b];
127 chunk_t xval_chunk = chunk_from_buf(xval);
128
129 memset(one, 0, this->b);
130 one[this->b - 1] = 0x01;
131
132 /* 3.1 */
133 chunk_mod(this->b, seed, xseed);
134
135 /* 3.2 */
136 for (i = 0; i < 2; i++) /* twice */
137 {
138 /* a. XVAL = (XKEY + XSEED j) mod 2^b */
139 add_mod(this->b, xkey, xseed, xval);
140 DBG3("XVAL %b", xval, this->b);
141 /* b. wi = G(t, XVAL ) */
142 this->g(t, xval_chunk, &w[i * this->b]);
143 DBG3("w[%d] %b", i, &w[i * this->b], this->b);
144 /* c. XKEY = (1 + XKEY + wi) mod 2b */
145 add_mod(this->b, xkey, &w[i * this->b], sum);
146 add_mod(this->b, sum, one, xkey);
147 DBG3("XKEY %b", xkey, this->b);
148 }
149
150 /* 3.3 done already, mod q not used */
151 }
152
153 /**
154 * Implementation of prf_t.get_block_size.
155 */
156 static size_t get_block_size(private_fips_prf_t *this)
157 {
158 return 2 * this->b;
159 }
160 /**
161 * Implementation of prf_t.allocate_bytes.
162 */
163 static void allocate_bytes(private_fips_prf_t *this, chunk_t seed, chunk_t *chunk)
164 {
165 *chunk = chunk_alloc(get_block_size(this));
166 get_bytes(this, seed, chunk->ptr);
167 }
168
169 /**
170 * Implementation of prf_t.get_key_size.
171 */
172 static size_t get_key_size(private_fips_prf_t *this)
173 {
174 return this->b;
175 }
176
177 /**
178 * Implementation of prf_t.set_key.
179 */
180 static void set_key(private_fips_prf_t *this, chunk_t key)
181 {
182 /* save key as "key mod 2^b" */
183 chunk_mod(this->b, key, this->key);
184 }
185
186 /**
187 * Implementation of the G() function based on SHA1
188 */
189 void g_sha1(u_int8_t t[], chunk_t c, u_int8_t res[])
190 {
191 hasher_t *hasher;
192 u_int8_t buf[64];
193 chunk_t state_chunk;
194 u_int32_t *state, *iv, *hash;
195
196 if (c.len < sizeof(buf))
197 {
198 /* pad c with zeros */
199 memset(buf, 0, sizeof(buf));
200 memcpy(buf, c.ptr, c.len);
201 c.ptr = buf;
202 c.len = sizeof(buf);
203 }
204 else
205 {
206 /* not more than 512 bits can be G()-ed */
207 c.len = sizeof(buf);
208 }
209
210 /* our SHA1 hasher's state is 32-Bit integers in host order. We must
211 * convert them */
212 hasher = hasher_create(HASH_SHA1);
213 state_chunk = hasher->get_state(hasher);
214 state = (u_int32_t*)state_chunk.ptr;
215 iv = (u_int32_t*)t;
216 hash = (u_int32_t*)res;
217 state[0] = htonl(iv[0]);
218 state[1] = htonl(iv[1]);
219 state[2] = htonl(iv[2]);
220 state[3] = htonl(iv[3]);
221 hasher->get_hash(hasher, c, NULL);
222 hash[0] = htonl(state[0]);
223 hash[1] = htonl(state[1]);
224 hash[2] = htonl(state[2]);
225 hash[3] = htonl(state[3]);
226 hash[4] = htonl(state[4]);
227 hasher->destroy(hasher);
228 }
229
230 /**
231 * Implementation of prf_t.destroy.
232 */
233 static void destroy(private_fips_prf_t *this)
234 {
235 free(this->key);
236 free(this);
237 }
238
239 /*
240 * Described in header.
241 */
242 fips_prf_t *fips_prf_create(size_t b, void(*g)(u_int8_t[],chunk_t,u_int8_t[]))
243 {
244 private_fips_prf_t *this = malloc_thing(private_fips_prf_t);
245
246 this->public.prf_interface.get_bytes = (void (*) (prf_t *,chunk_t,u_int8_t*))get_bytes;
247 this->public.prf_interface.allocate_bytes = (void (*) (prf_t*,chunk_t,chunk_t*))allocate_bytes;
248 this->public.prf_interface.get_block_size = (size_t (*) (prf_t*))get_block_size;
249 this->public.prf_interface.get_key_size = (size_t (*) (prf_t*))get_key_size;
250 this->public.prf_interface.set_key = (void (*) (prf_t *,chunk_t))set_key;
251 this->public.prf_interface.destroy = (void (*) (prf_t *))destroy;
252
253 this->g = g;
254 this->b = b;
255 this->key = malloc(b);
256
257 return &(this->public);
258 }