diff options
Diffstat (limited to 'lib/libalpm')
| -rw-r--r-- | lib/libalpm/sha1.c | 415 | ||||
| -rw-r--r-- | lib/libalpm/sha1.h | 60 | 
2 files changed, 475 insertions, 0 deletions
| diff --git a/lib/libalpm/sha1.c b/lib/libalpm/sha1.c new file mode 100644 index 00000000..4fd110ea --- /dev/null +++ b/lib/libalpm/sha1.c @@ -0,0 +1,415 @@ +/* sha.c - Functions to compute SHA1 message digest of files or +   memory blocks according to the NIST specification FIPS-180-1. + +   Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + +   This program is free software; you can redistribute it and/or modify it +   under the terms of the GNU General Public License as published by the +   Free Software Foundation; either version 2, or (at your option) any +   later version. + +   This program is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program; if not, write to the Free Software Foundation, +   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */ + +/* Written by Scott G. Miller +   Credits: +      Robert Klep <robert@ilse.nl>  -- Expansion function fix +*/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <libintl.h> + +#include "util.h" +#include "sha1.h" + +#include <sys/types.h> + +#include <stdlib.h> +#include <time.h> +#include <string.h> + +/* +  Not-swap is a macro that does an endian swap on architectures that are +  big-endian, as SHA needs some data in a little-endian format +*/ + +#ifdef WORDS_BIGENDIAN +# define NOTSWAP(n) (n) +# define SWAP(n)							\ +    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +#else +# define NOTSWAP(n)                                                         \ +    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +# define SWAP(n) (n) +#endif + +#define BLOCKSIZE 4096 +/* Ensure that BLOCKSIZE is a multiple of 64.  */ +#if BLOCKSIZE % 64 != 0 +/* FIXME-someday (soon?): use #error instead of this kludge.  */ +"invalid BLOCKSIZE" +#endif + +/* This array contains the bytes used to pad the buffer to the next +   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ }; + + +/* Starting with the result of former calls of this function (or the +   initialization function update the context for the next LEN bytes +   starting at BUFFER. +   It is necessary that LEN is a multiple of 64!!! */ +static void sha_process_block (const void *buffer, size_t len, +			       struct sha_ctx *ctx); + +/* Starting with the result of former calls of this function (or the +   initialization function update the context for the next LEN bytes +   starting at BUFFER. +   It is NOT required that LEN is a multiple of 64.  */ +static void sha_process_bytes (const void *buffer, size_t len, +			       struct sha_ctx *ctx); + +/* Put result from CTX in first 20 bytes following RESBUF.  The result is +   always in little endian byte order, so that a byte-wise output yields +   to the wanted ASCII representation of the message digest. + +   IMPORTANT: On some systems it is required that RESBUF is correctly +   aligned for a 32 bits value.  */ +static void *sha_read_ctx (const struct sha_ctx *ctx, void *resbuf); + +/* +  Takes a pointer to a 160 bit block of data (five 32 bit ints) and +  intializes it to the start constants of the SHA1 algorithm.  This +  must be called before using hash in the call to sha_hash +*/ +static void +sha_init_ctx (struct sha_ctx *ctx) +{ +  ctx->A = 0x67452301; +  ctx->B = 0xefcdab89; +  ctx->C = 0x98badcfe; +  ctx->D = 0x10325476; +  ctx->E = 0xc3d2e1f0; + +  ctx->total[0] = ctx->total[1] = 0; +  ctx->buflen = 0; +} + +/* Put result from CTX in first 20 bytes following RESBUF.  The result +   must be in little endian byte order. + +   IMPORTANT: On some systems it is required that RESBUF is correctly +   aligned for a 32 bits value.  */ +static void * +sha_read_ctx (const struct sha_ctx *ctx, void *resbuf) +{ +  ((sha_uint32 *) resbuf)[0] = NOTSWAP (ctx->A); +  ((sha_uint32 *) resbuf)[1] = NOTSWAP (ctx->B); +  ((sha_uint32 *) resbuf)[2] = NOTSWAP (ctx->C); +  ((sha_uint32 *) resbuf)[3] = NOTSWAP (ctx->D); +  ((sha_uint32 *) resbuf)[4] = NOTSWAP (ctx->E); + +  return resbuf; +} + +/* Process the remaining bytes in the internal buffer and the usual +   prolog according to the standard and write the result to RESBUF. + +   IMPORTANT: On some systems it is required that RESBUF is correctly +   aligned for a 32 bits value.  */ +static void * +sha_finish_ctx (struct sha_ctx *ctx, void *resbuf) +{ +  /* Take yet unprocessed bytes into account.  */ +  sha_uint32 bytes = ctx->buflen; +  size_t pad; + +  /* Now count remaining bytes.  */ +  ctx->total[0] += bytes; +  if (ctx->total[0] < bytes) +    ++ctx->total[1]; + +  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; +  memcpy (&ctx->buffer[bytes], fillbuf, pad); + +  /* Put the 64-bit file length in *bits* at the end of the buffer.  */ +  *(sha_uint32 *) &ctx->buffer[bytes + pad + 4] = NOTSWAP (ctx->total[0] << 3); +  *(sha_uint32 *) &ctx->buffer[bytes + pad] = NOTSWAP ((ctx->total[1] << 3) | +						    (ctx->total[0] >> 29)); + +  /* Process last bytes.  */ +  sha_process_block (ctx->buffer, bytes + pad + 8, ctx); + +  return sha_read_ctx (ctx, resbuf); +} + +static void +sha_process_bytes (const void *buffer, size_t len, struct sha_ctx *ctx) +{ +  /* When we already have some bits in our internal buffer concatenate +     both inputs first.  */ +  if (ctx->buflen != 0) +    { +      size_t left_over = ctx->buflen; +      size_t add = 128 - left_over > len ? len : 128 - left_over; + +      memcpy (&ctx->buffer[left_over], buffer, add); +      ctx->buflen += add; + +      if (ctx->buflen > 64) +	{ +	  sha_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + +	  ctx->buflen &= 63; +	  /* The regions in the following copy operation cannot overlap.  */ +	  memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], +		  ctx->buflen); +	} + +      buffer = (const char *) buffer + add; +      len -= add; +    } + +  /* Process available complete blocks.  */ +  if (len >= 64) +    { +#if !_STRING_ARCH_unaligned +/* To check alignment gcc has an appropriate operator.  Other +   compilers don't.  */ +# if __GNUC__ >= 2 +#  define UNALIGNED_P(p) (((sha_uintptr) p) % __alignof__ (sha_uint32) != 0) +# else +#  define UNALIGNED_P(p) (((sha_uintptr) p) % sizeof (sha_uint32) != 0) +# endif +      if (UNALIGNED_P (buffer)) +	while (len > 64) +	  { +	    sha_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); +	    buffer = (const char *) buffer + 64; +	    len -= 64; +	  } +      else +#endif +	{ +	  sha_process_block (buffer, len & ~63, ctx); +	  buffer = (const char *) buffer + (len & ~63); +	  len &= 63; +	} +    } + +  /* Move remaining bytes in internal buffer.  */ +  if (len > 0) +    { +      size_t left_over = ctx->buflen; + +      memcpy (&ctx->buffer[left_over], buffer, len); +      left_over += len; +      if (left_over >= 64) +	{ +	  sha_process_block (ctx->buffer, 64, ctx); +	  left_over -= 64; +	  memcpy (ctx->buffer, &ctx->buffer[64], left_over); +	} +      ctx->buflen = left_over; +    } +} + +/* --- Code below is the primary difference between md5.c and sha.c --- */ + +/* SHA1 round constants */ +#define K1 0x5a827999L +#define K2 0x6ed9eba1L +#define K3 0x8f1bbcdcL +#define K4 0xca62c1d6L + +/* Round functions.  Note that F2 is the same as F4.  */ +#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) ) +#define F2(B,C,D) (B ^ C ^ D) +#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) ) +#define F4(B,C,D) (B ^ C ^ D) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. +   It is assumed that LEN % 64 == 0. +   Most of this code comes from GnuPG's cipher/sha1.c.  */ + +static void +sha_process_block (const void *buffer, size_t len, struct sha_ctx *ctx) +{ +  const sha_uint32 *words = buffer; +  size_t nwords = len / sizeof (sha_uint32); +  const sha_uint32 *endp = words + nwords; +  sha_uint32 x[16]; +  sha_uint32 a = ctx->A; +  sha_uint32 b = ctx->B; +  sha_uint32 c = ctx->C; +  sha_uint32 d = ctx->D; +  sha_uint32 e = ctx->E; + +  /* First increment the byte count.  RFC 1321 specifies the possible +     length of the file up to 2^64 bits.  Here we only compute the +     number of bytes.  Do a double word increment.  */ +  ctx->total[0] += len; +  if (ctx->total[0] < len) +    ++ctx->total[1]; + +#define M(I) ( tm =   x[I&0x0f] ^ x[(I-14)&0x0f] \ +		    ^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \ +	       , (x[I&0x0f] = rol(tm, 1)) ) + +#define R(A,B,C,D,E,F,K,M)  do { E += rol( A, 5 )     \ +				      + F( B, C, D )  \ +				      + K	      \ +				      + M;	      \ +				 B = rol( B, 30 );    \ +			       } while(0) + +  while (words < endp) +    { +      sha_uint32 tm; +      int t; +      /* FIXME: see sha1.c for a better implementation.  */ +      for (t = 0; t < 16; t++) +	{ +	  x[t] = NOTSWAP (*words); +	  words++; +	} + +      R( a, b, c, d, e, F1, K1, x[ 0] ); +      R( e, a, b, c, d, F1, K1, x[ 1] ); +      R( d, e, a, b, c, F1, K1, x[ 2] ); +      R( c, d, e, a, b, F1, K1, x[ 3] ); +      R( b, c, d, e, a, F1, K1, x[ 4] ); +      R( a, b, c, d, e, F1, K1, x[ 5] ); +      R( e, a, b, c, d, F1, K1, x[ 6] ); +      R( d, e, a, b, c, F1, K1, x[ 7] ); +      R( c, d, e, a, b, F1, K1, x[ 8] ); +      R( b, c, d, e, a, F1, K1, x[ 9] ); +      R( a, b, c, d, e, F1, K1, x[10] ); +      R( e, a, b, c, d, F1, K1, x[11] ); +      R( d, e, a, b, c, F1, K1, x[12] ); +      R( c, d, e, a, b, F1, K1, x[13] ); +      R( b, c, d, e, a, F1, K1, x[14] ); +      R( a, b, c, d, e, F1, K1, x[15] ); +      R( e, a, b, c, d, F1, K1, M(16) ); +      R( d, e, a, b, c, F1, K1, M(17) ); +      R( c, d, e, a, b, F1, K1, M(18) ); +      R( b, c, d, e, a, F1, K1, M(19) ); +      R( a, b, c, d, e, F2, K2, M(20) ); +      R( e, a, b, c, d, F2, K2, M(21) ); +      R( d, e, a, b, c, F2, K2, M(22) ); +      R( c, d, e, a, b, F2, K2, M(23) ); +      R( b, c, d, e, a, F2, K2, M(24) ); +      R( a, b, c, d, e, F2, K2, M(25) ); +      R( e, a, b, c, d, F2, K2, M(26) ); +      R( d, e, a, b, c, F2, K2, M(27) ); +      R( c, d, e, a, b, F2, K2, M(28) ); +      R( b, c, d, e, a, F2, K2, M(29) ); +      R( a, b, c, d, e, F2, K2, M(30) ); +      R( e, a, b, c, d, F2, K2, M(31) ); +      R( d, e, a, b, c, F2, K2, M(32) ); +      R( c, d, e, a, b, F2, K2, M(33) ); +      R( b, c, d, e, a, F2, K2, M(34) ); +      R( a, b, c, d, e, F2, K2, M(35) ); +      R( e, a, b, c, d, F2, K2, M(36) ); +      R( d, e, a, b, c, F2, K2, M(37) ); +      R( c, d, e, a, b, F2, K2, M(38) ); +      R( b, c, d, e, a, F2, K2, M(39) ); +      R( a, b, c, d, e, F3, K3, M(40) ); +      R( e, a, b, c, d, F3, K3, M(41) ); +      R( d, e, a, b, c, F3, K3, M(42) ); +      R( c, d, e, a, b, F3, K3, M(43) ); +      R( b, c, d, e, a, F3, K3, M(44) ); +      R( a, b, c, d, e, F3, K3, M(45) ); +      R( e, a, b, c, d, F3, K3, M(46) ); +      R( d, e, a, b, c, F3, K3, M(47) ); +      R( c, d, e, a, b, F3, K3, M(48) ); +      R( b, c, d, e, a, F3, K3, M(49) ); +      R( a, b, c, d, e, F3, K3, M(50) ); +      R( e, a, b, c, d, F3, K3, M(51) ); +      R( d, e, a, b, c, F3, K3, M(52) ); +      R( c, d, e, a, b, F3, K3, M(53) ); +      R( b, c, d, e, a, F3, K3, M(54) ); +      R( a, b, c, d, e, F3, K3, M(55) ); +      R( e, a, b, c, d, F3, K3, M(56) ); +      R( d, e, a, b, c, F3, K3, M(57) ); +      R( c, d, e, a, b, F3, K3, M(58) ); +      R( b, c, d, e, a, F3, K3, M(59) ); +      R( a, b, c, d, e, F4, K4, M(60) ); +      R( e, a, b, c, d, F4, K4, M(61) ); +      R( d, e, a, b, c, F4, K4, M(62) ); +      R( c, d, e, a, b, F4, K4, M(63) ); +      R( b, c, d, e, a, F4, K4, M(64) ); +      R( a, b, c, d, e, F4, K4, M(65) ); +      R( e, a, b, c, d, F4, K4, M(66) ); +      R( d, e, a, b, c, F4, K4, M(67) ); +      R( c, d, e, a, b, F4, K4, M(68) ); +      R( b, c, d, e, a, F4, K4, M(69) ); +      R( a, b, c, d, e, F4, K4, M(70) ); +      R( e, a, b, c, d, F4, K4, M(71) ); +      R( d, e, a, b, c, F4, K4, M(72) ); +      R( c, d, e, a, b, F4, K4, M(73) ); +      R( b, c, d, e, a, F4, K4, M(74) ); +      R( a, b, c, d, e, F4, K4, M(75) ); +      R( e, a, b, c, d, F4, K4, M(76) ); +      R( d, e, a, b, c, F4, K4, M(77) ); +      R( c, d, e, a, b, F4, K4, M(78) ); +      R( b, c, d, e, a, F4, K4, M(79) ); + +      a = ctx->A += a; +      b = ctx->B += b; +      c = ctx->C += c; +      d = ctx->D += d; +      e = ctx->E += e; +    } +} + +/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All +rights reserved. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + + +char* _alpm_SHAFile(char *filename) { +    FILE *file; +    struct sha_ctx context; +    int len, i; +    unsigned char buffer[1024], digest[20]; +    char *ret; +     +    if((file = fopen(filename, "rb")) == NULL) { +	fprintf(stderr, _("%s can't be opened\n"), filename); +    } else { +	sha_init_ctx(&context); +	while((len = fread(buffer, 1, 1024, file))) { +	    sha_process_bytes(buffer, len, &context); +	} +	sha_finish_ctx(&context, digest); +	fclose(file); +#ifdef DEBUG +	SHAPrint(digest); +#endif +	ret = (char*)malloc(41); +	ret[0] = '\0'; +	for(i = 0; i < 20; i++) { +	    sprintf(ret, "%s%02x", ret, digest[i]); +	} +	return(ret); +    } + +    return(NULL); +} diff --git a/lib/libalpm/sha1.h b/lib/libalpm/sha1.h new file mode 100644 index 00000000..22530eb9 --- /dev/null +++ b/lib/libalpm/sha1.h @@ -0,0 +1,60 @@ +/* Declarations of functions and data types used for SHA1 sum +   library functions. +   Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + +   This program is free software; you can redistribute it and/or modify it +   under the terms of the GNU General Public License as published by the +   Free Software Foundation; either version 2, or (at your option) any +   later version. + +   This program is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program; if not, write to the Free Software Foundation, +   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */ + +#include <stdio.h> +#include <limits.h> + +#define rol(x,n) ( ((x) << (n)) | ((x) >> (32 -(n))) ) +/* The code below is from md5.h (from coreutils), little modifications */ +#define UINT_MAX_32_BITS 4294967295U + +#if UINT_MAX == UINT_MAX_32_BITS +    typedef unsigned int sha_uint32; +#else +#if USHRT_MAX == UINT_MAX_32_BITS +    typedef unsigned short sha_uint32; +#else +#if ULONG_MAX == UINT_MAX_32_BITS +    typedef unsigned long sha_uint32; +#else +    /* The following line is intended to evoke an error. Using #error is not portable enough.  */ +#error "Cannot determine unsigned 32-bit data type" +#endif +#endif +#endif +/* We have to make a guess about the integer type equivalent in size +   to pointers which should always be correct.  */ +typedef unsigned long int sha_uintptr; + +/* Structure to save state of computation between the single steps.  */ +struct sha_ctx +{ +  sha_uint32 A; +  sha_uint32 B; +  sha_uint32 C; +  sha_uint32 D; +  sha_uint32 E; + +  sha_uint32 total[2]; +  sha_uint32 buflen; +  char buffer[128]; +}; + + +/* Needed for pacman */ +char *_alpm_SHAFile (char *); | 
