From cac3ea1e92cd70b25aa03986ab5825d27e77966a Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Thu, 3 Sep 1998 06:25:38 +0000 Subject: [PATCH] Import public domain sha1 routines from Steve Reid . Modified for OpenLDAP use by Daniel J. Gregor . --- include/lutil_md5.h | 11 +- include/lutil_sha1.h | 28 ++++ libraries/liblutil/Make-template | 4 +- libraries/liblutil/md5.c | 22 +-- libraries/liblutil/sha1.c | 261 +++++++++++++++++++++++++++++++ servers/slapd/back-ldbm/bind.c | 8 +- 6 files changed, 313 insertions(+), 21 deletions(-) create mode 100644 include/lutil_sha1.h create mode 100644 libraries/liblutil/sha1.c diff --git a/include/lutil_md5.h b/include/lutil_md5.h index 71aad8f35a..ed7181c438 100644 --- a/include/lutil_md5.h +++ b/include/lutil_md5.h @@ -9,7 +9,10 @@ important. ANSI guarantees that "unsigned long" will be big enough, and always using it seems to have few disadvantages. */ +#ifndef LDAP_UINT32 +#define LDAP_UINT32 typedef unsigned long uint32; +#endif struct MD5Context { uint32 buf[4]; @@ -17,10 +20,10 @@ struct MD5Context { unsigned char in[64]; }; -void MD5Init(struct MD5Context *context); -void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len); -void MD5Final(unsigned char digest[16], struct MD5Context *context); -void MD5Transform(uint32 buf[4], const unsigned char in[64]); +void ldap_MD5Init(struct MD5Context *context); +void ldap_MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len); +void ldap_MD5Final(unsigned char digest[16], struct MD5Context *context); +void ldap_MD5Transform(uint32 buf[4], const unsigned char in[64]); /* * This is needed to make RSAREF happy on some MS-DOS compilers. diff --git a/include/lutil_sha1.h b/include/lutil_sha1.h new file mode 100644 index 0000000000..7e1da078ac --- /dev/null +++ b/include/lutil_sha1.h @@ -0,0 +1,28 @@ +/* This version is based on: + * $OpenBSD: sha1.h,v 1.8 1997/07/15 01:54:23 millert Exp $ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + */ + +/* XXX I wonder if this will work on 64bit architectures... */ +#ifndef LDAP_UINT32 +#define LDAP_UINT32 +typedef unsigned long uint32; +#endif + +typedef struct { + uint32 state[5]; + uint32 count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +void ldap_SHA1Transform __P((uint32 state[5], const unsigned char buffer[64])); +void ldap_SHA1Init __P((SHA1_CTX *context)); +void ldap_SHA1Update __P((SHA1_CTX *context, const unsigned char *data, u_int len)); +void ldap_SHA1Final __P((unsigned char digest[20], SHA1_CTX *context)); +char *ldap_SHA1End __P((SHA1_CTX *, char *)); +char *ldap_SHA1File __P((char *, char *)); +char *ldap_SHA1Data __P((const unsigned char *, size_t, char *)); diff --git a/libraries/liblutil/Make-template b/libraries/liblutil/Make-template index c1ee9a263e..aec8460fd7 100644 --- a/libraries/liblutil/Make-template +++ b/libraries/liblutil/Make-template @@ -15,8 +15,8 @@ LDAPSRC = ../.. -SRCS = base64.c md5.c -OBJS = base64.o md5.o +SRCS = base64.c md5.c sha1.c +OBJS = base64.o md5.o sha1.o HDIR = ../../include diff --git a/libraries/liblutil/md5.c b/libraries/liblutil/md5.c index 838ed54ff6..225b9dc73b 100644 --- a/libraries/liblutil/md5.c +++ b/libraries/liblutil/md5.c @@ -63,7 +63,7 @@ putu32 (data, addr) * initialization constants. */ void -MD5Init(ctx) +ldap_MD5Init(ctx) struct MD5Context *ctx; { ctx->buf[0] = 0x67452301; @@ -80,7 +80,7 @@ MD5Init(ctx) * of bytes. */ void -MD5Update(ctx, buf, len) +ldap_MD5Update(ctx, buf, len) struct MD5Context *ctx; unsigned char const *buf; unsigned len; @@ -107,7 +107,7 @@ MD5Update(ctx, buf, len) return; } memcpy(p, buf, t); - MD5Transform(ctx->buf, ctx->in); + ldap_MD5Transform(ctx->buf, ctx->in); buf += t; len -= t; } @@ -116,7 +116,7 @@ MD5Update(ctx, buf, len) while (len >= 64) { memcpy(ctx->in, buf, 64); - MD5Transform(ctx->buf, ctx->in); + ldap_MD5Transform(ctx->buf, ctx->in); buf += 64; len -= 64; } @@ -131,7 +131,7 @@ MD5Update(ctx, buf, len) * 1 0* (64-bit count of bits processed, MSB-first) */ void -MD5Final(digest, ctx) +ldap_MD5Final(digest, ctx) unsigned char digest[16]; struct MD5Context *ctx; { @@ -153,7 +153,7 @@ MD5Final(digest, ctx) if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); - MD5Transform(ctx->buf, ctx->in); + ldap_MD5Transform(ctx->buf, ctx->in); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); @@ -166,7 +166,7 @@ MD5Final(digest, ctx) putu32(ctx->bits[0], ctx->in + 56); putu32(ctx->bits[1], ctx->in + 60); - MD5Transform(ctx->buf, ctx->in); + ldap_MD5Transform(ctx->buf, ctx->in); putu32(ctx->buf[0], digest); putu32(ctx->buf[1], digest + 4); putu32(ctx->buf[2], digest + 8); @@ -194,7 +194,7 @@ MD5Final(digest, ctx) * the data and converts bytes into longwords for this routine. */ void -MD5Transform(buf, inraw) +ldap_MD5Transform(buf, inraw) uint32 buf[4]; const unsigned char inraw[64]; { @@ -306,9 +306,9 @@ main (int argc, char **argv) for (j = 1; j < argc; ++j) { printf ("MD5 (\"%s\") = ", argv[j]); - MD5Init (&context); - MD5Update (&context, argv[j], strlen (argv[j])); - MD5Final (checksum, &context); + ldap_MD5Init (&context); + ldap_MD5Update (&context, argv[j], strlen (argv[j])); + ldap_MD5Final (checksum, &context); for (i = 0; i < 16; i++) { printf ("%02x", (unsigned int) checksum[i]); diff --git a/libraries/liblutil/sha1.c b/libraries/liblutil/sha1.c new file mode 100644 index 0000000000..9d4399b5dd --- /dev/null +++ b/libraries/liblutil/sha1.c @@ -0,0 +1,261 @@ +/* Acquired from: + * $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 + */ + +#define SHA1HANDSOFF /* Copies data before messing with it. */ + +#include +#include +#include "lutil_sha1.h" + +#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); + + +/* + * Hash a single 512-bit block. This is the core of the algorithm. + */ +void ldap_SHA1Transform(state, buffer) + uint32 state[5]; + const unsigned char buffer[64]; +{ + uint32 a, b, c, d, e; + typedef union { + unsigned char c[64]; + u_int l[16]; + } CHAR64LONG16; + CHAR64LONG16 *block; + +#ifdef SHA1HANDSOFF + static unsigned char workspace[64]; + block = (CHAR64LONG16 *)workspace; + (void)memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16 *)buffer; +#endif + + /* 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; +} + + +/* + * ldap_SHA1Init - Initialize new context + */ +void ldap_SHA1Init(context) + SHA1_CTX *context; +{ + + /* 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] = context->count[1] = 0; +} + + +/* + * Run your data through this. + */ +void ldap_SHA1Update(context, data, len) + SHA1_CTX *context; + const unsigned char *data; + u_int len; +{ + u_int i, j; + + 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)); + ldap_SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) + ldap_SHA1Transform(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. + */ +void ldap_SHA1Final(digest, context) + unsigned char digest[20]; + SHA1_CTX* context; +{ + u_int i; + unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + ldap_SHA1Update(context, (unsigned char *)"\200", 1); + while ((context->count[0] & 504) != 448) + ldap_SHA1Update(context, (unsigned char *)"\0", 1); + ldap_SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + + if (digest) { + for (i = 0; i < 20; i++) + digest[i] = (unsigned char) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } +} + + +/* sha1hl.c + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: sha1hl.c,v 1.1 1997/07/12 20:06:03 millert Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include +#include + +/* ARGSUSED */ +char * +ldap_SHA1End(ctx, buf) + SHA1_CTX *ctx; + char *buf; +{ + int i; + char *p = buf; + unsigned char digest[20]; + static const char hex[]="0123456789abcdef"; + + if (p == NULL && (p = malloc(41)) == NULL) + return 0; + + ldap_SHA1Final(digest,ctx); + for (i = 0; i < 20; i++) { + p[i + i] = hex[digest[i] >> 4]; + p[i + i + 1] = hex[digest[i] & 0x0f]; + } + p[i + i] = '\0'; + return(p); +} + +char * +ldap_SHA1File (filename, buf) + char *filename; + char *buf; +{ + unsigned char buffer[BUFSIZ]; + SHA1_CTX ctx; + int fd, num, oerrno; + + ldap_SHA1Init(&ctx); + + if ((fd = open(filename,O_RDONLY)) < 0) + return(0); + + while ((num = read(fd, buffer, sizeof(buffer))) > 0) + ldap_SHA1Update(&ctx, buffer, num); + + oerrno = errno; + close(fd); + errno = oerrno; + return(num < 0 ? 0 : ldap_SHA1End(&ctx, buf)); +} + +char * +ldap_SHA1Data (data, len, buf) + const unsigned char *data; + size_t len; + char *buf; +{ + SHA1_CTX ctx; + + ldap_SHA1Init(&ctx); + ldap_SHA1Update(&ctx, data, len); + return(ldap_SHA1End(&ctx, buf)); +} diff --git a/servers/slapd/back-ldbm/bind.c b/servers/slapd/back-ldbm/bind.c index 3ab224136a..9aabe85c36 100644 --- a/servers/slapd/back-ldbm/bind.c +++ b/servers/slapd/back-ldbm/bind.c @@ -20,7 +20,7 @@ extern char *crypt (char *key, char *salt); #endif /* LDAP_CRYPT */ #ifdef LDAP_SHA1 -#include +#include #endif /* LDAP_SHA1 */ #ifdef LDAP_MD5 #include @@ -91,9 +91,9 @@ crypted_value_find( char *userpassword = vals[i]->bv_val + sizeof("{SHA}") - 1; - SHA1Init(&SHA1context); - SHA1Update(&SHA1context, cred->bv_val, strlen(cred->bv_val)); - SHA1Final(SHA1digest, &SHA1context); + ldap_SHA1Init(&SHA1context); + ldap_SHA1Update(&SHA1context, cred->bv_val, strlen(cred->bv_val)); + ldap_SHA1Final(SHA1digest, &SHA1context); if (b64_ntop(SHA1digest, sizeof(SHA1digest), base64digest, sizeof(base64digest)) < 0) -- 2.39.5