Coverage Report

Created: 2024-02-25 06:14

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