VirtualBox

source: vbox/trunk/src/libs/curl-7.87.0/lib/sha256.c@ 98929

Last change on this file since 98929 was 98326, checked in by vboxsync, 2 years ago

curl-7.87.0: Applied and adjusted our curl changes to 7.83.1. bugref:10356

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette