source: trunk/libtransmission/sha1.c @ 2557

Last change on this file since 2557 was 2557, checked in by charles, 15 years ago

(libT) not all libT source files need to #include sha1/openssl, just three of them. Also, no need to compile a local sha1 implementation if we're using openssl's.

  • Property svn:keywords set to Date Rev Author Id
File size: 7.1 KB
Line 
1/*
2 sha1.c: Implementation of SHA-1 Secure Hash Algorithm-1
3
4 Based upon: NIST FIPS180-1 Secure Hash Algorithm-1
5   http://www.itl.nist.gov/fipspubs/fip180-1.htm
6
7 Non-official Japanese Translation by HIRATA Yasuyuki:
8   http://yasu.asuka.net/translations/SHA-1.html
9
10 Copyright (C) 2002 vi@nwr.jp. All rights reserved.
11
12 This software is provided 'as-is', without any express or implied
13 warranty. In no event will the authors be held liable for any damages
14 arising from the use of this software.
15
16 Permission is granted to anyone to use this software for any purpose,
17 including commercial applications, and to alter it and redistribute it
18 freely, subject to the following restrictions:
19
20 1. The origin of this software must not be misrepresented; you must not
21    claim that you wrote the original software. If you use this software
22    in a product, an acknowledgement in the product documentation would be
23    appreciated but is not required.
24 2. Altered source versions must be plainly marked as such, and must not be
25    misrepresented as beging the original software.
26 3. This notice may not be removed or altered from any source distribution.
27
28 Note:
29   The copyright notice above is copied from md5.h by L. Peter Deutsch
30   <ghost@aladdin.com>. Thank him since I'm not a good speaker of English. :)
31 */
32
33#include <string.h>
34#include "sha1.h"
35
36#if !defined(HAVE_OPENSSL) && !defined(HAVE_LIBSSL)
37
38#define BITS 8
39#define INLINE  inline
40
41struct sha1_state_s
42{
43  sha1_byte_t   sha1_buf[64];   /* 512 bits */
44  int           sha1_count;     /* How many bytes are used */
45  sha1_word_t   sha1_size1;             /* Length counter Lower Word */
46  sha1_word_t   sha1_size2;             /* Length counter Upper Word */
47  sha1_word_t   sha1_h[5];              /* Hash output */
48};
49
50/*
51 * Packing bytes to a word
52 *
53 * Should not assume p is aligned to word boundary
54 */
55static INLINE sha1_word_t packup(sha1_byte_t *p)
56{
57  /* Portable, but slow */
58  return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3] << 0;
59}
60
61/*
62 * Unpacking a word to bytes
63 *
64 * Should not assume p is aligned to word boundary
65 */
66static void unpackup(sha1_byte_t *p, sha1_word_t q)
67{
68  p[0] = (q >> 24) & 0xff;
69  p[1] = (q >> 16) & 0xff;
70  p[2] = (q >>  8) & 0xff;
71  p[3] = (q >>  0) & 0xff;
72}
73
74/*
75 * Processing a block
76 */
77static inline void sha1_update_now(sha1_state_t *pms, sha1_byte_t *bp)
78{
79  sha1_word_t   tmp, a, b, c, d, e, w[16+16];
80  int   i, s;
81
82  /* pack 64 bytes into 16 words */
83  for(i = 0; i < 16; i++) {
84    w[i] = packup(bp + i * sizeof(sha1_word_t));
85  }
86  memcpy(w + 16, w + 0, sizeof(sha1_word_t) * 16);
87
88  a = pms->sha1_h[0], b = pms->sha1_h[1], c = pms->sha1_h[2], d = pms->sha1_h[3], e = pms->sha1_h[4];
89
90#define rot(x,n) (((x) << n) | ((x) >> (32-n)))
91#define f0(b, c, d)     ((b&c)|(~b&d))
92#define f1(b, c, d)     (b^c^d)
93#define f2(b, c, d)     ((b&c)|(b&d)|(c&d))
94#define f3(b, c, d)     (b^c^d)
95#define k0              0x5a827999
96#define k1              0x6ed9eba1
97#define k2              0x8f1bbcdc
98#define k3              0xca62c1d6
99
100  /* t=0-15 */
101  s = 0;
102  for(i = 0; i < 16; i++) {
103    tmp = rot(a, 5) + f0(b, c, d) + e + w[s] + k0;
104    e = d; d = c; c = rot(b, 30); b = a; a = tmp;
105    s = (s + 1) % 16;
106  }
107
108  /* t=16-19 */
109  for(i = 16; i < 20; i++) {
110    w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
111    w[s+16] = w[s];
112    tmp = rot(a, 5) + f0(b, c, d) + e + w[s] + k0;
113    e = d; d = c; c = rot(b, 30); b = a; a = tmp;
114    s = (s + 1) % 16;
115  }
116
117  /* t=20-39 */
118  for(i = 0; i < 20; i++) {
119    w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
120    w[s+16] = w[s];
121    tmp = rot(a, 5) + f1(b, c, d) + e + w[s] + k1;
122    e = d; d = c; c = rot(b, 30); b = a; a = tmp;
123    s = (s + 1) % 16;
124  }
125
126  /* t=40-59 */
127  for(i = 0; i < 20; i++) {
128    w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
129    w[s+16] = w[s];
130    tmp = rot(a, 5) + f2(b, c, d) + e + w[s] + k2;
131    e = d; d = c; c = rot(b, 30); b = a; a = tmp;
132    s = (s + 1) % 16;
133  }
134
135  /* t=60-79 */
136  for(i = 0; i < 20; i++) {
137    w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
138    w[s+16] = w[s];
139    tmp = rot(a, 5) + f3(b, c, d) + e + w[s] + k3;
140    e = d; d = c; c = rot(b, 30); b = a; a = tmp;
141    s = (s + 1) % 16;
142  }
143
144  pms->sha1_h[0] += a, pms->sha1_h[1] += b, pms->sha1_h[2] += c, pms->sha1_h[3] += d, pms->sha1_h[4] += e;
145}
146
147/*
148 * Increment sha1_size1, sha1_size2 field of sha1_state_t
149 */
150static INLINE void incr(sha1_state_t *pms, int v)
151{
152  sha1_word_t   q;
153
154  q = pms->sha1_size1 + v * BITS;
155  if(q < pms->sha1_size1) {
156    pms->sha1_size2++;
157  }
158  pms->sha1_size1 = q;
159}
160
161/*
162 * Initialize sha1_state_t as FIPS specifies
163 */
164void    sha1_init(sha1_state_t *pms)
165{
166  memset(pms, 0, sizeof(*pms));
167  pms->sha1_h[0] = 0x67452301;  /* Initialize H[0]-H[4] */
168  pms->sha1_h[1] = 0xEFCDAB89;
169  pms->sha1_h[2] = 0x98BADCFE;
170  pms->sha1_h[3] = 0x10325476;
171  pms->sha1_h[4] = 0xC3D2E1F0;
172}
173
174/*
175 * Fill block and update output when needed
176 */
177void    sha1_update(sha1_state_t *pms, sha1_byte_t *bufp, int length)
178{
179  /* Is the buffer partially filled? */
180  if(pms->sha1_count != 0) {
181    if(pms->sha1_count + length >= (signed) sizeof(pms->sha1_buf)) {    /* buffer is filled enough */
182      int fil = sizeof(pms->sha1_buf) - pms->sha1_count;                /* length to copy */
183
184      memcpy(pms->sha1_buf + pms->sha1_count, bufp, fil);
185      sha1_update_now(pms, pms->sha1_buf);
186      length -= fil;
187      bufp += fil;
188      pms->sha1_count = 0;
189      incr(pms, fil);
190    } else {
191      memcpy(pms->sha1_buf + pms->sha1_count, bufp, length);
192      pms->sha1_count += length;
193      incr(pms, length);
194      return;
195    }
196  }
197
198  /* Loop to update state */
199  for(;;) {
200    if(length < (signed) sizeof(pms->sha1_buf)) {               /* Short to fill up the buffer */
201      if(length) {
202        memcpy(pms->sha1_buf, bufp, length);
203      }
204      pms->sha1_count = length;
205      incr(pms, length);
206      break;
207    }
208    sha1_update_now(pms, bufp);
209    length -= sizeof(pms->sha1_buf);
210    bufp += sizeof(pms->sha1_buf);
211    incr(pms, sizeof(pms->sha1_buf));
212  }
213}
214
215void    sha1_finish(sha1_state_t *pms, sha1_byte_t output[SHA1_OUTPUT_SIZE])
216{
217  int i;
218  sha1_byte_t buf[1];
219
220  /* fill a bit */
221  buf[0] = 0x80;
222  sha1_update(pms, buf, 1);
223
224  /* Decrement sha1_size1, sha1_size2 */
225  if((pms->sha1_size1 -= BITS) == 0) {
226    pms->sha1_size2--;
227  }
228
229  /* fill zeros */
230  if(pms->sha1_count > (signed) (sizeof(pms->sha1_buf) - 2 * sizeof(sha1_word_t))) {
231    memset(pms->sha1_buf + pms->sha1_count, 0, sizeof(pms->sha1_buf) - pms->sha1_count);
232    sha1_update_now(pms, pms->sha1_buf);
233    pms->sha1_count = 0;
234  }
235  memset(pms->sha1_buf + pms->sha1_count, 0,
236    sizeof(pms->sha1_buf) - pms->sha1_count - sizeof(sha1_word_t) * 2);
237
238  /* fill last length */
239  unpackup(pms->sha1_buf + sizeof(pms->sha1_buf) - sizeof(sha1_word_t) * 2, pms->sha1_size2);
240  unpackup(pms->sha1_buf + sizeof(pms->sha1_buf) - sizeof(sha1_word_t) * 1, pms->sha1_size1);
241
242  /* final update */
243  sha1_update_now(pms, pms->sha1_buf);
244
245  /* move hash value to output byte array */
246  for(i = 0; i < (signed) (sizeof(pms->sha1_h)/sizeof(sha1_word_t)); i++) {
247    unpackup(output + i * sizeof(sha1_word_t), pms->sha1_h[i]);
248  }
249}
250
251void
252tr_sha1( const void * input_buffer, int length, unsigned char * output)
253{
254    sha1_state_t pms;
255    sha1_init( &pms );
256    sha1_update( &pms, (sha1_byte_t *) input_buffer, length );
257    sha1_finish( &pms, (sha1_byte_t *) output );
258}
259
260#endif
Note: See TracBrowser for help on using the repository browser.