Coverage Report

Created: 2026-06-15 07:03

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