2
0

curl_sha512_256.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  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. /* The recommended order of the TLS backends:
  29. * * OpenSSL
  30. * * GnuTLS
  31. * * wolfSSL
  32. * * Schannel SSPI
  33. * * SecureTransport (Darwin)
  34. * * mbedTLS
  35. * * BearSSL
  36. * * Rustls
  37. * Skip the backend if it does not support the required algorithm */
  38. #if defined(USE_OPENSSL)
  39. # include <openssl/opensslv.h>
  40. # if (!defined(LIBRESSL_VERSION_NUMBER) && \
  41. defined(OPENSSL_VERSION_NUMBER) && \
  42. (OPENSSL_VERSION_NUMBER >= 0x10101000L)) || \
  43. (defined(LIBRESSL_VERSION_NUMBER) && \
  44. (LIBRESSL_VERSION_NUMBER >= 0x3080000fL))
  45. # include <openssl/opensslconf.h>
  46. # if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA512)
  47. # include <openssl/evp.h>
  48. # define USE_OPENSSL_SHA512_256 1
  49. # define HAS_SHA512_256_IMPLEMENTATION 1
  50. # ifdef __NetBSD__
  51. /* Some NetBSD versions has a bug in SHA-512/256.
  52. * See https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=58039
  53. * The problematic versions:
  54. * - NetBSD before 9.4
  55. * - NetBSD 9 all development versions (9.99.x)
  56. * - NetBSD 10 development versions (10.99.x) before 10.99.11
  57. * The bug was fixed in NetBSD 9.4 release, NetBSD 10.0 release,
  58. * NetBSD 10.99.11 development.
  59. * It is safe to apply the workaround even if the bug is not present, as
  60. * the workaround just reduces performance slightly. */
  61. # include <sys/param.h>
  62. # if __NetBSD_Version__ < 904000000 || \
  63. (__NetBSD_Version__ >= 999000000 && \
  64. __NetBSD_Version__ < 1000000000) || \
  65. (__NetBSD_Version__ >= 1099000000 && \
  66. __NetBSD_Version__ < 1099001100)
  67. # define NEED_NETBSD_SHA512_256_WORKAROUND 1
  68. # include <string.h>
  69. # endif
  70. # endif
  71. # endif
  72. # endif
  73. #endif /* USE_OPENSSL */
  74. #if !defined(HAS_SHA512_256_IMPLEMENTATION) && defined(USE_GNUTLS)
  75. # include <nettle/sha.h>
  76. # if defined(SHA512_256_DIGEST_SIZE)
  77. # define USE_GNUTLS_SHA512_256 1
  78. # define HAS_SHA512_256_IMPLEMENTATION 1
  79. # endif
  80. #endif /* ! HAS_SHA512_256_IMPLEMENTATION && USE_GNUTLS */
  81. #if defined(USE_OPENSSL_SHA512_256)
  82. /* OpenSSL does not provide macros for SHA-512/256 sizes */
  83. /**
  84. * Size of the SHA-512/256 single processing block in bytes.
  85. */
  86. #define CURL_SHA512_256_BLOCK_SIZE 128
  87. /**
  88. * Size of the SHA-512/256 resulting digest in bytes.
  89. * This is the final digest size, not intermediate hash.
  90. */
  91. #define CURL_SHA512_256_DIGEST_SIZE CURL_SHA512_256_DIGEST_LENGTH
  92. /**
  93. * Context type used for SHA-512/256 calculations
  94. */
  95. typedef EVP_MD_CTX *Curl_sha512_256_ctx;
  96. /**
  97. * Initialise structure for SHA-512/256 calculation.
  98. *
  99. * @param context the calculation context
  100. * @return CURLE_OK if succeed,
  101. * error code otherwise
  102. */
  103. static CURLcode
  104. Curl_sha512_256_init(void *context)
  105. {
  106. Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
  107. *ctx = EVP_MD_CTX_create();
  108. if(!*ctx)
  109. return CURLE_OUT_OF_MEMORY;
  110. if(EVP_DigestInit_ex(*ctx, EVP_sha512_256(), NULL)) {
  111. /* Check whether the header and this file use the same numbers */
  112. DEBUGASSERT(EVP_MD_CTX_size(*ctx) == CURL_SHA512_256_DIGEST_SIZE);
  113. /* Check whether the block size is correct */
  114. DEBUGASSERT(EVP_MD_CTX_block_size(*ctx) == CURL_SHA512_256_BLOCK_SIZE);
  115. return CURLE_OK; /* Success */
  116. }
  117. /* Cleanup */
  118. EVP_MD_CTX_destroy(*ctx);
  119. return CURLE_FAILED_INIT;
  120. }
  121. /**
  122. * Process portion of bytes.
  123. *
  124. * @param context the calculation context
  125. * @param data bytes to add to hash
  126. * @return CURLE_OK if succeed,
  127. * error code otherwise
  128. */
  129. static CURLcode
  130. Curl_sha512_256_update(void *context,
  131. const unsigned char *data,
  132. size_t length)
  133. {
  134. Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
  135. if(!EVP_DigestUpdate(*ctx, data, length))
  136. return CURLE_SSL_CIPHER;
  137. return CURLE_OK;
  138. }
  139. /**
  140. * Finalise SHA-512/256 calculation, return digest.
  141. *
  142. * @param context the calculation context
  143. * @param[out] digest set to the hash, must be #CURL_SHA512_256_DIGEST_SIZE
  144. # bytes
  145. * @return CURLE_OK if succeed,
  146. * error code otherwise
  147. */
  148. static CURLcode
  149. Curl_sha512_256_finish(unsigned char *digest,
  150. void *context)
  151. {
  152. CURLcode ret;
  153. Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
  154. #ifdef NEED_NETBSD_SHA512_256_WORKAROUND
  155. /* Use a larger buffer to work around a bug in NetBSD:
  156. https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=58039 */
  157. unsigned char tmp_digest[CURL_SHA512_256_DIGEST_SIZE * 2];
  158. ret = EVP_DigestFinal_ex(*ctx,
  159. tmp_digest, NULL) ? CURLE_OK : CURLE_SSL_CIPHER;
  160. if(ret == CURLE_OK)
  161. memcpy(digest, tmp_digest, CURL_SHA512_256_DIGEST_SIZE);
  162. explicit_memset(tmp_digest, 0, sizeof(tmp_digest));
  163. #else /* ! NEED_NETBSD_SHA512_256_WORKAROUND */
  164. ret = EVP_DigestFinal_ex(*ctx, digest, NULL) ? CURLE_OK : CURLE_SSL_CIPHER;
  165. #endif /* ! NEED_NETBSD_SHA512_256_WORKAROUND */
  166. EVP_MD_CTX_destroy(*ctx);
  167. *ctx = NULL;
  168. return ret;
  169. }
  170. #elif defined(USE_GNUTLS_SHA512_256)
  171. #define CURL_SHA512_256_BLOCK_SIZE SHA512_256_BLOCK_SIZE
  172. #define CURL_SHA512_256_DIGEST_SIZE SHA512_256_DIGEST_SIZE
  173. /**
  174. * Context type used for SHA-512/256 calculations
  175. */
  176. typedef struct sha512_256_ctx Curl_sha512_256_ctx;
  177. /**
  178. * Initialise structure for SHA-512/256 calculation.
  179. *
  180. * @param context the calculation context
  181. * @return always CURLE_OK
  182. */
  183. static CURLcode
  184. Curl_sha512_256_init(void *context)
  185. {
  186. Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
  187. /* Check whether the header and this file use the same numbers */
  188. DEBUGASSERT(CURL_SHA512_256_DIGEST_LENGTH == CURL_SHA512_256_DIGEST_SIZE);
  189. sha512_256_init(ctx);
  190. return CURLE_OK;
  191. }
  192. /**
  193. * Process portion of bytes.
  194. *
  195. * @param context the calculation context
  196. * @param data bytes to add to hash
  197. * @param length number of bytes in @a data
  198. * @return always CURLE_OK
  199. */
  200. static CURLcode
  201. Curl_sha512_256_update(void *context,
  202. const unsigned char *data,
  203. size_t length)
  204. {
  205. Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
  206. DEBUGASSERT((data != NULL) || (length == 0));
  207. sha512_256_update(ctx, length, (const uint8_t *)data);
  208. return CURLE_OK;
  209. }
  210. /**
  211. * Finalise SHA-512/256 calculation, return digest.
  212. *
  213. * @param context the calculation context
  214. * @param[out] digest set to the hash, must be #CURL_SHA512_256_DIGEST_SIZE
  215. # bytes
  216. * @return always CURLE_OK
  217. */
  218. static CURLcode
  219. Curl_sha512_256_finish(unsigned char *digest,
  220. void *context)
  221. {
  222. Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
  223. sha512_256_digest(ctx,
  224. (size_t)CURL_SHA512_256_DIGEST_SIZE, (uint8_t *)digest);
  225. return CURLE_OK;
  226. }
  227. #else /* No system or TLS backend SHA-512/256 implementation available */
  228. /* Use local implementation */
  229. #define HAS_SHA512_256_IMPLEMENTATION 1
  230. /* ** This implementation of SHA-512/256 hash calculation was originally ** *
  231. * ** written by Evgeny Grin (Karlson2k) for GNU libmicrohttpd. ** *
  232. * ** The author ported the code to libcurl. The ported code is provided ** *
  233. * ** under curl license. ** *
  234. * ** This is a minimal version with minimal optimizations. Performance ** *
  235. * ** can be significantly improved. Big-endian store and load macros ** *
  236. * ** are obvious targets for optimization. ** */
  237. #ifdef __GNUC__
  238. # if defined(__has_attribute) && defined(__STDC_VERSION__)
  239. # if __has_attribute(always_inline) && __STDC_VERSION__ >= 199901
  240. # define MHDX_INLINE inline __attribute__((always_inline))
  241. # endif
  242. # endif
  243. #endif
  244. #if !defined(MHDX_INLINE) && \
  245. defined(_MSC_VER) && !defined(__GNUC__) && !defined(__clang__)
  246. # if _MSC_VER >= 1400
  247. # define MHDX_INLINE __forceinline
  248. # endif
  249. #endif
  250. #if !defined(MHDX_INLINE)
  251. /* Assume that 'inline' keyword works or the
  252. * macro was already defined correctly. */
  253. # define MHDX_INLINE inline
  254. #endif
  255. /* Bits manipulation macros and functions.
  256. Can be moved to other headers to reuse. */
  257. #define MHDX_GET_64BIT_BE(ptr) \
  258. ( ((curl_uint64_t)(((const unsigned char*)(ptr))[0]) << 56) | \
  259. ((curl_uint64_t)(((const unsigned char*)(ptr))[1]) << 48) | \
  260. ((curl_uint64_t)(((const unsigned char*)(ptr))[2]) << 40) | \
  261. ((curl_uint64_t)(((const unsigned char*)(ptr))[3]) << 32) | \
  262. ((curl_uint64_t)(((const unsigned char*)(ptr))[4]) << 24) | \
  263. ((curl_uint64_t)(((const unsigned char*)(ptr))[5]) << 16) | \
  264. ((curl_uint64_t)(((const unsigned char*)(ptr))[6]) << 8) | \
  265. (curl_uint64_t)(((const unsigned char*)(ptr))[7]) )
  266. #define MHDX_PUT_64BIT_BE(ptr,val) do { \
  267. ((unsigned char*)(ptr))[7]=(unsigned char)((curl_uint64_t)(val)); \
  268. ((unsigned char*)(ptr))[6]=(unsigned char)(((curl_uint64_t)(val)) >> 8); \
  269. ((unsigned char*)(ptr))[5]=(unsigned char)(((curl_uint64_t)(val)) >> 16); \
  270. ((unsigned char*)(ptr))[4]=(unsigned char)(((curl_uint64_t)(val)) >> 24); \
  271. ((unsigned char*)(ptr))[3]=(unsigned char)(((curl_uint64_t)(val)) >> 32); \
  272. ((unsigned char*)(ptr))[2]=(unsigned char)(((curl_uint64_t)(val)) >> 40); \
  273. ((unsigned char*)(ptr))[1]=(unsigned char)(((curl_uint64_t)(val)) >> 48); \
  274. ((unsigned char*)(ptr))[0]=(unsigned char)(((curl_uint64_t)(val)) >> 56); \
  275. } while(0)
  276. /* Defined as a function. The macro version may duplicate the binary code
  277. * size as each argument is used twice, so if any calculation is used
  278. * as an argument, the calculation could be done twice. */
  279. static MHDX_INLINE curl_uint64_t
  280. MHDx_rotr64(curl_uint64_t value, unsigned int bits)
  281. {
  282. bits %= 64;
  283. if(0 == bits)
  284. return value;
  285. /* Defined in a form which modern compiler could optimize. */
  286. return (value >> bits) | (value << (64 - bits));
  287. }
  288. /* SHA-512/256 specific data */
  289. /**
  290. * Number of bits in a single SHA-512/256 word.
  291. */
  292. #define SHA512_256_WORD_SIZE_BITS 64
  293. /**
  294. * Number of bytes in a single SHA-512/256 word.
  295. */
  296. #define SHA512_256_BYTES_IN_WORD (SHA512_256_WORD_SIZE_BITS / 8)
  297. /**
  298. * Hash is kept internally as 8 64-bit words.
  299. * This is the intermediate hash size, used during computing the final digest.
  300. */
  301. #define SHA512_256_HASH_SIZE_WORDS 8
  302. /**
  303. * Size of the SHA-512/256 resulting digest in words.
  304. * This is the final digest size, not intermediate hash.
  305. */
  306. #define SHA512_256_DIGEST_SIZE_WORDS (SHA512_256_HASH_SIZE_WORDS / 2)
  307. /**
  308. * Size of the SHA-512/256 resulting digest in bytes
  309. * This is the final digest size, not intermediate hash.
  310. */
  311. #define CURL_SHA512_256_DIGEST_SIZE \
  312. (SHA512_256_DIGEST_SIZE_WORDS * SHA512_256_BYTES_IN_WORD)
  313. /**
  314. * Size of the SHA-512/256 single processing block in bits.
  315. */
  316. #define SHA512_256_BLOCK_SIZE_BITS 1024
  317. /**
  318. * Size of the SHA-512/256 single processing block in bytes.
  319. */
  320. #define CURL_SHA512_256_BLOCK_SIZE (SHA512_256_BLOCK_SIZE_BITS / 8)
  321. /**
  322. * Size of the SHA-512/256 single processing block in words.
  323. */
  324. #define SHA512_256_BLOCK_SIZE_WORDS \
  325. (SHA512_256_BLOCK_SIZE_BITS / SHA512_256_WORD_SIZE_BITS)
  326. /**
  327. * SHA-512/256 calculation context
  328. */
  329. struct mhdx_sha512_256ctx
  330. {
  331. /**
  332. * Intermediate hash value. The variable is properly aligned. Smart
  333. * compilers may automatically use fast load/store instruction for big
  334. * endian data on little endian machine.
  335. */
  336. curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS];
  337. /**
  338. * SHA-512/256 input data buffer. The buffer is properly aligned. Smart
  339. * compilers may automatically use fast load/store instruction for big
  340. * endian data on little endian machine.
  341. */
  342. curl_uint64_t buffer[SHA512_256_BLOCK_SIZE_WORDS];
  343. /**
  344. * The number of bytes, lower part
  345. */
  346. curl_uint64_t count;
  347. /**
  348. * The number of bits, high part. Unlike lower part, this counts the number
  349. * of bits, not bytes.
  350. */
  351. curl_uint64_t count_bits_hi;
  352. };
  353. /**
  354. * Context type used for SHA-512/256 calculations
  355. */
  356. typedef struct mhdx_sha512_256ctx Curl_sha512_256_ctx;
  357. /**
  358. * Initialise structure for SHA-512/256 calculation.
  359. *
  360. * @param context the calculation context
  361. * @return always CURLE_OK
  362. */
  363. static CURLcode
  364. MHDx_sha512_256_init(void *context)
  365. {
  366. struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *) context;
  367. /* Check whether the header and this file use the same numbers */
  368. DEBUGASSERT(CURL_SHA512_256_DIGEST_LENGTH == CURL_SHA512_256_DIGEST_SIZE);
  369. DEBUGASSERT(sizeof(curl_uint64_t) == 8);
  370. /* Initial hash values, see FIPS PUB 180-4 section 5.3.6.2 */
  371. /* Values generated by "IV Generation Function" as described in
  372. * section 5.3.6 */
  373. ctx->H[0] = CURL_UINT64_C(0x22312194FC2BF72C);
  374. ctx->H[1] = CURL_UINT64_C(0x9F555FA3C84C64C2);
  375. ctx->H[2] = CURL_UINT64_C(0x2393B86B6F53B151);
  376. ctx->H[3] = CURL_UINT64_C(0x963877195940EABD);
  377. ctx->H[4] = CURL_UINT64_C(0x96283EE2A88EFFE3);
  378. ctx->H[5] = CURL_UINT64_C(0xBE5E1E2553863992);
  379. ctx->H[6] = CURL_UINT64_C(0x2B0199FC2C85B8AA);
  380. ctx->H[7] = CURL_UINT64_C(0x0EB72DDC81C52CA2);
  381. /* Initialise number of bytes and high part of number of bits. */
  382. ctx->count = CURL_UINT64_C(0);
  383. ctx->count_bits_hi = CURL_UINT64_C(0);
  384. return CURLE_OK;
  385. }
  386. /**
  387. * Base of the SHA-512/256 transformation.
  388. * Gets a full 128 bytes block of data and updates hash values;
  389. * @param H hash values
  390. * @param data the data buffer with #CURL_SHA512_256_BLOCK_SIZE bytes block
  391. */
  392. static void
  393. MHDx_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS],
  394. const void *data)
  395. {
  396. /* Working variables,
  397. see FIPS PUB 180-4 section 6.7, 6.4. */
  398. curl_uint64_t a = H[0];
  399. curl_uint64_t b = H[1];
  400. curl_uint64_t c = H[2];
  401. curl_uint64_t d = H[3];
  402. curl_uint64_t e = H[4];
  403. curl_uint64_t f = H[5];
  404. curl_uint64_t g = H[6];
  405. curl_uint64_t h = H[7];
  406. /* Data buffer, used as a cyclic buffer.
  407. See FIPS PUB 180-4 section 5.2.2, 6.7, 6.4. */
  408. curl_uint64_t W[16];
  409. /* 'Ch' and 'Maj' macro functions are defined with widely-used optimization.
  410. See FIPS PUB 180-4 formulae 4.8, 4.9. */
  411. #define Sha512_Ch(x,y,z) ( (z) ^ ((x) & ((y) ^ (z))) )
  412. #define Sha512_Maj(x,y,z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) )
  413. /* Four 'Sigma' macro functions.
  414. See FIPS PUB 180-4 formulae 4.10, 4.11, 4.12, 4.13. */
  415. #define SIG0(x) \
  416. ( MHDx_rotr64((x), 28) ^ MHDx_rotr64((x), 34) ^ MHDx_rotr64((x), 39) )
  417. #define SIG1(x) \
  418. ( MHDx_rotr64((x), 14) ^ MHDx_rotr64((x), 18) ^ MHDx_rotr64((x), 41) )
  419. #define sig0(x) \
  420. ( MHDx_rotr64((x), 1) ^ MHDx_rotr64((x), 8) ^ ((x) >> 7) )
  421. #define sig1(x) \
  422. ( MHDx_rotr64((x), 19) ^ MHDx_rotr64((x), 61) ^ ((x) >> 6) )
  423. if(1) {
  424. unsigned int t;
  425. /* K constants array.
  426. See FIPS PUB 180-4 section 4.2.3 for K values. */
  427. static const curl_uint64_t K[80] = {
  428. CURL_UINT64_C(0x428a2f98d728ae22), CURL_UINT64_C(0x7137449123ef65cd),
  429. CURL_UINT64_C(0xb5c0fbcfec4d3b2f), CURL_UINT64_C(0xe9b5dba58189dbbc),
  430. CURL_UINT64_C(0x3956c25bf348b538), CURL_UINT64_C(0x59f111f1b605d019),
  431. CURL_UINT64_C(0x923f82a4af194f9b), CURL_UINT64_C(0xab1c5ed5da6d8118),
  432. CURL_UINT64_C(0xd807aa98a3030242), CURL_UINT64_C(0x12835b0145706fbe),
  433. CURL_UINT64_C(0x243185be4ee4b28c), CURL_UINT64_C(0x550c7dc3d5ffb4e2),
  434. CURL_UINT64_C(0x72be5d74f27b896f), CURL_UINT64_C(0x80deb1fe3b1696b1),
  435. CURL_UINT64_C(0x9bdc06a725c71235), CURL_UINT64_C(0xc19bf174cf692694),
  436. CURL_UINT64_C(0xe49b69c19ef14ad2), CURL_UINT64_C(0xefbe4786384f25e3),
  437. CURL_UINT64_C(0x0fc19dc68b8cd5b5), CURL_UINT64_C(0x240ca1cc77ac9c65),
  438. CURL_UINT64_C(0x2de92c6f592b0275), CURL_UINT64_C(0x4a7484aa6ea6e483),
  439. CURL_UINT64_C(0x5cb0a9dcbd41fbd4), CURL_UINT64_C(0x76f988da831153b5),
  440. CURL_UINT64_C(0x983e5152ee66dfab), CURL_UINT64_C(0xa831c66d2db43210),
  441. CURL_UINT64_C(0xb00327c898fb213f), CURL_UINT64_C(0xbf597fc7beef0ee4),
  442. CURL_UINT64_C(0xc6e00bf33da88fc2), CURL_UINT64_C(0xd5a79147930aa725),
  443. CURL_UINT64_C(0x06ca6351e003826f), CURL_UINT64_C(0x142929670a0e6e70),
  444. CURL_UINT64_C(0x27b70a8546d22ffc), CURL_UINT64_C(0x2e1b21385c26c926),
  445. CURL_UINT64_C(0x4d2c6dfc5ac42aed), CURL_UINT64_C(0x53380d139d95b3df),
  446. CURL_UINT64_C(0x650a73548baf63de), CURL_UINT64_C(0x766a0abb3c77b2a8),
  447. CURL_UINT64_C(0x81c2c92e47edaee6), CURL_UINT64_C(0x92722c851482353b),
  448. CURL_UINT64_C(0xa2bfe8a14cf10364), CURL_UINT64_C(0xa81a664bbc423001),
  449. CURL_UINT64_C(0xc24b8b70d0f89791), CURL_UINT64_C(0xc76c51a30654be30),
  450. CURL_UINT64_C(0xd192e819d6ef5218), CURL_UINT64_C(0xd69906245565a910),
  451. CURL_UINT64_C(0xf40e35855771202a), CURL_UINT64_C(0x106aa07032bbd1b8),
  452. CURL_UINT64_C(0x19a4c116b8d2d0c8), CURL_UINT64_C(0x1e376c085141ab53),
  453. CURL_UINT64_C(0x2748774cdf8eeb99), CURL_UINT64_C(0x34b0bcb5e19b48a8),
  454. CURL_UINT64_C(0x391c0cb3c5c95a63), CURL_UINT64_C(0x4ed8aa4ae3418acb),
  455. CURL_UINT64_C(0x5b9cca4f7763e373), CURL_UINT64_C(0x682e6ff3d6b2b8a3),
  456. CURL_UINT64_C(0x748f82ee5defb2fc), CURL_UINT64_C(0x78a5636f43172f60),
  457. CURL_UINT64_C(0x84c87814a1f0ab72), CURL_UINT64_C(0x8cc702081a6439ec),
  458. CURL_UINT64_C(0x90befffa23631e28), CURL_UINT64_C(0xa4506cebde82bde9),
  459. CURL_UINT64_C(0xbef9a3f7b2c67915), CURL_UINT64_C(0xc67178f2e372532b),
  460. CURL_UINT64_C(0xca273eceea26619c), CURL_UINT64_C(0xd186b8c721c0c207),
  461. CURL_UINT64_C(0xeada7dd6cde0eb1e), CURL_UINT64_C(0xf57d4f7fee6ed178),
  462. CURL_UINT64_C(0x06f067aa72176fba), CURL_UINT64_C(0x0a637dc5a2c898a6),
  463. CURL_UINT64_C(0x113f9804bef90dae), CURL_UINT64_C(0x1b710b35131c471b),
  464. CURL_UINT64_C(0x28db77f523047d84), CURL_UINT64_C(0x32caab7b40c72493),
  465. CURL_UINT64_C(0x3c9ebe0a15c9bebc), CURL_UINT64_C(0x431d67c49c100d4c),
  466. CURL_UINT64_C(0x4cc5d4becb3e42b6), CURL_UINT64_C(0x597f299cfc657e2a),
  467. CURL_UINT64_C(0x5fcb6fab3ad6faec), CURL_UINT64_C(0x6c44198c4a475817)
  468. };
  469. /* One step of SHA-512/256 computation,
  470. see FIPS PUB 180-4 section 6.4.2 step 3.
  471. * Note: this macro updates working variables in-place, without rotation.
  472. * Note: the first (vH += SIG1(vE) + Ch(vE,vF,vG) + kt + wt) equals T1 in
  473. FIPS PUB 180-4 section 6.4.2 step 3.
  474. the second (vH += SIG0(vA) + Maj(vE,vF,vC) equals T1 + T2 in
  475. FIPS PUB 180-4 section 6.4.2 step 3.
  476. * Note: 'wt' must be used exactly one time in this macro as macro for
  477. 'wt' calculation may change other data as well every time when
  478. used. */
  479. #define SHA2STEP64(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do { \
  480. (vD) += ((vH) += SIG1((vE)) + Sha512_Ch((vE),(vF),(vG)) + (kt) + (wt)); \
  481. (vH) += SIG0((vA)) + Sha512_Maj((vA),(vB),(vC)); } while (0)
  482. /* One step of SHA-512/256 computation with working variables rotation,
  483. see FIPS PUB 180-4 section 6.4.2 step 3. This macro version reassigns
  484. all working variables on each step. */
  485. #define SHA2STEP64RV(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do { \
  486. curl_uint64_t tmp_h_ = (vH); \
  487. SHA2STEP64((vA),(vB),(vC),(vD),(vE),(vF),(vG),tmp_h_,(kt),(wt)); \
  488. (vH) = (vG); \
  489. (vG) = (vF); \
  490. (vF) = (vE); \
  491. (vE) = (vD); \
  492. (vD) = (vC); \
  493. (vC) = (vB); \
  494. (vB) = (vA); \
  495. (vA) = tmp_h_; } while(0)
  496. /* Get value of W(t) from input data buffer for 0 <= t <= 15,
  497. See FIPS PUB 180-4 section 6.2.
  498. Input data must be read in big-endian bytes order,
  499. see FIPS PUB 180-4 section 3.1.2. */
  500. #define SHA512_GET_W_FROM_DATA(buf,t) \
  501. MHDX_GET_64BIT_BE( \
  502. ((const unsigned char*) (buf)) + (t) * SHA512_256_BYTES_IN_WORD)
  503. /* During first 16 steps, before making any calculation on each step, the
  504. W element is read from the input data buffer as a big-endian value and
  505. stored in the array of W elements. */
  506. for(t = 0; t < 16; ++t) {
  507. SHA2STEP64RV(a, b, c, d, e, f, g, h, K[t], \
  508. W[t] = SHA512_GET_W_FROM_DATA(data, t));
  509. }
  510. /* 'W' generation and assignment for 16 <= t <= 79.
  511. See FIPS PUB 180-4 section 6.4.2.
  512. As only the last 16 'W' are used in calculations, it is possible to
  513. use 16 elements array of W as a cyclic buffer.
  514. Note: ((t-16) & 15) have same value as (t & 15) */
  515. #define Wgen(w,t) \
  516. (curl_uint64_t)( (w)[(t - 16) & 15] + sig1((w)[((t) - 2) & 15]) \
  517. + (w)[((t) - 7) & 15] + sig0((w)[((t) - 15) & 15]) )
  518. /* During the last 64 steps, before making any calculation on each step,
  519. current W element is generated from other W elements of the cyclic
  520. buffer and the generated value is stored back in the cyclic buffer. */
  521. for(t = 16; t < 80; ++t) {
  522. SHA2STEP64RV(a, b, c, d, e, f, g, h, K[t], \
  523. W[t & 15] = Wgen(W, t));
  524. }
  525. }
  526. /* Compute and store the intermediate hash.
  527. See FIPS PUB 180-4 section 6.4.2 step 4. */
  528. H[0] += a;
  529. H[1] += b;
  530. H[2] += c;
  531. H[3] += d;
  532. H[4] += e;
  533. H[5] += f;
  534. H[6] += g;
  535. H[7] += h;
  536. }
  537. /**
  538. * Process portion of bytes.
  539. *
  540. * @param context the calculation context
  541. * @param data bytes to add to hash
  542. * @param length number of bytes in @a data
  543. * @return always CURLE_OK
  544. */
  545. static CURLcode
  546. MHDx_sha512_256_update(void *context,
  547. const unsigned char *data,
  548. size_t length)
  549. {
  550. unsigned int bytes_have; /**< Number of bytes in the context buffer */
  551. struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *)context;
  552. /* the void pointer here is required to mute Intel compiler warning */
  553. void *const ctx_buf = ctx->buffer;
  554. DEBUGASSERT((data != NULL) || (length == 0));
  555. if(0 == length)
  556. return CURLE_OK; /* Shortcut, do nothing */
  557. /* Note: (count & (CURL_SHA512_256_BLOCK_SIZE-1))
  558. equals (count % CURL_SHA512_256_BLOCK_SIZE) for this block size. */
  559. bytes_have = (unsigned int) (ctx->count & (CURL_SHA512_256_BLOCK_SIZE - 1));
  560. ctx->count += length;
  561. if(length > ctx->count)
  562. ctx->count_bits_hi += 1U << 3; /* Value wrap */
  563. ctx->count_bits_hi += ctx->count >> 61;
  564. ctx->count &= CURL_UINT64_C(0x1FFFFFFFFFFFFFFF);
  565. if(0 != bytes_have) {
  566. unsigned int bytes_left = CURL_SHA512_256_BLOCK_SIZE - bytes_have;
  567. if(length >= bytes_left) {
  568. /* Combine new data with data in the buffer and process the full
  569. block. */
  570. memcpy(((unsigned char *) ctx_buf) + bytes_have,
  571. data,
  572. bytes_left);
  573. data += bytes_left;
  574. length -= bytes_left;
  575. MHDx_sha512_256_transform(ctx->H, ctx->buffer);
  576. bytes_have = 0;
  577. }
  578. }
  579. while(CURL_SHA512_256_BLOCK_SIZE <= length) {
  580. /* Process any full blocks of new data directly,
  581. without copying to the buffer. */
  582. MHDx_sha512_256_transform(ctx->H, data);
  583. data += CURL_SHA512_256_BLOCK_SIZE;
  584. length -= CURL_SHA512_256_BLOCK_SIZE;
  585. }
  586. if(0 != length) {
  587. /* Copy incomplete block of new data (if any)
  588. to the buffer. */
  589. memcpy(((unsigned char *) ctx_buf) + bytes_have, data, length);
  590. }
  591. return CURLE_OK;
  592. }
  593. /**
  594. * Size of "length" insertion in bits.
  595. * See FIPS PUB 180-4 section 5.1.2.
  596. */
  597. #define SHA512_256_SIZE_OF_LEN_ADD_BITS 128
  598. /**
  599. * Size of "length" insertion in bytes.
  600. */
  601. #define SHA512_256_SIZE_OF_LEN_ADD (SHA512_256_SIZE_OF_LEN_ADD_BITS / 8)
  602. /**
  603. * Finalise SHA-512/256 calculation, return digest.
  604. *
  605. * @param context the calculation context
  606. * @param[out] digest set to the hash, must be #CURL_SHA512_256_DIGEST_SIZE
  607. # bytes
  608. * @return always CURLE_OK
  609. */
  610. static CURLcode
  611. MHDx_sha512_256_finish(unsigned char *digest,
  612. void *context)
  613. {
  614. struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *)context;
  615. curl_uint64_t num_bits; /**< Number of processed bits */
  616. unsigned int bytes_have; /**< Number of bytes in the context buffer */
  617. /* the void pointer here is required to mute Intel compiler warning */
  618. void *const ctx_buf = ctx->buffer;
  619. /* Memorise the number of processed bits.
  620. The padding and other data added here during the postprocessing must
  621. not change the amount of hashed data. */
  622. num_bits = ctx->count << 3;
  623. /* Note: (count & (CURL_SHA512_256_BLOCK_SIZE-1))
  624. equals (count % CURL_SHA512_256_BLOCK_SIZE) for this block size. */
  625. bytes_have = (unsigned int) (ctx->count & (CURL_SHA512_256_BLOCK_SIZE - 1));
  626. /* Input data must be padded with a single bit "1", then with zeros and
  627. the finally the length of data in bits must be added as the final bytes
  628. of the last block.
  629. See FIPS PUB 180-4 section 5.1.2. */
  630. /* Data is always processed in form of bytes (not by individual bits),
  631. therefore position of the first padding bit in byte is always
  632. predefined (0x80). */
  633. /* Buffer always have space at least for one byte (as full buffers are
  634. processed when formed). */
  635. ((unsigned char *) ctx_buf)[bytes_have++] = 0x80U;
  636. if(CURL_SHA512_256_BLOCK_SIZE - bytes_have < SHA512_256_SIZE_OF_LEN_ADD) {
  637. /* No space in the current block to put the total length of message.
  638. Pad the current block with zeros and process it. */
  639. if(bytes_have < CURL_SHA512_256_BLOCK_SIZE)
  640. memset(((unsigned char *) ctx_buf) + bytes_have, 0,
  641. CURL_SHA512_256_BLOCK_SIZE - bytes_have);
  642. /* Process the full block. */
  643. MHDx_sha512_256_transform(ctx->H, ctx->buffer);
  644. /* Start the new block. */
  645. bytes_have = 0;
  646. }
  647. /* Pad the rest of the buffer with zeros. */
  648. memset(((unsigned char *) ctx_buf) + bytes_have, 0,
  649. CURL_SHA512_256_BLOCK_SIZE - SHA512_256_SIZE_OF_LEN_ADD - bytes_have);
  650. /* Put high part of number of bits in processed message and then lower
  651. part of number of bits as big-endian values.
  652. See FIPS PUB 180-4 section 5.1.2. */
  653. /* Note: the target location is predefined and buffer is always aligned */
  654. MHDX_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
  655. + CURL_SHA512_256_BLOCK_SIZE \
  656. - SHA512_256_SIZE_OF_LEN_ADD, \
  657. ctx->count_bits_hi);
  658. MHDX_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
  659. + CURL_SHA512_256_BLOCK_SIZE \
  660. - SHA512_256_SIZE_OF_LEN_ADD \
  661. + SHA512_256_BYTES_IN_WORD, \
  662. num_bits);
  663. /* Process the full final block. */
  664. MHDx_sha512_256_transform(ctx->H, ctx->buffer);
  665. /* Put in BE mode the leftmost part of the hash as the final digest.
  666. See FIPS PUB 180-4 section 6.7. */
  667. MHDX_PUT_64BIT_BE((digest + 0 * SHA512_256_BYTES_IN_WORD), ctx->H[0]);
  668. MHDX_PUT_64BIT_BE((digest + 1 * SHA512_256_BYTES_IN_WORD), ctx->H[1]);
  669. MHDX_PUT_64BIT_BE((digest + 2 * SHA512_256_BYTES_IN_WORD), ctx->H[2]);
  670. MHDX_PUT_64BIT_BE((digest + 3 * SHA512_256_BYTES_IN_WORD), ctx->H[3]);
  671. /* Erase potentially sensitive data. */
  672. memset(ctx, 0, sizeof(struct mhdx_sha512_256ctx));
  673. return CURLE_OK;
  674. }
  675. /* Map to the local implementation */
  676. #define Curl_sha512_256_init MHDx_sha512_256_init
  677. #define Curl_sha512_256_update MHDx_sha512_256_update
  678. #define Curl_sha512_256_finish MHDx_sha512_256_finish
  679. #endif /* Local SHA-512/256 code */
  680. /**
  681. * Compute SHA-512/256 hash for the given data in one function call
  682. * @param[out] output the pointer to put the hash
  683. * @param[in] input the pointer to the data to process
  684. * @param input_size the size of the data pointed by @a input
  685. * @return always #CURLE_OK
  686. */
  687. CURLcode
  688. Curl_sha512_256it(unsigned char *output, const unsigned char *input,
  689. size_t input_size)
  690. {
  691. Curl_sha512_256_ctx ctx;
  692. CURLcode res;
  693. res = Curl_sha512_256_init(&ctx);
  694. if(res != CURLE_OK)
  695. return res;
  696. res = Curl_sha512_256_update(&ctx, (const void *) input, input_size);
  697. if(res != CURLE_OK) {
  698. (void) Curl_sha512_256_finish(output, &ctx);
  699. return res;
  700. }
  701. return Curl_sha512_256_finish(output, &ctx);
  702. }
  703. /* Wrapper function, takes 'unsigned int' as length type, returns void */
  704. static void
  705. Curl_sha512_256_update_i(void *context,
  706. const unsigned char *data,
  707. unsigned int length)
  708. {
  709. /* Hypothetically the function may fail, but assume it does not */
  710. (void) Curl_sha512_256_update(context, data, length);
  711. }
  712. /* Wrapper function, returns void */
  713. static void
  714. Curl_sha512_256_finish_v(unsigned char *result,
  715. void *context)
  716. {
  717. /* Hypothetically the function may fail, but assume it does not */
  718. (void) Curl_sha512_256_finish(result, context);
  719. }
  720. /* Wrapper function, takes 'unsigned int' as length type, returns void */
  721. const struct HMAC_params Curl_HMAC_SHA512_256[] = {
  722. {
  723. /* Initialize context procedure. */
  724. Curl_sha512_256_init,
  725. /* Update context with data. */
  726. Curl_sha512_256_update_i,
  727. /* Get final result procedure. */
  728. Curl_sha512_256_finish_v,
  729. /* Context structure size. */
  730. sizeof(Curl_sha512_256_ctx),
  731. /* Maximum key length (bytes). */
  732. CURL_SHA512_256_BLOCK_SIZE,
  733. /* Result length (bytes). */
  734. CURL_SHA512_256_DIGEST_SIZE
  735. }
  736. };
  737. #endif /* !CURL_DISABLE_DIGEST_AUTH && !CURL_DISABLE_SHA512_256 */