DeepCover Embedded Security in IoT: Public-key Secured Data Paths
Dependencies: MaximInterface
sha256_software.c
00001 /******************************************************************************* 00002 * Copyright (C) 2013 Maxim Integrated Products, Inc., All Rights Reserved. 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a 00005 * copy of this software and associated documentation files (the "Software"), 00006 * to deal in the Software without restriction, including without limitation 00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00008 * and/or sell copies of the Software, and to permit persons to whom the 00009 * Software is furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included 00012 * in all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00017 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES 00018 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 00019 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 00020 * OTHER DEALINGS IN THE SOFTWARE. 00021 * 00022 * Except as contained in this notice, the name of Maxim Integrated 00023 * Products, Inc. shall not be used except as stated in the Maxim Integrated 00024 * Products, Inc. Branding Policy. 00025 * 00026 * The mere transfer of this software does not imply any licenses 00027 * of trade secrets, proprietary technology, copyrights, patents, 00028 * trademarks, maskwork rights, or any other form of intellectual 00029 * property whatsoever. Maxim Integrated Products, Inc. retains all 00030 * ownership rights. 00031 ******************************************************************************* 00032 */ 00033 00034 #include <string.h> 00035 00036 typedef unsigned char uchar; 00037 typedef unsigned short ushort; 00038 typedef unsigned long ulong; 00039 00040 #define SHA_256_INITIAL_LENGTH 8 00041 00042 #define TRUE 1 00043 #define FALSE 0 00044 00045 // General Purpose SHA-256 Function 00046 void ComputeSHA256(uchar* message, short length, ushort skipconst, ushort reverse, uchar* digest); 00047 00048 // Utility Functions 00049 static ulong sha_ch(ulong x, ulong y, ulong z); 00050 static ulong sha_maj(ulong x, ulong y, ulong z); 00051 static ulong sha_rotr_32(ulong val, ushort r); 00052 static ulong sha_shr_32(ulong val, ushort r); 00053 static ulong sha_bigsigma256_0(ulong x); 00054 static ulong sha_littlesigma256_0(ulong x); 00055 static ulong sha_littlesigma256_1(ulong x); 00056 static void sha_copy32(const ulong* p1, ulong* p2, ushort length); 00057 static void sha_copyWordsToBytes32(const ulong* input, uchar* output, ushort numwords); 00058 static void sha_writeResult(ushort reverse, uchar* outpointer, const ulong* H32); 00059 static ulong sha_getW(int index, ulong* W32); 00060 static void sha_prepareSchedule(const uchar* message, ulong* W32); 00061 static void sha256_hashblock(const uchar* message, ushort lastblock, ulong* H32); 00062 00063 // External Debug print 00064 #ifdef DEBUG_SHA 00065 extern int dprintf(char *format, ...); 00066 #endif 00067 00068 // SHA-256 globals values 00069 static const ulong SHA_256_Initial[] = 00070 { 00071 0x6a09e667, 00072 0xbb67ae85, 00073 0x3c6ef372, 00074 0xa54ff53a, 00075 0x510e527f, 00076 0x9b05688c, 00077 0x1f83d9ab, 00078 0x5be0cd19 00079 }; 00080 00081 static const ulong SHA_CONSTANTS[] = 00082 { 00083 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 00084 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 00085 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 00086 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 00087 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 00088 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 00089 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 00090 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, 00091 0xca273ece, 0xd186b8c7, 0xeada7dd6, 0xf57d4f7f, 0x06f067aa, 0x0a637dc5, 0x113f9804, 0x1b710b35, 00092 0x28db77f5, 0x32caab7b, 0x3c9ebe0a, 0x431d67c4, 0x4cc5d4be, 0x597f299c, 0x5fcb6fab, 0x6c44198c 00093 }; 00094 00095 //----------------------------------------------------------------------------- 00096 // ------ General Purpose SHA-256 Function 00097 //----------------------------------------------------------------------------- 00098 00099 //----------------------------------------------------------------------------- 00100 /// Computes SHA-256 given the data block 'message' with no padding. 00101 /// The result is returned in 'digest'. 00102 /// 00103 /// @param[in] message 00104 /// Buffer containing the message to hash 00105 /// @param[in] skipconst 00106 /// Flag to skip adding constant on last block (skipconst=1) (Required for Maxim devices) 00107 /// @param[in] reverse 00108 /// Flag to reverse order of digest (reverse=1, MSWord first, LSByte first) (Required for Maxim devices) 00109 /// @param[out] digest 00110 /// Pointer to result hash digest in byte order used by Maxim devices 00111 // 00112 void ComputeSHA256(uchar* message, short length, ushort skipconst, ushort reverse, uchar* digest) 00113 { 00114 const ushort wordsize = 32; 00115 00116 ushort bytes_per_block; 00117 ushort nonpaddedlength; 00118 ushort numblocks; 00119 ushort i,j; 00120 ulong bitlength; 00121 ushort markerwritten; 00122 ushort lastblock; 00123 00124 uchar workbuffer[128]; 00125 ulong H32[8]; // last SHA result variables 00126 00127 #ifdef DEBUG_SHA 00128 dprintf("\nSHA-256 INPUT:\n"); 00129 for (i = 0; i < length; i+=4) 00130 { 00131 for (j = 0; j < 4; j++) 00132 dprintf("%02X ",message[i+j]); 00133 dprintf("\n"); 00134 } 00135 dprintf("\n"); 00136 #endif 00137 00138 // if wordsize is 32 bits, we need 512 bit blocks. else 1024 bit blocks. 00139 // that means 16 words are in one message. 00140 bytes_per_block = 16 * (wordsize / 8); 00141 // 1 byte for the '80' that follows the message, 8 or 16 bytes of length 00142 nonpaddedlength = length + 1 + (wordsize/4); 00143 numblocks = nonpaddedlength / bytes_per_block; 00144 if ((nonpaddedlength % bytes_per_block) != 0) 00145 { 00146 // then there is some remainder we need to pad 00147 numblocks++; 00148 } 00149 00150 sha_copy32(SHA_256_Initial, H32, SHA_256_INITIAL_LENGTH); 00151 00152 bitlength = 8 * length; 00153 markerwritten = 0; 00154 // 'length' is our number of bytes remaining. 00155 for (i = 0; i < numblocks; i++) 00156 { 00157 if (length > bytes_per_block) 00158 { 00159 memcpy(workbuffer, message, bytes_per_block); 00160 length -= bytes_per_block; 00161 } 00162 else if (length==bytes_per_block) 00163 { 00164 memcpy(workbuffer, message, length); 00165 length = 0; 00166 } 00167 else // length is less than number of bytes in a block 00168 { 00169 memcpy(workbuffer, message, length); 00170 // message is now used for temporary space 00171 message = workbuffer + length; 00172 if (markerwritten == 0) 00173 { 00174 *message++ = 0x80; 00175 length++; 00176 } 00177 00178 while (length < bytes_per_block) 00179 { 00180 // this loop is inserting padding, in this case all zeroes 00181 *message++ = 0; 00182 length++; 00183 } 00184 length = 0; 00185 // signify that we have already written the 80h 00186 markerwritten = 1; 00187 } 00188 00189 // on the last block, put the bit length at the very end 00190 lastblock = (i == (numblocks - 1)); 00191 if (lastblock) 00192 { 00193 // point at the last byte in the block 00194 message = workbuffer + bytes_per_block - 1; 00195 for (j = 0; j < wordsize/4; j++) 00196 { 00197 *message-- = (uchar)bitlength; 00198 bitlength = bitlength >> 8; 00199 } 00200 } 00201 00202 // SHA in software 00203 sha256_hashblock(workbuffer, (ushort)(lastblock && skipconst), H32); 00204 message += bytes_per_block; 00205 } 00206 00207 sha_writeResult(reverse, digest, H32); 00208 00209 #ifdef DEBUG_SHA 00210 dprintf("\nSHA-256 Result:\n"); 00211 for (i = 0; i < 32; i++) 00212 dprintf("%02X ",digest[i]); 00213 dprintf("\n"); 00214 #endif 00215 } 00216 00217 //----------------------------------------------------------------------------- 00218 // ------ Internal utility functions to support SHA-256 calculation 00219 //----------------------------------------------------------------------------- 00220 00221 //----------------------------------------------------------------------------- 00222 /// @internal 00223 /// SHA-256 support function 00224 /// @endinternal 00225 // 00226 static ulong sha_ch(ulong x, ulong y, ulong z) 00227 { 00228 return (x & y) ^ ((~x) & z); 00229 } 00230 00231 //----------------------------------------------------------------------------- 00232 /// @internal 00233 /// SHA-256 support function 00234 /// @endinternal 00235 // 00236 static ulong sha_maj(ulong x, ulong y, ulong z) 00237 { 00238 ulong temp = x & y; 00239 temp ^= (x & z); 00240 temp ^= (y & z); 00241 return temp; //(x & y) ^ (x & z) ^ (y & z); 00242 } 00243 00244 //----------------------------------------------------------------------------- 00245 /// @internal 00246 /// SHA-256 support function 00247 /// @endinternal 00248 // 00249 static ulong sha_rotr_32(ulong val, ushort r) 00250 { 00251 val = val & 0xFFFFFFFFL; 00252 return ((val >> r) | (val << (32 - r))) & 0xFFFFFFFFL; 00253 } 00254 00255 //----------------------------------------------------------------------------- 00256 /// @internal 00257 /// SHA-256 support function 00258 /// @endinternal 00259 // 00260 static ulong sha_shr_32(ulong val, ushort r) 00261 { 00262 val = val & 0xFFFFFFFFL; 00263 return val >> r; 00264 } 00265 00266 //----------------------------------------------------------------------------- 00267 /// @internal 00268 /// SHA-256 support function 00269 /// @endinternal 00270 // 00271 static ulong sha_bigsigma256_0(ulong x) 00272 { 00273 return sha_rotr_32(x,2) ^ sha_rotr_32(x,13) ^ sha_rotr_32(x,22); 00274 } 00275 00276 //----------------------------------------------------------------------------- 00277 /// @internal 00278 /// SHA-256 support function 00279 /// @endinternal 00280 // 00281 static ulong sha_bigsigma256_1(ulong x) 00282 { 00283 return sha_rotr_32(x,6) ^ sha_rotr_32(x,11) ^ sha_rotr_32(x,25); 00284 } 00285 00286 //----------------------------------------------------------------------------- 00287 /// @internal 00288 /// SHA-256 support function 00289 /// @endinternal 00290 // 00291 static ulong sha_littlesigma256_0(ulong x) 00292 { 00293 return sha_rotr_32(x,7) ^ sha_rotr_32(x,18) ^ sha_shr_32(x,3); 00294 } 00295 00296 //----------------------------------------------------------------------------- 00297 /// @internal 00298 /// SHA-256 support function 00299 /// @endinternal 00300 // 00301 static ulong sha_littlesigma256_1(ulong x) 00302 { 00303 return sha_rotr_32(x,17) ^ sha_rotr_32(x,19) ^ sha_shr_32(x,10); 00304 } 00305 00306 //----------------------------------------------------------------------------- 00307 /// @internal 00308 /// SHA-256 support function 00309 /// @endinternal 00310 // 00311 static void sha_copy32(const ulong* p1, ulong* p2, ushort length) 00312 { 00313 while (length > 0) 00314 { 00315 *p2++ = *p1++; 00316 length--; 00317 } 00318 } 00319 00320 //----------------------------------------------------------------------------- 00321 /// @internal 00322 /// SHA-256 support function 00323 /// @endinternal 00324 // 00325 static void sha_copyWordsToBytes32(const ulong* input, uchar* output, ushort numwords) 00326 { 00327 ulong temp; 00328 ushort i; 00329 00330 for (i=0;i<numwords;i++) 00331 { 00332 temp = *input++; 00333 *output++ = (uchar)(temp >> 24); 00334 *output++ = (uchar)(temp >> 16); 00335 *output++ = (uchar)(temp >> 8); 00336 *output++ = (uchar)(temp); 00337 } 00338 } 00339 00340 //----------------------------------------------------------------------------- 00341 /// @internal 00342 /// SHA-256 support function 00343 /// @endinternal 00344 // 00345 static void sha_writeResult(ushort reverse, uchar* outpointer, const ulong* H32) 00346 { 00347 int i; 00348 uchar tmp; 00349 00350 sha_copyWordsToBytes32(H32, outpointer, 8); 00351 00352 if (reverse) 00353 { 00354 for (i = 0; i < 16; i++) 00355 { 00356 tmp = outpointer[i]; 00357 outpointer[i] = outpointer[31-i]; 00358 outpointer[31-i] = tmp; 00359 } 00360 } 00361 00362 } 00363 00364 //----------------------------------------------------------------------------- 00365 /// @internal 00366 /// SHA-256 support function 00367 /// @endinternal 00368 // 00369 static ulong sha_getW(int index, ulong* W32) 00370 { 00371 ulong newW; 00372 if (index < 16) 00373 { 00374 return W32[index]; 00375 } 00376 00377 newW = sha_littlesigma256_1(W32[(index-2)&0x0f]) + 00378 W32[(index-7)&0x0f] + 00379 sha_littlesigma256_0(W32[(index-15)&0x0f]) + 00380 W32[(index-16)&0x0f]; 00381 W32[index & 0x0f] = newW & 0xFFFFFFFFL; // just in case... 00382 00383 return newW; 00384 } 00385 00386 //----------------------------------------------------------------------------- 00387 /// @internal 00388 /// SHA-256 support function 00389 /// Prepair the block for hashing 00390 /// @endinternal 00391 // 00392 static void sha_prepareSchedule(const uchar* message, ulong* W32) 00393 { 00394 // we need to copy the initial message into the 16 W registers 00395 ushort i,j; 00396 ulong temp; 00397 for (i = 0; i < 16; i++) 00398 { 00399 temp = 0; 00400 for (j = 0; j < 4;j++) 00401 { 00402 temp = temp << 8; 00403 temp = temp | (*message & 0xff); 00404 message++; 00405 } 00406 00407 W32[i] = temp; 00408 } 00409 } 00410 00411 //----------------------------------------------------------------------------- 00412 /// @internal 00413 /// SHA-256 support function 00414 /// Hash a single block of data. 00415 /// @endinternal 00416 // 00417 static void sha256_hashblock(const uchar* message, ushort lastblock, ulong* H32) 00418 { 00419 ushort sha1counter = 0; 00420 ushort sha1functionselect = 0; 00421 ushort i; 00422 ulong nodeT1, nodeT2; 00423 00424 ulong Wt, Kt; 00425 00426 ulong a32, b32, c32, d32, e32, f32, g32, h32; // SHA working variables 00427 ulong W32[16]; // SHA message schedule 00428 00429 // chunk the original message into the working schedule 00430 sha_prepareSchedule(message, W32); 00431 00432 a32 = H32[0]; 00433 b32 = H32[1]; 00434 c32 = H32[2]; 00435 d32 = H32[3]; 00436 e32 = H32[4]; 00437 f32 = H32[5]; 00438 g32 = H32[6]; 00439 h32 = H32[7]; 00440 00441 // rounds 00442 for (i = 0; i < 64; i++) 00443 { 00444 Wt = sha_getW(i, W32); 00445 Kt = SHA_CONSTANTS[i]; 00446 00447 nodeT1 = (h32 + sha_bigsigma256_1(e32) + sha_ch(e32,f32,g32) + Kt + Wt); // & 0xFFFFFFFFL; 00448 nodeT2 = (sha_bigsigma256_0(a32) + sha_maj(a32,b32,c32)); // & 0xFFFFFFFFL; 00449 h32 = g32; 00450 g32 = f32; 00451 f32 = e32; 00452 e32 = d32 + nodeT1; 00453 d32 = c32; 00454 c32 = b32; 00455 b32 = a32; 00456 a32 = nodeT1 + nodeT2; 00457 00458 sha1counter++; 00459 if (sha1counter==20) 00460 { 00461 sha1functionselect++; 00462 sha1counter = 0; 00463 } 00464 00465 } 00466 00467 if (!lastblock) 00468 { 00469 // now fix up our H array 00470 H32[0] += a32; 00471 H32[1] += b32; 00472 H32[2] += c32; 00473 H32[3] += d32; 00474 H32[4] += e32; 00475 H32[5] += f32; 00476 H32[6] += g32; 00477 H32[7] += h32; 00478 } 00479 else 00480 { 00481 // now fix up our H array 00482 H32[0] = a32; 00483 H32[1] = b32; 00484 H32[2] = c32; 00485 H32[3] = d32; 00486 H32[4] = e32; 00487 H32[5] = f32; 00488 H32[6] = g32; 00489 H32[7] = h32; 00490 } 00491 }
Generated on Tue Jul 12 2022 12:06:49 by 1.7.2