summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2004-05-03 17:30:16 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2004-05-03 17:30:16 +0000
commit92c35e1d3a72a9dcbb1608827e7a8a87a5665cee (patch)
tree4efbbda5a46ebcdc9e9acc0262a5e1a5ee588aa7 /lib
parent3ce312b75c1e80c476cd991ad38c1782f4893aaf (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.inc30
-rw-r--r--lib/libc/hash/helper.c28
-rw-r--r--lib/libc/hash/md4.c25
-rw-r--r--lib/libc/hash/md5.c25
-rw-r--r--lib/libc/hash/mdX.341
-rw-r--r--lib/libc/hash/rmd160.336
-rw-r--r--lib/libc/hash/rmd160.c20
-rw-r--r--lib/libc/hash/sha1.336
-rw-r--r--lib/libc/hash/sha1.c22
-rw-r--r--lib/libc/hash/sha2.345
-rw-r--r--lib/libc/hash/sha2.c148
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);