Logo Search packages:      
Sourcecode: transmission version File versions  Download package

sha1.c

/*
 sha1.c: Implementation of SHA-1 Secure Hash Algorithm-1

 Based upon: NIST FIPS180-1 Secure Hash Algorithm-1
   http://www.itl.nist.gov/fipspubs/fip180-1.htm

 Non-official Japanese Translation by HIRATA Yasuyuki:
   http://yasu.asuka.net/translations/SHA-1.html

 Copyright (C) 2002 vi@nwr.jp. All rights reserved.

 This software is provided 'as-is', without any express or implied
 warranty. In no event will the authors be held liable for any damages
 arising from the use of this software.

 Permission is granted to anyone to use this software for any purpose,
 including commercial applications, and to alter it and redistribute it
 freely, subject to the following restrictions:

 1. The origin of this software must not be misrepresented; you must not
    claim that you wrote the original software. If you use this software
    in a product, an acknowledgement in the product documentation would be
    appreciated but is not required.
 2. Altered source versions must be plainly marked as such, and must not be
    misrepresented as beging the original software.
 3. This notice may not be removed or altered from any source distribution.

 Note:
   The copyright notice above is copied from md5.h by L. Peter Deutsch
   <ghost@aladdin.com>. Thank him since I'm not a good speaker of English. :)
 */
#include <string.h>
#include "sha1.h"

#define     INLINE      inline
/*
 * Packing bytes to a word
 *
 * Should not assume p is aligned to word boundary
 */
static INLINE sha1_word_t packup(sha1_byte_t *p)
{
  /* Portable, but slow */
  return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3] << 0;
}

/*
 * Unpacking a word to bytes
 *
 * Should not assume p is aligned to word boundary
 */
static void unpackup(sha1_byte_t *p, sha1_word_t q)
{
  p[0] = (q >> 24) & 0xff;
  p[1] = (q >> 16) & 0xff;
  p[2] = (q >>  8) & 0xff;
  p[3] = (q >>  0) & 0xff;
}

/*
 * Processing a block
 */
static inline void sha1_update_now(sha1_state_s *pms, sha1_byte_t *bp)
{
  sha1_word_t     tmp, a, b, c, d, e, w[16+16];
  int i, s;

  /* pack 64 bytes into 16 words */
  for(i = 0; i < 16; i++) {
    w[i] = packup(bp + i * sizeof(sha1_word_t));
  }
  memcpy(w + 16, w + 0, sizeof(sha1_word_t) * 16);

  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];

#define     rot(x,n) (((x) << n) | ((x) >> (32-n)))
#define     f0(b, c, d) ((b&c)|(~b&d))
#define     f1(b, c, d) (b^c^d)
#define     f2(b, c, d) ((b&c)|(b&d)|(c&d))
#define     f3(b, c, d) (b^c^d)
#define k0        0x5a827999
#define     k1          0x6ed9eba1
#define     k2          0x8f1bbcdc
#define     k3          0xca62c1d6

  /* t=0-15 */
  s = 0;
  for(i = 0; i < 16; i++) {
    tmp = rot(a, 5) + f0(b, c, d) + e + w[s] + k0;
    e = d; d = c; c = rot(b, 30); b = a; a = tmp;
    s = (s + 1) % 16;
  }

  /* t=16-19 */
  for(i = 16; i < 20; i++) {
    w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
    w[s+16] = w[s];
    tmp = rot(a, 5) + f0(b, c, d) + e + w[s] + k0;
    e = d; d = c; c = rot(b, 30); b = a; a = tmp;
    s = (s + 1) % 16;
  }

  /* t=20-39 */
  for(i = 0; i < 20; i++) {
    w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
    w[s+16] = w[s];
    tmp = rot(a, 5) + f1(b, c, d) + e + w[s] + k1;
    e = d; d = c; c = rot(b, 30); b = a; a = tmp;
    s = (s + 1) % 16;
  }

  /* t=40-59 */
  for(i = 0; i < 20; i++) {
    w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
    w[s+16] = w[s];
    tmp = rot(a, 5) + f2(b, c, d) + e + w[s] + k2;
    e = d; d = c; c = rot(b, 30); b = a; a = tmp;
    s = (s + 1) % 16;
  }

  /* t=60-79 */
  for(i = 0; i < 20; i++) {
    w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
    w[s+16] = w[s];
    tmp = rot(a, 5) + f3(b, c, d) + e + w[s] + k3;
    e = d; d = c; c = rot(b, 30); b = a; a = tmp;
    s = (s + 1) % 16;
  }

  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;
}

/*
 * Increment sha1_size1, sha1_size2 field of sha1_state_s
 */
static INLINE void incr(sha1_state_s *pms, int v)
{
  sha1_word_t     q;

  q = pms->sha1_size1 + v * BITS;
  if(q < pms->sha1_size1) {
    pms->sha1_size2++;
  }
  pms->sha1_size1 = q;
}

/*
 * Initialize sha1_state_s as FIPS specifies
 */
void  sha1_init(sha1_state_s *pms)
{
  memset(pms, 0, sizeof(*pms));
  pms->sha1_h[0] = 0x67452301;      /* Initialize H[0]-H[4] */
  pms->sha1_h[1] = 0xEFCDAB89;
  pms->sha1_h[2] = 0x98BADCFE;
  pms->sha1_h[3] = 0x10325476;
  pms->sha1_h[4] = 0xC3D2E1F0;
}

/*
 * Fill block and update output when needed
 */
void  sha1_update(sha1_state_s *pms, sha1_byte_t *bufp, int length)
{
  /* Is the buffer partially filled? */
  if(pms->sha1_count != 0) {
    if(pms->sha1_count + length >= (signed) sizeof(pms->sha1_buf)) {    /* buffer is filled enough */
      int fil = sizeof(pms->sha1_buf) - pms->sha1_count;          /* length to copy */

      memcpy(pms->sha1_buf + pms->sha1_count, bufp, fil);
      sha1_update_now(pms, pms->sha1_buf);
      length -= fil;
      bufp += fil;
      pms->sha1_count = 0;
      incr(pms, fil);
    } else {
      memcpy(pms->sha1_buf + pms->sha1_count, bufp, length);
      pms->sha1_count += length;
      incr(pms, length);
      return;
    }
  }

  /* Loop to update state */
  for(;;) {
    if(length < (signed) sizeof(pms->sha1_buf)) {           /* Short to fill up the buffer */
      if(length) {
        memcpy(pms->sha1_buf, bufp, length);
      }
      pms->sha1_count = length;
      incr(pms, length);
      break;
    }
    sha1_update_now(pms, bufp);
    length -= sizeof(pms->sha1_buf);
    bufp += sizeof(pms->sha1_buf);
    incr(pms, sizeof(pms->sha1_buf));
  }
}

void  sha1_finish(sha1_state_s *pms, sha1_byte_t output[SHA1_OUTPUT_SIZE])
{
  int i;
  sha1_byte_t buf[1];

  /* fill a bit */
  buf[0] = 0x80;
  sha1_update(pms, buf, 1);

  /* Decrement sha1_size1, sha1_size2 */
  if((pms->sha1_size1 -= BITS) == 0) {
    pms->sha1_size2--;
  }

  /* fill zeros */
  if(pms->sha1_count > (signed) (sizeof(pms->sha1_buf) - 2 * sizeof(sha1_word_t))) {
    memset(pms->sha1_buf + pms->sha1_count, 0, sizeof(pms->sha1_buf) - pms->sha1_count);
    sha1_update_now(pms, pms->sha1_buf);
    pms->sha1_count = 0;
  }
  memset(pms->sha1_buf + pms->sha1_count, 0,
    sizeof(pms->sha1_buf) - pms->sha1_count - sizeof(sha1_word_t) * 2);

  /* fill last length */
  unpackup(pms->sha1_buf + sizeof(pms->sha1_buf) - sizeof(sha1_word_t) * 2, pms->sha1_size2);
  unpackup(pms->sha1_buf + sizeof(pms->sha1_buf) - sizeof(sha1_word_t) * 1, pms->sha1_size1);

  /* final update */
  sha1_update_now(pms, pms->sha1_buf);

  /* move hash value to output byte array */
  for(i = 0; i < (signed) (sizeof(pms->sha1_h)/sizeof(sha1_word_t)); i++) {
    unpackup(output + i * sizeof(sha1_word_t), pms->sha1_h[i]);
  }
}

Generated by  Doxygen 1.6.0   Back to index