00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "postgres.h"
00040
00041 #include <sys/param.h>
00042
00043 #include "sha1.h"
00044
00045
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;
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;
00256 padlen = 64 - padstart;
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 }