123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- /*++
- Copyright (c) 2015 Minoca Corp.
- This file is licensed under the terms of the GNU General Public License
- version 3. Alternative licensing terms are available. Contact
- info@minocacorp.com for details. See the LICENSE file at the root of this
- project for complete licensing information.
- Module Name:
- sha1.c
- Abstract:
- This module implements the SHA-1 hash function.
- Author:
- Evan Green 13-Jan-2015
- Environment:
- Any
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include "cryptop.h"
- //
- // --------------------------------------------------------------------- Macros
- //
- //
- // This macro rotates a 32-bit value left by the given number of bits.
- //
- #define SHA1_ROTATE32(_Value, _ShiftCount) \
- (((_Value) << (_ShiftCount)) | ((_Value) >> (32 - (_ShiftCount))))
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- VOID
- CypSha1ProcessMessage (
- PSHA1_CONTEXT Context
- );
- VOID
- CypSha1PadMessage (
- PSHA1_CONTEXT Context
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- const ULONG CySha1KConstants[4] = {
- 0x5A827999UL,
- 0x6ED9EBA1UL,
- 0x8F1BBCDCUL,
- 0xCA62C1D6UL
- };
- //
- // ------------------------------------------------------------------ Functions
- //
- CRYPTO_API
- VOID
- CySha1Initialize (
- PSHA1_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine initializes a SHA-1 context structure, preparing it to accept
- and hash data.
- Arguments:
- Context - Supplies a pointer to the context to initialize.
- Return Value:
- None.
- --*/
- {
- Context->Length = 0;
- Context->BlockIndex = 0;
- Context->IntermediateHash[0] = 0x67452301UL;
- Context->IntermediateHash[1] = 0xEFCDAB89UL;
- Context->IntermediateHash[2] = 0x98BADCFEUL;
- Context->IntermediateHash[3] = 0x10325476UL;
- Context->IntermediateHash[4] = 0xC3D2E1F0UL;
- return;
- }
- CRYPTO_API
- VOID
- CySha1AddContent (
- PSHA1_CONTEXT Context,
- PUCHAR Message,
- UINTN Length
- )
- /*++
- Routine Description:
- This routine adds data to a SHA-1 digest.
- Arguments:
- Context - Supplies a pointer to the initialized SHA-1 context.
- Message - Supplies a pointer to the buffer containing the bytes.
- Length - Supplies the length of the message buffer, in bytes.
- Return Value:
- None.
- --*/
- {
- while (Length != 0) {
- Context->MessageBlock[Context->BlockIndex] = *Message;
- Context->BlockIndex += 1;
- Context->Length += BITS_PER_BYTE;
- if (Context->BlockIndex == sizeof(Context->MessageBlock)) {
- CypSha1ProcessMessage(Context);
- }
- Message += 1;
- Length -= 1;
- }
- return;
- }
- CRYPTO_API
- VOID
- CySha1GetHash (
- PSHA1_CONTEXT Context,
- UCHAR Hash[SHA1_HASH_SIZE]
- )
- /*++
- Routine Description:
- This routine computes and returns the final SHA-1 hash value for the
- messages that have been previously entered.
- Arguments:
- Context - Supplies a pointer to the initialized SHA-1 context.
- Hash - Supplies a pointer where the final hash value will be returned. This
- buffer must be SHA1_HASH_SIZE length in bytes.
- Return Value:
- None.
- --*/
- {
- INT DigestIndex;
- INT ShiftAmount;
- CypSha1PadMessage(Context);
- Context->Length = 0;
- for (DigestIndex = 0; DigestIndex < SHA1_HASH_SIZE; DigestIndex += 1) {
- ShiftAmount = (sizeof(ULONG) - 1 - (DigestIndex % sizeof(ULONG))) *
- BITS_PER_BYTE;
- Hash[DigestIndex] =
- Context->IntermediateHash[DigestIndex / sizeof(ULONG)] >>
- ShiftAmount;
- }
- return;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- VOID
- CypSha1ProcessMessage (
- PSHA1_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine processes the 512 bits in the current message block and adds
- them to the digest.
- Arguments:
- Context - Supplies a pointer to the initialized SHA-1 context with a full
- message block.
- Return Value:
- None.
- --*/
- {
- ULONG Block[80];
- ULONG BlockA;
- ULONG BlockB;
- ULONG BlockC;
- ULONG BlockD;
- ULONG BlockE;
- INT Index;
- ULONG Value;
- //
- // Initialize the first 16 words in the block array.
- //
- for (Index = 0; Index < 16; Index += 1) {
- Block[Index] = ((ULONG)Context->MessageBlock[Index * 4] << 24) |
- ((ULONG)Context->MessageBlock[(Index * 4) + 1] << 16) |
- ((ULONG)Context->MessageBlock[(Index * 4) + 2] << 8) |
- (Context->MessageBlock[(Index * 4) + 3]);
- }
- for (Index = 16; Index < 80; Index += 1) {
- Value = Block[Index - 3] ^ Block[Index - 8] ^ Block[Index - 14] ^
- Block[Index - 16];
- Block[Index] = SHA1_ROTATE32(Value, 1);
- }
- BlockA = Context->IntermediateHash[0];
- BlockB = Context->IntermediateHash[1];
- BlockC = Context->IntermediateHash[2];
- BlockD = Context->IntermediateHash[3];
- BlockE = Context->IntermediateHash[4];
- for (Index = 0; Index < 20; Index += 1) {
- Value = SHA1_ROTATE32(BlockA, 5) +
- ((BlockB & BlockC) | ((~BlockB) & BlockD)) +
- BlockE + Block[Index] + CySha1KConstants[0];
- BlockE = BlockD;
- BlockD = BlockC;
- BlockC = SHA1_ROTATE32(BlockB, 30);
- BlockB = BlockA;
- BlockA = Value;
- }
- for (Index = 20; Index < 40; Index += 1) {
- Value = SHA1_ROTATE32(BlockA, 5) + (BlockB ^ BlockC ^ BlockD) +
- BlockE + Block[Index] + CySha1KConstants[1];
- BlockE = BlockD;
- BlockD = BlockC;
- BlockC = SHA1_ROTATE32(BlockB, 30);
- BlockB = BlockA;
- BlockA = Value;
- }
- for (Index = 40; Index < 60; Index += 1) {
- Value = SHA1_ROTATE32(BlockA, 5) +
- ((BlockB & BlockC) | (BlockB & BlockD) | (BlockC & BlockD)) +
- BlockE + Block[Index] + CySha1KConstants[2];
- BlockE = BlockD;
- BlockD = BlockC;
- BlockC = SHA1_ROTATE32(BlockB, 30);
- BlockB = BlockA;
- BlockA = Value;
- }
- for (Index = 60; Index < 80; Index += 1) {
- Value = SHA1_ROTATE32(BlockA, 5) + (BlockB ^ BlockC ^ BlockD) +
- BlockE + Block[Index] + CySha1KConstants[3];
- BlockE = BlockD;
- BlockD = BlockC;
- BlockC = SHA1_ROTATE32(BlockB, 30);
- BlockB = BlockA;
- BlockA = Value;
- }
- Context->IntermediateHash[0] += BlockA;
- Context->IntermediateHash[1] += BlockB;
- Context->IntermediateHash[2] += BlockC;
- Context->IntermediateHash[3] += BlockD;
- Context->IntermediateHash[4] += BlockE;
- Context->BlockIndex = 0;
- return;
- }
- VOID
- CypSha1PadMessage (
- PSHA1_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine pads the message out to an even multiple of 512 bits.
- The standard specifies that the first padding bit must be a 1, and then the
- last 64 bits represent the length of the original message.
- Arguments:
- Context - Supplies a pointer to the initialized SHA-1 context with a full
- message block.
- Return Value:
- None.
- --*/
- {
- //
- // Check to see if the current message block is too small to hold the
- // initial padding bits and length. If so, process the block, then continue
- // padding onto a second block.
- //
- if (Context->BlockIndex > 55) {
- Context->MessageBlock[Context->BlockIndex] = 0x80;
- Context->BlockIndex += 1;
- while (Context->BlockIndex < sizeof(Context->MessageBlock)) {
- Context->MessageBlock[Context->BlockIndex] = 0;
- Context->BlockIndex += 1;
- }
- CypSha1ProcessMessage(Context);
- while (Context->BlockIndex < 56) {
- Context->MessageBlock[Context->BlockIndex] = 0;
- Context->BlockIndex += 1;
- }
- } else {
- Context->MessageBlock[Context->BlockIndex] = 0x80;
- Context->BlockIndex += 1;
- while (Context->BlockIndex < 56) {
- Context->MessageBlock[Context->BlockIndex] = 0;
- Context->BlockIndex += 1;
- }
- }
- //
- // Store the message length in the last 8 octets.
- //
- Context->MessageBlock[56] = (UCHAR)(Context->Length >> (32 + 24));
- Context->MessageBlock[57] = (UCHAR)(Context->Length >> (32 + 16));
- Context->MessageBlock[58] = (UCHAR)(Context->Length >> (32 + 8));
- Context->MessageBlock[59] = (UCHAR)(Context->Length >> 32);
- Context->MessageBlock[60] = (UCHAR)(Context->Length >> 24);
- Context->MessageBlock[61] = (UCHAR)(Context->Length >> 16);
- Context->MessageBlock[62] = (UCHAR)(Context->Length >> 8);
- Context->MessageBlock[63] = (UCHAR)(Context->Length);
- CypSha1ProcessMessage(Context);
- return;
- }
|