// /* // --------------------------------------------------------------------------- // Copyright (c) 2002, Dr Brian Gladman , Worcester, UK. // All rights reserved. // LICENSE TERMS // The free distribution and use of this software in both source and binary // form is allowed (with or without changes) provided that: // 1. distributions of this source code include the above copyright // notice, this list of conditions and the following disclaimer; // 2. distributions in binary form include the above copyright // notice, this list of conditions and the following disclaimer // in the documentation and/or other associated materials; // 3. the copyright holder's name is not used to endorse products // built using this software without specific written permission. // ALTERNATIVELY, provided that this notice is retained in full, this product // may be distributed under the terms of the GNU General Public License (GPL), // in which case the provisions of the GPL apply INSTEAD OF those given above. // DISCLAIMER // This software is provided 'as is' with no explicit or implied warranties // in respect of its properties, including, but not limited to, correctness // and/or fitness for purpose. // --------------------------------------------------------------------------- // Issue Date: 24/01/2003 // This is a byte oriented version of SHA1 that operates on arrays of bytes // stored in memory. // */ // #include "com_BmcType.h" // #include "sha1.h" // #include "memory.h" // #include "Platform.h" // #include "coreTypes.h" // /* // To obtain the highest speed on processors with 32-bit words, this code // needs to determine the order in which bytes are packed into such words. // The following block of code is an attempt to capture the most obvious // ways in which various environemnts specify their endian definitions. // It may well fail, in which case the definitions will need to be set by // editing at the points marked **** EDIT HERE IF NECESSARY **** below. // */ // #define SHA_LITTLE_ENDIAN 1 // #define SHA_BIG_ENDIAN 2 // #if IS_PLATFORM_X86() || IS_PLATFORM_ARM() || IS_PLATFORM_SH() // #define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN // #else // #define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN // #endif // #define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) // #if (PLATFORM_BYTE_ORDER == SHA_BIG_ENDIAN) // #define swap_b32(x) (x) // #elif defined(bswap_32) // #define swap_b32(x) bswap_32(x) // #else // #define swap_b32(x) ((rotl32((x), 8) & 0x00ff00ff) | (rotl32((x), 24) & 0xff00ff00)) // #endif // #define SHA1_MASK (SHA1_BLOCK_SIZE - 1) // /* reverse byte order in 32-bit words */ // #define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z))) // #define parity(x,y,z) ((x) ^ (y) ^ (z)) // #define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) // /* A normal version as set out in the FIPS */ // #define rnd(f,k) \ // t = a; a = rotl32(a,5) + f(b,c,d) + e + k + w[i]; \ // e = d; d = c; c = rotl32(b, 30); b = t // #if (PLATFORM_BYTE_ORDER == SHA_LITTLE_ENDIAN) // static uint32 mask[4] = // { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff }; // static uint32 bits[4] = // { 0x00000080, 0x00008000, 0x00800000, 0x80000000 }; // #else // static uint32 mask[4] = // { 0x00000000, 0xff000000, 0xffff0000, 0xffffff00 }; // static uint32 bits[4] = // { 0x80000000, 0x00800000, 0x00008000, 0x00000080 }; // #endif // /*---------------------------------------- // * sha1_compile // *----------------------------------------*/ // void // sha1_compile ( Sha1_Ctx_T* pctx) // { // int i; // uint32 w [80], a, b, c, d, e, t; // /* note that words are compiled from the buffer into 32-bit */ // /* words in big-endian order so an order reversal is needed */ // /* here on little endian machines */ // for (i = 0; i < SHA1_BLOCK_SIZE / 4; ++i) // { // w [i] = swap_b32 (pctx->wbuf [i]); // } // for (i = SHA1_BLOCK_SIZE / 4; i < 80; ++i) // { // w[i] = rotl32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1); // } // a = pctx->hash [0]; // b = pctx->hash [1]; // c = pctx->hash [2]; // d = pctx->hash [3]; // e = pctx->hash [4]; // for (i = 0; i < 20; ++i) // { // rnd (ch, 0x5a827999); // } // for (i = 20; i < 40; ++i) // { // rnd (parity, 0x6ed9eba1); // } // for (i = 40; i < 60; ++i) // { // rnd (maj, 0x8f1bbcdc); // } // for (i = 60; i < 80; ++i) // { // rnd (parity, 0xca62c1d6); // } // pctx->hash [0] += a; // pctx->hash [1] += b; // pctx->hash [2] += c; // pctx->hash [3] += d; // pctx->hash [4] += e; // } // /*---------------------------------------- // * sha1_begin // *----------------------------------------*/ // void // sha1_begin ( Sha1_Ctx_T* pctx) // { // pctx->count [0] = pctx->count [1] = 0; // pctx->hash [0] = 0x67452301; // pctx->hash [1] = 0xefcdab89; // pctx->hash [2] = 0x98badcfe; // pctx->hash [3] = 0x10325476; // pctx->hash [4] = 0xc3d2e1f0; // } // /*---------------------------------------- // * sha1_hash // *----------------------------------------*/ // void // sha1_hash ( INT8U* pdata, INT16U len, Sha1_Ctx_T* pctx) // { // /* SHA1 hash data in an array of bytes into hash buffer and */ // /* call the hash_compile function as required. */ // uint32 pos = (uint32)(pctx->count[0] & SHA1_MASK), // space = SHA1_BLOCK_SIZE - pos; // INT8U *sp = pdata; // if ((pctx->count[0] += len) < len) { ++(pctx->count[1]); } // while (len >= space) /* tranfer whole blocks if possible */ // { // memcpy ((( INT8U*)pctx->wbuf) + pos, sp, space); // sp += space; len -= (INT16U)space; space = SHA1_BLOCK_SIZE; pos = 0; // sha1_compile (pctx); // } // //dispscont (pctx); // /*lint -e{803} conceivable data overrun */ // /* there are two cases: the above while loop entered or not */ // /* entered. If not entered, 'space = SHA1_BLOCK_SIZE - pos' */ // /* and 'len < space' so that 'len + pos < SHA1_BLOCK_SIZE'. */ // /* If entered, 'pos = 0', 'space = SHA1_BLOCK_SIZE' and */ // /* 'len < space' so that 'pos + len < SHA1_BLOCK_SIZE'. In */ // /* both cases, therefore, the memory copy is in the buffer */ // memcpy ((( INT8U*)pctx->wbuf) + pos, sp, len); // } // /*---------------------------------------- // * sha1_end // *----------------------------------------*/ // void // sha1_end ( INT8U* phval, Sha1_Ctx_T* pctx) // { // uint32 i = (uint32)(pctx->count [0] & SHA1_MASK); // /* SHA1 final padding and digest calculation */ // /* mask out the rest of any partial 32-bit word and then set */ // /* the next byte to 0x80. On big-endian machines any bytes in */ // /* the buffer will be at the top end of 32 bit words, on little */ // /* endian machines they will be at the bottom. Hence the AND */ // /* and OR masks above are reversed for little endian systems */ // /* Note that we can always add the first padding byte at this */ // /* point because the buffer always has at least one empty slot */ // pctx->wbuf [(INT16U)(i >> 2)] = (pctx->wbuf [(INT16U)(i >> 2)] & mask [(INT16U)(i & 3)]) | bits [(INT16U)(i & 3)]; // /* we need 9 or more empty positions, one for the padding byte */ // /* (above) and eight for the length count. If there is not */ // /* enough space pad and empty the buffer */ // if (i > SHA1_BLOCK_SIZE - 9) // { // if (i < 60) { pctx->wbuf [15] = 0; } // sha1_compile (pctx); // i = 0; // } // else /* compute a word index for the empty buffer positions */ // { // i = (i >> 2) + 1; // } // /* and zero pad all but last two positions */ // while (i < 14) { pctx->wbuf[(INT16U)(i++)] = 0; } // /* assemble the eight byte counter in in big-endian format */ // pctx->wbuf [14] = swap_b32 ((pctx->count[1] << 3) | (pctx->count[0] >> 29)); // pctx->wbuf [15] = swap_b32 (pctx->count[0] << 3); // sha1_compile (pctx); // /* extract the hash value as bytes in case the hash buffer is */ // /* misaligned for 32-bit words */ // /*lint -e{504} unusual shift operation (unusually formed right argument) */ // for (i = 0; i < SHA1_DIGEST_SIZE; ++i) // { // phval [(INT16U)(i)] = (INT8U)(pctx->hash [(INT16U)(i >> 2)] >> (8 * (~i & 3))); // } // } // /*---------------------------------------- // * sha1 // *----------------------------------------*/ // void // sha1 ( INT8U* phval, INT8U* pdata, INT16U len) // { // Sha1_Ctx_T cx; // sha1_begin (&cx); // sha1_hash (pdata, len, &cx); // sha1_end (phval, &cx); // }