LCOV - code coverage report
Current view: top level - libs/sha512/src - sha512.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 85.0 % 80 68
Test Date: 2026-01-12 05:34:38 Functions: 100.0 % 4 4

            Line data    Source code
       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@gmail.com, http://libtom.org
      10              :  */
      11              : 
      12              : #include "sha512.h"
      13              : #include <stdio.h>
      14              : 
      15              : /* the K array */
      16              : static const uint64_t K[80] =
      17              : {
      18              :         UINT64_C(0x428a2f98d728ae22),UINT64_C(0x7137449123ef65cd),
      19              :         UINT64_C(0xb5c0fbcfec4d3b2f),UINT64_C(0xe9b5dba58189dbbc),
      20              :         UINT64_C(0x3956c25bf348b538),UINT64_C(0x59f111f1b605d019),
      21              :         UINT64_C(0x923f82a4af194f9b),UINT64_C(0xab1c5ed5da6d8118),
      22              :         UINT64_C(0xd807aa98a3030242),UINT64_C(0x12835b0145706fbe),
      23              :         UINT64_C(0x243185be4ee4b28c),UINT64_C(0x550c7dc3d5ffb4e2),
      24              :         UINT64_C(0x72be5d74f27b896f),UINT64_C(0x80deb1fe3b1696b1),
      25              :         UINT64_C(0x9bdc06a725c71235),UINT64_C(0xc19bf174cf692694),
      26              :         UINT64_C(0xe49b69c19ef14ad2),UINT64_C(0xefbe4786384f25e3),
      27              :         UINT64_C(0x0fc19dc68b8cd5b5),UINT64_C(0x240ca1cc77ac9c65),
      28              :         UINT64_C(0x2de92c6f592b0275),UINT64_C(0x4a7484aa6ea6e483),
      29              :         UINT64_C(0x5cb0a9dcbd41fbd4),UINT64_C(0x76f988da831153b5),
      30              :         UINT64_C(0x983e5152ee66dfab),UINT64_C(0xa831c66d2db43210),
      31              :         UINT64_C(0xb00327c898fb213f),UINT64_C(0xbf597fc7beef0ee4),
      32              :         UINT64_C(0xc6e00bf33da88fc2),UINT64_C(0xd5a79147930aa725),
      33              :         UINT64_C(0x06ca6351e003826f),UINT64_C(0x142929670a0e6e70),
      34              :         UINT64_C(0x27b70a8546d22ffc),UINT64_C(0x2e1b21385c26c926),
      35              :         UINT64_C(0x4d2c6dfc5ac42aed),UINT64_C(0x53380d139d95b3df),
      36              :         UINT64_C(0x650a73548baf63de),UINT64_C(0x766a0abb3c77b2a8),
      37              :         UINT64_C(0x81c2c92e47edaee6),UINT64_C(0x92722c851482353b),
      38              :         UINT64_C(0xa2bfe8a14cf10364),UINT64_C(0xa81a664bbc423001),
      39              :         UINT64_C(0xc24b8b70d0f89791),UINT64_C(0xc76c51a30654be30),
      40              :         UINT64_C(0xd192e819d6ef5218),UINT64_C(0xd69906245565a910),
      41              :         UINT64_C(0xf40e35855771202a),UINT64_C(0x106aa07032bbd1b8),
      42              :         UINT64_C(0x19a4c116b8d2d0c8),UINT64_C(0x1e376c085141ab53),
      43              :         UINT64_C(0x2748774cdf8eeb99),UINT64_C(0x34b0bcb5e19b48a8),
      44              :         UINT64_C(0x391c0cb3c5c95a63),UINT64_C(0x4ed8aa4ae3418acb),
      45              :         UINT64_C(0x5b9cca4f7763e373),UINT64_C(0x682e6ff3d6b2b8a3),
      46              :         UINT64_C(0x748f82ee5defb2fc),UINT64_C(0x78a5636f43172f60),
      47              :         UINT64_C(0x84c87814a1f0ab72),UINT64_C(0x8cc702081a6439ec),
      48              :         UINT64_C(0x90befffa23631e28),UINT64_C(0xa4506cebde82bde9),
      49              :         UINT64_C(0xbef9a3f7b2c67915),UINT64_C(0xc67178f2e372532b),
      50              :         UINT64_C(0xca273eceea26619c),UINT64_C(0xd186b8c721c0c207),
      51              :         UINT64_C(0xeada7dd6cde0eb1e),UINT64_C(0xf57d4f7fee6ed178),
      52              :         UINT64_C(0x06f067aa72176fba),UINT64_C(0x0a637dc5a2c898a6),
      53              :         UINT64_C(0x113f9804bef90dae),UINT64_C(0x1b710b35131c471b),
      54              :         UINT64_C(0x28db77f523047d84),UINT64_C(0x32caab7b40c72493),
      55              :         UINT64_C(0x3c9ebe0a15c9bebc),UINT64_C(0x431d67c49c100d4c),
      56              :         UINT64_C(0x4cc5d4becb3e42b6),UINT64_C(0x597f299cfc657e2a),
      57              :         UINT64_C(0x5fcb6fab3ad6faec),UINT64_C(0x6c44198c4a475817)
      58              : };
      59              : 
      60              : /* Various logical functions */
      61              : 
      62              : #define ROR64c(x,y) \
      63              :         ( ((((x)&UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)(y)&UINT64_C(63))) | \
      64              :         ((x)<<((uint64_t)(64-((y)&UINT64_C(63))))))&UINT64_C(0xFFFFFFFFFFFFFFFF))
      65              : 
      66              : #define STORE64H(x,y) \
      67              :         { \
      68              :                 (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
      69              :                 (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
      70              :                 (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
      71              :                 (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); \
      72              :         }
      73              : 
      74              : #define LOAD64H(x,y) \
      75              :         { \
      76              :                 x = (((uint64_t)((y)[0] & 255))<<56)|(((uint64_t)((y)[1] & 255))<<48) | \
      77              :                         (((uint64_t)((y)[2] & 255))<<40)|(((uint64_t)((y)[3] & 255))<<32) | \
      78              :                         (((uint64_t)((y)[4] & 255))<<24)|(((uint64_t)((y)[5] & 255))<<16) | \
      79              :                         (((uint64_t)((y)[6] & 255))<<8)|(((uint64_t)((y)[7] & 255))); \
      80              :         }
      81              : 
      82              : #define Ch(x,y,z)       (z ^ (x & (y ^ z)))
      83              : #define Maj(x,y,z)      (((x | y)&z) | (x & y))
      84              : #define S(x,n)         ROR64c(x,n)
      85              : #define R(x,n)         (((x)&UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)n))
      86              : #define Sigma0(x)       (S(x,28) ^ S(x,34) ^ S(x,39))
      87              : #define Sigma1(x)       (S(x,14) ^ S(x,18) ^ S(x,41))
      88              : #define Gamma0(x)       (S(x,1) ^ S(x,8) ^ R(x,7))
      89              : #define Gamma1(x)       (S(x,19) ^ S(x,61) ^ R(x,6))
      90              : #ifndef MIN
      91              : #define MIN(x,y) ( ((x)<(y))?(x):(y) )
      92              : #endif
      93              : 
      94              : /* compress 1024-bits */
      95        13419 : static int sha512_compress(
      96              :         SHA512_Context      *md,
      97              :         const unsigned char *buf)
      98              : {
      99              :         uint64_t S[8],W[80],t0,t1;
     100              :         int i;
     101              : 
     102              :         /* copy state into S */
     103       120771 :         for(i = 0; i < 8; i++)
     104              :         {
     105       107352 :                 S[i] = md->state[i];
     106              :         }
     107              : 
     108              :         /* copy the state into 1024-bits into W[0..15] */
     109       228123 :         for(i = 0; i < 16; i++)
     110              :         {
     111       214704 :                 LOAD64H(W[i],buf + (8*i));
     112              :         }
     113              : 
     114              :         /* fill W[16..79] */
     115       872235 :         for(i = 16; i < 80; i++)
     116              :         {
     117       858816 :                 W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
     118              :         }
     119              : 
     120              :         /* Compress */
     121              :     #define RND(a,b,c,d,e,f,g,h,i) \
     122              :             t0 = h + Sigma1(e) + Ch(e,f,g) + K[i] + W[i]; \
     123              :             t1 = Sigma0(a) + Maj(a,b,c); \
     124              :             d += t0; \
     125              :             h = t0 + t1;
     126              : 
     127       147609 :         for(i = 0; i < 80; i += 8)
     128              :         {
     129       134190 :                 RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
     130       134190 :                 RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
     131       134190 :                 RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
     132       134190 :                 RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
     133       134190 :                 RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
     134       134190 :                 RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
     135       134190 :                 RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
     136       134190 :                 RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
     137              :         }
     138              : 
     139              :     #undef RND
     140              : 
     141              :         /* feedback */
     142       120771 :         for(i = 0; i < 8; i++)
     143              :         {
     144       107352 :                 md->state[i] = md->state[i] + S[i];
     145              :         }
     146              : 
     147        13419 :         return 0;
     148              : }
     149              : 
     150              : /**
     151              :    Initialize the hash state
     152              :    @param md   The hash state you wish to initialize
     153              :    @return 0 if successful
     154              :  */
     155         1903 : int sha512_init(SHA512_Context *md)
     156              : {
     157         1903 :         if(md == NULL)
     158              :         {
     159            0 :                 return 1;
     160              :         }
     161              : 
     162         1903 :         md->curlen = 0;
     163         1903 :         md->length = 0;
     164         1903 :         md->state[0] = UINT64_C(0x6a09e667f3bcc908);
     165         1903 :         md->state[1] = UINT64_C(0xbb67ae8584caa73b);
     166         1903 :         md->state[2] = UINT64_C(0x3c6ef372fe94f82b);
     167         1903 :         md->state[3] = UINT64_C(0xa54ff53a5f1d36f1);
     168         1903 :         md->state[4] = UINT64_C(0x510e527fade682d1);
     169         1903 :         md->state[5] = UINT64_C(0x9b05688c2b3e6c1f);
     170         1903 :         md->state[6] = UINT64_C(0x1f83d9abfb41bd6b);
     171         1903 :         md->state[7] = UINT64_C(0x5be0cd19137e2179);
     172              : 
     173         1903 :         return 0;
     174              : }
     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 0 if successful
     182              :  */
     183         1867 : int sha512_update(
     184              :         SHA512_Context      *md,
     185              :         const unsigned char *in,
     186              :         size_t              inlen)
     187              : {
     188              :         size_t n;
     189              :         size_t i;
     190              :         int err;
     191              : 
     192         1867 :         if(md == NULL)
     193              :         {
     194            0 :                 return 1;
     195              :         }
     196              : 
     197         1867 :         if(in == NULL)
     198              :         {
     199            0 :                 return 1;
     200              :         }
     201              : 
     202         1867 :         if(md->curlen > sizeof(md->buf))
     203              :         {
     204            0 :                 return 1;
     205              :         }
     206              : 
     207        15094 :         while(inlen > 0)
     208              :         {
     209        13227 :                 if(md->curlen == 0 && inlen >= 128)
     210              :                 {
     211        11400 :                         if((err = sha512_compress (md,in)) != 0)
     212              :                         {
     213            0 :                                 return err;
     214              :                         }
     215        11400 :                         md->length += 128 * 8;
     216        11400 :                         in += 128;
     217        11400 :                         inlen -= 128;
     218              :                 } else {
     219         1827 :                         n = MIN(inlen,(128 - md->curlen));
     220              : 
     221        57452 :                         for(i = 0; i < n; i++)
     222              :                         {
     223        55625 :                                 md->buf[i + md->curlen] = in[i];
     224              :                         }
     225              : 
     226         1827 :                         md->curlen += n;
     227         1827 :                         in += n;
     228         1827 :                         inlen -= n;
     229              : 
     230         1827 :                         if(md->curlen == 128)
     231              :                         {
     232            0 :                                 if((err = sha512_compress (md,md->buf)) != 0)
     233              :                                 {
     234            0 :                                         return err;
     235              :                                 }
     236            0 :                                 md->length += 8*128;
     237            0 :                                 md->curlen = 0;
     238              :                         }
     239              :                 }
     240              :         }
     241         1867 :         return 0;
     242              : }
     243              : 
     244              : /**
     245              :    Terminate the hash to get the digest
     246              :    @param md  The hash state
     247              :    @param out [out] The destination of the hash (64 bytes)
     248              :    @return 0 if successful
     249              :  */
     250         1903 : int sha512_final(
     251              :         SHA512_Context *md,
     252              :         unsigned char  *out)
     253              : {
     254              :         int i;
     255              : 
     256         1903 :         if(md == NULL)
     257              :         {
     258            0 :                 return 1;
     259              :         }
     260              : 
     261         1903 :         if(out == NULL)
     262              :         {
     263            0 :                 return 1;
     264              :         }
     265              : 
     266         1903 :         if(md->curlen >= sizeof(md->buf))
     267              :         {
     268            0 :                 return 1;
     269              :         }
     270              : 
     271              :         /* increase the length of the message */
     272         1903 :         md->length += md->curlen * UINT64_C(8);
     273              : 
     274              :         /* append the '1' bit */
     275         1903 :         md->buf[md->curlen++] = (unsigned char)0x80;
     276              : 
     277              :         /* if the length is currently above 112 bytes we append zeros
     278              :          * then compress.  Then we can fall back to padding zeros and length
     279              :          * encoding like normal.
     280              :          */
     281         1903 :         if(md->curlen > 112)
     282              :         {
     283         1124 :                 while(md->curlen < 128)
     284              :                 {
     285         1008 :                         md->buf[md->curlen++] = (unsigned char)0;
     286              :                 }
     287          116 :                 sha512_compress(md,md->buf);
     288          116 :                 md->curlen = 0;
     289              :         }
     290              : 
     291              :         /* pad upto 120 bytes of zeroes
     292              :          * note: that from 112 to 120 is the 64 MSB of the length.  We assume that you won't hash
     293              :          * > 2^64 bits of data... :-)
     294              :          */
     295       186575 :         while(md->curlen < 120)
     296              :         {
     297       184672 :                 md->buf[md->curlen++] = (unsigned char)0;
     298              :         }
     299              : 
     300              :         /* store length */
     301         1903 :         STORE64H(md->length,md->buf+120);
     302         1903 :         sha512_compress(md,md->buf);
     303              : 
     304              :         /* copy output */
     305        17127 :         for(i = 0; i < 8; i++)
     306              :         {
     307        15224 :                 STORE64H(md->state[i],out+(8*i));
     308              :         }
     309              : 
     310         1903 :         return 0;
     311              : }
     312              : 
     313              : #if 0
     314              : void test(
     315              :         const unsigned char *message,
     316              :         size_t              message_len,
     317              :         unsigned char       *out)
     318              : {
     319              :         // int ret;
     320              :         // if ((ret = sha512_init(&ctx))) return ret;
     321              :         // if ((ret = sha512_update(&ctx, message, message_len))) return ret;
     322              :         // if ((ret = sha512_final(&ctx, out))) return ret;
     323              : 
     324              :         SHA512_Context ctx;
     325              :         sha512_init(&ctx);
     326              :         sha512_update(&ctx,message,message_len);
     327              :         sha512_final(&ctx,out);
     328              : }
     329              : 
     330              : int main(void)
     331              : {
     332              :         unsigned char out[SHA512_DIGEST_LENGTH];
     333              :         const unsigned char message[] = "Hello World";
     334              :         test(message,sizeof(message),out);
     335              : 
     336              :         for(size_t i = 0; i < 64; i++)
     337              :         {
     338              :                 printf("%02x",out[i]);
     339              :         }
     340              :         putchar('\n');
     341              : 
     342              :         return(0);
     343              : }
     344              : #endif
        

Generated by: LCOV version 2.0-1