Browse Source

Crypto library with unified interface.

Uses both existing MD2/MD5/SHA1 and the Gifford SHA256-512, unless WITHOUT_SHA2
is defined.
Johny Mattsson 9 years ago
parent
commit
32dd9b7b7a
6 changed files with 382 additions and 192 deletions
  1. 3 1
      app/Makefile
  2. 44 0
      app/crypto/Makefile
  3. 168 0
      app/crypto/digests.c
  4. 81 0
      app/crypto/digests.h
  5. 39 191
      app/crypto/sha2.c
  6. 47 0
      app/crypto/sha2.h

+ 3 - 1
app/Makefile

@@ -37,7 +37,8 @@ SUBDIRS=    \
 	wofs 	\
 	modules	\
 	spiffs	\
-	cjson
+	cjson  \
+	crypto \
 
 endif # } PDIR
 
@@ -86,6 +87,7 @@ COMPONENTS_eagle.app.v6 = \
 	wofs/wofs.a 	\
 	spiffs/spiffs.a 	\
 	cjson/libcjson.a 	\
+	crypto/libcrypto.a \
 	modules/libmodules.a
 
 LINKFLAGS_eagle.app.v6 = \

+ 44 - 0
app/crypto/Makefile

@@ -0,0 +1,44 @@
+
+#############################################################
+# Required variables for each makefile
+# Discard this section from all parent makefiles
+# Expected variables (with automatic defaults):
+#   CSRCS (all "C" files in the dir)
+#   SUBDIRS (all subdirs with a Makefile)
+#   GEN_LIBS - list of libs to be generated ()
+#   GEN_IMAGES - list of images to be generated ()
+#   COMPONENTS_xxx - a list of libs/objs in the form
+#     subdir/lib to be extracted and rolled up into
+#     a generated lib/image xxx.a ()
+#
+ifndef PDIR
+GEN_LIBS = libcrypto.a
+endif
+
+#############################################################
+# Configuration i.e. compile options etc.
+# Target specific stuff (defines etc.) goes in here!
+# Generally values applying to a tree are captured in the
+#   makefile at its root level - these are then overridden
+#   for a subtree within the makefile rooted therein
+#
+#DEFINES +=
+
+#############################################################
+# Recursion Magic - Don't touch this!!
+#
+# Each subtree potentially has an include directory
+#   corresponding to the common APIs applicable to modules
+#   rooted at that subtree. Accordingly, the INCLUDE PATH
+#   of a module can only contain the include directories up
+#   its parent path, and not its siblings
+#
+# Required for each makefile to inherit from the parent
+#
+
+INCLUDES := $(INCLUDES) -I $(PDIR)include
+INCLUDES += -I ./
+INCLUDES += -I ../libc
+PDIR := ../$(PDIR)
+sinclude $(PDIR)Makefile
+

+ 168 - 0
app/crypto/digests.c

@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2015, DiUS Computing Pty Ltd (jmattsson@dius.com.au)
+ * 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.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 CONTRIBUTOR(S) 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.
+ *
+ */
+#include "digests.h"
+#include "lwip/mem.h"
+#include "lwip/arch.h"
+#include "ssl/ssl_crypto.h"
+#include "sha2.h"
+#include <string.h>
+#include <c_errno.h>
+
+typedef char ensure_int_and_size_t_same[(sizeof(int)==sizeof(size_t)) ? 0 : -1];
+
+/* None of the functions match the prototype fully due to the void *, and in
+   some cases also the int vs size_t len, so wrap declarations in a macro. */
+#define MECH(pfx, ds, bs) \
+  { #pfx, \
+    (create_ctx_fn)pfx ## _Init, \
+    (update_ctx_fn)pfx ## _Update, \
+    (finalize_ctx_fn)pfx ## _Final, \
+    sizeof(pfx ## _CTX), \
+    ds, \
+    bs }
+
+static const digest_mech_info_t hash_mechs[] =
+{
+   MECH(MD2,  MD2_SIZE,  16)
+  ,MECH(MD5,  MD5_SIZE,  64)
+  ,MECH(SHA1, SHA1_SIZE, 64)
+#ifndef WITHOUT_SHA2
+  ,MECH(SHA256, SHA256_DIGEST_LENGTH, SHA256_BLOCK_LENGTH)
+  ,MECH(SHA384, SHA384_DIGEST_LENGTH, SHA384_BLOCK_LENGTH)
+  ,MECH(SHA512, SHA512_DIGEST_LENGTH, SHA512_BLOCK_LENGTH)
+#endif
+};
+
+#undef MECH
+
+const digest_mech_info_t *crypto_digest_mech (const char *mech)
+{
+  if (!mech)
+    return 0;
+
+  size_t i;
+  for (i = 0; i < (sizeof (hash_mechs) / sizeof (digest_mech_info_t)); ++i)
+  {
+    const digest_mech_info_t *mi = hash_mechs + i;
+    if (strcasecmp (mech, mi->name) == 0)
+      return mi;
+  }
+  return 0;
+}
+
+static const char hex[] = "0123456789abcdef";
+// note: supports in-place encoding
+void crypto_encode_asciihex (const char *bin, size_t binlen, char *outbuf)
+{
+  size_t aidx = binlen * 2;
+  int i;
+  for (i = binlen -1; i >= 0; --i)
+  {
+    outbuf[aidx--] = hex[bin[i] & 0xf];
+    outbuf[aidx--] = hex[bin[i] >>  4];
+  }
+}
+
+
+size_t crypto_digest_size (const char *mech)
+{
+  const digest_mech_info_t *mi = crypto_digest_mech (mech);
+  return mi ? mi->digest_size : 0;
+}
+
+
+int crypto_hash (const digest_mech_info_t *mi,
+  const char *data, size_t data_len,
+  uint8_t *digest)
+{
+  if (!mi)
+    return EINVAL;
+
+  void *ctx = os_malloc (mi->ctx_size);
+  if (!ctx)
+    return ENOMEM;
+
+  mi->create (ctx);
+  mi->update (ctx, data, data_len);
+  mi->finalize (digest, ctx);
+
+  os_free (ctx);
+  return 0;
+}
+
+
+int crypto_hmac (const digest_mech_info_t *mi,
+   const char *data, size_t data_len,
+   const char *key, size_t key_len,
+   uint8_t *digest)
+{
+  if (!mi)
+    return EINVAL;
+
+  void *ctx = os_malloc (mi->ctx_size);
+  if (!ctx)
+    return ENOMEM;
+
+  // If key too long, it needs to be hashed before use
+  if (key_len > mi->block_size)
+  {
+    mi->create (ctx);
+    mi->update (ctx, key, key_len);
+    mi->finalize (digest, ctx);
+    key = digest;
+    key_len = mi->block_size;
+  }
+
+  const size_t bs = mi->block_size;
+  uint8_t k_ipad[bs];
+  uint8_t k_opad[bs];
+
+  os_memset (k_ipad, 0x36, bs);
+  os_memset (k_opad, 0x5c, bs);
+  size_t i;
+  for (i = 0; i < key_len; ++i)
+  {
+    k_ipad[i] ^= key[i];
+    k_opad[i] ^= key[i];
+  }
+
+  mi->create (ctx);
+  mi->update (ctx, k_ipad, bs);
+  mi->update (ctx, data, data_len);
+  mi->finalize (digest, ctx);
+
+  mi->create (ctx);
+  mi->update (ctx, k_opad, bs);
+  mi->update (ctx, digest, mi->digest_size);
+  mi->finalize (digest, ctx);
+
+  os_free (ctx);
+  return 0;
+}

+ 81 - 0
app/crypto/digests.h

@@ -0,0 +1,81 @@
+#ifndef _CRYPTO_DIGESTS_H_
+#define _CRYPTO_DIGESTS_H_
+
+#include <c_types.h>
+
+typedef void (*create_ctx_fn)(void *ctx);
+typedef void (*update_ctx_fn)(void *ctx, const uint8_t *msg, int len);
+typedef void (*finalize_ctx_fn)(uint8_t *digest, void *ctx);
+
+/**
+ * Description of a message digest mechanism.
+ *
+ * Typical usage (if not using the crypto_xxxx() functions below):
+ *   digest_mech_info_t *mi = crypto_digest_mech (chosen_algorithm);
+ *   void *ctx = os_malloc (mi->ctx_size);
+ *   mi->create (ctx);
+ *   mi->update (ctx, data, len);
+ *   ...
+ *   uint8_t *digest = os_malloc (mi->digest_size);
+ *   mi->finalize (digest, ctx);
+ *   ...
+ *   os_free (ctx);
+ *   os_free (digest);
+ */
+typedef struct
+{
+  const char *    name;
+  create_ctx_fn   create;
+  update_ctx_fn   update;
+  finalize_ctx_fn finalize;
+  uint16_t        ctx_size;
+  uint16_t        digest_size;
+  uint16_t        block_size;
+} digest_mech_info_t;
+
+
+/**
+ * Looks up the mech data for a specified digest algorithm.
+ * @param mech The name of the algorithm, e.g. "MD5", "SHA256"
+ * @returns The mech data, or null if the mech is unknown.
+ */
+const digest_mech_info_t *crypto_digest_mech (const char *mech);
+
+/**
+ * Wrapper function for performing a one-in-all hashing operation.
+ * @param mi       A mech from @c crypto_digest_mech(). A null pointer @c mi
+ *                 is harmless, but will of course result in an error return.
+ * @param data     The data to create a digest for.
+ * @param data_len Number of bytes at @c data to digest.
+ * @param digest   Output buffer, must be at least @c mi->digest_size in size.
+ * @return 0 on success, non-zero on error.
+ */
+int crypto_hash (const digest_mech_info_t *mi, const char *data, size_t data_len, uint8_t *digest);
+
+
+/**
+ * Generate a HMAC signature.
+ * @param mi       A mech from @c crypto_digest_mech(). A null pointer @c mi
+ *                 is harmless, but will of course result in an error return.
+ * @param data     The data to generate a signature for.
+ * @param data_len Number of bytes at @c data to process.
+ * @param key      The key to use.
+ * @param key_len  Number of bytes the @c key comprises.
+ * @param digest   Output buffer, must be at least @c mi->digest_size in size.
+ * @return 0 on success, non-zero on error.
+ */
+int crypto_hmac (const digest_mech_info_t *mi, const char *data, size_t data_len, const char *key, size_t key_len, uint8_t *digest);
+
+/**
+ * Perform ASCII Hex encoding. Does not null-terminate the buffer.
+ *
+ * @param bin     The buffer to ascii-hex encode.
+ * @param bin_len Number of bytes in @c bin to encode.
+ * @param outbuf  Output buffer, must be at least @c bin_len*2 bytes in size.
+ *                Note that in-place encoding is supported, and as such
+ *                bin==outbuf is safe, provided the buffer is large enough.
+ */
+void crypto_encode_asciihex (const char *bin, size_t bin_len, char *outbuf);
+
+
+#endif

+ 39 - 191
app/crypto/sha2.c

@@ -3,6 +3,7 @@
  * AUTHOR:	Aaron D. Gifford - http://www.aarongifford.com/
  * 
  * Copyright (c) 2000-2001, Aaron D. Gifford
+ * Copyright (c) 2015, DiUS Computing Pty Ltd (jmattsson@dius.com.au)
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,9 +32,11 @@
  *
  */
 
-#include <string.h>	/* memcpy()/memset() or bcopy()/bzero() */
-#include <assert.h>	/* assert() */
+#ifndef WITHOUT_SHA2
+
 #include "sha2.h"
+#include <string.h>	/* memcpy()/memset() or bcopy()/bzero() */
+#define assert(x) do {} while (0)
 
 /*
  * ASSERT NOTE:
@@ -56,76 +59,19 @@
  */
 
 
-/*** SHA-256/384/512 Machine Architecture Definitions *****************/
-/*
- * BYTE_ORDER NOTE:
- *
- * Please make sure that your system defines BYTE_ORDER.  If your
- * architecture is little-endian, make sure it also defines
- * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
- * equivilent.
- *
- * If your system does not define the above, then you can do so by
- * hand like this:
- *
- *   #define LITTLE_ENDIAN 1234
- *   #define BIG_ENDIAN    4321
- *
- * And for little-endian machines, add:
- *
- *   #define BYTE_ORDER LITTLE_ENDIAN 
- *
- * Or for big-endian machines:
- *
- *   #define BYTE_ORDER BIG_ENDIAN
- *
- * The FreeBSD machine this was written on defines BYTE_ORDER
- * appropriately by including <sys/types.h> (which in turn includes
- * <machine/endian.h> where the appropriate definitions are actually
- * made).
- */
-#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
-#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
-#endif
-
-/*
- * Define the followingsha2_* types to types of the correct length on
- * the native archtecture.   Most BSD systems and Linux define u_intXX_t
- * types.  Machines with very recent ANSI C headers, can use the
- * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H
- * during compile or in the sha.h header file.
- *
- * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t
- * will need to define these three typedefs below (and the appropriate
- * ones in sha.h too) by hand according to their system architecture.
- *
- * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t
- * types and pointing out recent ANSI C support for uintXX_t in inttypes.h.
- */
-#ifdef SHA2_USE_INTTYPES_H
-
 typedef uint8_t  sha2_byte;	/* Exactly 1 byte */
 typedef uint32_t sha2_word32;	/* Exactly 4 bytes */
 typedef uint64_t sha2_word64;	/* Exactly 8 bytes */
 
-#else /* SHA2_USE_INTTYPES_H */
-
-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 */
-
-#endif /* SHA2_USE_INTTYPES_H */
-
 
 /*** SHA-256/384/512 Various Length Definitions ***********************/
-/* NOTE: Most of these are in sha2.h */
 #define SHA256_SHORT_BLOCK_LENGTH	(SHA256_BLOCK_LENGTH - 8)
 #define SHA384_SHORT_BLOCK_LENGTH	(SHA384_BLOCK_LENGTH - 16)
 #define SHA512_SHORT_BLOCK_LENGTH	(SHA512_BLOCK_LENGTH - 16)
 
 
 /*** ENDIAN REVERSAL MACROS *******************************************/
-#if BYTE_ORDER == LITTLE_ENDIAN
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 #define REVERSE32(w,x)	{ \
 	sha2_word32 tmp = (w); \
 	tmp = (tmp >> 16) | (tmp << 16); \
@@ -139,7 +85,7 @@ typedef u_int64_t sha2_word64;	/* Exactly 8 bytes */
 	(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
 	      ((tmp & 0x0000ffff0000ffffULL) << 16); \
 }
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
 
 /*
  * Macro for incrementally adding the unsigned 64-bit integer n to the
@@ -324,15 +270,9 @@ const static sha2_word64 sha512_initial_hash_value[8] = {
 	0x5be0cd19137e2179ULL
 };
 
-/*
- * Constant used by SHA256/384/512_End() functions for converting the
- * digest to a readable hexadecimal character string:
- */
-static const char *sha2_hex_digits = "0123456789abcdef";
-
 
 /*** SHA-256: *********************************************************/
-void SHA256_Init(SHA256_CTX* context) {
+void ICACHE_FLASH_ATTR SHA256_Init(SHA256_CTX* context) {
 	if (context == (SHA256_CTX*)0) {
 		return;
 	}
@@ -345,7 +285,7 @@ void SHA256_Init(SHA256_CTX* context) {
 
 /* Unrolled SHA-256 round macros: */
 
-#if BYTE_ORDER == LITTLE_ENDIAN
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN_
 
 #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
 	REVERSE32(*data++, W256[j]); \
@@ -356,7 +296,7 @@ void SHA256_Init(SHA256_CTX* context) {
 	j++
 
 
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
+#else /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN_ */
 
 #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
 	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
@@ -365,7 +305,7 @@ void SHA256_Init(SHA256_CTX* context) {
 	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
 	j++
 
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN_ */
 
 #define ROUND256(a,b,c,d,e,f,g,h)	\
 	s0 = W256[(j+1)&0x0f]; \
@@ -378,7 +318,7 @@ void SHA256_Init(SHA256_CTX* context) {
 	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
 	j++
 
-void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
+void ICACHE_FLASH_ATTR SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
 	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
 	sha2_word32	T1, *W256;
 	int		j;
@@ -436,7 +376,7 @@ void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
 
 #else /* SHA2_UNROLL_TRANSFORM */
 
-void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
+void ICACHE_FLASH_ATTR SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
 	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
 	sha2_word32	T1, T2, *W256;
 	int		j;
@@ -455,15 +395,15 @@ void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
 
 	j = 0;
 	do {
-#if BYTE_ORDER == LITTLE_ENDIAN
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 		/* Copy data while converting to host byte order */
 		REVERSE32(*data++,W256[j]);
 		/* Apply the SHA-256 compression function to update a..h */
 		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
+#else /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN_ */
 		/* Apply the SHA-256 compression function to update a..h with copy */
 		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN_ */
 		T2 = Sigma0_256(a) + Maj(a, b, c);
 		h = g;
 		g = f;
@@ -516,7 +456,7 @@ void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
 
 #endif /* SHA2_UNROLL_TRANSFORM */
 
-void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
+void ICACHE_FLASH_ATTR SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
 	unsigned int	freespace, usedspace;
 
 	if (len == 0) {
@@ -564,7 +504,7 @@ void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
 	usedspace = freespace = 0;
 }
 
-void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
+void ICACHE_FLASH_ATTR SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
 	sha2_word32	*d = (sha2_word32*)digest;
 	unsigned int	usedspace;
 
@@ -574,7 +514,7 @@ void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
 	/* If no digest buffer is passed, we don't bother doing this: */
 	if (digest != (sha2_byte*)0) {
 		usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
-#if BYTE_ORDER == LITTLE_ENDIAN
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 		/* Convert FROM host byte order */
 		REVERSE64(context->bitcount,context->bitcount);
 #endif
@@ -608,7 +548,7 @@ void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
 		/* Final transform: */
 		SHA256_Transform(context, (sha2_word32*)context->buffer);
 
-#if BYTE_ORDER == LITTLE_ENDIAN
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 		{
 			/* Convert TO host byte order */
 			int	j;
@@ -627,40 +567,9 @@ void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
 	usedspace = 0;
 }
 
-char *SHA256_End(SHA256_CTX* context, char buffer[]) {
-	sha2_byte	digest[SHA256_DIGEST_LENGTH], *d = digest;
-	int		i;
-
-	/* Sanity check: */
-	assert(context != (SHA256_CTX*)0);
-
-	if (buffer != (char*)0) {
-		SHA256_Final(digest, context);
-
-		for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
-			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
-			*buffer++ = sha2_hex_digits[*d & 0x0f];
-			d++;
-		}
-		*buffer = (char)0;
-	} else {
-		MEMSET_BZERO(context, sizeof(SHA256_CTX));
-	}
-	MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH);
-	return buffer;
-}
-
-char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) {
-	SHA256_CTX	context;
-
-	SHA256_Init(&context);
-	SHA256_Update(&context, data, len);
-	return SHA256_End(&context, digest);
-}
-
 
 /*** SHA-512: *********************************************************/
-void SHA512_Init(SHA512_CTX* context) {
+void ICACHE_FLASH_ATTR SHA512_Init(SHA512_CTX* context) {
 	if (context == (SHA512_CTX*)0) {
 		return;
 	}
@@ -672,7 +581,7 @@ void SHA512_Init(SHA512_CTX* context) {
 #ifdef SHA2_UNROLL_TRANSFORM
 
 /* Unrolled SHA-512 round macros: */
-#if BYTE_ORDER == LITTLE_ENDIAN
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN_
 
 #define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
 	REVERSE64(*data++, W512[j]); \
@@ -683,7 +592,7 @@ void SHA512_Init(SHA512_CTX* context) {
 	j++
 
 
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
+#else /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN_ */
 
 #define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
 	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
@@ -692,7 +601,7 @@ void SHA512_Init(SHA512_CTX* context) {
 	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
 	j++
 
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN_ */
 
 #define ROUND512(a,b,c,d,e,f,g,h)	\
 	s0 = W512[(j+1)&0x0f]; \
@@ -705,7 +614,7 @@ void SHA512_Init(SHA512_CTX* context) {
 	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
 	j++
 
-void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
+void ICACHE_FLASH_ATTR SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
 	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
 	sha2_word64	T1, *W512 = (sha2_word64*)context->buffer;
 	int		j;
@@ -760,7 +669,7 @@ void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
 
 #else /* SHA2_UNROLL_TRANSFORM */
 
-void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
+void ICACHE_FLASH_ATTR SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
 	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
 	sha2_word64	T1, T2, *W512 = (sha2_word64*)context->buffer;
 	int		j;
@@ -777,15 +686,15 @@ void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
 
 	j = 0;
 	do {
-#if BYTE_ORDER == LITTLE_ENDIAN
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 		/* Convert TO host byte order */
 		REVERSE64(*data++, W512[j]);
 		/* Apply the SHA-512 compression function to update a..h */
 		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
+#else /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN_ */
 		/* Apply the SHA-512 compression function to update a..h with copy */
 		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN_ */
 		T2 = Sigma0_512(a) + Maj(a, b, c);
 		h = g;
 		g = f;
@@ -838,7 +747,7 @@ void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
 
 #endif /* SHA2_UNROLL_TRANSFORM */
 
-void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
+void ICACHE_FLASH_ATTR SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
 	unsigned int	freespace, usedspace;
 
 	if (len == 0) {
@@ -886,11 +795,11 @@ void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
 	usedspace = freespace = 0;
 }
 
-void SHA512_Last(SHA512_CTX* context) {
+void ICACHE_FLASH_ATTR SHA512_Last(SHA512_CTX* context) {
 	unsigned int	usedspace;
 
 	usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
-#if BYTE_ORDER == LITTLE_ENDIAN
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 	/* Convert FROM host byte order */
 	REVERSE64(context->bitcount[0],context->bitcount[0]);
 	REVERSE64(context->bitcount[1],context->bitcount[1]);
@@ -927,7 +836,7 @@ void SHA512_Last(SHA512_CTX* context) {
 	SHA512_Transform(context, (sha2_word64*)context->buffer);
 }
 
-void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
+void ICACHE_FLASH_ATTR SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
 	sha2_word64	*d = (sha2_word64*)digest;
 
 	/* Sanity check: */
@@ -938,7 +847,7 @@ void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
 		SHA512_Last(context);
 
 		/* Save the hash data for output: */
-#if BYTE_ORDER == LITTLE_ENDIAN
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 		{
 			/* Convert TO host byte order */
 			int	j;
@@ -956,40 +865,9 @@ void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
 	MEMSET_BZERO(context, sizeof(SHA512_CTX));
 }
 
-char *SHA512_End(SHA512_CTX* context, char buffer[]) {
-	sha2_byte	digest[SHA512_DIGEST_LENGTH], *d = digest;
-	int		i;
-
-	/* Sanity check: */
-	assert(context != (SHA512_CTX*)0);
-
-	if (buffer != (char*)0) {
-		SHA512_Final(digest, context);
-
-		for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
-			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
-			*buffer++ = sha2_hex_digits[*d & 0x0f];
-			d++;
-		}
-		*buffer = (char)0;
-	} else {
-		MEMSET_BZERO(context, sizeof(SHA512_CTX));
-	}
-	MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH);
-	return buffer;
-}
-
-char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) {
-	SHA512_CTX	context;
-
-	SHA512_Init(&context);
-	SHA512_Update(&context, data, len);
-	return SHA512_End(&context, digest);
-}
-
 
 /*** SHA-384: *********************************************************/
-void SHA384_Init(SHA384_CTX* context) {
+void ICACHE_FLASH_ATTR SHA384_Init(SHA384_CTX* context) {
 	if (context == (SHA384_CTX*)0) {
 		return;
 	}
@@ -998,11 +876,11 @@ void SHA384_Init(SHA384_CTX* context) {
 	context->bitcount[0] = context->bitcount[1] = 0;
 }
 
-void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) {
+void ICACHE_FLASH_ATTR 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) {
+void ICACHE_FLASH_ATTR SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
 	sha2_word64	*d = (sha2_word64*)digest;
 
 	/* Sanity check: */
@@ -1013,7 +891,7 @@ void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
 		SHA512_Last((SHA512_CTX*)context);
 
 		/* Save the hash data for output: */
-#if BYTE_ORDER == LITTLE_ENDIAN
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 		{
 			/* Convert TO host byte order */
 			int	j;
@@ -1031,34 +909,4 @@ void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
 	MEMSET_BZERO(context, sizeof(SHA384_CTX));
 }
 
-char *SHA384_End(SHA384_CTX* context, char buffer[]) {
-	sha2_byte	digest[SHA384_DIGEST_LENGTH], *d = digest;
-	int		i;
-
-	/* Sanity check: */
-	assert(context != (SHA384_CTX*)0);
-
-	if (buffer != (char*)0) {
-		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 {
-		MEMSET_BZERO(context, sizeof(SHA384_CTX));
-	}
-	MEMSET_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 // WITHOUT_SHA2

+ 47 - 0
app/crypto/sha2.h

@@ -0,0 +1,47 @@
+#ifndef __SHA2_H__
+#define __SHA2_H__
+
+#include <c_types.h>
+
+/**************************************************************************
+ * SHA256/384/512 declarations
+ **************************************************************************/
+
+#define SHA256_BLOCK_LENGTH  64
+#define SHA256_DIGEST_LENGTH 32
+
+typedef struct
+{
+  uint32_t state[8];
+  uint64_t bitcount;
+  uint8_t  buffer[SHA256_BLOCK_LENGTH];
+} SHA256_CTX;
+
+
+void SHA256_Init(SHA256_CTX *);
+void SHA256_Update(SHA256_CTX *, const uint8_t *msg, size_t len);
+void SHA256_Final(uint8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*);
+
+#define SHA384_BLOCK_LENGTH  128
+#define SHA384_DIGEST_LENGTH  48
+
+typedef struct
+{
+  uint64_t state[8];
+  uint64_t bitcount[2];
+  uint8_t  buffer[SHA384_BLOCK_LENGTH];
+} SHA384_CTX;
+
+void SHA384_Init(SHA384_CTX*);
+void SHA384_Update(SHA384_CTX*, const uint8_t *msg, size_t len);
+void SHA384_Final(uint8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*);
+
+#define SHA512_BLOCK_LENGTH  128
+#define SHA512_DIGEST_LENGTH  64
+typedef SHA384_CTX SHA512_CTX;
+
+void SHA512_Init(SHA512_CTX*);
+void SHA512_Update(SHA512_CTX*, const uint8_t *msg, size_t len);
+void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
+
+#endif