瀏覽代碼

[rng] Add ANS X9.82 Approved HMAC_DRBG algorithm

ANS X9.82 specifies several Approved algorithms for use in a
Deterministic Random Bit Generator (DRBG).  One such algorithm is
HMAC_DRBG, which can be implemented using the existing iPXE SHA-1 and
HMAC functionality.  This algorithm provides a maximum security
strength of 128 bits.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 年之前
父節點
當前提交
5c2d6fa399
共有 3 個文件被更改,包括 496 次插入0 次删除
  1. 342
    0
      src/crypto/hmac_drbg.c
  2. 1
    0
      src/include/ipxe/errfile.h
  3. 153
    0
      src/include/ipxe/hmac_drbg.h

+ 342
- 0
src/crypto/hmac_drbg.c 查看文件

@@ -0,0 +1,342 @@
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., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+/** @file
22
+ *
23
+ * HMAC_DRBG algorithm
24
+ *
25
+ * This algorithm is designed to comply with ANS X9.82 Part 3-2007
26
+ * Section 10.2.2.2.  This standard is not freely available, but most
27
+ * of the text appears to be shared with NIST SP 800-90, which can be
28
+ * downloaded from
29
+ *
30
+ *     http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
31
+ *
32
+ * Where possible, references are given to both documents.  In the
33
+ * case of any disagreement, ANS X9.82 takes priority over NIST SP
34
+ * 800-90.  (In particular, note that some algorithms that are
35
+ * Approved by NIST SP 800-90 are not Approved by ANS X9.82.)
36
+ */
37
+
38
+#include <stdint.h>
39
+#include <errno.h>
40
+#include <ipxe/crypto.h>
41
+#include <ipxe/hmac.h>
42
+#include <ipxe/hmac_drbg.h>
43
+
44
+/**
45
+ * Update the HMAC_DRBG key
46
+ *
47
+ * @v state		HMAC_DRBG internal state
48
+ * @v data		Provided data
49
+ * @v len		Length of provided data
50
+ * @v single		Single byte used in concatenation
51
+ *
52
+ * This function carries out the operation
53
+ *
54
+ *     K = HMAC ( K, V || single || provided_data )
55
+ *
56
+ * as used by hmac_drbg_update()
57
+ */
58
+static void hmac_drbg_update_key ( struct hmac_drbg_state *state,
59
+				   const void *data, size_t len,
60
+				   const uint8_t single ) {
61
+	uint8_t context[HMAC_DRBG_CTX_SIZE];
62
+	size_t key_len = sizeof ( state->key );
63
+
64
+	DBGC ( state, "HMAC_DRBG %p provided data :\n", state );
65
+	DBGC_HDA ( state, 0, data, len );
66
+
67
+	/* Sanity checks */
68
+	assert ( state != NULL );
69
+	assert ( ( data != NULL ) || ( len == 0 ) );
70
+	assert ( ( single == 0x00 ) || ( single == 0x01 ) );
71
+
72
+	/* K = HMAC ( K, V || single || provided_data ) */
73
+	hmac_init ( &hmac_drbg_algorithm, context, state->key, &key_len );
74
+	assert ( key_len == sizeof ( state->key ) );
75
+	hmac_update ( &hmac_drbg_algorithm, context,
76
+		      state->value, sizeof ( state->value ) );
77
+	hmac_update ( &hmac_drbg_algorithm, context,
78
+		      &single, sizeof ( single ) );
79
+	hmac_update ( &hmac_drbg_algorithm, context, data, len );
80
+	hmac_final ( &hmac_drbg_algorithm, context, state->key, &key_len,
81
+		     state->key );
82
+	assert ( key_len == sizeof ( state->key ) );
83
+
84
+	DBGC ( state, "HMAC_DRBG %p K = HMAC ( K, V || %#02x || "
85
+	       "provided_data ) :\n", state, single );
86
+	DBGC_HDA ( state, 0, state->key, sizeof ( state->key ) );
87
+}
88
+
89
+/**
90
+ * Update the HMAC_DRBG value
91
+ *
92
+ * @v state		HMAC_DRBG internal state
93
+ * @v data		Provided data
94
+ * @v len		Length of provided data
95
+ * @v single		Single byte used in concatenation
96
+ *
97
+ * This function carries out the operation
98
+ *
99
+ *     V = HMAC ( K, V )
100
+ *
101
+ * as used by hmac_drbg_update() and hmac_drbg_generate()
102
+ */
103
+static void hmac_drbg_update_value ( struct hmac_drbg_state *state ) {
104
+	uint8_t context[HMAC_DRBG_CTX_SIZE];
105
+	size_t key_len = sizeof ( state->key );
106
+
107
+	/* Sanity checks */
108
+	assert ( state != NULL );
109
+
110
+	/* V = HMAC ( K, V ) */
111
+	hmac_init ( &hmac_drbg_algorithm, context, state->key, &key_len );
112
+	assert ( key_len == sizeof ( state->key ) );
113
+	hmac_update ( &hmac_drbg_algorithm, context,
114
+		      state->value, sizeof ( state->value ) );
115
+	hmac_final ( &hmac_drbg_algorithm, context, state->key, &key_len,
116
+		     state->value );
117
+	assert ( key_len == sizeof ( state->key ) );
118
+
119
+	DBGC ( state, "HMAC_DRBG %p V = HMAC ( K, V ) :\n", state );
120
+	DBGC_HDA ( state, 0, state->value, sizeof ( state->value ) );
121
+}
122
+
123
+/**
124
+ * Update HMAC_DRBG internal state
125
+ *
126
+ * @v state		HMAC_DRBG internal state
127
+ * @v data		Provided data
128
+ * @v len		Length of provided data
129
+ *
130
+ * This is the HMAC_DRBG_Update function defined in ANS X9.82 Part
131
+ * 3-2007 Section 10.2.2.2.2 (NIST SP 800-90 Section 10.1.2.2).
132
+ *
133
+ * The key and value are updated in-place within the HMAC_DRBG
134
+ * internal state.
135
+ */
136
+static void hmac_drbg_update ( struct hmac_drbg_state *state,
137
+			       const void *data, size_t len ) {
138
+
139
+	DBGC ( state, "HMAC_DRBG %p update\n", state );
140
+
141
+	/* Sanity checks */
142
+	assert ( state != NULL );
143
+	assert ( ( data != NULL ) || ( len == 0 ) );
144
+
145
+	/* 1.  K = HMAC ( K, V || 0x00 || provided_data ) */
146
+	hmac_drbg_update_key ( state, data, len, 0x00 );
147
+
148
+	/* 2.  V = HMAC ( K, V ) */
149
+	hmac_drbg_update_value ( state );
150
+
151
+	/* 3.  If ( provided_data = Null ), then return K and V */
152
+	if ( ! len )
153
+		return;
154
+
155
+	/* 4.  K = HMAC ( K, V || 0x01 || provided_data ) */
156
+	hmac_drbg_update_key ( state, data, len, 0x01 );
157
+
158
+	/* 5.  V = HMAC ( K, V ) */
159
+	hmac_drbg_update_value ( state );
160
+
161
+	/* 6.  Return K and V */
162
+}
163
+
164
+/**
165
+ * Instantiate HMAC_DRBG
166
+ *
167
+ * @v state		HMAC_DRBG internal state to be initialised
168
+ * @v entropy		Entropy input
169
+ * @v entropy_len	Length of entropy input
170
+ * @v personal		Personalisation string
171
+ * @v personal_len	Length of personalisation string
172
+ *
173
+ * This is the HMAC_DRBG_Instantiate_algorithm function defined in ANS
174
+ * X9.82 Part 3-2007 Section 10.2.2.2.3 (NIST SP 800-90 Section
175
+ * 10.1.2.3).
176
+ *
177
+ * The nonce must be included within the entropy input (i.e. the
178
+ * entropy input must contain at least 3/2 * security_strength bits of
179
+ * entropy, as per ANS X9.82 Part 3-2007 Section 8.4.2 (NIST SP 800-90
180
+ * Section 8.6.7).
181
+ *
182
+ * The key, value and reseed counter are updated in-place within the
183
+ * HMAC_DRBG internal state.
184
+ */
185
+void hmac_drbg_instantiate ( struct hmac_drbg_state *state,
186
+			     const void *entropy, size_t entropy_len,
187
+			     const void *personal, size_t personal_len ){
188
+
189
+	DBGC ( state, "HMAC_DRBG %p instantiate\n", state );
190
+
191
+	/* Sanity checks */
192
+	assert ( state != NULL );
193
+	assert ( entropy != NULL );
194
+	assert ( ( 8 * entropy_len ) >=
195
+		 ( 3 * HMAC_DRBG_SECURITY_STRENGTH / 2 ) );
196
+	assert ( ( personal != NULL ) || ( personal_len == 0 ) );
197
+
198
+	/* 1.  seed_material = entropy_input || nonce ||
199
+	 *     personalisation_string
200
+	 */
201
+
202
+	/* 2.  Key = 0x00 00..00 */
203
+	memset ( state->key, 0x00, sizeof ( state->key ) );
204
+
205
+	/* 3.  V = 0x01 01...01 */
206
+	memset ( state->value, 0x01, sizeof ( state->value ) );
207
+
208
+	/* 4.  ( Key, V ) = HMAC_DBRG_Update ( seed_material, Key, V )
209
+	 * 5.  reseed_counter = 1
210
+	 * 6.  Return V, Key and reseed_counter as the
211
+	 *     initial_working_state
212
+	 */
213
+	hmac_drbg_reseed ( state, entropy, entropy_len,
214
+			   personal, personal_len );
215
+}
216
+
217
+/**
218
+ * Reseed HMAC_DRBG
219
+ *
220
+ * @v state		HMAC_DRBG internal state
221
+ * @v entropy		Entropy input
222
+ * @v entropy_len	Length of entropy input
223
+ * @v additional	Additional input
224
+ * @v additional_len	Length of additional input
225
+ *
226
+ * This is the HMAC_DRBG_Reseed_algorithm function defined in ANS X9.82
227
+ * Part 3-2007 Section 10.2.2.2.4 (NIST SP 800-90 Section 10.1.2.4).
228
+ *
229
+ * The key, value and reseed counter are updated in-place within the
230
+ * HMAC_DRBG internal state.
231
+ */
232
+void hmac_drbg_reseed ( struct hmac_drbg_state *state,
233
+			const void *entropy, size_t entropy_len,
234
+			const void *additional, size_t additional_len ) {
235
+	uint8_t seed_material[ entropy_len + additional_len ];
236
+
237
+	DBGC ( state, "HMAC_DRBG %p (re)seed\n", state );
238
+
239
+	/* Sanity checks */
240
+	assert ( state != NULL );
241
+	assert ( entropy != NULL );
242
+	assert ( ( 8 * entropy_len ) >= HMAC_DRBG_SECURITY_STRENGTH );
243
+	assert ( ( additional != NULL ) || ( additional_len == 0 ) );
244
+
245
+	/* 1.  seed_material = entropy_input || additional_input */
246
+	memcpy ( seed_material, entropy, entropy_len );
247
+	memcpy ( ( seed_material + entropy_len ), additional, additional_len );
248
+	DBGC ( state, "HMAC_DRBG %p seed material :\n", state );
249
+	DBGC_HDA ( state, 0, seed_material, sizeof ( seed_material ) );
250
+
251
+	/* 2.  ( Key, V ) = HMAC_DBRG_Update ( seed_material, Key, V ) */
252
+	hmac_drbg_update ( state, seed_material, sizeof ( seed_material ) );
253
+
254
+	/* 3.  reseed_counter = 1 */
255
+	state->reseed_counter = 1;
256
+
257
+	/* 4.  Return V, Key and reseed_counter as the new_working_state */
258
+}
259
+
260
+/**
261
+ * Generate pseudorandom bits using HMAC_DRBG
262
+ *
263
+ * @v state		HMAC_DRBG internal state
264
+ * @v additional	Additional input
265
+ * @v additional_len	Length of additional input
266
+ * @v data		Output buffer
267
+ * @v len		Length of output buffer
268
+ * @ret rc		Return status code
269
+ *
270
+ * This is the HMAC_DRBG_Generate_algorithm function defined in ANS X9.82
271
+ * Part 3-2007 Section 10.2.2.2.5 (NIST SP 800-90 Section 10.1.2.5).
272
+ *
273
+ * Requests must be for an integral number of bytes.
274
+ *
275
+ * The key, value and reseed counter are updated in-place within the
276
+ * HMAC_DRBG internal state.
277
+ *
278
+ * Note that the only permitted error is "reseed required".
279
+ */
280
+int hmac_drbg_generate ( struct hmac_drbg_state *state,
281
+			 const void *additional, size_t additional_len,
282
+			 void *data, size_t len ) {
283
+	void *orig_data = data;
284
+	size_t orig_len = len;
285
+	size_t frag_len;
286
+
287
+	DBGC ( state, "HMAC_DRBG %p generate\n", state );
288
+
289
+	/* Sanity checks */
290
+	assert ( state != NULL );
291
+	assert ( data != NULL );
292
+	assert ( ( additional != NULL ) || ( additional_len == 0 ) );
293
+
294
+	/* 1.  If reseed_counter > reseed_interval, then return an
295
+	 *     indication that a reseed is required
296
+	 */
297
+	if ( state->reseed_counter > HMAC_DRBG_RESEED_INTERVAL ) {
298
+		DBGC ( state, "HMAC_DRBG %p reseed interval exceeded\n",
299
+		       state );
300
+		return -ESTALE;
301
+	}
302
+
303
+	/* 2.  If additional_input != Null, then
304
+	 *     ( Key, V ) = HMAC_DRBG_Update ( additional_input, Key, V )
305
+	 */
306
+	if ( additional_len )
307
+		hmac_drbg_update ( state, additional, additional_len );
308
+
309
+	/* 3.  temp = Null
310
+	 * 4.  While ( len ( temp ) < requested_number_of_bits ) do:
311
+	 */
312
+	while ( len ) {
313
+
314
+		/* 4.1  V = HMAC ( Key, V ) */
315
+		hmac_drbg_update_value ( state );
316
+
317
+		/* 4.2.  temp = temp || V
318
+		 * 5.    returned_bits = Leftmost requested_number_of_bits
319
+		 *       of temp
320
+		 */
321
+		frag_len = len;
322
+		if ( frag_len > sizeof ( state->value ) )
323
+			frag_len = sizeof ( state->value );
324
+		memcpy ( data, state->value, frag_len );
325
+		data += frag_len;
326
+		len -= frag_len;
327
+	}
328
+
329
+	/* 6.  ( Key, V ) = HMAC_DRBG_Update ( additional_input, Key, V ) */
330
+	hmac_drbg_update ( state, additional, additional_len );
331
+
332
+	/* 7.  reseed_counter = reseed_counter + 1 */
333
+	state->reseed_counter++;
334
+
335
+	DBGC ( state, "HMAC_DRBG %p generated :\n", state );
336
+	DBGC_HDA ( state, 0, orig_data, orig_len );
337
+
338
+	/* 8.  Return SUCCESS, returned_bits, and the new values of
339
+	 *     Key, V and reseed_counter as the new_working_state
340
+	 */
341
+	return 0;
342
+}

+ 1
- 0
src/include/ipxe/errfile.h 查看文件

@@ -242,6 +242,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
242 242
 #define ERRFILE_bofm		      ( ERRFILE_OTHER | 0x00210000 )
243 243
 #define ERRFILE_prompt		      ( ERRFILE_OTHER | 0x00220000 )
244 244
 #define ERRFILE_nvo_cmd		      ( ERRFILE_OTHER | 0x00230000 )
245
+#define ERRFILE_hmac_drbg	      ( ERRFILE_OTHER | 0x00240000 )
245 246
 
246 247
 /** @} */
247 248
 

+ 153
- 0
src/include/ipxe/hmac_drbg.h 查看文件

@@ -0,0 +1,153 @@
1
+#ifndef _IPXE_HMAC_DRBG_H
2
+#define _IPXE_HMAC_DRBG_H
3
+
4
+/** @file
5
+ *
6
+ * HMAC_DRBG algorithm
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+#include <stdint.h>
13
+#include <ipxe/sha1.h>
14
+
15
+/** Use SHA-1 as the underlying hash algorithm
16
+ *
17
+ * HMAC_DRBG using SHA-1 is an Approved algorithm in ANS X9.82.
18
+ */
19
+#define hmac_drbg_algorithm sha1_algorithm
20
+
21
+/** Maximum security strength
22
+ *
23
+ * The maximum security strength of HMAC_DRBG using SHA-1 is 128 bits
24
+ * (according to the list of maximum security strengths documented in
25
+ * NIST SP 800-57 Part 1 Section 5.6.1 Table 3).
26
+ */
27
+#define HMAC_DRBG_MAX_SECURITY_STRENGTH 128
28
+
29
+/** Security strength
30
+ *
31
+ * For the sake of implementation simplicity, only a single security
32
+ * strength is supported, which is the maximum security strength
33
+ * supported by the algorithm.
34
+ */
35
+#define HMAC_DRBG_SECURITY_STRENGTH HMAC_DRBG_MAX_SECURITY_STRENGTH
36
+
37
+/** Underlying hash algorithm output length (in bytes) */
38
+#define HMAC_DRBG_OUTLEN_BYTES SHA1_DIGEST_SIZE
39
+
40
+/** Required minimum entropy for instantiate and reseed
41
+ *
42
+ * The minimum required entropy for HMAC_DRBG is equal to the security
43
+ * strength according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 2
44
+ * (NIST SP 800-90 Section 10.1 Table 2).
45
+ */
46
+#define HMAC_DRBG_MIN_ENTROPY_BYTES ( HMAC_DRBG_SECURITY_STRENGTH / 8 )
47
+
48
+/** Minimum entropy input length
49
+ *
50
+ * The minimum entropy input length for HMAC_DRBG is equal to the
51
+ * security strength according to ANS X9.82 Part 3-2007 Section 10.2.1
52
+ * Table 2 (NIST SP 800-90 Section 10.1 Table 2).
53
+ */
54
+#define HMAC_DRBG_MIN_ENTROPY_LEN_BYTES ( HMAC_DRBG_SECURITY_STRENGTH / 8 )
55
+
56
+/** Maximum entropy input length
57
+ *
58
+ * The maximum entropy input length for HMAC_DRBG is 2^35 bits
59
+ * according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 2 (NIST SP
60
+ * 800-90 Section 10.1 Table 2).
61
+ *
62
+ * We choose to allow up to 2^32-1 bytes (i.e. 2^35-8 bits).
63
+ */
64
+#define HMAC_DRBG_MAX_ENTROPY_LEN_BYTES 0xffffffffUL
65
+
66
+/** Maximum personalisation string length
67
+ *
68
+ * The maximum permitted personalisation string length for HMAC_DRBG
69
+ * is 2^35 bits according to ANS X9.82 Part 3-2007 Section 10.2.1
70
+ * Table 1 (NIST SP 800-90 Section 10.1 Table 2).
71
+ *
72
+ * We choose to allow up to 2^32-1 bytes (i.e. 2^35-8 bits).
73
+ */
74
+#define HMAC_DRBG_MAX_PERSONAL_LEN_BYTES 0xffffffffUL
75
+
76
+/** Maximum additional input length
77
+ *
78
+ * The maximum permitted additional input length for HMAC_DRBG is 2^35
79
+ * bits according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 1
80
+ * (NIST SP 800-90 Section 10.1 Table 2).
81
+ *
82
+ * We choose to allow up to 2^32-1 bytes (i.e. 2^35-8 bits).
83
+ */
84
+#define HMAC_DRBG_MAX_ADDITIONAL_LEN_BYTES 0xffffffffUL
85
+
86
+/** Maximum length of generated pseudorandom data per request
87
+ *
88
+ * The maximum number of bits per request for HMAC_DRBG is 2^19 bits
89
+ * according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 1 (NIST SP
90
+ * 800-90 Section 10.1 Table 2).
91
+ *
92
+ * We choose to allow up to 2^16-1 bytes (i.e. 2^19-8 bits).
93
+ */
94
+#define HMAC_DRBG_MAX_GENERATED_LEN_BYTES 0x0000ffffUL
95
+
96
+/** Reseed interval
97
+ *
98
+ * The maximum permitted reseed interval for HMAC_DRBG using SHA-1 is
99
+ * 2^48 according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 2
100
+ * (NIST SP 800-90 Section 10.1 Table 2).  However, the sample
101
+ * implementation given in ANS X9.82 Part 3-2007 Annex E.2.1 (NIST SP
102
+ * 800-90 Appendix F.2) shows a reseed interval of 10000.
103
+ *
104
+ * We choose a very conservative reseed interval.
105
+ */
106
+#define HMAC_DRBG_RESEED_INTERVAL 1024
107
+
108
+/** Underlying hash algorithm context size (in bytes) */
109
+#define HMAC_DRBG_CTX_SIZE SHA1_CTX_SIZE
110
+
111
+/**
112
+ * HMAC_DRBG internal state
113
+ *
114
+ * This structure is defined by ANS X9.82 Part 3-2007 Section
115
+ * 10.2.2.2.1 (NIST SP 800-90 Section 10.1.2.1).
116
+ *
117
+ * The "administrative information" portions (security_strength and
118
+ * prediction_resistance) are design-time constants and so are not
119
+ * present as fields in this structure.
120
+ */
121
+struct hmac_drbg_state {
122
+	/** Current value
123
+	 *
124
+	 * "The value V of outlen bits, which is updated each time
125
+	 * another outlen bits of output are produced"
126
+	 */
127
+	uint8_t value[HMAC_DRBG_OUTLEN_BYTES];
128
+	/** Current key
129
+	 *
130
+	 * "The outlen-bit Key, which is updated at least once each
131
+	 * time that the DRBG mechanism generates pseudorandom bits."
132
+	 */
133
+	uint8_t key[HMAC_DRBG_OUTLEN_BYTES];
134
+	/** Reseed counter
135
+	 *
136
+	 * "A counter (reseed_counter) that indicates the number of
137
+	 * requests for pseudorandom bits since instantiation or
138
+	 * reseeding"
139
+	 */
140
+	unsigned int reseed_counter;
141
+};
142
+
143
+extern void hmac_drbg_instantiate ( struct hmac_drbg_state *state,
144
+				    const void *entropy, size_t entropy_len,
145
+				    const void *personal, size_t personal_len );
146
+extern void hmac_drbg_reseed ( struct hmac_drbg_state *state,
147
+			       const void *entropy, size_t entropy_len,
148
+			       const void *additional, size_t additional_len );
149
+extern int hmac_drbg_generate ( struct hmac_drbg_state *state,
150
+				const void *additional, size_t additional_len,
151
+				void *data, size_t len );
152
+
153
+#endif /* _IPXE_HMAC_DRBG_H */

Loading…
取消
儲存