Home | History | Annotate | Download | only in lib
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2018, Florin Petriuc, <petriuc.florin (at) 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)                                        \
     56 do {                                                                \
     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)                                    \
     65 do {                                                            \
     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)                                  \
     77 do {                                                          \
     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 
     89 typedef 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 */
     99 static 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 */
    127 static 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 */
    163 static 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 */
    183 static 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 */
    221 static 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 
    258 void 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