master xplshn/aruu / shared / libutil / sha1.c
  1/* public domain sha1 implementation based on rfc3174 and libtomcrypt */
  2#include <stdint.h>
  3#include <string.h>
  4
  5#include "../sha1.h"
  6
  7static uint32_t
  8rol(uint32_t n, int k)
  9{
 10  return (n << k) | (n >> (32 - k));
 11}
 12#define F0(b, c, d) (d ^ (b & (c ^ d)))
 13#define F1(b, c, d) (b ^ c ^ d)
 14#define F2(b, c, d) ((b & c) | (d & (b | c)))
 15#define F3(b, c, d) (b ^ c ^ d)
 16#define G0(a, b, c, d, e, i)                                                                       \
 17  e += rol(a, 5) + F0(b, c, d) + W[i] + 0x5A827999;                                                \
 18  b = rol(b, 30)
 19#define G1(a, b, c, d, e, i)                                                                       \
 20  e += rol(a, 5) + F1(b, c, d) + W[i] + 0x6ED9EBA1;                                                \
 21  b = rol(b, 30)
 22#define G2(a, b, c, d, e, i)                                                                       \
 23  e += rol(a, 5) + F2(b, c, d) + W[i] + 0x8F1BBCDC;                                                \
 24  b = rol(b, 30)
 25#define G3(a, b, c, d, e, i)                                                                       \
 26  e += rol(a, 5) + F3(b, c, d) + W[i] + 0xCA62C1D6;                                                \
 27  b = rol(b, 30)
 28
 29static void
 30processblock(struct sha1 *s, const uint8_t *buf)
 31{
 32  uint32_t W[80], a, b, c, d, e;
 33  int      i;
 34
 35  for (i = 0; i < 16; i++) {
 36    W[i] = (uint32_t)buf[4 * i] << 24;
 37    W[i] |= (uint32_t)buf[4 * i + 1] << 16;
 38    W[i] |= (uint32_t)buf[4 * i + 2] << 8;
 39    W[i] |= buf[4 * i + 3];
 40  }
 41  for (; i < 80; i++)
 42    W[i] = rol(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
 43  a = s->h[0];
 44  b = s->h[1];
 45  c = s->h[2];
 46  d = s->h[3];
 47  e = s->h[4];
 48  for (i = 0; i < 20;) {
 49    G0(a, b, c, d, e, i++);
 50    G0(e, a, b, c, d, i++);
 51    G0(d, e, a, b, c, i++);
 52    G0(c, d, e, a, b, i++);
 53    G0(b, c, d, e, a, i++);
 54  }
 55  while (i < 40) {
 56    G1(a, b, c, d, e, i++);
 57    G1(e, a, b, c, d, i++);
 58    G1(d, e, a, b, c, i++);
 59    G1(c, d, e, a, b, i++);
 60    G1(b, c, d, e, a, i++);
 61  }
 62  while (i < 60) {
 63    G2(a, b, c, d, e, i++);
 64    G2(e, a, b, c, d, i++);
 65    G2(d, e, a, b, c, i++);
 66    G2(c, d, e, a, b, i++);
 67    G2(b, c, d, e, a, i++);
 68  }
 69  while (i < 80) {
 70    G3(a, b, c, d, e, i++);
 71    G3(e, a, b, c, d, i++);
 72    G3(d, e, a, b, c, i++);
 73    G3(c, d, e, a, b, i++);
 74    G3(b, c, d, e, a, i++);
 75  }
 76  s->h[0] += a;
 77  s->h[1] += b;
 78  s->h[2] += c;
 79  s->h[3] += d;
 80  s->h[4] += e;
 81}
 82
 83static void
 84pad(struct sha1 *s)
 85{
 86  unsigned r = s->len % 64;
 87
 88  s->buf[r++] = 0x80;
 89  if (r > 56) {
 90    memset(s->buf + r, 0, 64 - r);
 91    r = 0;
 92    processblock(s, s->buf);
 93  }
 94  memset(s->buf + r, 0, 56 - r);
 95  s->len *= 8;
 96  s->buf[56] = s->len >> 56;
 97  s->buf[57] = s->len >> 48;
 98  s->buf[58] = s->len >> 40;
 99  s->buf[59] = s->len >> 32;
100  s->buf[60] = s->len >> 24;
101  s->buf[61] = s->len >> 16;
102  s->buf[62] = s->len >> 8;
103  s->buf[63] = s->len;
104  processblock(s, s->buf);
105}
106
107void
108sha1_init(void *ctx)
109{
110  struct sha1 *s = ctx;
111
112  s->len  = 0;
113  s->h[0] = 0x67452301;
114  s->h[1] = 0xEFCDAB89;
115  s->h[2] = 0x98BADCFE;
116  s->h[3] = 0x10325476;
117  s->h[4] = 0xC3D2E1F0;
118}
119
120void
121sha1_sum(void *ctx, uint8_t md[SHA1_DIGEST_LENGTH])
122{
123  struct sha1 *s = ctx;
124  int          i;
125
126  pad(s);
127  for (i = 0; i < 5; i++) {
128    md[4 * i]     = s->h[i] >> 24;
129    md[4 * i + 1] = s->h[i] >> 16;
130    md[4 * i + 2] = s->h[i] >> 8;
131    md[4 * i + 3] = s->h[i];
132  }
133}
134
135void
136sha1_update(void *ctx, const void *m, unsigned long len)
137{
138  struct sha1   *s = ctx;
139  const uint8_t *p = m;
140  unsigned       r = s->len % 64;
141
142  s->len += len;
143  if (r) {
144    if (len < 64 - r) {
145      memcpy(s->buf + r, p, len);
146      return;
147    }
148    memcpy(s->buf + r, p, 64 - r);
149    len -= 64 - r;
150    p += 64 - r;
151    processblock(s, s->buf);
152  }
153  for (; len >= 64; len -= 64, p += 64)
154    processblock(s, p);
155  memcpy(s->buf, p, len);
156}