A whole bunch of changes to eventually support
[libgcrypt.git] / cipher / sha256.c
index 260ecd7..b0a5629 100644 (file)
@@ -1,5 +1,5 @@
 /* sha256.c - SHA256 hash function
- *     Copyright (C) 2003 Free Software Foundation, Inc.
+ *     Copyright (C) 2003, 2006, 2008 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 
 /*  Test vectors:
     
     "abc"
-    ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad
+    SHA224: 23097d22 3405d822 8642a477 bda255b3 2aadbce4 bda0b3f7 e36c9da7
+    SHA256: ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad
 
     "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-    248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
+    SHA224: 75388b16 512776cc 5dba5da1 fd890150 b0c6455c b4f58b19 52522525
+    SHA256: 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
  
     "a" one million times
-    cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0
+    SHA224: 20794655 980c91d8 bbb4c1ea 97618a4b f03f4258 1948b2ee 4ee7ad67
+    SHA256: cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0
 
  */
 
@@ -37,7 +39,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
+
 #include "g10lib.h"
 #include "memory.h"
 #include "bithelp.h"
@@ -54,7 +56,7 @@ typedef struct {
 static void
 sha256_init (void *context)
 {
-  SHA256_CONTEXT *hd = (SHA256_CONTEXT *) context;
+  SHA256_CONTEXT *hd = context;
 
   hd->h0 = 0x6a09e667;
   hd->h1 = 0xbb67ae85;
@@ -70,6 +72,25 @@ sha256_init (void *context)
 }
 
 
+static void
+sha224_init (void *context)
+{
+  SHA256_CONTEXT *hd = context;
+
+  hd->h0 = 0xc1059ed8;
+  hd->h1 = 0x367cd507;
+  hd->h2 = 0x3070dd17;
+  hd->h3 = 0xf70e5939;
+  hd->h4 = 0xffc00b31;
+  hd->h5 = 0x68581511;
+  hd->h6 = 0x64f98fa7;
+  hd->h7 = 0xbefa4fa4;
+
+  hd->nblocks = 0;
+  hd->count = 0;
+}
+
+
 /*
   Transform the message X which consists of 16 32-bit-words. See FIPS
   180-2 for details.  */
@@ -94,7 +115,7 @@ sha256_init (void *context)
           } while (0)
  
 static void
-transform (SHA256_CONTEXT *hd, byte *data)
+transform (SHA256_CONTEXT *hd, const unsigned char *data)
 {
   static const u32 K[64] = {
     0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
@@ -129,7 +150,7 @@ transform (SHA256_CONTEXT *hd, byte *data)
   g = hd->h6;
   h = hd->h7;
   
-#ifdef BIG_ENDIAN_HOST
+#ifdef WORDS_BIGENDIAN
   memcpy (x, data, 64);
 #else
   { 
@@ -174,9 +195,11 @@ transform (SHA256_CONTEXT *hd, byte *data)
 /* Update the message digest with the contents of INBUF with length
   INLEN.  */
 static void
-sha256_write (void *context, byte *inbuf, size_t inlen)
+sha256_write (void *context, const void *inbuf_arg, size_t inlen)
 {
-  SHA256_CONTEXT *hd = (SHA256_CONTEXT *) context;
+  const unsigned char *inbuf = inbuf_arg;
+  SHA256_CONTEXT *hd = context;
+
   if (hd->count == 64)
     { /* flush the buffer */
       transform (hd, hd->buf);
@@ -217,7 +240,7 @@ sha256_write (void *context, byte *inbuf, size_t inlen)
 static void
 sha256_final(void *context)
 {
-  SHA256_CONTEXT *hd = (SHA256_CONTEXT *) context;
+  SHA256_CONTEXT *hd = context;
   u32 t, msb, lsb;
   byte *p;
   
@@ -264,7 +287,7 @@ sha256_final(void *context)
   _gcry_burn_stack (74*4+32);
 
   p = hd->buf;
-#ifdef BIG_ENDIAN_HOST
+#ifdef WORDS_BIGENDIAN
 #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0)
 #else /* little endian */
 #define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16;         \
@@ -284,18 +307,132 @@ sha256_final(void *context)
 static byte *
 sha256_read (void *context)
 {
-  SHA256_CONTEXT *hd = (SHA256_CONTEXT *) context;
+  SHA256_CONTEXT *hd = context;
+
   return hd->buf;
 }
 
-static byte asn[19] = /* Object ID is  2.16.840.1.101.3.4.2.1 */
+
+\f
+/* 
+     Self-test section.
+ */
+
+
+static gpg_err_code_t
+selftests_sha224 (selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+  
+  what = "low-level";
+  errtxt = NULL; /*selftest ();*/
+  if (errtxt)
+    goto failed;
+
+  /* FIXME:  need more tests.  */
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("digest", GCRY_MD_SHA224, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+static gpg_err_code_t
+selftests_sha256 (selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+  
+  what = "low-level";
+  errtxt = NULL; /*selftest ();*/
+  if (errtxt)
+    goto failed;
+
+  /* FIXME:  need more tests.  */
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("digest", GCRY_MD_SHA256, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+/* Run a full self-test for ALGO and return 0 on success.  */
+static gpg_err_code_t
+run_selftests (int algo, selftest_report_func_t report)
+{
+  gpg_err_code_t ec;
+
+  switch (algo)
+    {
+    case GCRY_MD_SHA224:
+      ec = selftests_sha224 (report);
+      break;
+    case GCRY_MD_SHA256:
+      ec = selftests_sha256 (report);
+      break;
+    default:
+      ec = GPG_ERR_DIGEST_ALGO;
+      break;
+        
+    }
+  return ec;
+}
+
+
+
+\f
+static byte asn224[19] = /* Object ID is 2.16.840.1.101.3.4.2.4 */
+  { 0x30, 0x2D, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
+    0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04,
+    0x1C
+  };
+
+static gcry_md_oid_spec_t oid_spec_sha224[] =
+  {
+    /* From RFC3874, Section 4 */
+    { "2.16.840.1.101.3.4.2.4" }, 
+    { NULL },
+  };
+
+static byte asn256[19] = /* Object ID is  2.16.840.1.101.3.4.2.1 */
   { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
     0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
     0x00, 0x04, 0x20 };
 
-GcryDigestSpec digest_spec_sha256 =
+static gcry_md_oid_spec_t oid_spec_sha256[] =
+  {
+    /* According to the OpenPGP draft rfc2440-bis06 */
+    { "2.16.840.1.101.3.4.2.1" }, 
+    /* PKCS#1 sha256WithRSAEncryption */
+    { "1.2.840.113549.1.1.11" },
+
+    { NULL },
+  };
+
+gcry_md_spec_t _gcry_digest_spec_sha224 =
+  {
+    "SHA224", asn224, DIM (asn224), oid_spec_sha224, 28,
+    sha224_init, sha256_write, sha256_final, sha256_read,
+    sizeof (SHA256_CONTEXT)
+  };
+md_extra_spec_t _gcry_digest_extraspec_sha224 = 
+  {
+    run_selftests
+  };
+
+gcry_md_spec_t _gcry_digest_spec_sha256 =
   {
-    "SHA256", GCRY_MD_SHA256, asn, DIM (asn), 32,
+    "SHA256", asn256, DIM (asn256), oid_spec_sha256, 32,
     sha256_init, sha256_write, sha256_final, sha256_read,
     sizeof (SHA256_CONTEXT)
   };
+md_extra_spec_t _gcry_digest_extraspec_sha256 = 
+  {
+    run_selftests
+  };