dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** This implementation of SHA1 is adapted from the example implementation dbda8d6ce9 2007-07-21 drh: ** contained in RFC-3174. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #include <stdint.h> 17486c353f 2007-10-23 drh: #include <sys/types.h> dbda8d6ce9 2007-07-21 drh: #include "config.h" dbda8d6ce9 2007-07-21 drh: #include "sha1.h" dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: * If you do not have the ISO standard stdint.h header file, then you dbda8d6ce9 2007-07-21 drh: * must typdef the following: dbda8d6ce9 2007-07-21 drh: * name meaning dbda8d6ce9 2007-07-21 drh: * uint32_t unsigned 32 bit integer dbda8d6ce9 2007-07-21 drh: * uint8_t unsigned 8 bit integer (i.e., unsigned char) dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #define SHA1HashSize 20 dbda8d6ce9 2007-07-21 drh: #define shaSuccess 0 dbda8d6ce9 2007-07-21 drh: #define shaInputTooLong 1 dbda8d6ce9 2007-07-21 drh: #define shaStateError 2 dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: * This structure will hold context information for the SHA-1 dbda8d6ce9 2007-07-21 drh: * hashing operation dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: typedef struct SHA1Context SHA1Context; dbda8d6ce9 2007-07-21 drh: struct SHA1Context { dbda8d6ce9 2007-07-21 drh: uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: uint32_t Length_Low; /* Message length in bits */ dbda8d6ce9 2007-07-21 drh: uint32_t Length_High; /* Message length in bits */ dbda8d6ce9 2007-07-21 drh: 8fb641e071 2007-10-23 drh: int Message_Block_Index; /* Index into message block array */ dbda8d6ce9 2007-07-21 drh: uint8_t Message_Block[64]; /* 512-bit message blocks */ dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: int Computed; /* Is the digest computed? */ dbda8d6ce9 2007-07-21 drh: int Corrupted; /* Is the message digest corrupted? */ dbda8d6ce9 2007-07-21 drh: }; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: * sha1.c dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Description: dbda8d6ce9 2007-07-21 drh: * This file implements the Secure Hashing Algorithm 1 as dbda8d6ce9 2007-07-21 drh: * defined in FIPS PUB 180-1 published April 17, 1995. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * The SHA-1, produces a 160-bit message digest for a given dbda8d6ce9 2007-07-21 drh: * data stream. It should take about 2**n steps to find a dbda8d6ce9 2007-07-21 drh: * message with the same digest as a given message and dbda8d6ce9 2007-07-21 drh: * 2**(n/2) to find any two messages with the same digest, dbda8d6ce9 2007-07-21 drh: * when n is the digest size in bits. Therefore, this dbda8d6ce9 2007-07-21 drh: * algorithm can serve as a means of providing a dbda8d6ce9 2007-07-21 drh: * "fingerprint" for a message. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Portability Issues: dbda8d6ce9 2007-07-21 drh: * SHA-1 is defined in terms of 32-bit "words". This code dbda8d6ce9 2007-07-21 drh: * uses <stdint.h> (included via "sha1.h" to define 32 and 8 dbda8d6ce9 2007-07-21 drh: * bit unsigned integer types. If your C compiler does not dbda8d6ce9 2007-07-21 drh: * support 32 bit unsigned integers, this code is not dbda8d6ce9 2007-07-21 drh: * appropriate. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Caveats: dbda8d6ce9 2007-07-21 drh: * SHA-1 is designed to work with messages less than 2^64 bits dbda8d6ce9 2007-07-21 drh: * long. Although SHA-1 allows a message digest to be generated dbda8d6ce9 2007-07-21 drh: * for messages of any number of bits less than 2^64, this dbda8d6ce9 2007-07-21 drh: * implementation only works with messages with a length that is dbda8d6ce9 2007-07-21 drh: * a multiple of the size of an 8-bit character. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: * Define the SHA1 circular left shift macro dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #define SHA1CircularShift(bits,word) \ dbda8d6ce9 2007-07-21 drh: (((word) << (bits)) | ((word) >> (32-(bits)))) dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* Local Function Prototyptes */ dbda8d6ce9 2007-07-21 drh: static void SHA1PadMessage(SHA1Context *); dbda8d6ce9 2007-07-21 drh: static void SHA1ProcessMessageBlock(SHA1Context *); dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: * SHA1Reset dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Description: dbda8d6ce9 2007-07-21 drh: * This function will initialize the SHA1Context in preparation dbda8d6ce9 2007-07-21 drh: * for computing a new SHA1 message digest. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Parameters: dbda8d6ce9 2007-07-21 drh: * context: [in/out] dbda8d6ce9 2007-07-21 drh: * The context to reset. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Returns: dbda8d6ce9 2007-07-21 drh: * sha Error Code. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: static int SHA1Reset(SHA1Context *context) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: context->Length_Low = 0; dbda8d6ce9 2007-07-21 drh: context->Length_High = 0; dbda8d6ce9 2007-07-21 drh: context->Message_Block_Index = 0; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: context->Intermediate_Hash[0] = 0x67452301; dbda8d6ce9 2007-07-21 drh: context->Intermediate_Hash[1] = 0xEFCDAB89; dbda8d6ce9 2007-07-21 drh: context->Intermediate_Hash[2] = 0x98BADCFE; dbda8d6ce9 2007-07-21 drh: context->Intermediate_Hash[3] = 0x10325476; dbda8d6ce9 2007-07-21 drh: context->Intermediate_Hash[4] = 0xC3D2E1F0; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: context->Computed = 0; dbda8d6ce9 2007-07-21 drh: context->Corrupted = 0; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: return shaSuccess; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: * SHA1Result dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Description: dbda8d6ce9 2007-07-21 drh: * This function will return the 160-bit message digest into the dbda8d6ce9 2007-07-21 drh: * Message_Digest array provided by the caller. dbda8d6ce9 2007-07-21 drh: * NOTE: The first octet of hash is stored in the 0th element, dbda8d6ce9 2007-07-21 drh: * the last octet of hash in the 19th element. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Parameters: dbda8d6ce9 2007-07-21 drh: * context: [in/out] dbda8d6ce9 2007-07-21 drh: * The context to use to calculate the SHA-1 hash. dbda8d6ce9 2007-07-21 drh: * Message_Digest: [out] dbda8d6ce9 2007-07-21 drh: * Where the digest is returned. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Returns: dbda8d6ce9 2007-07-21 drh: * sha Error Code. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: static int SHA1Result( SHA1Context *context, dbda8d6ce9 2007-07-21 drh: uint8_t Message_Digest[SHA1HashSize]) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: int i; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: if (context->Corrupted) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: return context->Corrupted; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: if (!context->Computed) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: SHA1PadMessage(context); dbda8d6ce9 2007-07-21 drh: for(i=0; i<64; ++i) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: /* message may be sensitive, clear it out */ dbda8d6ce9 2007-07-21 drh: context->Message_Block[i] = 0; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: context->Length_Low = 0; /* and clear length */ dbda8d6ce9 2007-07-21 drh: context->Length_High = 0; dbda8d6ce9 2007-07-21 drh: context->Computed = 1; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: for(i = 0; i < SHA1HashSize; ++i) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: Message_Digest[i] = context->Intermediate_Hash[i>>2] dbda8d6ce9 2007-07-21 drh: >> 8 * ( 3 - ( i & 0x03 ) ); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: return shaSuccess; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: * SHA1Input dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Description: dbda8d6ce9 2007-07-21 drh: * This function accepts an array of octets as the next portion dbda8d6ce9 2007-07-21 drh: * of the message. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Parameters: dbda8d6ce9 2007-07-21 drh: * context: [in/out] dbda8d6ce9 2007-07-21 drh: * The SHA context to update dbda8d6ce9 2007-07-21 drh: * message_array: [in] dbda8d6ce9 2007-07-21 drh: * An array of characters representing the next portion of dbda8d6ce9 2007-07-21 drh: * the message. dbda8d6ce9 2007-07-21 drh: * length: [in] dbda8d6ce9 2007-07-21 drh: * The length of the message in message_array dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Returns: dbda8d6ce9 2007-07-21 drh: * sha Error Code. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: static dbda8d6ce9 2007-07-21 drh: int SHA1Input( SHA1Context *context, dbda8d6ce9 2007-07-21 drh: const uint8_t *message_array, dbda8d6ce9 2007-07-21 drh: unsigned length) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: if (!length) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: return shaSuccess; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: if (context->Computed) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: context->Corrupted = shaStateError; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: return shaStateError; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: if (context->Corrupted) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: return context->Corrupted; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: while(length-- && !context->Corrupted) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: context->Message_Block[context->Message_Block_Index++] = dbda8d6ce9 2007-07-21 drh: (*message_array & 0xFF); dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: context->Length_Low += 8; dbda8d6ce9 2007-07-21 drh: if (context->Length_Low == 0) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: context->Length_High++; dbda8d6ce9 2007-07-21 drh: if (context->Length_High == 0) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: /* Message is too long */ dbda8d6ce9 2007-07-21 drh: context->Corrupted = 1; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: if (context->Message_Block_Index == 64) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: SHA1ProcessMessageBlock(context); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: message_array++; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: return shaSuccess; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: * SHA1ProcessMessageBlock dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Description: dbda8d6ce9 2007-07-21 drh: * This function will process the next 512 bits of the message dbda8d6ce9 2007-07-21 drh: * stored in the Message_Block array. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Parameters: dbda8d6ce9 2007-07-21 drh: * None. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Returns: dbda8d6ce9 2007-07-21 drh: * Nothing. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Comments: dbda8d6ce9 2007-07-21 drh: * Many of the variable names in this code, especially the dbda8d6ce9 2007-07-21 drh: * single character names, were used because those were the dbda8d6ce9 2007-07-21 drh: * names used in the publication. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: static void SHA1ProcessMessageBlock(SHA1Context *context) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: const uint32_t K[] = { /* Constants defined in SHA-1 */ dbda8d6ce9 2007-07-21 drh: 0x5A827999, dbda8d6ce9 2007-07-21 drh: 0x6ED9EBA1, dbda8d6ce9 2007-07-21 drh: 0x8F1BBCDC, dbda8d6ce9 2007-07-21 drh: 0xCA62C1D6 dbda8d6ce9 2007-07-21 drh: }; dbda8d6ce9 2007-07-21 drh: int t; /* Loop counter */ dbda8d6ce9 2007-07-21 drh: uint32_t temp; /* Temporary word value */ dbda8d6ce9 2007-07-21 drh: uint32_t W[80]; /* Word sequence */ dbda8d6ce9 2007-07-21 drh: uint32_t A, B, C, D, E; /* Word buffers */ dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: * Initialize the first 16 words in the array W dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: for(t = 0; t < 16; t++) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: W[t] = context->Message_Block[t * 4] << 24; dbda8d6ce9 2007-07-21 drh: W[t] |= context->Message_Block[t * 4 + 1] << 16; dbda8d6ce9 2007-07-21 drh: W[t] |= context->Message_Block[t * 4 + 2] << 8; dbda8d6ce9 2007-07-21 drh: W[t] |= context->Message_Block[t * 4 + 3]; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: for(t = 16; t < 80; t++) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: A = context->Intermediate_Hash[0]; dbda8d6ce9 2007-07-21 drh: B = context->Intermediate_Hash[1]; dbda8d6ce9 2007-07-21 drh: C = context->Intermediate_Hash[2]; dbda8d6ce9 2007-07-21 drh: D = context->Intermediate_Hash[3]; dbda8d6ce9 2007-07-21 drh: E = context->Intermediate_Hash[4]; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: for(t = 0; t < 20; t++) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: temp = SHA1CircularShift(5,A) + dbda8d6ce9 2007-07-21 drh: ((B & C) | ((~B) & D)) + E + W[t] + K[0]; dbda8d6ce9 2007-07-21 drh: E = D; dbda8d6ce9 2007-07-21 drh: D = C; dbda8d6ce9 2007-07-21 drh: C = SHA1CircularShift(30,B); dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: B = A; dbda8d6ce9 2007-07-21 drh: A = temp; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: for(t = 20; t < 40; t++) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; dbda8d6ce9 2007-07-21 drh: E = D; dbda8d6ce9 2007-07-21 drh: D = C; dbda8d6ce9 2007-07-21 drh: C = SHA1CircularShift(30,B); dbda8d6ce9 2007-07-21 drh: B = A; dbda8d6ce9 2007-07-21 drh: A = temp; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: for(t = 40; t < 60; t++) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: temp = SHA1CircularShift(5,A) + dbda8d6ce9 2007-07-21 drh: ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; dbda8d6ce9 2007-07-21 drh: E = D; dbda8d6ce9 2007-07-21 drh: D = C; dbda8d6ce9 2007-07-21 drh: C = SHA1CircularShift(30,B); dbda8d6ce9 2007-07-21 drh: B = A; dbda8d6ce9 2007-07-21 drh: A = temp; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: for(t = 60; t < 80; t++) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; dbda8d6ce9 2007-07-21 drh: E = D; dbda8d6ce9 2007-07-21 drh: D = C; dbda8d6ce9 2007-07-21 drh: C = SHA1CircularShift(30,B); dbda8d6ce9 2007-07-21 drh: B = A; dbda8d6ce9 2007-07-21 drh: A = temp; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: context->Intermediate_Hash[0] += A; dbda8d6ce9 2007-07-21 drh: context->Intermediate_Hash[1] += B; dbda8d6ce9 2007-07-21 drh: context->Intermediate_Hash[2] += C; dbda8d6ce9 2007-07-21 drh: context->Intermediate_Hash[3] += D; dbda8d6ce9 2007-07-21 drh: context->Intermediate_Hash[4] += E; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: context->Message_Block_Index = 0; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: * SHA1PadMessage dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: * Description: dbda8d6ce9 2007-07-21 drh: * According to the standard, the message must be padded to an even dbda8d6ce9 2007-07-21 drh: * 512 bits. The first padding bit must be a '1'. The last 64 dbda8d6ce9 2007-07-21 drh: * bits represent the length of the original message. All bits in dbda8d6ce9 2007-07-21 drh: * between should be 0. This function will pad the message dbda8d6ce9 2007-07-21 drh: * according to those rules by filling the Message_Block array dbda8d6ce9 2007-07-21 drh: * accordingly. It will also call the ProcessMessageBlock function dbda8d6ce9 2007-07-21 drh: * provided appropriately. When it returns, it can be assumed that dbda8d6ce9 2007-07-21 drh: * the message digest has been computed. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: * Parameters: dbda8d6ce9 2007-07-21 drh: * context: [in/out] dbda8d6ce9 2007-07-21 drh: * The context to pad dbda8d6ce9 2007-07-21 drh: * ProcessMessageBlock: [in] dbda8d6ce9 2007-07-21 drh: * The appropriate SHA*ProcessMessageBlock function dbda8d6ce9 2007-07-21 drh: * Returns: dbda8d6ce9 2007-07-21 drh: * Nothing. dbda8d6ce9 2007-07-21 drh: * dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: static void SHA1PadMessage(SHA1Context *context) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: * Check to see if the current message block is too small to hold dbda8d6ce9 2007-07-21 drh: * the initial padding bits and length. If so, we will pad the dbda8d6ce9 2007-07-21 drh: * block, process it, and then continue padding into a second dbda8d6ce9 2007-07-21 drh: * block. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: if (context->Message_Block_Index > 55) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: context->Message_Block[context->Message_Block_Index++] = 0x80; dbda8d6ce9 2007-07-21 drh: while(context->Message_Block_Index < 64) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: context->Message_Block[context->Message_Block_Index++] = 0; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: SHA1ProcessMessageBlock(context); dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: while(context->Message_Block_Index < 56) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: context->Message_Block[context->Message_Block_Index++] = 0; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: else dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: context->Message_Block[context->Message_Block_Index++] = 0x80; dbda8d6ce9 2007-07-21 drh: while(context->Message_Block_Index < 56) dbda8d6ce9 2007-07-21 drh: { dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: context->Message_Block[context->Message_Block_Index++] = 0; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: * Store the message length as the last 8 octets dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: context->Message_Block[56] = context->Length_High >> 24; dbda8d6ce9 2007-07-21 drh: context->Message_Block[57] = context->Length_High >> 16; dbda8d6ce9 2007-07-21 drh: context->Message_Block[58] = context->Length_High >> 8; dbda8d6ce9 2007-07-21 drh: context->Message_Block[59] = context->Length_High; dbda8d6ce9 2007-07-21 drh: context->Message_Block[60] = context->Length_Low >> 24; dbda8d6ce9 2007-07-21 drh: context->Message_Block[61] = context->Length_Low >> 16; dbda8d6ce9 2007-07-21 drh: context->Message_Block[62] = context->Length_Low >> 8; dbda8d6ce9 2007-07-21 drh: context->Message_Block[63] = context->Length_Low; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: SHA1ProcessMessageBlock(context); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Convert a digest into base-16. digest should be declared as dbda8d6ce9 2007-07-21 drh: ** "unsigned char digest[20]" in the calling function. The SHA1 dbda8d6ce9 2007-07-21 drh: ** digest is stored in the first 20 bytes. zBuf should dbda8d6ce9 2007-07-21 drh: ** be "char zBuf[41]". dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: static void DigestToBase16(unsigned char *digest, char *zBuf){ dbda8d6ce9 2007-07-21 drh: static char const zEncode[] = "0123456789abcdef"; dbda8d6ce9 2007-07-21 drh: int i, j; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: for(j=i=0; i<20; i++){ dbda8d6ce9 2007-07-21 drh: int a = digest[i]; dbda8d6ce9 2007-07-21 drh: zBuf[j++] = zEncode[(a>>4)&0xf]; dbda8d6ce9 2007-07-21 drh: zBuf[j++] = zEncode[a & 0xf]; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: zBuf[j] = 0; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** The state of a incremental SHA1 checksum computation. Only one dbda8d6ce9 2007-07-21 drh: ** such computation can be underway at a time, of course. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: static SHA1Context incrCtx; dbda8d6ce9 2007-07-21 drh: static int incrInit = 0; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Add more text to the incremental SHA1 checksum. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void sha1sum_step_text(const char *zText, int nBytes){ dbda8d6ce9 2007-07-21 drh: if( !incrInit ){ dbda8d6ce9 2007-07-21 drh: SHA1Reset(&incrCtx); dbda8d6ce9 2007-07-21 drh: incrInit = 1; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: if( nBytes<=0 ){ dbda8d6ce9 2007-07-21 drh: if( nBytes==0 ) return; dbda8d6ce9 2007-07-21 drh: nBytes = strlen(zText); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: SHA1Input(&incrCtx, (unsigned char*)zText, nBytes); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Add the content of a blob to the incremental SHA1 checksum. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void sha1sum_step_blob(Blob *p){ dbda8d6ce9 2007-07-21 drh: sha1sum_step_text(blob_buffer(p), blob_size(p)); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Finish the incremental SHA1 checksum. Store the result in blob pOut dbda8d6ce9 2007-07-21 drh: ** if pOut!=0. Also return a pointer to the result. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This resets the incremental checksum preparing for the next round dbda8d6ce9 2007-07-21 drh: ** of computation. The return pointer points to a static buffer that dbda8d6ce9 2007-07-21 drh: ** is overwritten by subsequent calls to this function. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: char *sha1sum_finish(Blob *pOut){ dbda8d6ce9 2007-07-21 drh: unsigned char zResult[20]; dbda8d6ce9 2007-07-21 drh: static char zOut[41]; dbda8d6ce9 2007-07-21 drh: sha1sum_step_text(0,0); dbda8d6ce9 2007-07-21 drh: SHA1Result(&incrCtx, zResult); dbda8d6ce9 2007-07-21 drh: incrInit = 0; dbda8d6ce9 2007-07-21 drh: DigestToBase16(zResult, zOut); dbda8d6ce9 2007-07-21 drh: if( pOut ){ dbda8d6ce9 2007-07-21 drh: blob_zero(pOut); dbda8d6ce9 2007-07-21 drh: blob_append(pOut, zOut, 40); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: return zOut; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Compute the SHA1 checksum of a file on disk. Store the resulting dbda8d6ce9 2007-07-21 drh: ** checksum in the blob pCksum. pCksum is assumed to be ininitialized. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Return the number of errors. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: int sha1sum_file(const char *zFilename, Blob *pCksum){ dbda8d6ce9 2007-07-21 drh: FILE *in; dbda8d6ce9 2007-07-21 drh: SHA1Context ctx; dbda8d6ce9 2007-07-21 drh: unsigned char zResult[20]; dbda8d6ce9 2007-07-21 drh: char zBuf[10240]; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: in = fopen(zFilename,"rb"); dbda8d6ce9 2007-07-21 drh: if( in==0 ){ dbda8d6ce9 2007-07-21 drh: return 1; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: SHA1Reset(&ctx); dbda8d6ce9 2007-07-21 drh: for(;;){ dbda8d6ce9 2007-07-21 drh: int n; dbda8d6ce9 2007-07-21 drh: n = fread(zBuf, 1, sizeof(zBuf), in); dbda8d6ce9 2007-07-21 drh: if( n<=0 ) break; dbda8d6ce9 2007-07-21 drh: SHA1Input(&ctx, (unsigned char*)zBuf, (unsigned)n); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: fclose(in); dbda8d6ce9 2007-07-21 drh: blob_zero(pCksum); dbda8d6ce9 2007-07-21 drh: blob_resize(pCksum, 40); dbda8d6ce9 2007-07-21 drh: SHA1Result(&ctx, zResult); dbda8d6ce9 2007-07-21 drh: DigestToBase16(zResult, blob_buffer(pCksum)); dbda8d6ce9 2007-07-21 drh: return 0; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Compute the SHA1 checksum of a blob in memory. Store the resulting dbda8d6ce9 2007-07-21 drh: ** checksum in the blob pCksum. pCksum is assumed to be either dbda8d6ce9 2007-07-21 drh: ** uninitialized or the same blob as pIn. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Return the number of errors. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: int sha1sum_blob(const Blob *pIn, Blob *pCksum){ dbda8d6ce9 2007-07-21 drh: SHA1Context ctx; dbda8d6ce9 2007-07-21 drh: unsigned char zResult[20]; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: SHA1Reset(&ctx); dbda8d6ce9 2007-07-21 drh: SHA1Input(&ctx, (unsigned char*)blob_buffer(pIn), blob_size(pIn)); dbda8d6ce9 2007-07-21 drh: if( pIn==pCksum ){ dbda8d6ce9 2007-07-21 drh: blob_reset(pCksum); dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: blob_zero(pCksum); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: blob_resize(pCksum, 40); dbda8d6ce9 2007-07-21 drh: SHA1Result(&ctx, zResult); dbda8d6ce9 2007-07-21 drh: DigestToBase16(zResult, blob_buffer(pCksum)); dbda8d6ce9 2007-07-21 drh: return 0; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* c83c1110f6 2009-09-30 drh: ** COMMAND: sha1sum c83c1110f6 2009-09-30 drh: ** %fossil sha1sum FILE... dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Compute an SHA1 checksum of all files named on the command-line. dbda8d6ce9 2007-07-21 drh: ** If an file is named "-" then take its content from standard input. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void sha1sum_test(void){ dbda8d6ce9 2007-07-21 drh: int i; dbda8d6ce9 2007-07-21 drh: Blob in; dbda8d6ce9 2007-07-21 drh: Blob cksum; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: for(i=2; i<g.argc; i++){ dbda8d6ce9 2007-07-21 drh: if( g.argv[i][0]=='-' && g.argv[i][1]==0 ){ dbda8d6ce9 2007-07-21 drh: blob_read_from_channel(&in, stdin, -1); dbda8d6ce9 2007-07-21 drh: sha1sum_blob(&in, &cksum); dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: sha1sum_file(g.argv[i], &cksum); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: printf("%s %s\n", blob_str(&cksum), g.argv[i]); dbda8d6ce9 2007-07-21 drh: blob_reset(&cksum); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: }