From 8e6fa1a62783366de9c286f96ed1cde4773f23b4 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 12 Dec 2014 11:53:51 +0900 Subject: [PATCH] Variable length keysize supported in flash.c --- ChangeLog | 22 +++++++++++++++ src/flash.c | 74 ++++++++++++++++++++++++++++++--------------------- src/gnuk.h | 39 +++++++++++++++++---------- src/openpgp.c | 9 ++++--- 4 files changed, 96 insertions(+), 48 deletions(-) diff --git a/ChangeLog b/ChangeLog index c374714..924b57d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2014-11-19 Niibe Yutaka + + * 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 * src/gnuk.h (MAX_PRVKEY_LEN): New. diff --git a/src/flash.c b/src/flash.c index 52d4fb9..23a50e9 100644 --- a/src/flash.c +++ b/src/flash.c @@ -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 * @@ -57,9 +57,12 @@ * _data_pool * * _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. */ diff --git a/src/gnuk.h b/src/gnuk.h index 12852ef..b5f4538 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -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) diff --git a/src/openpgp.c b/src/openpgp.c index edeaa4b..c825fa3 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -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;