1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * SHA1 hash implementation and interface functions 3e5b75505Sopenharmony_ci * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> 4e5b75505Sopenharmony_ci * 5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license. 6e5b75505Sopenharmony_ci * See README for more details. 7e5b75505Sopenharmony_ci */ 8e5b75505Sopenharmony_ci 9e5b75505Sopenharmony_ci#include "includes.h" 10e5b75505Sopenharmony_ci 11e5b75505Sopenharmony_ci#include "common.h" 12e5b75505Sopenharmony_ci#include "sha1.h" 13e5b75505Sopenharmony_ci#include "sha1_i.h" 14e5b75505Sopenharmony_ci#include "md5.h" 15e5b75505Sopenharmony_ci#include "crypto.h" 16e5b75505Sopenharmony_ci 17e5b75505Sopenharmony_citypedef struct SHA1Context SHA1_CTX; 18e5b75505Sopenharmony_ci 19e5b75505Sopenharmony_civoid SHA1Transform(u32 state[5], const unsigned char buffer[64]); 20e5b75505Sopenharmony_ci 21e5b75505Sopenharmony_ci 22e5b75505Sopenharmony_ci#ifdef CONFIG_CRYPTO_INTERNAL 23e5b75505Sopenharmony_ci/** 24e5b75505Sopenharmony_ci * sha1_vector - SHA-1 hash for data vector 25e5b75505Sopenharmony_ci * @num_elem: Number of elements in the data vector 26e5b75505Sopenharmony_ci * @addr: Pointers to the data areas 27e5b75505Sopenharmony_ci * @len: Lengths of the data blocks 28e5b75505Sopenharmony_ci * @mac: Buffer for the hash 29e5b75505Sopenharmony_ci * Returns: 0 on success, -1 of failure 30e5b75505Sopenharmony_ci */ 31e5b75505Sopenharmony_ciint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 32e5b75505Sopenharmony_ci{ 33e5b75505Sopenharmony_ci SHA1_CTX ctx; 34e5b75505Sopenharmony_ci size_t i; 35e5b75505Sopenharmony_ci 36e5b75505Sopenharmony_ci if (TEST_FAIL()) 37e5b75505Sopenharmony_ci return -1; 38e5b75505Sopenharmony_ci 39e5b75505Sopenharmony_ci SHA1Init(&ctx); 40e5b75505Sopenharmony_ci for (i = 0; i < num_elem; i++) 41e5b75505Sopenharmony_ci SHA1Update(&ctx, addr[i], len[i]); 42e5b75505Sopenharmony_ci SHA1Final(mac, &ctx); 43e5b75505Sopenharmony_ci return 0; 44e5b75505Sopenharmony_ci} 45e5b75505Sopenharmony_ci#endif /* CONFIG_CRYPTO_INTERNAL */ 46e5b75505Sopenharmony_ci 47e5b75505Sopenharmony_ci 48e5b75505Sopenharmony_ci/* ===== start - public domain SHA1 implementation ===== */ 49e5b75505Sopenharmony_ci 50e5b75505Sopenharmony_ci/* 51e5b75505Sopenharmony_ciSHA-1 in C 52e5b75505Sopenharmony_ciBy Steve Reid <sreid@sea-to-sky.net> 53e5b75505Sopenharmony_ci100% Public Domain 54e5b75505Sopenharmony_ci 55e5b75505Sopenharmony_ci----------------- 56e5b75505Sopenharmony_ciModified 7/98 57e5b75505Sopenharmony_ciBy James H. Brown <jbrown@burgoyne.com> 58e5b75505Sopenharmony_ciStill 100% Public Domain 59e5b75505Sopenharmony_ci 60e5b75505Sopenharmony_ciCorrected a problem which generated improper hash values on 16 bit machines 61e5b75505Sopenharmony_ciRoutine SHA1Update changed from 62e5b75505Sopenharmony_ci void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int 63e5b75505Sopenharmony_cilen) 64e5b75505Sopenharmony_cito 65e5b75505Sopenharmony_ci void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned 66e5b75505Sopenharmony_cilong len) 67e5b75505Sopenharmony_ci 68e5b75505Sopenharmony_ciThe 'len' parameter was declared an int which works fine on 32 bit machines. 69e5b75505Sopenharmony_ciHowever, on 16 bit machines an int is too small for the shifts being done 70e5b75505Sopenharmony_ciagainst 71e5b75505Sopenharmony_ciit. This caused the hash function to generate incorrect values if len was 72e5b75505Sopenharmony_cigreater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). 73e5b75505Sopenharmony_ci 74e5b75505Sopenharmony_ciSince the file IO in main() reads 16K at a time, any file 8K or larger would 75e5b75505Sopenharmony_cibe guaranteed to generate the wrong hash (e.g. Test Vector #3, a million 76e5b75505Sopenharmony_ci"a"s). 77e5b75505Sopenharmony_ci 78e5b75505Sopenharmony_ciI also changed the declaration of variables i & j in SHA1Update to 79e5b75505Sopenharmony_ciunsigned long from unsigned int for the same reason. 80e5b75505Sopenharmony_ci 81e5b75505Sopenharmony_ciThese changes should make no difference to any 32 bit implementations since 82e5b75505Sopenharmony_cian 83e5b75505Sopenharmony_ciint and a long are the same size in those environments. 84e5b75505Sopenharmony_ci 85e5b75505Sopenharmony_ci-- 86e5b75505Sopenharmony_ciI also corrected a few compiler warnings generated by Borland C. 87e5b75505Sopenharmony_ci1. Added #include <process.h> for exit() prototype 88e5b75505Sopenharmony_ci2. Removed unused variable 'j' in SHA1Final 89e5b75505Sopenharmony_ci3. Changed exit(0) to return(0) at end of main. 90e5b75505Sopenharmony_ci 91e5b75505Sopenharmony_ciALL changes I made can be located by searching for comments containing 'JHB' 92e5b75505Sopenharmony_ci----------------- 93e5b75505Sopenharmony_ciModified 8/98 94e5b75505Sopenharmony_ciBy Steve Reid <sreid@sea-to-sky.net> 95e5b75505Sopenharmony_ciStill 100% public domain 96e5b75505Sopenharmony_ci 97e5b75505Sopenharmony_ci1- Removed #include <process.h> and used return() instead of exit() 98e5b75505Sopenharmony_ci2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) 99e5b75505Sopenharmony_ci3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net 100e5b75505Sopenharmony_ci 101e5b75505Sopenharmony_ci----------------- 102e5b75505Sopenharmony_ciModified 4/01 103e5b75505Sopenharmony_ciBy Saul Kravitz <Saul.Kravitz@celera.com> 104e5b75505Sopenharmony_ciStill 100% PD 105e5b75505Sopenharmony_ciModified to run on Compaq Alpha hardware. 106e5b75505Sopenharmony_ci 107e5b75505Sopenharmony_ci----------------- 108e5b75505Sopenharmony_ciModified 4/01 109e5b75505Sopenharmony_ciBy Jouni Malinen <j@w1.fi> 110e5b75505Sopenharmony_ciMinor changes to match the coding style used in Dynamics. 111e5b75505Sopenharmony_ci 112e5b75505Sopenharmony_ciModified September 24, 2004 113e5b75505Sopenharmony_ciBy Jouni Malinen <j@w1.fi> 114e5b75505Sopenharmony_ciFixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined. 115e5b75505Sopenharmony_ci 116e5b75505Sopenharmony_ci*/ 117e5b75505Sopenharmony_ci 118e5b75505Sopenharmony_ci/* 119e5b75505Sopenharmony_ciTest Vectors (from FIPS PUB 180-1) 120e5b75505Sopenharmony_ci"abc" 121e5b75505Sopenharmony_ci A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D 122e5b75505Sopenharmony_ci"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 123e5b75505Sopenharmony_ci 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 124e5b75505Sopenharmony_ciA million repetitions of "a" 125e5b75505Sopenharmony_ci 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F 126e5b75505Sopenharmony_ci*/ 127e5b75505Sopenharmony_ci 128e5b75505Sopenharmony_ci#define SHA1HANDSOFF 129e5b75505Sopenharmony_ci 130e5b75505Sopenharmony_ci#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) 131e5b75505Sopenharmony_ci 132e5b75505Sopenharmony_ci/* blk0() and blk() perform the initial expand. */ 133e5b75505Sopenharmony_ci/* I got the idea of expanding during the round function from SSLeay */ 134e5b75505Sopenharmony_ci#ifndef WORDS_BIGENDIAN 135e5b75505Sopenharmony_ci#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \ 136e5b75505Sopenharmony_ci (rol(block->l[i], 8) & 0x00FF00FF)) 137e5b75505Sopenharmony_ci#else 138e5b75505Sopenharmony_ci#define blk0(i) block->l[i] 139e5b75505Sopenharmony_ci#endif 140e5b75505Sopenharmony_ci#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \ 141e5b75505Sopenharmony_ci block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) 142e5b75505Sopenharmony_ci 143e5b75505Sopenharmony_ci/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 144e5b75505Sopenharmony_ci#define R0(v,w,x,y,z,i) \ 145e5b75505Sopenharmony_ci z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ 146e5b75505Sopenharmony_ci w = rol(w, 30); 147e5b75505Sopenharmony_ci#define R1(v,w,x,y,z,i) \ 148e5b75505Sopenharmony_ci z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ 149e5b75505Sopenharmony_ci w = rol(w, 30); 150e5b75505Sopenharmony_ci#define R2(v,w,x,y,z,i) \ 151e5b75505Sopenharmony_ci z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30); 152e5b75505Sopenharmony_ci#define R3(v,w,x,y,z,i) \ 153e5b75505Sopenharmony_ci z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ 154e5b75505Sopenharmony_ci w = rol(w, 30); 155e5b75505Sopenharmony_ci#define R4(v,w,x,y,z,i) \ 156e5b75505Sopenharmony_ci z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ 157e5b75505Sopenharmony_ci w=rol(w, 30); 158e5b75505Sopenharmony_ci 159e5b75505Sopenharmony_ci 160e5b75505Sopenharmony_ci#ifdef VERBOSE /* SAK */ 161e5b75505Sopenharmony_civoid SHAPrintContext(SHA1_CTX *context, char *msg) 162e5b75505Sopenharmony_ci{ 163e5b75505Sopenharmony_ci printf("%s (%d,%d) %x %x %x %x %x\n", 164e5b75505Sopenharmony_ci msg, 165e5b75505Sopenharmony_ci context->count[0], context->count[1], 166e5b75505Sopenharmony_ci context->state[0], 167e5b75505Sopenharmony_ci context->state[1], 168e5b75505Sopenharmony_ci context->state[2], 169e5b75505Sopenharmony_ci context->state[3], 170e5b75505Sopenharmony_ci context->state[4]); 171e5b75505Sopenharmony_ci} 172e5b75505Sopenharmony_ci#endif 173e5b75505Sopenharmony_ci 174e5b75505Sopenharmony_ci/* Hash a single 512-bit block. This is the core of the algorithm. */ 175e5b75505Sopenharmony_ci 176e5b75505Sopenharmony_civoid SHA1Transform(u32 state[5], const unsigned char buffer[64]) 177e5b75505Sopenharmony_ci{ 178e5b75505Sopenharmony_ci u32 a, b, c, d, e; 179e5b75505Sopenharmony_ci typedef union { 180e5b75505Sopenharmony_ci unsigned char c[64]; 181e5b75505Sopenharmony_ci u32 l[16]; 182e5b75505Sopenharmony_ci } CHAR64LONG16; 183e5b75505Sopenharmony_ci CHAR64LONG16* block; 184e5b75505Sopenharmony_ci#ifdef SHA1HANDSOFF 185e5b75505Sopenharmony_ci CHAR64LONG16 workspace; 186e5b75505Sopenharmony_ci block = &workspace; 187e5b75505Sopenharmony_ci os_memcpy(block, buffer, 64); 188e5b75505Sopenharmony_ci#else 189e5b75505Sopenharmony_ci block = (CHAR64LONG16 *) buffer; 190e5b75505Sopenharmony_ci#endif 191e5b75505Sopenharmony_ci /* Copy context->state[] to working vars */ 192e5b75505Sopenharmony_ci a = state[0]; 193e5b75505Sopenharmony_ci b = state[1]; 194e5b75505Sopenharmony_ci c = state[2]; 195e5b75505Sopenharmony_ci d = state[3]; 196e5b75505Sopenharmony_ci e = state[4]; 197e5b75505Sopenharmony_ci /* 4 rounds of 20 operations each. Loop unrolled. */ 198e5b75505Sopenharmony_ci R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); 199e5b75505Sopenharmony_ci R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); 200e5b75505Sopenharmony_ci R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); 201e5b75505Sopenharmony_ci R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); 202e5b75505Sopenharmony_ci R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); 203e5b75505Sopenharmony_ci R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); 204e5b75505Sopenharmony_ci R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); 205e5b75505Sopenharmony_ci R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); 206e5b75505Sopenharmony_ci R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); 207e5b75505Sopenharmony_ci R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); 208e5b75505Sopenharmony_ci R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); 209e5b75505Sopenharmony_ci R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); 210e5b75505Sopenharmony_ci R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); 211e5b75505Sopenharmony_ci R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); 212e5b75505Sopenharmony_ci R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); 213e5b75505Sopenharmony_ci R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); 214e5b75505Sopenharmony_ci R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); 215e5b75505Sopenharmony_ci R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); 216e5b75505Sopenharmony_ci R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); 217e5b75505Sopenharmony_ci R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); 218e5b75505Sopenharmony_ci /* Add the working vars back into context.state[] */ 219e5b75505Sopenharmony_ci state[0] += a; 220e5b75505Sopenharmony_ci state[1] += b; 221e5b75505Sopenharmony_ci state[2] += c; 222e5b75505Sopenharmony_ci state[3] += d; 223e5b75505Sopenharmony_ci state[4] += e; 224e5b75505Sopenharmony_ci /* Wipe variables */ 225e5b75505Sopenharmony_ci a = b = c = d = e = 0; 226e5b75505Sopenharmony_ci#ifdef SHA1HANDSOFF 227e5b75505Sopenharmony_ci forced_memzero(block, 64); 228e5b75505Sopenharmony_ci#endif 229e5b75505Sopenharmony_ci} 230e5b75505Sopenharmony_ci 231e5b75505Sopenharmony_ci 232e5b75505Sopenharmony_ci/* SHA1Init - Initialize new context */ 233e5b75505Sopenharmony_ci 234e5b75505Sopenharmony_civoid SHA1Init(SHA1_CTX* context) 235e5b75505Sopenharmony_ci{ 236e5b75505Sopenharmony_ci /* SHA1 initialization constants */ 237e5b75505Sopenharmony_ci context->state[0] = 0x67452301; 238e5b75505Sopenharmony_ci context->state[1] = 0xEFCDAB89; 239e5b75505Sopenharmony_ci context->state[2] = 0x98BADCFE; 240e5b75505Sopenharmony_ci context->state[3] = 0x10325476; 241e5b75505Sopenharmony_ci context->state[4] = 0xC3D2E1F0; 242e5b75505Sopenharmony_ci context->count[0] = context->count[1] = 0; 243e5b75505Sopenharmony_ci} 244e5b75505Sopenharmony_ci 245e5b75505Sopenharmony_ci 246e5b75505Sopenharmony_ci/* Run your data through this. */ 247e5b75505Sopenharmony_ci 248e5b75505Sopenharmony_civoid SHA1Update(SHA1_CTX* context, const void *_data, u32 len) 249e5b75505Sopenharmony_ci{ 250e5b75505Sopenharmony_ci u32 i, j; 251e5b75505Sopenharmony_ci const unsigned char *data = _data; 252e5b75505Sopenharmony_ci 253e5b75505Sopenharmony_ci#ifdef VERBOSE 254e5b75505Sopenharmony_ci SHAPrintContext(context, "before"); 255e5b75505Sopenharmony_ci#endif 256e5b75505Sopenharmony_ci j = (context->count[0] >> 3) & 63; 257e5b75505Sopenharmony_ci if ((context->count[0] += len << 3) < (len << 3)) 258e5b75505Sopenharmony_ci context->count[1]++; 259e5b75505Sopenharmony_ci context->count[1] += (len >> 29); 260e5b75505Sopenharmony_ci if ((j + len) > 63) { 261e5b75505Sopenharmony_ci os_memcpy(&context->buffer[j], data, (i = 64-j)); 262e5b75505Sopenharmony_ci SHA1Transform(context->state, context->buffer); 263e5b75505Sopenharmony_ci for ( ; i + 63 < len; i += 64) { 264e5b75505Sopenharmony_ci SHA1Transform(context->state, &data[i]); 265e5b75505Sopenharmony_ci } 266e5b75505Sopenharmony_ci j = 0; 267e5b75505Sopenharmony_ci } 268e5b75505Sopenharmony_ci else i = 0; 269e5b75505Sopenharmony_ci os_memcpy(&context->buffer[j], &data[i], len - i); 270e5b75505Sopenharmony_ci#ifdef VERBOSE 271e5b75505Sopenharmony_ci SHAPrintContext(context, "after "); 272e5b75505Sopenharmony_ci#endif 273e5b75505Sopenharmony_ci} 274e5b75505Sopenharmony_ci 275e5b75505Sopenharmony_ci 276e5b75505Sopenharmony_ci/* Add padding and return the message digest. */ 277e5b75505Sopenharmony_ci 278e5b75505Sopenharmony_civoid SHA1Final(unsigned char digest[20], SHA1_CTX* context) 279e5b75505Sopenharmony_ci{ 280e5b75505Sopenharmony_ci u32 i; 281e5b75505Sopenharmony_ci unsigned char finalcount[8]; 282e5b75505Sopenharmony_ci 283e5b75505Sopenharmony_ci for (i = 0; i < 8; i++) { 284e5b75505Sopenharmony_ci finalcount[i] = (unsigned char) 285e5b75505Sopenharmony_ci ((context->count[(i >= 4 ? 0 : 1)] >> 286e5b75505Sopenharmony_ci ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ 287e5b75505Sopenharmony_ci } 288e5b75505Sopenharmony_ci SHA1Update(context, (unsigned char *) "\200", 1); 289e5b75505Sopenharmony_ci while ((context->count[0] & 504) != 448) { 290e5b75505Sopenharmony_ci SHA1Update(context, (unsigned char *) "\0", 1); 291e5b75505Sopenharmony_ci } 292e5b75505Sopenharmony_ci SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() 293e5b75505Sopenharmony_ci */ 294e5b75505Sopenharmony_ci for (i = 0; i < 20; i++) { 295e5b75505Sopenharmony_ci digest[i] = (unsigned char) 296e5b75505Sopenharmony_ci ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 297e5b75505Sopenharmony_ci 255); 298e5b75505Sopenharmony_ci } 299e5b75505Sopenharmony_ci /* Wipe variables */ 300e5b75505Sopenharmony_ci os_memset(context->buffer, 0, 64); 301e5b75505Sopenharmony_ci os_memset(context->state, 0, 20); 302e5b75505Sopenharmony_ci os_memset(context->count, 0, 8); 303e5b75505Sopenharmony_ci forced_memzero(finalcount, sizeof(finalcount)); 304e5b75505Sopenharmony_ci} 305e5b75505Sopenharmony_ci 306e5b75505Sopenharmony_ci/* ===== end - public domain SHA1 implementation ===== */ 307