1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
// Support for Calculation of SHA1 in SW
//
// Copyright (C) 2006-2011 IBM Corporation
//
// Authors:
// Stefan Berger <stefanb@linux.vnet.ibm.com>
//
// 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;
}
|