iPXE
hash_df.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  * Hash-based derivation function (Hash_df)
00041  *
00042  * This algorithm is designed to comply with ANS X9.82 Part 3-2007
00043  * Section 10.5.2.  This standard is not freely available, but most of
00044  * the 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 <assert.h>
00058 #include <byteswap.h>
00059 #include <ipxe/crypto.h>
00060 #include <ipxe/hash_df.h>
00061 
00062 /**
00063  * Distribute entropy throughout a buffer
00064  *
00065  * @v hash              Underlying hash algorithm
00066  * @v input             Input data
00067  * @v input_len         Length of input data, in bytes
00068  * @v output            Output buffer
00069  * @v output_len        Length of output buffer, in bytes
00070  *
00071  * This is the Hash_df function defined in ANS X9.82 Part 3-2007
00072  * Section 10.5.2 (NIST SP 800-90 Section 10.4.1).
00073  *
00074  * The number of bits requested is implicit in the length of the
00075  * output buffer.  Requests must be for an integral number of bytes.
00076  *
00077  * The output buffer is filled incrementally with each iteration of
00078  * the central loop, rather than constructing an overall "temp" and
00079  * then taking the leftmost(no_of_bits_to_return) bits.
00080  *
00081  * There is no way for the Hash_df function to fail.  The returned
00082  * status SUCCESS is implicit.
00083  */
00084 void hash_df ( struct digest_algorithm *hash, const void *input,
00085                size_t input_len, void *output, size_t output_len ) {
00086         uint8_t context[hash->ctxsize];
00087         uint8_t digest[hash->digestsize];
00088         size_t frag_len;
00089         struct {
00090                 uint8_t pad[3];
00091                 uint8_t counter;
00092                 uint32_t no_of_bits_to_return;
00093         } __attribute__ (( packed )) prefix;
00094         void *temp;
00095         size_t remaining;
00096 
00097         DBGC ( &hash_df, "HASH_DF input:\n" );
00098         DBGC_HDA ( &hash_df, 0, input, input_len );
00099 
00100         /* Sanity checks */
00101         assert ( input != NULL );
00102         assert ( output != NULL );
00103 
00104         /* 1.  temp = the Null string
00105          * 2.  len = ceil ( no_of_bits_to_return / outlen )
00106          *
00107          * (Nothing to do.  We fill the output buffer incrementally,
00108          * rather than constructing the complete "temp" in-memory.
00109          * "len" is implicit in the number of iterations required to
00110          * fill the output buffer, and so is not calculated
00111          * explicitly.)
00112          */
00113 
00114         /* 3.  counter = an 8-bit binary value representing the integer "1" */
00115         prefix.counter = 1;
00116 
00117         /* 4.  For i = 1 to len do */
00118         for ( temp = output, remaining = output_len ; remaining > 0 ; ) {
00119 
00120                 /* Comment: in step 5.1 (sic), no_of_bits_to_return is
00121                  * used as a 32-bit string.
00122                  *
00123                  * 4.1  temp = temp || Hash ( counter || no_of_bits_to_return
00124                  *                            || input_string )
00125                  */
00126                 prefix.no_of_bits_to_return = htonl ( output_len * 8 );
00127                 digest_init ( hash, context );
00128                 digest_update ( hash, context, &prefix.counter,
00129                                 ( sizeof ( prefix ) -
00130                                   offsetof ( typeof ( prefix ), counter ) ) );
00131                 digest_update ( hash, context, input, input_len );
00132                 digest_final ( hash, context, digest );
00133 
00134                 /* 4.2  counter = counter + 1 */
00135                 prefix.counter++;
00136 
00137                 /* 5.    requested_bits = Leftmost ( no_of_bits_to_return )
00138                  *       of temp
00139                  *
00140                  * (We fill the output buffer incrementally.)
00141                  */
00142                 frag_len = sizeof ( digest );
00143                 if ( frag_len > remaining )
00144                         frag_len = remaining;
00145                 memcpy ( temp, digest, frag_len );
00146                 temp += frag_len;
00147                 remaining -= frag_len;
00148         }
00149 
00150         /* 6.  Return SUCCESS and requested_bits */
00151         DBGC ( &hash_df, "HASH_DF output:\n" );
00152         DBGC_HDA ( &hash_df, 0, output, output_len );
00153         return;
00154 }