Coverage Report

Created: 2025-08-26 07:08

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