VirtualBox

source: vbox/trunk/src/libs/curl-8.7.1/lib/curl_sha512_256.c@ 105945

Last change on this file since 105945 was 104204, checked in by vboxsync, 8 months ago

fixing export flags in libs

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette