Back to index

courier  0.68.2
sha512.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2008 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #define       SHA1_INTERNAL
00007 #include      "sha1.h"
00008 
00009 #include      <string.h>
00010 #include      <stdlib.h>
00011 
00012 
00013 #define ROTR(x,n) ((SHA512_WORD)(((SHA512_WORD)(x) >> (n))|((x) << (64-(n)))))
00014 
00015 #define ROTL(x,n) ((SHA512_WORD)(((SHA512_WORD)(x) << (n))|((x) >> (64-(n)))))
00016 
00017 
00018 #define CH(x,y,z) ((SHA512_WORD)(((x) & (y)) ^ ((~(x))&(z))))
00019 #define MAJ(x,y,z) ((SHA512_WORD)(((x)&(y))^((x)&(z))^((y)&(z))))
00020 
00021 #define SUM0(x) ((SHA512_WORD)(ROTR((x),28)^ROTR((x),34)^ROTR((x),39)))
00022 #define SUM1(x) ((SHA512_WORD)(ROTR((x),14)^ROTR((x),18)^ROTR((x),41)))
00023 
00024 #define TH0(x) ((SHA512_WORD)(ROTR((x),1)^ROTR((x),8)^((SHA512_WORD)(x)>>7)))
00025 #define TH1(x) ((SHA512_WORD)(ROTR((x),19)^ROTR((x),61)^((SHA512_WORD)(x)>>6)))
00026 
00027 static const SHA512_WORD K[80]={
00028        0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
00029        0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
00030        0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
00031        0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
00032        0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
00033        0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
00034        0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
00035        0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
00036        0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
00037        0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
00038        0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
00039        0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
00040        0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
00041        0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
00042        0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
00043        0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
00044        0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
00045        0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
00046        0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
00047        0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
00048 
00049 void sha512_context_init(struct SHA512_CONTEXT *c)
00050 {
00051        if (sizeof(SHA512_WORD) != 8)
00052               abort();
00053 
00054        c->H[0] = 0x6a09e667f3bcc908ULL;
00055        c->H[1] = 0xbb67ae8584caa73bULL;
00056        c->H[2] = 0x3c6ef372fe94f82bULL;
00057        c->H[3] = 0xa54ff53a5f1d36f1ULL;
00058        c->H[4] = 0x510e527fade682d1ULL;
00059        c->H[5] = 0x9b05688c2b3e6c1fULL;
00060        c->H[6] = 0x1f83d9abfb41bd6bULL;
00061        c->H[7] = 0x5be0cd19137e2179ULL;
00062 
00063        c->blk_ptr=0;
00064 }
00065 
00066 void sha512_context_hash(struct SHA512_CONTEXT *cc,
00067                       const unsigned char blk[SHA512_BLOCK_SIZE])
00068 {
00069        SHA512_WORD W[80];
00070        unsigned i, t;
00071        SHA512_WORD a,b,c,d,e,f,g,h;
00072 
00073        for (i=t=0; t<16; t++)
00074        {
00075               SHA512_WORD x=blk[i]; i++;
00076 
00077               x=(x << 8) | blk[i]; i++;
00078               x=(x << 8) | blk[i]; i++;
00079               x=(x << 8) | blk[i]; i++;
00080               x=(x << 8) | blk[i]; i++;
00081               x=(x << 8) | blk[i]; i++;
00082               x=(x << 8) | blk[i]; i++;
00083               W[t]=(x << 8) | blk[i]; i++;
00084        }
00085 
00086        for (t=16; t<80; t++)
00087               W[t]= TH1(W[t-2]) + W[t-7] + TH0(W[t-15]) + W[t-16];
00088 
00089        a=cc->H[0];
00090        b=cc->H[1];
00091        c=cc->H[2];
00092        d=cc->H[3];
00093        e=cc->H[4];
00094        f=cc->H[5];
00095        g=cc->H[6];
00096        h=cc->H[7];
00097 
00098        for (t=0; t<80; t++)
00099        {
00100               SHA512_WORD T1=h + SUM1(e) + CH(e,f,g) + K[t] + W[t];
00101               SHA512_WORD T2=SUM0(a)+MAJ(a,b,c);
00102               h=g;
00103               g=f;
00104               f=e;
00105               e=d+T1;
00106               d=c;
00107               c=b;
00108               b=a;
00109               a=T1+T2;
00110        }
00111 
00112        cc->H[0] += a;
00113        cc->H[1] += b;
00114        cc->H[2] += c;
00115        cc->H[3] += d;
00116        cc->H[4] += e;
00117        cc->H[5] += f;
00118        cc->H[6] += g;
00119        cc->H[7] += h;
00120 }
00121 
00122 void sha512_context_hashstream(struct SHA512_CONTEXT *c, const void *p, unsigned l)
00123 {
00124        const unsigned char *cp=(const unsigned char *)p;
00125        unsigned ll;
00126 
00127        while (l)
00128        {
00129               if (c->blk_ptr == 0 && l >= SHA512_BLOCK_SIZE)
00130               {
00131                      sha512_context_hash(c, cp);
00132                      cp += SHA512_BLOCK_SIZE;
00133                      l -= SHA512_BLOCK_SIZE;
00134                      continue;
00135               }
00136 
00137               ll=l;
00138               if (ll > SHA512_BLOCK_SIZE - c->blk_ptr)
00139                      ll=SHA512_BLOCK_SIZE - c->blk_ptr;
00140               memcpy(c->blk + c->blk_ptr, cp, ll);
00141               c->blk_ptr += ll;
00142               cp += ll;
00143               l -= ll;
00144               if (c->blk_ptr >= SHA512_BLOCK_SIZE)
00145               {
00146                      sha512_context_hash(c, c->blk);
00147                      c->blk_ptr=0;
00148               }
00149        }
00150 }
00151 
00152 void sha512_context_endstream(struct SHA512_CONTEXT *c, SHA512_WORD l)
00153 {
00154        unsigned char buf[16];
00155        size_t i;
00156        static const unsigned char zero[SHA512_BLOCK_SIZE-8];
00157 
00158        buf[0]=0x80;
00159        sha512_context_hashstream(c, &buf, 1);
00160        while (c->blk_ptr != SHA512_BLOCK_SIZE-16)
00161        {
00162               if (c->blk_ptr > SHA512_BLOCK_SIZE-16)
00163               {
00164                      sha512_context_hashstream(c, zero,
00165                             SHA512_BLOCK_SIZE - c->blk_ptr);
00166                      continue;
00167               }
00168               sha512_context_hashstream(c, zero,
00169                      SHA512_BLOCK_SIZE-16-c->blk_ptr);
00170        }
00171 
00172        l *= 8;
00173 
00174        for (i=0; i<16; i++)
00175        {
00176               buf[15-i]=l;
00177               l >>= 8;
00178        }
00179 
00180        sha512_context_hashstream(c, buf, sizeof(buf));
00181 }
00182 
00183 void sha512_context_digest(struct SHA512_CONTEXT *c, SHA512_DIGEST d)
00184 {
00185        unsigned char *dp=d + SHA512_DIGEST_SIZE;
00186        unsigned i;
00187 
00188        for ( i=8; i; )
00189        {
00190               SHA512_WORD   w=c->H[--i];
00191 
00192               *--dp=w; w >>= 8;
00193               *--dp=w; w >>= 8;
00194               *--dp=w; w >>= 8;
00195               *--dp=w; w >>= 8;
00196               *--dp=w; w >>= 8;
00197               *--dp=w; w >>= 8;
00198               *--dp=w; w >>= 8;
00199               *--dp=w;
00200        }
00201 }
00202 
00203 void sha512_context_restore(struct SHA512_CONTEXT *c, const SHA512_DIGEST d)
00204 {
00205        const unsigned char *dp=d;
00206        unsigned i;
00207 
00208        for (i=0; i<8; i++)
00209        {
00210               SHA512_WORD   w= *dp++;
00211 
00212               w=(w << 8) | *dp++;
00213               w=(w << 8) | *dp++;
00214               w=(w << 8) | *dp++;
00215               w=(w << 8) | *dp++;
00216               w=(w << 8) | *dp++;
00217               w=(w << 8) | *dp++;
00218               w=(w << 8) | *dp++;
00219               c->H[i]=w;
00220        }
00221        c->blk_ptr=0;
00222 }
00223 
00224 void sha512_digest(const void *msg, unsigned len, SHA512_DIGEST d)
00225 {
00226        struct SHA512_CONTEXT c;
00227 
00228        sha512_context_init( &c );
00229        sha512_context_hashstream(&c, msg, len);
00230        sha512_context_endstream(&c, len);
00231        sha512_context_digest( &c, d );
00232 }