This commit is contained in:
NIIBE Yutaka
2012-06-14 08:46:59 +09:00
parent 81f8f94dd4
commit 670e9058f1
10 changed files with 292 additions and 32 deletions

View File

@@ -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> 2012-06-13 Niibe Yutaka <gniibe@fsij.org>
Bug fixes.
* src/main.c (display_interaction): Assign to main_mode. * 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. Key generation is configure option.
* src/configure (keygen): Add --enable-keygen option. * src/configure (keygen): Add --enable-keygen option.

5
NEWS
View File

@@ -8,6 +8,11 @@ Gnuk NEWS - User visible changes
Finally, key generation is supported. Note that it is very slow. It Finally, key generation is supported. Note that it is very slow. It
will takes a few minutes to generate two keys. 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 * Major changes in Gnuk 0.19

10
README
View File

@@ -189,6 +189,11 @@ Souce code
Gnuk source code is under src/ directory. 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 License
======= =======
@@ -197,7 +202,7 @@ It is distributed under GNU General Public Licence version 3 or later
(GPLv3+). Please see src/COPYING. (GPLv3+). Please see src/COPYING.
Please note that it is distributed with external source code too. 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 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 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 * polarssl-0.14.0/ -- PolarSSL 0.14.0
Taken from http://polarssl.org/ Taken from http://polarssl.org/
We use PolarSSL for RSA computation, AES encryption/decryption We use PolarSSL for RSA computation, AES encryption/decryption.
and SHA-1 computation.
The file include/polarssl/bn_mul.h is heavily modified for ARM The file include/polarssl/bn_mul.h is heavily modified for ARM
Cortex-M3. Cortex-M3.

View File

@@ -24,9 +24,7 @@
#include "config.h" #include "config.h"
#include "ch.h" #include "ch.h"
#include "gnuk.h" #include "gnuk.h"
#include "sha256.h"
#include "polarssl/config.h"
#include "polarssl/sha1.h"
uint8_t volatile auth_status; /* Initialized to AC_NONE_AUTHORIZED */ 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: success_one_step:
sha1 (pw, pw_len, keystring); sha256 (pw, pw_len, keystring);
if (access == AC_PSO_CDS_AUTHORIZED) if (access == AC_PSO_CDS_AUTHORIZED)
{ {
r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring); 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, calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len,
uint8_t md[KEYSTRING_MD_SIZE]) 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) while (count > pw_len + 8)
{ {
sha1_update (&sha1_ctx, salt, 8); sha256_update (&sha256_ctx, salt, 8);
sha1_update (&sha1_ctx, pw, pw_len); sha256_update (&sha256_ctx, pw, pw_len);
count -= pw_len + 8; count -= pw_len + 8;
} }
if (count <= 8) if (count <= 8)
sha1_update (&sha1_ctx, salt, count); sha256_update (&sha256_ctx, salt, count);
else else
{ {
sha1_update (&sha1_ctx, salt, 8); sha256_update (&sha256_ctx, salt, 8);
count -= 8; count -= 8;
sha1_update (&sha1_ctx, pw, count); sha256_update (&sha256_ctx, pw, count);
} }
sha1_finish (&sha1_ctx, md); sha256_finish (&sha256_ctx, md);
memset (&sha1_ctx, 0, sizeof (sha1_ctx));
} }
uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE]; uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
@@ -283,7 +280,7 @@ verify_admin (const uint8_t *pw, int pw_len)
if (r <= 0) if (r <= 0)
return r; return r;
sha1 (pw, pw_len, keystring_md_pw3); sha256 (pw, pw_len, keystring_md_pw3);
auth_status |= AC_ADMIN_AUTHORIZED; auth_status |= AC_ADMIN_AUTHORIZED;
return 1; return 1;
} }

View File

@@ -1,6 +1,6 @@
CRYPTDIR = ../polarssl-0.14.0 CRYPTDIR = ../polarssl-0.14.0
CRYPTSRCDIR = $(CRYPTDIR)/library CRYPTSRCDIR = $(CRYPTDIR)/library
CRYPTINCDIR = $(CRYPTDIR)/include CRYPTINCDIR = $(CRYPTDIR)/include
CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/sha1.c \ CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c \
$(CRYPTSRCDIR)/aes.c \ $(CRYPTSRCDIR)/aes.c \
call-rsa.c sha256.c call-rsa.c

View 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_PASSLEN_SIZE 1
#define KEYSTRING_SALT_SIZE 8 /* optional */ #define KEYSTRING_SALT_SIZE 8 /* optional */
#define KEYSTRING_ITER_SIZE 1 /* 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_PW1 (KEYSTRING_PASSLEN_SIZE+KEYSTRING_MD_SIZE)
#define KEYSTRING_SIZE_RC (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 \ #define KEYSTRING_SIZE_PW3 (KEYSTRING_PASSLEN_SIZE+KEYSTRING_SALT_SIZE \

View File

@@ -28,10 +28,10 @@
#include "sys.h" #include "sys.h"
#include "gnuk.h" #include "gnuk.h"
#include "openpgp.h" #include "openpgp.h"
#include "sha256.h"
#include "polarssl/config.h" #include "polarssl/config.h"
#include "polarssl/aes.h" #include "polarssl/aes.h"
#include "polarssl/sha1.h"
#define PASSWORD_ERRORS_MAX 3 /* >= errors, it will be locked */ #define PASSWORD_ERRORS_MAX 3 /* >= errors, it will be locked */
static const uint8_t *pw_err_counter_p[3]; 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_len = len;
newpw = data; newpw = data;
sha1 (newpw, newpw_len, new_ks); sha256 (newpw, newpw_len, new_ks);
new_ks0[0] = newpw_len; new_ks0[0] = newpw_len;
r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks); r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks);
if (r <= -2) 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]; uint8_t ks123_pw1[KEYSTRING_SIZE_PW1];
ks123_pw1[0] = strlen (OPENPGP_CARD_INITIAL_PW1); ks123_pw1[0] = strlen (OPENPGP_CARD_INITIAL_PW1);
sha1 ((uint8_t *)OPENPGP_CARD_INITIAL_PW1, sha256 ((uint8_t *)OPENPGP_CARD_INITIAL_PW1,
strlen (OPENPGP_CARD_INITIAL_PW1), ks123_pw1+1); strlen (OPENPGP_CARD_INITIAL_PW1), ks123_pw1+1);
encrypt (ks123_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE); encrypt (ks123_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE);
} }

View File

@@ -27,8 +27,7 @@
#include "gnuk.h" #include "gnuk.h"
#include "sys.h" #include "sys.h"
#include "openpgp.h" #include "openpgp.h"
#include "polarssl/config.h" #include "sha256.h"
#include "polarssl/sha1.h"
#define CLS(a) a.cmd_apdu_head[0] #define CLS(a) a.cmd_apdu_head[0]
#define INS(a) a.cmd_apdu_head[1] #define INS(a) a.cmd_apdu_head[1]
@@ -225,6 +224,7 @@ cmd_change_password (void)
const uint8_t *newpw; const uint8_t *newpw;
int pw_len, newpw_len; int pw_len, newpw_len;
int who = p2 - 0x80; int who = p2 - 0x80;
int who_old;
int r; int r;
DEBUG_INFO ("Change PW\r\n"); 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); 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); pw_len = verify_user_0 (AC_PSO_CDS_AUTHORIZED, pw, len, -1, ks_pw1);
who_old = who;
if (pw_len < 0) if (pw_len < 0)
{ {
@@ -284,14 +285,15 @@ cmd_change_password (void)
newpw = pw + pw_len; newpw = pw + pw_len;
newpw_len = len - pw_len; newpw_len = len - pw_len;
gpg_set_pw3 (newpw, newpw_len); gpg_set_pw3 (newpw, newpw_len);
who_old = admin_authorized;
} }
} }
sha1 (pw, pw_len, old_ks); sha256 (pw, pw_len, old_ks);
sha1 (newpw, newpw_len, new_ks); sha256 (newpw, newpw_len, new_ks);
new_ks0[0] = newpw_len; 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) if (r <= -2)
{ {
DEBUG_INFO ("memory error.\r\n"); DEBUG_INFO ("memory error.\r\n");
@@ -366,8 +368,8 @@ cmd_reset_user_password (void)
pw_len = ks_rc[0]; pw_len = ks_rc[0];
newpw = pw + pw_len; newpw = pw + pw_len;
newpw_len = len - pw_len; newpw_len = len - pw_len;
sha1 (pw, pw_len, old_ks); sha256 (pw, pw_len, old_ks);
sha1 (newpw, newpw_len, new_ks); sha256 (newpw, newpw_len, new_ks);
new_ks0[0] = newpw_len; new_ks0[0] = newpw_len;
r = gpg_change_keystring (BY_RESETCODE, old_ks, BY_USER, new_ks); r = gpg_change_keystring (BY_RESETCODE, old_ks, BY_USER, new_ks);
if (r <= -2) if (r <= -2)
@@ -418,7 +420,7 @@ cmd_reset_user_password (void)
newpw_len = len; newpw_len = len;
newpw = pw; newpw = pw;
sha1 (newpw, newpw_len, new_ks); sha256 (newpw, newpw_len, new_ks);
new_ks0[0] = newpw_len; new_ks0[0] = newpw_len;
r = gpg_change_keystring (admin_authorized, old_ks, BY_USER, new_ks); r = gpg_change_keystring (admin_authorized, old_ks, BY_USER, new_ks);
if (r <= -2) if (r <= -2)

223
src/sha256.c Normal file
View File

@@ -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));
}

14
src/sha256.h Normal file
View File

@@ -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);