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 12KB

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