Now, v2 works.
authorNIIBE Yutaka <gniibe@fsij.org>
Mon, 30 Aug 2010 11:02:22 +0000 (20:02 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Mon, 30 Aug 2010 11:02:22 +0000 (20:02 +0900)
13 files changed:
README
polarssl-0.14.0/include/polarssl/config.h
src/Makefile
src/ac.c
src/crypt.mk [new file with mode: 0644]
src/debug.c [new file with mode: 0644]
src/flash.c
src/gen-gpg-data [new file with mode: 0644]
src/gnuk.h
src/gpg.c
src/openpgp-do.c
src/rsa-sign.c
src/rsa.mk [deleted file]

diff --git a/README b/README
index 8c2a6f6..603a15f 100644 (file)
--- a/README
+++ b/README
+Gnuk - A USB Token software implementation
+
+                                               Version 0.0     2010-09-01
+                                                             Niibe Yutaka
+
+What's Gnuk
+===========
+
+Gnuk is a USB token software implementation to use with GNU privacy
+guard.  Gnuk supports OpenPGP card protocol version 2, and it runs on
+Olimex STM32-H103 board.
+
+
+Release notes
+=============
+
+Initially, the development was started with a copy of the files in
+ChibiOS_2.0.2/demos/ARMCM3-STM32F103-GCC/*, Makefile, linker script,
+and header files (chconf.h, halconf.h, and mcuconf.h).
+
+Since this is the initial release, some garbages still remain.
+
+
+Target
+======
+
+We use Olimex STM32-H103 board.
+
+I think that it runs on Olimex STM32-P103 too.  We are porting to
+STM32 Primer 2.
+
+
 Souce code
 ==========
 
-Initially, it is copy of ChibiOS_2.0.2/demos/ARMCM3-STM32F103-GCC/*.
+Gnuk source code is under src/ directory.
+
+
+License
+=======
+
+It is distributed under GNU General Public Licence version 3 or later
+(GPLv3+).
+
 
-External source
-===============
+External source code
+====================
 
-* ChibiOS_2.0.2
+Gnuk is distributed with external source code.
+
+* ChibiOS_2.0.2/  -- ChibiOS/RT 2.0.2
 Taken from http://chibios.sourceforge.net/
 Note that CRLF is converted to LF in this repository.
+We use ChibiOS/RT as the kernel for Gnuk.
 
-* PolarSSS 0.14.0
+* polarssl-0.14.0/  -- PolarSSL 0.14.0
 Taken from http://polarssl.org/
+We use PolarSSL for RSA computation.
+
+
+* STM32_USB-FS-Device_Driver/ -- a part of USB-FS-Device_Lib
+* Virtual_COM_Port/ -- a part of USB-FS-Device_Lib
+
+STM32F10x USB Full Speed Device Library (USB-FS-Device_Lib)
+is a STM32F10x library for USB functionality.
 
-* STM32F10x USB Full Speed Device Library (USB-FS-Device_Lib)
 I took Libraries/STM32_USB-FS-Device_Driver and a part of
-Project/Virtual_COM_Port in STM32_USB-FS-Device_Lib distribution.
+Project/ in STM32_USB-FS-Device_Lib distribution.
 See http://www.st.com for detail.
 
 
-HOWTO RUN
-=================
+How to compile
+==============
+
+You need GNU Toolchain and newlib for 'arm-none-eabi' target.
+
+See http://github.com/esden/summon-arm-toolchain/ for preparation of
+GNU Toolchain for 'arm-none-eabi' target.
+
+  $ cd gnuk-VERSION/src
+  $ make
+
+Then, we will have "gnuk.elf".
+
+
+How to run
+==========
+
+If you are using Olimex JTAG-Tiny, type following to invoke OpenOCD:
+
+  $ openocd -f interface/olimex-jtag-tiny.cfg -f board/olimex_stm32_h103.cfg
+
+Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
+
+  $ telnet localhost 4444
+  > reset halt
+  > flash write_image erase gnuk.elf
+  > reset
+  > exit
+  $ 
+
+
+How to debug
+============
 
-$ openocd -f interface/olimex-jtag-tiny.cfg -f board/olimex_stm32_h103.cfg
+We can use GDB.
 
-$ arm-none-eabi-gdb --annotate=3 gnuk.elf
+  $ arm-none-eabi-gdb gnuk.elf
 
-$ telnet localhost 4444
-> reset halt
-> flash write_image erase gnuk.elf
-> reset
-> exit
-$ 
+-- 
index 96058f2..c51df72 100644 (file)
@@ -92,9 +92,8 @@
 
 /*
  * Uncomment this macro to store the AES tables in ROM.
- *
-#define POLARSSL_AES_ROM_TABLES
  */
+#define POLARSSL_AES_ROM_TABLES
 
 /*
  * Module:  library/aes.c
index 729b32b..6fe84aa 100644 (file)
@@ -66,7 +66,7 @@ include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/port.mk
 include $(CHIBIOS)/os/kernel/kernel.mk
 include stmusb.mk
 include vcomport.mk
-include rsa.mk
+include crypt.mk
 include ../boards/OLIMEX_STM32_H103/board.mk
 
 # C sources that can be compiled in ARM or THUMB mode depending on the global
@@ -80,15 +80,16 @@ CSRC = $(PORTSRC) \
        $(CHIBIOS)/os/various/syscalls.c \
        $(STMUSBSRC) \
        $(VCOMSRC) \
-       $(RSASRC) \
-       main.c hw_config.c usb_lld.c usb_desc.c usb_prop.c \
+       $(CRYPTSRC) \
+       main.c debug.c usb_lld.c \
+       hw_config.c usb_desc.c usb_prop.c \
        usb-icc.c gpg.c ac.c openpgp-do.c flash.c
 
 # List ASM source files here
 ASMSRC = $(PORTASM) \
          $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/vectors.s gpg-data.s
 
-INCDIR = $(RSAINCDIR) $(STMUSBINCDIR) $(VCOMDIR) \
+INCDIR = $(CRYPTINCDIR) $(STMUSBINCDIR) $(VCOMDIR) \
         $(PORTINC) $(KERNINC) $(TESTINC) \
          $(HALINC) $(PLATFORMINC) $(BOARDINC) \
          $(CHIBIOS)/os/various
index c48b9d1..0115095 100644 (file)
--- a/src/ac.c
+++ b/src/ac.c
@@ -5,6 +5,9 @@
 #include "ch.h"
 #include "gnuk.h"
 
+#include "polarssl/config.h"
+#include "polarssl/sha1.h"
+
 static uint8_t auth_status = AC_NONE_AUTHORIZED;
 
 int
@@ -26,16 +29,21 @@ ac_check_status (uint8_t ac_flag)
  * check magic in params
  */
 
+uint8_t keystring_pw1[KEYSTRING_LEN] = {
+  0x62, 0x10, 0x27, 0x44, 0x34, 0x05, 0x2f, 0x20,
+  0xfc, 0xb8, 0x3e, 0x1d, 0x0f, 0x49, 0x22, 0x04,
+  0xfc, 0xb1, 0x18, 0x84
+};
+
 int
 verify_pso_cds (uint8_t *pw, int pw_len)
 {
-#if 0
-  compute_hash;
-  if (cmp_hash (pw1_hash, hash) == 0)
-    good;
-  else
-    return -1;
-#endif
+  int r;
+
+  sha1 (pw, pw_len, keystring_pw1);
+  if ((r = gpg_load_key (GPG_KEY_FOR_SIGNATURE)) < 0)
+    return r;
+
   auth_status |= AC_PSO_CDS_AUTHORIZED;
   return 0;
 }
@@ -43,13 +51,6 @@ verify_pso_cds (uint8_t *pw, int pw_len)
 int
 verify_pso_other (uint8_t *pw, int pw_len)
 {
-#if 0
-  compute_hash;
-  if (cmp_hash (pw1_hash, hash) == 0)
-    good;
-  else
-    return -1;
-#endif
   auth_status |= AC_PSO_OTHER_AUTHORIZED;
   return 0;
 }
diff --git a/src/crypt.mk b/src/crypt.mk
new file mode 100644 (file)
index 0000000..0304fdc
--- /dev/null
@@ -0,0 +1,6 @@
+CRYPTDIR = ../polarssl-0.14.0
+CRYPTSRCDIR = $(CRYPTDIR)/library
+CRYPTINCDIR = $(CRYPTDIR)/include
+CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/sha1.c \
+       $(CRYPTSRCDIR)/aes.c \
+       rsa-sign.c
diff --git a/src/debug.c b/src/debug.c
new file mode 100644 (file)
index 0000000..ef58242
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * debug.c -- Debuging with virtual COM port
+ *
+ * Copyright (C) 2010 Free Software Initiative of Japan
+ * Author: NIIBE Yutaka <gniibe@fsij.org>
+ *
+ * This file is a part of Gnuk, a GnuPG USB Token implementation.
+ *
+ * Gnuk is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Gnuk is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "config.h"
+#include "ch.h"
+#include "gnuk.h"
+
+static void
+put_hex (uint8_t nibble)
+{
+  uint8_t c;
+
+  if (nibble < 0x0a)
+    c = '0' + nibble;
+  else
+    c = 'a' + nibble - 0x0a;
+
+  _write (&c, 1);
+}
+
+void
+put_byte (uint8_t b)
+{
+  put_hex (b >> 4);
+  put_hex (b &0x0f);
+  _write ("\r\n", 2);
+}
+
+void
+put_byte_with_no_nl (uint8_t b)
+{
+  _write (" ", 1);
+  put_hex (b >> 4);
+  put_hex (b &0x0f);
+}
+
+void
+put_short (uint16_t x)
+{
+  put_hex (x >> 12);
+  put_hex ((x >> 8)&0x0f);
+  put_hex ((x >> 4)&0x0f);
+  put_hex (x & 0x0f);
+  _write ("\r\n", 2);
+}
+
+void
+put_string (const char *s)
+{
+  _write (s, strlen (s));
+}
+
+
index 8f173dc..fbb3c4a 100644 (file)
  *
  */
 
+/*
+ * Writing to Flash ROM is NOT YET IMPLEMENTED, just API only
+ */
+
 #include "ch.h"
 #include "gnuk.h"
 
+static uint8_t do_pool[256];
+static uint8_t *last_p = do_pool;
+
+/*
+ * TLV (Tag, Length, and Value)
+ */
 uint8_t *
 flash_do_write (uint16_t tag, uint8_t *data, int len)
 {
-  static uint8_t do_pool[1024];
-  static uint8_t *last_p = do_pool;
   uint8_t *p = last_p;
 
   if (last_p - do_pool + len + 2 + 3 > 1024)
@@ -54,3 +62,35 @@ flash_do_write (uint16_t tag, uint8_t *data, int len)
 
   return p + 2;
 }
+
+static uint8_t k1[KEY_CONTENT_LEN];
+#if 0
+static uint8_t k2[KEY_CONTENT_LEN];
+static uint8_t k3[KEY_CONTENT_LEN];
+#endif
+
+uint8_t *
+flash_key_alloc (enum kind_of_key kk)
+{
+  switch (kk)
+    {
+    case GPG_KEY_FOR_SIGNATURE:
+      return k1;
+#if 0
+    case GPG_KEY_FOR_DECRYPT:
+      return k2;
+    case GPG_KEY_FOR_AUTHENTICATION:
+      return k3;
+#else
+    default:
+      return k1;
+#endif
+    }
+}
+
+int
+flash_key_write (uint8_t *key_addr, uint8_t *key_data)
+{
+  memcpy (key_addr, key_data, KEY_CONTENT_LEN);
+  return 0;
+}
diff --git a/src/gen-gpg-data b/src/gen-gpg-data
new file mode 100644 (file)
index 0000000..0d0152b
--- /dev/null
@@ -0,0 +1,15 @@
+#! /bin/sh
+
+arm-none-eabi-gcc -S -mcpu=cortex-m3 -O0 -ggdb -fomit-frame-pointer \
+    -falign-functions=16 -ffunction-sections \
+    -Wall -Wextra -Wstrict-prototypes -Wa,-alms=gpg-data.lst \
+    -DCORTEX_USE_BASEPRI=TRUE  -DTHUMB_PRESENT -mno-thumb-interwork \
+    -DTHUMB_NO_INTERWORKING -mthumb -DTHUMB \
+    -I . -I../STM32_USB-FS-Device_Driver/inc -I../USBCDC \
+    -I../ChibiOS_2.0.2/os/ports/GCC/ARMCMx \
+    -I../ChibiOS_2.0.2/os/ports/GCC/ARMCMx/STM32F10x \
+    -I../ChibiOS_2.0.2/os/ports/GCC/ARMCMx/cmsis \
+    -I../ChibiOS_2.0.2/os/kernel/include -I../ChibiOS_2.0.2/test \
+    -I../ChibiOS_2.0.2/os/hal/include \
+    -I../ChibiOS_2.0.2/os/hal/platforms/STM32 -I../boards/OLIMEX_STM32_H103 \
+    -I../ChibiOS_2.0.2/os/various gpg-data.c
index cc4c1fe..a4708ff 100644 (file)
@@ -1,6 +1,7 @@
 extern Thread *blinker_thread;
 
 extern void put_byte (uint8_t b);
+extern void put_byte_with_no_nl (uint8_t b);
 extern void put_short (uint16_t x);
 extern void put_string (const char *s);
 
@@ -50,3 +51,34 @@ extern void gpg_do_get_data (uint16_t tag);
 extern void gpg_do_put_data (uint16_t tag, uint8_t *data, int len);
 
 extern uint8_t * flash_do_write (uint16_t tag, uint8_t *data, int len);
+
+enum kind_of_key {
+  GPG_KEY_FOR_SIGNATURE,
+  GPG_KEY_FOR_DECRYPT,
+  GPG_KEY_FOR_AUTHENTICATION,
+};
+
+extern uint8_t *flash_key_alloc (enum kind_of_key);
+
+#define KEY_MAGIC_LEN 8
+#define KEY_CONTENT_LEN 256
+#define GNUK_MAGIC "Gnuk KEY"
+#define KEYSTORE_LEN (KEY_MAGIC_LEN+4+4+KEY_CONTENT_LEN)
+
+struct key_data {
+  uint8_t *key_addr;
+  /* encrypted data content */
+  char magic[KEY_MAGIC_LEN];
+  uint32_t random;
+  uint32_t check;
+  uint8_t data[KEY_CONTENT_LEN];
+};
+
+extern int flash_key_write (uint8_t *key_addr, uint8_t *key_data);
+
+#define KEYSTRING_LEN 20       /* Use 16-byte for AES encryption */
+extern uint8_t keystring_pw1[KEYSTRING_LEN];
+
+extern int gpg_load_key (enum kind_of_key kk);
+
+extern struct key_data kd;
index ffe25b0..eae0072 100644 (file)
--- a/src/gpg.c
+++ b/src/gpg.c
 #include "hal.h"
 #include "gnuk.h"
 
-static void
-put_hex (uint8_t nibble)
-{
-  uint8_t c;
-
-  if (nibble < 0x0a)
-    c = '0' + nibble;
-  else
-    c = 'a' + nibble - 0x0a;
-
-  _write (&c, 1);
-}
-
-void
-put_byte (uint8_t b)
-{
-  put_hex (b >> 4);
-  put_hex (b &0x0f);
-  _write ("\r\n", 2);
-}
-
-void
-put_short (uint16_t x)
-{
-  put_hex (x >> 12);
-  put_hex ((x >> 8)&0x0f);
-  put_hex ((x >> 4)&0x0f);
-  put_hex (x & 0x0f);
-  _write ("\r\n", 2);
-}
-
-void
-put_string (const char *s)
-{
-  _write (s, strlen (s));
-}
-
-
-#define RSA_SIGNATURE_LENGTH 128 /* 256 *//* 256 byte == 2048-bit */
+#define RSA_SIGNATURE_LENGTH 256 /* 256 byte == 2048-bit */
 extern unsigned char *rsa_sign (unsigned char *);
 
 #define INS_PUT_DATA      0xDA
@@ -277,6 +239,7 @@ process_command_apdu (void)
       if (cmd_APDU[2] == 0x9E && cmd_APDU[3] == 0x9A)
        {
          if (cmd_APDU_size != 8 + 35 && cmd_APDU_size != 8 + 35 + 1)
+           /* Extended Lc: 3-byte */
            {
              put_string (" wrong length: ");
              put_short (cmd_APDU_size);
index 61d3504..abbd70f 100644 (file)
@@ -26,6 +26,9 @@
 #include "ch.h"
 #include "gnuk.h"
 
+#include "polarssl/config.h"
+#include "polarssl/aes.h"
+
 /*
  * Compile time vars:
  *   AID, Historical Bytes (template), Extended Capabilities,
@@ -120,6 +123,7 @@ enum do_type {
   DO_CN_READ,
   DO_PROC_READ,
   DO_PROC_WRITE,
+  DO_PROC_READWRITE,
   DO_HASH,
   DO_KEYPTR
 };
@@ -142,6 +146,8 @@ static struct do_table_entry *get_do_entry (uint16_t tag);
 #define GNUK_DO_KEYPTR_DEC 0xff02
 #define GNUK_DO_KEYPTR_AUT 0xff03
 #define GNUK_DO_HASH_PW3   0xff04
+#define GNUK_DO_HASH_RC    0xff05
+#define GNUK_DO_PW_STATUS  0xff06
 
 #define GPG_DO_AID             0x004f
 #define GPG_DO_NAME            0x005b
@@ -311,24 +317,225 @@ do_kgtime_all (uint16_t tag)
 }
 
 static void
-put_hex (uint8_t nibble)
+rw_pw_status (uint16_t tag, uint8_t *data, int len, int is_write)
 {
-  uint8_t c;
+  struct do_table_entry *do_p;
+
+  if (is_write)
+    {
+      const uint8_t *do_data;
 
-  if (nibble < 0x0a)
-    c = '0' + nibble;
+      do_p = get_do_entry (GNUK_DO_PW_STATUS);
+      if (do_p)
+       {
+         do_data = (const uint8_t *)do_p->obj;
+         if (do_data)
+           memcpy (data, &do_data[2], SIZE_PW_STATUS_BYTES - 1);
+
+         do_p->obj = flash_do_write (tag, data, len);
+         if (do_p->obj)
+           write_res_apdu (NULL, 0, 0x90, 0x00); /* success */
+         else
+           write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
+       }
+      else
+       /* No record */
+       write_res_apdu (NULL, 0, 0x6a, 0x88);
+    }
   else
-    c = 'a' + nibble - 0x0a;
+    {
+      const uint8_t *do_data;
+
+      if (with_tag)
+       {
+         copy_tag (tag);
+         *res_p++ = SIZE_PW_STATUS_BYTES;
+       }
+
+      do_p = get_do_entry (GNUK_DO_PW_STATUS);
+      do_data = (const uint8_t *)do_p->obj;
+      if (do_data)
+       {
+         memcpy (res_p, &do_data[1], SIZE_PW_STATUS_BYTES);
+         res_p += SIZE_PW_STATUS_BYTES;
+       }
+      else
+       /* No record */
+       write_res_apdu (NULL, 0, 0x6a, 0x88);
+    }
+}
+
+static void
+proc_resetting_code (uint16_t tag, uint8_t *data, int len)
+{
+  /* Not implementad yet */
+  /*
+   * calculate hash, write it to GNUK_DO_HASH_RC.
+   */
+  /* Then, we need to reset RC counter in GNUK_DO_PW_STATUS */
+}
+
+static uint8_t iv[16];
+
+static aes_context aes;
+static int iv_offset;
 
-  _write (&c, 1);
+static void
+encrypt (uint8_t *key_str, uint8_t *data)
+{
+  aes_setkey_enc (&aes, key_str, 128);
+  memset (iv, 0, 16);
+  iv_offset = 0;
+  aes_crypt_cfb128 (&aes, AES_ENCRYPT, KEYSTORE_LEN, &iv_offset, iv, data, data);
+
+  {
+    int i, len = KEYSTORE_LEN;
+
+    put_string ("ENC\r\n");
+    for (i = 0; i < len; i++)
+      {
+       put_byte_with_no_nl (data[i]);
+       if ((i & 0x0f) == 0x0f)
+         _write ("\r\n", 2);
+      }
+    _write ("\r\n", 2);
+  }
 }
 
+struct key_data kd;
+
 static void
-o_put_byte (uint8_t b)
+decrypt (uint8_t *key_str, uint8_t *data)
+{
+  aes_setkey_enc (&aes, key_str, 128);
+  memset (iv, 0, 16);
+  iv_offset = 0;
+  aes_crypt_cfb128 (&aes, AES_DECRYPT, KEYSTORE_LEN, &iv_offset, iv, data, data);
+  {
+    int i, len = KEYSTORE_LEN;
+
+    put_string ("DEC\r\n");
+    for (i = 0; i < len; i++)
+      {
+       put_byte_with_no_nl (data[i]);
+       if ((i & 0x0f) == 0x0f)
+         _write ("\r\n", 2);
+      }
+    _write ("\r\n", 2);
+  }
+}
+
+int
+gpg_load_key (enum kind_of_key kk)
+{
+  struct do_table_entry *do_p;
+
+  switch (kk)
+    {
+    case GPG_KEY_FOR_SIGNATURE:
+      do_p = get_do_entry (GNUK_DO_KEYPTR_SIG);
+      break;
+    case GPG_KEY_FOR_DECRYPT:
+      do_p = get_do_entry (GNUK_DO_KEYPTR_DEC);
+      break;
+    case GPG_KEY_FOR_AUTHENTICATION:
+      do_p = get_do_entry (GNUK_DO_KEYPTR_AUT);
+      break;
+    }
+  if (do_p == NULL)
+    return -1;
+
+  kd.key_addr = *(uint8_t **)&((uint8_t *)do_p->obj)[1];
+  memcpy (((uint8_t *)&kd)+4, ((uint8_t *)do_p->obj)+5, KEY_MAGIC_LEN+4+4);
+  memcpy (kd.data, kd.key_addr, KEY_CONTENT_LEN);
+
+  decrypt (keystring_pw1, ((uint8_t *)&kd) + 4);
+  if (memcmp (kd.magic, GNUK_MAGIC, KEY_MAGIC_LEN) != 0)
+    return -1;
+  /* XXX: more sanity check */
+  return 0;
+}
+
+uint32_t
+get_random (void)
+{
+  return 0x80808080;           /* XXX: for now */
+}
+
+static uint32_t
+calc_check (uint8_t *data, int len)
+{
+  uint32_t check = 0;
+  int i;
+
+  for (i = 0; i < len; i++)
+    check += data[i];
+
+  return check;
+}
+
+static int
+gpg_write_do_keyptr (enum kind_of_key kk, uint8_t *key_data, int key_len)
 {
-  _write (" ", 1);
-  put_hex (b >> 4);
-  put_hex (b &0x0f);
+  uint8_t *p;
+  int len;
+  int r;
+  uint32_t key_addr;
+  struct do_table_entry *do_p;
+
+#if 0
+  assert (key_len == KEY_CONTENT_LEN+4);
+  /* key_data should starts with 00 01 00 01 (E) */
+#endif
+
+  put_short (key_len);
+
+  key_data += 4;
+
+  kd.key_addr = flash_key_alloc (kk);
+  if (kd.key_addr == NULL)
+    return -1;
+
+  memcpy (kd.magic, GNUK_MAGIC, KEY_MAGIC_LEN);
+  kd.check = calc_check (key_data, KEY_CONTENT_LEN);
+  kd.random = get_random ();
+  memcpy (kd.data, key_data, KEY_CONTENT_LEN);
+
+  put_string ("enc...");
+
+  encrypt (keystring_pw1, ((uint8_t *)&kd) + 4);
+
+  put_string ("done\r\n");
+
+  if ((r = flash_key_write (kd.key_addr, kd.data)) < 0)
+    return r;
+
+  switch (kk)
+    {
+    case GPG_KEY_FOR_SIGNATURE:
+      p = flash_do_write (GNUK_DO_KEYPTR_SIG, &kd,
+                         sizeof (kd) - KEY_CONTENT_LEN);
+      do_p = get_do_entry (GNUK_DO_KEYPTR_SIG);
+      do_p->obj = p;
+      break;
+    case GPG_KEY_FOR_DECRYPT:
+      p = flash_do_write (GNUK_DO_KEYPTR_DEC, &kd,
+                         sizeof (kd) - KEY_CONTENT_LEN);
+      do_p = get_do_entry (GNUK_DO_KEYPTR_DEC);
+      do_p->obj = p;
+      break;
+    case GPG_KEY_FOR_AUTHENTICATION:
+      p = flash_do_write (GNUK_DO_KEYPTR_AUT, &kd,
+                         sizeof (kd) - KEY_CONTENT_LEN);
+      do_p = get_do_entry (GNUK_DO_KEYPTR_AUT);
+      do_p->obj = p;
+      break;
+    }
+
+  if (p == NULL)
+    return -1;
+
+  return 0;
 }
 
 /*
@@ -338,22 +545,34 @@ o_put_byte (uint8_t b)
  *       91 xx
  *       92 xx
  *       93 xx
- *   5f48, xx: cardholder privatge key
+ *   5f48, xx: cardholder private key
  */
 static void
 proc_key_import (uint16_t tag, uint8_t *data, int len)
 {
-  int i;
+  int i, r;
+  enum kind_of_key kk;
 
   for (i = 0; i < len; i++)
     {
-      o_put_byte (data[i]);
+      put_byte_with_no_nl (data[i]);
       if ((i & 0x0f) == 0x0f)
        _write ("\r\n", 2);
     }
   _write ("\r\n", 2);
 
-  write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
+  if (data[4] == 0xa4)
+    kk = GPG_KEY_FOR_AUTHENTICATION;
+  else if (data[4] == 0xb8)
+    kk = GPG_KEY_FOR_DECRYPT;
+  else                         /* 0xb6 */
+    kk = GPG_KEY_FOR_SIGNATURE;
+
+  r = gpg_write_do_keyptr (kk, &data[22], len - 22);
+  if (r < 0)
+    write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
+  else
+    write_res_apdu (NULL, 0, 0x90, 0x00); /* success */
 }
 
 static const uint16_t const cn_ch_data[] = {
@@ -383,11 +602,16 @@ gpg_do_table[] = {
   { GNUK_DO_KEYPTR_DEC, DO_KEYPTR, AC_NEVER, AC_NEVER, NULL },
   { GNUK_DO_KEYPTR_AUT, DO_KEYPTR, AC_NEVER, AC_NEVER, NULL },
   { GNUK_DO_HASH_PW3, DO_HASH, AC_NEVER, AC_NEVER, NULL },
-  /* Pseudo DO: calculated */
+  { GNUK_DO_HASH_RC, DO_HASH, AC_NEVER, AC_NEVER, NULL },
+  { GNUK_DO_PW_STATUS, DO_VAR, AC_NEVER, AC_NEVER, NULL },
+  /* Pseudo DO READ: calculated */
   { GPG_DO_HIST_BYTES, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_hist_bytes },
   { GPG_DO_FP_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_fp_all },
   { GPG_DO_CAFP_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_cafp_all },
   { GPG_DO_KGTIME_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_kgtime_all },
+  /* Pseudo DO READ/WRITE: calculated */
+  { GPG_DO_PW_STATUS, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
+    rw_pw_status },
   /* Fixed data */
   { GPG_DO_AID, DO_FIXED, AC_ALWAYS, AC_NEVER, aid },
   { GPG_DO_EXTCAP, DO_FIXED, AC_ALWAYS, AC_NEVER, extended_capabilities },
@@ -397,7 +621,6 @@ gpg_do_table[] = {
   /* Variable(s): Fixed size, not changeable by user */
   { GPG_DO_DS_COUNT, DO_VAR, AC_ALWAYS, AC_NEVER, NULL },
   /* Variables: Fixed size */
-  { GPG_DO_PW_STATUS, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
   { GPG_DO_SEX, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
   { GPG_DO_FP_SIG, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
   { GPG_DO_FP_DEC, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
@@ -414,12 +637,13 @@ gpg_do_table[] = {
   { GPG_DO_NAME, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
   { GPG_DO_LANGUAGE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
   { GPG_DO_CH_CERTIFICATE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
-  /* Variable(s): Variable size, write only by user */
-  { GPG_DO_RESETTING_CODE, DO_VAR, AC_NEVER, AC_ADMIN_AUTHORIZED, NULL },
   /* Compound data: Read access only */
   { GPG_DO_CH_DATA, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_ch_data },
   { GPG_DO_APP_DATA, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_app_data },
   { GPG_DO_SS_TEMP, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_ss_temp },
+  /* Simple data: write access only */
+  { GPG_DO_RESETTING_CODE, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
+    proc_resetting_code },
   /* Compound data: Write access only*/
   { GPG_DO_KEY_IMPORT, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
     proc_key_import },
@@ -448,7 +672,7 @@ gpg_do_table_init (void)
 
   do_p = get_do_entry (GPG_DO_LOGIN_DATA);
   do_p->obj = do_5e;
-  do_p = get_do_entry (GPG_DO_PW_STATUS);
+  do_p = get_do_entry (GNUK_DO_PW_STATUS);
   do_p->obj = do_c4;
 #if 0
   do_p = get_do_entry (GPG_DO_FP_SIG);
@@ -578,6 +802,14 @@ copy_do (struct do_table_entry *do_p)
        do_func (do_p->tag);
        break;
       }
+    case DO_PROC_READWRITE:
+      {
+       void (*rw_func)(uint16_t, uint8_t *, int, int)
+         = (void (*)(uint16_t, uint8_t *, int, int))do_p->obj;
+
+       rw_func (do_p->tag, NULL, 0, 0);
+       break;
+      }
     case DO_PROC_WRITE:
     case DO_HASH:
     case DO_KEYPTR:
@@ -655,33 +887,25 @@ gpg_do_put_data (uint16_t tag, uint8_t *data, int len)
 
            flash_do_release (do_data);
 #endif
-           if (tag == GPG_DO_PW_STATUS)
-             {
-               /* XXX: only the first byte can be changed */
-             }
+           if (len == 0)
+             /* make DO empty */
+             do_p->obj = NULL;
            else
              {
-               if (len == 0)
-                 /* make DO empty */
-                 do_p->obj = NULL;
+               do_p->obj = flash_do_write (tag, data, len);
+               if (do_p->obj)
+                 write_res_apdu (NULL, 0, 0x90, 0x00); /* success */
                else
-                 {
-                   do_p->obj = flash_do_write (tag, data, len);
-                   if (do_p->obj)
-                     write_res_apdu (NULL, 0, 0x90, 0x00); /* success */
-                   else
-                     write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
-                 }
+                 write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
              }
+           break;
+         }
+       case DO_PROC_READWRITE:
+         {
+           void (*rw_func)(uint16_t, uint8_t *, int, int)
+             = (void (*)(uint16_t, uint8_t *, int, int))do_p->obj;
 
-           /*
-            *
-            */
-           if (tag == GPG_DO_RESETTING_CODE)
-             {
-               /* XXX: Changing Resetting code,
-                * we need to reset RC counter in GPG_DO_PW_STATUS */
-             }
+           rw_func (tag, data, len, 1);
            break;
          }
        case DO_PROC_WRITE:
index 7f129ed..d49cbdd 100644 (file)
 #include "ch.h"
 #include "gnuk.h"
-#include <polarssl/config.h>
-#include <polarssl/rsa.h>
+#include "polarssl/config.h"
+#include "polarssl/rsa.h"
 
 static unsigned char output[256];
-
-/* big endian */
-static const unsigned char p[64] = {
-  0xe3,0xec,0x42,0x6c,0x23,0x37,0x1f,0x96,
-  0x55,0x2f,0x1d,0x2a,0x37,0xd2,0x66,0x43,
-  0x3c,0xb1,0xa5,0x24,0x47,0x8e,0x29,0x86,
-  0xee,0xec,0xa9,0x86,0x1e,0x05,0xfb,0xfa,
-  0x00,0x0e,0x69,0xbc,0x60,0x47,0x1c,0x00,
-  0x96,0xdc,0x30,0x00,0x05,0xfb,0xe0,0x00,
-  0xae,0x05,0x38,0x38,0xf9,0x7e,0xa6,0xae,
-  0xf6,0x90,0x68,0x48,0xf5,0x23,0x7f,0x3d,
-};
-
-static const unsigned char q[64] = {
-  0xf2,0x8c,0xa0,0x24,0x38,0x7c,0x6e,0x66,
-  0x9c,0x39,0xe9,0x4d,0x2b,0xe3,0x94,0xd1,
-  0x93,0x3f,0x17,0xcb,0x3f,0x4e,0x8d,0xa4,
-  0xdd,0x1f,0xee,0x00,0x7d,0x8c,0x5e,0xbb,
-  0xc7,0x80,0x1a,0xf5,0x79,0x80,0x63,0x5a,
-  0xc7,0xa2,0xb7,0x92,0x75,0x26,0xda,0xd4,
-  0xc9,0x9f,0x83,0x58,0x81,0x0a,0x53,0xa3,
-  0xe4,0x0b,0xd1,0xde,0xe2,0x33,0xf2,0x9b,
-};
-
-/* dq = 1/e mod (p - 1) */
-static const unsigned char dp[64] = {
-  0x44,0x60,0x63,0x88,0xe7,0x83,0xa9,0x01,
-  0x43,0xaa,0xef,0xb7,0xf3,0xa9,0x36,0x2e,
-  0xa3,0xad,0xb3,0x9a,0x4f,0xb1,0x31,0x7a,
-  0x1e,0x81,0x77,0x56,0x19,0xf9,0xb7,0x9f,
-  0x47,0x97,0x0b,0x57,0x8d,0x16,0xa8,0x2a,
-  0xf1,0x17,0x3b,0x7b,0x36,0x50,0x5a,0xe2,
-  0x39,0x52,0xad,0x8c,0x42,0x25,0x21,0xc2,
-  0x49,0x8c,0x07,0x0d,0x24,0x25,0xb3,0x0d,
-};
-
-/* dq = 1/e mod (q - 1) */
-static const unsigned char dq[64] = {
-  0x6c,0xbe,0xbd,0xe1,0xdf,0x6d,0x72,0x76,
-  0x10,0xdf,0x2a,0x09,0x8e,0x7e,0xe7,0xaf,
-  0x1a,0xcc,0x73,0xd7,0x8d,0x57,0xa3,0xcb,
-  0xe1,0xd4,0x39,0xfa,0x00,0x50,0x19,0xfd,
-  0x28,0xd1,0xf7,0xc4,0x4d,0x28,0x51,0xe3,
-  0x56,0x94,0x4e,0xa7,0x9c,0x5c,0xc2,0x4a,
-  0x1a,0xe7,0xa8,0x94,0xda,0xae,0x0d,0x97,
-  0xf2,0x5b,0x96,0x49,0xce,0xb3,0x29,0xb7,
-};
-
-/* q_inv = 1/q mod p */
-static const unsigned char q_inv[64] = {
-  0x19,0x77,0x6a,0xc8,0xd7,0x2b,0x9f,0x82,
-  0x2d,0xbd,0x05,0x89,0xd8,0x0f,0x1e,0xb6,
-  0x19,0x82,0x58,0x2f,0x7f,0xfd,0xee,0x50,
-  0x00,0x75,0x85,0x69,0x64,0x37,0x32,0xa0,
-  0x62,0x55,0x5b,0x13,0x71,0x9e,0x4e,0x1f,
-  0x93,0x4c,0xa2,0x77,0x6c,0x70,0x07,0xa6,
-  0xfb,0xd5,0x4e,0x94,0xab,0xbd,0xa0,0x0e,
-  0x0d,0x42,0x07,0x9d,0xbb,0x5d,0xbc,0x75,
-};
+static rsa_context ctx;
 
 unsigned char *
 rsa_sign (unsigned char *raw_message)
 {
-  rsa_context ctx;
   mpi P1, Q1, H;
   int len;
+  int r;
 
-  len = (cmd_APDU[5]<<8) | cmd_APDU[6]; /* cmd_APDU_size - 6 */
+  len = (cmd_APDU[5]<<8) | cmd_APDU[6];
+  put_byte (len);
+  /* cmd_APDU_size - 6 */
 
   mpi_init( &P1, &Q1, &H, NULL );
   rsa_init( &ctx, RSA_PKCS_V15, 0 );
 
-#if 0
   ctx.len = 2048 / 8;
-#else
-  ctx.len = 1024 / 8;
-  mpi_read_string( &ctx.E, 16, "10001" );
-  mpi_read_binary (&ctx.P, p, ctx.len / 2);
-  mpi_read_binary (&ctx.Q, q, ctx.len / 2);
-  mpi_mul_mpi( &ctx.N, &ctx.P, &ctx.Q );
-  mpi_sub_int( &P1, &ctx.P, 1 );
-  mpi_sub_int( &Q1, &ctx.Q, 1 );
-  mpi_mul_mpi( &H, &P1, &Q1 );
-  mpi_inv_mod( &ctx.D , &ctx.E, &H  );
-  mpi_read_binary (&ctx.DP, dp, ctx.len / 2);
-  mpi_read_binary (&ctx.DQ, dq, ctx.len / 2);
-  mpi_read_binary (&ctx.QP, q_inv, ctx.len / 2);
-#endif
+  mpi_read_string ( &ctx.E, 16, "10001" );
+  mpi_read_binary ( &ctx.P, &kd.data[0], ctx.len / 2 );
+  mpi_read_binary ( &ctx.Q, &kd.data[128], ctx.len / 2 );
+  mpi_mul_mpi ( &ctx.N, &ctx.P, &ctx.Q );
+  mpi_sub_int ( &P1, &ctx.P, 1 );
+  mpi_sub_int ( &Q1, &ctx.Q, 1 );
+  mpi_mul_mpi ( &H, &P1, &Q1 );
+  mpi_inv_mod ( &ctx.D , &ctx.E, &H  );
+  mpi_mod_mpi ( &ctx.DP, &ctx.D, &P1);
+  mpi_mod_mpi ( &ctx.DQ, &ctx.D, &Q1);
+  mpi_inv_mod ( &ctx.QP, &ctx.Q, &ctx.P);
+  mpi_free (&P1, &Q1, &H, NULL);
 
   put_string ("RSA...");
   {
     int r;
-    if ((r = rsa_check_privkey( &ctx )) == 0)
+    if ((r = rsa_check_privkey ( &ctx )) == 0)
       put_string ("ok...");
     else
       {
        put_string ("failed.\r\n");
        put_byte (r);
+       rsa_free (&ctx);
        return output;
       }
   }
 
-#if 0
-  rsa_pkcs1_sign( &ctx, RSA_PRIVATE, SIG_RSA_RAW, len, raw_message, output);
-  put_string ("done.\r\n");
-  return output;
-#else
-  rsa_pkcs1_sign( &ctx, RSA_PRIVATE, SIG_RSA_RAW, len, raw_message, output );
+  r = rsa_pkcs1_sign ( &ctx, RSA_PRIVATE, SIG_RSA_RAW,
+                      len, raw_message, output );
+  put_short (r);
   put_string ("done.\r\n");
+  rsa_free (&ctx);
   return output;
-#endif
 }
diff --git a/src/rsa.mk b/src/rsa.mk
deleted file mode 100644 (file)
index 9fe30cc..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-RSADIR = ../polarssl-0.14.0
-RSASRCDIR = $(RSADIR)/library
-RSAINCDIR = $(RSADIR)/include
-RSASRC = $(RSASRCDIR)/bignum.c $(RSASRCDIR)/rsa.c rsa-sign.c