blob: 55716c63b0ccb003096a5bbfea820735865af1e8 [file] [log] [blame]
Alex Deymo486467e2017-12-19 19:04:07 +01001/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2016, 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
Elliott Hughescac39802018-04-27 16:19:43 -070032#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
Alex Deymo486467e2017-12-19 19:04:07 +010041/* When OpenSSL is available we use the SHA256-function from OpenSSL */
42#include <openssl/sha.h>
Alex Deymo486467e2017-12-19 19:04:07 +010043#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#ifndef MIN
127#define MIN(x, y) (((x) < (y)) ? (x) : (y))
128#endif
129/* compress 512-bits */
130static int sha256_compress(struct sha256_state *md,
131 unsigned char *buf)
132{
133 unsigned long S[8], W[64], t0, t1;
134 unsigned long t;
135 int i;
136 /* copy state into S */
137 for(i = 0; i < 8; i++) {
138 S[i] = md->state[i];
139 }
140 /* copy the state into 512-bits into W[0..15] */
141 for(i = 0; i < 16; i++)
142 W[i] = WPA_GET_BE32(buf + (4 * i));
143 /* fill W[16..63] */
144 for(i = 16; i < 64; i++) {
145 W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
146 W[i - 16];
147 }
148 /* Compress */
149#define RND(a,b,c,d,e,f,g,h,i) \
150 t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
151 t1 = Sigma0(a) + Maj(a, b, c); \
152 d += t0; \
153 h = t0 + t1;
154 for(i = 0; i < 64; ++i) {
155 RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
156 t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
157 S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
158 }
159 /* feedback */
160 for(i = 0; i < 8; i++) {
161 md->state[i] = md->state[i] + S[i];
162 }
163 return 0;
164}
165/* Initialize the hash state */
166static void SHA256_Init(struct sha256_state *md)
167{
168 md->curlen = 0;
169 md->length = 0;
170 md->state[0] = 0x6A09E667UL;
171 md->state[1] = 0xBB67AE85UL;
172 md->state[2] = 0x3C6EF372UL;
173 md->state[3] = 0xA54FF53AUL;
174 md->state[4] = 0x510E527FUL;
175 md->state[5] = 0x9B05688CUL;
176 md->state[6] = 0x1F83D9ABUL;
177 md->state[7] = 0x5BE0CD19UL;
178}
179/**
180 Process a block of memory though the hash
181 @param md The hash state
182 @param in The data to hash
183 @param inlen The length of the data (octets)
184 @return CRYPT_OK if successful
185*/
186static int SHA256_Update(struct sha256_state *md,
187 const unsigned char *in,
188 unsigned long inlen)
189{
190 unsigned long n;
191#define block_size 64
192 if(md->curlen > sizeof(md->buf))
193 return -1;
194 while(inlen > 0) {
195 if(md->curlen == 0 && inlen >= block_size) {
196 if(sha256_compress(md, (unsigned char *)in) < 0)
197 return -1;
198 md->length += block_size * 8;
199 in += block_size;
200 inlen -= block_size;
201 }
202 else {
203 n = MIN(inlen, (block_size - md->curlen));
204 memcpy(md->buf + md->curlen, in, n);
205 md->curlen += n;
206 in += n;
207 inlen -= n;
208 if(md->curlen == block_size) {
209 if(sha256_compress(md, md->buf) < 0)
210 return -1;
211 md->length += 8 * block_size;
212 md->curlen = 0;
213 }
214 }
215 }
216 return 0;
217}
218/**
219 Terminate the hash to get the digest
220 @param md The hash state
221 @param out [out] The destination of the hash (32 bytes)
222 @return CRYPT_OK if successful
223*/
224static int SHA256_Final(unsigned char *out,
225 struct sha256_state *md)
226{
227 int i;
228 if(md->curlen >= sizeof(md->buf))
229 return -1;
230 /* increase the length of the message */
231 md->length += md->curlen * 8;
232 /* append the '1' bit */
233 md->buf[md->curlen++] = (unsigned char)0x80;
234 /* if the length is currently above 56 bytes we append zeros
235 * then compress. Then we can fall back to padding zeros and length
236 * encoding like normal.
237 */
238 if(md->curlen > 56) {
239 while(md->curlen < 64) {
240 md->buf[md->curlen++] = (unsigned char)0;
241 }
242 sha256_compress(md, md->buf);
243 md->curlen = 0;
244 }
Elliott Hughescac39802018-04-27 16:19:43 -0700245 /* pad up to 56 bytes of zeroes */
Alex Deymo486467e2017-12-19 19:04:07 +0100246 while(md->curlen < 56) {
247 md->buf[md->curlen++] = (unsigned char)0;
248 }
249 /* store length */
250 WPA_PUT_BE64(md->buf + 56, md->length);
251 sha256_compress(md, md->buf);
252 /* copy output */
253 for(i = 0; i < 8; i++)
254 WPA_PUT_BE32(out + (4 * i), md->state[i]);
255 return 0;
256}
257/* ===== end - public domain SHA256 implementation ===== */
258
259#endif
260
261void Curl_sha256it(unsigned char *outbuffer, /* 32 unsigned chars */
262 const unsigned char *input)
263{
264 SHA256_CTX ctx;
265 SHA256_Init(&ctx);
266 SHA256_Update(&ctx, input, curlx_uztoui(strlen((char *)input)));
267 SHA256_Final(outbuffer, &ctx);
268}
269
270#endif /* CURL_DISABLE_CRYPTO_AUTH */