Coverage Report

Created: 2025-10-10 06:31

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_OPENSSL
36
#include <openssl/evp.h>
37
#elif defined(USE_GNUTLS)
38
#include <nettle/sha.h>
39
#elif defined(USE_MBEDTLS)
40
#include <mbedtls/version.h>
41
#if MBEDTLS_VERSION_NUMBER < 0x03020000
42
  #error "mbedTLS 3.2.0 or later required"
43
#endif
44
#include <mbedtls/sha256.h>
45
#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
46
              (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
47
      (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
48
              (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
49
#include <CommonCrypto/CommonDigest.h>
50
#define AN_APPLE_OS
51
#elif defined(USE_WIN32_CRYPTO)
52
#include <wincrypt.h>
53
#endif
54
55
/* The last 2 #include files should be in this order */
56
#include "curl_memory.h"
57
#include "memdebug.h"
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
0
{
80
0
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
81
0
  ctx->openssl_ctx = EVP_MD_CTX_create();
82
0
  if(!ctx->openssl_ctx)
83
0
    return CURLE_OUT_OF_MEMORY;
84
85
0
  if(!EVP_DigestInit_ex(ctx->openssl_ctx, EVP_sha256(), NULL)) {
86
0
    EVP_MD_CTX_destroy(ctx->openssl_ctx);
87
0
    return CURLE_FAILED_INIT;
88
0
  }
89
0
  return CURLE_OK;
90
0
}
91
92
static void my_sha256_update(void *in,
93
                             const unsigned char *data,
94
                             unsigned int length)
95
0
{
96
0
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
97
0
  EVP_DigestUpdate(ctx->openssl_ctx, data, length);
98
0
}
99
100
static void my_sha256_final(unsigned char *digest, void *in)
101
0
{
102
0
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
103
0
  EVP_DigestFinal_ex(ctx->openssl_ctx, digest, NULL);
104
0
  EVP_MD_CTX_destroy(ctx->openssl_ctx);
105
0
}
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)
130
131
typedef mbedtls_sha256_context my_sha256_ctx;
132
133
static CURLcode my_sha256_init(void *ctx)
134
{
135
  (void)mbedtls_sha256_starts(ctx, 0);
136
  return CURLE_OK;
137
}
138
139
static void my_sha256_update(void *ctx,
140
                             const unsigned char *data,
141
                             unsigned int length)
142
{
143
  (void)mbedtls_sha256_update(ctx, data, length);
144
}
145
146
static void my_sha256_final(unsigned char *digest, void *ctx)
147
{
148
  (void)mbedtls_sha256_finish(ctx, digest);
149
}
150
151
#elif defined(AN_APPLE_OS)
152
typedef CC_SHA256_CTX my_sha256_ctx;
153
154
static CURLcode my_sha256_init(void *ctx)
155
{
156
  (void)CC_SHA256_Init(ctx);
157
  return CURLE_OK;
158
}
159
160
static void my_sha256_update(void *ctx,
161
                             const unsigned char *data,
162
                             unsigned int length)
163
{
164
  (void)CC_SHA256_Update(ctx, data, length);
165
}
166
167
static void my_sha256_final(unsigned char *digest, void *ctx)
168
{
169
  (void)CC_SHA256_Final(digest, ctx);
170
}
171
172
#elif defined(USE_WIN32_CRYPTO)
173
174
struct sha256_ctx {
175
  HCRYPTPROV hCryptProv;
176
  HCRYPTHASH hHash;
177
};
178
typedef struct sha256_ctx my_sha256_ctx;
179
180
/* Offered when targeting Vista (XP SP2+) */
181
#ifndef CALG_SHA_256
182
#define CALG_SHA_256 0x0000800c
183
#endif
184
185
static CURLcode my_sha256_init(void *in)
186
{
187
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
188
  if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_AES,
189
                         CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
190
    return CURLE_OUT_OF_MEMORY;
191
192
  if(!CryptCreateHash(ctx->hCryptProv, CALG_SHA_256, 0, 0, &ctx->hHash)) {
193
    CryptReleaseContext(ctx->hCryptProv, 0);
194
    ctx->hCryptProv = 0;
195
    return CURLE_FAILED_INIT;
196
  }
197
198
  return CURLE_OK;
199
}
200
201
static void my_sha256_update(void *in,
202
                             const unsigned char *data,
203
                             unsigned int length)
204
{
205
  my_sha256_ctx *ctx = (my_sha256_ctx *)in;
206
#ifdef __MINGW32CE__
207
  CryptHashData(ctx->hHash, (BYTE *)CURL_UNCONST(data), length, 0);
208
#else
209
  CryptHashData(ctx->hHash, (const BYTE *)data, length, 0);
210
#endif
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) ((((unsigned long)(a)[0]) << 24) | \
237
                         (((unsigned long)(a)[1]) << 16) | \
238
                         (((unsigned long)(a)[2]) <<  8) | \
239
                          ((unsigned long)(a)[3]))
240
#define WPA_PUT_BE32(a, val)                                        \
241
do {                                                                \
242
  (a)[0] = (unsigned char)((((unsigned long) (val)) >> 24) & 0xff); \
243
  (a)[1] = (unsigned char)((((unsigned long) (val)) >> 16) & 0xff); \
244
  (a)[2] = (unsigned char)((((unsigned long) (val)) >> 8) & 0xff);  \
245
  (a)[3] = (unsigned char)(((unsigned long) (val)) & 0xff);         \
246
} while(0)
247
248
#ifdef HAVE_LONGLONG
249
#define WPA_PUT_BE64(a, val)                                    \
250
do {                                                            \
251
  (a)[0] = (unsigned char)(((unsigned long long)(val)) >> 56);  \
252
  (a)[1] = (unsigned char)(((unsigned long long)(val)) >> 48);  \
253
  (a)[2] = (unsigned char)(((unsigned long long)(val)) >> 40);  \
254
  (a)[3] = (unsigned char)(((unsigned long long)(val)) >> 32);  \
255
  (a)[4] = (unsigned char)(((unsigned long long)(val)) >> 24);  \
256
  (a)[5] = (unsigned char)(((unsigned long long)(val)) >> 16);  \
257
  (a)[6] = (unsigned char)(((unsigned long long)(val)) >> 8);   \
258
  (a)[7] = (unsigned char)(((unsigned long long)(val)) & 0xff); \
259
} while(0)
260
#else
261
#define WPA_PUT_BE64(a, val)                                  \
262
do {                                                          \
263
  (a)[0] = (unsigned char)(((unsigned __int64)(val)) >> 56);  \
264
  (a)[1] = (unsigned char)(((unsigned __int64)(val)) >> 48);  \
265
  (a)[2] = (unsigned char)(((unsigned __int64)(val)) >> 40);  \
266
  (a)[3] = (unsigned char)(((unsigned __int64)(val)) >> 32);  \
267
  (a)[4] = (unsigned char)(((unsigned __int64)(val)) >> 24);  \
268
  (a)[5] = (unsigned char)(((unsigned __int64)(val)) >> 16);  \
269
  (a)[6] = (unsigned char)(((unsigned __int64)(val)) >> 8);   \
270
  (a)[7] = (unsigned char)(((unsigned __int64)(val)) & 0xff); \
271
} while(0)
272
#endif
273
274
struct sha256_state {
275
#ifdef HAVE_LONGLONG
276
  unsigned long long length;
277
#else
278
  unsigned __int64 length;
279
#endif
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
(((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | \
305
   ((unsigned long)(x) << (unsigned long)(32 - ((y) & 31)))) & 0xFFFFFFFFUL)
306
#define Sha256_Ch(x,y,z)  (z ^ (x & (y ^ z)))
307
#define Sha256_Maj(x,y,z) (((x | y) & z) | (x & y))
308
#define Sha256_S(x, n)    RORc((x), (n))
309
#define Sha256_R(x, n)    (((x)&0xFFFFFFFFUL)>>(n))
310
#define Sigma0(x)         (Sha256_S(x, 2) ^ Sha256_S(x, 13) ^ Sha256_S(x, 22))
311
#define Sigma1(x)         (Sha256_S(x, 6) ^ Sha256_S(x, 11) ^ Sha256_S(x, 25))
312
#define Gamma0(x)         (Sha256_S(x, 7) ^ Sha256_S(x, 18) ^ Sha256_R(x, 3))
313
#define Gamma1(x)         (Sha256_S(x, 17) ^ Sha256_S(x, 19) ^ Sha256_R(x, 10))
314
315
/* Compress 512-bits */
316
static int sha256_compress(struct sha256_state *md,
317
                           const unsigned char *buf)
318
{
319
  unsigned long S[8], W[64];
320
  int i;
321
322
  /* Copy state into S */
323
  for(i = 0; i < 8; i++) {
324
    S[i] = md->state[i];
325
  }
326
  /* copy the state into 512-bits into W[0..15] */
327
  for(i = 0; i < 16; i++)
328
    W[i] = WPA_GET_BE32(buf + (4 * i));
329
  /* fill W[16..63] */
330
  for(i = 16; i < 64; i++) {
331
    W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
332
      W[i - 16];
333
  }
334
335
  /* Compress */
336
#define RND(a,b,c,d,e,f,g,h,i)                                           \
337
  do {                                                                   \
338
    unsigned long t0 = h + Sigma1(e) + Sha256_Ch(e, f, g) + K[i] + W[i]; \
339
    unsigned long t1 = Sigma0(a) + Sha256_Maj(a, b, c);                  \
340
    d += t0;                                                             \
341
    h = t0 + t1;                                                         \
342
  } while(0)
343
344
  for(i = 0; i < 64; ++i) {
345
    unsigned long t;
346
    RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
347
    t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
348
    S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
349
  }
350
351
  /* Feedback */
352
  for(i = 0; i < 8; i++) {
353
    md->state[i] = md->state[i] + S[i];
354
  }
355
356
  return 0;
357
}
358
359
/* Initialize the hash state */
360
static CURLcode my_sha256_init(void *in)
361
{
362
  struct sha256_state *md = (struct sha256_state *)in;
363
  md->curlen = 0;
364
  md->length = 0;
365
  md->state[0] = 0x6A09E667UL;
366
  md->state[1] = 0xBB67AE85UL;
367
  md->state[2] = 0x3C6EF372UL;
368
  md->state[3] = 0xA54FF53AUL;
369
  md->state[4] = 0x510E527FUL;
370
  md->state[5] = 0x9B05688CUL;
371
  md->state[6] = 0x1F83D9ABUL;
372
  md->state[7] = 0x5BE0CD19UL;
373
374
  return CURLE_OK;
375
}
376
377
/*
378
   Process a block of memory though the hash
379
   @param md     The hash state
380
   @param in     The data to hash
381
   @param inlen  The length of the data (octets)
382
*/
383
static void my_sha256_update(void *ctx,
384
                             const unsigned char *in,
385
                             unsigned int len)
386
{
387
  unsigned long inlen = len;
388
  unsigned long n;
389
  struct sha256_state *md = (struct sha256_state *)ctx;
390
#define CURL_SHA256_BLOCK_SIZE 64
391
  if(md->curlen > sizeof(md->buf))
392
    return;
393
  while(inlen > 0) {
394
    if(md->curlen == 0 && inlen >= CURL_SHA256_BLOCK_SIZE) {
395
      if(sha256_compress(md, in) < 0)
396
        return;
397
      md->length += CURL_SHA256_BLOCK_SIZE * 8;
398
      in += CURL_SHA256_BLOCK_SIZE;
399
      inlen -= CURL_SHA256_BLOCK_SIZE;
400
    }
401
    else {
402
      n = CURLMIN(inlen, (CURL_SHA256_BLOCK_SIZE - md->curlen));
403
      memcpy(md->buf + md->curlen, in, n);
404
      md->curlen += n;
405
      in += n;
406
      inlen -= n;
407
      if(md->curlen == CURL_SHA256_BLOCK_SIZE) {
408
        if(sha256_compress(md, md->buf) < 0)
409
          return;
410
        md->length += 8 * CURL_SHA256_BLOCK_SIZE;
411
        md->curlen = 0;
412
      }
413
    }
414
  }
415
}
416
417
/*
418
   Terminate the hash to get the digest
419
   @param md  The hash state
420
   @param out [out] The destination of the hash (32 bytes)
421
   @return 0 if successful
422
*/
423
static void my_sha256_final(unsigned char *out, void *ctx)
424
{
425
  struct sha256_state *md = ctx;
426
  int i;
427
428
  if(md->curlen >= sizeof(md->buf))
429
    return;
430
431
  /* Increase the length of the message */
432
  md->length += md->curlen * 8;
433
434
  /* Append the '1' bit */
435
  md->buf[md->curlen++] = (unsigned char)0x80;
436
437
  /* If the length is currently above 56 bytes we append zeros
438
   * then compress. Then we can fall back to padding zeros and length
439
   * encoding like normal.
440
   */
441
  if(md->curlen > 56) {
442
    while(md->curlen < 64) {
443
      md->buf[md->curlen++] = (unsigned char)0;
444
    }
445
    sha256_compress(md, md->buf);
446
    md->curlen = 0;
447
  }
448
449
  /* Pad up to 56 bytes of zeroes */
450
  while(md->curlen < 56) {
451
    md->buf[md->curlen++] = (unsigned char)0;
452
  }
453
454
  /* Store length */
455
  WPA_PUT_BE64(md->buf + 56, md->length);
456
  sha256_compress(md, md->buf);
457
458
  /* Copy output */
459
  for(i = 0; i < 8; i++)
460
    WPA_PUT_BE32(out + (4 * i), md->state[i]);
461
}
462
463
#endif /* CRYPTO LIBS */
464
465
/*
466
 * Curl_sha256it()
467
 *
468
 * Generates a SHA256 hash for the given input data.
469
 *
470
 * Parameters:
471
 *
472
 * output [in/out] - The output buffer.
473
 * input  [in]     - The input data.
474
 * length [in]     - The input length.
475
 *
476
 * Returns CURLE_OK on success.
477
 */
478
CURLcode Curl_sha256it(unsigned char *output, const unsigned char *input,
479
                       const size_t length)
480
0
{
481
0
  CURLcode result;
482
0
  my_sha256_ctx ctx;
483
484
0
  result = my_sha256_init(&ctx);
485
0
  if(!result) {
486
0
    my_sha256_update(&ctx, input, curlx_uztoui(length));
487
0
    my_sha256_final(output, &ctx);
488
0
  }
489
0
  return result;
490
0
}
491
492
493
const struct HMAC_params Curl_HMAC_SHA256 = {
494
  my_sha256_init,        /* Hash initialization function. */
495
  my_sha256_update,      /* Hash update function. */
496
  my_sha256_final,       /* Hash computation end function. */
497
  sizeof(my_sha256_ctx), /* Size of hash context structure. */
498
  64,                    /* Maximum key length. */
499
  32                     /* Result size. */
500
};
501
502
#endif /* AWS, DIGEST, or libssh2 */