iPXE
drbg.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  *
00023  * Alternatively, you may distribute this code in source or binary
00024  * form, with or without modification, provided that the following
00025  * conditions are met:
00026  *
00027  *  1. Redistributions of source code must retain the above copyright
00028  *     notice, this list of conditions and the above disclaimer.
00029  *
00030  *  2. Redistributions in binary form must reproduce the above
00031  *     copyright notice, this list of conditions and the above
00032  *     disclaimer in the documentation and/or other materials provided
00033  *     with the distribution.
00034  */
00035 
00036 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00037 
00038 /** @file
00039  *
00040  * DRBG mechanism
00041  *
00042  * This mechanism is designed to comply with ANS X9.82 Part 3-2007
00043  * Section 9.  This standard is not freely available, but most of the
00044  * text appears to be shared with NIST SP 800-90, which can be
00045  * downloaded from
00046  *
00047  *     http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
00048  *
00049  * Where possible, references are given to both documents.  In the
00050  * case of any disagreement, ANS X9.82 takes priority over NIST SP
00051  * 800-90.  (In particular, note that some algorithms that are
00052  * Approved by NIST SP 800-90 are not Approved by ANS X9.82.)
00053  */
00054 
00055 #include <stdint.h>
00056 #include <string.h>
00057 #include <errno.h>
00058 #include <assert.h>
00059 #include <ipxe/entropy.h>
00060 #include <ipxe/drbg.h>
00061 
00062 /**
00063  * Instantiate DRBG
00064  *
00065  * @v state             Algorithm state to be initialised
00066  * @v personal          Personalisation string
00067  * @v personal_len      Length of personalisation string
00068  * @ret rc              Return status code
00069  *
00070  * This is the Instantiate_function defined in ANS X9.82 Part 3-2007
00071  * Section 9.2 (NIST SP 800-90 Section 9.1).
00072  *
00073  * Only a single security strength is supported, and prediction
00074  * resistance is always enabled.  The nonce is accounted for by
00075  * increasing the entropy input, as per ANS X9.82 Part 3-2007 Section
00076  * 8.4.2 (NIST SP 800-90 Section 8.6.7).
00077  */
00078 int drbg_instantiate ( struct drbg_state *state, const void *personal,
00079                        size_t personal_len ) {
00080         unsigned int entropy_bits = ( ( 3 * DRBG_SECURITY_STRENGTH + 1 ) / 2 );
00081         size_t min_len = DRBG_MIN_ENTROPY_LEN_BYTES;
00082         size_t max_len = DRBG_MAX_ENTROPY_LEN_BYTES;
00083         uint8_t data[max_len];
00084         int len;
00085         int rc;
00086 
00087         DBGC ( state, "DRBG %p instantiate\n", state );
00088 
00089         /* Sanity checks */
00090         assert ( state != NULL );
00091 
00092         /* 1.  If requested_instantiation_security_strength >
00093          *     highest_supported_security_strength, then return an
00094          *     ERROR_FLAG
00095          */
00096         if ( DRBG_SECURITY_STRENGTH > DRBG_MAX_SECURITY_STRENGTH ) {
00097                 DBGC ( state, "DRBG %p cannot support security strength %d\n",
00098                        state, DRBG_SECURITY_STRENGTH );
00099                 return -ENOTSUP;
00100         }
00101 
00102         /* 2.  If prediction_resistance_flag is set, and prediction
00103          *     resistance is not supported, then return an ERROR_FLAG
00104          *
00105          * (Nothing to do since prediction resistance is always
00106          * supported.)
00107          */
00108 
00109         /* 3.  If the length of the personalization_string >
00110          *     max_personalization_string_length, return an ERROR_FLAG
00111          */
00112         if ( personal_len > DRBG_MAX_PERSONAL_LEN_BYTES ) {
00113                 DBGC ( state, "DRBG %p personalisation string too long (%zd "
00114                        "bytes)\n", state, personal_len );
00115                 return -ERANGE;
00116         }
00117 
00118         /* 4.  Set security_strength to the nearest security strength
00119          *     greater than or equal to
00120          *     requested_instantiation_security_strength.
00121          *
00122          * (Nothing to do since we support only a single security
00123          * strength.)
00124          */
00125 
00126         /* 5.  Using the security_strength, select appropriate DRBG
00127          *     mechanism parameters.
00128          *
00129          * (Nothing to do since we support only a single security
00130          * strength.)
00131          */
00132 
00133         /* 6.  ( status, entropy_input ) = Get_entropy_input (
00134          *     security_strength, min_length, max_length,
00135          *     prediction_resistance_request )
00136          * 7.  If an ERROR is returned in step 6, return a
00137          *     CATASTROPHIC_ERROR_FLAG.
00138          * 8.  Obtain a nonce.
00139          */
00140         len = get_entropy_input ( entropy_bits, data, min_len,
00141                                   sizeof ( data ) );
00142         if ( len < 0 ) {
00143                 rc = len;
00144                 DBGC ( state, "DRBG %p could not get entropy input: %s\n",
00145                        state, strerror ( rc ) );
00146                 return rc;
00147         }
00148         assert ( len >= ( int ) min_len );
00149         assert ( len <= ( int ) sizeof ( data ) );
00150 
00151         /* 9.  initial_working_state = Instantiate_algorithm (
00152          *     entropy_input, nonce, personalization_string ).
00153          */
00154         drbg_instantiate_algorithm ( state, data, len, personal, personal_len );
00155 
00156         /* 10.  Get a state_handle for a currently empty state.  If an
00157          *      empty internal state cannot be found, return an
00158          *      ERROR_FLAG.
00159          * 11.  Set the internal state indicated by state_handle to
00160          *      the initial values for the internal state (i.e. set
00161          *      the working_state to the values returned as
00162          *      initial_working_state in step 9 and any other values
00163          *      required for the working_state, and set the
00164          *      administrative information to the appropriate values.
00165          *
00166          * (Almost nothing to do since the memory to hold the state
00167          * was passed in by the caller and has already been updated
00168          * in-situ.)
00169          */
00170         state->reseed_required = 0;
00171         state->valid = 1;
00172 
00173         /* 12.  Return SUCCESS and state_handle. */
00174         return 0;
00175 }
00176 
00177 /**
00178  * Reseed DRBG
00179  *
00180  * @v state             Algorithm state
00181  * @v additional        Additional input
00182  * @v additional_len    Length of additional input
00183  * @ret rc              Return status code
00184  *
00185  * This is the Reseed_function defined in ANS X9.82 Part 3-2007
00186  * Section 9.3 (NIST SP 800-90 Section 9.2).
00187  *
00188  * Prediction resistance is always enabled.
00189  */
00190 int drbg_reseed ( struct drbg_state *state, const void *additional,
00191                   size_t additional_len ) {
00192         unsigned int entropy_bits = DRBG_SECURITY_STRENGTH;
00193         size_t min_len = DRBG_MIN_ENTROPY_LEN_BYTES;
00194         size_t max_len = DRBG_MAX_ENTROPY_LEN_BYTES;
00195         uint8_t data[max_len];
00196         int len;
00197         int rc;
00198 
00199         DBGC ( state, "DRBG %p reseed\n", state );
00200 
00201         /* Sanity checks */
00202         assert ( state != NULL );
00203 
00204         /* 1.  Using state_handle, obtain the current internal state.
00205          *     If state_handle indicates an invalid or empty internal
00206          *     state, return an ERROR_FLAG.
00207          *
00208          * (Almost nothing to do since the memory holding the internal
00209          * state was passed in by the caller.)
00210          */
00211         if ( ! state->valid ) {
00212                 DBGC ( state, "DRBG %p not valid\n", state );
00213                 return -EINVAL;
00214         }
00215 
00216         /* 2.  If prediction_resistance_request is set, and
00217          *     prediction_resistance_flag is not set, then return an
00218          *     ERROR_FLAG.
00219          *
00220          * (Nothing to do since prediction resistance is always
00221          * supported.)
00222          */
00223 
00224         /* 3.  If the length of the additional_input >
00225          *     max_additional_input_length, return an ERROR_FLAG.
00226          */
00227         if ( additional_len > DRBG_MAX_ADDITIONAL_LEN_BYTES ) {
00228                 DBGC ( state, "DRBG %p additional input too long (%zd bytes)\n",
00229                        state, additional_len );
00230                 return -ERANGE;
00231         }
00232 
00233         /* 4.  ( status, entropy_input ) = Get_entropy_input (
00234          *     security_strength, min_length, max_length,
00235          *     prediction_resistance_request ).
00236          *
00237          * 5.  If an ERROR is returned in step 4, return a
00238          *     CATASTROPHIC_ERROR_FLAG.
00239          */
00240         len = get_entropy_input ( entropy_bits, data, min_len,
00241                                   sizeof ( data ) );
00242         if ( len < 0 ) {
00243                 rc = len;
00244                 DBGC ( state, "DRBG %p could not get entropy input: %s\n",
00245                        state, strerror ( rc ) );
00246                 return rc;
00247         }
00248 
00249         /* 6.  new_working_state = Reseed_algorithm ( working_state,
00250          *     entropy_input, additional_input ).
00251          */
00252         drbg_reseed_algorithm ( state, data, len, additional, additional_len );
00253 
00254         /* 7.  Replace the working_state in the internal state
00255          *     indicated by state_handle with the values of
00256          *     new_working_state obtained in step 6.
00257          *
00258          * (Nothing to do since the state has already been updated in-situ.)
00259          */
00260 
00261         /* 8.  Return SUCCESS. */
00262         return 0;
00263 }
00264 
00265 /**
00266  * Generate pseudorandom bits using DRBG
00267  *
00268  * @v state             Algorithm state
00269  * @v additional        Additional input
00270  * @v additional_len    Length of additional input
00271  * @v prediction_resist Prediction resistance is required
00272  * @v data              Output buffer
00273  * @v len               Length of output buffer
00274  * @ret rc              Return status code
00275  *
00276  * This is the Generate_function defined in ANS X9.82 Part 3-2007
00277  * Section 9.4 (NIST SP 800-90 Section 9.3).
00278  *
00279  * Requests must be for an integral number of bytes.  Only a single
00280  * security strength is supported.  Prediction resistance is supported
00281  * if requested.
00282  */
00283 int drbg_generate ( struct drbg_state *state, const void *additional,
00284                     size_t additional_len, int prediction_resist,
00285                     void *data, size_t len ) {
00286         int rc;
00287 
00288         DBGC ( state, "DRBG %p generate\n", state );
00289 
00290         /* Sanity checks */
00291         assert ( state != NULL );
00292         assert ( data != NULL );
00293 
00294         /* 1.  Using state_handle, obtain the current internal state
00295          *     for the instantiation.  If state_handle indicates an
00296          *     invalid or empty internal state, then return an ERROR_FLAG.
00297          *
00298          * (Almost nothing to do since the memory holding the internal
00299          * state was passed in by the caller.)
00300          */
00301         if ( ! state->valid ) {
00302                 DBGC ( state, "DRBG %p not valid\n", state );
00303                 return -EINVAL;
00304         }
00305 
00306         /* 2.  If requested_number_of_bits >
00307          *     max_number_of_bits_per_request, then return an
00308          *     ERROR_FLAG.
00309          */
00310         if ( len > DRBG_MAX_GENERATED_LEN_BYTES ) {
00311                 DBGC ( state, "DRBG %p request too long (%zd bytes)\n",
00312                        state, len );
00313                 return -ERANGE;
00314         }
00315 
00316         /* 3.  If requested_security_strength > the security_strength
00317          *     indicated in the internal state, then return an
00318          *     ERROR_FLAG.
00319          *
00320          * (Nothing to do since only a single security strength is
00321          * supported.)
00322          */
00323 
00324         /* 4.  If the length of the additional_input >
00325          *     max_additional_input_length, then return an ERROR_FLAG.
00326          */
00327         if ( additional_len > DRBG_MAX_ADDITIONAL_LEN_BYTES ) {
00328                 DBGC ( state, "DRBG %p additional input too long (%zd bytes)\n",
00329                        state, additional_len );
00330                 return -ERANGE;
00331         }
00332 
00333         /* 5.  If prediction_resistance_request is set, and
00334          *     prediction_resistance_flag is not set, then return an
00335          *     ERROR_FLAG.
00336          *
00337          * (Nothing to do since prediction resistance is always
00338          * supported.)
00339          */
00340 
00341         /* 6.  Clear the reseed_required_flag. */
00342         state->reseed_required = 0;
00343 
00344  step_7:
00345         /* 7.  If reseed_required_flag is set, or if
00346          *     prediction_resistance_request is set, then
00347          */
00348         if ( state->reseed_required || prediction_resist ) {
00349 
00350                 /* 7.1  status = Reseed_function ( state_handle,
00351                  *      prediction_resistance_request,
00352                  *      additional_input )
00353                  * 7.2  If status indicates an ERROR, then return
00354                  *      status.
00355                  */
00356                 if ( ( rc = drbg_reseed ( state, additional,
00357                                           additional_len ) ) != 0 ) {
00358                         DBGC ( state, "DRBG %p could not reseed: %s\n",
00359                                state, strerror ( rc ) );
00360                         return rc;
00361                 }
00362 
00363                 /* 7.3  Using state_handle, obtain the new internal
00364                  *      state.
00365                  *
00366                  * (Nothing to do since the internal state has been
00367                  * updated in-situ.)
00368                  */
00369 
00370                 /* 7.4  additional_input = the Null string. */
00371                 additional = NULL;
00372                 additional_len = 0;
00373 
00374                 /* 7.5  Clear the reseed_required_flag. */
00375                 state->reseed_required = 0;
00376         }
00377 
00378         /* 8.  ( status, pseudorandom_bits, new_working_state ) =
00379          *     Generate_algorithm ( working_state,
00380          *     requested_number_of_bits, additional_input ).
00381          */
00382         rc = drbg_generate_algorithm ( state, additional, additional_len,
00383                                        data, len );
00384 
00385         /* 9.  If status indicates that a reseed is required before
00386          *     the requested bits can be generated, then
00387          */
00388         if ( rc != 0 ) {
00389 
00390                 /* 9.1  Set the reseed_required_flag. */
00391                 state->reseed_required = 1;
00392 
00393                 /* 9.2  If the prediction_resistance_flag is set, then
00394                  *      set the prediction_resistance_request
00395                  *      indication.
00396                  */
00397                 prediction_resist = 1;
00398 
00399                 /* 9.3  Go to step 7. */
00400                 goto step_7;
00401         }
00402 
00403         /* 10.  Replace the old working_state in the internal state
00404          *      indicated by state_handle with the values of
00405          *      new_working_state.
00406          *
00407          * (Nothing to do since the working state has already been
00408          * updated in-situ.)
00409          */
00410 
00411         /* 11.  Return SUCCESS and pseudorandom_bits. */
00412         return 0;
00413 }
00414 
00415 /**
00416  * Uninstantiate DRBG
00417  *
00418  * @v state             Algorithm state
00419  *
00420  * This is the Uninstantiate_function defined in ANS X9.82 Part 3-2007
00421  * Section 9.5 (NIST SP 800-90 Section 9.4).
00422  */
00423 void drbg_uninstantiate ( struct drbg_state *state ) {
00424 
00425         DBGC ( state, "DRBG %p uninstantiate\n", state );
00426 
00427         /* Sanity checks */
00428         assert ( state != NULL );
00429 
00430         /* 1.  If state_handle indicates an invalid state, then return
00431          *     an ERROR_FLAG.
00432          *
00433          * (Nothing to do since the memory holding the internal state
00434          * was passed in by the caller.)
00435          */
00436 
00437         /* 2.  Erase the contents of the internal state indicated by
00438          *     state_handle.
00439          */
00440         memset ( state, 0, sizeof ( *state ) );
00441 
00442         /* 3.  Return SUCCESS. */
00443 }