Coverage Report

Created: 2025-10-30 06:17

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