diff options
author | Wilmer van der Gaast <wilmer@gaast.net> | 2007-11-23 23:07:44 +0000 |
---|---|---|
committer | Wilmer van der Gaast <wilmer@gaast.net> | 2007-11-23 23:07:44 +0000 |
commit | 77bfd077778c30c70f791752ce3a13d537aedd3b (patch) | |
tree | b75b50003195e89c58ca3698a396c458d9ebea89 /lib | |
parent | df6d1da013f42caa5f11dbcbb0d54710682811f7 (diff) |
Replaced GPL-incompatible SHA1 hashing code (and renamed the files in case
I ever need SHA256 ;-)).
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile | 2 | ||||
-rw-r--r-- | lib/sha.c | 173 | ||||
-rw-r--r-- | lib/sha.h | 21 | ||||
-rw-r--r-- | lib/sha1.c | 375 | ||||
-rw-r--r-- | lib/sha1.h | 66 |
5 files changed, 442 insertions, 195 deletions
diff --git a/lib/Makefile b/lib/Makefile index bc1966d9..a79f7c4c 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -9,7 +9,7 @@ -include ../Makefile.settings # [SH] Program variables -objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha.o $(SSL_CLIENT) url.o +objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha1.o $(SSL_CLIENT) url.o CFLAGS += -Wall LFLAGS += -r diff --git a/lib/sha.c b/lib/sha.c deleted file mode 100644 index 895505a1..00000000 --- a/lib/sha.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is SHA 180-1 Reference Implementation (Compact version) - * - * The Initial Developer of the Original Code is Paul Kocher of - * Cryptography Research. Portions created by Paul Kocher are - * Copyright (C) 1995-9 by Cryptography Research, Inc. All - * Rights Reserved. - * - * Contributor(s): - * - */ - -#define BITLBEE_CORE -#include "nogaim.h" - -static void shaHashBlock(SHA_CTX *ctx); - -void shaInit(SHA_CTX *ctx) { - int i; - - ctx->lenW = 0; - ctx->sizeHi = ctx->sizeLo = 0; - - /* Initialize H with the magic constants (see FIPS180 for constants) - */ - ctx->H[0] = 0x67452301L; - ctx->H[1] = 0xefcdab89L; - ctx->H[2] = 0x98badcfeL; - ctx->H[3] = 0x10325476L; - ctx->H[4] = 0xc3d2e1f0L; - - for (i = 0; i < 80; i++) - ctx->W[i] = 0; -} - - -void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len) { - int i; - - /* Read the data into W and process blocks as they get full - */ - for (i = 0; i < len; i++) { - ctx->W[ctx->lenW / 4] <<= 8; - ctx->W[ctx->lenW / 4] |= (guint32)dataIn[i]; - if ((++ctx->lenW) % 64 == 0) { - shaHashBlock(ctx); - ctx->lenW = 0; - } - ctx->sizeLo += 8; - ctx->sizeHi += (ctx->sizeLo < 8); - } -} - - -void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]) { - unsigned char pad0x80 = 0x80; - unsigned char pad0x00 = 0x00; - unsigned char padlen[8]; - int i; - - /* Pad with a binary 1 (e.g. 0x80), then zeroes, then length - */ - padlen[0] = (unsigned char)((ctx->sizeHi >> 24) & 255); - padlen[1] = (unsigned char)((ctx->sizeHi >> 16) & 255); - padlen[2] = (unsigned char)((ctx->sizeHi >> 8) & 255); - padlen[3] = (unsigned char)((ctx->sizeHi >> 0) & 255); - padlen[4] = (unsigned char)((ctx->sizeLo >> 24) & 255); - padlen[5] = (unsigned char)((ctx->sizeLo >> 16) & 255); - padlen[6] = (unsigned char)((ctx->sizeLo >> 8) & 255); - padlen[7] = (unsigned char)((ctx->sizeLo >> 0) & 255); - shaUpdate(ctx, &pad0x80, 1); - while (ctx->lenW != 56) - shaUpdate(ctx, &pad0x00, 1); - shaUpdate(ctx, padlen, 8); - - /* Output hash - */ - for (i = 0; i < 20; i++) { - hashout[i] = (unsigned char)(ctx->H[i / 4] >> 24); - ctx->H[i / 4] <<= 8; - } - - /* - * Re-initialize the context (also zeroizes contents) - */ - shaInit(ctx); -} - - -void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]) { - SHA_CTX ctx; - - shaInit(&ctx); - shaUpdate(&ctx, dataIn, len); - shaFinal(&ctx, hashout); -} - - -#define SHA_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xffffffffL) - -static void shaHashBlock(SHA_CTX *ctx) { - int t; - guint32 A,B,C,D,E,TEMP; - - for (t = 16; t <= 79; t++) - ctx->W[t] = - SHA_ROTL(ctx->W[t-3] ^ ctx->W[t-8] ^ ctx->W[t-14] ^ ctx->W[t-16], 1); - - A = ctx->H[0]; - B = ctx->H[1]; - C = ctx->H[2]; - D = ctx->H[3]; - E = ctx->H[4]; - - for (t = 0; t <= 19; t++) { - TEMP = (SHA_ROTL(A,5) + (((C^D)&B)^D) + E + ctx->W[t] + 0x5a827999L) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - for (t = 20; t <= 39; t++) { - TEMP = (SHA_ROTL(A,5) + (B^C^D) + E + ctx->W[t] + 0x6ed9eba1L) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - for (t = 40; t <= 59; t++) { - TEMP = (SHA_ROTL(A,5) + ((B&C)|(D&(B|C))) + E + ctx->W[t] + 0x8f1bbcdcL) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - for (t = 60; t <= 79; t++) { - TEMP = (SHA_ROTL(A,5) + (B^C^D) + E + ctx->W[t] + 0xca62c1d6L) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - - ctx->H[0] += A; - ctx->H[1] += B; - ctx->H[2] += C; - ctx->H[3] += D; - ctx->H[4] += E; -} - -/*---------------------------------------------------------------------------- - * - * This code added by Thomas "temas" Muldowney for Jabber compatability - * - *---------------------------------------------------------------------------*/ -char *shahash(char *str) -{ - static char final[41]; - char *pos; - unsigned char hashval[20]; - int x; - - if(!str || strlen(str) == 0) - return NULL; - - shaBlock((unsigned char *)str, strlen(str), hashval); - - pos = final; - for(x=0;x<20;x++) - { - g_snprintf(pos, 3, "%02x", hashval[x]); - pos += 2; - } - return (char *)final; -} diff --git a/lib/sha.h b/lib/sha.h deleted file mode 100644 index e8152b1b..00000000 --- a/lib/sha.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __SHA_H__ -#define __SHA_H__ - -#include <gmodule.h> - -G_MODULE_EXPORT int strprintsha(char *dest, int *hashval); - -typedef struct { - guint32 H[5]; - guint32 W[80]; - int lenW; - guint32 sizeHi,sizeLo; -} SHA_CTX; - -G_MODULE_EXPORT void shaInit(SHA_CTX *ctx); -G_MODULE_EXPORT void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len); -G_MODULE_EXPORT void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]); -G_MODULE_EXPORT void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]); -G_MODULE_EXPORT char *shahash(char *str); - -#endif diff --git a/lib/sha1.c b/lib/sha1.c new file mode 100644 index 00000000..ee4fcc19 --- /dev/null +++ b/lib/sha1.c @@ -0,0 +1,375 @@ +/* + * SHA1 hashing code copied from Lepton's crack <http://usuarios.lycos.es/reinob/> + * + * Adapted to be API-compatible with the previous (GPL-incompatible) code. + */ + +/* + * sha1.c + * + * Description: + * This file implements the Secure Hashing Algorithm 1 as + * defined in FIPS PUB 180-1 published April 17, 1995. + * + * The SHA-1, produces a 160-bit message digest for a given + * data stream. It should take about 2**n steps to find a + * message with the same digest as a given message and + * 2**(n/2) to find any two messages with the same digest, + * when n is the digest size in bits. Therefore, this + * algorithm can serve as a means of providing a + * "fingerprint" for a message. + * + * Portability Issues: + * SHA-1 is defined in terms of 32-bit "words". This code + * uses <stdint.h> (included via "sha1.h" to define 32 and 8 + * bit unsigned integer types. If your C compiler does not + * support 32 bit unsigned integers, this code is not + * appropriate. + * + * Caveats: + * SHA-1 is designed to work with messages less than 2^64 bits + * long. Although SHA-1 allows a message digest to be generated + * for messages of any number of bits less than 2^64, this + * implementation only works with messages with a length that is + * a multiple of the size of an 8-bit character. + * + */ + +#include "sha1.h" + +/* + * Define the SHA1 circular left shift macro + */ +#define SHA1CircularShift(bits,word) \ + (((word) << (bits)) | ((word) >> (32-(bits)))) + +/* Local Function Prototyptes */ +static void sha1_pad(sha1_state_t *); +static void sha1_process_block(sha1_state_t *); + +/* + * sha1_init + * + * Description: + * This function will initialize the sha1_state_t in preparation + * for computing a new SHA1 message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * + * Returns: + * sha Error Code. + * + */ +int sha1_init(sha1_state_t * context) +{ + context->Length_Low = 0; + context->Length_High = 0; + context->Message_Block_Index = 0; + + context->Intermediate_Hash[0] = 0x67452301; + context->Intermediate_Hash[1] = 0xEFCDAB89; + context->Intermediate_Hash[2] = 0x98BADCFE; + context->Intermediate_Hash[3] = 0x10325476; + context->Intermediate_Hash[4] = 0xC3D2E1F0; + + context->Computed = 0; + context->Corrupted = 0; + + return shaSuccess; +} + +/* + * sha1_finish + * + * Description: + * This function will return the 160-bit message digest into the + * Message_Digest array provided by the caller. + * NOTE: The first octet of hash is stored in the 0th element, + * the last octet of hash in the 19th element. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA-1 hash. + * Message_Digest: [out] + * Where the digest is returned. + * + * Returns: + * sha Error Code. + * + */ +int sha1_finish(sha1_state_t * context, uint8_t Message_Digest[sha1_hash_size]) +{ + int i; + + if (!context || !Message_Digest) { + return shaNull; + } + + if (context->Corrupted) { + return context->Corrupted; + } + + if (!context->Computed) { + sha1_pad(context); + for (i = 0; i < 64; ++i) { + /* message may be sensitive, clear it out */ + context->Message_Block[i] = 0; + } + context->Length_Low = 0; /* and clear length */ + context->Length_High = 0; + context->Computed = 1; + + } + + for (i = 0; i < sha1_hash_size; ++i) { + Message_Digest[i] = context->Intermediate_Hash[i >> 2] + >> 8 * (3 - (i & 0x03)); + } + + return shaSuccess; +} + +/* + * sha1_append + * + * Description: + * This function accepts an array of octets as the next portion + * of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update + * message_array: [in] + * An array of characters representing the next portion of + * the message. + * length: [in] + * The length of the message in message_array + * + * Returns: + * sha Error Code. + * + */ +int +sha1_append(sha1_state_t * context, + const uint8_t * message_array, unsigned length) +{ + if (!length) { + return shaSuccess; + } + + if (!context || !message_array) { + return shaNull; + } + + if (context->Computed) { + context->Corrupted = shaStateError; + + return shaStateError; + } + + if (context->Corrupted) { + return context->Corrupted; + } + while (length-- && !context->Corrupted) { + context->Message_Block[context->Message_Block_Index++] = + (*message_array & 0xFF); + + context->Length_Low += 8; + if (context->Length_Low == 0) { + context->Length_High++; + if (context->Length_High == 0) { + /* Message is too long */ + context->Corrupted = 1; + } + } + + if (context->Message_Block_Index == 64) { + sha1_process_block(context); + } + + message_array++; + } + + return shaSuccess; +} + +/* + * sha1_process_block + * + * Description: + * This function will process the next 512 bits of the message + * stored in the Message_Block array. + * + * Parameters: + * None. + * + * Returns: + * Nothing. + * + * Comments: + * Many of the variable names in this code, especially the + * single character names, were used because those were the + * names used in the publication. + * + * + */ +static void sha1_process_block(sha1_state_t * context) +{ + const uint32_t K[] = { /* Constants defined in SHA-1 */ + 0x5A827999, + 0x6ED9EBA1, + 0x8F1BBCDC, + 0xCA62C1D6 + }; + int t; /* Loop counter */ + uint32_t temp; /* Temporary word value */ + uint32_t W[80]; /* Word sequence */ + uint32_t A, B, C, D, E; /* Word buffers */ + + /* + * Initialize the first 16 words in the array W + */ + for (t = 0; t < 16; t++) { + W[t] = context->Message_Block[t * 4] << 24; + W[t] |= context->Message_Block[t * 4 + 1] << 16; + W[t] |= context->Message_Block[t * 4 + 2] << 8; + W[t] |= context->Message_Block[t * 4 + 3]; + } + + for (t = 16; t < 80; t++) { + W[t] = + SHA1CircularShift(1, + W[t - 3] ^ W[t - 8] ^ W[t - + 14] ^ W[t - + 16]); + } + + A = context->Intermediate_Hash[0]; + B = context->Intermediate_Hash[1]; + C = context->Intermediate_Hash[2]; + D = context->Intermediate_Hash[3]; + E = context->Intermediate_Hash[4]; + + for (t = 0; t < 20; t++) { + temp = SHA1CircularShift(5, A) + + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + E = D; + D = C; + C = SHA1CircularShift(30, B); + + B = A; + A = temp; + } + + for (t = 20; t < 40; t++) { + temp = + SHA1CircularShift(5, + A) + (B ^ C ^ D) + E + W[t] + K[1]; + E = D; + D = C; + C = SHA1CircularShift(30, B); + B = A; + A = temp; + } + + for (t = 40; t < 60; t++) { + temp = SHA1CircularShift(5, A) + + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + E = D; + D = C; + C = SHA1CircularShift(30, B); + B = A; + A = temp; + } + + for (t = 60; t < 80; t++) { + temp = + SHA1CircularShift(5, + A) + (B ^ C ^ D) + E + W[t] + K[3]; + E = D; + D = C; + C = SHA1CircularShift(30, B); + B = A; + A = temp; + } + + context->Intermediate_Hash[0] += A; + context->Intermediate_Hash[1] += B; + context->Intermediate_Hash[2] += C; + context->Intermediate_Hash[3] += D; + context->Intermediate_Hash[4] += E; + + context->Message_Block_Index = 0; +} + +/* + * sha1_pad + * + * Description: + * According to the standard, the message must be padded to an even + * 512 bits. The first padding bit must be a '1'. The last 64 + * bits represent the length of the original message. All bits in + * between should be 0. This function will pad the message + * according to those rules by filling the Message_Block array + * accordingly. It will also call the ProcessMessageBlock function + * provided appropriately. When it returns, it can be assumed that + * the message digest has been computed. + * + * Parameters: + * context: [in/out] + * The context to pad + * ProcessMessageBlock: [in] + * The appropriate SHA*ProcessMessageBlock function + * Returns: + * Nothing. + * + */ + +static void sha1_pad(sha1_state_t * context) +{ + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + if (context->Message_Block_Index > 55) { + context->Message_Block[context->Message_Block_Index++] = + 0x80; + while (context->Message_Block_Index < 64) { + context->Message_Block[context-> + Message_Block_Index++] = 0; + } + + sha1_process_block(context); + + while (context->Message_Block_Index < 56) { + context->Message_Block[context-> + Message_Block_Index++] = 0; + } + } else { + context->Message_Block[context->Message_Block_Index++] = + 0x80; + while (context->Message_Block_Index < 56) { + + context->Message_Block[context-> + Message_Block_Index++] = 0; + } + } + + /* + * Store the message length as the last 8 octets + */ + context->Message_Block[56] = context->Length_High >> 24; + context->Message_Block[57] = context->Length_High >> 16; + context->Message_Block[58] = context->Length_High >> 8; + context->Message_Block[59] = context->Length_High; + context->Message_Block[60] = context->Length_Low >> 24; + context->Message_Block[61] = context->Length_Low >> 16; + context->Message_Block[62] = context->Length_Low >> 8; + context->Message_Block[63] = context->Length_Low; + + sha1_process_block(context); +} diff --git a/lib/sha1.h b/lib/sha1.h new file mode 100644 index 00000000..368c0669 --- /dev/null +++ b/lib/sha1.h @@ -0,0 +1,66 @@ +/* + * SHA1 hashing code copied from Lepton's crack <http://usuarios.lycos.es/reinob/> + * + * Adapted to be API-compatible with the previous (GPL-incompatible) code. + */ + +/* + * sha1.h + * + * Description: + * This is the header file for code which implements the Secure + * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published + * April 17, 1995. + * + * Many of the variable names in this code, especially the + * single character names, were used because those were the names + * used in the publication. + * + * Please read the file sha1.c for more information. + * + */ + +#ifndef _SHA1_H_ +#define _SHA1_H_ + +#include <stdint.h> +#include <gmodule.h> + +#ifndef _SHA_enum_ +#define _SHA_enum_ +enum { + shaSuccess = 0, + shaNull, /* Null pointer parameter */ + shaInputTooLong, /* input data too long */ + shaStateError /* called Input after Result */ +}; +#endif +#define sha1_hash_size 20 + +/* + * This structure will hold context information for the SHA-1 + * hashing operation + */ +typedef struct SHA1Context { + uint32_t Intermediate_Hash[sha1_hash_size/4]; /* Message Digest */ + + uint32_t Length_Low; /* Message length in bits */ + uint32_t Length_High; /* Message length in bits */ + + /* Index into message block array */ + int_least16_t Message_Block_Index; + uint8_t Message_Block[64]; /* 512-bit message blocks */ + + int Computed; /* Is the digest computed? */ + int Corrupted; /* Is the message digest corrupted? */ +} sha1_state_t; + +/* + * Function Prototypes + */ + +G_MODULE_EXPORT int sha1_init(sha1_state_t *); +G_MODULE_EXPORT int sha1_append(sha1_state_t *, const uint8_t *, unsigned int); +G_MODULE_EXPORT int sha1_finish(sha1_state_t *, uint8_t Message_Digest[sha1_hash_size]); + +#endif |