Coverage Report

Created: 2026-07-14 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Utilities/cmcurl/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
{
63
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
64
  ctx->openssl_ctx = EVP_MD_CTX_create();
65
  if(!ctx->openssl_ctx)
66
    return CURLE_OUT_OF_MEMORY;
67
68
  if(!EVP_DigestInit_ex(ctx->openssl_ctx, EVP_sha256(), NULL)) {
69
    EVP_MD_CTX_destroy(ctx->openssl_ctx);
70
    return CURLE_FAILED_INIT;
71
  }
72
  return CURLE_OK;
73
}
74
75
static void my_sha256_update(void *in,
76
                             const unsigned char *data,
77
                             unsigned int length)
78
{
79
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
80
  EVP_DigestUpdate(ctx->openssl_ctx, data, length);
81
}
82
83
static void my_sha256_final(unsigned char *digest, void *in)
84
{
85
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
86
  EVP_DigestFinal_ex(ctx->openssl_ctx, digest, NULL);
87
  EVP_MD_CTX_destroy(ctx->openssl_ctx);
88
}
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
  memset(ctx, 0, sizeof(my_sha256_ctx));
152
  if(psa_hash_setup(ctx, PSA_ALG_SHA_256) != PSA_SUCCESS)
153
    return CURLE_OUT_OF_MEMORY;
154
  return CURLE_OK;
155
}
156
157
static void my_sha256_update(void *ctx,
158
                             const unsigned char *data,
159
                             unsigned int length)
160
{
161
  (void)psa_hash_update(ctx, data, length);
162
}
163
164
static void my_sha256_final(unsigned char *digest, void *ctx)
165
{
166
  size_t actual_length;
167
  (void)psa_hash_finish(ctx, digest, CURL_SHA256_DIGEST_LENGTH,
168
                        &actual_length);
169
}
170
171
#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
172
              (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
173
      (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
174
              (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
175
#include <CommonCrypto/CommonDigest.h>
176
177
typedef CC_SHA256_CTX my_sha256_ctx;
178
179
static CURLcode my_sha256_init(void *ctx)
180
{
181
  (void)CC_SHA256_Init(ctx);
182
  return CURLE_OK;
183
}
184
185
static void my_sha256_update(void *ctx,
186
                             const unsigned char *data,
187
                             unsigned int length)
188
{
189
  (void)CC_SHA256_Update(ctx, data, length);
190
}
191
192
static void my_sha256_final(unsigned char *digest, void *ctx)
193
{
194
  (void)CC_SHA256_Final(digest, ctx);
195
}
196
197
#elif defined(USE_WIN32_CRYPTO)
198
#include <wincrypt.h>
199
200
struct sha256_ctx {
201
  HCRYPTPROV hCryptProv;
202
  HCRYPTHASH hHash;
203
};
204
typedef struct sha256_ctx my_sha256_ctx;
205
206
static CURLcode my_sha256_init(void *in)
207
{
208
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
209
  if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_AES,
210
                          CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
211
    return CURLE_OUT_OF_MEMORY;
212
213
  if(!CryptCreateHash(ctx->hCryptProv, CALG_SHA_256, 0, 0, &ctx->hHash)) {
214
    CryptReleaseContext(ctx->hCryptProv, 0);
215
    ctx->hCryptProv = 0;
216
    return CURLE_FAILED_INIT;
217
  }
218
219
  return CURLE_OK;
220
}
221
222
static void my_sha256_update(void *in,
223
                             const unsigned char *data,
224
                             unsigned int length)
225
{
226
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
227
  CryptHashData(ctx->hHash, (const BYTE *)data, length, 0);
228
}
229
230
static void my_sha256_final(unsigned char *digest, void *in)
231
{
232
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
233
  unsigned long length = 0;
234
235
  CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
236
  if(length == CURL_SHA256_DIGEST_LENGTH)
237
    CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0);
238
239
  if(ctx->hHash)
240
    CryptDestroyHash(ctx->hHash);
241
242
  if(ctx->hCryptProv)
243
    CryptReleaseContext(ctx->hCryptProv, 0);
244
}
245
246
#else
247
248
/* When no other crypto library is available we use this code segment */
249
250
/* This is based on the SHA256 implementation in LibTomCrypt that was released
251
 * into public domain. */
252
253
#define WPA_GET_BE32(a)              \
254
0
  ((((unsigned long)(a)[0]) << 24) | \
255
0
   (((unsigned long)(a)[1]) << 16) | \
256
0
   (((unsigned long)(a)[2]) <<  8) | \
257
0
    ((unsigned long)(a)[3]))
258
#define WPA_PUT_BE32(a, val)                                         \
259
0
  do {                                                               \
260
0
    (a)[0] = (unsigned char)((((unsigned long)(val)) >> 24) & 0xff); \
261
0
    (a)[1] = (unsigned char)((((unsigned long)(val)) >> 16) & 0xff); \
262
0
    (a)[2] = (unsigned char)((((unsigned long)(val)) >>  8) & 0xff); \
263
0
    (a)[3] = (unsigned char)(((unsigned long)(val)) & 0xff);         \
264
0
  } while(0)
265
266
#define WPA_PUT_BE64(a, val)                            \
267
0
  do {                                                  \
268
0
    (a)[0] = (unsigned char)(((uint64_t)(val)) >> 56);  \
269
0
    (a)[1] = (unsigned char)(((uint64_t)(val)) >> 48);  \
270
0
    (a)[2] = (unsigned char)(((uint64_t)(val)) >> 40);  \
271
0
    (a)[3] = (unsigned char)(((uint64_t)(val)) >> 32);  \
272
0
    (a)[4] = (unsigned char)(((uint64_t)(val)) >> 24);  \
273
0
    (a)[5] = (unsigned char)(((uint64_t)(val)) >> 16);  \
274
0
    (a)[6] = (unsigned char)(((uint64_t)(val)) >>  8);  \
275
0
    (a)[7] = (unsigned char)(((uint64_t)(val)) & 0xff); \
276
0
  } while(0)
277
278
struct sha256_state {
279
  uint64_t length;
280
  unsigned long state[8], curlen;
281
  unsigned char buf[64];
282
};
283
typedef struct sha256_state my_sha256_ctx;
284
285
/* The K array */
286
static const unsigned long K[64] = {
287
  0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
288
  0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
289
  0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
290
  0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
291
  0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
292
  0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
293
  0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
294
  0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
295
  0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
296
  0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
297
  0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
298
  0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
299
  0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
300
};
301
302
/* Various logical functions */
303
#define RORc(x, y) \
304
0
  (((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | \
305
0
     ((unsigned long)(x) << (unsigned long)(32 - ((y) & 31)))) & 0xFFFFFFFFUL)
306
307
0
#define Sha256_Ch(x, y, z)  (z ^ (x & (y ^ z)))
308
0
#define Sha256_Maj(x, y, z) (((x | y) & z) | (x & y))
309
0
#define Sha256_S(x, n)      RORc(x, n)
310
0
#define Sha256_R(x, n)      (((x) & 0xFFFFFFFFUL) >> (n))
311
312
0
#define Sigma0(x)         (Sha256_S(x, 2) ^ Sha256_S(x, 13) ^ Sha256_S(x, 22))
313
0
#define Sigma1(x)         (Sha256_S(x, 6) ^ Sha256_S(x, 11) ^ Sha256_S(x, 25))
314
0
#define Gamma0(x)         (Sha256_S(x, 7) ^ Sha256_S(x, 18) ^ Sha256_R(x, 3))
315
0
#define Gamma1(x)         (Sha256_S(x, 17) ^ Sha256_S(x, 19) ^ Sha256_R(x, 10))
316
317
/* Compress 512 bits */
318
static int sha256_compress(struct sha256_state *md, const unsigned char *buf)
319
0
{
320
0
  unsigned long S[8], W[64];
321
0
  int i;
322
323
  /* Copy state into S */
324
0
  for(i = 0; i < 8; i++) {
325
0
    S[i] = md->state[i];
326
0
  }
327
  /* copy the state into 512 bits into W[0..15] */
328
0
  for(i = 0; i < 16; i++)
329
0
    W[i] = WPA_GET_BE32(buf + (4 * i));
330
  /* fill W[16..63] */
331
0
  for(i = 16; i < 64; i++) {
332
0
    W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
333
0
  }
334
335
  /* Compress */
336
0
#define RND(a, b, c, d, e, f, g, h, i)                                   \
337
0
  do {                                                                   \
338
0
    unsigned long t0 = h + Sigma1(e) + Sha256_Ch(e, f, g) + K[i] + W[i]; \
339
0
    unsigned long t1 = Sigma0(a) + Sha256_Maj(a, b, c);                  \
340
0
    d += t0;                                                             \
341
0
    h = t0 + t1;                                                         \
342
0
  } while(0)
343
344
0
  for(i = 0; i < 64; ++i) {
345
0
    unsigned long t;
346
0
    RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
347
0
    t = S[7];
348
0
    S[7] = S[6];
349
0
    S[6] = S[5];
350
0
    S[5] = S[4];
351
0
    S[4] = S[3];
352
0
    S[3] = S[2];
353
0
    S[2] = S[1];
354
0
    S[1] = S[0];
355
0
    S[0] = t;
356
0
  }
357
358
  /* Feedback */
359
0
  for(i = 0; i < 8; i++) {
360
0
    md->state[i] = md->state[i] + S[i];
361
0
  }
362
363
0
  return 0;
364
0
}
365
366
/* Initialize the hash state */
367
static CURLcode my_sha256_init(void *in)
368
0
{
369
0
  struct sha256_state *md = (struct sha256_state *)in;
370
0
  md->curlen = 0;
371
0
  md->length = 0;
372
0
  md->state[0] = 0x6A09E667UL;
373
0
  md->state[1] = 0xBB67AE85UL;
374
0
  md->state[2] = 0x3C6EF372UL;
375
0
  md->state[3] = 0xA54FF53AUL;
376
0
  md->state[4] = 0x510E527FUL;
377
0
  md->state[5] = 0x9B05688CUL;
378
0
  md->state[6] = 0x1F83D9ABUL;
379
0
  md->state[7] = 0x5BE0CD19UL;
380
381
0
  return CURLE_OK;
382
0
}
383
384
/*
385
   Process a block of memory though the hash
386
   @param md     The hash state
387
   @param in     The data to hash
388
   @param inlen  The length of the data (octets)
389
*/
390
static void my_sha256_update(void *ctx,
391
                             const unsigned char *in,
392
                             unsigned int len)
393
0
{
394
0
  unsigned long inlen = len;
395
0
  unsigned long n;
396
0
  struct sha256_state *md = (struct sha256_state *)ctx;
397
0
#define CURL_SHA256_BLOCK_SIZE 64
398
0
  if(md->curlen > sizeof(md->buf))
399
0
    return;
400
0
  while(inlen > 0) {
401
0
    if(md->curlen == 0 && inlen >= CURL_SHA256_BLOCK_SIZE) {
402
0
      if(sha256_compress(md, in) < 0)
403
0
        return;
404
0
      md->length += CURL_SHA256_BLOCK_SIZE * 8;
405
0
      in += CURL_SHA256_BLOCK_SIZE;
406
0
      inlen -= CURL_SHA256_BLOCK_SIZE;
407
0
    }
408
0
    else {
409
0
      n = CURLMIN(inlen, (CURL_SHA256_BLOCK_SIZE - md->curlen));
410
0
      memcpy(md->buf + md->curlen, in, n);
411
0
      md->curlen += n;
412
0
      in += n;
413
0
      inlen -= n;
414
0
      if(md->curlen == CURL_SHA256_BLOCK_SIZE) {
415
0
        if(sha256_compress(md, md->buf) < 0)
416
0
          return;
417
0
        md->length += 8 * CURL_SHA256_BLOCK_SIZE;
418
0
        md->curlen = 0;
419
0
      }
420
0
    }
421
0
  }
422
0
}
423
424
/*
425
   Terminate the hash to get the digest
426
   @param md  The hash state
427
   @param out [out] The destination of the hash (32 bytes)
428
   @return 0 if successful
429
*/
430
static void my_sha256_final(unsigned char *out, void *ctx)
431
0
{
432
0
  struct sha256_state *md = ctx;
433
0
  int i;
434
435
0
  if(md->curlen >= sizeof(md->buf))
436
0
    return;
437
438
  /* Increase the length of the message */
439
0
  md->length += md->curlen * 8;
440
441
  /* Append the '1' bit */
442
0
  md->buf[md->curlen++] = (unsigned char)0x80;
443
444
  /* If the length is currently above 56 bytes we append zeros
445
   * then compress. Then we can fall back to padding zeros and length
446
   * encoding like normal.
447
   */
448
0
  if(md->curlen > 56) {
449
0
    while(md->curlen < 64) {
450
0
      md->buf[md->curlen++] = 0;
451
0
    }
452
0
    sha256_compress(md, md->buf);
453
0
    md->curlen = 0;
454
0
  }
455
456
  /* Pad up to 56 bytes of zeroes */
457
0
  while(md->curlen < 56) {
458
0
    md->buf[md->curlen++] = 0;
459
0
  }
460
461
  /* Store length */
462
0
  WPA_PUT_BE64(md->buf + 56, md->length);
463
0
  sha256_compress(md, md->buf);
464
465
  /* Copy output */
466
0
  for(i = 0; i < 8; i++)
467
0
    WPA_PUT_BE32(out + (4 * i), md->state[i]);
468
0
}
469
470
#endif /* CRYPTO LIBS */
471
472
/*
473
 * Curl_sha256it()
474
 *
475
 * Generates a SHA256 hash for the given input data.
476
 *
477
 * Parameters:
478
 *
479
 * output [in/out] - The output buffer.
480
 * input  [in]     - The input data.
481
 * length [in]     - The input length.
482
 *
483
 * Returns CURLE_OK on success.
484
 */
485
CURLcode Curl_sha256it(unsigned char *output, const unsigned char *input,
486
                       size_t len)
487
0
{
488
0
  CURLcode result;
489
0
  my_sha256_ctx ctx;
490
491
0
  result = my_sha256_init(&ctx);
492
0
  if(!result) {
493
0
    do {
494
0
      unsigned int ilen = (unsigned int)CURLMIN(len, UINT_MAX);
495
0
      my_sha256_update(&ctx, input, ilen);
496
0
      len -= ilen;
497
0
      input += ilen;
498
0
    } while(len);
499
0
    my_sha256_final(output, &ctx);
500
0
  }
501
0
  return result;
502
0
}
503
504
const struct HMAC_params Curl_HMAC_SHA256 = {
505
  my_sha256_init,        /* Hash initialization function. */
506
  my_sha256_update,      /* Hash update function. */
507
  my_sha256_final,       /* Hash computation end function. */
508
  sizeof(my_sha256_ctx), /* Size of hash context structure. */
509
  64,                    /* Maximum key length. */
510
  32                     /* Result size. */
511
};
512
513
#endif /* AWS, DIGEST, or libssh2 */