source: trunk/libtransmission/sha1.c @ 346

Last change on this file since 346 was 261, checked in by titer, 15 years ago

Updated svn:keywords

  • Property svn:keywords set to Date Rev Author Id
File size: 6.5 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#include <string.h>
33#include "sha1.h"
34
35#define INLINE  inline
36/*
37 * Packing bytes to a word
38 *
39 * Should not assume p is aligned to word boundary
40 */
41static INLINE sha1_word_t packup(sha1_byte_t *p)
42{
43  /* Portable, but slow */
44  return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3] << 0;
45}
46
47/*
48 * Unpacking a word to bytes
49 *
50 * Should not assume p is aligned to word boundary
51 */
52static void unpackup(sha1_byte_t *p, sha1_word_t q)
53{
54  p[0] = (q >> 24) & 0xff;
55  p[1] = (q >> 16) & 0xff;
56  p[2] = (q >>  8) & 0xff;
57  p[3] = (q >>  0) & 0xff;
58}
59
60/*
61 * Processing a block
62 */
63static inline void sha1_update_now(sha1_state_s *pms, sha1_byte_t *bp)
64{
65  sha1_word_t   tmp, a, b, c, d, e, w[16+16];
66  int   i, s;
67
68  /* pack 64 bytes into 16 words */
69  for(i = 0; i < 16; i++) {
70    w[i] = packup(bp + i * sizeof(sha1_word_t));
71  }
72  memcpy(w + 16, w + 0, sizeof(sha1_word_t) * 16);
73
74  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];
75
76#define rot(x,n) (((x) << n) | ((x) >> (32-n)))
77#define f0(b, c, d)     ((b&c)|(~b&d))
78#define f1(b, c, d)     (b^c^d)
79#define f2(b, c, d)     ((b&c)|(b&d)|(c&d))
80#define f3(b, c, d)     (b^c^d)
81#define k0              0x5a827999
82#define k1              0x6ed9eba1
83#define k2              0x8f1bbcdc
84#define k3              0xca62c1d6
85
86  /* t=0-15 */
87  s = 0;
88  for(i = 0; i < 16; i++) {
89    tmp = rot(a, 5) + f0(b, c, d) + e + w[s] + k0;
90    e = d; d = c; c = rot(b, 30); b = a; a = tmp;
91    s = (s + 1) % 16;
92  }
93
94  /* t=16-19 */
95  for(i = 16; i < 20; i++) {
96    w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
97    w[s+16] = w[s];
98    tmp = rot(a, 5) + f0(b, c, d) + e + w[s] + k0;
99    e = d; d = c; c = rot(b, 30); b = a; a = tmp;
100    s = (s + 1) % 16;
101  }
102
103  /* t=20-39 */
104  for(i = 0; i < 20; i++) {
105    w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
106    w[s+16] = w[s];
107    tmp = rot(a, 5) + f1(b, c, d) + e + w[s] + k1;
108    e = d; d = c; c = rot(b, 30); b = a; a = tmp;
109    s = (s + 1) % 16;
110  }
111
112  /* t=40-59 */
113  for(i = 0; i < 20; i++) {
114    w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
115    w[s+16] = w[s];
116    tmp = rot(a, 5) + f2(b, c, d) + e + w[s] + k2;
117    e = d; d = c; c = rot(b, 30); b = a; a = tmp;
118    s = (s + 1) % 16;
119  }
120
121  /* t=60-79 */
122  for(i = 0; i < 20; i++) {
123    w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
124    w[s+16] = w[s];
125    tmp = rot(a, 5) + f3(b, c, d) + e + w[s] + k3;
126    e = d; d = c; c = rot(b, 30); b = a; a = tmp;
127    s = (s + 1) % 16;
128  }
129
130  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;
131}
132
133/*
134 * Increment sha1_size1, sha1_size2 field of sha1_state_s
135 */
136static INLINE void incr(sha1_state_s *pms, int v)
137{
138  sha1_word_t   q;
139
140  q = pms->sha1_size1 + v * BITS;
141  if(q < pms->sha1_size1) {
142    pms->sha1_size2++;
143  }
144  pms->sha1_size1 = q;
145}
146
147/*
148 * Initialize sha1_state_s as FIPS specifies
149 */
150void    sha1_init(sha1_state_s *pms)
151{
152  memset(pms, 0, sizeof(*pms));
153  pms->sha1_h[0] = 0x67452301;  /* Initialize H[0]-H[4] */
154  pms->sha1_h[1] = 0xEFCDAB89;
155  pms->sha1_h[2] = 0x98BADCFE;
156  pms->sha1_h[3] = 0x10325476;
157  pms->sha1_h[4] = 0xC3D2E1F0;
158}
159
160/*
161 * Fill block and update output when needed
162 */
163void    sha1_update(sha1_state_s *pms, sha1_byte_t *bufp, int length)
164{
165  /* Is the buffer partially filled? */
166  if(pms->sha1_count != 0) {
167    if(pms->sha1_count + length >= (signed) sizeof(pms->sha1_buf)) {    /* buffer is filled enough */
168      int fil = sizeof(pms->sha1_buf) - pms->sha1_count;                /* length to copy */
169
170      memcpy(pms->sha1_buf + pms->sha1_count, bufp, fil);
171      sha1_update_now(pms, pms->sha1_buf);
172      length -= fil;
173      bufp += fil;
174      pms->sha1_count = 0;
175      incr(pms, fil);
176    } else {
177      memcpy(pms->sha1_buf + pms->sha1_count, bufp, length);
178      pms->sha1_count += length;
179      incr(pms, length);
180      return;
181    }
182  }
183
184  /* Loop to update state */
185  for(;;) {
186    if(length < (signed) sizeof(pms->sha1_buf)) {               /* Short to fill up the buffer */
187      if(length) {
188        memcpy(pms->sha1_buf, bufp, length);
189      }
190      pms->sha1_count = length;
191      incr(pms, length);
192      break;
193    }
194    sha1_update_now(pms, bufp);
195    length -= sizeof(pms->sha1_buf);
196    bufp += sizeof(pms->sha1_buf);
197    incr(pms, sizeof(pms->sha1_buf));
198  }
199}
200
201void    sha1_finish(sha1_state_s *pms, sha1_byte_t output[SHA1_OUTPUT_SIZE])
202{
203  int i;
204  sha1_byte_t buf[1];
205
206  /* fill a bit */
207  buf[0] = 0x80;
208  sha1_update(pms, buf, 1);
209
210  /* Decrement sha1_size1, sha1_size2 */
211  if((pms->sha1_size1 -= BITS) == 0) {
212    pms->sha1_size2--;
213  }
214
215  /* fill zeros */
216  if(pms->sha1_count > (signed) (sizeof(pms->sha1_buf) - 2 * sizeof(sha1_word_t))) {
217    memset(pms->sha1_buf + pms->sha1_count, 0, sizeof(pms->sha1_buf) - pms->sha1_count);
218    sha1_update_now(pms, pms->sha1_buf);
219    pms->sha1_count = 0;
220  }
221  memset(pms->sha1_buf + pms->sha1_count, 0,
222    sizeof(pms->sha1_buf) - pms->sha1_count - sizeof(sha1_word_t) * 2);
223
224  /* fill last length */
225  unpackup(pms->sha1_buf + sizeof(pms->sha1_buf) - sizeof(sha1_word_t) * 2, pms->sha1_size2);
226  unpackup(pms->sha1_buf + sizeof(pms->sha1_buf) - sizeof(sha1_word_t) * 1, pms->sha1_size1);
227
228  /* final update */
229  sha1_update_now(pms, pms->sha1_buf);
230
231  /* move hash value to output byte array */
232  for(i = 0; i < (signed) (sizeof(pms->sha1_h)/sizeof(sha1_word_t)); i++) {
233    unpackup(output + i * sizeof(sha1_word_t), pms->sha1_h[i]);
234  }
235}
Note: See TracBrowser for help on using the repository browser.