[video_subr] Use memmove() for overlapping memory copy
[ipxe.git] / src / crypto / hmac_drbg.c
1 /*
2 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 *
23 * Alternatively, you may distribute this code in source or binary
24 * form, with or without modification, provided that the following
25 * conditions are met:
26 *
27 * 1. Redistributions of source code must retain the above copyright
28 * notice, this list of conditions and the above disclaimer.
29 *
30 * 2. Redistributions in binary form must reproduce the above
31 * copyright notice, this list of conditions and the above
32 * disclaimer in the documentation and/or other materials provided
33 * with the distribution.
34 */
35
36 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
37
38 /** @file
39 *
40 * HMAC_DRBG algorithm
41 *
42 * This algorithm is designed to comply with ANS X9.82 Part 3-2007
43 * Section 10.2.2.2. This standard is not freely available, but most
44 * of the text appears to be shared with NIST SP 800-90, which can be
45 * downloaded from
46 *
47 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
48 *
49 * Where possible, references are given to both documents. In the
50 * case of any disagreement, ANS X9.82 takes priority over NIST SP
51 * 800-90. (In particular, note that some algorithms that are
52 * Approved by NIST SP 800-90 are not Approved by ANS X9.82.)
53 */
54
55 #include <stdint.h>
56 #include <string.h>
57 #include <errno.h>
58 #include <assert.h>
59 #include <ipxe/crypto.h>
60 #include <ipxe/hmac.h>
61 #include <ipxe/hmac_drbg.h>
62
63 /**
64 * Update the HMAC_DRBG key
65 *
66 * @v hash Underlying hash algorithm
67 * @v state HMAC_DRBG internal state
68 * @v data Provided data
69 * @v len Length of provided data
70 * @v single Single byte used in concatenation
71 *
72 * This function carries out the operation
73 *
74 * K = HMAC ( K, V || single || provided_data )
75 *
76 * as used by hmac_drbg_update()
77 */
78 static void hmac_drbg_update_key ( struct digest_algorithm *hash,
79 struct hmac_drbg_state *state,
80 const void *data, size_t len,
81 const uint8_t single ) {
82 uint8_t context[ hash->ctxsize ];
83 size_t out_len = hash->digestsize;
84
85 DBGC ( state, "HMAC_DRBG_%s %p provided data :\n", hash->name, state );
86 DBGC_HDA ( state, 0, data, len );
87
88 /* Sanity checks */
89 assert ( hash != NULL );
90 assert ( state != NULL );
91 assert ( ( data != NULL ) || ( len == 0 ) );
92 assert ( ( single == 0x00 ) || ( single == 0x01 ) );
93
94 /* K = HMAC ( K, V || single || provided_data ) */
95 hmac_init ( hash, context, state->key, &out_len );
96 assert ( out_len == hash->digestsize );
97 hmac_update ( hash, context, state->value, out_len );
98 hmac_update ( hash, context, &single, sizeof ( single ) );
99 hmac_update ( hash, context, data, len );
100 hmac_final ( hash, context, state->key, &out_len, state->key );
101 assert ( out_len == hash->digestsize );
102
103 DBGC ( state, "HMAC_DRBG_%s %p K = HMAC ( K, V || %#02x || "
104 "provided_data ) :\n", hash->name, state, single );
105 DBGC_HDA ( state, 0, state->key, out_len );
106 }
107
108 /**
109 * Update the HMAC_DRBG value
110 *
111 * @v hash Underlying hash algorithm
112 * @v state HMAC_DRBG internal state
113 * @v data Provided data
114 * @v len Length of provided data
115 * @v single Single byte used in concatenation
116 *
117 * This function carries out the operation
118 *
119 * V = HMAC ( K, V )
120 *
121 * as used by hmac_drbg_update() and hmac_drbg_generate()
122 */
123 static void hmac_drbg_update_value ( struct digest_algorithm *hash,
124 struct hmac_drbg_state *state ) {
125 uint8_t context[ hash->ctxsize ];
126 size_t out_len = hash->digestsize;
127
128 /* Sanity checks */
129 assert ( hash != NULL );
130 assert ( state != NULL );
131
132 /* V = HMAC ( K, V ) */
133 hmac_init ( hash, context, state->key, &out_len );
134 assert ( out_len == hash->digestsize );
135 hmac_update ( hash, context, state->value, out_len );
136 hmac_final ( hash, context, state->key, &out_len, state->value );
137 assert ( out_len == hash->digestsize );
138
139 DBGC ( state, "HMAC_DRBG_%s %p V = HMAC ( K, V ) :\n",
140 hash->name, state );
141 DBGC_HDA ( state, 0, state->value, out_len );
142 }
143
144 /**
145 * Update HMAC_DRBG internal state
146 *
147 * @v hash Underlying hash algorithm
148 * @v state HMAC_DRBG internal state
149 * @v data Provided data
150 * @v len Length of provided data
151 *
152 * This is the HMAC_DRBG_Update function defined in ANS X9.82 Part
153 * 3-2007 Section 10.2.2.2.2 (NIST SP 800-90 Section 10.1.2.2).
154 *
155 * The key and value are updated in-place within the HMAC_DRBG
156 * internal state.
157 */
158 static void hmac_drbg_update ( struct digest_algorithm *hash,
159 struct hmac_drbg_state *state,
160 const void *data, size_t len ) {
161
162 DBGC ( state, "HMAC_DRBG_%s %p update\n", hash->name, state );
163
164 /* Sanity checks */
165 assert ( hash != NULL );
166 assert ( state != NULL );
167 assert ( ( data != NULL ) || ( len == 0 ) );
168
169 /* 1. K = HMAC ( K, V || 0x00 || provided_data ) */
170 hmac_drbg_update_key ( hash, state, data, len, 0x00 );
171
172 /* 2. V = HMAC ( K, V ) */
173 hmac_drbg_update_value ( hash, state );
174
175 /* 3. If ( provided_data = Null ), then return K and V */
176 if ( ! len )
177 return;
178
179 /* 4. K = HMAC ( K, V || 0x01 || provided_data ) */
180 hmac_drbg_update_key ( hash, state, data, len, 0x01 );
181
182 /* 5. V = HMAC ( K, V ) */
183 hmac_drbg_update_value ( hash, state );
184
185 /* 6. Return K and V */
186 }
187
188 /**
189 * Instantiate HMAC_DRBG
190 *
191 * @v hash Underlying hash algorithm
192 * @v state HMAC_DRBG internal state to be initialised
193 * @v entropy Entropy input
194 * @v entropy_len Length of entropy input
195 * @v personal Personalisation string
196 * @v personal_len Length of personalisation string
197 *
198 * This is the HMAC_DRBG_Instantiate_algorithm function defined in ANS
199 * X9.82 Part 3-2007 Section 10.2.2.2.3 (NIST SP 800-90 Section
200 * 10.1.2.3).
201 *
202 * The nonce must be included within the entropy input (i.e. the
203 * entropy input must contain at least 3/2 * security_strength bits of
204 * entropy, as per ANS X9.82 Part 3-2007 Section 8.4.2 (NIST SP 800-90
205 * Section 8.6.7).
206 *
207 * The key, value and reseed counter are updated in-place within the
208 * HMAC_DRBG internal state.
209 */
210 void hmac_drbg_instantiate ( struct digest_algorithm *hash,
211 struct hmac_drbg_state *state,
212 const void *entropy, size_t entropy_len,
213 const void *personal, size_t personal_len ){
214 size_t out_len = hash->digestsize;
215
216 DBGC ( state, "HMAC_DRBG_%s %p instantiate\n", hash->name, state );
217
218 /* Sanity checks */
219 assert ( hash != NULL );
220 assert ( state != NULL );
221 assert ( entropy != NULL );
222 assert ( ( personal != NULL ) || ( personal_len == 0 ) );
223
224 /* 1. seed_material = entropy_input || nonce ||
225 * personalisation_string
226 */
227
228 /* 2. Key = 0x00 00..00 */
229 memset ( state->key, 0x00, out_len );
230
231 /* 3. V = 0x01 01...01 */
232 memset ( state->value, 0x01, out_len );
233
234 /* 4. ( Key, V ) = HMAC_DBRG_Update ( seed_material, Key, V )
235 * 5. reseed_counter = 1
236 * 6. Return V, Key and reseed_counter as the
237 * initial_working_state
238 */
239 hmac_drbg_reseed ( hash, state, entropy, entropy_len,
240 personal, personal_len );
241 }
242
243 /**
244 * Reseed HMAC_DRBG
245 *
246 * @v hash Underlying hash algorithm
247 * @v state HMAC_DRBG internal state
248 * @v entropy Entropy input
249 * @v entropy_len Length of entropy input
250 * @v additional Additional input
251 * @v additional_len Length of additional input
252 *
253 * This is the HMAC_DRBG_Reseed_algorithm function defined in ANS X9.82
254 * Part 3-2007 Section 10.2.2.2.4 (NIST SP 800-90 Section 10.1.2.4).
255 *
256 * The key, value and reseed counter are updated in-place within the
257 * HMAC_DRBG internal state.
258 */
259 void hmac_drbg_reseed ( struct digest_algorithm *hash,
260 struct hmac_drbg_state *state,
261 const void *entropy, size_t entropy_len,
262 const void *additional, size_t additional_len ) {
263 uint8_t seed_material[ entropy_len + additional_len ];
264
265 DBGC ( state, "HMAC_DRBG_%s %p (re)seed\n", hash->name, state );
266
267 /* Sanity checks */
268 assert ( hash != NULL );
269 assert ( state != NULL );
270 assert ( entropy != NULL );
271 assert ( ( additional != NULL ) || ( additional_len == 0 ) );
272
273 /* 1. seed_material = entropy_input || additional_input */
274 memcpy ( seed_material, entropy, entropy_len );
275 memcpy ( ( seed_material + entropy_len ), additional, additional_len );
276 DBGC ( state, "HMAC_DRBG_%s %p seed material :\n", hash->name, state );
277 DBGC_HDA ( state, 0, seed_material, sizeof ( seed_material ) );
278
279 /* 2. ( Key, V ) = HMAC_DBRG_Update ( seed_material, Key, V ) */
280 hmac_drbg_update ( hash, state, seed_material,
281 sizeof ( seed_material ) );
282
283 /* 3. reseed_counter = 1 */
284 state->reseed_counter = 1;
285
286 /* 4. Return V, Key and reseed_counter as the new_working_state */
287 }
288
289 /**
290 * Generate pseudorandom bits using HMAC_DRBG
291 *
292 * @v hash Underlying hash algorithm
293 * @v state HMAC_DRBG internal state
294 * @v additional Additional input
295 * @v additional_len Length of additional input
296 * @v data Output buffer
297 * @v len Length of output buffer
298 * @ret rc Return status code
299 *
300 * This is the HMAC_DRBG_Generate_algorithm function defined in ANS X9.82
301 * Part 3-2007 Section 10.2.2.2.5 (NIST SP 800-90 Section 10.1.2.5).
302 *
303 * Requests must be for an integral number of bytes.
304 *
305 * The key, value and reseed counter are updated in-place within the
306 * HMAC_DRBG internal state.
307 *
308 * Note that the only permitted error is "reseed required".
309 */
310 int hmac_drbg_generate ( struct digest_algorithm *hash,
311 struct hmac_drbg_state *state,
312 const void *additional, size_t additional_len,
313 void *data, size_t len ) {
314 size_t out_len = hash->digestsize;
315 void *orig_data = data;
316 size_t orig_len = len;
317 size_t frag_len;
318
319 DBGC ( state, "HMAC_DRBG_%s %p generate\n", hash->name, state );
320
321 /* Sanity checks */
322 assert ( hash != NULL );
323 assert ( state != NULL );
324 assert ( data != NULL );
325 assert ( ( additional != NULL ) || ( additional_len == 0 ) );
326
327 /* 1. If reseed_counter > reseed_interval, then return an
328 * indication that a reseed is required
329 */
330 if ( state->reseed_counter > HMAC_DRBG_RESEED_INTERVAL ) {
331 DBGC ( state, "HMAC_DRBG_%s %p reseed interval exceeded\n",
332 hash->name, state );
333 return -ESTALE;
334 }
335
336 /* 2. If additional_input != Null, then
337 * ( Key, V ) = HMAC_DRBG_Update ( additional_input, Key, V )
338 */
339 if ( additional_len )
340 hmac_drbg_update ( hash, state, additional, additional_len );
341
342 /* 3. temp = Null
343 * 4. While ( len ( temp ) < requested_number_of_bits ) do:
344 */
345 while ( len ) {
346
347 /* 4.1 V = HMAC ( Key, V ) */
348 hmac_drbg_update_value ( hash, state );
349
350 /* 4.2. temp = temp || V
351 * 5. returned_bits = Leftmost requested_number_of_bits
352 * of temp
353 */
354 frag_len = len;
355 if ( frag_len > out_len )
356 frag_len = out_len;
357 memcpy ( data, state->value, frag_len );
358 data += frag_len;
359 len -= frag_len;
360 }
361
362 /* 6. ( Key, V ) = HMAC_DRBG_Update ( additional_input, Key, V ) */
363 hmac_drbg_update ( hash, state, additional, additional_len );
364
365 /* 7. reseed_counter = reseed_counter + 1 */
366 state->reseed_counter++;
367
368 DBGC ( state, "HMAC_DRBG_%s %p generated :\n", hash->name, state );
369 DBGC_HDA ( state, 0, orig_data, orig_len );
370
371 /* 8. Return SUCCESS, returned_bits, and the new values of
372 * Key, V and reseed_counter as the new_working_state
373 */
374 return 0;
375 }