Coverage Report

Created: 2026-07-16 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/curl/lib/sha256.c
Line
Count
Source
1
/***************************************************************************
2
 *                                  _   _ ____  _
3
 *  Project                     ___| | | |  _ \| |
4
 *                             / __| | | | |_) | |
5
 *                            | (__| |_| |  _ <| |___
6
 *                             \___|\___/|_| \_\_____|
7
 *
8
 * Copyright (C) Florin Petriuc, <petriuc.florin@gmail.com>
9
 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
10
 *
11
 * This software is licensed as described in the file COPYING, which
12
 * you should have received as part of this distribution. The terms
13
 * are also available at https://curl.se/docs/copyright.html.
14
 *
15
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
16
 * copies of the Software, and permit persons to whom the Software is
17
 * furnished to do so, under the terms of the COPYING file.
18
 *
19
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20
 * KIND, either express or implied.
21
 *
22
 * SPDX-License-Identifier: curl
23
 *
24
 ***************************************************************************/
25
#include "curl_setup.h"
26
27
#if !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) || \
28
  defined(USE_LIBSSH2) || defined(USE_SSL)
29
30
#include "curl_sha256.h"
31
32
#ifdef USE_MBEDTLS
33
#include <mbedtls/version.h>
34
#if MBEDTLS_VERSION_NUMBER < 0x03020000
35
#error "mbedTLS 3.2.0 or later required"
36
#endif
37
#include <psa/crypto_config.h>
38
#endif
39
40
/* Please keep the SSL backend-specific #if branches in this order:
41
 *
42
 * 1. USE_OPENSSL
43
 * 2. USE_WOLFSSL
44
 * 3. USE_GNUTLS
45
 * 4. USE_MBEDTLS
46
 * 5. USE_WIN32_CRYPTO
47
 * 6. USE_COMMON_CRYPTO
48
 *
49
 * This ensures that the same SSL branch gets activated throughout this source
50
 * file even if multiple backends are enabled at the same time.
51
 */
52
53
#ifdef USE_OPENSSL
54
#include <openssl/evp.h>
55
56
struct ossl_sha256_ctx {
57
  EVP_MD_CTX *openssl_ctx;
58
};
59
typedef struct ossl_sha256_ctx my_sha256_ctx;
60
61
static CURLcode my_sha256_init(void *in)
62
0
{
63
0
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
64
0
  ctx->openssl_ctx = EVP_MD_CTX_new();
65
0
  if(!ctx->openssl_ctx)
66
0
    return CURLE_OUT_OF_MEMORY;
67
68
0
  if(!EVP_DigestInit_ex(ctx->openssl_ctx, EVP_sha256(), NULL)) {
69
0
    EVP_MD_CTX_free(ctx->openssl_ctx);
70
0
    return CURLE_FAILED_INIT;
71
0
  }
72
0
  return CURLE_OK;
73
0
}
74
75
static void my_sha256_update(void *in,
76
                             const unsigned char *data,
77
                             unsigned int length)
78
0
{
79
0
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
80
0
  EVP_DigestUpdate(ctx->openssl_ctx, data, length);
81
0
}
82
83
static void my_sha256_final(unsigned char *digest, void *in)
84
0
{
85
0
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
86
0
  EVP_DigestFinal_ex(ctx->openssl_ctx, digest, NULL);
87
0
  EVP_MD_CTX_free(ctx->openssl_ctx);
88
0
}
89
90
#elif defined(USE_WOLFSSL)
91
#include <wolfssl/options.h>
92
#include <wolfssl/wolfcrypt/sha256.h>
93
94
typedef struct wc_Sha256 my_sha256_ctx;
95
96
static CURLcode my_sha256_init(void *in)
97
{
98
  if(wc_InitSha256(in))
99
    return CURLE_FAILED_INIT;
100
  return CURLE_OK;
101
}
102
103
static void my_sha256_update(void *in,
104
                             const unsigned char *data,
105
                             unsigned int length)
106
{
107
  (void)wc_Sha256Update(in, data, (word32)length);
108
}
109
110
static void my_sha256_final(unsigned char *digest, void *in)
111
{
112
  (void)wc_Sha256Final(in, digest);
113
}
114
115
#elif defined(USE_GNUTLS)
116
#include <nettle/sha2.h>
117
#include <nettle/version.h>
118
119
typedef struct sha256_ctx my_sha256_ctx;
120
121
static CURLcode my_sha256_init(void *ctx)
122
{
123
  sha256_init(ctx);
124
  return CURLE_OK;
125
}
126
127
static void my_sha256_update(void *ctx,
128
                             const unsigned char *data,
129
                             unsigned int length)
130
{
131
  sha256_update(ctx, length, data);
132
}
133
134
static void my_sha256_final(unsigned char *digest, void *ctx)
135
{
136
#if NETTLE_VERSION_MAJOR >= 4
137
  sha256_digest(ctx, digest);
138
#else
139
  sha256_digest(ctx, SHA256_DIGEST_SIZE, digest);
140
#endif
141
}
142
143
#elif defined(USE_MBEDTLS) && \
144
  defined(PSA_WANT_ALG_SHA_256) && PSA_WANT_ALG_SHA_256
145
#include <psa/crypto.h>
146
147
typedef psa_hash_operation_t my_sha256_ctx;
148
149
static CURLcode my_sha256_init(void *ctx)
150
{
151
  psa_hash_operation_t *pctx = (psa_hash_operation_t *)ctx;
152
  *pctx = psa_hash_operation_init();
153
  if(psa_hash_setup(pctx, PSA_ALG_SHA_256) != PSA_SUCCESS)
154
    return CURLE_OUT_OF_MEMORY;
155
  return CURLE_OK;
156
}
157
158
static void my_sha256_update(void *ctx,
159
                             const unsigned char *data,
160
                             unsigned int length)
161
{
162
  (void)psa_hash_update(ctx, data, length);
163
}
164
165
static void my_sha256_final(unsigned char *digest, void *ctx)
166
{
167
  size_t actual_length;
168
  (void)psa_hash_finish(ctx, digest, CURL_SHA256_DIGEST_LENGTH,
169
                        &actual_length);
170
}
171
172
#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
173
              (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
174
      (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
175
              (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
176
#include <CommonCrypto/CommonDigest.h>
177
178
typedef CC_SHA256_CTX my_sha256_ctx;
179
180
static CURLcode my_sha256_init(void *ctx)
181
{
182
  (void)CC_SHA256_Init(ctx);
183
  return CURLE_OK;
184
}
185
186
static void my_sha256_update(void *ctx,
187
                             const unsigned char *data,
188
                             unsigned int length)
189
{
190
  (void)CC_SHA256_Update(ctx, data, length);
191
}
192
193
static void my_sha256_final(unsigned char *digest, void *ctx)
194
{
195
  (void)CC_SHA256_Final(digest, ctx);
196
}
197
198
#elif defined(USE_WIN32_CRYPTO)
199
#include <wincrypt.h>
200
201
struct sha256_ctx {
202
  HCRYPTPROV hCryptProv;
203
  HCRYPTHASH hHash;
204
};
205
typedef struct sha256_ctx my_sha256_ctx;
206
207
static CURLcode my_sha256_init(void *in)
208
{
209
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
210
  if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_AES,
211
                          CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
212
    return CURLE_OUT_OF_MEMORY;
213
214
  if(!CryptCreateHash(ctx->hCryptProv, CALG_SHA_256, 0, 0, &ctx->hHash)) {
215
    CryptReleaseContext(ctx->hCryptProv, 0);
216
    ctx->hCryptProv = 0;
217
    return CURLE_FAILED_INIT;
218
  }
219
220
  return CURLE_OK;
221
}
222
223
static void my_sha256_update(void *in,
224
                             const unsigned char *data,
225
                             unsigned int length)
226
{
227
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
228
  CryptHashData(ctx->hHash, (const BYTE *)data, length, 0);
229
}
230
231
static void my_sha256_final(unsigned char *digest, void *in)
232
{
233
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
234
  unsigned long length = 0;
235
236
  CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
237
  if(length == CURL_SHA256_DIGEST_LENGTH)
238
    CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0);
239
240
  if(ctx->hHash)
241
    CryptDestroyHash(ctx->hHash);
242
243
  if(ctx->hCryptProv)
244
    CryptReleaseContext(ctx->hCryptProv, 0);
245
}
246
247
#else
248
249
/* When no other crypto library is available we use this code segment */
250
251
/* This is based on the SHA256 implementation in LibTomCrypt that was released
252
 * into public domain. */
253
254
#define WPA_GET_BE32(a)              \
255
  ((((unsigned long)(a)[0]) << 24) | \
256
   (((unsigned long)(a)[1]) << 16) | \
257
   (((unsigned long)(a)[2]) <<  8) | \
258
    ((unsigned long)(a)[3]))
259
#define WPA_PUT_BE32(a, val)                                         \
260
  do {                                                               \
261
    (a)[0] = (unsigned char)((((unsigned long)(val)) >> 24) & 0xff); \
262
    (a)[1] = (unsigned char)((((unsigned long)(val)) >> 16) & 0xff); \
263
    (a)[2] = (unsigned char)((((unsigned long)(val)) >>  8) & 0xff); \
264
    (a)[3] = (unsigned char)(((unsigned long)(val)) & 0xff);         \
265
  } while(0)
266
267
#define WPA_PUT_BE64(a, val)                            \
268
  do {                                                  \
269
    (a)[0] = (unsigned char)(((uint64_t)(val)) >> 56);  \
270
    (a)[1] = (unsigned char)(((uint64_t)(val)) >> 48);  \
271
    (a)[2] = (unsigned char)(((uint64_t)(val)) >> 40);  \
272
    (a)[3] = (unsigned char)(((uint64_t)(val)) >> 32);  \
273
    (a)[4] = (unsigned char)(((uint64_t)(val)) >> 24);  \
274
    (a)[5] = (unsigned char)(((uint64_t)(val)) >> 16);  \
275
    (a)[6] = (unsigned char)(((uint64_t)(val)) >>  8);  \
276
    (a)[7] = (unsigned char)(((uint64_t)(val)) & 0xff); \
277
  } while(0)
278
279
struct sha256_state {
280
  uint64_t length;
281
  unsigned long state[8], curlen;
282
  unsigned char buf[64];
283
};
284
typedef struct sha256_state my_sha256_ctx;
285
286
/* The K array */
287
static const unsigned long K[64] = {
288
  0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
289
  0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
290
  0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
291
  0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
292
  0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
293
  0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
294
  0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
295
  0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
296
  0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
297
  0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
298
  0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
299
  0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
300
  0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
301
};
302
303
/* Various logical functions */
304
#define RORc(x, y) \
305
  (((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | \
306
     ((unsigned long)(x) << (unsigned long)(32 - ((y) & 31)))) & 0xFFFFFFFFUL)
307
308
#define Sha256_Ch(x, y, z)  (z ^ (x & (y ^ z)))
309
#define Sha256_Maj(x, y, z) (((x | y) & z) | (x & y))
310
#define Sha256_S(x, n)      RORc(x, n)
311
#define Sha256_R(x, n)      (((x) & 0xFFFFFFFFUL) >> (n))
312
313
#define Sigma0(x)         (Sha256_S(x, 2) ^ Sha256_S(x, 13) ^ Sha256_S(x, 22))
314
#define Sigma1(x)         (Sha256_S(x, 6) ^ Sha256_S(x, 11) ^ Sha256_S(x, 25))
315
#define Gamma0(x)         (Sha256_S(x, 7) ^ Sha256_S(x, 18) ^ Sha256_R(x, 3))
316
#define Gamma1(x)         (Sha256_S(x, 17) ^ Sha256_S(x, 19) ^ Sha256_R(x, 10))
317
318
/* Compress 512 bits */
319
static int sha256_compress(struct sha256_state *md, const unsigned char *buf)
320
{
321
  unsigned long S[8], W[64];
322
  int i;
323
324
  /* Copy state into S */
325
  for(i = 0; i < 8; i++) {
326
    S[i] = md->state[i];
327
  }
328
  /* copy the state into 512 bits into W[0..15] */
329
  for(i = 0; i < 16; i++)
330
    W[i] = WPA_GET_BE32(buf + (4 * i));
331
  /* fill W[16..63] */
332
  for(i = 16; i < 64; i++) {
333
    W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
334
  }
335
336
  /* Compress */
337
#define RND(a, b, c, d, e, f, g, h, i)                                   \
338
  do {                                                                   \
339
    unsigned long t0 = h + Sigma1(e) + Sha256_Ch(e, f, g) + K[i] + W[i]; \
340
    unsigned long t1 = Sigma0(a) + Sha256_Maj(a, b, c);                  \
341
    d += t0;                                                             \
342
    h = t0 + t1;                                                         \
343
  } while(0)
344
345
  for(i = 0; i < 64; ++i) {
346
    unsigned long t;
347
    RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
348
    t = S[7];
349
    S[7] = S[6];
350
    S[6] = S[5];
351
    S[5] = S[4];
352
    S[4] = S[3];
353
    S[3] = S[2];
354
    S[2] = S[1];
355
    S[1] = S[0];
356
    S[0] = t;
357
  }
358
359
  /* Feedback */
360
  for(i = 0; i < 8; i++) {
361
    md->state[i] = md->state[i] + S[i];
362
  }
363
364
  return 0;
365
}
366
367
/* Initialize the hash state */
368
static CURLcode my_sha256_init(void *in)
369
{
370
  struct sha256_state *md = (struct sha256_state *)in;
371
  md->curlen = 0;
372
  md->length = 0;
373
  md->state[0] = 0x6A09E667UL;
374
  md->state[1] = 0xBB67AE85UL;
375
  md->state[2] = 0x3C6EF372UL;
376
  md->state[3] = 0xA54FF53AUL;
377
  md->state[4] = 0x510E527FUL;
378
  md->state[5] = 0x9B05688CUL;
379
  md->state[6] = 0x1F83D9ABUL;
380
  md->state[7] = 0x5BE0CD19UL;
381
382
  return CURLE_OK;
383
}
384
385
/*
386
   Process a block of memory though the hash
387
   @param md     The hash state
388
   @param in     The data to hash
389
   @param inlen  The length of the data (octets)
390
*/
391
static void my_sha256_update(void *ctx,
392
                             const unsigned char *in,
393
                             unsigned int len)
394
{
395
  unsigned long inlen = len;
396
  unsigned long n;
397
  struct sha256_state *md = (struct sha256_state *)ctx;
398
#define CURL_SHA256_BLOCK_SIZE 64
399
  if(md->curlen > sizeof(md->buf))
400
    return;
401
  while(inlen > 0) {
402
    if(md->curlen == 0 && inlen >= CURL_SHA256_BLOCK_SIZE) {
403
      if(sha256_compress(md, in) < 0)
404
        return;
405
      md->length += CURL_SHA256_BLOCK_SIZE * 8;
406
      in += CURL_SHA256_BLOCK_SIZE;
407
      inlen -= CURL_SHA256_BLOCK_SIZE;
408
    }
409
    else {
410
      n = CURLMIN(inlen, (CURL_SHA256_BLOCK_SIZE - md->curlen));
411
      memcpy(md->buf + md->curlen, in, n);
412
      md->curlen += n;
413
      in += n;
414
      inlen -= n;
415
      if(md->curlen == CURL_SHA256_BLOCK_SIZE) {
416
        if(sha256_compress(md, md->buf) < 0)
417
          return;
418
        md->length += 8 * CURL_SHA256_BLOCK_SIZE;
419
        md->curlen = 0;
420
      }
421
    }
422
  }
423
}
424
425
/*
426
   Terminate the hash to get the digest
427
   @param md  The hash state
428
   @param out [out] The destination of the hash (32 bytes)
429
   @return 0 if successful
430
*/
431
static void my_sha256_final(unsigned char *out, void *ctx)
432
{
433
  struct sha256_state *md = ctx;
434
  int i;
435
436
  if(md->curlen >= sizeof(md->buf))
437
    return;
438
439
  /* Increase the length of the message */
440
  md->length += md->curlen * 8;
441
442
  /* Append the '1' bit */
443
  md->buf[md->curlen++] = (unsigned char)0x80;
444
445
  /* If the length is currently above 56 bytes we append zeros
446
   * then compress. Then we can fall back to padding zeros and length
447
   * encoding like normal.
448
   */
449
  if(md->curlen > 56) {
450
    while(md->curlen < 64) {
451
      md->buf[md->curlen++] = 0;
452
    }
453
    sha256_compress(md, md->buf);
454
    md->curlen = 0;
455
  }
456
457
  /* Pad up to 56 bytes of zeroes */
458
  while(md->curlen < 56) {
459
    md->buf[md->curlen++] = 0;
460
  }
461
462
  /* Store length */
463
  WPA_PUT_BE64(md->buf + 56, md->length);
464
  sha256_compress(md, md->buf);
465
466
  /* Copy output */
467
  for(i = 0; i < 8; i++)
468
    WPA_PUT_BE32(out + (4 * i), md->state[i]);
469
}
470
471
#endif /* CRYPTO LIBS */
472
473
/*
474
 * Curl_sha256it()
475
 *
476
 * Generates a SHA256 hash for the given input data.
477
 *
478
 * Parameters:
479
 *
480
 * output [in/out] - The output buffer.
481
 * input  [in]     - The input data.
482
 * length [in]     - The input length.
483
 *
484
 * Returns CURLE_OK on success.
485
 */
486
CURLcode Curl_sha256it(unsigned char *output, const unsigned char *input,
487
                       size_t len)
488
0
{
489
0
  CURLcode result;
490
0
  my_sha256_ctx ctx;
491
492
0
  result = my_sha256_init(&ctx);
493
0
  if(!result) {
494
0
    do {
495
0
      unsigned int ilen = (unsigned int)CURLMIN(len, UINT_MAX);
496
0
      my_sha256_update(&ctx, input, ilen);
497
0
      len -= ilen;
498
0
      input += ilen;
499
0
    } while(len);
500
0
    my_sha256_final(output, &ctx);
501
0
  }
502
0
  return result;
503
0
}
504
505
const struct HMAC_params Curl_HMAC_SHA256 = {
506
  my_sha256_init,        /* Hash initialization function. */
507
  my_sha256_update,      /* Hash update function. */
508
  my_sha256_final,       /* Hash computation end function. */
509
  sizeof(my_sha256_ctx), /* Size of hash context structure. */
510
  64,                    /* Maximum key length. */
511
  32                     /* Result size. */
512
};
513
514
#endif /* AWS, DIGEST, or libssh2 */