jabberd2  2.2.16
util/sha1.c
Go to the documentation of this file.
00001 /* 
00002  * The contents of this file are subject to the Mozilla Public
00003  * License Version 1.1 (the "License"); you may not use this file
00004  * except in compliance with the License. You may obtain a copy of
00005  * the License at http://www.mozilla.org/MPL/
00006  * 
00007  * Software distributed under the License is distributed on an "AS
00008  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
00009  * implied. See the License for the specific language governing
00010  * rights and limitations under the License.
00011  * 
00012  * The Original Code is SHA 180-1 Reference Implementation (Compact version)
00013  * 
00014  * The Initial Developer of the Original Code is Paul Kocher of
00015  * Cryptography Research.  Portions created by Paul Kocher are 
00016  * Copyright (C) 1995-9 by Cryptography Research, Inc.  All
00017  * Rights Reserved.
00018  * 
00019  */
00020 
00021 /* modified for j2 by Robert Norris */
00022 
00023 #include "sha1.h"
00024 #include <string.h>
00025 
00026 static void sha1_hashblock(sha1_state_t *ctx);
00027 
00028 void sha1_init(sha1_state_t *ctx) {
00029   int i;
00030 
00031   ctx->lenW = 0;
00032   ctx->sizeHi = ctx->sizeLo = 0;
00033 
00034   /* Initialize H with the magic constants (see FIPS180 for constants)
00035    */
00036   ctx->H[0] = 0x67452301L;
00037   ctx->H[1] = 0xefcdab89L;
00038   ctx->H[2] = 0x98badcfeL;
00039   ctx->H[3] = 0x10325476L;
00040   ctx->H[4] = 0xc3d2e1f0L;
00041 
00042   for (i = 0; i < 80; i++)
00043     ctx->W[i] = 0;
00044 }
00045 
00046 
00047 void sha1_append(sha1_state_t *ctx, const unsigned char *dataIn, int len) {
00048   int i;
00049 
00050   /* Read the data into W and process blocks as they get full
00051    */
00052   for (i = 0; i < len; i++) {
00053     ctx->W[ctx->lenW / 4] <<= 8;
00054     ctx->W[ctx->lenW / 4] |= (uint32_t)dataIn[i];
00055     if ((++ctx->lenW) % 64 == 0) {
00056       sha1_hashblock(ctx);
00057       ctx->lenW = 0;
00058     }
00059     ctx->sizeLo += 8;
00060     ctx->sizeHi += (ctx->sizeLo < 8);
00061   }
00062 }
00063 
00064 
00065 void sha1_finish(sha1_state_t *ctx, unsigned char hashout[20]) {
00066   unsigned char pad0x80 = 0x80;
00067   unsigned char pad0x00 = 0x00;
00068   unsigned char padlen[8];
00069   int i;
00070 
00071   /* Pad with a binary 1 (e.g. 0x80), then zeroes, then length
00072    */
00073   padlen[0] = (unsigned char)((ctx->sizeHi >> 24) & 255);
00074   padlen[1] = (unsigned char)((ctx->sizeHi >> 16) & 255);
00075   padlen[2] = (unsigned char)((ctx->sizeHi >> 8) & 255);
00076   padlen[3] = (unsigned char)((ctx->sizeHi >> 0) & 255);
00077   padlen[4] = (unsigned char)((ctx->sizeLo >> 24) & 255);
00078   padlen[5] = (unsigned char)((ctx->sizeLo >> 16) & 255);
00079   padlen[6] = (unsigned char)((ctx->sizeLo >> 8) & 255);
00080   padlen[7] = (unsigned char)((ctx->sizeLo >> 0) & 255);
00081   sha1_append(ctx, &pad0x80, 1);
00082   while (ctx->lenW != 56)
00083     sha1_append(ctx, &pad0x00, 1);
00084   sha1_append(ctx, padlen, 8);
00085 
00086   /* Output hash
00087    */
00088   for (i = 0; i < 20; i++) {
00089     hashout[i] = (unsigned char)(ctx->H[i / 4] >> 24);
00090     ctx->H[i / 4] <<= 8;
00091   }
00092 
00093   /*
00094    *  Re-initialize the context (also zeroizes contents)
00095    */
00096   sha1_init(ctx); 
00097 }
00098 
00099 
00100 void sha1_hash(const unsigned char *dataIn, int len, unsigned char hashout[20]) {
00101   sha1_state_t ctx;
00102 
00103   sha1_init(&ctx);
00104   sha1_append(&ctx, dataIn, len);
00105   sha1_finish(&ctx, hashout);
00106 }
00107 
00108 
00109 #define SHA_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xffffffffL)
00110 
00111 static void sha1_hashblock(sha1_state_t *ctx) {
00112   int t;
00113   uint32_t A,B,C,D,E,TEMP;
00114 
00115   for (t = 16; t <= 79; t++)
00116     ctx->W[t] =
00117       SHA_ROTL(ctx->W[t-3] ^ ctx->W[t-8] ^ ctx->W[t-14] ^ ctx->W[t-16], 1);
00118 
00119   A = ctx->H[0];
00120   B = ctx->H[1];
00121   C = ctx->H[2];
00122   D = ctx->H[3];
00123   E = ctx->H[4];
00124 
00125   for (t = 0; t <= 19; t++) {
00126     TEMP = (SHA_ROTL(A,5) + (((C^D)&B)^D)     + E + ctx->W[t] + 0x5a827999L) & 0xffffffffL;
00127     E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
00128   }
00129   for (t = 20; t <= 39; t++) {
00130     TEMP = (SHA_ROTL(A,5) + (B^C^D)           + E + ctx->W[t] + 0x6ed9eba1L) & 0xffffffffL;
00131     E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
00132   }
00133   for (t = 40; t <= 59; t++) {
00134     TEMP = (SHA_ROTL(A,5) + ((B&C)|(D&(B|C))) + E + ctx->W[t] + 0x8f1bbcdcL) & 0xffffffffL;
00135     E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
00136   }
00137   for (t = 60; t <= 79; t++) {
00138     TEMP = (SHA_ROTL(A,5) + (B^C^D)           + E + ctx->W[t] + 0xca62c1d6L) & 0xffffffffL;
00139     E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
00140   }
00141 
00142   ctx->H[0] += A;
00143   ctx->H[1] += B;
00144   ctx->H[2] += C;
00145   ctx->H[3] += D;
00146   ctx->H[4] += E;
00147 }