Coverage Report

Created: 2025-07-11 06:33

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