1 /* Software-based Trusted Platform Module (TPM) Emulator
2  * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>
3  *
4  * This module is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published
6  * by the Free Software Foundation; either version 2 of the License,
7  * or (at your option) any later version.
8  *
9  * This module is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * $Id: sha1.c 364 2010-02-11 10:24:45Z mast $
15  */
16 
17 #include "sha1.h"
18 #include <string.h>
19 
20 /* This code is based on Steve Reid's <steve@edmweb.com>
21    public domain implementation. */
22 
23 #define rol(v,b) (((v) << (b)) | ((v) >> (32 - (b))))
24 #ifdef __BIG_ENDIAN__
25 #define B0(i) (buf[i] = buf[i])
26 #else
27 #define B0(i) (buf[i] = (((buf[i] & 0xff000000) >> 24) \
28                        | ((buf[i] & 0x00ff0000) >> 8) \
29                        | ((buf[i] & 0x0000ff00) << 8) \
30                        | ((buf[i] & 0x000000ff) << 24)))
31 
32 #endif
33 #define B1(i) (buf[i & 15] = rol(buf[i & 15] ^ buf[(i-14) & 15] \
34                                  ^ buf[(i-8) & 15] ^ buf[(i-3) & 15], 1))
35 #define F0(x,y,z) ((x & (y ^ z)) ^ z)
36 #define F1(x,y,z) (x ^ y ^ z)
37 #define F2(x,y,z) (((x | y) & z) | (x & y))
38 #define R0(a,b,c,d,e,i) e += F0(b,c,d) + B0(i) + 0x5A827999 + rol(a,5); b = rol(b,30);
39 #define R1(a,b,c,d,e,i) e += F0(b,c,d) + B1(i) + 0x5A827999 + rol(a,5); b = rol(b,30);
40 #define R2(a,b,c,d,e,i) e += F1(b,c,d) + B1(i) + 0x6ED9EBA1 + rol(a,5); b = rol(b,30);
41 #define R3(a,b,c,d,e,i) e += F2(b,c,d) + B1(i) + 0x8F1BBCDC + rol(a,5); b = rol(b,30);
42 #define R4(a,b,c,d,e,i) e += F1(b,c,d) + B1(i) + 0xCA62C1D6 + rol(a,5); b = rol(b,30);
43 
tpm_sha1_transform(uint32_t h[5],const uint8_t data[64])44 static void tpm_sha1_transform(uint32_t h[5], const uint8_t data[64])
45 {
46   uint32_t a, b, c, d, e;
47   uint32_t buf[16];
48 
49   /* copy state and data*/
50   a = h[0];
51   b = h[1];
52   c = h[2];
53   d = h[3];
54   e = h[4];
55   memcpy(buf, data, 64);
56   /* unrolled sha-1 rounds */
57   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);
58   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);
59   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);
60   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);
61   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);
62   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);
63   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);
64   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);
65   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);
66   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);
67   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);
68   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);
69   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);
70   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);
71   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);
72   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);
73   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);
74   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);
75   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);
76   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);
77   /* update state */
78   h[0] += a;
79   h[1] += b;
80   h[2] += c;
81   h[3] += d;
82   h[4] += e;
83   /* overwrite all used variables */
84   a = b = c = d = e = 0;
85   memset(buf, 0, 64);
86 }
87 
88 
tpm_sha1_init(tpm_sha1_ctx_t * ctx)89 void tpm_sha1_init(tpm_sha1_ctx_t *ctx)
90 {
91   /* initialise with sha-1 constants */
92   ctx->h[0] = 0x67452301;
93   ctx->h[1] = 0xEFCDAB89;
94   ctx->h[2] = 0x98BADCFE;
95   ctx->h[3] = 0x10325476;
96   ctx->h[4] = 0xC3D2E1F0;
97   ctx->count_lo = ctx->count_hi = 0;
98 }
99 
tpm_sha1_update(tpm_sha1_ctx_t * ctx,const uint8_t * data,size_t length)100 void tpm_sha1_update(tpm_sha1_ctx_t *ctx, const uint8_t *data, size_t length)
101 {
102   size_t buf_off = (ctx->count_lo >> 3) & 63;
103   size_t data_off = 0;
104 
105   /* add data */
106   if (length + buf_off >= 64) {
107     data_off = 64 - buf_off;
108     memcpy(&ctx->buf[buf_off], data, data_off);
109     tpm_sha1_transform(ctx->h, ctx->buf);
110     while (data_off + 64 <= length) {
111       tpm_sha1_transform(ctx->h, &data[data_off]);
112       data_off += 64;
113     }
114     buf_off = 0;
115   }
116   memcpy(&ctx->buf[buf_off], &data[data_off], length - data_off);
117   /* update counter */
118   buf_off = ctx->count_lo;
119   ctx->count_lo += length << 3;
120   if (ctx->count_lo < buf_off) ctx->count_hi++;
121   ctx->count_hi += length >> 29;
122 }
123 
tpm_sha1_update_be32(tpm_sha1_ctx_t * ctx,uint32_t data)124 void tpm_sha1_update_be32(tpm_sha1_ctx_t *ctx, uint32_t data)
125 {
126   uint8_t buf[4];
127 
128   buf[0] = (data >> 24) & 0xff;
129   buf[1] = (data >> 16) & 0xff;
130   buf[2] = (data >>  8) & 0xff;
131   buf[3] = (data >>  0) & 0xff;
132   tpm_sha1_update(ctx, buf, 4);
133 }
134 
tpm_sha1_final(tpm_sha1_ctx_t * ctx,uint8_t digest[SHA1_DIGEST_LENGTH])135 void tpm_sha1_final(tpm_sha1_ctx_t *ctx, uint8_t digest[SHA1_DIGEST_LENGTH])
136 {
137   uint8_t d, counter[8];
138 
139   /* setup counter */
140   for (d = 0; d < 4; d++) {
141     counter[d    ] = (ctx->count_hi >> (24 - d * 8)) & 0xff;
142     counter[d + 4] = (ctx->count_lo >> (24 - d * 8)) & 0xff;
143   }
144   /* add padding */
145   d = 0x80;
146   tpm_sha1_update(ctx, &d, 1);
147   d = 0x00;
148   while ((ctx->count_lo & (63 * 8)) != (56 * 8)) tpm_sha1_update(ctx, &d, 1);
149   /* add counter */
150   tpm_sha1_update(ctx, counter, 8);
151   for (d = 0; d < SHA1_DIGEST_LENGTH; d++)
152     digest[d] = (uint8_t)(ctx->h[d >> 2] >> (8 * (3 - (d & 3))) & 0xff);
153   /* overwrite all used variables */
154   memset(ctx, 0, sizeof(*ctx));
155   memset(counter, 0, sizeof(counter));
156 }
157