SHA256
authorNIIBE Yutaka <gniibe@fsij.org>
Wed, 13 Jun 2012 23:46:59 +0000 (08:46 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Wed, 13 Jun 2012 23:46:59 +0000 (08:46 +0900)
ChangeLog
NEWS
README
src/ac.c
src/crypt.mk
src/gnuk.h
src/openpgp-do.c
src/openpgp.c
src/sha256.c [new file with mode: 0644]
src/sha256.h [new file with mode: 0644]

index bfa1b96..69c78d4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,21 @@
+2012-06-14  Niibe Yutaka  <gniibe@fsij.org>
+
+       KDF is now SHA-256 (was: SHA1).
+       * src/sha256.c: New file.  Based on the implementation by Dr Brian
+       Gladman.
+       * src/openpgp.c (cmd_change_password, cmd_reset_user_password):
+       Use sha256.
+       * src/openpgp-do.c (proc_resetting_code, gpg_do_write_prvkey): Likewise.
+       * src/ac.c (verify_user_0, calc_md, verify_admin): Likewise.
+       * src/crypt.mk (CRYPTSRC): Add sha256.c, removing sha1.c.
+       * src/gnuk.h (KEYSTRING_MD_SIZE): It's 32 for SHA-256.
+
 2012-06-13  Niibe Yutaka  <gniibe@fsij.org>
 
+       Bug fixes.
        * src/main.c (display_interaction): Assign to main_mode.
+       * src/openpgp.c (cmd_change_password): Bug fix for admin less mode
+       to admin full mode.  Variable who_old should be admin_authorized.
 
        Key generation is configure option.
        * src/configure (keygen): Add --enable-keygen option.
diff --git a/NEWS b/NEWS
index 992df93..971e952 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,11 @@ Gnuk NEWS - User visible changes
 Finally, key generation is supported.  Note that it is very slow.  It
 will takes a few minutes to generate two keys.
 
+** KDF (Key Derivation Function) is now SHA-256
+Data encryption key for private keys are computed by KDF (Key
+Derivation Function, sometimes also is refered as string to key
+function, S2K).  It was SHA1 before, but it is replaced by SHA-256.
+
 
 * Major changes in Gnuk 0.19
 
diff --git a/README b/README
index 2424da6..3d5bc90 100644 (file)
--- a/README
+++ b/README
@@ -189,6 +189,11 @@ Souce code
 
 Gnuk source code is under src/ directory.
 
+Note that SHA-2 hash function implementation, src/sha256.c, is based
+on the original implementation by Dr. Brian Gladman.  See:
+
+  http://gladman.plushost.co.uk/oldsite/cryptography_technology/sha/index.php
+
 
 License
 =======
@@ -197,7 +202,7 @@ It is distributed under GNU General Public Licence version 3 or later
 (GPLv3+).  Please see src/COPYING.
 
 Please note that it is distributed with external source code too.
-Please read relevant licenses for external source code, too.
+Please read relevant licenses for external source code as well.
 
 The author(s) of Gnuk expect users of Gnuk will be able to access the
 source code of Gnuk, so that users can study the code and can modify
@@ -221,8 +226,7 @@ Gnuk is distributed with external source code.
 * polarssl-0.14.0/  -- PolarSSL 0.14.0
 
   Taken from http://polarssl.org/
-  We use PolarSSL for RSA computation, AES encryption/decryption
-  and SHA-1 computation.
+  We use PolarSSL for RSA computation, AES encryption/decryption.
 
   The file include/polarssl/bn_mul.h is heavily modified for ARM
   Cortex-M3.
index 87e09ba..2e530a0 100644 (file)
--- a/src/ac.c
+++ b/src/ac.c
@@ -24,9 +24,7 @@
 #include "config.h"
 #include "ch.h"
 #include "gnuk.h"
-
-#include "polarssl/config.h"
-#include "polarssl/sha1.h"
+#include "sha256.h"
 
 uint8_t volatile auth_status;  /* Initialized to AC_NONE_AUTHORIZED */
 
@@ -89,7 +87,7 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
     }
 
  success_one_step:
-  sha1 (pw, pw_len, keystring);
+  sha256 (pw, pw_len, keystring);
   if (access == AC_PSO_CDS_AUTHORIZED)
     {
       r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
@@ -161,28 +159,27 @@ static void
 calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len,
         uint8_t md[KEYSTRING_MD_SIZE])
 {
-  sha1_context sha1_ctx;
+  sha256_context sha256_ctx;
 
-  sha1_starts (&sha1_ctx);
+  sha256_start (&sha256_ctx);
 
   while (count > pw_len + 8)
     {
-      sha1_update (&sha1_ctx, salt, 8);
-      sha1_update (&sha1_ctx, pw, pw_len);
+      sha256_update (&sha256_ctx, salt, 8);
+      sha256_update (&sha256_ctx, pw, pw_len);
       count -= pw_len + 8;
     }
 
   if (count <= 8)
-    sha1_update (&sha1_ctx, salt, count);
+    sha256_update (&sha256_ctx, salt, count);
   else
     {
-      sha1_update (&sha1_ctx, salt, 8);
+      sha256_update (&sha256_ctx, salt, 8);
       count -= 8;
-      sha1_update (&sha1_ctx, pw, count);
+      sha256_update (&sha256_ctx, pw, count);
     }
 
-  sha1_finish (&sha1_ctx, md);
-  memset (&sha1_ctx, 0, sizeof (sha1_ctx));
+  sha256_finish (&sha256_ctx, md);
 }
 
 uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
@@ -283,7 +280,7 @@ verify_admin (const uint8_t *pw, int pw_len)
   if (r <= 0)
     return r;
 
-  sha1 (pw, pw_len, keystring_md_pw3);
+  sha256 (pw, pw_len, keystring_md_pw3);
   auth_status |= AC_ADMIN_AUTHORIZED;
   return 1;
 }
index f0b7ea5..e9c530d 100644 (file)
@@ -1,6 +1,6 @@
 CRYPTDIR = ../polarssl-0.14.0
 CRYPTSRCDIR = $(CRYPTDIR)/library
 CRYPTINCDIR = $(CRYPTDIR)/include
-CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/sha1.c \
+CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c \
        $(CRYPTSRCDIR)/aes.c \
-       call-rsa.c
+       sha256.c call-rsa.c
index cebb700..30cb99e 100644 (file)
@@ -198,7 +198,7 @@ extern int flash_key_write (uint8_t *key_addr, const uint8_t *key_data, const ui
 #define KEYSTRING_PASSLEN_SIZE  1
 #define KEYSTRING_SALT_SIZE     8 /* optional */
 #define KEYSTRING_ITER_SIZE     1 /* optional */
-#define KEYSTRING_MD_SIZE       20
+#define KEYSTRING_MD_SIZE       32
 #define KEYSTRING_SIZE_PW1 (KEYSTRING_PASSLEN_SIZE+KEYSTRING_MD_SIZE)
 #define KEYSTRING_SIZE_RC  (KEYSTRING_PASSLEN_SIZE+KEYSTRING_MD_SIZE)
 #define KEYSTRING_SIZE_PW3 (KEYSTRING_PASSLEN_SIZE+KEYSTRING_SALT_SIZE \
index 348bc04..c333234 100644 (file)
 #include "sys.h"
 #include "gnuk.h"
 #include "openpgp.h"
+#include "sha256.h"
 
 #include "polarssl/config.h"
 #include "polarssl/aes.h"
-#include "polarssl/sha1.h"
 
 #define PASSWORD_ERRORS_MAX 3  /* >= errors, it will be locked */
 static const uint8_t *pw_err_counter_p[3];
@@ -543,7 +543,7 @@ proc_resetting_code (const uint8_t *data, int len)
 
   newpw_len = len;
   newpw = data;
-  sha1 (newpw, newpw_len, new_ks);
+  sha256 (newpw, newpw_len, new_ks);
   new_ks0[0] = newpw_len;
   r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks);
   if (r <= -2)
@@ -780,8 +780,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
       uint8_t ks123_pw1[KEYSTRING_SIZE_PW1];
 
       ks123_pw1[0] = strlen (OPENPGP_CARD_INITIAL_PW1);
-      sha1 ((uint8_t *)OPENPGP_CARD_INITIAL_PW1, 
-           strlen (OPENPGP_CARD_INITIAL_PW1), ks123_pw1+1);
+      sha256 ((uint8_t *)OPENPGP_CARD_INITIAL_PW1, 
+             strlen (OPENPGP_CARD_INITIAL_PW1), ks123_pw1+1);
       encrypt (ks123_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE);
     }
 
index e6605aa..2fa8f0a 100644 (file)
@@ -27,8 +27,7 @@
 #include "gnuk.h"
 #include "sys.h"
 #include "openpgp.h"
-#include "polarssl/config.h"
-#include "polarssl/sha1.h"
+#include "sha256.h"
 
 #define CLS(a) a.cmd_apdu_head[0]
 #define INS(a) a.cmd_apdu_head[1]
@@ -225,6 +224,7 @@ cmd_change_password (void)
   const uint8_t *newpw;
   int pw_len, newpw_len;
   int who = p2 - 0x80;
+  int who_old;
   int r;
 
   DEBUG_INFO ("Change PW\r\n");
@@ -244,6 +244,7 @@ cmd_change_password (void)
       const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
 
       pw_len = verify_user_0 (AC_PSO_CDS_AUTHORIZED, pw, len, -1, ks_pw1);
+      who_old = who;
 
       if (pw_len < 0)
        {
@@ -284,14 +285,15 @@ cmd_change_password (void)
          newpw = pw + pw_len;
          newpw_len = len - pw_len;
          gpg_set_pw3 (newpw, newpw_len);
+         who_old = admin_authorized;
        }
     }
 
-  sha1 (pw, pw_len, old_ks);
-  sha1 (newpw, newpw_len, new_ks);
+  sha256 (pw, pw_len, old_ks);
+  sha256 (newpw, newpw_len, new_ks);
   new_ks0[0] = newpw_len;
 
-  r = gpg_change_keystring (who, old_ks, who, new_ks);
+  r = gpg_change_keystring (who_old, old_ks, who, new_ks);
   if (r <= -2)
     {
       DEBUG_INFO ("memory error.\r\n");
@@ -366,8 +368,8 @@ cmd_reset_user_password (void)
       pw_len = ks_rc[0];
       newpw = pw + pw_len;
       newpw_len = len - pw_len;
-      sha1 (pw, pw_len, old_ks);
-      sha1 (newpw, newpw_len, new_ks);
+      sha256 (pw, pw_len, old_ks);
+      sha256 (newpw, newpw_len, new_ks);
       new_ks0[0] = newpw_len;
       r = gpg_change_keystring (BY_RESETCODE, old_ks, BY_USER, new_ks);
       if (r <= -2)
@@ -418,7 +420,7 @@ cmd_reset_user_password (void)
 
       newpw_len = len;
       newpw = pw;
-      sha1 (newpw, newpw_len, new_ks);
+      sha256 (newpw, newpw_len, new_ks);
       new_ks0[0] = newpw_len;
       r = gpg_change_keystring (admin_authorized, old_ks, BY_USER, new_ks);
       if (r <= -2)
diff --git a/src/sha256.c b/src/sha256.c
new file mode 100644 (file)
index 0000000..d896296
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * sha256.c -- Compute SHA-256 hash
+ *
+ * Just for little endian architecture.
+ *
+ * Code taken from:
+ *  http://gladman.plushost.co.uk/oldsite/cryptography_technology/sha/index.php
+ *
+ *  File names are sha2.c, sha2.h, brg_types.h, brg_endian.h
+ *  in the archive sha2-07-01-07.zip.
+ *
+ * Code is modified in the style of PolarSSL API.
+ *
+ * See original copyright notice below.
+ */
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 2002, Dr Brian Gladman, Worcester, UK.   All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+   1. distributions of this source code include the above copyright
+      notice, this list of conditions and the following disclaimer;
+
+   2. distributions in binary form include the above copyright
+      notice, this list of conditions and the following disclaimer
+      in the documentation and/or other associated materials;
+
+   3. the copyright holder's name is not used to endorse products
+      built using this software without specific written permission.
+
+ ALTERNATIVELY, provided that this notice is retained in full, this product
+ may be distributed under the terms of the GNU General Public License (GPL),
+ in which case the provisions of the GPL apply INSTEAD OF those given above.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 01/08/2005
+*/
+
+#include <string.h>
+#include <stdlib.h>
+#include "sha256.h"
+
+#define SHA256_DIGEST_SIZE  32
+#define SHA256_BLOCK_SIZE   64
+#define SHA256_MASK (SHA256_BLOCK_SIZE - 1)
+
+static void bswap32_buf (uint32_t *p, int n)
+{
+  while (n--)
+    p[n] = __builtin_bswap32 (p[n]); /* bswap32 is GCC extention */
+}
+
+#define rotr32(x,n)   (((x) >> n) | ((x) << (32 - n)))
+
+#define ch(x,y,z)       ((z) ^ ((x) & ((y) ^ (z))))
+#define maj(x,y,z)      (((x) & (y)) | ((z) & ((x) ^ (y))))
+
+/* round transforms for SHA256 compression functions */
+#define vf(n,i) v[(n - i) & 7]
+
+#define hf(i) (p[i & 15] += \
+    g_1(p[(i + 14) & 15]) + p[(i + 9) & 15] + g_0(p[(i + 1) & 15]))
+
+#define v_cycle(i,j)                                \
+    vf(7,i) += (j ? hf(i) : p[i]) + k_0[i+j]        \
+    + s_1(vf(4,i)) + ch(vf(4,i),vf(5,i),vf(6,i));   \
+    vf(3,i) += vf(7,i);                             \
+    vf(7,i) += s_0(vf(0,i))+ maj(vf(0,i),vf(1,i),vf(2,i))
+
+#define s_0(x)  (rotr32((x),  2) ^ rotr32((x), 13) ^ rotr32((x), 22))
+#define s_1(x)  (rotr32((x),  6) ^ rotr32((x), 11) ^ rotr32((x), 25))
+#define g_0(x)  (rotr32((x),  7) ^ rotr32((x), 18) ^ ((x) >>  3))
+#define g_1(x)  (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10))
+#define k_0     k256
+
+const uint32_t k256[64] = {
+  0X428A2F98, 0X71374491, 0XB5C0FBCF, 0XE9B5DBA5,
+  0X3956C25B, 0X59F111F1, 0X923F82A4, 0XAB1C5ED5,
+  0XD807AA98, 0X12835B01, 0X243185BE, 0X550C7DC3,
+  0X72BE5D74, 0X80DEB1FE, 0X9BDC06A7, 0XC19BF174,
+  0XE49B69C1, 0XEFBE4786, 0X0FC19DC6, 0X240CA1CC,
+  0X2DE92C6F, 0X4A7484AA, 0X5CB0A9DC, 0X76F988DA,
+  0X983E5152, 0XA831C66D, 0XB00327C8, 0XBF597FC7,
+  0XC6E00BF3, 0XD5A79147, 0X06CA6351, 0X14292967,
+  0X27B70A85, 0X2E1B2138, 0X4D2C6DFC, 0X53380D13,
+  0X650A7354, 0X766A0ABB, 0X81C2C92E, 0X92722C85,
+  0XA2BFE8A1, 0XA81A664B, 0XC24B8B70, 0XC76C51A3,
+  0XD192E819, 0XD6990624, 0XF40E3585, 0X106AA070,
+  0X19A4C116, 0X1E376C08, 0X2748774C, 0X34B0BCB5,
+  0X391C0CB3, 0X4ED8AA4A, 0X5B9CCA4F, 0X682E6FF3,
+  0X748F82EE, 0X78A5636F, 0X84C87814, 0X8CC70208,
+  0X90BEFFFA, 0XA4506CEB, 0XBEF9A3F7, 0XC67178F2,
+};
+
+void
+sha256_process (sha256_context *ctx)
+{
+  uint32_t i;
+  uint32_t *p = ctx->wbuf;
+  uint32_t v[8];
+
+  memcpy (v, ctx->state, 8 * sizeof (uint32_t));
+
+  for (i = 0; i < 64; i += 16)
+    {
+      v_cycle ( 0, i);
+      v_cycle ( 1, i);
+      v_cycle ( 2, i);
+      v_cycle ( 3, i);
+      v_cycle ( 4, i);
+      v_cycle ( 5, i);
+      v_cycle ( 6, i);
+      v_cycle ( 7, i);
+      v_cycle ( 8, i);
+      v_cycle ( 9, i);
+      v_cycle (10, i);
+      v_cycle (11, i);
+      v_cycle (12, i);
+      v_cycle (13, i);
+      v_cycle (14, i);
+      v_cycle (15, i);
+    }
+
+  ctx->state[0] += v[0];
+  ctx->state[1] += v[1];
+  ctx->state[2] += v[2];
+  ctx->state[3] += v[3];
+  ctx->state[4] += v[4];
+  ctx->state[5] += v[5];
+  ctx->state[6] += v[6];
+  ctx->state[7] += v[7];
+}
+
+void
+sha256_update (sha256_context *ctx, const unsigned char *input,
+              unsigned int ilen)
+{
+  uint32_t left = (ctx->total[0] & SHA256_MASK);
+  uint32_t fill = SHA256_BLOCK_SIZE - left;
+
+  ctx->total[0] += ilen;
+  if (ctx->total[0] < ilen)
+    ctx->total[1]++;
+
+  while (ilen >= fill)
+    {
+      memcpy (((unsigned char*)ctx->wbuf) + left, input, fill);
+      bswap32_buf (ctx->wbuf, SHA256_BLOCK_SIZE >> 2);
+      sha256_process (ctx);
+      input += fill;
+      ilen -= fill;
+      left = 0;
+      fill = SHA256_BLOCK_SIZE;
+    }
+
+  memcpy (((unsigned char*)ctx->wbuf) + left, input, ilen);
+}
+
+void
+sha256_finish (sha256_context *ctx, unsigned char output[32])
+{
+  uint32_t last = (ctx->total[0] & SHA256_MASK);
+
+  bswap32_buf (ctx->wbuf, (last + 3) >> 2);
+
+  ctx->wbuf[last >> 2] &= 0xffffff80 << (8 * (~last & 3));
+  ctx->wbuf[last >> 2] |= 0x00000080 << (8 * (~last & 3));
+
+  if (last > SHA256_BLOCK_SIZE - 9)
+    {
+      if (last < 60)
+       ctx->wbuf[15] = 0;
+      sha256_process (ctx);
+      last = 0;
+    }
+  else
+    last = (last >> 2) + 1;
+
+  while (last < 14)
+    ctx->wbuf[last++] = 0;
+
+  ctx->wbuf[14] = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
+  ctx->wbuf[15] = ctx->total[0] << 3;
+  sha256_process (ctx);
+
+  bswap32_buf (ctx->state, SHA256_DIGEST_SIZE >> 2);
+  memcpy (output, ctx->state, SHA256_DIGEST_SIZE);
+}
+
+const uint32_t initial_state[8] =
+{
+  0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+  0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
+};
+
+void
+sha256_start (sha256_context *ctx)
+{
+  ctx->total[0] = ctx->total[1] = 0;
+  memcpy (ctx->state, initial_state, 8 * sizeof(uint32_t));
+}
+
+void
+sha256 (const unsigned char *input, unsigned int ilen,
+       unsigned char output[32])
+{
+  sha256_context ctx;
+
+  sha256_start (&ctx);
+  sha256_update (&ctx, input, ilen);
+  sha256_finish (&ctx, output);
+
+  memset (&ctx, 0, sizeof (sha256_context));
+}
diff --git a/src/sha256.h b/src/sha256.h
new file mode 100644 (file)
index 0000000..d52fb77
--- /dev/null
@@ -0,0 +1,14 @@
+typedef struct
+{
+  uint32_t total[2];
+  uint32_t state[8];
+  uint32_t wbuf[16];
+} sha256_context;
+
+extern void sha256 (const unsigned char *input, unsigned int ilen,
+                   unsigned char output[32]);
+extern void sha256_start (sha256_context *ctx);
+extern void sha256_finish (sha256_context *ctx, unsigned char output[32]);
+extern void sha256_update (sha256_context *ctx, const unsigned char *input,
+                          unsigned int ilen);
+extern void sha256_process (sha256_context *ctx);