Coverage Report

Created: 2024-02-25 06:14

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