1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2019, Florin Petriuc, <petriuc.florin@gmail.com>
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.haxx.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23#include "curl_setup.h"
24
25#ifndef CURL_DISABLE_CRYPTO_AUTH
26
27#include "warnless.h"
28#include "curl_sha256.h"
29
30#if defined(USE_OPENSSL)
31
32#include <openssl/opensslv.h>
33
34#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
35#define USE_OPENSSL_SHA256
36#endif
37
38#endif
39
40#ifdef USE_OPENSSL_SHA256
41/* When OpenSSL is available we use the SHA256-function from OpenSSL */
42#include <openssl/sha.h>
43#else
44
45/* When no other crypto library is available we use this code segment */
46
47/* ===== start - public domain SHA256 implementation ===== */
48/* This is based on SHA256 implementation in LibTomCrypt that was released into
49 * public domain by Tom St Denis. */
50
51#define WPA_GET_BE32(a) ((((unsigned long)(a)[0]) << 24) | \
52 (((unsigned long)(a)[1]) << 16) | \
53 (((unsigned long)(a)[2]) << 8) | \
54 ((unsigned long)(a)[3]))
55#define WPA_PUT_BE32(a, val) \
56do { \
57 (a)[0] = (unsigned char)((((unsigned long) (val)) >> 24) & 0xff); \
58 (a)[1] = (unsigned char)((((unsigned long) (val)) >> 16) & 0xff); \
59 (a)[2] = (unsigned char)((((unsigned long) (val)) >> 8) & 0xff); \
60 (a)[3] = (unsigned char)(((unsigned long) (val)) & 0xff); \
61} while(0)
62
63#ifdef HAVE_LONGLONG
64#define WPA_PUT_BE64(a, val) \
65do { \
66 (a)[0] = (unsigned char)(((unsigned long long)(val)) >> 56); \
67 (a)[1] = (unsigned char)(((unsigned long long)(val)) >> 48); \
68 (a)[2] = (unsigned char)(((unsigned long long)(val)) >> 40); \
69 (a)[3] = (unsigned char)(((unsigned long long)(val)) >> 32); \
70 (a)[4] = (unsigned char)(((unsigned long long)(val)) >> 24); \
71 (a)[5] = (unsigned char)(((unsigned long long)(val)) >> 16); \
72 (a)[6] = (unsigned char)(((unsigned long long)(val)) >> 8); \
73 (a)[7] = (unsigned char)(((unsigned long long)(val)) & 0xff); \
74} while(0)
75#else
76#define WPA_PUT_BE64(a, val) \
77do { \
78 (a)[0] = (unsigned char)(((unsigned __int64)(val)) >> 56); \
79 (a)[1] = (unsigned char)(((unsigned __int64)(val)) >> 48); \
80 (a)[2] = (unsigned char)(((unsigned __int64)(val)) >> 40); \
81 (a)[3] = (unsigned char)(((unsigned __int64)(val)) >> 32); \
82 (a)[4] = (unsigned char)(((unsigned __int64)(val)) >> 24); \
83 (a)[5] = (unsigned char)(((unsigned __int64)(val)) >> 16); \
84 (a)[6] = (unsigned char)(((unsigned __int64)(val)) >> 8); \
85 (a)[7] = (unsigned char)(((unsigned __int64)(val)) & 0xff); \
86} while(0)
87#endif
88
89typedef struct sha256_state {
90#ifdef HAVE_LONGLONG
91 unsigned long long length;
92#else
93 unsigned __int64 length;
94#endif
95 unsigned long state[8], curlen;
96 unsigned char buf[64];
97} SHA256_CTX;
98/* the K array */
99static const unsigned long K[64] = {
100 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
101 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
102 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
103 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
104 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
105 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
106 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
107 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
108 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
109 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
110 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
111 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
112 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
113};
114/* Various logical functions */
115#define RORc(x, y) \
116(((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | \
117 ((unsigned long)(x) << (unsigned long)(32 - ((y) & 31)))) & 0xFFFFFFFFUL)
118#define Ch(x,y,z) (z ^ (x & (y ^ z)))
119#define Maj(x,y,z) (((x | y) & z) | (x & y))
120#define S(x, n) RORc((x), (n))
121#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
122#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
123#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
124#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
125#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
126/* compress 512-bits */
127static int sha256_compress(struct sha256_state *md,
128 unsigned char *buf)
129{
130 unsigned long S[8], W[64];
131 int i;
132 /* copy state into S */
133 for(i = 0; i < 8; i++) {
134 S[i] = md->state[i];
135 }
136 /* copy the state into 512-bits into W[0..15] */
137 for(i = 0; i < 16; i++)
138 W[i] = WPA_GET_BE32(buf + (4 * i));
139 /* fill W[16..63] */
140 for(i = 16; i < 64; i++) {
141 W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
142 W[i - 16];
143 }
144 /* Compress */
145#define RND(a,b,c,d,e,f,g,h,i) \
146 unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
147 unsigned long t1 = Sigma0(a) + Maj(a, b, c); \
148 d += t0; \
149 h = t0 + t1;
150 for(i = 0; i < 64; ++i) {
151 unsigned long t;
152 RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
153 t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
154 S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
155 }
156 /* feedback */
157 for(i = 0; i < 8; i++) {
158 md->state[i] = md->state[i] + S[i];
159 }
160 return 0;
161}
162/* Initialize the hash state */
163static void SHA256_Init(struct sha256_state *md)
164{
165 md->curlen = 0;
166 md->length = 0;
167 md->state[0] = 0x6A09E667UL;
168 md->state[1] = 0xBB67AE85UL;
169 md->state[2] = 0x3C6EF372UL;
170 md->state[3] = 0xA54FF53AUL;
171 md->state[4] = 0x510E527FUL;
172 md->state[5] = 0x9B05688CUL;
173 md->state[6] = 0x1F83D9ABUL;
174 md->state[7] = 0x5BE0CD19UL;
175}
176/**
177 Process a block of memory though the hash
178 @param md The hash state
179 @param in The data to hash
180 @param inlen The length of the data (octets)
181 @return CRYPT_OK if successful
182*/
183static int SHA256_Update(struct sha256_state *md,
184 const unsigned char *in,
185 unsigned long inlen)
186{
187 unsigned long n;
188#define block_size 64
189 if(md->curlen > sizeof(md->buf))
190 return -1;
191 while(inlen > 0) {
192 if(md->curlen == 0 && inlen >= block_size) {
193 if(sha256_compress(md, (unsigned char *)in) < 0)
194 return -1;
195 md->length += block_size * 8;
196 in += block_size;
197 inlen -= block_size;
198 }
199 else {
200 n = CURLMIN(inlen, (block_size - md->curlen));
201 memcpy(md->buf + md->curlen, in, n);
202 md->curlen += n;
203 in += n;
204 inlen -= n;
205 if(md->curlen == block_size) {
206 if(sha256_compress(md, md->buf) < 0)
207 return -1;
208 md->length += 8 * block_size;
209 md->curlen = 0;
210 }
211 }
212 }
213 return 0;
214}
215/**
216 Terminate the hash to get the digest
217 @param md The hash state
218 @param out [out] The destination of the hash (32 bytes)
219 @return CRYPT_OK if successful
220*/
221static int SHA256_Final(unsigned char *out,
222 struct sha256_state *md)
223{
224 int i;
225 if(md->curlen >= sizeof(md->buf))
226 return -1;
227 /* increase the length of the message */
228 md->length += md->curlen * 8;
229 /* append the '1' bit */
230 md->buf[md->curlen++] = (unsigned char)0x80;
231 /* if the length is currently above 56 bytes we append zeros
232 * then compress. Then we can fall back to padding zeros and length
233 * encoding like normal.
234 */
235 if(md->curlen > 56) {
236 while(md->curlen < 64) {
237 md->buf[md->curlen++] = (unsigned char)0;
238 }
239 sha256_compress(md, md->buf);
240 md->curlen = 0;
241 }
242 /* pad up to 56 bytes of zeroes */
243 while(md->curlen < 56) {
244 md->buf[md->curlen++] = (unsigned char)0;
245 }
246 /* store length */
247 WPA_PUT_BE64(md->buf + 56, md->length);
248 sha256_compress(md, md->buf);
249 /* copy output */
250 for(i = 0; i < 8; i++)
251 WPA_PUT_BE32(out + (4 * i), md->state[i]);
252 return 0;
253}
254/* ===== end - public domain SHA256 implementation ===== */
255
256#endif
257
258void Curl_sha256it(unsigned char *outbuffer, /* 32 unsigned chars */
259 const unsigned char *input)
260{
261 SHA256_CTX ctx;
262 SHA256_Init(&ctx);
263 SHA256_Update(&ctx, input, curlx_uztoui(strlen((char *)input)));
264 SHA256_Final(outbuffer, &ctx);
265}
266
267#endif /* CURL_DISABLE_CRYPTO_AUTH */
268