sha2: new header <sha2.h>
diff mbox

Message ID 1427350202-281697-1-git-send-email-shawn@churchofgit.com
State New
Headers show

Commit Message

Shawn Landden March 26, 2015, 6:10 a.m. UTC
Export the SHA2 family of functions.

v2
---
 crypt/sha256-block.c |  2 +-
 crypt/sha256-crypt.c |  6 +++---
 crypt/sha256.c       | 51 ++++++++++++++++++++++++++++++++++++---------------
 crypt/sha256.h       | 35 ++++++++++++++++++++++++++++-------
 crypt/sha256test.c   | 11 +++++------
 crypt/sha512-block.c |  2 +-
 crypt/sha512-crypt.c |  6 +++---
 crypt/sha512.c       | 52 ++++++++++++++++++++++++++++++++++++----------------
 crypt/sha512.h       | 34 ++++++++++++++++++++++++++++------
 crypt/sha512test.c   |  9 ++++-----
 include/sha2.h       | 32 ++++++++++++++++++++++++++++++++
 11 files changed, 177 insertions(+), 63 deletions(-)
 create mode 100644 include/sha2.h

Comments

Mike Frysinger March 26, 2015, 6:24 a.m. UTC | #1
On 25 Mar 2015 23:10, Shawn Landden wrote:
> Export the SHA2 family of functions.

you should write a proper ChangeLog entry

> --- /dev/null
> +++ b/include/sha2.h

this file is missing a proper header block (licensing/copyright/etc...)

> +/* 256 bits is 32 bytes
> + * for sha2-224 truncate from end after calling sha256_final()
> + */

GNU style says use full sentences, two spaces at th eend, and cuddle the 
trailing */ marker

> +typedef struct {
> +       char __internal_state[352];

only two spaces indent
-mike
Roland McGrath March 27, 2015, 7:48 p.m. UTC | #2
You haven't said anything to justify the change.  People are giving you
feedback on the implementation details, but that should not be interpreted
as agreement with the effect of the change.  I don't think we have any
desire whatsoever to support new APIs in -lcrypt.  There are other
libraries that provide things like SHA implementations.  Just use those.
Shawn Landden March 27, 2015, 8:08 p.m. UTC | #3

Shawn Landden March 30, 2015, 1:15 a.m. UTC | #4
On Fri, Mar 27, 2015 at 12:48:23PM -0700, Roland McGrath wrote:
> You haven't said anything to justify the change.  People are giving you
> feedback on the implementation details, but that should not be interpreted
> as agreement with the effect of the change.  I don't think we have any
> desire whatsoever to support new APIs in -lcrypt.  There are other
> libraries that provide things like SHA implementations.  Just use those.
I responded to this earlier but it ended up sending an empty message :/

There is alot of duplication of effort on these hash sums and the most commonly used
library for them is OpenSSL, which has infamous licensing issues.
Moreover AFAIK only OpenSSL is mature enough to support Intel and ARM cpu extensions
for SHA2.
Although I am not proposing we add support for SHA1 (which is now considered insecure)
I note that git doesn't support Intel or ARM's cpu extensions for SHA1 even though that
application's performance is heavily dependant on hashes.
We already have to do SHA2 hashes in libcrypt, and by adding CPU acceleration support
we can save applications much duplication of effort. OpenSSL is also quite overkill for applications
that do not want to do AES.

-Shawn

Patch
diff mbox

diff --git a/crypt/sha256-block.c b/crypt/sha256-block.c
index 8a77096..8b391f6 100644
--- a/crypt/sha256-block.c
+++ b/crypt/sha256-block.c
@@ -3,7 +3,7 @@ 
 /* Process LEN bytes of BUFFER, accumulating context into CTX.
    It is assumed that LEN % 64 == 0.  */
 void
-sha256_process_block (const void *buffer, size_t len, struct sha256_ctx *ctx)
+sha256_process_block (const void *buffer, size_t len, sha256_ctx *ctx)
 {
   const uint32_t *words = buffer;
   size_t nwords = len / sizeof (uint32_t);
diff --git a/crypt/sha256-crypt.c b/crypt/sha256-crypt.c
index d90e291..cdefa60 100644
--- a/crypt/sha256-crypt.c
+++ b/crypt/sha256-crypt.c
@@ -68,7 +68,7 @@  typedef int PRBool;
   __sha256_init_ctx (ctxp)
 
 # define sha256_process_bytes(buf, len, ctxp, nss_ctxp) \
-  __sha256_process_bytes(buf, len, ctxp)
+  __sha256_process_bytes(ctxp, buf, len)
 
 # define sha256_finish_ctx(ctxp, nss_ctxp, result) \
   __sha256_finish_ctx (ctxp, result)
@@ -189,8 +189,8 @@  __sha256_crypt_r (key, salt, buffer, buflen)
   NSSLOWHASHContext *nss_ctx = NULL;
   NSSLOWHASHContext *nss_alt_ctx = NULL;
 #else
-  struct sha256_ctx ctx;
-  struct sha256_ctx alt_ctx;
+  sha256_ctx ctx;
+  sha256_ctx alt_ctx;
 #endif
 
   /* Prepare for the real work.  */
diff --git a/crypt/sha256.c b/crypt/sha256.c
index b6db8b2..8512ddc 100644
--- a/crypt/sha256.c
+++ b/crypt/sha256.c
@@ -82,13 +82,13 @@  static const uint32_t K[64] =
   };
 
 void
-sha256_process_block (const void *, size_t, struct sha256_ctx *);
+sha256_process_block (const void *, size_t, sha256_ctx *);
 
 /* Initialize structure containing state of computation.
    (FIPS 180-2:5.3.2)  */
 void
 __sha256_init_ctx (ctx)
-     struct sha256_ctx *ctx;
+     sha256_ctx *ctx;
 {
   ctx->H[0] = 0x6a09e667;
   ctx->H[1] = 0xbb67ae85;
@@ -103,16 +103,9 @@  __sha256_init_ctx (ctx)
   ctx->buflen = 0;
 }
 
-
-/* Process the remaining bytes in the internal buffer and the usual
-   prolog according to the standard and write the result to RESBUF.
-
-   IMPORTANT: On some systems it is required that RESBUF is correctly
-   aligned for a 32 bits value.  */
-void *
-__sha256_finish_ctx (ctx, resbuf)
-     struct sha256_ctx *ctx;
-     void *resbuf;
+void
+__sha256_finish_ctx_generic (ctx)
+     sha256_ctx *ctx;
 {
   /* Take yet unprocessed bytes into account.  */
   uint32_t bytes = ctx->buflen;
@@ -135,20 +128,48 @@  __sha256_finish_ctx (ctx, resbuf)
 
   /* Process last bytes.  */
   sha256_process_block (ctx->buffer, bytes + pad + 8, ctx);
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void
+__sha256_finish_ctx (ctx, resbuf)
+     sha256_ctx *ctx;
+     void *resbuf;
+{
+  __sha256_finish_ctx_generic (ctx)
 
   /* Put result from CTX in first 32 bytes following RESBUF.  */
   for (unsigned int i = 0; i < 8; ++i)
     ((uint32_t *) resbuf)[i] = SWAP (ctx->H[i]);
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
 
-  return resbuf;
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void
+__sha224_finish_ctx (ctx, resbuf)
+     sha256_ctx *ctx;
+     void *resbuf;
+{
+  __sha256_finish_ctx_generic (ctx)
+
+  /* Put result from CTX in first 28 bytes following RESBUF.  */
+  for (unsigned int i = 0; i < 7; ++i)
+    ((uint32_t *) resbuf)[i] = SWAP (ctx->H[i]);
 }
 
 
 void
-__sha256_process_bytes (buffer, len, ctx)
+__sha256_process_bytes (ctx, buffer, len)
+     sha256_ctx *ctx;
      const void *buffer;
      size_t len;
-     struct sha256_ctx *ctx;
 {
   /* When we already have some bits in our internal buffer concatenate
      both inputs first.  */
diff --git a/crypt/sha256.h b/crypt/sha256.h
index 27e0fe6..de427a2 100644
--- a/crypt/sha256.h
+++ b/crypt/sha256.h
@@ -27,7 +27,7 @@ 
 
 
 /* Structure to save state of computation between the single steps.  */
-struct sha256_ctx
+typedef struct
 {
   uint32_t H[8];
 
@@ -38,32 +38,53 @@  struct sha256_ctx
 #define TOTAL64_high (BYTE_ORDER == LITTLE_ENDIAN)
     uint32_t total[2];
   };
-  uint32_t buflen;
   union
   {
     char buffer[128];
     uint32_t buffer32[32];
     uint64_t buffer64[16];
   };
-};
+  uint32_t buflen;
+} sha256_ctx __attribute__((align(16));
 
 /* Initialize structure containing state of computation.
    (FIPS 180-2: 5.3.2)  */
-extern void __sha256_init_ctx (struct sha256_ctx *ctx) __THROW;
+extern void __sha256_init_ctx (sha256_ctx *__restrict ctx) __THROW;
+weak_alias(__sha256_init_ctx, sha256_init)
 
 /* Starting with the result of former calls of this function (or the
    initialization function update the context for the next LEN bytes
    starting at BUFFER.
    It is NOT required that LEN is a multiple of 64.  */
-extern void __sha256_process_bytes (const void *buffer, size_t len,
-				    struct sha256_ctx *ctx) __THROW;
+extern void __sha256_process_bytes (sha256_ctx *__restrict ctx, const void *__restrict buffer,
+				    size_t len) __THROW;
+weak_alias(__sha256_process_bytes, sha256_update)
 
 /* Process the remaining bytes in the buffer and put result from CTX
    in first 32 bytes following RESBUF.
 
    IMPORTANT: On some systems it is required that RESBUF is correctly
    aligned for a 32 bits value.  */
-extern void *__sha256_finish_ctx (struct sha256_ctx *ctx, void *resbuf)
+extern void *__sha256_finish_ctx (sha256_ctx *__restrict ctx, void *__restrict resbuf)
   __THROW;
+weak_alias(__sha256_finish_ctx, sha256_finish)
+
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 28 bytes following RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *__sha224_finish_ctx (sha256_ctx *__restrict ctx, void *__restrict resbuf)
+  __THROW;
+weak_alias(__sha224_finish_ctx, sha224_finish)
+
+extern void *__sha256(const void *__restrict d, size_t n, void *__restrict md) {
+	sha256_ctx ctx;
 
+	sha256_init(&ctx);
+	sha256_update(&ctx, d, n);
+	sha256_finish(&ctx, md);
+	return md;
+}
+weak_alias(__sha512, sha512)
 #endif /* sha256.h */
diff --git a/crypt/sha256test.c b/crypt/sha256test.c
index 39e8030..be46f69 100644
--- a/crypt/sha256test.c
+++ b/crypt/sha256test.c
@@ -44,7 +44,7 @@  static const struct
 int
 main (void)
 {
-  struct sha256_ctx ctx;
+  sha256_ctx ctx;
   char sum[32];
   int result = 0;
   int cnt;
@@ -52,8 +52,7 @@  main (void)
   for (cnt = 0; cnt < (int) (sizeof (tests) / sizeof (tests[0])); ++cnt)
     {
       __sha256_init_ctx (&ctx);
-      __sha256_process_bytes (tests[cnt].input, strlen (tests[cnt].input),
-			      &ctx);
+      __sha256_process_bytes (&ctx, tests[cnt].input, strlen (tests[cnt].input));
       __sha256_finish_ctx (&ctx, sum);
       if (memcmp (tests[cnt].result, sum, 32) != 0)
 	{
@@ -63,7 +62,7 @@  main (void)
 
       __sha256_init_ctx (&ctx);
       for (int i = 0; tests[cnt].input[i] != '\0'; ++i)
-	__sha256_process_bytes (&tests[cnt].input[i], 1, &ctx);
+	__sha256_process_bytes (&ctx, &tests[cnt].input[i], 1);
       __sha256_finish_ctx (&ctx, sum);
       if (memcmp (tests[cnt].result, sum, 32) != 0)
 	{
@@ -77,7 +76,7 @@  main (void)
   memset (buf, 'a', sizeof (buf));
   __sha256_init_ctx (&ctx);
   for (int i = 0; i < 1000; ++i)
-    __sha256_process_bytes (buf, sizeof (buf), &ctx);
+    __sha256_process_bytes (&ctx, buf, sizeof (buf));
   __sha256_finish_ctx (&ctx, sum);
   static const char expected[32] =
     "\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67"
@@ -90,7 +89,7 @@  main (void)
 
   __sha256_init_ctx (&ctx);
   for (int i = 0; i < 100000; ++i)
-    __sha256_process_bytes (buf, 10, &ctx);
+    __sha256_process_bytes (&ctx, buf, 10);
   __sha256_finish_ctx (&ctx, sum);
   if (memcmp (expected, sum, 32) != 0)
     {
diff --git a/crypt/sha512-block.c b/crypt/sha512-block.c
index c542db1..7a7c2b0 100644
--- a/crypt/sha512-block.c
+++ b/crypt/sha512-block.c
@@ -3,7 +3,7 @@ 
 /* Process LEN bytes of BUFFER, accumulating context into CTX.
    It is assumed that LEN % 128 == 0.  */
 void
-sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx)
+sha512_process_block (const void *buffer, size_t len, sha512_ctx *ctx)
 {
   const uint64_t *words = buffer;
   size_t nwords = len / sizeof (uint64_t);
diff --git a/crypt/sha512-crypt.c b/crypt/sha512-crypt.c
index 9c581ab..4cfecea 100644
--- a/crypt/sha512-crypt.c
+++ b/crypt/sha512-crypt.c
@@ -68,7 +68,7 @@  typedef int PRBool;
   __sha512_init_ctx (ctxp)
 
 # define sha512_process_bytes(buf, len, ctxp, nss_ctxp) \
-  __sha512_process_bytes(buf, len, ctxp)
+  __sha512_process_bytes(ctxp, buf, len)
 
 # define sha512_finish_ctx(ctxp, nss_ctxp, result) \
   __sha512_finish_ctx (ctxp, result)
@@ -188,8 +188,8 @@  __sha512_crypt_r (key, salt, buffer, buflen)
   NSSLOWHASHContext *nss_ctx = NULL;
   NSSLOWHASHContext *nss_alt_ctx = NULL;
 #else
-  struct sha512_ctx ctx;
-  struct sha512_ctx alt_ctx;
+  sha512_ctx ctx;
+  sha512_ctx alt_ctx;
 #endif
 
   /* Prepare for the real work.  */
diff --git a/crypt/sha512.c b/crypt/sha512.c
index 608de82..d351f43 100644
--- a/crypt/sha512.c
+++ b/crypt/sha512.c
@@ -102,13 +102,13 @@  static const uint64_t K[80] =
   };
 
 void
-sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx);
+sha512_process_block (const void *buffer, size_t len, sha512_ctx *ctx);
 
 /* Initialize structure containing state of computation.
    (FIPS 180-2:5.3.3)  */
 void
 __sha512_init_ctx (ctx)
-     struct sha512_ctx *ctx;
+     sha512_ctx *ctx;
 {
   ctx->H[0] = UINT64_C (0x6a09e667f3bcc908);
   ctx->H[1] = UINT64_C (0xbb67ae8584caa73b);
@@ -123,16 +123,9 @@  __sha512_init_ctx (ctx)
   ctx->buflen = 0;
 }
 
-
-/* Process the remaining bytes in the internal buffer and the usual
-   prolog according to the standard and write the result to RESBUF.
-
-   IMPORTANT: On some systems it is required that RESBUF is correctly
-   aligned for a 32 bits value.  */
-void *
-__sha512_finish_ctx (ctx, resbuf)
-     struct sha512_ctx *ctx;
-     void *resbuf;
+void
+__sha512_finish_ctx_generic (ct)
+     sha512_ctx *ctx;
 {
   /* Take yet unprocessed bytes into account.  */
   uint64_t bytes = ctx->buflen;
@@ -157,20 +150,47 @@  __sha512_finish_ctx (ctx, resbuf)
 
   /* Process last bytes.  */
   sha512_process_block (ctx->buffer, bytes + pad + 16, ctx);
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 64 bits value.  */
+void
+__sha512_finish_ctx (ctx, resbuf)
+     sha512_ctx *ctx;
+     void *resbuf;
+{
+  __sha512_finish_ctx_generic (ctx);
 
   /* Put result from CTX in first 64 bytes following RESBUF.  */
   for (unsigned int i = 0; i < 8; ++i)
     ((uint64_t *) resbuf)[i] = SWAP (ctx->H[i]);
-
-  return resbuf;
 }
 
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 64 bits value.  */
+void
+__sha384_finish_ctx (ctx, resbuf)
+     sha512_ctx *ctx;
+     void *resbuf;
+{
+  __sha512_finish_ctx_generic (ctx);
+
+  /* Put result from CTX in first 48 bytes following RESBUF.  */
+  for (unsigned int i = 0; i < 6; ++i)
+    ((uint64_t *) resbuf)[i] = SWAP (ctx->H[i]);
+}
 
 void
-__sha512_process_bytes (buffer, len, ctx)
+__sha512_process_bytes (ctx, buffer, len)
+     sha512_ctx *ctx;
      const void *buffer;
      size_t len;
-     struct sha512_ctx *ctx;
 {
   /* When we already have some bits in our internal buffer concatenate
      both inputs first.  */
diff --git a/crypt/sha512.h b/crypt/sha512.h
index 159f000..76fb81e 100644
--- a/crypt/sha512.h
+++ b/crypt/sha512.h
@@ -28,7 +28,7 @@ 
 
 
 /* Structure to save state of computation between the single steps.  */
-struct sha512_ctx
+typedef struct
 {
   uint64_t H[8];
 
@@ -43,30 +43,52 @@  struct sha512_ctx
     uint64_t total[2];
   };
   uint64_t buflen;
+  uint8_t __padding[8];
   union
   {
     char buffer[256];
     uint64_t buffer64[32];
   };
-};
+} sha512_ctx __attribute__((align(16));
 
 /* Initialize structure containing state of computation.
    (FIPS 180-2: 5.3.3)  */
-extern void __sha512_init_ctx (struct sha512_ctx *ctx) __THROW;
+extern void __sha512_init_ctx (sha512_ctx *__restrict ctx) __THROW;
+weak_alias(__sha512_init_ctx, sha512_init)
 
 /* Starting with the result of former calls of this function (or the
    initialization function update the context for the next LEN bytes
    starting at BUFFER.
    It is NOT required that LEN is a multiple of 128.  */
-extern void __sha512_process_bytes (const void *buffer, size_t len,
-				    struct sha512_ctx *ctx) __THROW;
+extern void __sha512_process_bytes (sha512_ctx *__restrict ctx,
+				const void *__restrict buffer, size_t len) __THROW;
+weak_alias(__sha512_process_bytes, sha512_update)
 
 /* Process the remaining bytes in the buffer and put result from CTX
    in first 64 bytes following RESBUF.
 
    IMPORTANT: On some systems it is required that RESBUF is correctly
    aligned for a 64 bits value.  */
-extern void *__sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf)
+extern void __sha512_finish_ctx (sha512_ctx *ctx, void *__restrict resbuf)
   __THROW;
+weak_alias(__sha512_finish_ctx, sha512_finish)
 
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 48 bytes following RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 64 bits value.  */
+extern void __sha384_finish_ctx (sha512_ctx *ctx, void *__restrict resbuf)
+  __THROW;
+weak_alias(__sha384_finish_ctx, sha384_finish)
+
+extern void *__sha512(const void *__restrict d, size_t n, void *__restrict md) {
+	sha512_ctx ctx;
+
+	sha512_init(&ctx);
+	sha512_update(&ctx, d, n);
+	sha512_finish(&ctx, md);
+	return md;
+}
+weak_alias(__sha512, sha512)
 #endif /* sha512.h */
diff --git a/crypt/sha512test.c b/crypt/sha512test.c
index 792e9a7..296ce89 100644
--- a/crypt/sha512test.c
+++ b/crypt/sha512test.c
@@ -63,7 +63,7 @@  static const struct
 int
 main (void)
 {
-  struct sha512_ctx ctx;
+  sha512_ctx ctx;
   char sum[64];
   int result = 0;
   int cnt;
@@ -71,8 +71,7 @@  main (void)
   for (cnt = 0; cnt < (int) (sizeof (tests) / sizeof (tests[0])); ++cnt)
     {
       __sha512_init_ctx (&ctx);
-      __sha512_process_bytes (tests[cnt].input, strlen (tests[cnt].input),
-			      &ctx);
+      __sha512_process_bytes (&ctx, tests[cnt].input, strlen (tests[cnt].input));
       __sha512_finish_ctx (&ctx, sum);
       if (memcmp (tests[cnt].result, sum, 64) != 0)
 	{
@@ -82,7 +81,7 @@  main (void)
 
       __sha512_init_ctx (&ctx);
       for (int i = 0; tests[cnt].input[i] != '\0'; ++i)
-	__sha512_process_bytes (&tests[cnt].input[i], 1, &ctx);
+	__sha512_process_bytes (&ctx, &tests[cnt].input[i], 1);
       __sha512_finish_ctx (&ctx, sum);
       if (memcmp (tests[cnt].result, sum, 64) != 0)
 	{
@@ -96,7 +95,7 @@  main (void)
   memset (buf, 'a', sizeof (buf));
   __sha512_init_ctx (&ctx);
   for (int i = 0; i < 1000; ++i)
-    __sha512_process_bytes (buf, sizeof (buf), &ctx);
+    __sha512_process_bytes (&ctx, buf, sizeof (buf));
   __sha512_finish_ctx (&ctx, sum);
   static const char expected[64] =
     "\xe7\x18\x48\x3d\x0c\xe7\x69\x64\x4e\x2e\x42\xc7\xbc\x15\xb4\x63"
diff --git a/include/sha2.h b/include/sha2.h
new file mode 100644
index 0000000..ad7d97d
--- /dev/null
+++ b/include/sha2.h
@@ -0,0 +1,32 @@ 
+#ifndef _SHA2_H
+#define _SHA2_H
+
+#include <stdint.h>
+
+typedef struct {
+       char __internal_state[176];
+} sha256_ctx __attribute__((align(16));
+
+/* 256 bits is 32 bytes
+ * for sha2-224 truncate from end after calling sha256_final()
+ */
+void *sha256(const void *__restrict d, size_t n, void *__restrict md);
+void sha256_init(sha256_ctx *s);
+void sha256_update(sha256_ctx *__restrict s, const void *__restrict d, size_t n);
+/* md must be 32-bit aligned */
+void sha256_final(sha256_ctx *__restrict s, void *__restrict md);
+
+typedef struct {
+       char __internal_state[352];
+} sha512_ctx __attribute__((align(16));
+
+/* 512 bits is 64 bytes
+ * for sha2-384 truncate from end after calling sha512_final()
+ */
+void *sha512(const void *__restrict d, size_t n, void *__restrict md);
+void sha512_init(sha512_ctx *s);
+void sha512_update(sha512_ctx *__restrict s, const void *__restrict d, size_t n);
+/* md must be 64-bit aligned */
+void sha512_final(sha512_ctx *__restrict s, void *__restrict md);
+
+#endif