Coverage Report

Created: 2023-06-07 07:02

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