commit 8f403aa7a888dc9fea38a61e214681f4de4bc05f
Author: Peter Avalos <pavalos@dragonflybsd.org>
Date:   Sun Dec 19 00:32:24 2010 -1000

    Add SHA384 functions to libmd.

diff --git a/lib/libmd/Makefile b/lib/libmd/Makefile
index c7b2d04..3f8273a 100644
--- a/lib/libmd/Makefile
+++ b/lib/libmd/Makefile
@@ -9,7 +9,7 @@ SRCS=	md2c.c md4c.c md5c.c md2hl.c md4hl.c md5hl.c \
 INCS=	md2.h md4.h md5.h ripemd.h sha.h sha256.h sha512.h
 WARNS?=	2
 
-MAN+=	md2.3 md4.3 md5.3 ripemd.3 sha.3 sha256.3 sha512.3
+MAN+=	md2.3 md4.3 md5.3 ripemd.3 sha.3 sha256.3 sha384.3 sha512.3
 MLINKS+=md2.3 MD2Init.3 md2.3 MD2Update.3 md2.3 MD2Pad.3 md2.3 MD2Final.3
 MLINKS+=md2.3 MD2End.3  md2.3 MD2File.3   md2.3 MD2FileChunk.3
 MLINKS+=md2.3 MD2Data.3
@@ -33,6 +33,8 @@ MLINKS+=sha256.3 SHA256_Init.3  sha256.3 SHA256_Update.3
 MLINKS+=sha256.3 SHA256_Final.3 sha256.3 SHA256_End.3
 MLINKS+=sha256.3 SHA256_File.3  sha256.3 SHA256_FileChunk.3
 MLINKS+=sha256.3 SHA256_Data.3
+MLINKS+=sha384.3 SHA384_Init.3 sha384.3 SHA384_Update.3
+MLINKS+=sha384.3 SHA384_Final.3
 MLINKS+=sha512.3 SHA512_Init.3  sha512.3 SHA512_Update.3
 MLINKS+=sha512.3 SHA512_Final.3 sha512.3 SHA512_End.3
 MLINKS+=sha512.3 SHA512_File.3  sha512.3 SHA512_FileChunk.3                                               
diff --git a/lib/libmd/sha384.3 b/lib/libmd/sha384.3
new file mode 100644
index 0000000..f0e459b
--- /dev/null
+++ b/lib/libmd/sha384.3
@@ -0,0 +1,77 @@
+.\"
+.\" ----------------------------------------------------------------------------
+.\" "THE BEER-WARE LICENSE" (Revision 42):
+.\" <phk@FreeBSD.org> 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
+.\" ----------------------------------------------------------------------------
+.\"
+.\" 	From: Id: mdX.3,v 1.14 1999/02/11 20:31:49 wollman Exp
+.\" $FreeBSD: src/lib/libmd/sha512.3,v 1.4 2005/11/17 13:00:00 ru Exp $
+.\" $DragonFly: src/lib/libmd/sha512.3,v 1.2 2008/09/11 20:25:34 swildner Exp $
+.\"
+.Dd July 4, 2010
+.Dt SHA384 3
+.Os
+.Sh NAME
+.Nm SHA384_Init ,
+.Nm SHA384_Update ,
+.Nm SHA384_Final
+.Nd calculate the FIPS 180-2 ``SHA-384'' message digest
+.Sh LIBRARY
+.Lb libmd
+.Sh SYNOPSIS
+.In sys/types.h
+.In sha512.h
+.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_Final "u_int8_t digest[48]" "SHA384_CTX *context"
+.Sh DESCRIPTION
+The
+.Li SHA384_
+functions calculate a 384-bit cryptographic checksum (digest)
+for any number of input bytes.
+A cryptographic checksum is a one-way
+hash function; that is, it is computationally impractical to find
+the input corresponding to a particular output.
+This net result is
+a
+.Dq fingerprint
+of the input-data, which does not disclose the actual input.
+.Pp
+The
+.Fn SHA384_Init ,
+.Fn SHA384_Update ,
+and
+.Fn SHA384_Final
+functions are the core functions.
+Allocate an
+.Vt SHA384_CTX ,
+initialize it with
+.Fn SHA384_Init ,
+run over the data with
+.Fn SHA384_Update ,
+and finally extract the result using
+.Fn SHA384_Final .
+.Pp
+.Sh SEE ALSO
+.Xr md2 3 ,
+.Xr md4 3 ,
+.Xr md5 3 ,
+.Xr ripemd 3 ,
+.Xr sha 3
+.Sh HISTORY
+These functions appeared in
+.Dx 2.9 .
+.Sh AUTHORS
+The core hash routines were implemented by Colin Percival based on
+the published
+.Tn FIPS 180-2
+standard.
+.Sh BUGS
+No method is known to exist which finds two files having the same hash value,
+nor to find a file with a specific hash value.
+There is on the other hand no guarantee that such a method does not exist.
diff --git a/lib/libmd/sha512.h b/lib/libmd/sha512.h
index eeaf339..dc8c68c 100644
--- a/lib/libmd/sha512.h
+++ b/lib/libmd/sha512.h
@@ -31,6 +31,9 @@
 #define _SHA512_H_
 
 #include <sys/types.h>
+#define SHA384_BLOCK_LENGTH		128
+#define SHA384_DIGEST_LENGTH		48
+#define SHA384_DIGEST_STRING_LENGTH	(SHA384_DIGEST_LENGTH * 2 + 1)
 #define SHA512_BLOCK_LENGTH		128
 #define SHA512_DIGEST_LENGTH		64
 #define SHA512_DIGEST_STRING_LENGTH	(SHA512_DIGEST_LENGTH * 2 + 1)
@@ -41,8 +44,12 @@ typedef struct _SHA512_CTX {
 	u_int8_t	buffer[SHA512_BLOCK_LENGTH];
 } SHA512_CTX;
 
+typedef SHA512_CTX SHA384_CTX;
 
 __BEGIN_DECLS
+void	SHA384_Init(SHA384_CTX *);
+void	SHA384_Update(SHA384_CTX *, const u_int8_t *, size_t);
+void	SHA384_Final(u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX *);
 void	SHA512_Init(SHA512_CTX*);
 void	SHA512_Update(SHA512_CTX*, const void *, size_t);
 void	SHA512_Final(unsigned char [SHA512_DIGEST_LENGTH], SHA512_CTX *);
diff --git a/lib/libmd/sha512c.c b/lib/libmd/sha512c.c
index 4f3bb48..da8d616 100644
--- a/lib/libmd/sha512c.c
+++ b/lib/libmd/sha512c.c
@@ -94,6 +94,18 @@ typedef u_int8_t  sha2_byte;	/* Exactly 1 byte */
 typedef u_int32_t sha2_word32;	/* Exactly 4 bytes */
 typedef u_int64_t sha2_word64;	/* Exactly 8 bytes */
 
+/* Initial hash value H for SHA-384 */
+static const sha2_word64 sha384_initial_hash_value[8] = {
+	0xcbbb9d5dc1059ed8ULL,
+	0x629a292a367cd507ULL,
+	0x9159015a3070dd17ULL,
+	0x152fecd8f70e5939ULL,
+	0x67332667ffc00b31ULL,
+	0x8eb44a8768581511ULL,
+	0xdb0c2e0d64f98fa7ULL,
+	0x47b5481dbefa4fa4ULL
+};
+
 /* Initial hash value H for SHA-512 */
 static const sha2_word64 sha512_initial_hash_value[8] = {
 	0x6a09e667f3bcc908ULL,
@@ -409,3 +421,78 @@ char* SHA512_Data(const void *data, size_t len, char *digest) {
 #endif
 
 
+/*** SHA-384: *********************************************************/
+void SHA384_Init(SHA384_CTX* context) {
+	if (context == NULL) {
+		return;
+	}
+	bcopy(sha384_initial_hash_value, context->state, SHA512_DIGEST_LENGTH);
+	bzero(context->buffer, SHA384_BLOCK_LENGTH);
+	context->bitcount[0] = context->bitcount[1] = 0;
+}
+
+void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) {
+	SHA512_Update((SHA512_CTX*)context, data, len);
+}
+
+void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
+	sha2_word64	*d = (sha2_word64*)digest;
+
+	/* Sanity check: */
+	assert(context != NULL);
+
+	/* 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];
+			}
+		}
+#else
+		bcopy(context->state, d, SHA384_DIGEST_LENGTH);
+#endif
+	}
+
+	/* Zero out state data */
+	bzero(context, sizeof(*context));
+}
+
+#if 0
+char *SHA384_End(SHA384_CTX* context, char buffer[]) {
+	sha2_byte	digest[SHA384_DIGEST_LENGTH], *d = digest;
+	int		i;
+
+	/* Sanity check: */
+	assert(context != NULL);
+
+	if (buffer != NULL) {
+		SHA384_Final(digest, context);
+
+		for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+			*buffer++ = sha2_hex_digits[*d & 0x0f];
+			d++;
+		}
+		*buffer = (char)0;
+	} else {
+		bzero(context, sizeof(*context));
+	}
+	bzero(digest, SHA384_DIGEST_LENGTH);
+	return buffer;
+}
+
+char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) {
+	SHA384_CTX	context;
+
+	SHA384_Init(&context);
+	SHA384_Update(&context, data, len);
+	return SHA384_End(&context, digest);
+}
+#endif
