// Support for Calculation of SHA1 in SW // // Copyright (C) 2006-2011 IBM Corporation // // Authors: // Stefan Berger // // This file may be distributed under the terms of the GNU LGPLv3 license. // // See: http://www.itl.nist.gov/fipspubs/fip180-1.htm // RFC3174, Wikipedia's SHA1 alogrithm description // #include "config.h" #include "byteorder.h" // cpu_to_*, __swab64 #include "sha.h" // sha1 #include "string.h" // memcpy #include "x86.h" // rol typedef struct _sha1_ctx { u32 h[5]; } sha1_ctx; static void sha1_block(u32 *w, sha1_ctx *ctx) { u32 i; u32 a,b,c,d,e,f; u32 tmp; u32 idx; static const u32 sha_ko[4] = { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 }; /* change endianness of given data */ for (i = 0; i < 16; i++) w[i] = be32_to_cpu(w[i]); for (i = 16; i <= 79; i++) { tmp = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]; w[i] = rol(tmp,1); } a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3]; e = ctx->h[4]; for (i = 0; i <= 79; i++) { if (i <= 19) { f = (b & c) | ((b ^ 0xffffffff) & d); idx = 0; } else if (i <= 39) { f = b ^ c ^ d; idx = 1; } else if (i <= 59) { f = (b & c) | (b & d) | (c & d); idx = 2; } else { f = b ^ c ^ d; idx = 3; } tmp = rol(a, 5) + f + e + sha_ko[idx] + w[i]; e = d; d = c; c = rol(b, 30); b = a; a = tmp; } ctx->h[0] += a; ctx->h[1] += b; ctx->h[2] += c; ctx->h[3] += d; ctx->h[4] += e; } static void sha1_do(sha1_ctx *ctx, const u8 *data32, u32 length) { u32 offset; u16 num; u32 bits = 0; u32 w[80]; u64 tmp; /* treat data in 64-byte chunks */ for (offset = 0; length - offset >= 64; offset += 64) { memcpy(w, data32 + offset, 64); sha1_block((u32 *)w, ctx); bits += (64 * 8); } /* last block with less than 64 bytes */ num = length - offset; bits += (num << 3); memcpy(w, data32 + offset, num); ((u8 *)w)[num] = 0x80; if (64 - (num + 1) > 0) memset( &((u8 *)w)[num + 1], 0x0, 64 - (num + 1)); if (num >= 56) { /* cannot append number of bits here */ sha1_block((u32 *)w, ctx); memset(w, 0x0, 60); } /* write number of bits to end of block */ tmp = __swab64(bits); memcpy(&w[14], &tmp, 8); sha1_block(w, ctx); /* need to switch result's endianness */ for (num = 0; num < 5; num++) ctx->h[num] = cpu_to_be32(ctx->h[num]); } void sha1(const u8 *data, u32 length, u8 *hash) { if (!CONFIG_TCGBIOS) return; sha1_ctx ctx = { .h[0] = 0x67452301, .h[1] = 0xefcdab89, .h[2] = 0x98badcfe, .h[3] = 0x10325476, .h[4] = 0xc3d2e1f0, }; sha1_do(&ctx, data, length); memcpy(hash, &ctx.h[0], 20); return; }