source: roaraudio/libroar/hash_sha1.c @ 5823:f9f70dbaa376

Last change on this file since 5823:f9f70dbaa376 was 5823:f9f70dbaa376, checked in by phi, 11 years ago

updated copyright

File size: 8.7 KB
Line 
1//hashh_sha1.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2012-2013
5 *      Copyright (C) Steve Reid <steve@edmweb.com>
6 *
7 *  This file is part of libroar a part of RoarAudio,
8 *  a cross-platform sound system for both, home and professional use.
9 *  See README for details.
10 *
11 *  This file is free software; you can redistribute it and/or modify
12 *  it under the terms of the GNU General Public License version 3
13 *  as published by the Free Software Foundation.
14 *
15 *  libroar is distributed in the hope that it will be useful,
16 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 *  GNU General Public License for more details.
19 *
20 *  You should have received a copy of the GNU General Public License
21 *  along with this software; see the file COPYING.  If not, write to
22 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 *  Boston, MA 02110-1301, USA.
24 *
25 *  NOTE for everyone want's to change something and send patches:
26 *  read README and HACKING! There a addition information on
27 *  the license of this document you need to read before you send
28 *  any patches.
29 *
30 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
31 *  or libpulse*:
32 *  The libs libroaresd, libroararts and libroarpulse link this lib
33 *  and are therefore GPL. Because of this it may be illigal to use
34 *  them with any software that uses libesd, libartsc or libpulse*.
35 */
36
37#include "libroar.h"
38
39#define SHA1_BLOCK_LENGTH               64
40#define SHA1_DIGEST_LENGTH              20
41#define SHA1_DIGEST_STRING_LENGTH       (SHA1_DIGEST_LENGTH * 2 + 1)
42
43union uint864uint3216 {
44 uint8_t c[64];
45 uint32_t l[16];
46};
47
48int roar_hash_sha1_proc(void * state, const void * data, size_t len);
49
50
51#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
52
53/*
54 * blk0() and blk() perform the initial expand.
55 * I got the idea of expanding during the round function from SSLeay
56 */
57#if BYTE_ORDER == LITTLE_ENDIAN
58# define blk0(i) (compblock->l[i] = (rol(compblock->l[i],24)&0xFF00FF00) \
59    |(rol(compblock->l[i],8)&0x00FF00FF))
60#else
61# define blk0(i) compblock->l[i]
62#endif
63#define blk(i) (compblock->l[i&15] = rol(compblock->l[(i+13)&15]^compblock->l[(i+8)&15] \
64    ^compblock->l[(i+2)&15]^compblock->l[i&15],1))
65
66/*
67 * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
68 */
69#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
70#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
71#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
72#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
73#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
74
75int roar_hash_sha1_init(void * state) {
76 struct roar_hash_sha1 * context = state;
77
78 if ( state == NULL ) {
79  roar_err_set(ROAR_ERROR_FAULT);
80  return -1;
81 }
82
83 memset(context, 0, sizeof(struct roar_hash_sha1));
84
85 context->state[0] = 0x67452301;
86 context->state[1] = 0xEFCDAB89;
87 context->state[2] = 0x98BADCFE;
88 context->state[3] = 0x10325476;
89 context->state[4] = 0xC3D2E1F0;
90
91 return 0;
92}
93
94int roar_hash_sha1_uninit(void * state) {
95 (void)state;
96 return 0;
97}
98
99int roar_hash_sha1_digest(void * state, void * digest, size_t * len) {
100 struct roar_hash_sha1 * context = state;
101 uint64_t count;
102 int i;
103
104 if ( state == NULL || digest == NULL || len == NULL ) {
105  roar_err_set(ROAR_ERROR_FAULT);
106  return -1;
107 }
108
109 if ( context->is_final ) {
110  roar_err_set(ROAR_ERROR_BUSY);
111  return -1;
112 }
113
114 if ( *len < SHA1_DIGEST_LENGTH ) {
115  roar_err_set(ROAR_ERROR_NOSPC);
116  return -1;
117 }
118
119 *len = SHA1_DIGEST_LENGTH;
120
121 context->count *= 8;
122 count = ROAR_HOST2NET64(context->count);
123
124 roar_hash_sha1_proc(state, "\200", 1);
125
126 // TODO: make this calc the correct length directly.
127 // this is inefficent.
128 while (context->in_buffer != (SHA1_BLOCK_LENGTH - 8)) {
129  ROAR_DBG("roar_hash_sha1_digest(state=%p, digest=%p, len=%p): context->in_buffer = %i", state, digest, len, (int)context->in_buffer);
130  roar_hash_sha1_proc(state, "\0", 1);
131 }
132
133 roar_hash_sha1_proc(state, &count, 8);
134
135
136 for (i = 0; i < SHA1_DIGEST_LENGTH; i++) {
137  ((uint8_t *)digest)[i] = (uint8_t)((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
138 }
139
140 memset(context, 0, sizeof(struct roar_hash_sha1));
141 context->is_final = 1;
142
143 return 0;
144}
145
146int roar_hash_sha1_proc_block(void * state, const void * block) {
147 struct roar_hash_sha1 * context = state;
148 uint32_t a, b, c, d, e;
149 uint8_t workspace[SHA1_BLOCK_LENGTH];
150 union uint864uint3216 * compblock = (union uint864uint3216 *)(void*)workspace;
151
152 if ( state == NULL || block == NULL ) {
153  roar_err_set(ROAR_ERROR_FAULT);
154  return -1;
155 }
156
157 if ( context->is_final ) {
158  roar_err_set(ROAR_ERROR_BUSY);
159  return -1;
160 }
161
162 if ( context->in_buffer ) {
163  return roar_hash_sha1_proc(state, block, SHA1_BLOCK_LENGTH);
164 }
165
166 memcpy(compblock, block, SHA1_BLOCK_LENGTH);
167
168 /* Copy context->state[] to working vars */
169 a = context->state[0];
170 b = context->state[1];
171 c = context->state[2];
172 d = context->state[3];
173 e = context->state[4];
174
175 /* 4 rounds of 20 operations each. Loop unrolled. */
176 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);
177 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);
178 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);
179 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);
180 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);
181 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);
182 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);
183 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);
184 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);
185 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);
186 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);
187 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);
188 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);
189 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);
190 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);
191 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);
192 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);
193 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);
194 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);
195 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);
196
197 /* Add the working vars back into context.state[] */
198 context->state[0] += a;
199 context->state[1] += b;
200 context->state[2] += c;
201 context->state[3] += d;
202 context->state[4] += e;
203
204 /* Wipe variables */
205 a = b = c = d = e = 0;
206
207 return 0;
208}
209
210int roar_hash_sha1_proc(void * state, const void * data, size_t len) {
211 struct roar_hash_sha1 * context = state;
212 size_t buflen;
213
214 ROAR_DBG("roar_hash_sha1_proc(state=%p, data=%p, len=%llu) = ?", state, data, (long long unsigned int)len);
215
216 if ( state == NULL || data == NULL ) {
217  roar_err_set(ROAR_ERROR_FAULT);
218  return -1;
219 }
220
221 if ( context->is_final ) {
222  roar_err_set(ROAR_ERROR_BUSY);
223  return -1;
224 }
225
226 ROAR_DBG("roar_hash_sha1_proc(state=%p, data=%p, len=%llu) = ?", state, data, (long long unsigned int)len);
227
228 context->count += len;
229
230 if ( context->in_buffer ) {
231  ROAR_DBG("roar_hash_sha1_proc(state=%p, data=%p, len=%llu) = ?", state, data, (long long unsigned int)len);
232  buflen = len > (SHA1_BLOCK_LENGTH - context->in_buffer) ? SHA1_BLOCK_LENGTH - context->in_buffer : len;
233  memcpy(context->buffer + context->in_buffer, data, buflen);
234  context->in_buffer += buflen;
235  if ( context->in_buffer == SHA1_BLOCK_LENGTH ) {
236   ROAR_DBG("roar_hash_sha1_proc(state=%p, data=%p, len=%llu) = ?", state, data, (long long unsigned int)len);
237   context->in_buffer = 0;
238   roar_hash_sha1_proc_block(state, context->buffer);
239  } else {
240   ROAR_DBG("roar_hash_sha1_proc(state=%p, data=%p, len=%llu) = 0", state, data, (long long unsigned int)len);
241   return 0;
242  }
243
244  len  -= buflen;
245  data += buflen;
246 }
247
248 ROAR_DBG("roar_hash_sha1_proc(state=%p, data=%p, len=%llu) = ?", state, data, (long long unsigned int)len);
249
250 while (len >= SHA1_BLOCK_LENGTH) {
251  ROAR_DBG("roar_hash_sha1_proc(state=%p, data=%p, len=%llu) = ?", state, data, (long long unsigned int)len);
252  roar_hash_sha1_proc_block(state, data);
253  len  -= SHA1_BLOCK_LENGTH;
254  data += SHA1_BLOCK_LENGTH;
255 }
256
257 ROAR_DBG("roar_hash_sha1_proc(state=%p, data=%p, len=%llu) = ?", state, data, (long long unsigned int)len);
258
259 if ( len ) {
260  memcpy(context->buffer, data, len);
261  context->in_buffer = len;
262 }
263
264 ROAR_DBG("roar_hash_sha1_proc(state=%p, data=%p, len=%llu) = 0", state, data, (long long unsigned int)len);
265 return 0;
266}
267
268//ll
Note: See TracBrowser for help on using the repository browser.