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