Coverage Report

Created: 2026-03-12 06:35

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
  #if defined(PSA_WANT_ALG_SHA_256) && PSA_WANT_ALG_SHA_256  /* mbedTLS 4+ */
39
    #define USE_MBEDTLS_SHA256
40
  #endif
41
#endif
42
43
#ifdef USE_OPENSSL
44
#include <openssl/evp.h>
45
#elif defined(USE_GNUTLS)
46
#include <nettle/sha.h>
47
#elif defined(USE_MBEDTLS_SHA256)
48
#include <psa/crypto.h>
49
#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
50
              (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
51
      (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
52
              (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
53
#include <CommonCrypto/CommonDigest.h>
54
#define AN_APPLE_OS
55
#elif defined(USE_WIN32_CRYPTO)
56
#include <wincrypt.h>
57
#endif
58
59
/* Please keep the SSL backend-specific #if branches in this order:
60
 *
61
 * 1. USE_OPENSSL
62
 * 2. USE_GNUTLS
63
 * 3. USE_MBEDTLS
64
 * 4. USE_COMMON_CRYPTO
65
 * 5. USE_WIN32_CRYPTO
66
 *
67
 * This ensures that the same SSL branch gets activated throughout this source
68
 * file even if multiple backends are enabled at the same time.
69
 */
70
71
#ifdef USE_OPENSSL
72
73
struct ossl_sha256_ctx {
74
  EVP_MD_CTX *openssl_ctx;
75
};
76
typedef struct ossl_sha256_ctx my_sha256_ctx;
77
78
static CURLcode my_sha256_init(void *in)
79
{
80
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
81
  ctx->openssl_ctx = EVP_MD_CTX_create();
82
  if(!ctx->openssl_ctx)
83
    return CURLE_OUT_OF_MEMORY;
84
85
  if(!EVP_DigestInit_ex(ctx->openssl_ctx, EVP_sha256(), NULL)) {
86
    EVP_MD_CTX_destroy(ctx->openssl_ctx);
87
    return CURLE_FAILED_INIT;
88
  }
89
  return CURLE_OK;
90
}
91
92
static void my_sha256_update(void *in,
93
                             const unsigned char *data,
94
                             unsigned int length)
95
{
96
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
97
  EVP_DigestUpdate(ctx->openssl_ctx, data, length);
98
}
99
100
static void my_sha256_final(unsigned char *digest, void *in)
101
{
102
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
103
  EVP_DigestFinal_ex(ctx->openssl_ctx, digest, NULL);
104
  EVP_MD_CTX_destroy(ctx->openssl_ctx);
105
}
106
107
#elif defined(USE_GNUTLS)
108
109
typedef struct sha256_ctx my_sha256_ctx;
110
111
static CURLcode my_sha256_init(void *ctx)
112
{
113
  sha256_init(ctx);
114
  return CURLE_OK;
115
}
116
117
static void my_sha256_update(void *ctx,
118
                             const unsigned char *data,
119
                             unsigned int length)
120
{
121
  sha256_update(ctx, length, data);
122
}
123
124
static void my_sha256_final(unsigned char *digest, void *ctx)
125
{
126
  sha256_digest(ctx, SHA256_DIGEST_SIZE, digest);
127
}
128
129
#elif defined(USE_MBEDTLS_SHA256)
130
131
typedef psa_hash_operation_t my_sha256_ctx;
132
133
static CURLcode my_sha256_init(void *ctx)
134
{
135
  memset(ctx, 0, sizeof(my_sha256_ctx));
136
  if(psa_hash_setup(ctx, PSA_ALG_SHA_256) != PSA_SUCCESS)
137
    return CURLE_OUT_OF_MEMORY;
138
  return CURLE_OK;
139
}
140
141
static void my_sha256_update(void *ctx,
142
                             const unsigned char *data,
143
                             unsigned int length)
144
{
145
  (void)psa_hash_update(ctx, data, length);
146
}
147
148
static void my_sha256_final(unsigned char *digest, void *ctx)
149
{
150
  size_t actual_length;
151
  (void)psa_hash_finish(ctx, digest, CURL_SHA256_DIGEST_LENGTH,
152
                        &actual_length);
153
}
154
155
#elif defined(AN_APPLE_OS)
156
typedef CC_SHA256_CTX my_sha256_ctx;
157
158
static CURLcode my_sha256_init(void *ctx)
159
{
160
  (void)CC_SHA256_Init(ctx);
161
  return CURLE_OK;
162
}
163
164
static void my_sha256_update(void *ctx,
165
                             const unsigned char *data,
166
                             unsigned int length)
167
{
168
  (void)CC_SHA256_Update(ctx, data, length);
169
}
170
171
static void my_sha256_final(unsigned char *digest, void *ctx)
172
{
173
  (void)CC_SHA256_Final(digest, ctx);
174
}
175
176
#elif defined(USE_WIN32_CRYPTO)
177
178
struct sha256_ctx {
179
  HCRYPTPROV hCryptProv;
180
  HCRYPTHASH hHash;
181
};
182
typedef struct sha256_ctx my_sha256_ctx;
183
184
/* Offered when targeting Vista (XP SP2+) */
185
#ifndef CALG_SHA_256
186
#define CALG_SHA_256 0x0000800c
187
#endif
188
189
static CURLcode my_sha256_init(void *in)
190
{
191
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
192
  if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_AES,
193
                          CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
194
    return CURLE_OUT_OF_MEMORY;
195
196
  if(!CryptCreateHash(ctx->hCryptProv, CALG_SHA_256, 0, 0, &ctx->hHash)) {
197
    CryptReleaseContext(ctx->hCryptProv, 0);
198
    ctx->hCryptProv = 0;
199
    return CURLE_FAILED_INIT;
200
  }
201
202
  return CURLE_OK;
203
}
204
205
static void my_sha256_update(void *in,
206
                             const unsigned char *data,
207
                             unsigned int length)
208
{
209
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
210
  CryptHashData(ctx->hHash, (const BYTE *)data, length, 0);
211
}
212
213
static void my_sha256_final(unsigned char *digest, void *in)
214
{
215
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
216
  unsigned long length = 0;
217
218
  CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
219
  if(length == CURL_SHA256_DIGEST_LENGTH)
220
    CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0);
221
222
  if(ctx->hHash)
223
    CryptDestroyHash(ctx->hHash);
224
225
  if(ctx->hCryptProv)
226
    CryptReleaseContext(ctx->hCryptProv, 0);
227
}
228
229
#else
230
231
/* When no other crypto library is available we use this code segment */
232
233
/* This is based on the SHA256 implementation in LibTomCrypt that was released
234
 * into public domain. */
235
236
#define WPA_GET_BE32(a)              \
237
0
  ((((unsigned long)(a)[0]) << 24) | \
238
0
   (((unsigned long)(a)[1]) << 16) | \
239
0
   (((unsigned long)(a)[2]) <<  8) | \
240
0
    ((unsigned long)(a)[3]))
241
#define WPA_PUT_BE32(a, val)                                         \
242
0
  do {                                                               \
243
0
    (a)[0] = (unsigned char)((((unsigned long)(val)) >> 24) & 0xff); \
244
0
    (a)[1] = (unsigned char)((((unsigned long)(val)) >> 16) & 0xff); \
245
0
    (a)[2] = (unsigned char)((((unsigned long)(val)) >>  8) & 0xff); \
246
0
    (a)[3] = (unsigned char) (((unsigned long)(val)) & 0xff);        \
247
0
  } while(0)
248
249
#ifdef HAVE_LONGLONG
250
#define WPA_PUT_BE64(a, val)                                      \
251
0
  do {                                                            \
252
0
    (a)[0] = (unsigned char)(((unsigned long long)(val)) >> 56);  \
253
0
    (a)[1] = (unsigned char)(((unsigned long long)(val)) >> 48);  \
254
0
    (a)[2] = (unsigned char)(((unsigned long long)(val)) >> 40);  \
255
0
    (a)[3] = (unsigned char)(((unsigned long long)(val)) >> 32);  \
256
0
    (a)[4] = (unsigned char)(((unsigned long long)(val)) >> 24);  \
257
0
    (a)[5] = (unsigned char)(((unsigned long long)(val)) >> 16);  \
258
0
    (a)[6] = (unsigned char)(((unsigned long long)(val)) >>  8);  \
259
0
    (a)[7] = (unsigned char)(((unsigned long long)(val)) & 0xff); \
260
0
  } while(0)
261
#else
262
#define WPA_PUT_BE64(a, val)                                    \
263
  do {                                                          \
264
    (a)[0] = (unsigned char)(((unsigned __int64)(val)) >> 56);  \
265
    (a)[1] = (unsigned char)(((unsigned __int64)(val)) >> 48);  \
266
    (a)[2] = (unsigned char)(((unsigned __int64)(val)) >> 40);  \
267
    (a)[3] = (unsigned char)(((unsigned __int64)(val)) >> 32);  \
268
    (a)[4] = (unsigned char)(((unsigned __int64)(val)) >> 24);  \
269
    (a)[5] = (unsigned char)(((unsigned __int64)(val)) >> 16);  \
270
    (a)[6] = (unsigned char)(((unsigned __int64)(val)) >>  8);  \
271
    (a)[7] = (unsigned char)(((unsigned __int64)(val)) & 0xff); \
272
  } while(0)
273
#endif
274
275
struct sha256_state {
276
#ifdef HAVE_LONGLONG
277
  unsigned long long length;
278
#else
279
  unsigned __int64 length;
280
#endif
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
0
  (((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | \
306
0
     ((unsigned long)(x) << (unsigned long)(32 - ((y) & 31)))) & 0xFFFFFFFFUL)
307
308
0
#define Sha256_Ch(x, y, z)  (z ^ (x & (y ^ z)))
309
0
#define Sha256_Maj(x, y, z) (((x | y) & z) | (x & y))
310
0
#define Sha256_S(x, n)      RORc((x), (n))
311
0
#define Sha256_R(x, n)      (((x) & 0xFFFFFFFFUL) >> (n))
312
313
0
#define Sigma0(x)         (Sha256_S(x, 2) ^ Sha256_S(x, 13) ^ Sha256_S(x, 22))
314
0
#define Sigma1(x)         (Sha256_S(x, 6) ^ Sha256_S(x, 11) ^ Sha256_S(x, 25))
315
0
#define Gamma0(x)         (Sha256_S(x, 7) ^ Sha256_S(x, 18) ^ Sha256_R(x, 3))
316
0
#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
0
{
321
0
  unsigned long S[8], W[64];
322
0
  int i;
323
324
  /* Copy state into S */
325
0
  for(i = 0; i < 8; i++) {
326
0
    S[i] = md->state[i];
327
0
  }
328
  /* copy the state into 512-bits into W[0..15] */
329
0
  for(i = 0; i < 16; i++)
330
0
    W[i] = WPA_GET_BE32(buf + (4 * i));
331
  /* fill W[16..63] */
332
0
  for(i = 16; i < 64; i++) {
333
0
    W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
334
0
  }
335
336
  /* Compress */
337
0
#define RND(a, b, c, d, e, f, g, h, i)                                   \
338
0
  do {                                                                   \
339
0
    unsigned long t0 = h + Sigma1(e) + Sha256_Ch(e, f, g) + K[i] + W[i]; \
340
0
    unsigned long t1 = Sigma0(a) + Sha256_Maj(a, b, c);                  \
341
0
    d += t0;                                                             \
342
0
    h = t0 + t1;                                                         \
343
0
  } while(0)
344
345
0
  for(i = 0; i < 64; ++i) {
346
0
    unsigned long t;
347
0
    RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
348
0
    t = S[7];
349
0
    S[7] = S[6];
350
0
    S[6] = S[5];
351
0
    S[5] = S[4];
352
0
    S[4] = S[3];
353
0
    S[3] = S[2];
354
0
    S[2] = S[1];
355
0
    S[1] = S[0];
356
0
    S[0] = t;
357
0
  }
358
359
  /* Feedback */
360
0
  for(i = 0; i < 8; i++) {
361
0
    md->state[i] = md->state[i] + S[i];
362
0
  }
363
364
0
  return 0;
365
0
}
366
367
/* Initialize the hash state */
368
static CURLcode my_sha256_init(void *in)
369
0
{
370
0
  struct sha256_state *md = (struct sha256_state *)in;
371
0
  md->curlen = 0;
372
0
  md->length = 0;
373
0
  md->state[0] = 0x6A09E667UL;
374
0
  md->state[1] = 0xBB67AE85UL;
375
0
  md->state[2] = 0x3C6EF372UL;
376
0
  md->state[3] = 0xA54FF53AUL;
377
0
  md->state[4] = 0x510E527FUL;
378
0
  md->state[5] = 0x9B05688CUL;
379
0
  md->state[6] = 0x1F83D9ABUL;
380
0
  md->state[7] = 0x5BE0CD19UL;
381
382
0
  return CURLE_OK;
383
0
}
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
0
{
395
0
  unsigned long inlen = len;
396
0
  unsigned long n;
397
0
  struct sha256_state *md = (struct sha256_state *)ctx;
398
0
#define CURL_SHA256_BLOCK_SIZE 64
399
0
  if(md->curlen > sizeof(md->buf))
400
0
    return;
401
0
  while(inlen > 0) {
402
0
    if(md->curlen == 0 && inlen >= CURL_SHA256_BLOCK_SIZE) {
403
0
      if(sha256_compress(md, in) < 0)
404
0
        return;
405
0
      md->length += CURL_SHA256_BLOCK_SIZE * 8;
406
0
      in += CURL_SHA256_BLOCK_SIZE;
407
0
      inlen -= CURL_SHA256_BLOCK_SIZE;
408
0
    }
409
0
    else {
410
0
      n = CURLMIN(inlen, (CURL_SHA256_BLOCK_SIZE - md->curlen));
411
0
      memcpy(md->buf + md->curlen, in, n);
412
0
      md->curlen += n;
413
0
      in += n;
414
0
      inlen -= n;
415
0
      if(md->curlen == CURL_SHA256_BLOCK_SIZE) {
416
0
        if(sha256_compress(md, md->buf) < 0)
417
0
          return;
418
0
        md->length += 8 * CURL_SHA256_BLOCK_SIZE;
419
0
        md->curlen = 0;
420
0
      }
421
0
    }
422
0
  }
423
0
}
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
0
{
433
0
  struct sha256_state *md = ctx;
434
0
  int i;
435
436
0
  if(md->curlen >= sizeof(md->buf))
437
0
    return;
438
439
  /* Increase the length of the message */
440
0
  md->length += md->curlen * 8;
441
442
  /* Append the '1' bit */
443
0
  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
0
  if(md->curlen > 56) {
450
0
    while(md->curlen < 64) {
451
0
      md->buf[md->curlen++] = (unsigned char)0;
452
0
    }
453
0
    sha256_compress(md, md->buf);
454
0
    md->curlen = 0;
455
0
  }
456
457
  /* Pad up to 56 bytes of zeroes */
458
0
  while(md->curlen < 56) {
459
0
    md->buf[md->curlen++] = (unsigned char)0;
460
0
  }
461
462
  /* Store length */
463
0
  WPA_PUT_BE64(md->buf + 56, md->length);
464
0
  sha256_compress(md, md->buf);
465
466
  /* Copy output */
467
0
  for(i = 0; i < 8; i++)
468
0
    WPA_PUT_BE32(out + (4 * i), md->state[i]);
469
0
}
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
                       const size_t length)
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
    my_sha256_update(&ctx, input, curlx_uztoui(length));
495
0
    my_sha256_final(output, &ctx);
496
0
  }
497
0
  return result;
498
0
}
499
500
const struct HMAC_params Curl_HMAC_SHA256 = {
501
  my_sha256_init,        /* Hash initialization function. */
502
  my_sha256_update,      /* Hash update function. */
503
  my_sha256_final,       /* Hash computation end function. */
504
  sizeof(my_sha256_ctx), /* Size of hash context structure. */
505
  64,                    /* Maximum key length. */
506
  32                     /* Result size. */
507
};
508
509
#endif /* AWS, DIGEST, or libssh2 */