Header And Logo

PostgreSQL
| The world's most advanced open source database.

sha1.c

Go to the documentation of this file.
00001 /*     $KAME: sha1.c,v 1.3 2000/02/22 14:01:18 itojun Exp $    */
00002 
00003 /*
00004  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  * 1. Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  * 2. Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in the
00014  *    documentation and/or other materials provided with the distribution.
00015  * 3. Neither the name of the project nor the names of its contributors
00016  *    may be used to endorse or promote products derived from this software
00017  *    without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
00020  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
00023  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00024  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00025  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00026  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00027  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00028  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00029  * SUCH DAMAGE.
00030  *
00031  * contrib/pgcrypto/sha1.c
00032  */
00033 /*
00034  * FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
00035  * based on: http://www.itl.nist.gov/fipspubs/fip180-1.htm
00036  * implemented by Jun-ichiro itojun Itoh <[email protected]>
00037  */
00038 
00039 #include "postgres.h"
00040 
00041 #include <sys/param.h>
00042 
00043 #include "sha1.h"
00044 
00045 /* constant table */
00046 static uint32 _K[] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6};
00047 
00048 #define K(t)    _K[(t) / 20]
00049 
00050 #define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d)))
00051 #define F1(b, c, d) (((b) ^ (c)) ^ (d))
00052 #define F2(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
00053 #define F3(b, c, d) (((b) ^ (c)) ^ (d))
00054 
00055 #define S(n, x)     (((x) << (n)) | ((x) >> (32 - (n))))
00056 
00057 #define H(n)    (ctxt->h.b32[(n)])
00058 #define COUNT   (ctxt->count)
00059 #define BCOUNT  (ctxt->c.b64[0] / 8)
00060 #define W(n)    (ctxt->m.b32[(n)])
00061 
00062 #define PUTBYTE(x) \
00063 do { \
00064     ctxt->m.b8[(COUNT % 64)] = (x);     \
00065     COUNT++;                \
00066     COUNT %= 64;                \
00067     ctxt->c.b64[0] += 8;            \
00068     if (COUNT % 64 == 0)            \
00069         sha1_step(ctxt);        \
00070 } while (0)
00071 
00072 #define PUTPAD(x) \
00073 do { \
00074     ctxt->m.b8[(COUNT % 64)] = (x);     \
00075     COUNT++;                \
00076     COUNT %= 64;                \
00077     if (COUNT % 64 == 0)            \
00078         sha1_step(ctxt);        \
00079 } while (0)
00080 
00081 static void sha1_step(struct sha1_ctxt *);
00082 
00083 static void
00084 sha1_step(struct sha1_ctxt * ctxt)
00085 {
00086     uint32      a,
00087                 b,
00088                 c,
00089                 d,
00090                 e;
00091     size_t      t,
00092                 s;
00093     uint32      tmp;
00094 
00095 #ifndef WORDS_BIGENDIAN
00096     struct sha1_ctxt tctxt;
00097 
00098     memmove(&tctxt.m.b8[0], &ctxt->m.b8[0], 64);
00099     ctxt->m.b8[0] = tctxt.m.b8[3];
00100     ctxt->m.b8[1] = tctxt.m.b8[2];
00101     ctxt->m.b8[2] = tctxt.m.b8[1];
00102     ctxt->m.b8[3] = tctxt.m.b8[0];
00103     ctxt->m.b8[4] = tctxt.m.b8[7];
00104     ctxt->m.b8[5] = tctxt.m.b8[6];
00105     ctxt->m.b8[6] = tctxt.m.b8[5];
00106     ctxt->m.b8[7] = tctxt.m.b8[4];
00107     ctxt->m.b8[8] = tctxt.m.b8[11];
00108     ctxt->m.b8[9] = tctxt.m.b8[10];
00109     ctxt->m.b8[10] = tctxt.m.b8[9];
00110     ctxt->m.b8[11] = tctxt.m.b8[8];
00111     ctxt->m.b8[12] = tctxt.m.b8[15];
00112     ctxt->m.b8[13] = tctxt.m.b8[14];
00113     ctxt->m.b8[14] = tctxt.m.b8[13];
00114     ctxt->m.b8[15] = tctxt.m.b8[12];
00115     ctxt->m.b8[16] = tctxt.m.b8[19];
00116     ctxt->m.b8[17] = tctxt.m.b8[18];
00117     ctxt->m.b8[18] = tctxt.m.b8[17];
00118     ctxt->m.b8[19] = tctxt.m.b8[16];
00119     ctxt->m.b8[20] = tctxt.m.b8[23];
00120     ctxt->m.b8[21] = tctxt.m.b8[22];
00121     ctxt->m.b8[22] = tctxt.m.b8[21];
00122     ctxt->m.b8[23] = tctxt.m.b8[20];
00123     ctxt->m.b8[24] = tctxt.m.b8[27];
00124     ctxt->m.b8[25] = tctxt.m.b8[26];
00125     ctxt->m.b8[26] = tctxt.m.b8[25];
00126     ctxt->m.b8[27] = tctxt.m.b8[24];
00127     ctxt->m.b8[28] = tctxt.m.b8[31];
00128     ctxt->m.b8[29] = tctxt.m.b8[30];
00129     ctxt->m.b8[30] = tctxt.m.b8[29];
00130     ctxt->m.b8[31] = tctxt.m.b8[28];
00131     ctxt->m.b8[32] = tctxt.m.b8[35];
00132     ctxt->m.b8[33] = tctxt.m.b8[34];
00133     ctxt->m.b8[34] = tctxt.m.b8[33];
00134     ctxt->m.b8[35] = tctxt.m.b8[32];
00135     ctxt->m.b8[36] = tctxt.m.b8[39];
00136     ctxt->m.b8[37] = tctxt.m.b8[38];
00137     ctxt->m.b8[38] = tctxt.m.b8[37];
00138     ctxt->m.b8[39] = tctxt.m.b8[36];
00139     ctxt->m.b8[40] = tctxt.m.b8[43];
00140     ctxt->m.b8[41] = tctxt.m.b8[42];
00141     ctxt->m.b8[42] = tctxt.m.b8[41];
00142     ctxt->m.b8[43] = tctxt.m.b8[40];
00143     ctxt->m.b8[44] = tctxt.m.b8[47];
00144     ctxt->m.b8[45] = tctxt.m.b8[46];
00145     ctxt->m.b8[46] = tctxt.m.b8[45];
00146     ctxt->m.b8[47] = tctxt.m.b8[44];
00147     ctxt->m.b8[48] = tctxt.m.b8[51];
00148     ctxt->m.b8[49] = tctxt.m.b8[50];
00149     ctxt->m.b8[50] = tctxt.m.b8[49];
00150     ctxt->m.b8[51] = tctxt.m.b8[48];
00151     ctxt->m.b8[52] = tctxt.m.b8[55];
00152     ctxt->m.b8[53] = tctxt.m.b8[54];
00153     ctxt->m.b8[54] = tctxt.m.b8[53];
00154     ctxt->m.b8[55] = tctxt.m.b8[52];
00155     ctxt->m.b8[56] = tctxt.m.b8[59];
00156     ctxt->m.b8[57] = tctxt.m.b8[58];
00157     ctxt->m.b8[58] = tctxt.m.b8[57];
00158     ctxt->m.b8[59] = tctxt.m.b8[56];
00159     ctxt->m.b8[60] = tctxt.m.b8[63];
00160     ctxt->m.b8[61] = tctxt.m.b8[62];
00161     ctxt->m.b8[62] = tctxt.m.b8[61];
00162     ctxt->m.b8[63] = tctxt.m.b8[60];
00163 #endif
00164 
00165     a = H(0);
00166     b = H(1);
00167     c = H(2);
00168     d = H(3);
00169     e = H(4);
00170 
00171     for (t = 0; t < 20; t++)
00172     {
00173         s = t & 0x0f;
00174         if (t >= 16)
00175             W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
00176         tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t);
00177         e = d;
00178         d = c;
00179         c = S(30, b);
00180         b = a;
00181         a = tmp;
00182     }
00183     for (t = 20; t < 40; t++)
00184     {
00185         s = t & 0x0f;
00186         W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
00187         tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t);
00188         e = d;
00189         d = c;
00190         c = S(30, b);
00191         b = a;
00192         a = tmp;
00193     }
00194     for (t = 40; t < 60; t++)
00195     {
00196         s = t & 0x0f;
00197         W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
00198         tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t);
00199         e = d;
00200         d = c;
00201         c = S(30, b);
00202         b = a;
00203         a = tmp;
00204     }
00205     for (t = 60; t < 80; t++)
00206     {
00207         s = t & 0x0f;
00208         W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
00209         tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t);
00210         e = d;
00211         d = c;
00212         c = S(30, b);
00213         b = a;
00214         a = tmp;
00215     }
00216 
00217     H(0) = H(0) + a;
00218     H(1) = H(1) + b;
00219     H(2) = H(2) + c;
00220     H(3) = H(3) + d;
00221     H(4) = H(4) + e;
00222 
00223     memset(&ctxt->m.b8[0], 0, 64);
00224 }
00225 
00226 /*------------------------------------------------------------*/
00227 
00228 void
00229 sha1_init(struct sha1_ctxt * ctxt)
00230 {
00231     memset(ctxt, 0, sizeof(struct sha1_ctxt));
00232     H(0) = 0x67452301;
00233     H(1) = 0xefcdab89;
00234     H(2) = 0x98badcfe;
00235     H(3) = 0x10325476;
00236     H(4) = 0xc3d2e1f0;
00237 }
00238 
00239 void
00240 sha1_pad(struct sha1_ctxt * ctxt)
00241 {
00242     size_t      padlen;         /* pad length in bytes */
00243     size_t      padstart;
00244 
00245     PUTPAD(0x80);
00246 
00247     padstart = COUNT % 64;
00248     padlen = 64 - padstart;
00249     if (padlen < 8)
00250     {
00251         memset(&ctxt->m.b8[padstart], 0, padlen);
00252         COUNT += padlen;
00253         COUNT %= 64;
00254         sha1_step(ctxt);
00255         padstart = COUNT % 64;  /* should be 0 */
00256         padlen = 64 - padstart; /* should be 64 */
00257     }
00258     memset(&ctxt->m.b8[padstart], 0, padlen - 8);
00259     COUNT += (padlen - 8);
00260     COUNT %= 64;
00261 #ifdef WORDS_BIGENDIAN
00262     PUTPAD(ctxt->c.b8[0]);
00263     PUTPAD(ctxt->c.b8[1]);
00264     PUTPAD(ctxt->c.b8[2]);
00265     PUTPAD(ctxt->c.b8[3]);
00266     PUTPAD(ctxt->c.b8[4]);
00267     PUTPAD(ctxt->c.b8[5]);
00268     PUTPAD(ctxt->c.b8[6]);
00269     PUTPAD(ctxt->c.b8[7]);
00270 #else
00271     PUTPAD(ctxt->c.b8[7]);
00272     PUTPAD(ctxt->c.b8[6]);
00273     PUTPAD(ctxt->c.b8[5]);
00274     PUTPAD(ctxt->c.b8[4]);
00275     PUTPAD(ctxt->c.b8[3]);
00276     PUTPAD(ctxt->c.b8[2]);
00277     PUTPAD(ctxt->c.b8[1]);
00278     PUTPAD(ctxt->c.b8[0]);
00279 #endif
00280 }
00281 
00282 void
00283 sha1_loop(struct sha1_ctxt * ctxt, const uint8 *input0, size_t len)
00284 {
00285     const uint8 *input;
00286     size_t      gaplen;
00287     size_t      gapstart;
00288     size_t      off;
00289     size_t      copysiz;
00290 
00291     input = (const uint8 *) input0;
00292     off = 0;
00293 
00294     while (off < len)
00295     {
00296         gapstart = COUNT % 64;
00297         gaplen = 64 - gapstart;
00298 
00299         copysiz = (gaplen < len - off) ? gaplen : len - off;
00300         memmove(&ctxt->m.b8[gapstart], &input[off], copysiz);
00301         COUNT += copysiz;
00302         COUNT %= 64;
00303         ctxt->c.b64[0] += copysiz * 8;
00304         if (COUNT % 64 == 0)
00305             sha1_step(ctxt);
00306         off += copysiz;
00307     }
00308 }
00309 
00310 void
00311 sha1_result(struct sha1_ctxt * ctxt, uint8 *digest0)
00312 {
00313     uint8      *digest;
00314 
00315     digest = (uint8 *) digest0;
00316     sha1_pad(ctxt);
00317 #ifdef WORDS_BIGENDIAN
00318     memmove(digest, &ctxt->h.b8[0], 20);
00319 #else
00320     digest[0] = ctxt->h.b8[3];
00321     digest[1] = ctxt->h.b8[2];
00322     digest[2] = ctxt->h.b8[1];
00323     digest[3] = ctxt->h.b8[0];
00324     digest[4] = ctxt->h.b8[7];
00325     digest[5] = ctxt->h.b8[6];
00326     digest[6] = ctxt->h.b8[5];
00327     digest[7] = ctxt->h.b8[4];
00328     digest[8] = ctxt->h.b8[11];
00329     digest[9] = ctxt->h.b8[10];
00330     digest[10] = ctxt->h.b8[9];
00331     digest[11] = ctxt->h.b8[8];
00332     digest[12] = ctxt->h.b8[15];
00333     digest[13] = ctxt->h.b8[14];
00334     digest[14] = ctxt->h.b8[13];
00335     digest[15] = ctxt->h.b8[12];
00336     digest[16] = ctxt->h.b8[19];
00337     digest[17] = ctxt->h.b8[18];
00338     digest[18] = ctxt->h.b8[17];
00339     digest[19] = ctxt->h.b8[16];
00340 #endif
00341 }