diff --git a/bin/tests/.cvsignore b/bin/tests/.cvsignore index 4dbf41f5e8..04283a8758 100644 --- a/bin/tests/.cvsignore +++ b/bin/tests/.cvsignore @@ -33,6 +33,7 @@ res_test rwlock_test sdig serial_test +sha1_test shutdown_test sock_test sym_test diff --git a/bin/tests/Makefile.in b/bin/tests/Makefile.in index cd22bfb1ed..26ea7a7276 100644 --- a/bin/tests/Makefile.in +++ b/bin/tests/Makefile.in @@ -69,6 +69,7 @@ XTARGETS = adb_test \ rdata_test \ rwlock_test \ serial_test \ + sha1_test \ shutdown_test \ sock_test \ sym_test \ @@ -107,6 +108,7 @@ SRCS = adb_test.c \ rdata_test.c \ rwlock_test.c \ serial_test.c \ + sha1_test.c \ shutdown_test.c \ sock_test.c \ sym_test.c \ @@ -157,6 +159,10 @@ omapi_test: omapi_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${OMAPIDEPLIBS} ${LIBTOOL} ${CC} ${CFLAGS} -o $@ omapi_test.@O@ \ ${OMAPILIBS} ${DNSLIBS} ${ISCLIBS} ${LIBS} +sha1_test: sha1_test.@O@ ${ISCDEPLIBS} + ${LIBTOOL} ${CC} ${CFLAGS} -o $@ sha1_test.@O@ \ + ${ISCLIBS} ${LIBS} + sock_test: sock_test.@O@ ${ISCDEPLIBS} ${LIBTOOL} ${CC} ${CFLAGS} -o $@ sock_test.@O@ \ ${ISCLIBS} ${LIBS} diff --git a/bin/tests/sha1_test.c b/bin/tests/sha1_test.c new file mode 100644 index 0000000000..677542e6ed --- /dev/null +++ b/bin/tests/sha1_test.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2000 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include +#include + +#include + +static void +print_digest(char *s, unsigned char d[20]) { + int i, j; + + printf("hashed %s:\n\t", s); + for (i = 0 ; i < 5 ; i++) { + printf(" "); + for (j = 0 ; j < 4 ; j++) + printf("%02x", d[i * 4 + j]); + } + printf("\n"); +} + +int +main(int argc, char **argv) { + isc_sha1_t sha1; + unsigned char digest[20]; + unsigned char buffer[1024]; + const unsigned char *s; + + UNUSED(argc); + UNUSED(argv); + + + s = "abc"; + isc_sha1_init(&sha1); + strcpy(buffer, s); + isc_sha1_update(&sha1, buffer, strlen(s)); + isc_sha1_final(&sha1, digest); + print_digest(buffer, digest); + + s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + isc_sha1_init(&sha1); + strcpy(buffer, s); + isc_sha1_update(&sha1, buffer, strlen(s)); + isc_sha1_final(&sha1, digest); + print_digest(buffer, digest); + + return (0); +} diff --git a/config.h.in b/config.h.in index 84bc8b1132..b7f50add62 100644 --- a/config.h.in +++ b/config.h.in @@ -94,6 +94,9 @@ int sigwait(const unsigned int *set, int *sig); } while (0) #endif /* SHUTUP_STDARG_CAST && __GNUC__ */ +/* Define if you have the header file. */ +#undef HAVE_ENDIAN_H + /* Define if you have the header file. */ #undef HAVE_FCNTL_H @@ -103,6 +106,9 @@ int sigwait(const unsigned int *set, int *sig); /* Define if you have the header file. */ #undef HAVE_LINUX_PRCTL_H +/* Define if you have the header file. */ +#undef HAVE_SYS_ENDIAN_H + /* Define if you have the header file. */ #undef HAVE_SYS_SOCKIO_H diff --git a/configure b/configure index 8076bb2b7d..1b75cc068e 100755 --- a/configure +++ b/configure @@ -1546,7 +1546,7 @@ EOF fi -for ac_hdr in fcntl.h sys/time.h unistd.h sys/sockio.h +for ac_hdr in fcntl.h sys/time.h unistd.h endian.h sys/endian.h sys/sockio.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 diff --git a/configure.in b/configure.in index abed0a557b..bfd4017ba1 100644 --- a/configure.in +++ b/configure.in @@ -13,7 +13,7 @@ dnl PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS dnl ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS dnl SOFTWARE. -AC_REVISION($Revision: 1.144 $) +AC_REVISION($Revision: 1.145 $) AC_PREREQ(2.13) @@ -245,7 +245,7 @@ AC_PROG_YACC AC_HEADER_STDC -AC_CHECK_HEADERS(fcntl.h sys/time.h unistd.h sys/sockio.h) +AC_CHECK_HEADERS(fcntl.h sys/time.h unistd.h endian.h sys/endian.h sys/sockio.h) AC_C_CONST AC_C_INLINE diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in index d02eaa631b..a41100d2d6 100644 --- a/lib/isc/Makefile.in +++ b/lib/isc/Makefile.in @@ -51,7 +51,7 @@ OBJS = @ISC_EXTRA_OBJS@ \ mem.@O@ mutexblock.@O@ netaddr.@O@ ondestroy.@O@ \ quota.@O@ random.@O@ \ ratelimiter.@O@ result.@O@ rwlock.@O@ \ - serial.@O@ sockaddr.@O@ string.@O@ symtab.@O@ \ + serial.@O@ sha1.@O@ sockaddr.@O@ string.@O@ symtab.@O@ \ task.@O@ taskpool.@O@ timer.@O@ version.@O@ \ ${UNIXOBJS} ${NLSOBJS} ${PTHREADOBJS} @@ -63,7 +63,7 @@ SRCS = @ISC_EXTRA_SRCS@ \ mem.c mutexblock.c netaddr.c ondestroy.c \ quota.c random.c \ ratelimiter.c result.c rwlock.c \ - serial.c sockaddr.c string.c symtab.c \ + serial.c sha1.c sockaddr.c string.c symtab.c \ task.c taskpool.c timer.c version.c LIBS = @LIBS@ diff --git a/lib/isc/include/isc/Makefile.in b/lib/isc/include/isc/Makefile.in index cbddb44304..ba70c595ef 100644 --- a/lib/isc/include/isc/Makefile.in +++ b/lib/isc/include/isc/Makefile.in @@ -28,7 +28,7 @@ HEADERS = assertions.h base64.h bitstring.h boolean.h buffer.h \ lfsr.h lib.h list.h log.h magic.h mem.h msgcat.h \ mutexblock.h netaddr.h ondestroy.h platform.h \ print.h quota.h random.h ratelimiter.h region.h \ - result.h resultclass.h rwlock.h serial.h sockaddr.h \ + result.h resultclass.h rwlock.h serial.h sha1.h sockaddr.h \ socket.h stdio.h string.h symtab.h task.h taskpool.h timer.h \ types.h util.h diff --git a/lib/isc/include/isc/sha1.h b/lib/isc/include/isc/sha1.h new file mode 100644 index 0000000000..63287d3242 --- /dev/null +++ b/lib/isc/include/isc/sha1.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2000 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* $Id: sha1.h,v 1.1 2000/06/07 00:15:19 explorer Exp $ */ + +/* $NetBSD: sha1.h,v 1.2 1998/05/29 22:55:44 thorpej Exp $ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + */ + +#ifndef ISC_SHA1_H +#define ISC_SHA1_H + +#include + +typedef struct { + isc_uint32_t state[5]; + isc_uint32_t count[2]; + unsigned char buffer[64]; +} isc_sha1_t; + +void isc_sha1_init(isc_sha1_t *ctx); +void isc_sha1_invalidate(isc_sha1_t *ctx); +void isc_sha1_update(isc_sha1_t *ctx, const unsigned char *data, u_int len); +void isc_sha1_final(isc_sha1_t *ctx, unsigned char digest[20]); + +void isc_sha1_transform(isc_uint32_t state[5], const unsigned char buffer[64]); + +#endif /* ISC_SHA1_H */ diff --git a/lib/isc/sha1.c b/lib/isc/sha1.c new file mode 100644 index 0000000000..0a84df0d43 --- /dev/null +++ b/lib/isc/sha1.c @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2000 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* $Id: sha1.c,v 1.1 2000/06/07 00:15:17 explorer Exp $ */ + +/* $NetBSD: sha1.c,v 1.5 2000/01/22 22:19:14 mycroft Exp $ */ +/* $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + * + * Test Vectors (from FIPS PUB 180-1) + * "abc" + * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + * A million repetitions of "a" + * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#if defined(HAVE_ENDIAN_H) +#include +#elif defined(HAVE_SYS_ENDIAN_H) +#include +#endif + +#if !defined(BYTE_ORDER) && defined(__BYTE_ORDER) +#define BYTE_ORDER __BYTE_ORDER +#define LITTLE_ENDIAN __LITTLE_ENDIAN +#define BIG_ENDIAN __BIG_ENDIAN +#endif + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* + * blk0() and blk() perform the initial expand. + * I got the idea of expanding during the round function from SSLeay + */ +#if BYTE_ORDER == LITTLE_ENDIAN +# define blk0(i) \ + (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) \ + | (rol(block->l[i], 8) & 0x00FF00FF)) +#else +# define blk0(i) block->l[i] +#endif +#define blk(i) \ + (block->l[i & 15] = rol(block->l[(i + 13) & 15] \ + ^ block->l[(i + 8) & 15] \ + ^ block->l[(i + 2) & 15] \ + ^ block->l[i & 15], 1)) + +/* + * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 + */ +#define R0(v,w,x,y,z,i) \ + z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ + w = rol(w, 30); +#define R1(v,w,x,y,z,i) \ + z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ + w = rol(w, 30); +#define R2(v,w,x,y,z,i) \ + z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \ + w = rol(w, 30); +#define R3(v,w,x,y,z,i) \ + z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ + w = rol(w, 30); +#define R4(v,w,x,y,z,i) \ + z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ + w = rol(w, 30); + +typedef union { + unsigned char c[64]; + unsigned int l[16]; +} CHAR64LONG16; + +/* + * Hash a single 512-bit block. This is the core of the algorithm. + */ +void +isc_sha1_transform(isc_uint32_t state[5], const unsigned char buffer[64]) { + isc_uint32_t a, b, c, d, e; + CHAR64LONG16 *block; + unsigned char workspace[64]; + + INSIST(buffer != NULL); + INSIST(state != NULL); + + block = (CHAR64LONG16 *)(void *)workspace; + (void)memcpy(block, buffer, 64); + + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* + * isc_sha1_init - Initialize new context + */ +void +isc_sha1_init(isc_sha1_t *context) +{ + + INSIST(context != NULL); + + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = 0; + context->count[1] = 0; +} + +void +isc_sha1_invalidate(isc_sha1_t *context) { + memset(context, 0, sizeof(isc_sha1_t)); +} + +/* + * Run your data through this. + */ +void +isc_sha1_update(isc_sha1_t *context, const unsigned char *data, + unsigned int len) +{ + unsigned int i, j; + + INSIST(context != 0); + INSIST(data != 0); + + j = context->count[0]; + if ((context->count[0] += len << 3) < j) + context->count[1] += (len >> 29) + 1; + j = (j >> 3) & 63; + if ((j + len) > 63) { + (void)memcpy(&context->buffer[j], data, (i = 64 - j)); + isc_sha1_transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) + isc_sha1_transform(context->state, &data[i]); + j = 0; + } else { + i = 0; + } + + (void)memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* + * Add padding and return the message digest. + */ + +static const unsigned char final_200 = '\200'; +static const unsigned char final_0 = '\0'; + +void +isc_sha1_final(isc_sha1_t *context, unsigned char digest[20]) { + unsigned int i; + unsigned char finalcount[8]; + + INSIST(digest != 0); + INSIST(context != 0); + + for (i = 0; i < 8; i++) { + /* Endian independent */ + finalcount[i] = (unsigned char) + ((context->count[(i >= 4 ? 0 : 1)] + >> ((3 - (i & 3)) * 8)) & 255); + } + + isc_sha1_update(context, &final_200, 1); + while ((context->count[0] & 504) != 448) + isc_sha1_update(context, &final_0, 1); + /* The next Update should cause a isc_sha1_transform() */ + isc_sha1_update(context, finalcount, 8); + + if (digest) { + for (i = 0; i < 20; i++) + digest[i] = (unsigned char) + ((context->state[i >> 2] + >> ((3 - (i & 3)) * 8)) & 255); + } +} diff --git a/util/copyrights b/util/copyrights index d4c64026c9..1b6bb7d01e 100644 --- a/util/copyrights +++ b/util/copyrights @@ -265,6 +265,7 @@ ./bin/tests/resolv.conf.sample X 2000 ./bin/tests/rwlock_test.c C 1998,1999,2000 ./bin/tests/serial_test.c C 1999,2000 +./bin/tests/sha1_test.c C 2000 ./bin/tests/shutdown_test.c C 1998,1999,2000 ./bin/tests/sock_test.c C 1998,1999,2000 ./bin/tests/sockaddr/.cvsignore X 1999,2000 @@ -688,6 +689,7 @@ ./lib/isc/include/isc/resultclass.h C 1999,2000 ./lib/isc/include/isc/rwlock.h C 1998,1999,2000 ./lib/isc/include/isc/serial.h C 1999,2000 +./lib/isc/include/isc/sha1.h C 2000 ./lib/isc/include/isc/sockaddr.h C 1998,1999,2000 ./lib/isc/include/isc/socket.h C 1998,1999,2000 ./lib/isc/include/isc/str.h C 1999,2000 @@ -732,6 +734,7 @@ ./lib/isc/result.c C 1998,1999,2000 ./lib/isc/rwlock.c C 1998,1999,2000 ./lib/isc/serial.c C 1999,2000 +./lib/isc/sha1.c C 2000 ./lib/isc/sockaddr.c C 1999,2000 ./lib/isc/string.c C 1999,2000 ./lib/isc/symtab.c C 1996,1997,1998,1999,2000