~ubuntu-branches/ubuntu/raring/ipxe/raring

« back to all changes in this revision

Viewing changes to src/crypto/drbg.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-11-14 15:47:31 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20121114154731-jhuy5d1h2jw75qe9
Tags: 1.0.0+git-4.d6b0b76-0ubuntu1
* New upstream snapshot:
  - d/p/iscsi*.patch: Dropped - included in snapshot.
  - Refreshed all other patches.
* d/p/enable-https.patch: Enable HTTPS support (LP: #1025239).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
20
FILE_LICENCE ( GPL2_OR_LATER );
 
21
 
 
22
/** @file
 
23
 *
 
24
 * DRBG mechanism
 
25
 *
 
26
 * This mechanism is designed to comply with ANS X9.82 Part 3-2007
 
27
 * Section 9.  This standard is not freely available, but most of the
 
28
 * text appears to be shared with NIST SP 800-90, which can be
 
29
 * downloaded from
 
30
 *
 
31
 *     http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
 
32
 *
 
33
 * Where possible, references are given to both documents.  In the
 
34
 * case of any disagreement, ANS X9.82 takes priority over NIST SP
 
35
 * 800-90.  (In particular, note that some algorithms that are
 
36
 * Approved by NIST SP 800-90 are not Approved by ANS X9.82.)
 
37
 */
 
38
 
 
39
#include <stdint.h>
 
40
#include <string.h>
 
41
#include <errno.h>
 
42
#include <assert.h>
 
43
#include <ipxe/entropy.h>
 
44
#include <ipxe/drbg.h>
 
45
 
 
46
/**
 
47
 * Instantiate DRBG
 
48
 *
 
49
 * @v state             Algorithm state to be initialised
 
50
 * @v personal          Personalisation string
 
51
 * @v personal_len      Length of personalisation string
 
52
 * @ret rc              Return status code
 
53
 *
 
54
 * This is the Instantiate_function defined in ANS X9.82 Part 3-2007
 
55
 * Section 9.2 (NIST SP 800-90 Section 9.1).
 
56
 *
 
57
 * Only a single security strength is supported, and prediction
 
58
 * resistance is always enabled.  The nonce is accounted for by
 
59
 * increasing the entropy input, as per ANS X9.82 Part 3-2007 Section
 
60
 * 8.4.2 (NIST SP 800-90 Section 8.6.7).
 
61
 */
 
62
int drbg_instantiate ( struct drbg_state *state, const void *personal,
 
63
                       size_t personal_len ) {
 
64
        unsigned int entropy_bits = ( ( 3 * DRBG_SECURITY_STRENGTH + 1 ) / 2 );
 
65
        size_t min_len = DRBG_MIN_ENTROPY_LEN_BYTES;
 
66
        size_t max_len = DRBG_MAX_ENTROPY_LEN_BYTES;
 
67
        uint8_t data[max_len];
 
68
        int len;
 
69
        int rc;
 
70
 
 
71
        DBGC ( state, "DRBG %p instantiate\n", state );
 
72
 
 
73
        /* Sanity checks */
 
74
        assert ( state != NULL );
 
75
 
 
76
        /* 1.  If requested_instantiation_security_strength >
 
77
         *     highest_supported_security_strength, then return an
 
78
         *     ERROR_FLAG
 
79
         */
 
80
        if ( DRBG_SECURITY_STRENGTH > DRBG_MAX_SECURITY_STRENGTH ) {
 
81
                DBGC ( state, "DRBG %p cannot support security strength %d\n",
 
82
                       state, DRBG_SECURITY_STRENGTH );
 
83
                return -ENOTSUP;
 
84
        }
 
85
 
 
86
        /* 2.  If prediction_resistance_flag is set, and prediction
 
87
         *     resistance is not supported, then return an ERROR_FLAG
 
88
         *
 
89
         * (Nothing to do since prediction resistance is always
 
90
         * supported.)
 
91
         */
 
92
 
 
93
        /* 3.  If the length of the personalization_string >
 
94
         *     max_personalization_string_length, return an ERROR_FLAG
 
95
         */
 
96
        if ( personal_len > DRBG_MAX_PERSONAL_LEN_BYTES ) {
 
97
                DBGC ( state, "DRBG %p personalisation string too long (%zd "
 
98
                       "bytes)\n", state, personal_len );
 
99
                return -ERANGE;
 
100
        }
 
101
 
 
102
        /* 4.  Set security_strength to the nearest security strength
 
103
         *     greater than or equal to
 
104
         *     requested_instantiation_security_strength.
 
105
         *
 
106
         * (Nothing to do since we support only a single security
 
107
         * strength.)
 
108
         */
 
109
 
 
110
        /* 5.  Using the security_strength, select appropriate DRBG
 
111
         *     mechanism parameters.
 
112
         *
 
113
         * (Nothing to do since we support only a single security
 
114
         * strength.)
 
115
         */
 
116
 
 
117
        /* 6.  ( status, entropy_input ) = Get_entropy_input (
 
118
         *     security_strength, min_length, max_length,
 
119
         *     prediction_resistance_request )
 
120
         * 7.  If an ERROR is returned in step 6, return a
 
121
         *     CATASTROPHIC_ERROR_FLAG.
 
122
         * 8.  Obtain a nonce.
 
123
         */
 
124
        len = get_entropy_input ( entropy_bits, data, min_len,
 
125
                                  sizeof ( data ) );
 
126
        if ( len < 0 ) {
 
127
                rc = len;
 
128
                DBGC ( state, "DRBG %p could not get entropy input: %s\n",
 
129
                       state, strerror ( rc ) );
 
130
                return rc;
 
131
        }
 
132
        assert ( len >= ( int ) min_len );
 
133
        assert ( len <= ( int ) sizeof ( data ) );
 
134
 
 
135
        /* 9.  initial_working_state = Instantiate_algorithm (
 
136
         *     entropy_input, nonce, personalization_string ).
 
137
         */
 
138
        drbg_instantiate_algorithm ( state, data, len, personal, personal_len );
 
139
 
 
140
        /* 10.  Get a state_handle for a currently empty state.  If an
 
141
         *      empty internal state cannot be found, return an
 
142
         *      ERROR_FLAG.
 
143
         * 11.  Set the internal state indicated by state_handle to
 
144
         *      the initial values for the internal state (i.e. set
 
145
         *      the working_state to the values returned as
 
146
         *      initial_working_state in step 9 and any other values
 
147
         *      required for the working_state, and set the
 
148
         *      administrative information to the appropriate values.
 
149
         *
 
150
         * (Almost nothing to do since the memory to hold the state
 
151
         * was passed in by the caller and has already been updated
 
152
         * in-situ.)
 
153
         */
 
154
        state->reseed_required = 0;
 
155
        state->valid = 1;
 
156
 
 
157
        /* 12.  Return SUCCESS and state_handle. */
 
158
        return 0;
 
159
}
 
160
 
 
161
/**
 
162
 * Reseed DRBG
 
163
 *
 
164
 * @v state             Algorithm state
 
165
 * @v additional        Additional input
 
166
 * @v additional_len    Length of additional input
 
167
 * @ret rc              Return status code
 
168
 *
 
169
 * This is the Reseed_function defined in ANS X9.82 Part 3-2007
 
170
 * Section 9.3 (NIST SP 800-90 Section 9.2).
 
171
 *
 
172
 * Prediction resistance is always enabled.
 
173
 */
 
174
int drbg_reseed ( struct drbg_state *state, const void *additional,
 
175
                  size_t additional_len ) {
 
176
        unsigned int entropy_bits = DRBG_SECURITY_STRENGTH;
 
177
        size_t min_len = DRBG_MIN_ENTROPY_LEN_BYTES;
 
178
        size_t max_len = DRBG_MAX_ENTROPY_LEN_BYTES;
 
179
        uint8_t data[max_len];
 
180
        int len;
 
181
        int rc;
 
182
 
 
183
        DBGC ( state, "DRBG %p reseed\n", state );
 
184
 
 
185
        /* Sanity checks */
 
186
        assert ( state != NULL );
 
187
 
 
188
        /* 1.  Using state_handle, obtain the current internal state.
 
189
         *     If state_handle indicates an invalid or empty internal
 
190
         *     state, return an ERROR_FLAG.
 
191
         *
 
192
         * (Almost nothing to do since the memory holding the internal
 
193
         * state was passed in by the caller.)
 
194
         */
 
195
        if ( ! state->valid ) {
 
196
                DBGC ( state, "DRBG %p not valid\n", state );
 
197
                return -EINVAL;
 
198
        }
 
199
 
 
200
        /* 2.  If prediction_resistance_request is set, and
 
201
         *     prediction_resistance_flag is not set, then return an
 
202
         *     ERROR_FLAG.
 
203
         *
 
204
         * (Nothing to do since prediction resistance is always
 
205
         * supported.)
 
206
         */
 
207
 
 
208
        /* 3.  If the length of the additional_input >
 
209
         *     max_additional_input_length, return an ERROR_FLAG.
 
210
         */
 
211
        if ( additional_len > DRBG_MAX_ADDITIONAL_LEN_BYTES ) {
 
212
                DBGC ( state, "DRBG %p additional input too long (%zd bytes)\n",
 
213
                       state, additional_len );
 
214
                return -ERANGE;
 
215
        }
 
216
 
 
217
        /* 4.  ( status, entropy_input ) = Get_entropy_input (
 
218
         *     security_strength, min_length, max_length,
 
219
         *     prediction_resistance_request ).
 
220
         *
 
221
         * 5.  If an ERROR is returned in step 4, return a
 
222
         *     CATASTROPHIC_ERROR_FLAG.
 
223
         */
 
224
        len = get_entropy_input ( entropy_bits, data, min_len,
 
225
                                  sizeof ( data ) );
 
226
        if ( len < 0 ) {
 
227
                rc = len;
 
228
                DBGC ( state, "DRBG %p could not get entropy input: %s\n",
 
229
                       state, strerror ( rc ) );
 
230
                return rc;
 
231
        }
 
232
 
 
233
        /* 6.  new_working_state = Reseed_algorithm ( working_state,
 
234
         *     entropy_input, additional_input ).
 
235
         */
 
236
        drbg_reseed_algorithm ( state, data, len, additional, additional_len );
 
237
 
 
238
        /* 7.  Replace the working_state in the internal state
 
239
         *     indicated by state_handle with the values of
 
240
         *     new_working_state obtained in step 6.
 
241
         *
 
242
         * (Nothing to do since the state has already been updated in-situ.)
 
243
         */
 
244
 
 
245
        /* 8.  Return SUCCESS. */
 
246
        return 0;
 
247
}
 
248
 
 
249
/**
 
250
 * Generate pseudorandom bits using DRBG
 
251
 *
 
252
 * @v state             Algorithm state
 
253
 * @v additional        Additional input
 
254
 * @v additional_len    Length of additional input
 
255
 * @v prediction_resist Prediction resistance is required
 
256
 * @v data              Output buffer
 
257
 * @v len               Length of output buffer
 
258
 * @ret rc              Return status code
 
259
 *
 
260
 * This is the Generate_function defined in ANS X9.82 Part 3-2007
 
261
 * Section 9.4 (NIST SP 800-90 Section 9.3).
 
262
 *
 
263
 * Requests must be for an integral number of bytes.  Only a single
 
264
 * security strength is supported.  Prediction resistance is supported
 
265
 * if requested.
 
266
 */
 
267
int drbg_generate ( struct drbg_state *state, const void *additional,
 
268
                    size_t additional_len, int prediction_resist,
 
269
                    void *data, size_t len ) {
 
270
        int rc;
 
271
 
 
272
        DBGC ( state, "DRBG %p generate\n", state );
 
273
 
 
274
        /* Sanity checks */
 
275
        assert ( state != NULL );
 
276
        assert ( data != NULL );
 
277
 
 
278
        /* 1.  Using state_handle, obtain the current internal state
 
279
         *     for the instantiation.  If state_handle indicates an
 
280
         *     invalid or empty internal state, then return an ERROR_FLAG.
 
281
         *
 
282
         * (Almost nothing to do since the memory holding the internal
 
283
         * state was passed in by the caller.)
 
284
         */
 
285
        if ( ! state->valid ) {
 
286
                DBGC ( state, "DRBG %p not valid\n", state );
 
287
                return -EINVAL;
 
288
        }
 
289
 
 
290
        /* 2.  If requested_number_of_bits >
 
291
         *     max_number_of_bits_per_request, then return an
 
292
         *     ERROR_FLAG.
 
293
         */
 
294
        if ( len > DRBG_MAX_GENERATED_LEN_BYTES ) {
 
295
                DBGC ( state, "DRBG %p request too long (%zd bytes)\n",
 
296
                       state, len );
 
297
                return -ERANGE;
 
298
        }
 
299
 
 
300
        /* 3.  If requested_security_strength > the security_strength
 
301
         *     indicated in the internal state, then return an
 
302
         *     ERROR_FLAG.
 
303
         *
 
304
         * (Nothing to do since only a single security strength is
 
305
         * supported.)
 
306
         */
 
307
 
 
308
        /* 4.  If the length of the additional_input >
 
309
         *     max_additional_input_length, then return an ERROR_FLAG.
 
310
         */
 
311
        if ( additional_len > DRBG_MAX_ADDITIONAL_LEN_BYTES ) {
 
312
                DBGC ( state, "DRBG %p additional input too long (%zd bytes)\n",
 
313
                       state, additional_len );
 
314
                return -ERANGE;
 
315
        }
 
316
 
 
317
        /* 5.  If prediction_resistance_request is set, and
 
318
         *     prediction_resistance_flag is not set, then return an
 
319
         *     ERROR_FLAG.
 
320
         *
 
321
         * (Nothing to do since prediction resistance is always
 
322
         * supported.)
 
323
         */
 
324
 
 
325
        /* 6.  Clear the reseed_required_flag. */
 
326
        state->reseed_required = 0;
 
327
 
 
328
 step_7:
 
329
        /* 7.  If reseed_required_flag is set, or if
 
330
         *     prediction_resistance_request is set, then
 
331
         */
 
332
        if ( state->reseed_required || prediction_resist ) {
 
333
 
 
334
                /* 7.1  status = Reseed_function ( state_handle,
 
335
                 *      prediction_resistance_request,
 
336
                 *      additional_input )
 
337
                 * 7.2  If status indicates an ERROR, then return
 
338
                 *      status.
 
339
                 */
 
340
                if ( ( rc = drbg_reseed ( state, additional,
 
341
                                          additional_len ) ) != 0 ) {
 
342
                        DBGC ( state, "DRBG %p could not reseed: %s\n",
 
343
                               state, strerror ( rc ) );
 
344
                        return rc;
 
345
                }
 
346
 
 
347
                /* 7.3  Using state_handle, obtain the new internal
 
348
                 *      state.
 
349
                 *
 
350
                 * (Nothing to do since the internal state has been
 
351
                 * updated in-situ.)
 
352
                 */
 
353
 
 
354
                /* 7.4  additional_input = the Null string. */
 
355
                additional = NULL;
 
356
                additional_len = 0;
 
357
 
 
358
                /* 7.5  Clear the reseed_required_flag. */
 
359
                state->reseed_required = 0;
 
360
        }
 
361
 
 
362
        /* 8.  ( status, pseudorandom_bits, new_working_state ) =
 
363
         *     Generate_algorithm ( working_state,
 
364
         *     requested_number_of_bits, additional_input ).
 
365
         */
 
366
        rc = drbg_generate_algorithm ( state, additional, additional_len,
 
367
                                       data, len );
 
368
 
 
369
        /* 9.  If status indicates that a reseed is required before
 
370
         *     the requested bits can be generated, then
 
371
         */
 
372
        if ( rc != 0 ) {
 
373
 
 
374
                /* 9.1  Set the reseed_required_flag. */
 
375
                state->reseed_required = 1;
 
376
 
 
377
                /* 9.2  If the prediction_resistance_flag is set, then
 
378
                 *      set the prediction_resistance_request
 
379
                 *      indication.
 
380
                 */
 
381
                prediction_resist = 1;
 
382
 
 
383
                /* 9.3  Go to step 7. */
 
384
                goto step_7;
 
385
        }
 
386
 
 
387
        /* 10.  Replace the old working_state in the internal state
 
388
         *      indicated by state_handle with the values of
 
389
         *      new_working_state.
 
390
         *
 
391
         * (Nothing to do since the working state has already been
 
392
         * updated in-situ.)
 
393
         */
 
394
 
 
395
        /* 11.  Return SUCCESS and pseudorandom_bits. */
 
396
        return 0;
 
397
}
 
398
 
 
399
/**
 
400
 * Uninstantiate DRBG
 
401
 *
 
402
 * @v state             Algorithm state
 
403
 *
 
404
 * This is the Uninstantiate_function defined in ANS X9.82 Part 3-2007
 
405
 * Section 9.5 (NIST SP 800-90 Section 9.4).
 
406
 */
 
407
void drbg_uninstantiate ( struct drbg_state *state ) {
 
408
 
 
409
        DBGC ( state, "DRBG %p uninstantiate\n", state );
 
410
 
 
411
        /* Sanity checks */
 
412
        assert ( state != NULL );
 
413
 
 
414
        /* 1.  If state_handle indicates an invalid state, then return
 
415
         *     an ERROR_FLAG.
 
416
         *
 
417
         * (Nothing to do since the memory holding the internal state
 
418
         * was passed in by the caller.)
 
419
         */
 
420
 
 
421
        /* 2.  Erase the contents of the internal state indicated by
 
422
         *     state_handle.
 
423
         */
 
424
        memset ( state, 0, sizeof ( *state ) );
 
425
 
 
426
        /* 3.  Return SUCCESS. */
 
427
}