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
103struct sha256_ctx {
104 EVP_MD_CTX *openssl_ctx;
105};
106typedef struct sha256_ctx my_sha256_ctx;
107
108static CURLcode my_sha256_init(my_sha256_ctx *ctx)
109{
110 ctx->openssl_ctx = EVP_MD_CTX_create();
111 if(!ctx->openssl_ctx)
112 return CURLE_OUT_OF_MEMORY;
113
114 if(!EVP_DigestInit_ex(ctx: ctx->openssl_ctx, type: EVP_sha256(), NULL)) {
115 EVP_MD_CTX_destroy(ctx->openssl_ctx);
116 return CURLE_FAILED_INIT;
117 }
118 return CURLE_OK;
119}
120
121static void my_sha256_update(my_sha256_ctx *ctx,
122 const unsigned char *data,
123 unsigned int length)
124{
125 EVP_DigestUpdate(ctx: ctx->openssl_ctx, d: data, cnt: length);
126}
127
128static void my_sha256_final(unsigned char *digest, my_sha256_ctx *ctx)
129{
130 EVP_DigestFinal_ex(ctx: ctx->openssl_ctx, md: digest, NULL);
131 EVP_MD_CTX_destroy(ctx->openssl_ctx);
132}
133
134#elif defined(USE_GNUTLS)
135
136typedef struct sha256_ctx my_sha256_ctx;
137
138static CURLcode my_sha256_init(my_sha256_ctx *ctx)
139{
140 sha256_init(ctx);
141 return CURLE_OK;
142}
143
144static 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
151static 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
158typedef mbedtls_sha256_context my_sha256_ctx;
159
160static 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
170static 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
181static 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)
191typedef CC_SHA256_CTX my_sha256_ctx;
192
193static CURLcode my_sha256_init(my_sha256_ctx *ctx)
194{
195 (void) CC_SHA256_Init(ctx);
196 return CURLE_OK;
197}
198
199static 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
206static 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
213struct sha256_ctx {
214 HCRYPTPROV hCryptProv;
215 HCRYPTHASH hHash;
216};
217typedef struct sha256_ctx my_sha256_ctx;
218
219#if !defined(CALG_SHA_256)
220#define CALG_SHA_256 0x0000800c
221#endif
222
223static 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
238static 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
245static 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) \
272do { \
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) \
281do { \
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) \
293do { \
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
305struct 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};
314typedef struct sha256_state my_sha256_ctx;
315
316/* The K array */
317static 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 */
347static 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 */
391static 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*/
414static 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*/
455static 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 */
512CURLcode Curl_sha256it(unsigned char *output, const unsigned char *input,
513 const size_t length)
514{
515 CURLcode result;
516 my_sha256_ctx ctx;
517
518 result = my_sha256_init(ctx: &ctx);
519 if(!result) {
520 my_sha256_update(ctx: &ctx, data: input, length: curlx_uztoui(uznum: length));
521 my_sha256_final(digest: output, ctx: &ctx);
522 }
523 return result;
524}
525
526
527const 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 */
546