X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Flib%2Fsha1.c;h=9fd9e40e2b150e42f73c2ec04695efacf85f746a;hb=2df589363f0c60f94ca9d5e856dfaf7cc5fcb178;hp=78877489bbd74d3c8fbdc92b31e583faa91f16c5;hpb=0797ebe3b2a38d9cc915247a78e26e9e86a6293a;p=bacula%2Fbacula diff --git a/bacula/src/lib/sha1.c b/bacula/src/lib/sha1.c index 78877489bb..9fd9e40e2b 100644 --- a/bacula/src/lib/sha1.c +++ b/bacula/src/lib/sha1.c @@ -2,30 +2,30 @@ * sha1.c * * Description: - * This file implements the Secure Hashing Algorithm 1 as - * defined in FIPS PUB 180-1 published April 17, 1995. + * 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 + * 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 (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. + * 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. + * 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. * * See sha1.h for copyright */ @@ -36,36 +36,36 @@ * Define the SHA1 circular left shift macro */ #define SHA1CircularShift(bits,word) \ - (((word) << (bits)) | ((word) >> (32-(bits)))) + (((word) << (bits)) | ((word) >> (32-(bits)))) /* Local Function Prototyptes */ -void SHA1PadMessage(SHA1Context *); -void SHA1ProcessMessageBlock(SHA1Context *); +static void SHA1PadMessage(SHA1Context *); +static void SHA1ProcessMessageBlock(SHA1Context *); /* - * SHA1Reset + * SHA1Init * * Description: - * This function will initialize the SHA1Context in preparation - * for computing a new SHA1 message digest. + * This function will initialize the SHA1Context in preparation + * for computing a new SHA1 message digest. * * Parameters: - * context: [in/out] - * The context to reset. + * context: [in/out] + * The context to reset. * * Returns: - * sha Error Code. + * sha Error Code. * */ -int SHA1Reset(SHA1Context *context) +int SHA1Init(SHA1Context *context) { if (!context) { - return shaNull; + return shaNull; } - context->Length_Low = 0; - context->Length_High = 0; + context->Length_Low = 0; + context->Length_High = 0; context->Message_Block_Index = 0; context->Intermediate_Hash[0] = 0x67452301; @@ -74,136 +74,123 @@ int SHA1Reset(SHA1Context *context) context->Intermediate_Hash[3] = 0x10325476; context->Intermediate_Hash[4] = 0xC3D2E1F0; - context->Computed = 0; - context->Corrupted = 0; + context->Computed = 0; + context->Corrupted = 0; return shaSuccess; } /* - * SHA1Result + * SHA1Final * * 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. + * 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. + * 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. + * sha Error Code. * */ -int SHA1Result( SHA1Context *context, - uint8_t Message_Digest[SHA1HashSize]) +int SHA1Final(SHA1Context *context, + uint8_t Message_Digest[SHA1HashSize]) { int i; - if (!context || !Message_Digest) - { - return shaNull; + if (!context || !Message_Digest) { + return shaNull; } - if (context->Corrupted) - { - return context->Corrupted; + if (context->Corrupted) { + return context->Corrupted; } - if (!context->Computed) - { - SHA1PadMessage(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; + if (!context->Computed) { + SHA1PadMessage(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 < SHA1HashSize; ++i) - { - Message_Digest[i] = context->Intermediate_Hash[i>>2] - >> 8 * ( 3 - ( i & 0x03 ) ); + for(i = 0; i < SHA1HashSize; ++i) { + Message_Digest[i] = context->Intermediate_Hash[i>>2] + >> 8 * ( 3 - ( i & 0x03 ) ); } return shaSuccess; } /* - * SHA1Input + * SHA1Update * * Description: - * This function accepts an array of octets as the next portion - * of the message. + * 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 + * 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. + * sha Error Code. * */ -int SHA1Input( SHA1Context *context, - const uint8_t *message_array, - unsigned length) +int SHA1Update(SHA1Context *context, + const uint8_t *message_array, + unsigned length) { - if (!length) - { - return shaSuccess; + if (!length) { + return shaSuccess; } - if (!context || !message_array) - { - return shaNull; - } - - if (context->Computed) - { - context->Corrupted = shaStateError; - - return shaStateError; + if (!context || !message_array) { + return shaNull; } - if (context->Corrupted) - { - return context->Corrupted; - } - while(length-- && !context->Corrupted) - { - context->Message_Block[context->Message_Block_Index++] = - (*message_array & 0xFF); + if (context->Computed) { + context->Corrupted = shaStateError; - context->Length_Low += 8; - if (context->Length_Low == 0) - { - context->Length_High++; - if (context->Length_High == 0) - { - /* Message is too long */ - context->Corrupted = 1; - } + return shaStateError; } - if (context->Message_Block_Index == 64) - { - SHA1ProcessMessageBlock(context); + if (context->Corrupted) { + return context->Corrupted; } - - message_array++; + 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) { + SHA1ProcessMessageBlock(context); + } + + message_array++; } return shaSuccess; @@ -213,49 +200,47 @@ int SHA1Input( SHA1Context *context, * SHA1ProcessMessageBlock * * Description: - * This function will process the next 512 bits of the message - * stored in the Message_Block array. + * This function will process the next 512 bits of the message + * stored in the Message_Block array. * * Parameters: - * None. + * None. * * Returns: - * Nothing. + * 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. + * Many of the variable names in this code, especially the + * single character names, were used because those were the + * names used in the publication. * * */ -void SHA1ProcessMessageBlock(SHA1Context *context) +static void SHA1ProcessMessageBlock(SHA1Context *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 */ + 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 + * 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 = 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++) - { + for(t = 16; t < 80; t++) { W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); } @@ -265,47 +250,43 @@ void SHA1ProcessMessageBlock(SHA1Context *context) 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 = 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 = 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 = 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; + 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; @@ -322,60 +303,54 @@ void SHA1ProcessMessageBlock(SHA1Context *context) * * Description: - * According to the standard, the message must be padded to an even + * 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. + * 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 + * context: [in/out] + * The context to pad + * ProcessMessageBlock: [in] + * The appropriate SHA*ProcessMessageBlock function * Returns: - * Nothing. + * Nothing. * */ -void SHA1PadMessage(SHA1Context *context) +static void SHA1PadMessage(SHA1Context *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. + * 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; - } - - SHA1ProcessMessageBlock(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; - } + 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; + } + + SHA1ProcessMessageBlock(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 + * 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; @@ -395,13 +370,13 @@ void SHA1PadMessage(SHA1Context *context) * sha1test.c * * Description: - * This file will exercise the SHA-1 code performing the three - * tests documented in FIPS PUB 180-1 plus one which calls - * SHA1Input with an exact multiple of 512 bits, plus a few - * error test checks. + * This file will exercise the SHA-1 code performing the three + * tests documented in FIPS PUB 180-1 plus one which calls + * SHA1Input with an exact multiple of 512 bits, plus a few + * error test checks. * * Portability Issues: - * None. + * None. * */ @@ -417,12 +392,12 @@ void SHA1PadMessage(SHA1Context *context) #define TEST2a "abcdbcdecdefdefgefghfghighijhi" #define TEST2b "jkijkljklmklmnlmnomnopnopq" -#define TEST2 TEST2a TEST2b +#define TEST2 TEST2a TEST2b #define TEST3 "a" #define TEST4a "01234567012345670123456701234567" #define TEST4b "01234567012345670123456701234567" /* an exact multiple of 512 bits */ -#define TEST4 TEST4a TEST4b +#define TEST4 TEST4a TEST4b char *testarray[4] = { TEST1, @@ -446,61 +421,89 @@ int main() uint8_t Message_Digest[20]; /* - * Perform SHA-1 tests + * Perform SHA-1 tests */ - for(j = 0; j < 4; ++j) - { + for(j = 0; j < 4; ++j) { printf( "\nTest %d: %d, '%s'\n", - j+1, - repeatcount[j], - testarray[j]); + j+1, + repeatcount[j], + testarray[j]); - err = SHA1Reset(&sha); - if (err) - { + err = SHA1Init(&sha); + if (err) { fprintf(stderr, "SHA1Reset Error %d.\n", err ); - break; /* out of for j loop */ - } + break; /* out of for j loop */ + } - for(i = 0; i < repeatcount[j]; ++i) - { + for(i = 0; i < repeatcount[j]; ++i) { - err = SHA1Input(&sha, - (const unsigned char *) testarray[j], - strlen(testarray[j])); - if (err) - { + err = SHA1Input(&sha, + (const unsigned char *) testarray[j], + strlen(testarray[j])); + if (err) { fprintf(stderr, "SHA1Input Error %d.\n", err ); - break; /* out of for i loop */ - } - } - - err = SHA1Result(&sha, Message_Digest); - if (err) - { - fprintf(stderr, + break; /* out of for i loop */ + } + } + + err = SHA1Final(&sha, Message_Digest); + if (err) { + fprintf(stderr, "SHA1Result Error %d, could not compute message digest.\n", - err ); - } - else - { + err ); + } + else + { printf("\t"); - for(i = 0; i < 20 ; ++i) - { + for(i = 0; i < 20 ; ++i) { printf("%02X ", Message_Digest[i]); - } + } printf("\n"); - } + } printf("Should match:\n"); printf("\t%s\n", resultarray[j]); } /* Test some error returns */ - err = SHA1Input(&sha,(const unsigned char *) testarray[1], 1); + err = SHA1Input(&sha,(const unsigned char *) testarray[1], 1); printf ("\nError %d. Should be %d.\n", err, shaStateError ); - err = SHA1Reset(0); + err = SHA1Init(0); printf ("\nError %d. Should be %d.\n", err, shaNull ); return 0; } #endif /* TEST_DRIVER */ + +#ifdef SHA1_SUM +/* + * Reads a single ASCII file and prints the HEX sha1 sum. + */ +#include +int main(int argc, char *argv[]) +{ + FILE *fd; + SHA1Context ctx; + char buf[5000]; + char signature[25]; + + if (argc < 1) { + printf("Must have filename\n"); + exit(1); + } + fd = fopen(argv[1], "rb"); + if (!fd) { + berrno be; + printf("Could not open %s: ERR=%s\n", argv[1], be.bstrerror(errno)); + exit(1); + } + SHA1Init(&ctx); + while (fgets(buf, sizeof(buf), fd)) { + SHA1Update(&ctx, (unsigned char *)buf, strlen(buf)); + } + SHA1Final(&ctx, (unsigned char *)signature); + for (int i=0; i < 20; i++) { + printf("%02x", signature[i]& 0xFF); + } + printf(" %s\n", argv[1]); +} +#endif