curl_sha512_256.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Evgeny Grin (Karlson2k), <k2k@narod.ru>.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. * SPDX-License-Identifier: curl
  22. *
  23. ***************************************************************************/
  24. #include "curl_setup.h"
  25. #if !defined(CURL_DISABLE_DIGEST_AUTH) && !defined(CURL_DISABLE_SHA512_256)
  26. #include "curl_sha512_256.h"
  27. #include "warnless.h"
  28. /* ** This implementation of SHA-512/256 hash calculation was originally ** *
  29. * ** written by Evgeny Grin (Karlson2k) for GNU libmicrohttpd. ** *
  30. * ** The author ported the code to libcurl. The ported code is provided ** *
  31. * ** under curl license. ** *
  32. * ** This is a minimal version with minimal optimisations. Performance ** *
  33. * ** can be significantly improved. Big-endian store and load macros ** *
  34. * ** are obvious targets for optimisation. ** */
  35. #ifdef __GNUC__
  36. # if defined(__has_attribute) && defined(__STDC_VERSION__)
  37. # if __has_attribute(always_inline) && __STDC_VERSION__ >= 199901
  38. # define MHDX_INLINE inline __attribute__((always_inline))
  39. # endif
  40. # endif
  41. #endif
  42. #if !defined(MHDX_INLINE) && \
  43. defined(_MSC_VER) && !defined(__GNUC__) && !defined(__clang__)
  44. # if _MSC_VER >= 1400
  45. # define MHDX_INLINE __forceinline
  46. # else
  47. # define MHDX_INLINE /* empty */
  48. # endif
  49. #endif
  50. #if !defined(MHDX_INLINE)
  51. # if defined(inline)
  52. /* Assume that 'inline' macro was already defined correctly by
  53. * the build system. */
  54. # define MHDX_INLINE inline
  55. # elif defined(__cplusplus)
  56. /* The code is compiled with C++ compiler.
  57. * C++ always supports 'inline'. */
  58. # define MHDX_INLINE inline
  59. # elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901
  60. /* C99 (and later) supports 'inline' keyword */
  61. # define MHDX_INLINE inline
  62. # elif defined(__GNUC__) && __GNUC__ >= 3
  63. /* GCC supports '__inline__' as an extension */
  64. # define MHDX_INLINE __inline__
  65. # else
  66. # define MHDX_INLINE /* empty */
  67. # endif
  68. #endif
  69. /* Bits manipulation macros and functions.
  70. Can be moved to other headers to reuse. */
  71. #define MHDX_GET_64BIT_BE(ptr) \
  72. ( ((curl_uint64_t)(((const unsigned char*)(ptr))[0]) << 56) | \
  73. ((curl_uint64_t)(((const unsigned char*)(ptr))[1]) << 48) | \
  74. ((curl_uint64_t)(((const unsigned char*)(ptr))[2]) << 40) | \
  75. ((curl_uint64_t)(((const unsigned char*)(ptr))[3]) << 32) | \
  76. ((curl_uint64_t)(((const unsigned char*)(ptr))[4]) << 24) | \
  77. ((curl_uint64_t)(((const unsigned char*)(ptr))[5]) << 16) | \
  78. ((curl_uint64_t)(((const unsigned char*)(ptr))[6]) << 8) | \
  79. (curl_uint64_t)(((const unsigned char*)(ptr))[7]) )
  80. #define MHDX_PUT_64BIT_BE(ptr,val) do { \
  81. ((unsigned char*)(ptr))[7]=(unsigned char)((curl_uint64_t)(val)); \
  82. ((unsigned char*)(ptr))[6]=(unsigned char)(((curl_uint64_t)(val)) >> 8); \
  83. ((unsigned char*)(ptr))[5]=(unsigned char)(((curl_uint64_t)(val)) >> 16); \
  84. ((unsigned char*)(ptr))[4]=(unsigned char)(((curl_uint64_t)(val)) >> 24); \
  85. ((unsigned char*)(ptr))[3]=(unsigned char)(((curl_uint64_t)(val)) >> 32); \
  86. ((unsigned char*)(ptr))[2]=(unsigned char)(((curl_uint64_t)(val)) >> 40); \
  87. ((unsigned char*)(ptr))[1]=(unsigned char)(((curl_uint64_t)(val)) >> 48); \
  88. ((unsigned char*)(ptr))[0]=(unsigned char)(((curl_uint64_t)(val)) >> 56); \
  89. } while(0)
  90. /* Defined as a function. The macro version may duplicate the binary code
  91. * size as each argument is used twice, so if any calculation is used
  92. * as an argument, the calculation could be done twice. */
  93. static MHDX_INLINE curl_uint64_t
  94. MHDx_rotr64(curl_uint64_t value, unsigned int bits)
  95. {
  96. bits %= 64;
  97. if(0 == bits)
  98. return value;
  99. /* Defined in a form which modern compiler could optimise. */
  100. return (value >> bits) | (value << (64 - bits));
  101. }
  102. /* SHA-512/256 specific data */
  103. /**
  104. * Number of bits in single SHA-512/256 word.
  105. */
  106. #define SHA512_256_WORD_SIZE_BITS 64
  107. /**
  108. * Number of bytes in single SHA-512/256 word.
  109. */
  110. #define SHA512_256_BYTES_IN_WORD (SHA512_256_WORD_SIZE_BITS / 8)
  111. /**
  112. * Hash is kept internally as 8 64-bit words.
  113. * This is intermediate hash size, used during computing the final digest.
  114. */
  115. #define SHA512_256_HASH_SIZE_WORDS 8
  116. /**
  117. * Size of SHA-512/256 resulting digest in bytes.
  118. * This is the final digest size, not intermediate hash.
  119. */
  120. #define SHA512_256_DIGEST_SIZE_WORDS (SHA512_256_HASH_SIZE_WORDS / 2)
  121. /**
  122. * Size of SHA-512/256 resulting digest in bytes
  123. * This is the final digest size, not intermediate hash.
  124. */
  125. #define SHA512_256_DIGEST_SIZE \
  126. (SHA512_256_DIGEST_SIZE_WORDS * SHA512_256_BYTES_IN_WORD)
  127. /**
  128. * Size of SHA-512/256 single processing block in bits.
  129. */
  130. #define SHA512_256_BLOCK_SIZE_BITS 1024
  131. /**
  132. * Size of SHA-512/256 single processing block in bytes.
  133. */
  134. #define SHA512_256_BLOCK_SIZE (SHA512_256_BLOCK_SIZE_BITS / 8)
  135. /**
  136. * Size of SHA-512/256 single processing block in words.
  137. */
  138. #define SHA512_256_BLOCK_SIZE_WORDS \
  139. (SHA512_256_BLOCK_SIZE_BITS / SHA512_256_WORD_SIZE_BITS)
  140. /**
  141. * SHA-512/256 calculation context
  142. */
  143. struct Sha512_256Ctx
  144. {
  145. /**
  146. * Intermediate hash value
  147. * The variable is properly aligned. Smart compiler
  148. * may automatically use fast load/store instruction
  149. * for big endian data on little endian machine.
  150. */
  151. curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS];
  152. /**
  153. * SHA-512/256 input data buffer
  154. * The buffer is properly aligned. Smart compiler
  155. * may automatically use fast load/store instruction
  156. * for big endian data on little endian machine.
  157. */
  158. curl_uint64_t buffer[SHA512_256_BLOCK_SIZE_WORDS];
  159. /**
  160. * The number of bytes, lower part
  161. */
  162. curl_uint64_t count;
  163. /**
  164. * The number of bits, high part.
  165. * Unlike lower part, this counts the number of bits, not bytes.
  166. */
  167. curl_uint64_t count_bits_hi;
  168. };
  169. /**
  170. * Initialise structure for SHA-512/256 calculation.
  171. *
  172. * @param context the calculation context
  173. * @return always CURLE_OK
  174. */
  175. static CURLcode
  176. MHDx_sha512_256_init(void *context)
  177. {
  178. struct Sha512_256Ctx *const ctx = (struct Sha512_256Ctx *) context;
  179. /* Check whether the header and this file use the same numbers */
  180. DEBUGASSERT(SHA512_256_DIGEST_LENGTH == SHA512_256_DIGEST_SIZE);
  181. DEBUGASSERT(sizeof(curl_uint64_t) == 8);
  182. /* Initial hash values, see FIPS PUB 180-4 section 5.3.6.2 */
  183. /* Values generated by "IV Generation Function" as described in
  184. * section 5.3.6 */
  185. ctx->H[0] = CURL_UINT64_C(0x22312194FC2BF72C);
  186. ctx->H[1] = CURL_UINT64_C(0x9F555FA3C84C64C2);
  187. ctx->H[2] = CURL_UINT64_C(0x2393B86B6F53B151);
  188. ctx->H[3] = CURL_UINT64_C(0x963877195940EABD);
  189. ctx->H[4] = CURL_UINT64_C(0x96283EE2A88EFFE3);
  190. ctx->H[5] = CURL_UINT64_C(0xBE5E1E2553863992);
  191. ctx->H[6] = CURL_UINT64_C(0x2B0199FC2C85B8AA);
  192. ctx->H[7] = CURL_UINT64_C(0x0EB72DDC81C52CA2);
  193. /* Initialise number of bytes and high part of number of bits. */
  194. ctx->count = CURL_UINT64_C(0);
  195. ctx->count_bits_hi = CURL_UINT64_C(0);
  196. return CURLE_OK;
  197. }
  198. /**
  199. * Base of SHA-512/256 transformation.
  200. * Gets full 128 bytes block of data and updates hash values;
  201. * @param H hash values
  202. * @param data the data buffer with #SHA512_256_BLOCK_SIZE bytes block
  203. */
  204. static void
  205. MHDx_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS],
  206. const void *data)
  207. {
  208. /* Working variables,
  209. see FIPS PUB 180-4 section 6.7, 6.4. */
  210. curl_uint64_t a = H[0];
  211. curl_uint64_t b = H[1];
  212. curl_uint64_t c = H[2];
  213. curl_uint64_t d = H[3];
  214. curl_uint64_t e = H[4];
  215. curl_uint64_t f = H[5];
  216. curl_uint64_t g = H[6];
  217. curl_uint64_t h = H[7];
  218. /* Data buffer, used as a cyclic buffer.
  219. See FIPS PUB 180-4 section 5.2.2, 6.7, 6.4. */
  220. curl_uint64_t W[16];
  221. /* 'Ch' and 'Maj' macro functions are defined with
  222. widely-used optimisation.
  223. See FIPS PUB 180-4 formulae 4.8, 4.9. */
  224. #define Ch(x,y,z) ( (z) ^ ((x) & ((y) ^ (z))) )
  225. #define Maj(x,y,z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) )
  226. /* Unoptimized (original) versions: */
  227. /* #define Ch(x,y,z) ( ( (x) & (y) ) ^ ( ~(x) & (z) ) ) */
  228. /* #define Maj(x,y,z) ( ((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)) ) */
  229. /* Four 'Sigma' macro functions.
  230. See FIPS PUB 180-4 formulae 4.10, 4.11, 4.12, 4.13. */
  231. #define SIG0(x) \
  232. ( MHDx_rotr64((x), 28) ^ MHDx_rotr64((x), 34) ^ MHDx_rotr64((x), 39) )
  233. #define SIG1(x) \
  234. ( MHDx_rotr64((x), 14) ^ MHDx_rotr64((x), 18) ^ MHDx_rotr64((x), 41) )
  235. #define sig0(x) \
  236. ( MHDx_rotr64((x), 1) ^ MHDx_rotr64((x), 8) ^ ((x) >> 7) )
  237. #define sig1(x) \
  238. ( MHDx_rotr64((x), 19) ^ MHDx_rotr64((x), 61) ^ ((x) >> 6) )
  239. if(1) {
  240. unsigned int t;
  241. /* K constants array.
  242. See FIPS PUB 180-4 section 4.2.3 for K values. */
  243. static const curl_uint64_t K[80] =
  244. { CURL_UINT64_C(0x428a2f98d728ae22), CURL_UINT64_C(0x7137449123ef65cd),
  245. CURL_UINT64_C(0xb5c0fbcfec4d3b2f), CURL_UINT64_C(0xe9b5dba58189dbbc),
  246. CURL_UINT64_C(0x3956c25bf348b538), CURL_UINT64_C(0x59f111f1b605d019),
  247. CURL_UINT64_C(0x923f82a4af194f9b), CURL_UINT64_C(0xab1c5ed5da6d8118),
  248. CURL_UINT64_C(0xd807aa98a3030242), CURL_UINT64_C(0x12835b0145706fbe),
  249. CURL_UINT64_C(0x243185be4ee4b28c), CURL_UINT64_C(0x550c7dc3d5ffb4e2),
  250. CURL_UINT64_C(0x72be5d74f27b896f), CURL_UINT64_C(0x80deb1fe3b1696b1),
  251. CURL_UINT64_C(0x9bdc06a725c71235), CURL_UINT64_C(0xc19bf174cf692694),
  252. CURL_UINT64_C(0xe49b69c19ef14ad2), CURL_UINT64_C(0xefbe4786384f25e3),
  253. CURL_UINT64_C(0x0fc19dc68b8cd5b5), CURL_UINT64_C(0x240ca1cc77ac9c65),
  254. CURL_UINT64_C(0x2de92c6f592b0275), CURL_UINT64_C(0x4a7484aa6ea6e483),
  255. CURL_UINT64_C(0x5cb0a9dcbd41fbd4), CURL_UINT64_C(0x76f988da831153b5),
  256. CURL_UINT64_C(0x983e5152ee66dfab), CURL_UINT64_C(0xa831c66d2db43210),
  257. CURL_UINT64_C(0xb00327c898fb213f), CURL_UINT64_C(0xbf597fc7beef0ee4),
  258. CURL_UINT64_C(0xc6e00bf33da88fc2), CURL_UINT64_C(0xd5a79147930aa725),
  259. CURL_UINT64_C(0x06ca6351e003826f), CURL_UINT64_C(0x142929670a0e6e70),
  260. CURL_UINT64_C(0x27b70a8546d22ffc), CURL_UINT64_C(0x2e1b21385c26c926),
  261. CURL_UINT64_C(0x4d2c6dfc5ac42aed), CURL_UINT64_C(0x53380d139d95b3df),
  262. CURL_UINT64_C(0x650a73548baf63de), CURL_UINT64_C(0x766a0abb3c77b2a8),
  263. CURL_UINT64_C(0x81c2c92e47edaee6), CURL_UINT64_C(0x92722c851482353b),
  264. CURL_UINT64_C(0xa2bfe8a14cf10364), CURL_UINT64_C(0xa81a664bbc423001),
  265. CURL_UINT64_C(0xc24b8b70d0f89791), CURL_UINT64_C(0xc76c51a30654be30),
  266. CURL_UINT64_C(0xd192e819d6ef5218), CURL_UINT64_C(0xd69906245565a910),
  267. CURL_UINT64_C(0xf40e35855771202a), CURL_UINT64_C(0x106aa07032bbd1b8),
  268. CURL_UINT64_C(0x19a4c116b8d2d0c8), CURL_UINT64_C(0x1e376c085141ab53),
  269. CURL_UINT64_C(0x2748774cdf8eeb99), CURL_UINT64_C(0x34b0bcb5e19b48a8),
  270. CURL_UINT64_C(0x391c0cb3c5c95a63), CURL_UINT64_C(0x4ed8aa4ae3418acb),
  271. CURL_UINT64_C(0x5b9cca4f7763e373), CURL_UINT64_C(0x682e6ff3d6b2b8a3),
  272. CURL_UINT64_C(0x748f82ee5defb2fc), CURL_UINT64_C(0x78a5636f43172f60),
  273. CURL_UINT64_C(0x84c87814a1f0ab72), CURL_UINT64_C(0x8cc702081a6439ec),
  274. CURL_UINT64_C(0x90befffa23631e28), CURL_UINT64_C(0xa4506cebde82bde9),
  275. CURL_UINT64_C(0xbef9a3f7b2c67915), CURL_UINT64_C(0xc67178f2e372532b),
  276. CURL_UINT64_C(0xca273eceea26619c), CURL_UINT64_C(0xd186b8c721c0c207),
  277. CURL_UINT64_C(0xeada7dd6cde0eb1e), CURL_UINT64_C(0xf57d4f7fee6ed178),
  278. CURL_UINT64_C(0x06f067aa72176fba), CURL_UINT64_C(0x0a637dc5a2c898a6),
  279. CURL_UINT64_C(0x113f9804bef90dae), CURL_UINT64_C(0x1b710b35131c471b),
  280. CURL_UINT64_C(0x28db77f523047d84), CURL_UINT64_C(0x32caab7b40c72493),
  281. CURL_UINT64_C(0x3c9ebe0a15c9bebc), CURL_UINT64_C(0x431d67c49c100d4c),
  282. CURL_UINT64_C(0x4cc5d4becb3e42b6), CURL_UINT64_C(0x597f299cfc657e2a),
  283. CURL_UINT64_C(0x5fcb6fab3ad6faec), CURL_UINT64_C(0x6c44198c4a475817)};
  284. /* One step of SHA-512/256 computation,
  285. see FIPS PUB 180-4 section 6.4.2 step 3.
  286. * Note: this macro updates working variables in-place, without rotation.
  287. * Note: the first (vH += SIG1(vE) + Ch(vE,vF,vG) + kt + wt) equals T1 in
  288. FIPS PUB 180-4 section 6.4.2 step 3.
  289. the second (vH += SIG0(vA) + Maj(vE,vF,vC) equals T1 + T2 in
  290. FIPS PUB 180-4 section 6.4.2 step 3.
  291. * Note: 'wt' must be used exactly one time in this macro as macro for
  292. 'wt' calculation may change other data as well every time when
  293. used. */
  294. #define SHA2STEP64(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do { \
  295. (vD) += ((vH) += SIG1 ((vE)) + Ch ((vE),(vF),(vG)) + (kt) + (wt)); \
  296. (vH) += SIG0 ((vA)) + Maj ((vA),(vB),(vC)); } while (0)
  297. /* One step of SHA-512/256 computation with working variables rotation,
  298. see FIPS PUB 180-4 section 6.4.2 step 3.
  299. * Note: this version of macro reassign all working variable on
  300. each step. */
  301. #define SHA2STEP64RV(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do { \
  302. curl_uint64_t tmp_h_ = (vH); \
  303. SHA2STEP64((vA),(vB),(vC),(vD),(vE),(vF),(vG),tmp_h_,(kt),(wt)); \
  304. (vH) = (vG); \
  305. (vG) = (vF); \
  306. (vF) = (vE); \
  307. (vE) = (vD); \
  308. (vD) = (vC); \
  309. (vC) = (vB); \
  310. (vB) = (vA); \
  311. (vA) = tmp_h_; } while(0)
  312. /* Get value of W(t) from input data buffer for 0 <= t <= 15,
  313. See FIPS PUB 180-4 section 6.2.
  314. Input data must be read in big-endian bytes order,
  315. see FIPS PUB 180-4 section 3.1.2. */
  316. #define SHA512_GET_W_FROM_DATA(buf,t) \
  317. MHDX_GET_64BIT_BE( \
  318. ((const unsigned char*) (buf)) + (t) * SHA512_256_BYTES_IN_WORD)
  319. /* During first 16 steps, before making any calculations on each step,
  320. the W element is read from the input data buffer as big-endian value and
  321. stored in the array of W elements. */
  322. for(t = 0; t < 16; ++t) {
  323. SHA2STEP64RV(a, b, c, d, e, f, g, h, K[t], \
  324. W[t] = SHA512_GET_W_FROM_DATA(data, t));
  325. }
  326. /* 'W' generation and assignment for 16 <= t <= 79.
  327. See FIPS PUB 180-4 section 6.4.2.
  328. As only last 16 'W' are used in calculations, it is possible to
  329. use 16 elements array of W as a cyclic buffer.
  330. * Note: ((t-16) & 15) have same value as (t & 15) */
  331. #define Wgen(w,t) \
  332. CURL_UINT64_CAST( (w)[(t - 16) & 15] + sig1((w)[((t) - 2) & 15]) \
  333. + (w)[((t) - 7) & 15] + sig0((w)[((t) - 15) & 15]) )
  334. /* During last 64 steps, before making any calculations on each step,
  335. current W element is generated from other W elements of the cyclic
  336. buffer and the generated value is stored back in the cyclic buffer. */
  337. for(t = 16; t < 80; ++t) {
  338. SHA2STEP64RV(a, b, c, d, e, f, g, h, K[t], \
  339. W[t & 15] = Wgen(W, t));
  340. }
  341. }
  342. /* Compute and store the intermediate hash.
  343. See FIPS PUB 180-4 section 6.4.2 step 4. */
  344. H[0] += a;
  345. H[1] += b;
  346. H[2] += c;
  347. H[3] += d;
  348. H[4] += e;
  349. H[5] += f;
  350. H[6] += g;
  351. H[7] += h;
  352. }
  353. /**
  354. * Process portion of bytes.
  355. *
  356. * @param context the calculation context
  357. * @param data bytes to add to hash
  358. * @param length number of bytes in @a data
  359. */
  360. static void
  361. MHDx_sha512_256_update(void *context,
  362. const unsigned char *data,
  363. unsigned int length)
  364. {
  365. unsigned int bytes_have; /**< Number of bytes in the context buffer */
  366. struct Sha512_256Ctx *const ctx = (struct Sha512_256Ctx *) context;
  367. /* Required to mute Intel compiler warning */
  368. void *const ctx_buf = ctx->buffer;
  369. DEBUGASSERT((data != NULL) || (length == 0));
  370. if(0 == length)
  371. return; /* Shortcut, do nothing */
  372. /* Note: (count & (SHA512_256_BLOCK_SIZE-1))
  373. equals (count % SHA512_256_BLOCK_SIZE) for this block size. */
  374. bytes_have = (unsigned int) (ctx->count & (SHA512_256_BLOCK_SIZE - 1));
  375. ctx->count += length;
  376. if(CURL_UINT64_CAST(length) > ctx->count)
  377. ctx->count_bits_hi += 1U << 3; /* Value wrap */
  378. ctx->count_bits_hi += ctx->count >> 61;
  379. ctx->count &= CURL_UINT64_C(0x1FFFFFFFFFFFFFFF);
  380. if(0 != bytes_have) {
  381. unsigned int bytes_left = SHA512_256_BLOCK_SIZE - bytes_have;
  382. if(length >= bytes_left) {
  383. /* Combine new data with data in the buffer and
  384. process the full block. */
  385. memcpy(((unsigned char *) ctx_buf) + bytes_have,
  386. data,
  387. bytes_left);
  388. data += bytes_left;
  389. length -= bytes_left;
  390. MHDx_sha512_256_transform(ctx->H, ctx->buffer);
  391. bytes_have = 0;
  392. }
  393. }
  394. while(SHA512_256_BLOCK_SIZE <= length) {
  395. /* Process any full blocks of new data directly,
  396. without copying to the buffer. */
  397. MHDx_sha512_256_transform(ctx->H, data);
  398. data += SHA512_256_BLOCK_SIZE;
  399. length -= SHA512_256_BLOCK_SIZE;
  400. }
  401. if(0 != length) {
  402. /* Copy incomplete block of new data (if any)
  403. to the buffer. */
  404. memcpy(((unsigned char *) ctx_buf) + bytes_have, data, length);
  405. }
  406. }
  407. /**
  408. * Size of "length" insertion in bits.
  409. * See FIPS PUB 180-4 section 5.1.2.
  410. */
  411. #define SHA512_256_SIZE_OF_LEN_ADD_BITS 128
  412. /**
  413. * Size of "length" insertion in bytes.
  414. */
  415. #define SHA512_256_SIZE_OF_LEN_ADD (SHA512_256_SIZE_OF_LEN_ADD_BITS / 8)
  416. /**
  417. * Finalise SHA-512/256 calculation, return digest.
  418. *
  419. * @param context the calculation context
  420. * @param[out] digest set to the hash, must be #SHA512_256_DIGEST_SIZE bytes
  421. */
  422. static void
  423. MHDx_sha512_256_finish(unsigned char *digest,
  424. void *context)
  425. {
  426. struct Sha512_256Ctx *const ctx = (struct Sha512_256Ctx *) context;
  427. curl_uint64_t num_bits; /**< Number of processed bits */
  428. unsigned int bytes_have; /**< Number of bytes in the context buffer */
  429. /* Required to mute Intel compiler warning */
  430. void *const ctx_buf = ctx->buffer;
  431. /* Memorise the number of processed bits.
  432. The padding and other data added here during the postprocessing must
  433. not change the amount of hashed data. */
  434. num_bits = ctx->count << 3;
  435. /* Note: (count & (SHA512_256_BLOCK_SIZE-1))
  436. equals (count % SHA512_256_BLOCK_SIZE) for this block size. */
  437. bytes_have = (unsigned int) (ctx->count & (SHA512_256_BLOCK_SIZE - 1));
  438. /* Input data must be padded with a single bit "1", then with zeros and
  439. the finally the length of data in bits must be added as the final bytes
  440. of the last block.
  441. See FIPS PUB 180-4 section 5.1.2. */
  442. /* Data is always processed in form of bytes (not by individual bits),
  443. therefore position of the first padding bit in byte is always
  444. predefined (0x80). */
  445. /* Buffer always have space at least for one byte (as full buffers are
  446. processed when formed). */
  447. ((unsigned char *) ctx_buf)[bytes_have++] = 0x80U;
  448. if(SHA512_256_BLOCK_SIZE - bytes_have < SHA512_256_SIZE_OF_LEN_ADD) {
  449. /* No space in the current block to put the total length of message.
  450. Pad the current block with zeros and process it. */
  451. if(bytes_have < SHA512_256_BLOCK_SIZE)
  452. memset(((unsigned char *) ctx_buf) + bytes_have, 0,
  453. SHA512_256_BLOCK_SIZE - bytes_have);
  454. /* Process the full block. */
  455. MHDx_sha512_256_transform(ctx->H, ctx->buffer);
  456. /* Start the new block. */
  457. bytes_have = 0;
  458. }
  459. /* Pad the rest of the buffer with zeros. */
  460. memset(((unsigned char *) ctx_buf) + bytes_have, 0,
  461. SHA512_256_BLOCK_SIZE - SHA512_256_SIZE_OF_LEN_ADD - bytes_have);
  462. /* Put high part of number of bits in processed message and then lower
  463. part of number of bits as big-endian values.
  464. See FIPS PUB 180-4 section 5.1.2. */
  465. /* Note: the target location is predefined and buffer is always aligned */
  466. MHDX_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
  467. + SHA512_256_BLOCK_SIZE \
  468. - SHA512_256_SIZE_OF_LEN_ADD, \
  469. ctx->count_bits_hi);
  470. MHDX_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
  471. + SHA512_256_BLOCK_SIZE \
  472. - SHA512_256_SIZE_OF_LEN_ADD \
  473. + SHA512_256_BYTES_IN_WORD, \
  474. num_bits);
  475. /* Process the full final block. */
  476. MHDx_sha512_256_transform(ctx->H, ctx->buffer);
  477. /* Put in BE mode the leftmost part of the hash as the final digest.
  478. See FIPS PUB 180-4 section 6.7. */
  479. MHDX_PUT_64BIT_BE((digest + 0 * SHA512_256_BYTES_IN_WORD), ctx->H[0]);
  480. MHDX_PUT_64BIT_BE((digest + 1 * SHA512_256_BYTES_IN_WORD), ctx->H[1]);
  481. MHDX_PUT_64BIT_BE((digest + 2 * SHA512_256_BYTES_IN_WORD), ctx->H[2]);
  482. MHDX_PUT_64BIT_BE((digest + 3 * SHA512_256_BYTES_IN_WORD), ctx->H[3]);
  483. /* Erase potentially sensitive data. */
  484. memset(ctx, 0, sizeof(struct Sha512_256Ctx));
  485. }
  486. /**
  487. * Compute SHA-512/256 hash for the given data in one function call
  488. * @param[out] output the pointer to put the hash
  489. * @param[in] input the pointer to the data to process
  490. * @param input_size the size of the data pointed by @a input
  491. * @return always #CURLE_OK
  492. */
  493. CURLcode
  494. Curl_sha512_256it(unsigned char *output, const unsigned char *input,
  495. size_t input_size)
  496. {
  497. struct Sha512_256Ctx ctx;
  498. static const unsigned int max_step_size = (unsigned int)(-1);
  499. (void) MHDx_sha512_256_init(&ctx); /* Always succeed */
  500. while(input_size >= max_step_size) {
  501. MHDx_sha512_256_update(&ctx, (const void *) input, max_step_size);
  502. input += max_step_size;
  503. input_size -= max_step_size;
  504. }
  505. MHDx_sha512_256_update(&ctx, (const void *) input,
  506. curlx_uztoui(input_size));
  507. MHDx_sha512_256_finish(output, &ctx);
  508. return CURLE_OK;
  509. }
  510. const struct HMAC_params Curl_HMAC_SHA512_256[] = {
  511. {
  512. /* Initialize context procedure. */
  513. MHDx_sha512_256_init,
  514. /* Update context with data. */
  515. MHDx_sha512_256_update,
  516. /* Get final result procedure. */
  517. MHDx_sha512_256_finish,
  518. /* Context structure size. */
  519. sizeof(struct Sha512_256Ctx),
  520. /* Maximum key length (bytes). */
  521. SHA512_256_BLOCK_SIZE,
  522. /* Result length (bytes). */
  523. SHA512_256_DIGEST_SIZE
  524. }
  525. };
  526. #endif /* !CURL_DISABLE_DIGEST_AUTH && !CURL_DISABLE_SHA512_256 */