You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

hmac_drbg.c 11KB

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