Home | History | Annotate | Download | only in sha2
      1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
      2  *
      3  * LibTomCrypt is a library that provides various cryptographic
      4  * algorithms in a highly modular and flexible manner.
      5  *
      6  * The library is free for all purposes without any express
      7  * guarantee it works.
      8  *
      9  * Tom St Denis, tomstdenis (at) gmail.com, http://libtomcrypt.com
     10  */
     11 #include "tomcrypt.h"
     12 
     13 /**
     14    @param sha512.c
     15    SHA512 by Tom St Denis
     16 */
     17 
     18 #ifdef SHA512
     19 
     20 const struct ltc_hash_descriptor sha512_desc =
     21 {
     22     "sha512",
     23     5,
     24     64,
     25     128,
     26 
     27     /* OID */
     28    { 2, 16, 840, 1, 101, 3, 4, 2, 3,  },
     29    9,
     30 
     31     &sha512_init,
     32     &sha512_process,
     33     &sha512_done,
     34     &sha512_test,
     35     NULL
     36 };
     37 
     38 /* the K array */
     39 static const ulong64 K[80] = {
     40 CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd),
     41 CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
     42 CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019),
     43 CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),
     44 CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe),
     45 CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),
     46 CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1),
     47 CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),
     48 CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3),
     49 CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),
     50 CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483),
     51 CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),
     52 CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210),
     53 CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),
     54 CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725),
     55 CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),
     56 CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926),
     57 CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),
     58 CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8),
     59 CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),
     60 CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),
     61 CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),
     62 CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910),
     63 CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),
     64 CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53),
     65 CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),
     66 CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb),
     67 CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),
     68 CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60),
     69 CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),
     70 CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9),
     71 CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),
     72 CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207),
     73 CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),
     74 CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6),
     75 CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),
     76 CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493),
     77 CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),
     78 CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a),
     79 CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)
     80 };
     81 
     82 /* Various logical functions */
     83 #define Ch(x,y,z)       (z ^ (x & (y ^ z)))
     84 #define Maj(x,y,z)      (((x | y) & z) | (x & y))
     85 #define S(x, n)         ROR64c(x, n)
     86 #define R(x, n)         (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)n))
     87 #define Sigma0(x)       (S(x, 28) ^ S(x, 34) ^ S(x, 39))
     88 #define Sigma1(x)       (S(x, 14) ^ S(x, 18) ^ S(x, 41))
     89 #define Gamma0(x)       (S(x, 1) ^ S(x, 8) ^ R(x, 7))
     90 #define Gamma1(x)       (S(x, 19) ^ S(x, 61) ^ R(x, 6))
     91 
     92 /* compress 1024-bits */
     93 #ifdef LTC_CLEAN_STACK
     94 static int _sha512_compress(hash_state * md, unsigned char *buf)
     95 #else
     96 static int  sha512_compress(hash_state * md, unsigned char *buf)
     97 #endif
     98 {
     99     ulong64 S[8], W[80], t0, t1;
    100     int i;
    101 
    102     /* copy state into S */
    103     for (i = 0; i < 8; i++) {
    104         S[i] = md->sha512.state[i];
    105     }
    106 
    107     /* copy the state into 1024-bits into W[0..15] */
    108     for (i = 0; i < 16; i++) {
    109         LOAD64H(W[i], buf + (8*i));
    110     }
    111 
    112     /* fill W[16..79] */
    113     for (i = 16; i < 80; i++) {
    114         W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
    115     }
    116 
    117     /* Compress */
    118 #ifdef LTC_SMALL_CODE
    119     for (i = 0; i < 80; i++) {
    120         t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i];
    121         t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]);
    122         S[7] = S[6];
    123         S[6] = S[5];
    124         S[5] = S[4];
    125         S[4] = S[3] + t0;
    126         S[3] = S[2];
    127         S[2] = S[1];
    128         S[1] = S[0];
    129         S[0] = t0 + t1;
    130     }
    131 #else
    132 #define RND(a,b,c,d,e,f,g,h,i)                    \
    133      t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \
    134      t1 = Sigma0(a) + Maj(a, b, c);                  \
    135      d += t0;                                        \
    136      h  = t0 + t1;
    137 
    138      for (i = 0; i < 80; i += 8) {
    139          RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
    140          RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
    141          RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
    142          RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
    143          RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
    144          RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
    145          RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
    146          RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
    147      }
    148 #endif
    149 
    150 
    151     /* feedback */
    152     for (i = 0; i < 8; i++) {
    153         md->sha512.state[i] = md->sha512.state[i] + S[i];
    154     }
    155 
    156     return CRYPT_OK;
    157 }
    158 
    159 /* compress 1024-bits */
    160 #ifdef LTC_CLEAN_STACK
    161 static int sha512_compress(hash_state * md, unsigned char *buf)
    162 {
    163     int err;
    164     err = _sha512_compress(md, buf);
    165     burn_stack(sizeof(ulong64) * 90 + sizeof(int));
    166     return err;
    167 }
    168 #endif
    169 
    170 /**
    171    Initialize the hash state
    172    @param md   The hash state you wish to initialize
    173    @return CRYPT_OK if successful
    174 */
    175 int sha512_init(hash_state * md)
    176 {
    177     LTC_ARGCHK(md != NULL);
    178     md->sha512.curlen = 0;
    179     md->sha512.length = 0;
    180     md->sha512.state[0] = CONST64(0x6a09e667f3bcc908);
    181     md->sha512.state[1] = CONST64(0xbb67ae8584caa73b);
    182     md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b);
    183     md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1);
    184     md->sha512.state[4] = CONST64(0x510e527fade682d1);
    185     md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f);
    186     md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b);
    187     md->sha512.state[7] = CONST64(0x5be0cd19137e2179);
    188     return CRYPT_OK;
    189 }
    190 
    191 /**
    192    Process a block of memory though the hash
    193    @param md     The hash state
    194    @param in     The data to hash
    195    @param inlen  The length of the data (octets)
    196    @return CRYPT_OK if successful
    197 */
    198 HASH_PROCESS(sha512_process, sha512_compress, sha512, 128)
    199 
    200 /**
    201    Terminate the hash to get the digest
    202    @param md  The hash state
    203    @param out [out] The destination of the hash (64 bytes)
    204    @return CRYPT_OK if successful
    205 */
    206 int sha512_done(hash_state * md, unsigned char *out)
    207 {
    208     int i;
    209 
    210     LTC_ARGCHK(md  != NULL);
    211     LTC_ARGCHK(out != NULL);
    212 
    213     if (md->sha512.curlen >= sizeof(md->sha512.buf)) {
    214        return CRYPT_INVALID_ARG;
    215     }
    216 
    217     /* increase the length of the message */
    218     md->sha512.length += md->sha512.curlen * CONST64(8);
    219 
    220     /* append the '1' bit */
    221     md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80;
    222 
    223     /* if the length is currently above 112 bytes we append zeros
    224      * then compress.  Then we can fall back to padding zeros and length
    225      * encoding like normal.
    226      */
    227     if (md->sha512.curlen > 112) {
    228         while (md->sha512.curlen < 128) {
    229             md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
    230         }
    231         sha512_compress(md, md->sha512.buf);
    232         md->sha512.curlen = 0;
    233     }
    234 
    235     /* pad upto 120 bytes of zeroes
    236      * note: that from 112 to 120 is the 64 MSB of the length.  We assume that you won't hash
    237      * > 2^64 bits of data... :-)
    238      */
    239     while (md->sha512.curlen < 120) {
    240         md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
    241     }
    242 
    243     /* store length */
    244     STORE64H(md->sha512.length, md->sha512.buf+120);
    245     sha512_compress(md, md->sha512.buf);
    246 
    247     /* copy output */
    248     for (i = 0; i < 8; i++) {
    249         STORE64H(md->sha512.state[i], out+(8*i));
    250     }
    251 #ifdef LTC_CLEAN_STACK
    252     zeromem(md, sizeof(hash_state));
    253 #endif
    254     return CRYPT_OK;
    255 }
    256 
    257 /**
    258   Self-test the hash
    259   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
    260 */
    261 int  sha512_test(void)
    262 {
    263  #ifndef LTC_TEST
    264     return CRYPT_NOP;
    265  #else
    266   static const struct {
    267       char *msg;
    268       unsigned char hash[64];
    269   } tests[] = {
    270     { "abc",
    271      { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
    272        0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
    273        0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
    274        0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
    275        0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
    276        0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
    277        0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
    278        0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }
    279     },
    280     { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
    281      { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
    282        0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
    283        0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
    284        0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
    285        0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
    286        0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
    287        0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
    288        0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 }
    289     },
    290   };
    291 
    292   int i;
    293   unsigned char tmp[64];
    294   hash_state md;
    295 
    296   for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
    297       sha512_init(&md);
    298       sha512_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
    299       sha512_done(&md, tmp);
    300       if (XMEMCMP(tmp, tests[i].hash, 64) != 0) {
    301          return CRYPT_FAIL_TESTVECTOR;
    302       }
    303   }
    304   return CRYPT_OK;
    305   #endif
    306 }
    307 
    308 #ifdef SHA384
    309    #include "sha384.c"
    310 #endif
    311 
    312 #endif
    313 
    314 
    315 
    316 
    317 /* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha2/sha512.c,v $ */
    318 /* $Revision: 1.8 $ */
    319 /* $Date: 2006/11/01 09:28:17 $ */
    320