[PATCH 01/15] Replace sys/crypto/sha2/sha2.c with lib/libmd/sha512c.c

Sebastian Huber sebastian.huber at embedded-brains.de
Thu Sep 8 13:27:18 UTC 2022


From: Allan Jude <allanjude at FreeBSD.org>

cperciva's libmd implementation is 5-30% faster

The same was done for SHA256 previously in r263218

cperciva's implementation was lacking SHA-384 which I implemented, validated against OpenSSL and the NIST documentation

Extend sbin/md5 to create sha384(1)

Chase dependancies on sys/crypto/sha2/sha2.{c,h} and replace them with sha512{c.c,.h}

Reviewed by:	cperciva, des, delphij
Approved by:	secteam, bapt (mentor)
MFC after:	2 weeks
Sponsored by:	ScaleEngine Inc.
Differential Revision:	https://reviews.freebsd.org/D3929
---
 cpukit/include/sha256.h | 15 ++++++--
 cpukit/include/sha384.h | 60 ++++++++++++++++++++++++++++++++
 cpukit/include/sha512.h | 16 +++++++--
 cpukit/libmd/sha512c.c  | 77 ++++++++++++++++++++++++++++++++++-------
 4 files changed, 149 insertions(+), 19 deletions(-)
 create mode 100644 cpukit/include/sha384.h

diff --git a/cpukit/include/sha256.h b/cpukit/include/sha256.h
index 1b6a4f4c57..9deed91255 100644
--- a/cpukit/include/sha256.h
+++ b/cpukit/include/sha256.h
@@ -29,22 +29,31 @@
 #ifndef _SHA256_H_
 #define _SHA256_H_
 
+#ifndef _KERNEL
 #include <sys/types.h>
+#endif
+
+#define SHA256_BLOCK_LENGTH		64
+#define SHA256_DIGEST_LENGTH		32
+#define SHA256_DIGEST_STRING_LENGTH	(SHA256_DIGEST_LENGTH * 2 + 1)
 
 typedef struct SHA256Context {
 	uint32_t state[8];
 	uint64_t count;
-	unsigned char buf[64];
+	uint8_t buf[SHA256_BLOCK_LENGTH];
 } SHA256_CTX;
 
 __BEGIN_DECLS
+
 void	SHA256_Init(SHA256_CTX *);
 void	SHA256_Update(SHA256_CTX *, const void *, size_t);
-void	SHA256_Final(unsigned char [32], SHA256_CTX *);
+void	SHA256_Final(unsigned char [SHA256_DIGEST_LENGTH], SHA256_CTX *);
+#ifndef _KERNEL
 char   *SHA256_End(SHA256_CTX *, char *);
+char   *SHA256_Data(const void *, unsigned int, char *);
 char   *SHA256_File(const char *, char *);
 char   *SHA256_FileChunk(const char *, char *, off_t, off_t);
-char   *SHA256_Data(const void *, unsigned int, char *);
+#endif
 __END_DECLS
 
 #endif /* !_SHA256_H_ */
diff --git a/cpukit/include/sha384.h b/cpukit/include/sha384.h
new file mode 100644
index 0000000000..2035d6ff54
--- /dev/null
+++ b/cpukit/include/sha384.h
@@ -0,0 +1,60 @@
+/*-
+ * Copyright 2005 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SHA384_H_
+#define _SHA384_H_
+
+#ifndef _KERNEL
+#include <sys/types.h>
+#endif
+
+#define SHA384_BLOCK_LENGTH		128
+#define SHA384_DIGEST_LENGTH		48
+#define SHA384_DIGEST_STRING_LENGTH	(SHA384_DIGEST_LENGTH * 2 + 1)
+
+typedef struct SHA384Context {
+	uint64_t state[8];
+	uint64_t count[2];
+	uint8_t buf[SHA384_BLOCK_LENGTH];
+} SHA384_CTX;
+
+__BEGIN_DECLS
+
+void	SHA384_Init(SHA384_CTX *);
+void	SHA384_Update(SHA384_CTX *, const void *, size_t);
+void	SHA384_Final(unsigned char [SHA384_DIGEST_LENGTH], SHA384_CTX *);
+#ifndef _KERNEL
+char   *SHA384_End(SHA384_CTX *, char *);
+char   *SHA384_Data(const void *, unsigned int, char *);
+char   *SHA384_File(const char *, char *);
+char   *SHA384_FileChunk(const char *, char *, off_t, off_t);
+#endif
+
+__END_DECLS
+
+#endif /* !_SHA384_H_ */
diff --git a/cpukit/include/sha512.h b/cpukit/include/sha512.h
index 8998f4c5bf..1964562160 100644
--- a/cpukit/include/sha512.h
+++ b/cpukit/include/sha512.h
@@ -29,22 +29,32 @@
 #ifndef _SHA512_H_
 #define _SHA512_H_
 
+#ifndef _KERNEL
 #include <sys/types.h>
+#endif
+
+#define SHA512_BLOCK_LENGTH		128
+#define SHA512_DIGEST_LENGTH		64
+#define SHA512_DIGEST_STRING_LENGTH	(SHA512_DIGEST_LENGTH * 2 + 1)
 
 typedef struct SHA512Context {
 	uint64_t state[8];
 	uint64_t count[2];
-	unsigned char buf[128];
+	uint8_t buf[SHA512_BLOCK_LENGTH];
 } SHA512_CTX;
 
 __BEGIN_DECLS
+
 void	SHA512_Init(SHA512_CTX *);
 void	SHA512_Update(SHA512_CTX *, const void *, size_t);
-void	SHA512_Final(unsigned char [64], SHA512_CTX *);
+void	SHA512_Final(unsigned char [SHA512_DIGEST_LENGTH], SHA512_CTX *);
+#ifndef _KERNEL
 char   *SHA512_End(SHA512_CTX *, char *);
+char   *SHA512_Data(const void *, unsigned int, char *);
 char   *SHA512_File(const char *, char *);
 char   *SHA512_FileChunk(const char *, char *, off_t, off_t);
-char   *SHA512_Data(const void *, unsigned int, char *);
+#endif
+
 __END_DECLS
 
 #endif /* !_SHA512_H_ */
diff --git a/cpukit/libmd/sha512c.c b/cpukit/libmd/sha512c.c
index a4f268045a..7d0e875550 100644
--- a/cpukit/libmd/sha512c.c
+++ b/cpukit/libmd/sha512c.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
 #include <string.h>
 
 #include "sha512.h"
+#include "sha384.h"
 
 #if BYTE_ORDER == BIG_ENDIAN
 
@@ -104,7 +105,7 @@ be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
  * the 512-bit input block to produce a new state.
  */
 static void
-SHA512_Transform(uint64_t * state, const unsigned char block[128])
+SHA512_Transform(uint64_t * state, const unsigned char block[SHA512_BLOCK_LENGTH])
 {
 	uint64_t W[80];
 	uint64_t S[8];
@@ -112,12 +113,12 @@ SHA512_Transform(uint64_t * state, const unsigned char block[128])
 	int i;
 
 	/* 1. Prepare message schedule W. */
-	be64dec_vect(W, block, 128);
+	be64dec_vect(W, block, SHA512_BLOCK_LENGTH);
 	for (i = 16; i < 80; i++)
 		W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
 
 	/* 2. Initialize working variables. */
-	memcpy(S, state, 64);
+	memcpy(S, state, SHA512_DIGEST_LENGTH);
 
 	/* 3. Mix. */
 	RNDr(S, W, 0, 0x428a2f98d728ae22ULL);
@@ -206,7 +207,7 @@ SHA512_Transform(uint64_t * state, const unsigned char block[128])
 		state[i] += S[i];
 }
 
-static const unsigned char PAD[128] = {
+static const unsigned char PAD[SHA512_BLOCK_LENGTH] = {
 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -279,22 +280,22 @@ SHA512_Update(SHA512_CTX * ctx, const void *in, size_t len)
 	ctx->count[0] += bitlen[0];
 
 	/* Handle the case where we don't need to perform any transforms */
-	if (len < 128 - r) {
+	if (len < SHA512_BLOCK_LENGTH - r) {
 		memcpy(&ctx->buf[r], src, len);
 		return;
 	}
 
 	/* Finish the current block */
-	memcpy(&ctx->buf[r], src, 128 - r);
+	memcpy(&ctx->buf[r], src, SHA512_BLOCK_LENGTH - r);
 	SHA512_Transform(ctx->state, ctx->buf);
-	src += 128 - r;
-	len -= 128 - r;
+	src += SHA512_BLOCK_LENGTH - r;
+	len -= SHA512_BLOCK_LENGTH - r;
 
 	/* Perform complete blocks */
-	while (len >= 128) {
+	while (len >= SHA512_BLOCK_LENGTH) {
 		SHA512_Transform(ctx->state, src);
-		src += 128;
-		len -= 128;
+		src += SHA512_BLOCK_LENGTH;
+		len -= SHA512_BLOCK_LENGTH;
 	}
 
 	/* Copy left over data into buffer */
@@ -306,14 +307,64 @@ SHA512_Update(SHA512_CTX * ctx, const void *in, size_t len)
  * and clears the context state.
  */
 void
-SHA512_Final(unsigned char digest[64], SHA512_CTX * ctx)
+SHA512_Final(unsigned char digest[SHA512_DIGEST_LENGTH], SHA512_CTX * ctx)
 {
 
 	/* Add padding */
 	SHA512_Pad(ctx);
 
 	/* Write the hash */
-	be64enc_vect(digest, ctx->state, 64);
+	be64enc_vect(digest, ctx->state, SHA512_DIGEST_LENGTH);
+
+	/* Clear the context state */
+	memset((void *)ctx, 0, sizeof(*ctx));
+}
+
+/*** SHA-384: *********************************************************/
+/*
+ * the SHA384 and SHA512 transforms are identical, so SHA384 is skipped
+ */
+
+/* SHA-384 initialization.  Begins a SHA-384 operation. */
+void
+SHA384_Init(SHA384_CTX * ctx)
+{
+
+	/* Zero bits processed so far */
+	ctx->count[0] = ctx->count[1] = 0;
+
+	/* Magic initialization constants */
+	ctx->state[0] = 0xcbbb9d5dc1059ed8ULL;
+	ctx->state[1] = 0x629a292a367cd507ULL;
+	ctx->state[2] = 0x9159015a3070dd17ULL;
+	ctx->state[3] = 0x152fecd8f70e5939ULL;
+	ctx->state[4] = 0x67332667ffc00b31ULL;
+	ctx->state[5] = 0x8eb44a8768581511ULL;
+	ctx->state[6] = 0xdb0c2e0d64f98fa7ULL;
+	ctx->state[7] = 0x47b5481dbefa4fa4ULL;
+}
+
+/* Add bytes into the SHA-384 hash */
+void
+SHA384_Update(SHA384_CTX * ctx, const void *in, size_t len)
+{
+
+	SHA512_Update((SHA512_CTX *)ctx, in, len);
+}
+
+/*
+ * SHA-384 finalization.  Pads the input data, exports the hash value,
+ * and clears the context state.
+ */
+void
+SHA384_Final(unsigned char digest[SHA384_DIGEST_LENGTH], SHA384_CTX * ctx)
+{
+
+	/* Add padding */
+	SHA512_Pad((SHA512_CTX *)ctx);
+
+	/* Write the hash */
+	be64enc_vect(digest, ctx->state, SHA384_DIGEST_LENGTH);
 
 	/* Clear the context state */
 	memset((void *)ctx, 0, sizeof(*ctx));
-- 
2.35.3



More information about the devel mailing list