Coverage Report

Created: 2025-07-11 06:33

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