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