diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2004-05-03 17:30:16 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2004-05-03 17:30:16 +0000 |
commit | 92c35e1d3a72a9dcbb1608827e7a8a87a5665cee (patch) | |
tree | 4efbbda5a46ebcdc9e9acc0262a5e1a5ee588aa7 /lib | |
parent | 3ce312b75c1e80c476cd991ad38c1782f4893aaf (diff) |
Add Pad and FileChunk functions for each family of hash functions.
The Pad function does padding like in Final but does not finish processing.
The FileChunk function creates a digest from a portion of a file.
Also made the length parameters consistent (and size_t).
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/hash/Makefile.inc | 30 | ||||
-rw-r--r-- | lib/libc/hash/helper.c | 28 | ||||
-rw-r--r-- | lib/libc/hash/md4.c | 25 | ||||
-rw-r--r-- | lib/libc/hash/md5.c | 25 | ||||
-rw-r--r-- | lib/libc/hash/mdX.3 | 41 | ||||
-rw-r--r-- | lib/libc/hash/rmd160.3 | 36 | ||||
-rw-r--r-- | lib/libc/hash/rmd160.c | 20 | ||||
-rw-r--r-- | lib/libc/hash/sha1.3 | 36 | ||||
-rw-r--r-- | lib/libc/hash/sha1.c | 22 | ||||
-rw-r--r-- | lib/libc/hash/sha2.3 | 45 | ||||
-rw-r--r-- | lib/libc/hash/sha2.c | 148 |
11 files changed, 315 insertions, 141 deletions
diff --git a/lib/libc/hash/Makefile.inc b/lib/libc/hash/Makefile.inc index 9c98c58df56..d86f8a2ffba 100644 --- a/lib/libc/hash/Makefile.inc +++ b/lib/libc/hash/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.16 2004/04/28 16:56:49 millert Exp $ +# $OpenBSD: Makefile.inc,v 1.17 2004/05/03 17:30:14 millert Exp $ # hash functions .PATH: ${LIBCSRCDIR}/hash @@ -6,24 +6,28 @@ HELPER= md4hl.c md5hl.c rmd160hl.c sha1hl.c sha256hl.c sha384hl.c sha512hl.c SRCS+= md4.c md5.c rmd160.c sha1.c sha2.c ${HELPER} MAN+= md4.3 md5.3 rmd160.3 sha1.3 sha2.3 -MLINKS+=md4.3 MD4Init.3 md4.3 MD4Update.3 md4.3 MD4Final.3 -MLINKS+=md4.3 MD4End.3 md4.3 MD4File.3 md4.3 MD4Data.3 -MLINKS+=md4.3 MD4Transform.3 -MLINKS+=md5.3 MD5Init.3 md5.3 MD5Update.3 md5.3 MD5Final.3 -MLINKS+=md5.3 MD5End.3 md5.3 MD5File.3 md5.3 MD5Data.3 -MLINKS+=md5.3 MD5Transform.3 -MLINKS+=rmd160.3 RMD160Init.3 rmd160.3 RMD160Update.3 rmd160.3 RMD160Final.3 -MLINKS+=rmd160.3 RMD160End.3 rmd160.3 RMD160File.3 rmd160.3 RMD160Data.3 -MLINKS+=rmd160.3 RMD160Transform.3 -MLINKS+=sha1.3 SHA1Init.3 sha1.3 SHA1Update.3 sha1.3 SHA1Final.3 -MLINKS+=sha1.3 SHA1End.3 sha1.3 SHA1File.3 sha1.3 SHA1Data.3 -MLINKS+=sha1.3 SHA1Transform.3 + +MLINKS+=md4.3 MD4Transform.3 md4.3 MD4Init.3 md4.3 MD4Final.3 +MLINKS+=md4.3 MD4Update.3 md4.3 MD4End.3 md4.3 MD4File.3 +MLINKS+=md4.3 MD4FileChunk.3 md4.3 MD4Pad.3 md4.3 MD4Data.3 +MLINKS+=md5.3 MD5Transform.3 md5.3 MD5Init.3 md5.3 MD5Final.3 +MLINKS+=md5.3 MD5Update.3 md5.3 MD5End.3 md5.3 MD5File.3 +MLINKS+=md5.3 MD5FileChunk.3 md5.3 MD5Pad.3 md5.3 MD5Data.3 +MLINKS+=rmd160.3 RMD160Transform.3 rmd160.3 RMD160Init.3 rmd160.3 RMD160Final.3 +MLINKS+=rmd160.3 RMD160Update.3 rmd160.3 RMD160End.3 rmd160.3 RMD160File.3 +MLINKS+=rmd160.3 RMD160FileChunk.3 rmd160.3 RMD160Pad.3 rmd160.3 RMD160Data.3 +MLINKS+=sha1.3 SHA1Transform.3 sha1.3 SHA1Init.3 sha1.3 SHA1Final.3 +MLINKS+=sha1.3 SHA1Update.3 sha1.3 SHA1End.3 sha1.3 SHA1File.3 +MLINKS+=sha1.3 SHA1FileChunk.3 sha1.3 SHA1Pad.3 sha1.3 SHA1Data.3 MLINKS+=sha2.3 SHA256_Init.3 sha2.3 SHA256_Update.3 sha2.3 SHA256_Final.3 MLINKS+=sha2.3 SHA256_End.3 sha2.3 SHA256_File.3 sha2.3 SHA256_Data.3 +MLINKS+=sha2.3 SHA256_Pad.3 sha2.3 SHA256_FileChunk.3 MLINKS+=sha2.3 SHA384_Init.3 sha2.3 SHA384_Update.3 sha2.3 SHA384_Final.3 MLINKS+=sha2.3 SHA384_End.3 sha2.3 SHA384_File.3 sha2.3 SHA384_Data.3 +MLINKS+=sha2.3 SHA384_Pad.3 sha2.3 SHA384_FileChunk.3 MLINKS+=sha2.3 SHA512_Init.3 sha2.3 SHA512_Update.3 sha2.3 SHA512_Final.3 MLINKS+=sha2.3 SHA512_End.3 sha2.3 SHA512_File.3 sha2.3 SHA512_Data.3 +MLINKS+=sha2.3 SHA512_Pad.3 sha2.3 SHA512_FileChunk.3 CLEANFILES+= ${HELPER} md[45].3 .ifndef NOMAN diff --git a/lib/libc/hash/helper.c b/lib/libc/hash/helper.c index a1fd763f78d..5735e851813 100644 --- a/lib/libc/hash/helper.c +++ b/lib/libc/hash/helper.c @@ -1,4 +1,4 @@ -/* $OpenBSD: helper.c,v 1.4 2004/04/29 15:51:16 millert Exp $ */ +/* $OpenBSD: helper.c,v 1.5 2004/05/03 17:30:14 millert Exp $ */ /* * ---------------------------------------------------------------------------- @@ -10,10 +10,10 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$OpenBSD: helper.c,v 1.4 2004/04/29 15:51:16 millert Exp $"; +static const char rcsid[] = "$OpenBSD: helper.c,v 1.5 2004/05/03 17:30:14 millert Exp $"; #endif /* LIBC_SCCS and not lint */ -#include <sys/types.h> +#include <sys/param.h> #include <errno.h> #include <fcntl.h> @@ -46,24 +46,36 @@ HASHEnd(HASH_CTX *ctx, char *buf) } char * -HASHFile(char *filename, char *buf) +HASHFileChunk(char *filename, char *buf, off_t off, off_t len) { u_char buffer[BUFSIZ]; HASH_CTX ctx; - int fd, num, save_errno; + int fd, save_errno; + ssize_t nr; HASHInit(&ctx); if ((fd = open(filename, O_RDONLY)) < 0) return (NULL); + if (off > 0 && lseek(fd, off, SEEK_SET) < 0) + return (NULL); - while ((num = read(fd, buffer, sizeof(buffer))) > 0) - HASHUpdate(&ctx, buffer, num); + while ((nr = read(fd, buffer, MIN(sizeof(buffer), len))) > 0) { + HASHUpdate(&ctx, buffer, (size_t)nr); + if (len > 0 && (len -= nr) == 0) + break; + } save_errno = errno; close(fd); errno = save_errno; - return (num < 0 ? NULL : HASHEnd(&ctx, buf)); + return (nr < 0 ? NULL : HASHEnd(&ctx, buf)); +} + +char * +HASHFile(char *filename, char *buf) +{ + return (HASHFileChunk(filename, buf, (off_t)0, (off_t)0)); } char * diff --git a/lib/libc/hash/md4.c b/lib/libc/hash/md4.c index c795722d196..da92290cff0 100644 --- a/lib/libc/hash/md4.c +++ b/lib/libc/hash/md4.c @@ -1,4 +1,4 @@ -/* $OpenBSD: md4.c,v 1.3 2004/04/29 18:45:39 millert Exp $ */ +/* $OpenBSD: md4.c,v 1.4 2004/05/03 17:30:14 millert Exp $ */ /* * This code implements the MD4 message-digest algorithm. @@ -19,7 +19,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$OpenBSD: md4.c,v 1.3 2004/04/29 18:45:39 millert Exp $"; +static const char rcsid[] = "$OpenBSD: md4.c,v 1.4 2004/05/03 17:30:14 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/types.h> @@ -69,10 +69,10 @@ MD4Init(MD4_CTX *ctx) void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len) { - u_int32_t have, need; + size_t have, need; /* Check how many bytes we already have and how many more we need. */ - have = (u_int32_t)((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1)); + have = (size_t)((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1)); need = MD4_BLOCK_LENGTH - have; /* Update bitcount */ @@ -101,15 +101,14 @@ MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len) } /* - * Final wrapup - pad to 64-byte boundary with the bit pattern + * Pad pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ void -MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx) +MD4Pad(MD4_CTX *ctx) { u_int8_t count[8]; - u_int32_t padlen; - int i; + size_t padlen; /* Convert count to 8 bytes in little endian order. */ PUT_64BIT_LE(count, ctx->count); @@ -121,7 +120,17 @@ MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx) padlen += MD4_BLOCK_LENGTH; MD4Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ MD4Update(ctx, count, 8); +} + +/* + * Final wrapup--call MD4Pad, fill in digest and zero out ctx. + */ +void +MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx) +{ + int i; + MD4Pad(ctx); if (digest != NULL) { for (i = 0; i < 4; i++) PUT_32BIT_LE(digest + i * 4, ctx->state[i]); diff --git a/lib/libc/hash/md5.c b/lib/libc/hash/md5.c index 492559d1fbe..c7d8a96ded0 100644 --- a/lib/libc/hash/md5.c +++ b/lib/libc/hash/md5.c @@ -1,4 +1,4 @@ -/* $OpenBSD: md5.c,v 1.4 2004/04/29 18:38:23 millert Exp $ */ +/* $OpenBSD: md5.c,v 1.5 2004/05/03 17:30:14 millert Exp $ */ /* * This code implements the MD5 message-digest algorithm. @@ -18,7 +18,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$OpenBSD: md5.c,v 1.4 2004/04/29 18:38:23 millert Exp $"; +static const char rcsid[] = "$OpenBSD: md5.c,v 1.5 2004/05/03 17:30:14 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/types.h> @@ -68,10 +68,10 @@ MD5Init(MD5_CTX *ctx) void MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len) { - u_int32_t have, need; + size_t have, need; /* Check how many bytes we already have and how many more we need. */ - have = (u_int32_t)((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1)); + have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1)); need = MD5_BLOCK_LENGTH - have; /* Update bitcount */ @@ -100,15 +100,14 @@ MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len) } /* - * Final wrapup - pad to 64-byte boundary with the bit pattern + * Pad pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ void -MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx) +MD5Pad(MD5_CTX *ctx) { u_int8_t count[8]; - u_int32_t padlen; - int i; + size_t padlen; /* Convert count to 8 bytes in little endian order. */ PUT_64BIT_LE(count, ctx->count); @@ -120,7 +119,17 @@ MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx) padlen += MD5_BLOCK_LENGTH; MD5Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ MD5Update(ctx, count, 8); +} + +/* + * Final wrapup--call MD5Pad, fill in digest and zero out ctx. + */ +void +MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx) +{ + int i; + MD5Pad(ctx); if (digest != NULL) { for (i = 0; i < 4; i++) PUT_32BIT_LE(digest + i * 4, ctx->state[i]); diff --git a/lib/libc/hash/mdX.3 b/lib/libc/hash/mdX.3 index a5dcb19ec51..a0cfbd08f7f 100644 --- a/lib/libc/hash/mdX.3 +++ b/lib/libc/hash/mdX.3 @@ -6,7 +6,7 @@ .\" this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp .\" ---------------------------------------------------------------------------- .\" -.\" $OpenBSD: mdX.3,v 1.3 2004/04/29 15:51:16 millert Exp $ +.\" $OpenBSD: mdX.3,v 1.4 2004/05/03 17:30:14 millert Exp $ .\" .Dd April 29, 2004 .Dt MDX 3 @@ -14,10 +14,12 @@ .Sh NAME .Nm MDXInit , .Nm MDXUpdate , +.Nm MDXPad , .Nm MDXFinal , .Nm MDXTransform , .Nm MDXEnd , .Nm MDXFile , +.Nm MDXFileChunk , .Nm MDXData .Nd calculate the RSA Data Security, Inc., ``MDX'' message digest .Sh SYNOPSIS @@ -28,6 +30,8 @@ .Ft void .Fn MDXUpdate "MDX_CTX *context" "const unsigned char *data" "unsigned int len" .Ft void +.Fn MDXPad "MDX_CTX *context" +.Ft void .Fn MDXFinal "u_int8_t digest[MDX_DIGEST_LENGTH]" "MDX_CTX *context" .Ft void .Fn MDXTransform "u_int32_t state[4]" "u_int8_t block[MDX_BLOCK_LENGTH]" @@ -36,6 +40,8 @@ .Ft "char *" .Fn MDXFile "char *filename" "char *buf" .Ft "char *" +.Fn MDXFileChunk "char *filename" "char *buf" "off_t offset" "off_t length" +.Ft "char *" .Fn MDXData "const u_int8_t *data" "size_t len" "char *buf" .Sh DESCRIPTION The MDX functions calculate a 128-bit cryptographic checksum (digest) @@ -70,10 +76,12 @@ run over the data with .Fn MDXUpdate , and finally extract the result using .Fn MDXFinal . -When a null pointer is passed to -.Fn MDXFinal -as first argument only the final padding will be applied and the -current context can still be used with +.Pp +The +.Fn MDXPad +function can be used to apply padding to the message digest as in +.Fn MDXFinal , +but the current context can still be used with .Fn MDXUpdate . .Pp The @@ -103,6 +111,23 @@ calculates the digest of a file, and uses .Fn MDXEnd to return the result. If the file cannot be opened, a null pointer is returned. +.Pp +.Fn MDXFileChunk +behaves like +.Fn MDXFile +but calculates the digest only for that portion of the file starting at +.Fa offset +and continuing for +.Fa length +bytes or until end of file is reached, whichever comes first. +A zero +.Fa length +can be specified to read until end of file. +A negative +.Fa length +or +.Fa offset +will be ignored. .Fn MDXData calculates the digest of a chunk of data in memory, and uses .Fn MDXEnd @@ -111,6 +136,7 @@ to return the result. When using .Fn MDXEnd , .Fn MDXFile , +.Fn MDXFileChunk , or .Fn MDXData , the @@ -170,14 +196,15 @@ These functions appeared in The original MDX routines were developed by .Tn RSA Data Security, Inc., and published in the above references. -This code is derived from a public domain implementation by Colin Plumb. +This code is derived from a public domain implementation written by Colin Plumb. .Pp The .Fn MDXEnd , .Fn MDXFile , +.Fn MDXFileChunk , and .Fn MDXData -helper functions were written by Poul-Henning Kamp. +helper functions are derived from code written by Poul-Henning Kamp. .Sh BUGS Hans Dobbertin has shown collisions for the full version of MD4 and found a collision in the compress function of MD5. diff --git a/lib/libc/hash/rmd160.3 b/lib/libc/hash/rmd160.3 index bcb6714a375..1d685ed0d24 100644 --- a/lib/libc/hash/rmd160.3 +++ b/lib/libc/hash/rmd160.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: rmd160.3,v 1.23 2004/04/29 15:51:16 millert Exp $ +.\" $OpenBSD: rmd160.3,v 1.24 2004/05/03 17:30:14 millert Exp $ .\" .\" Copyright (c) 1997, 2004 Todd C. Miller <Todd.Miller@courtesan.com> .\" @@ -23,10 +23,12 @@ .Sh NAME .Nm RMD160Init , .Nm RMD160Update , +.Nm RMD160Pad , .Nm RMD160Final , .Nm RMD160Transform , .Nm RMD160End , .Nm RMD160File , +.Nm RMD160FileChunk , .Nm RMD160Data .Nd calculate the ``RIPEMD-160'' message digest .Sh SYNOPSIS @@ -37,6 +39,8 @@ .Ft void .Fn RMD160Update "RMD160_CTX *context" "const u_int8_t *data" "u_int32_t nbytes" .Ft void +.Fn RMD160Pad "RMD160_CTX *context" +.Ft void .Fn RMD160Final "u_int8_t digest[RMD160_DIGEST_LENGTH]" "RMD160_CTX *context" .Ft void .Fn RMD160Transform "u_int32_t state[5]" "const u_int8_t block[RMD160_BLOCK_LENGTH]" @@ -45,6 +49,8 @@ .Ft "char *" .Fn RMD160File "char *filename" "char *buf" .Ft "char *" +.Fn RMD160FileChunk "char *filename" "char *buf" "off_t offset" "off_t length" +.Ft "char *" .Fn RMD160Data "const u_int8_t *data" "size_t len" "char *buf" .Sh DESCRIPTION The RMD160 functions implement the 160-bit RIPE message digest hash algorithm @@ -86,10 +92,12 @@ is called when all data has been added via and stores a message digest in the .Ar digest parameter. -When a null pointer is passed to -.Fn RMD160Final -as first argument only the final padding will be applied and the -current context can still be used with +.Pp +The +.Fn RMD160Pad +function can be used to apply padding to the message digest as in +.Fn RMD160Final , +but the current context can still be used with .Fn RMD160Update . .Pp The @@ -122,6 +130,23 @@ If .Fn RMD160File is unable to open the file a NULL pointer is returned. .Pp +.Fn RMD160FileChunk +behaves like +.Fn RMD160File +but calculates the digest only for that portion of the file starting at +.Fa offset +and continuing for +.Fa length +bytes or until end of file is reached, whichever comes first. +A zero +.Fa length +can be specified to read until end of file. +A negative +.Fa length +or +.Fa offset +will be ignored. +.Pp The .Fn RMD160Data function @@ -203,6 +228,7 @@ This implementation of RMD-160 was written by Markus Friedl. The .Fn RMD160End , .Fn RMD160File , +.Fn RMD160FileChunk , and .Fn RMD160Data helper functions are derived from code written by Poul-Henning Kamp. diff --git a/lib/libc/hash/rmd160.c b/lib/libc/hash/rmd160.c index e38843dead5..3da1781c679 100644 --- a/lib/libc/hash/rmd160.c +++ b/lib/libc/hash/rmd160.c @@ -32,7 +32,7 @@ #include <rmd160.h> #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: rmd160.c,v 1.14 2004/04/26 19:38:12 millert Exp $"; +static char rcsid[] = "$OpenBSD: rmd160.c,v 1.15 2004/05/03 17:30:15 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #define PUT_64BIT_LE(cp, value) do { \ @@ -104,9 +104,9 @@ RMD160Init(RMD160_CTX *ctx) } void -RMD160Update(RMD160_CTX *ctx, const u_char *input, u_int32_t len) +RMD160Update(RMD160_CTX *ctx, const u_char *input, size_t len) { - u_int32_t have, off, need; + size_t have, off, need; have = (ctx->count / 8) % RMD160_BLOCK_LENGTH; need = RMD160_BLOCK_LENGTH - have; @@ -131,11 +131,10 @@ RMD160Update(RMD160_CTX *ctx, const u_char *input, u_int32_t len) } void -RMD160Final(u_char digest[RMD160_DIGEST_LENGTH], RMD160_CTX *ctx) +RMD160Pad(RMD160_CTX *ctx) { - int i; - u_char size[8]; - u_int32_t padlen; + u_int8_t size[8]; + size_t padlen; PUT_64BIT_LE(size, ctx->count); @@ -148,7 +147,14 @@ RMD160Final(u_char digest[RMD160_DIGEST_LENGTH], RMD160_CTX *ctx) padlen += RMD160_BLOCK_LENGTH; RMD160Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ RMD160Update(ctx, size, 8); +} + +void +RMD160Final(u_char digest[RMD160_DIGEST_LENGTH], RMD160_CTX *ctx) +{ + int i; + RMD160Pad(ctx); if (digest != NULL) for (i = 0; i < 5; i++) PUT_32BIT_LE(digest + i*4, ctx->state[i]); diff --git a/lib/libc/hash/sha1.3 b/lib/libc/hash/sha1.3 index 937423cb9d3..28c166d18e8 100644 --- a/lib/libc/hash/sha1.3 +++ b/lib/libc/hash/sha1.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sha1.3,v 1.29 2004/04/29 15:51:16 millert Exp $ +.\" $OpenBSD: sha1.3,v 1.30 2004/05/03 17:30:15 millert Exp $ .\" .\" Copyright (c) 1997, 2004 Todd C. Miller <Todd.Miller@courtesan.com> .\" @@ -23,10 +23,12 @@ .Sh NAME .Nm SHA1Init , .Nm SHA1Update , +.Nm SHA1Pad , .Nm SHA1Final , .Nm SHA1Transform , .Nm SHA1End , .Nm SHA1File , +.Nm SHA1FileChunk , .Nm SHA1Data .Nd calculate the NIST Secure Hash Algorithm .Sh SYNOPSIS @@ -37,6 +39,8 @@ .Ft void .Fn SHA1Update "SHA1_CTX *context" "const u_int8_t *data" "u_int len" .Ft void +.Fn SHA1Pad "SHA1_CTX *context" +.Ft void .Fn SHA1Final "u_int8_t digest[SHA1_DIGEST_LENGTH]" "SHA1_CTX *context" .Ft void .Fn SHA1Transform "u_int32_t state[5]" "u_int8_t buffer[SHA1_BLOCK_LENGTH]" @@ -45,6 +49,8 @@ .Ft "char *" .Fn SHA1File "char *filename" "char *buf" .Ft "char *" +.Fn SHA1FileChunk "char *filename" "char *buf" "off_t offset" "off_t length" +.Ft "char *" .Fn SHA1Data "const u_int8_t *data" "size_t len" "char *buf" .Sh DESCRIPTION The SHA1 functions implement the NIST Secure Hash Algorithm (SHA-1), @@ -83,10 +89,12 @@ is called when all data has been added via and stores a message digest in the .Ar digest parameter. -When a null pointer is passed to -.Fn SHA1Final -as first argument only the final padding will be applied and the -current context can still be used with +.Pp +The +.Fn SHA1Pad +function can be used to apply padding to the message digest as in +.Fn SHA1Final , +but the current context can still be used with .Fn SHA1Update . .Pp The @@ -119,6 +127,23 @@ If .Fn SHA1File is unable to open the file a NULL pointer is returned. .Pp +.Fn SHA1FileChunk +behaves like +.Fn SHA1File +but calculates the digest only for that portion of the file starting at +.Fa offset +and continuing for +.Fa length +bytes or until end of file is reached, whichever comes first. +A zero +.Fa length +can be specified to read until end of file. +A negative +.Fa length +or +.Fa offset +will be ignored. +.Pp The .Fn SHA1Data function @@ -194,6 +219,7 @@ This implementation of SHA-1 was written by Steve Reid. The .Fn SHA1End , .Fn SHA1File , +.Fn SHA1FileChunk , and .Fn SHA1Data helper functions are derived from code written by Poul-Henning Kamp. diff --git a/lib/libc/hash/sha1.c b/lib/libc/hash/sha1.c index 847c5e8fd32..8776a8905eb 100644 --- a/lib/libc/hash/sha1.c +++ b/lib/libc/hash/sha1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sha1.c,v 1.15 2004/04/27 15:54:56 millert Exp $ */ +/* $OpenBSD: sha1.c,v 1.16 2004/05/03 17:30:15 millert Exp $ */ /* * SHA-1 in C @@ -15,7 +15,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: sha1.c,v 1.15 2004/04/27 15:54:56 millert Exp $"; +static char rcsid[] = "$OpenBSD: sha1.c,v 1.16 2004/05/03 17:30:15 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #define SHA1HANDSOFF /* Copies data before messing with it. */ @@ -131,11 +131,11 @@ SHA1Init(SHA1_CTX *context) * Run your data through this. */ void -SHA1Update(SHA1_CTX *context, const u_char *data, u_int len) +SHA1Update(SHA1_CTX *context, const u_char *data, size_t len) { - u_int i, j; + size_t i, j; - j = (u_int32_t)((context->count >> 3) & 63); + j = (size_t)((context->count >> 3) & 63); context->count += (len << 3); if ((j + len) > 63) { (void)memcpy(&context->buffer[j], data, (i = 64-j)); @@ -154,10 +154,10 @@ SHA1Update(SHA1_CTX *context, const u_char *data, u_int len) * Add padding and return the message digest. */ void -SHA1Final(u_char digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context) +SHA1Pad(SHA1_CTX *context) { + u_int8_t finalcount[8]; u_int i; - u_char finalcount[8]; for (i = 0; i < 8; i++) { finalcount[i] = (u_char)((context->count >> @@ -167,10 +167,18 @@ SHA1Final(u_char digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context) while ((context->count & 504) != 448) SHA1Update(context, (u_char *)"\0", 1); SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ +} + +void +SHA1Final(u_char digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context) +{ + u_int i; + SHA1Pad(context); if (digest) { for (i = 0; i < SHA1_DIGEST_LENGTH; i++) digest[i] = (u_char) ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); } + memset(context, 0, sizeof(*context)); } diff --git a/lib/libc/hash/sha2.3 b/lib/libc/hash/sha2.3 index deabd6f5c98..3d3f77a2475 100644 --- a/lib/libc/hash/sha2.3 +++ b/lib/libc/hash/sha2.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sha2.3,v 1.6 2004/04/29 15:51:16 millert Exp $ +.\" $OpenBSD: sha2.3,v 1.7 2004/05/03 17:30:15 millert Exp $ .\" .\" Copyright (c) 2003, 2004 Todd C. Miller <Todd.Miller@courtesan.com> .\" @@ -26,9 +26,11 @@ .Sh NAME .Nm SHA256_Init , .Nm SHA256_Update , +.Nm SHA256_Pad , .Nm SHA256_Final , .Nm SHA256_End , .Nm SHA256_File , +.Nm SHA256_FileChunk , .Nm SHA256_Data .Nd calculate the NIST Secure Hash Standard (version 2) .Sh SYNOPSIS @@ -39,36 +41,48 @@ .Ft void .Fn SHA256_Update "SHA256_CTX *context" "const u_int8_t *data" "size_t len" .Ft void +.Fn SHA256_Pad "SHA256_CTX *context" +.Ft void .Fn SHA256_Final "u_int8_t digest[SHA256_DIGEST_LENGTH]" "SHA256_CTX *context" .Ft "char *" .Fn SHA256_End "SHA256_CTX *context" "char *buf" .Ft "char *" .Fn SHA256_File "char *filename" "char *buf" .Ft "char *" +.Fn SHA256_FileChunk "char *filename" "char *buf" "off_t offset" "off_t length" +.Ft "char *" .Fn SHA256_Data "u_int8_t *data" "u_int len" "char *buf" .Ft void .Fn SHA384_Init "SHA384_CTX *context" .Ft void .Fn SHA384_Update "SHA384_CTX *context" "const u_int8_t *data" "size_t len" .Ft void +.Fn SHA384_Pad "SHA384_CTX *context" +.Ft void .Fn SHA384_Final "u_int8_t digest[SHA384_DIGEST_LENGTH]" "SHA384_CTX *context" .Ft "char *" .Fn SHA384_End "SHA384_CTX *context" "char *buf" .Ft "char *" .Fn SHA384_File "char *filename" "char *buf" .Ft "char *" +.Fn SHA384_FileChunk "char *filename" "char *buf" "off_t offset" "off_t length" +.Ft "char *" .Fn SHA384_Data "u_int8_t *data" "size_t len" "char *buf" .Ft void .Fn SHA512_Init "SHA512_CTX *context" .Ft void .Fn SHA512_Update "SHA512_CTX *context" "const u_int8_t *data" "size_t len" .Ft void +.Fn SHA512_Pad "SHA512_CTX *context" +.Ft void .Fn SHA512_Final "u_int8_t digest[SHA512_DIGEST_LENGTH]" "SHA512_CTX *context" .Ft "char *" .Fn SHA512_End "SHA512_CTX *context" "char *buf" .Ft "char *" .Fn SHA512_File "char *filename" "char *buf" .Ft "char *" +.Fn SHA512_FileChunk "char *filename" "char *buf" "off_t offset" "off_t length" +.Ft "char *" .Fn SHA512_Data "u_int8_t *data" "size_t len" "char *buf" .Sh DESCRIPTION The SHA2 functions implement the NIST Secure Hash Standard, @@ -110,10 +124,12 @@ is called when all data has been added via and stores a message digest in the .Ar digest parameter. -When a null pointer is passed to -.Fn SHA256_Final -as first argument only the final padding will be applied and the -current context can still be used with +.Pp +The +.Fn SHA256_Pad +function can be used to apply padding to the message digest as in +.Fn SHA256_Final , +but the current context can still be used with .Fn SHA256_Update . .Pp The @@ -132,6 +148,23 @@ If .Fn SHA256_File is unable to open the file, a NULL pointer is returned. .Pp +.Fn SHA256_FileChunk +behaves like +.Fn SHA256_File +but calculates the digest only for that portion of the file starting at +.Fa offset +and continuing for +.Fa length +bytes or until end of file is reached, whichever comes first. +A zero +.Fa length +can be specified to read until end of file. +A negative +.Fa length +or +.Fa offset +will be ignored. +.Pp The .Fn SHA256_Data function @@ -141,6 +174,7 @@ calculates the digest of an arbitrary string and returns the result via For each of the .Fn SHA256_End , .Fn SHA256_File , +.Fn SHA256_FileChunk , and .Fn SHA256_Data functions the @@ -208,6 +242,7 @@ This implementation of the SHA functions was written by Aaron D. Gifford. The .Fn SHA256_End , .Fn SHA256_File , +.Fn SHA256_FileChunk , and .Fn SHA256_Data helper functions are derived from code written by Poul-Henning Kamp. diff --git a/lib/libc/hash/sha2.c b/lib/libc/hash/sha2.c index 1fb85120c68..5809cd0721e 100644 --- a/lib/libc/hash/sha2.c +++ b/lib/libc/hash/sha2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sha2.c,v 1.6 2004/05/03 02:57:47 millert Exp $ */ +/* $OpenBSD: sha2.c,v 1.7 2004/05/03 17:30:15 millert Exp $ */ /* * FILE: sha2.c @@ -35,7 +35,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$OpenBSD: sha2.c,v 1.6 2004/05/03 02:57:47 millert Exp $"; +static const char rcsid[] = "$OpenBSD: sha2.c,v 1.7 2004/05/03 17:30:15 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/types.h> @@ -164,7 +164,6 @@ static const char rcsid[] = "$OpenBSD: sha2.c,v 1.6 2004/05/03 02:57:47 millert * library -- they are intended for private internal visibility/use * only. */ -void SHA512_Last(SHA512_CTX *); void SHA256_Transform(SHA256_CTX *, const u_int8_t *); void SHA512_Transform(SHA512_CTX *, const u_int8_t *); @@ -340,7 +339,7 @@ SHA256_Transform(SHA256_CTX *context, const u_int8_t *data) ROUND256_0_TO_15(b,c,d,e,f,g,h,a); } while (j < 16); - /* Now for the remaining rounds to 64: */ + /* Now for the remaining rounds up to 63: */ do { ROUND256(a,b,c,d,e,f,g,h); ROUND256(h,a,b,c,d,e,f,g); @@ -493,65 +492,74 @@ SHA256_Update(SHA256_CTX *context, const u_int8_t *data, size_t len) } void -SHA256_Final(u_int8_t digest[], SHA256_CTX *context) +SHA256_Pad(SHA256_CTX *context) { - u_int32_t *d = (u_int32_t *)digest; unsigned int usedspace; - /* If no digest buffer is passed, we don't bother doing this: */ - if (digest != NULL) { - usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; + usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; #if BYTE_ORDER == LITTLE_ENDIAN - /* Convert FROM host byte order */ - REVERSE64(context->bitcount,context->bitcount); + /* Convert FROM host byte order */ + REVERSE64(context->bitcount, context->bitcount); #endif - if (usedspace > 0) { - /* Begin padding with a 1 bit: */ - context->buffer[usedspace++] = 0x80; - - if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { - /* Set-up for the last transform: */ - memset(&context->buffer[usedspace], 0, SHA256_SHORT_BLOCK_LENGTH - usedspace); - } else { - if (usedspace < SHA256_BLOCK_LENGTH) { - memset(&context->buffer[usedspace], 0, SHA256_BLOCK_LENGTH - usedspace); - } - /* Do second-to-last transform: */ - SHA256_Transform(context, context->buffer); - - /* And set-up for the last transform: */ - memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); - } - } else { + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { /* Set-up for the last transform: */ - memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); + memset(&context->buffer[usedspace], 0, + SHA256_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < SHA256_BLOCK_LENGTH) { + memset(&context->buffer[usedspace], 0, + SHA256_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + SHA256_Transform(context, context->buffer); - /* Begin padding with a 1 bit: */ - *context->buffer = 0x80; + /* Prepare for last transform: */ + memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); } - /* Set the bit count: */ - *(u_int64_t *)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount; + } else { + /* Set-up for the last transform: */ + memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); - /* Final transform: */ - SHA256_Transform(context, context->buffer); + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Store the length of input data (in bits): */ + *(u_int64_t *)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount; + + /* Final transform: */ + SHA256_Transform(context, context->buffer); + /* Clean up: */ + usedspace = 0; +} + +void +SHA256_Final(u_int8_t digest[], SHA256_CTX *context) +{ + u_int32_t *d = (u_int32_t *)digest; + + SHA256_Pad(context); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != NULL) { #if BYTE_ORDER == LITTLE_ENDIAN - { - /* Convert TO host byte order */ - int j; - for (j = 0; j < 8; j++) { - REVERSE32(context->state[j],context->state[j]); - *d++ = context->state[j]; - } + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + REVERSE32(context->state[j], context->state[j]); + *d++ = context->state[j]; } #else memcpy(d, context->state, SHA256_DIGEST_LENGTH); #endif } - /* Clean up state data: */ + /* Zero out state data */ memset(context, 0, sizeof(*context)); - usedspace = 0; } @@ -599,9 +607,11 @@ void SHA512_Transform(SHA512_CTX *context, const u_int8_t *data) { u_int64_t a, b, c, d, e, f, g, h, s0, s1; - u_int64_t T1, *W512 = (u_int64_t *)context->buffer; + u_int64_t T1, *W512; int j; + W512 = (u_int64_t *)context->buffer; + /* Initialize registers with the prev. intermediate value */ a = context->state[0]; b = context->state[1]; @@ -614,6 +624,7 @@ SHA512_Transform(SHA512_CTX *context, const u_int8_t *data) j = 0; do { + /* Rounds 0 to 15 (unrolled): */ ROUND512_0_TO_15(a,b,c,d,e,f,g,h); ROUND512_0_TO_15(h,a,b,c,d,e,f,g); ROUND512_0_TO_15(g,h,a,b,c,d,e,f); @@ -656,9 +667,11 @@ void SHA512_Transform(SHA512_CTX *context, const u_int8_t *data) { u_int64_t a, b, c, d, e, f, g, h, s0, s1; - u_int64_t T1, T2, *W512 = (u_int64_t *)context->buffer; + u_int64_t T1, T2, *W512; int j; + W512 = (u_int64_t *)context->buffer; + /* Initialize registers with the prev. intermediate value */ a = context->state[0]; b = context->state[1]; @@ -777,7 +790,7 @@ SHA512_Update(SHA512_CTX *context, const u_int8_t *data, size_t len) } void -SHA512_Last(SHA512_CTX *context) +SHA512_Pad(SHA512_CTX *context) { unsigned int usedspace; @@ -817,6 +830,9 @@ SHA512_Last(SHA512_CTX *context) /* Final transform: */ SHA512_Transform(context, context->buffer); + + /* Clean up: */ + usedspace = 0; } void @@ -824,19 +840,16 @@ SHA512_Final(u_int8_t digest[], SHA512_CTX *context) { u_int64_t *d = (u_int64_t *)digest; + SHA512_Pad(context); + /* If no digest buffer is passed, we don't bother doing this: */ if (digest != NULL) { - SHA512_Last(context); - - /* Save the hash data for output: */ #if BYTE_ORDER == LITTLE_ENDIAN - { - /* Convert TO host byte order */ - int j; - for (j = 0; j < 8; j++) { - REVERSE64(context->state[j],context->state[j]); - *d++ = context->state[j]; - } + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + REVERSE64(context->state[j],context->state[j]); + *d++ = context->state[j]; } #else memcpy(d, context->state, SHA512_DIGEST_LENGTH); @@ -865,24 +878,23 @@ SHA384_Update(SHA384_CTX *context, const u_int8_t *data, size_t len) SHA512_Update((SHA512_CTX *)context, data, len); } +__weak_alias(SHA384_Pad, SHA512_Pad); + void SHA384_Final(u_int8_t digest[], SHA384_CTX *context) { u_int64_t *d = (u_int64_t *)digest; + SHA384_Pad(context); + /* If no digest buffer is passed, we don't bother doing this: */ if (digest != NULL) { - SHA512_Last((SHA512_CTX *)context); - - /* Save the hash data for output: */ #if BYTE_ORDER == LITTLE_ENDIAN - { - /* Convert TO host byte order */ - int j; - for (j = 0; j < 6; j++) { - REVERSE64(context->state[j],context->state[j]); - *d++ = context->state[j]; - } + /* Convert TO host byte order */ + int j; + for (j = 0; j < 6; j++) { + REVERSE64(context->state[j],context->state[j]); + *d++ = context->state[j]; } #else memcpy(d, context->state, SHA384_DIGEST_LENGTH); |