?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{FILE START}

library

?curdirlinks? - Rev 32

?prevdifflink? - Blame - ?getfile?

/*********************************************************************
 *
 *      Hash Function Library
 *  Library for Microchip TCP/IP Stack
 *       -Calculates MD5 and SHA-1 Hashes
 *       -Reference: RFC 1321 (MD5), RFC 3174 and FIPS 180-1 (SHA-1)
 *
 *********************************************************************
 * FileName:        Hashes.c
 * Dependencies:    None
 * Processor:       PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
 * Processor:       PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
 * Compiler:        Microchip C32 v1.05 or higher
 *                                      Microchip C30 v3.12 or higher
 *                                      Microchip C18 v3.30 or higher
 *                                      HI-TECH PICC-18 PRO 9.63PL2 or higher
 * Company:         Microchip Technology, Inc.
 *
 * Software License Agreement
 *
 * Copyright (C) 2002-2009 Microchip Technology Inc.  All rights
 * reserved.
 *
 * Microchip licenses to you the right to use, modify, copy, and
 * distribute:
 * (i)  the Software when embedded on a Microchip microcontroller or
 *      digital signal controller product ("Device") which is
 *      integrated into Licensee's product; or
 * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
 *              ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
 *              used in conjunction with a Microchip ethernet controller for
 *              the sole purpose of interfacing with the ethernet controller.
 *
 * You should refer to the license agreement accompanying this
 * Software for additional information regarding your rights and
 * obligations.
 *
 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
 *
 * IMPORTANT:  The implementation and use of third party algorithms, 
 * specifications and/or other technology may require a license from 
 * various third parties.  It is your responsibility to obtain 
 * information regarding any applicable licensing obligations.
 *
 *
 * Author               Date            Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Elliott Wood         5/01/07         Original
 * Elliott Wood                 11/21/07        Greatly increased HashBlock speed
 ********************************************************************/
#define __HASHES_C

/*****************************************************************************
  Internal:
        Performance Statistics are as follows:
        (Given in instructions per block = 512 bits = 64 bytes)
        
                                        MD5                                     SHA1
                C18                     23k instr/block         50k instr/block
                Hi-Tech C       19k instr/block         50k instr/block
                C30                     21k instr/block         17k instr/block
                
  ***************************************************************************/

#include "TCPIP Stack/TCPIP.h"

/****************************************************************************
  Section:
        Functions and variables required for both hash types
  ***************************************************************************/

#if defined(STACK_USE_MD5) || defined(STACK_USE_SHA1)

// Stores a copy of the last block with the required padding
BYTE lastBlock[64];

/*****************************************************************************
  Function:
        void HashAddData(HASH_SUM* theSum, BYTE* data, WORD len)

  Description:
        Adds data to the hash sum.

  Precondition:
        The hash sum has already been initialized

  Parameters:
        theSum - hash context state
        data - the data to be added to the hash sum
        len - length of data

  Returns:
        None
        
  Remarks:
        This function calls the appropriate hashing function based on the 
        hash typed defined in theSum.
  ***************************************************************************/
void HashAddData(HASH_SUM* theSum, BYTE* data, WORD len)
{
        #if defined(STACK_USE_MD5)
        if(theSum->hashType == HASH_MD5)
                MD5AddData(theSum, data, len);
        #endif
        #if defined(STACK_USE_SHA1)
        if(theSum->hashType == HASH_SHA1)
                SHA1AddData(theSum, data, len);
        #endif
}

/*****************************************************************************
  Function:
        void HashAddROMData(HASH_SUM* theSum, ROM BYTE* data, WORD len)

  Description:
        Adds data to the hash sum.

  Precondition:
        The hash sum has already been initialized

  Parameters:
        theSum - hash context state
        data - the data to be added to the hash sum
        len - length of data

  Returns:
        None
        
  Remarks:
        This function calls the appropriate hashing function based on the 
        hash typed defined in theSum.
        
        This function is aliased to HashAddData on non-PIC18 platforms.
  ***************************************************************************/
#if defined(__18CXX)
void HashAddROMData(HASH_SUM* theSum, ROM BYTE* data, WORD len)
{
        #if defined(STACK_USE_MD5)
        if(theSum->hashType == HASH_MD5)
                MD5AddROMData(theSum, data, len);
        #endif
        #if defined(STACK_USE_SHA1)
        if(theSum->hashType == HASH_SHA1)
                SHA1AddROMData(theSum, data, len);
        #endif
}
#endif

#endif


/****************************************************************************
  Section:
        Functions and variables required for MD5
  ***************************************************************************/

#if defined(STACK_USE_MD5)

// Array of pre-defined R vales for MD5
static ROM BYTE _MD5_r[64] = {7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,
                                  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,
                                  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,
                                  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21};

// Array of pre-defined K values for MD5
static ROM DWORD _MD5_k[64] = { 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501, 
                                                        0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821, 
                                                        0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8, 
                                                        0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A, 
                                                        0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70, 
                                                        0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665, 
                                                        0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1, 
                                                        0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391 };

static void MD5HashBlock(BYTE* data, DWORD* h0, DWORD* h1, DWORD* h2, DWORD* h3);

/*****************************************************************************
  Function:
        void MD5Initialize(HASH_SUM* theSum)

  Description:
        Initializes a new MD5 hash.

  Precondition:
        None

  Parameters:
        theSum - pointer to the allocated HASH_SUM object to initialize as MD5

  Returns:
        None
  ***************************************************************************/
void MD5Initialize(HASH_SUM* theSum)
{
        theSum->h0 = 0x67452301;
        theSum->h1 = 0xefcdab89;
        theSum->h2 = 0x98badcfe;
        theSum->h3 = 0x10325476;
        theSum->bytesSoFar = 0;
        theSum->hashType = HASH_MD5;
}

/*****************************************************************************
  Function:
        void MD5AddData(HASH_SUM* theSum, BYTE* data, WORD len)

  Description:
        Adds data to an MD5 hash calculation.

  Precondition:
        The hash context has already been initialized.

  Parameters:
        theSum - a pointer to the hash context structure
        data - the data to add to the hash
        len - the length of the data to add

  Returns:
        None
  ***************************************************************************/
void MD5AddData(HASH_SUM* theSum, BYTE* data, WORD len)
{
        BYTE *blockPtr;

        // Seek to the first free byte
        blockPtr = theSum->partialBlock + ( theSum->bytesSoFar & 0x3f );

        // Update the total number of bytes
        theSum->bytesSoFar += len;

        // Copy data into the partial block
        while(len != 0u)
        {
                *blockPtr++ = *data++;

                // If the partial block is full, hash the data and start over
                if(blockPtr == theSum->partialBlock + 64)
                {
                        MD5HashBlock(theSum->partialBlock, &theSum->h0, &theSum->h1, &theSum->h2, &theSum->h3);
                        blockPtr = theSum->partialBlock;
                }
                
                len--;
        }
        
}

/*****************************************************************************
  Function:
        void MD5AddROMData(HASH_SUM* theSum, ROM BYTE* data, WORD len)

  Description:
        Adds data to an MD5 hash calculation.

  Precondition:
        The hash context has already been initialized.

  Parameters:
        theSum - a pointer to the hash context structure
        data - the data to add to the hash
        len - the length of the data to add

  Returns:
        None
        
  Remarks:
        This function is aliased to MD5AddData on non-PIC18 platforms.
  ***************************************************************************/
#if defined(__18CXX)
void MD5AddROMData(HASH_SUM* theSum, ROM BYTE* data, WORD len)
{
        BYTE *blockPtr;

        // Seek to the first free byte
        blockPtr = theSum->partialBlock + ( theSum->bytesSoFar & 0x3f );

        // Update the total number of bytes
        theSum->bytesSoFar += len;

        // Copy data into the partial block
        while(len != 0u)
        {
                *blockPtr++ = *data++;

                // If the partial block is full, hash the data and start over
                if(blockPtr == theSum->partialBlock + 64)
                {
                        MD5HashBlock(theSum->partialBlock, &theSum->h0, &theSum->h1, &theSum->h2, &theSum->h3);
                        blockPtr = theSum->partialBlock;
                }
                
                len--;
        }
        
}
#endif

/*****************************************************************************
  Function:
        static void MD5HashBlock(BYTE* data, DWORD* h0, DWORD* h1, 
                                                                DWORD* h2, DWORD* h3)

  Summary:
        Calculates the MD5 hash sum of a block.

  Description:
        This function calculates the MD5 hash sum over a block and updates
        the values of h0-h3 with the next context.

  Precondition:
        The data pointer must be WORD aligned on 16-bit parts and DWORD
        aligned on 32-bit PICs.  If alignment is not correct, a memory alignment
        exception will occur.

  Parameters:
        data - The block of 64 bytes to hash
        h0 - the current hash context h0 value
        h1 - the current hash context h1 value
        h2 - the current hash context h2 value
        h3 - the current hash context h3 value

  Returns:
        None
  
  Internal:
        TODO convert data to a DWORD* or read from the pointer using byte
        accesses only to avoid any accidental alignment errors
  ***************************************************************************/
static void MD5HashBlock(BYTE* data, DWORD* h0, DWORD* h1, DWORD* h2, DWORD* h3)
{
        DWORD a, b, c, d, f, temp;
        BYTE i, j;

        // Set up a, b, c, d
        a = *h0;
        b = *h1;
        c = *h2;
        d = *h3;

        // Main mixer loop for 64 operations
        for(i = 0; i < 64u; i++)
        {
                if(i <= 15u)
                {
                        f = (b & c) | ((~b) & d);
                        j = i;
                }
                else if(i > 15u && i <= 31u)
                {
                        f = (d & b) | ((~d) & c);
                        j = (5 * i + 1) & 0x0f;
                }
                else if(i > 31u && i <= 47u)
                {
                        f = (b ^ c ^ d);
                        j = (3 * i + 5) & 0x0f;
                }
                else
                {
                        f = c ^ (b | (~d));
                        j = (7 * i) & 0x0f;
                }
                
                // Calculate the new mixer values
                temp = d;
                d = c;
                c = b;
                j *= 4;
                b = leftRotateDWORD(a+f+_MD5_k[i]+(*(DWORD*)&data[j]),_MD5_r[i]) + b;
                a = temp;
        }

        // Add the new hash to the sum
        *h0 += a;
        *h1 += b;
        *h2 += c;
        *h3 += d;

}

/*****************************************************************************
  Function:
        void MD5Calculate(HASH_SUM* theSum, BYTE* result)

  Summary:
        Calculates an MD5 hash

  Description:
        This function calculates the hash sum of all input data so far.  It is
        non-destructive to the hash context, so more data may be added after
        this function is called.

  Precondition:
        The hash context has been properly initialized.

  Parameters:
        theSum - the current hash context
        result - 16 byte array in which to store the resulting hash

  Returns:
        None
  ***************************************************************************/
void MD5Calculate(HASH_SUM* theSum, BYTE* result)
{
        DWORD h0, h1, h2, h3;
        BYTE i, *partPtr, *endPtr;

        // Initialize the hash variables
        h0 = theSum->h0;
        h1 = theSum->h1;
        h2 = theSum->h2;
        h3 = theSum->h3;

        // Find out how far along we are in the partial block and copy to last block
        partPtr = theSum->partialBlock;
        endPtr = partPtr + ( theSum->bytesSoFar & 0x3f );
        for(i = 0; partPtr != endPtr; i++)
        {
                lastBlock[i] = *partPtr++;
        }

        // Add one more 1 bit and 7 zeros
        lastBlock[i++] = 0x80;

        // If there's 8 or more bytes left to 64, then this is the last block
        if(i > 56u)
        {// If there's not enough space, then zero fill this and add a new block
                // Zero pad the remainder
                for( ; i < 64u; lastBlock[i++] = 0x00);

                // Calculate a hash on this block and add it to the sum
                MD5HashBlock(lastBlock, &h0, &h1, &h2, &h3);

                // Create a new block for the size
                i = 0;
        }

        // Zero fill the rest of the block
        for( ; i < 56u; lastBlock[i++] = 0x00);

        // Fill in the size, in bits, in little-endian
        lastBlock[56] = theSum->bytesSoFar << 3;
        lastBlock[57] = theSum->bytesSoFar >> 5;
        lastBlock[58] = theSum->bytesSoFar >> 13;
        lastBlock[59] = theSum->bytesSoFar >> 21;
        lastBlock[60] = theSum->bytesSoFar >> 29;
        lastBlock[61] = 0;
        lastBlock[62] = 0;
        lastBlock[63] = 0;

        // Calculate a hash on this final block and add it to the sum
        MD5HashBlock(lastBlock, &h0, &h1, &h2, &h3);
        
        // Format the result in little-endian format
        memcpy((void*)result,(void*)&h0,4);
        memcpy((void*)&result[4],(void*)&h1,4);
        memcpy((void*)&result[8],(void*)&h2,4);
        memcpy((void*)&result[12],(void*)&h3,4);
}

#endif //ends MD5

/****************************************************************************
  Section:
        Functions and variables required for SHA-1
  ***************************************************************************/

#if defined(STACK_USE_SHA1)

static void SHA1HashBlock(BYTE* data, DWORD* h0, DWORD* h1, DWORD* h2, DWORD* h3, DWORD* h4);

/*****************************************************************************
  Function:
        void SHA1Initialize(HASH_SUM* theSum)

  Description:
        Initializes a new SHA-1 hash.

  Precondition:
        None

  Parameters:
        theSum - pointer to the allocated HASH_SUM object to initialize as SHA-1

  Returns:
        None
  ***************************************************************************/
void SHA1Initialize(HASH_SUM* theSum)
{
        theSum->h0 = 0x67452301;
        theSum->h1 = 0xEFCDAB89;
        theSum->h2 = 0x98BADCFE;
        theSum->h3 = 0x10325476;
        theSum->h4 = 0xC3D2E1F0;
        theSum->bytesSoFar = 0;
        theSum->hashType = HASH_SHA1;
}

/*****************************************************************************
  Function:
        void SHA1AddData(HASH_SUM* theSum, BYTE* data, WORD len)

  Description:
        Adds data to a SHA-1 hash calculation.

  Precondition:
        The hash context has already been initialized.

  Parameters:
        theSum - a pointer to the hash context structure
        data - the data to add to the hash
        len - the length of the data to add

  Returns:
        None
  ***************************************************************************/
void SHA1AddData(HASH_SUM* theSum, BYTE* data, WORD len)
{
        BYTE *blockPtr;

        // Seek to the first free byte
        blockPtr = theSum->partialBlock + ( theSum->bytesSoFar & 0x3f );

        // Update the total number of bytes
        theSum->bytesSoFar += len;

        // Copy data into the partial block
        while(len != 0u)
        {
                *blockPtr++ = *data++;

                // If the partial block is full, hash the data and start over
                if(blockPtr == theSum->partialBlock + 64)
                {
                        SHA1HashBlock(theSum->partialBlock, &theSum->h0, &theSum->h1,
                                                         &theSum->h2, &theSum->h3, &theSum->h4);
                        blockPtr = theSum->partialBlock;
                }
                
                len--;
        }
        
}

/*****************************************************************************
  Function:
        void SHA1AddROMData(HASH_SUM* theSum, ROM BYTE* data, WORD len)

  Description:
        Adds data to a SHA-1 hash calculation.

  Precondition:
        The hash context has already been initialized.

  Parameters:
        theSum - a pointer to the hash context structure
        data - the data to add to the hash
        len - the length of the data to add

  Returns:
        None
        
  Remarks:
        This function is aliased to SHA1AddData on non-PIC18 platforms.
  ***************************************************************************/
#if defined(__18CXX)
void SHA1AddROMData(HASH_SUM* theSum, ROM BYTE* data, WORD len)
{
        BYTE *blockPtr;

        // Seek to the first free byte
        blockPtr = theSum->partialBlock + ( theSum->bytesSoFar & 0x3f );

        // Update the total number of bytes
        theSum->bytesSoFar += len;

        // Copy data into the partial block
        while(len != 0u)
        {
                *blockPtr++ = *data++;

                // If the partial block is full, hash the data and start over
                if(blockPtr == theSum->partialBlock + 64)
                {
                        SHA1HashBlock(theSum->partialBlock, &theSum->h0, &theSum->h1,
                                                         &theSum->h2, &theSum->h3, &theSum->h4);
                        blockPtr = theSum->partialBlock;
                }
                
                len--;
        }
        
}
#endif

/*****************************************************************************
  Function:
        static void SHA1HashBlock(BYTE* data, DWORD* h0, DWORD* h1, 
                                                                DWORD* h2, DWORD* h3, DWORD* h4)

  Summary:
        Calculates the SHA-1 hash sum of a block.

  Description:
        This function calculates the SHA-1 hash sum over a block and updates
        the values of h0-h3 with the next context.

  Precondition:
        The data pointer must be WORD aligned on 16-bit parts and DWORD
        aligned on 32-bit PICs.  If alignment is not correct, a memory alignment
        exception will occur.

  Parameters:
        data - The block of 64 bytes to hash
        h0 - the current hash context h0 value
        h1 - the current hash context h1 value
        h2 - the current hash context h2 value
        h3 - the current hash context h3 value
        h4 - the current hash context h4 value

  Returns:
        None
  
  Internal:
        TODO convert data to a DWORD* or read from the pointer using byte
        accesses only to avoid any accidental alignment errors
  ***************************************************************************/
static void SHA1HashBlock(BYTE* data, DWORD* h0, DWORD* h1, DWORD* h2, 
                                                        DWORD* h3, DWORD* h4)
{
        DWORD a, b, c, d, e, f, k, temp;
        DWORD_VAL *w = (DWORD_VAL*)lastBlock;
        BYTE i, back3, back8, back14;

        // Set up a, b, c, d, e
        a = *h0;
        b = *h1;
        c = *h2;
        d = *h3;
        e = *h4;

        // Set up the w[] vector
        if(lastBlock == data)
        {// If they're the same, just swap endian-ness
                for(i = 0; i < 16u; i++)
                {
                        back3 = data[3];
                        data[3] = data[0];
                        data[0] = back3;
                        back3 = data[1];
                        data[1] = data[2];
                        data[2] = back3;
                        data += 4;
                }
        }
        else
        {// Otherwise, copy values in swaping endian-ness as we go
                for(i = 0; i < 16u; i++)
                {
                        w[i].v[3] = *data++;
                        w[i].v[2] = *data++;
                        w[i].v[1] = *data++;
                        w[i].v[0] = *data++;
                }
        }
        back3 = 13;
        back8 = 8;
        back14 = 2;

        // Main mixer loop for 80 operations
        for(i = 0; i < 80u; i++)
        {
                if(i <= 19u)
                {
                        f = (b & c) | ((~b) & d);
                        k = 0x5A827999;
                }
                else if(i >= 20u && i <= 39u)
                {
                        f = b ^ c ^ d;
                        k = 0x6ED9EBA1;
                }
                else if(i >= 40u && i <= 59u)
                {
                        f = (b & c) | (b & d) | (c & d);
                        k = 0x8F1BBCDC;
                }
                else
                {
                        f = b ^ c ^ d;
                        k = 0xCA62C1D6;
                }

                // Calculate the w[] value and store it in the array for future use
                if(i >= 16u)
                {
                        #if defined(HI_TECH_C)
                        // This section is unrolled for HI_TECH_C because it cannot parse
                        // the expression used by the other compilers
                        DWORD temp2;
                        temp = w[back3].Val;
                        temp2 = w[back8].Val;
                        temp ^= temp2;
                        temp2 = w[back14].Val;
                        temp ^= temp2;
                        temp2 = w[i&0x0f].Val;
                        temp ^= temp2;
                        w[i&0x0f].Val = leftRotateDWORD(temp, 1);
                        #else
                        w[i&0x0f].Val = leftRotateDWORD( ( w[back3].Val ^ w[back8].Val ^
                                                                                        w[back14].Val ^ w[i&0x0f].Val), 1);
                        #endif
                        back3 += 1;
                        back8 += 1;
                        back14 += 1;
                        back3 &= 0x0f;
                        back8 &= 0x0f;
                        back14 &= 0x0f;
                }
                
                // Calculate the new mixers
                temp = leftRotateDWORD(a, 5) + f + e + k + w[i & 0x0f].Val;
                e = d;
                d = c;
                c = leftRotateDWORD(b, 30);
                b = a;
                a = temp;
        }

        // Add the new hash to the sum
        *h0 += a;
        *h1 += b;
        *h2 += c;
        *h3 += d;
        *h4 += e;

}

/*****************************************************************************
  Function:
        void MD5Calculate(HASH_SUM* theSum, BYTE* result)

  Summary:
        Calculates a SHA-1 hash

  Description:
        This function calculates the hash sum of all input data so far.  It is
        non-destructive to the hash context, so more data may be added after
        this function is called.

  Precondition:
        The hash context has been properly initialized.

  Parameters:
        theSum - the current hash context
        result - 20 byte array in which to store the resulting hash

  Returns:
        None
  ***************************************************************************/
void SHA1Calculate(HASH_SUM* theSum, BYTE* result)
{
        DWORD h0, h1, h2, h3, h4;
        BYTE i, *partPtr, *endPtr;

        // Initialize the hash variables
        h0 = theSum->h0;
        h1 = theSum->h1;
        h2 = theSum->h2;
        h3 = theSum->h3;
        h4 = theSum->h4;

        // Find out how far along we are in the partial block and copy to last block
        partPtr = theSum->partialBlock;
        endPtr = partPtr + ( theSum->bytesSoFar & 0x3f );
        for(i = 0; partPtr != endPtr; i++)
        {
                lastBlock[i] = *partPtr++;
        }

        // Add one more bit and 7 zeros
        lastBlock[i++] = 0x80;

        // If there's 8 or more bytes left to 64, then this is the last block
        if(i > 56u)
        {// If there's not enough space, then zero fill this and add a new block
                // Zero pad the remainder
                for( ; i < 64u; lastBlock[i++] = 0x00);

                // Calculate a hash on this block and add it to the sum
                SHA1HashBlock(lastBlock, &h0, &h1, &h2, &h3, &h4);

                //create a new block for the size
                i = 0;
        }

        // Zero fill the rest of the block
        for( ; i < 56u; lastBlock[i++] = 0x00);

        // Fill in the size, in bits, in big-endian
        lastBlock[63] = theSum->bytesSoFar << 3;
        lastBlock[62] = theSum->bytesSoFar >> 5;
        lastBlock[61] = theSum->bytesSoFar >> 13;
        lastBlock[60] = theSum->bytesSoFar >> 21;
        lastBlock[59] = theSum->bytesSoFar >> 29;
        lastBlock[58] = 0;
        lastBlock[57] = 0;
        lastBlock[56] = 0;

        // Calculate a hash on this final block and add it to the sum
        SHA1HashBlock(lastBlock, &h0, &h1, &h2, &h3, &h4);
        
        // Format the result in big-endian format
        *result++ = ((BYTE*)&h0)[3];
        *result++ = ((BYTE*)&h0)[2];
        *result++ = ((BYTE*)&h0)[1];
        *result++ = ((BYTE*)&h0)[0];
        *result++ = ((BYTE*)&h1)[3];
        *result++ = ((BYTE*)&h1)[2];
        *result++ = ((BYTE*)&h1)[1];
        *result++ = ((BYTE*)&h1)[0];
        *result++ = ((BYTE*)&h2)[3];
        *result++ = ((BYTE*)&h2)[2];
        *result++ = ((BYTE*)&h2)[1];
        *result++ = ((BYTE*)&h2)[0];
        *result++ = ((BYTE*)&h3)[3];
        *result++ = ((BYTE*)&h3)[2];
        *result++ = ((BYTE*)&h3)[1];
        *result++ = ((BYTE*)&h3)[0];
        *result++ = ((BYTE*)&h4)[3];
        *result++ = ((BYTE*)&h4)[2];
        *result++ = ((BYTE*)&h4)[1];
        *result++ = ((BYTE*)&h4)[0];
}

#endif  //#end SHA-1
{FILE END}
{FOOTER START}

Powered by WebSVN v2.8.3