Variable length keysize supported in flash.c
authorNIIBE Yutaka <gniibe@fsij.org>
Fri, 12 Dec 2014 02:53:51 +0000 (11:53 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Fri, 12 Dec 2014 02:53:51 +0000 (11:53 +0900)
ChangeLog
src/flash.c
src/gnuk.h
src/openpgp.c

index c374714..924b57d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2014-11-19  Niibe Yutaka  <gniibe@fsij.org>
+
+       * src/gnuk.h (FIRMWARE_UPDATE_KEY_CONTENT_LEN): New.
+       (size_of_key): New enum.
+
+       * src/openpgp.c (gpg_get_firmware_update_key)
+       (cmd_read_binary, cmd_external_authenticate): Use
+       FIRMWARE_UPDATE_KEY_CONTENT_LEN.
+
+       * src/flash.c (KEY_SIZE): Remove.
+       (key_available_at): Add new arg as KEY_SIZE.
+       (flash_check_all_other_keys_released): Likewise.
+       (flash_key_fill_zero_as_released, flash_key_release): Likewise.
+
+       (flash_init): Move initializing keys into another function.
+       (flash_init_keys): New function.
+
+       (flash_key_alloc): Use gpg_get_algo_attr_key_size.
+       (flash_key_write): Add new arg as KEY_DATA_LEN.
+
+       (flash_write_binary): Use FIRMWARE_UPDATE_KEY_CONTENT_LEN.
+
 2014-09-16  Niibe Yutaka  <gniibe@fsij.org>
 
        * src/gnuk.h (MAX_PRVKEY_LEN): New.
index 52d4fb9..23a50e9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * flash.c -- Data Objects (DO) and GPG Key handling on Flash ROM
  *
- * Copyright (C) 2010, 2011, 2012, 2013
+ * Copyright (C) 2010, 2011, 2012, 2013, 2014
  *               Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *
  * _data_pool
  *        <two pages>
  * _keystore_pool
- *         three flash pages for keystore (single: 512-byte (p, q and N))
+ *         Three flash pages for keystore
+ *         a page contains a key data of:
+ *              For RSA-2048: 512-byte (p, q and N)
+ *              For RSA-4096: 1024-byte (p, q and N)
+ *              For ECDSA/ECDH and EdDSA, there are padding after public key
  */
-#define KEY_SIZE       512     /* P, Q and N */
 
 #define FLASH_DATA_POOL_HEADER_SIZE    2
 #define FLASH_DATA_POOL_SIZE           (FLASH_PAGE_SIZE*2)
@@ -77,20 +80,20 @@ const uint8_t const flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
 /* Linker set this symbol */
 extern uint8_t _data_pool;
 
-static int key_available_at (uint8_t *k)
+static int key_available_at (const uint8_t *k, int key_size)
 {
   int i;
 
-  for (i = 0; i < KEY_SIZE; i++)
+  for (i = 0; i < key_size; i++)
     if (k[i])
       break;
-  if (i == KEY_SIZE)   /* It's ZERO.  Released key.  */
+  if (i == key_size)   /* It's ZERO.  Released key.  */
     return 0;
 
-  for (i = 0; i < KEY_SIZE; i++)
+  for (i = 0; i < key_size; i++)
     if (k[i] != 0xff)
       break;
-  if (i == KEY_SIZE)   /* It's FULL.  Unused key.  */
+  if (i == key_size)   /* It's FULL.  Unused key.  */
     return 0;
 
   return 1;
@@ -102,8 +105,6 @@ flash_init (void)
   uint16_t gen0, gen1;
   uint16_t *gen0_p = (uint16_t *)&_data_pool;
   uint16_t *gen1_p = (uint16_t *)(&_data_pool + FLASH_PAGE_SIZE);
-  uint8_t *p;
-  int i; 
 
   /* Check data pool generation and choose the page */
   gen0 = *gen0_p;
@@ -117,24 +118,34 @@ flash_init (void)
   else
     data_pool = &_data_pool;
 
+  return data_pool + FLASH_DATA_POOL_HEADER_SIZE;
+}
+
+void
+flash_init_keys (void)
+{
+  const uint8_t *p;
+  int i;
+
   /* For each key, find its address.  */
   p = &_keystore_pool;
   for (i = 0; i < 3; i++)
     {
-      uint8_t *k;
+      const uint8_t *k;
+      int key_size = gpg_get_algo_attr_key_size (i, GPG_KEY_STORAGE);
 
-      kd[i].key_addr = NULL;
-      for (k = p; k < p + FLASH_PAGE_SIZE; k += KEY_SIZE)
-       if (key_available_at (k))
+      kd[i].pubkey = NULL;
+      for (k = p; k < p + FLASH_PAGE_SIZE; k += key_size)
+       if (key_available_at (k, key_size))
          {
-           kd[i].key_addr = k;
+           int prv_len = gpg_get_algo_attr_key_size (i, GPG_KEY_PRIVATE);
+
+           kd[i].pubkey = k + prv_len;
            break;
          }
 
       p += FLASH_PAGE_SIZE;
     }
-
-  return data_pool + FLASH_DATA_POOL_HEADER_SIZE;
 }
 
 /*
@@ -151,6 +162,7 @@ flash_init (void)
  *     123-counter
  *     14-bit counter
  *     bool object
+ *     small enum
  *
  * Format of a Data Object:
  *    NR:   8-bit tag_number
@@ -311,20 +323,21 @@ flash_key_alloc (enum kind_of_key kk)
 {
   uint8_t *k0, *k;
   int i; 
+  int key_size = gpg_get_algo_attr_key_size (kk, GPG_KEY_STORAGE);
 
   /* There is a page for each KK.  */
   k0 = &_keystore_pool + (FLASH_PAGE_SIZE * kk);
 
   /* Seek free space in the page.  */
-  for (k = k0; k < k0 + FLASH_PAGE_SIZE; k += KEY_SIZE)
+  for (k = k0; k < k0 + FLASH_PAGE_SIZE; k += key_size)
     {
       const uint32_t *p = (const uint32_t *)k;
 
-      for (i = 0; i < KEY_SIZE/4; i++)
+      for (i = 0; i < key_size/4; i++)
        if (p[i] != 0xffffffff)
          break;
 
-      if (i == KEY_SIZE/4)     /* Yes, it's empty.  */
+      if (i == key_size/4)     /* Yes, it's empty.  */
        return k;
     }
 
@@ -334,7 +347,8 @@ flash_key_alloc (enum kind_of_key kk)
 }
 
 int
-flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
+flash_key_write (uint8_t *key_addr,
+                const uint8_t *key_data, int key_data_len,
                 const uint8_t *pubkey, int pubkey_len)
 {
   uint16_t hw;
@@ -342,7 +356,7 @@ flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
   int i;
 
   addr = (uint32_t)key_addr;
-  for (i = 0; i < KEY_CONTENT_LEN/2; i ++)
+  for (i = 0; i < key_data_len/2; i ++)
     {
       hw = key_data[i*2] | (key_data[i*2+1]<<8);
       if (flash_program_halfword (addr, hw) != 0)
@@ -362,14 +376,14 @@ flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
 }
 
 static int
-flash_check_all_other_keys_released (const uint8_t *key_addr)
+flash_check_all_other_keys_released (const uint8_t *key_addr, int key_size)
 {
   uint32_t start = (uint32_t)key_addr & ~(FLASH_PAGE_SIZE - 1);
   const uint32_t *p = (const uint32_t *)start;
 
   while (p < (const uint32_t *)(start + FLASH_PAGE_SIZE))
     if (p == (const uint32_t *)key_addr)
-      p += KEY_SIZE/4;
+      p += key_size/4;
     else
       if (*p)
        return 0;
@@ -380,22 +394,22 @@ flash_check_all_other_keys_released (const uint8_t *key_addr)
 }
 
 static void
-flash_key_fill_zero_as_released (uint8_t *key_addr)
+flash_key_fill_zero_as_released (uint8_t *key_addr, int key_size)
 {
   int i;
   uint32_t addr = (uint32_t)key_addr;
 
-  for (i = 0; i < KEY_SIZE/2; i++)
+  for (i = 0; i < key_size/2; i++)
     flash_program_halfword (addr + i*2, 0);
 }
 
 void
-flash_key_release (uint8_t *key_addr)
+flash_key_release (uint8_t *key_addr, int key_size)
 {
-  if (flash_check_all_other_keys_released (key_addr))
+  if (flash_check_all_other_keys_released (key_addr, key_size))
     flash_erase_page (((uint32_t)key_addr & ~(FLASH_PAGE_SIZE - 1)));
   else
-    flash_key_fill_zero_as_released (key_addr);
+    flash_key_fill_zero_as_released (key_addr, key_size);
 }
 
 
@@ -590,7 +604,7 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
     }
   else if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
     {
-      maxsize = KEY_CONTENT_LEN;
+      maxsize = FIRMWARE_UPDATE_KEY_CONTENT_LEN;
       p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0);
       if (len == 0 && offset == 0)
        { /* This means removal of update key.  */
index 12852ef..b5f4538 100644 (file)
@@ -49,8 +49,7 @@ void ccid_card_change_signal (int how);
 /* USB buffer size of LL (Low-level): size of single Bulk transaction */
 #define USB_LL_BUF_SIZE 64
 
-enum icc_state
-{
+enum icc_state {
   ICC_STATE_NOCARD,            /* No card available */
   ICC_STATE_START,             /* Initial */
   ICC_STATE_WAIT,              /* Waiting APDU */
@@ -85,10 +84,10 @@ int ac_check_status (uint8_t ac_flag);
 int verify_pso_cds (const uint8_t *pw, int pw_len);
 int verify_other (const uint8_t *pw, int pw_len);
 int verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len,
-                         int pw_len_known, const uint8_t *ks_pw1, int saveks);
+                  int pw_len_known, const uint8_t *ks_pw1, int saveks);
 int verify_admin (const uint8_t *pw, int pw_len);
 int verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
-                          const uint8_t *ks_pw3, int saveks);
+                   const uint8_t *ks_pw3, int saveks);
 
 void ac_reset_pso_cds (void);
 void ac_reset_other (void);
@@ -117,13 +116,21 @@ enum kind_of_key {
   GPG_KEY_FOR_AUTHENTICATION,
 };
 
+enum size_of_key {
+  GPG_KEY_STORAGE = 0,         /* PUBKEY + PRVKEY rounded to 2^N */
+  GPG_KEY_PUBLIC,
+  GPG_KEY_PRIVATE,
+};
+
 const uint8_t *flash_init (void);
+void flash_init_keys (void);
 void flash_do_release (const uint8_t *);
 const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
 uint8_t *flash_key_alloc (enum kind_of_key);
-void flash_key_release (uint8_t *);
-int flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
-                           const uint8_t *pubkey, int pubkey_len);
+void flash_key_release (uint8_t *, int);
+int flash_key_write (uint8_t *key_addr,
+                    const uint8_t *key_data, int key_data_len,
+                    const uint8_t *pubkey, int pubkey_len);
 void flash_set_data_pool_last (const uint8_t *p);
 void flash_clear_halfword (uint32_t addr);
 void flash_increment_counter (uint8_t counter_tag_nr);
@@ -136,7 +143,8 @@ void flash_reset_counter (uint8_t counter_tag_nr);
 #define FILEID_UPDATE_KEY_3    4
 #define FILEID_CH_CERTIFICATE  5
 int flash_erase_binary (uint8_t file_id);
-int flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t len, uint16_t offset);
+int flash_write_binary (uint8_t file_id, const uint8_t *data,
+                       uint16_t len, uint16_t offset);
 
 #define FLASH_CH_CERTIFICATE_SIZE 2048
 
@@ -144,13 +152,15 @@ int flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t len, uint
 extern uint8_t ch_certificate_start;
 extern uint8_t random_bits_start;
 
+#define FIRMWARE_UPDATE_KEY_CONTENT_LEN 256    /* RSA-2048 (p and q) */
+
 #define INITIAL_VECTOR_SIZE 16
 #define DATA_ENCRYPTION_KEY_SIZE 16
 
 #define MAX_PRVKEY_LEN 512     /* Maximum is the case for RSA 4096-bit.  */
 
 struct key_data {
-  const uint8_t *pubkey;        /* Pointer to public key*/
+  const uint8_t *pubkey;       /* Pointer to public key*/
   uint8_t data[MAX_PRVKEY_LEN]; /* decrypted private key data content */
 };
 
@@ -208,11 +218,11 @@ void s2k (const unsigned char *salt, size_t slen,
 void gpg_do_clear_prvkey (enum kind_of_key kk);
 int gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring);
 int gpg_do_chks_prvkey (enum kind_of_key kk,
-                              int who_old, const uint8_t *old_ks,
-                              int who_new, const uint8_t *new_ks);
+                       int who_old, const uint8_t *old_ks,
+                       int who_new, const uint8_t *new_ks);
 
 int gpg_change_keystring (int who_old, const uint8_t *old_ks,
-                                int who_new, const uint8_t *new_ks);
+                         int who_new, const uint8_t *new_ks);
 
 extern struct key_data kd[3];
 
@@ -370,7 +380,8 @@ void flash_warning (const char *msg);
 void flash_put_data_internal (const uint8_t *p, uint16_t hw);
 void flash_bool_write_internal (const uint8_t *p, int nr);
 void flash_cnt123_write_internal (const uint8_t *p, int which, int v);
-void flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len);
+void flash_do_write_internal (const uint8_t *p, int nr,
+                             const uint8_t *data, int len);
 
 extern const uint8_t gnukStringSerial[];
 
@@ -380,7 +391,7 @@ extern const uint8_t gnukStringSerial[];
 #define LED_START_COMMAND      (8)
 #define LED_FINISH_COMMAND     (16)
 #define LED_FATAL              (32)
-extern void led_blink (int spec);
+void led_blink (int spec);
 
 #if defined(PINPAD_SUPPORT)
 # if defined(PINPAD_CIR_SUPPORT)
index edeaa4b..c825fa3 100644 (file)
@@ -634,7 +634,7 @@ gpg_get_firmware_update_key (uint8_t keyno)
   extern uint8_t _updatekey_store;
   const uint8_t *p;
 
-  p = &_updatekey_store + keyno * KEY_CONTENT_LEN;
+  p = &_updatekey_store + keyno * FIRMWARE_UPDATE_KEY_CONTENT_LEN;
   return p;
 }
 
@@ -693,8 +693,8 @@ cmd_read_binary (void)
       else
        {
          p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0);
-         res_APDU_size = KEY_CONTENT_LEN;
-         memcpy (res_APDU, p, KEY_CONTENT_LEN);
+         res_APDU_size = FIRMWARE_UPDATE_KEY_CONTENT_LEN;
+         memcpy (res_APDU, p, FIRMWARE_UPDATE_KEY_CONTENT_LEN);
          GPG_SUCCESS ();
        }
     }
@@ -1211,7 +1211,8 @@ cmd_external_authenticate (void)
       return;
     }
 
-  r = rsa_verify (pubkey, challenge, signature);
+  r = rsa_verify (pubkey, FIRMWARE_UPDATE_KEY_CONTENT_LEN,
+                 challenge, signature);
   random_bytes_free (challenge);
   challenge = NULL;