xmpp/sha.c

Go to the documentation of this file.
00001 /*
00002  * $Id: sha.c 4494 2008-07-22 13:43:48Z henningw $
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  * 
00018  *  Gabber
00019  *  Copyright (C) 1999-2000 Dave Smith & Julian Missig
00020  *
00021  */
00022 
00023 /*! \file
00024  * \ingroup xmpp
00025  */
00026 
00027 
00028 /* 
00029    Implements the Secure Hash Algorithm (SHA1)
00030 
00031    Copyright (C) 1999 Scott G. Miller
00032 
00033    Released under the terms of the GNU General Public License v2
00034    see file COPYING for details
00035 
00036    Credits: 
00037       Robert Klep <robert@ilse.nl>  -- Expansion function fix 
00038      Thomas "temas" Muldowney <temas@box5.net>:
00039          -- shahash() for string fun
00040          -- Will add the int32 stuff in a few
00041          
00042    ---
00043    FIXME: This source takes int to be a 32 bit integer.  This
00044    may vary from system to system.  I'd use autoconf if I was familiar
00045    with it.  Anyone want to help me out?
00046 */
00047 
00048 //#include <config.h>
00049 
00050 #include <stdio.h>
00051 #include <stdlib.h>
00052 #include <fcntl.h>
00053 #include <string.h>
00054 
00055 #ifndef MACOS
00056 #  include <sys/stat.h>
00057 #  include <sys/types.h>
00058 #endif
00059 #ifndef WIN32
00060 #  include <unistd.h>
00061 #  define INT64 long long
00062 #else
00063 #  define snprintf _snprintf
00064 #  define INT64 __int64
00065 #endif
00066 
00067 #define switch_endianness(x) (x<<24 & 0xff000000) | \
00068                              (x<<8  & 0x00ff0000) | \
00069                              (x>>8  & 0x0000ff00) | \
00070                              (x>>24 & 0x000000ff)
00071 
00072 /* Initial hash values */
00073 #define Ai 0x67452301 
00074 #define Bi 0xefcdab89
00075 #define Ci 0x98badcfe
00076 #define Di 0x10325476
00077 #define Ei 0xc3d2e1f0
00078 
00079 /* SHA1 round constants */
00080 #define K1 0x5a827999
00081 #define K2 0x6ed9eba1
00082 #define K3 0x8f1bbcdc 
00083 #define K4 0xca62c1d6
00084 
00085 /* Round functions.  Note that f2() is used in both rounds 2 and 4 */
00086 #define f1(B,C,D) ((B & C) | ((~B) & D))
00087 #define f2(B,C,D) (B ^ C ^ D)
00088 #define f3(B,C,D) ((B & C) | (B & D) | (C & D))
00089 
00090 /* left circular shift functions (rotate left) */
00091 #define rol1(x) ((x<<1) | ((x>>31) & 1))
00092 #define rol5(A) ((A<<5) | ((A>>27) & 0x1f))
00093 #define rol30(B) ((B<<30) | ((B>>2) & 0x3fffffff))
00094 
00095 /*
00096   Hashes 'data', which should be a pointer to 512 bits of data (sixteen
00097   32 bit ints), into the ongoing 160 bit hash value (five 32 bit ints)
00098   'hash'
00099 */
00100 int 
00101 sha_hash(int *data, int *hash)  
00102 {
00103   int W[80];
00104   unsigned int A=hash[0], B=hash[1], C=hash[2], D=hash[3], E=hash[4];
00105   unsigned int t, x, TEMP;
00106 
00107   for (t=0; t<16; t++) 
00108     {
00109 #ifndef WORDS_BIGENDIAN
00110       W[t]=switch_endianness(data[t]);
00111 #else 
00112       W[t]=data[t];
00113 #endif
00114     }
00115 
00116 
00117   /* SHA1 Data expansion */
00118   for (t=16; t<80; t++) 
00119     {
00120       x=W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
00121       W[t]=rol1(x);
00122     }
00123 
00124   /* SHA1 main loop (t=0 to 79) 
00125    This is broken down into four subloops in order to use
00126    the correct round function and constant */
00127   for (t=0; t<20; t++) 
00128     {
00129       TEMP=rol5(A) + f1(B,C,D) + E + W[t] + K1;
00130       E=D;
00131       D=C;
00132       C=rol30(B);
00133       B=A;
00134       A=TEMP;
00135     }
00136   for (; t<40; t++) 
00137     {
00138       TEMP=rol5(A) + f2(B,C,D) + E + W[t] + K2;
00139       E=D;
00140       D=C;
00141       C=rol30(B);
00142       B=A;
00143       A=TEMP;
00144     }
00145   for (; t<60; t++) 
00146     {
00147       TEMP=rol5(A) + f3(B,C,D) + E + W[t] + K3;
00148       E=D;
00149       D=C;
00150       C=rol30(B);
00151       B=A;
00152       A=TEMP;
00153     }
00154   for (; t<80; t++) 
00155     {
00156       TEMP=rol5(A) + f2(B,C,D) + E + W[t] + K4;
00157       E=D;
00158       D=C;
00159       C=rol30(B);
00160       B=A;
00161       A=TEMP;
00162     }
00163   hash[0]+=A; 
00164   hash[1]+=B;
00165   hash[2]+=C;
00166   hash[3]+=D;
00167   hash[4]+=E;
00168   return 0;
00169 }
00170 
00171 /*
00172   Takes a pointer to a 160 bit block of data (five 32 bit ints) and
00173   initializes it to the start constants of the SHA1 algorithm.  This
00174   must be called before using hash in the call to sha_hash
00175 */
00176 int 
00177 sha_init(int *hash) 
00178 {
00179   hash[0]=Ai;
00180   hash[1]=Bi;
00181   hash[2]=Ci;
00182   hash[3]=Di;
00183   hash[4]=Ei;
00184   return 0;
00185 }
00186 
00187 int strprintsha(char *dest, int *hashval) 
00188 {
00189    int x;
00190    char *hashstr = dest;
00191    for (x=0; x<5; x++) 
00192    {
00193       snprintf(hashstr, 9, "%08x", hashval[x]);
00194       hashstr+=8;
00195    }
00196    /*old way */
00197    //snprintf(hashstr++, 1, "\0");
00198    /*new way - by bogdan*/
00199    *hashstr = 0;
00200 
00201    return 0;
00202 }
00203 
00204 char *shahash(const char *str) 
00205 {
00206    char read_buffer[65];
00207    //int read_buffer[64];
00208    int c=1, i;
00209        
00210    INT64 length=0;
00211 
00212    int strsz;
00213    static char final[40];
00214    int *hashval;
00215 
00216    hashval = (int *)malloc(20);
00217 
00218    sha_init(hashval);
00219 
00220    strsz = strlen(str);
00221 
00222    if(strsz == 0) 
00223    {
00224         memset(read_buffer, 0, 65);
00225         read_buffer[0] = 0x80;
00226         sha_hash((int *)read_buffer, hashval);
00227    }
00228 
00229    while (strsz>0) 
00230    {
00231       memset(read_buffer, 0, 65);
00232       strncpy((char*)read_buffer, str, 64);
00233       c = strlen((char *)read_buffer);
00234       length+=c;
00235       strsz-=c;
00236       if (strsz<=0) 
00237       {
00238          length<<=3; 
00239          read_buffer[c]=(char)0x80;
00240          for (i=c+1; i<64; i++) 
00241             read_buffer[i]=0;
00242          if (c>55) 
00243          {
00244             /* we need to do an entire new block */
00245             sha_hash((int *)read_buffer, hashval);
00246             for (i=0; i<14; i++) 
00247                ((int*)read_buffer)[i]=0;
00248          }      
00249 #ifndef WORDS_BIGENDIAN
00250          for (i=0; i<8; i++) 
00251          {
00252             read_buffer[56+i]=(char)(length>>(56-(i*8))) & 0xff;
00253          }
00254 #else 
00255          memcpy(read_buffer+56, &length, 8);
00256 #endif
00257       }
00258       
00259       sha_hash((int *)read_buffer, hashval);
00260       str+=64;
00261    }
00262 
00263    strprintsha((char *)final, hashval);
00264    free(hashval);
00265    return (char *)final;
00266 }

Generated on Fri May 25 00:00:31 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6