xref: /third_party/curl/lib/sha256.c (revision 13498266)
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->openssl_ctx, 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->openssl_ctx, data, length);
126}
127
128static void my_sha256_final(unsigned char *digest, my_sha256_ctx *ctx)
129{
130  EVP_DigestFinal_ex(ctx->openssl_ctx, 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);
519  if(!result) {
520    my_sha256_update(&ctx, input, curlx_uztoui(length));
521    my_sha256_final(output, &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