Coverage Report

Created: 2025-08-03 06:36

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