firmware update keys handling
This commit is contained in:
13
ChangeLog
13
ChangeLog
@@ -1,5 +1,18 @@
|
|||||||
2012-05-31 Niibe Yutaka <gniibe@fsij.org>
|
2012-05-31 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
Support "firmware update" keys.
|
||||||
|
* src/flash.c (flash_write_binary): Support update keys.
|
||||||
|
* src/gnuk.h (FILEID_UPDATE_KEY_0, FILEID_UPDATE_KEY_1)
|
||||||
|
(FILEID_UPDATE_KEY_2,FILEID_UPDATE_KEY_3): New.
|
||||||
|
* src/gnuk.ld.in (_updatekey_store): New.
|
||||||
|
* src/openpgp.c (FILE_EF_UPDATE_KEY_0, FILE_EF_UPDATE_KEY_1)
|
||||||
|
(FILE_EF_UPDATE_KEY_2, FILE_EF_UPDATE_KEY_3): New.
|
||||||
|
(gpg_get_firmware_update_key): New.
|
||||||
|
(cmd_read_binary): Support update keys and certificate.
|
||||||
|
(modify_binary): New.
|
||||||
|
(cmd_update_binary, cmd_write_binary): Use modify_binary.
|
||||||
|
(cmd_external_authenticate): Support up to four keys.
|
||||||
|
|
||||||
Version string of system service is now USB string.
|
Version string of system service is now USB string.
|
||||||
* src/sys.h (unique_device_id): Define here, not as system
|
* src/sys.h (unique_device_id): Define here, not as system
|
||||||
service.
|
service.
|
||||||
|
|||||||
@@ -511,6 +511,11 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
|
|||||||
maxsize = 6;
|
maxsize = 6;
|
||||||
p = &openpgpcard_aid[8];
|
p = &openpgpcard_aid[8];
|
||||||
}
|
}
|
||||||
|
else if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
|
||||||
|
{
|
||||||
|
maxsize = KEY_CONTENT_LEN;
|
||||||
|
p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0);
|
||||||
|
}
|
||||||
#if defined(CERTDO_SUPPORT)
|
#if defined(CERTDO_SUPPORT)
|
||||||
else if (file_id == FILEID_CH_CERTIFICATE)
|
else if (file_id == FILEID_CH_CERTIFICATE)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -141,7 +141,11 @@ extern void flash_increment_counter (uint8_t counter_tag_nr);
|
|||||||
extern void flash_reset_counter (uint8_t counter_tag_nr);
|
extern void flash_reset_counter (uint8_t counter_tag_nr);
|
||||||
|
|
||||||
#define FILEID_SERIAL_NO 0
|
#define FILEID_SERIAL_NO 0
|
||||||
#define FILEID_CH_CERTIFICATE 1
|
#define FILEID_UPDATE_KEY_0 1
|
||||||
|
#define FILEID_UPDATE_KEY_1 2
|
||||||
|
#define FILEID_UPDATE_KEY_2 3
|
||||||
|
#define FILEID_UPDATE_KEY_3 4
|
||||||
|
#define FILEID_CH_CERTIFICATE 5
|
||||||
extern int flash_erase_binary (uint8_t file_id);
|
extern int flash_erase_binary (uint8_t file_id);
|
||||||
extern int flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t len, uint16_t offset);
|
extern int flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t len, uint16_t offset);
|
||||||
|
|
||||||
|
|||||||
@@ -159,6 +159,9 @@ SECTIONS
|
|||||||
_keystore_pool = .;
|
_keystore_pool = .;
|
||||||
. += 512*3;
|
. += 512*3;
|
||||||
. = ALIGN(@FLASH_PAGE_SIZE@);
|
. = ALIGN(@FLASH_PAGE_SIZE@);
|
||||||
|
_updatekey_store = .;
|
||||||
|
. += 1024;
|
||||||
|
. = ALIGN(@FLASH_PAGE_SIZE@);
|
||||||
} > flash =0xffffffff
|
} > flash =0xffffffff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
241
src/openpgp.c
241
src/openpgp.c
@@ -81,8 +81,12 @@ set_res_sw (uint8_t sw1, uint8_t sw2)
|
|||||||
#define FILE_DF_OPENPGP 1
|
#define FILE_DF_OPENPGP 1
|
||||||
#define FILE_MF 2
|
#define FILE_MF 2
|
||||||
#define FILE_EF_DIR 3
|
#define FILE_EF_DIR 3
|
||||||
#define FILE_EF_SERIAL 4
|
#define FILE_EF_SERIAL_NO 4
|
||||||
#define FILE_EF_CH_CERTIFICATE 5
|
#define FILE_EF_UPDATE_KEY_0 5
|
||||||
|
#define FILE_EF_UPDATE_KEY_1 6
|
||||||
|
#define FILE_EF_UPDATE_KEY_2 7
|
||||||
|
#define FILE_EF_UPDATE_KEY_3 8
|
||||||
|
#define FILE_EF_CH_CERTIFICATE 9
|
||||||
|
|
||||||
static uint8_t file_selection;
|
static uint8_t file_selection;
|
||||||
|
|
||||||
@@ -484,23 +488,95 @@ cmd_pgp_gakp (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint8_t *
|
||||||
|
gpg_get_firmware_update_key (uint8_t keyno)
|
||||||
|
{
|
||||||
|
extern uint8_t _updatekey_store;
|
||||||
|
const uint8_t *p;
|
||||||
|
|
||||||
|
p = &_updatekey_store + keyno * KEY_CONTENT_LEN;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CERTDO_SUPPORT
|
||||||
|
#define FILEID_CH_CERTIFICATE_IS_VALID 1
|
||||||
|
#else
|
||||||
|
#define FILEID_CH_CERTIFICATE_IS_VALID 0
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_read_binary (void)
|
cmd_read_binary (void)
|
||||||
{
|
{
|
||||||
|
int is_short_EF = (P1 (apdu) & 0x80) != 0;
|
||||||
|
uint8_t file_id;
|
||||||
|
const uint8_t *p;
|
||||||
|
uint16_t offset;
|
||||||
|
|
||||||
DEBUG_INFO (" - Read binary\r\n");
|
DEBUG_INFO (" - Read binary\r\n");
|
||||||
|
|
||||||
if (file_selection == FILE_EF_SERIAL)
|
if (is_short_EF)
|
||||||
|
file_id = (P1 (apdu) & 0x1f);
|
||||||
|
else
|
||||||
|
file_id = file_selection - FILE_EF_SERIAL_NO + FILEID_SERIAL_NO;
|
||||||
|
|
||||||
|
if ((!FILEID_CH_CERTIFICATE_IS_VALID && file_id == FILEID_CH_CERTIFICATE)
|
||||||
|
|| file_id > FILEID_CH_CERTIFICATE)
|
||||||
{
|
{
|
||||||
if (P2 (apdu) >= 6)
|
GPG_NO_FILE ();
|
||||||
GPG_BAD_P0_P1 ();
|
return;
|
||||||
else
|
}
|
||||||
{
|
|
||||||
gpg_do_get_data (0x004f, 1); /* AID */
|
if (is_short_EF)
|
||||||
res_APDU[0] = 0x5a;
|
{
|
||||||
}
|
file_selection = file_id - FILEID_SERIAL_NO + FILE_EF_SERIAL_NO;
|
||||||
|
offset = P2 (apdu);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
GPG_NO_RECORD();
|
offset = (P1 (apdu) << 8) | P2 (apdu);
|
||||||
|
|
||||||
|
if (file_id == FILEID_SERIAL_NO)
|
||||||
|
{
|
||||||
|
if (offset != 0)
|
||||||
|
GPG_BAD_P1_P2 ();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gpg_do_get_data (0x004f, 1); /* Get AID... */
|
||||||
|
res_APDU[0] = 0x5a; /* ... and overwrite the first byte of data. */
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
|
||||||
|
{
|
||||||
|
if (offset != 0)
|
||||||
|
GPG_MEMORY_FAILURE ();
|
||||||
|
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);
|
||||||
|
GPG_SUCCESS ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined(CERTDO_SUPPORT)
|
||||||
|
else /* file_id == FILEID_CH_CERTIFICATE */
|
||||||
|
{
|
||||||
|
uint16_t len = 256;
|
||||||
|
|
||||||
|
p = &ch_certificate_start;
|
||||||
|
if (offset >= FLASH_CH_CERTIFICATE_SIZE)
|
||||||
|
GPG_MEMORY_FAILURE ();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (offset + len >= FLASH_CH_CERTIFICATE_SIZE)
|
||||||
|
len = FLASH_CH_CERTIFICATE_SIZE - offset;
|
||||||
|
|
||||||
|
res_APDU_size = len;
|
||||||
|
memcpy (res_APDU, p + offset, len);
|
||||||
|
GPG_SUCCESS ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -543,7 +619,7 @@ cmd_select_file (void)
|
|||||||
* MF.EF-GDO -- Serial number of the card and name of the owner
|
* MF.EF-GDO -- Serial number of the card and name of the owner
|
||||||
*/
|
*/
|
||||||
GPG_SUCCESS ();
|
GPG_SUCCESS ();
|
||||||
file_selection = FILE_EF_SERIAL;
|
file_selection = FILE_EF_SERIAL_NO;
|
||||||
}
|
}
|
||||||
else if (apdu.cmd_apdu_data_len == 2
|
else if (apdu.cmd_apdu_data_len == 2
|
||||||
&& apdu.cmd_apdu_data[0] == 0x3f && apdu.cmd_apdu_data[1] == 0x00)
|
&& apdu.cmd_apdu_data[0] == 0x3f && apdu.cmd_apdu_data[1] == 0x00)
|
||||||
@@ -704,17 +780,17 @@ cmd_internal_authenticate (void)
|
|||||||
DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n");
|
DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MBD_OPRATION_WRITE 0
|
||||||
|
#define MBD_OPRATION_UPDATE 1
|
||||||
|
|
||||||
#if defined(CERTDO_SUPPORT)
|
|
||||||
static void
|
static void
|
||||||
cmd_update_binary (void)
|
modify_binary (uint8_t op, uint8_t p1, uint8_t p2, int len)
|
||||||
{
|
{
|
||||||
int len = apdu.cmd_apdu_data_len;
|
uint8_t file_id;
|
||||||
uint16_t offset;
|
uint16_t offset;
|
||||||
|
int is_short_EF = (p1 & 0x80) != 0;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
DEBUG_INFO (" - UPDATE BINARY\r\n");
|
|
||||||
|
|
||||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||||
{
|
{
|
||||||
DEBUG_INFO ("security error.");
|
DEBUG_INFO ("security error.");
|
||||||
@@ -722,41 +798,52 @@ cmd_update_binary (void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((P1 (apdu) & 0x80))
|
if (is_short_EF)
|
||||||
if ((P1 (apdu) & 0x7f) == FILEID_CH_CERTIFICATE)
|
file_id = (p1 & 0x1f);
|
||||||
{
|
|
||||||
file_selection = FILE_EF_CH_CERTIFICATE;
|
|
||||||
r = flash_erase_binary (FILEID_CH_CERTIFICATE);
|
|
||||||
if (r < 0)
|
|
||||||
{
|
|
||||||
DEBUG_INFO ("memory error.\r\n");
|
|
||||||
GPG_MEMORY_FAILURE ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GPG_NO_FILE ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
file_id = file_selection - FILE_EF_SERIAL_NO + FILEID_SERIAL_NO;
|
||||||
if (file_selection != FILE_EF_CH_CERTIFICATE)
|
|
||||||
{
|
|
||||||
GPG_COMMAND_NOT_ALLOWED ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = (P1 (apdu) << 8) | P2 (apdu);
|
if (!FILEID_CH_CERTIFICATE_IS_VALID && file_id == FILEID_CH_CERTIFICATE)
|
||||||
|
{
|
||||||
|
GPG_NO_FILE ();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (op == MBD_OPRATION_UPDATE && file_id != FILEID_CH_CERTIFICATE)
|
||||||
|
{
|
||||||
|
GPG_CONDITION_NOT_SATISFIED ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_id > FILEID_CH_CERTIFICATE)
|
||||||
|
{
|
||||||
|
GPG_NO_FILE ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_short_EF)
|
||||||
|
{
|
||||||
|
file_selection = file_id - FILEID_SERIAL_NO + FILE_EF_SERIAL_NO;
|
||||||
|
offset = p2;
|
||||||
|
|
||||||
|
if (op == MBD_OPRATION_UPDATE)
|
||||||
|
{
|
||||||
|
r = flash_erase_binary (file_id);
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
DEBUG_INFO ("memory error.\r\n");
|
||||||
|
GPG_MEMORY_FAILURE ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
offset = (p1 << 8) | p2;
|
||||||
|
|
||||||
DEBUG_SHORT (len);
|
DEBUG_SHORT (len);
|
||||||
DEBUG_SHORT (offset);
|
DEBUG_SHORT (offset);
|
||||||
|
|
||||||
r = flash_write_binary (FILEID_CH_CERTIFICATE,
|
r = flash_write_binary (file_id, apdu.cmd_apdu_data, len, offset);
|
||||||
apdu.cmd_apdu_data, len, offset);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
{
|
{
|
||||||
DEBUG_INFO ("memory error.\r\n");
|
DEBUG_INFO ("memory error.\r\n");
|
||||||
@@ -765,6 +852,17 @@ cmd_update_binary (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
GPG_SUCCESS ();
|
GPG_SUCCESS ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(CERTDO_SUPPORT)
|
||||||
|
static void
|
||||||
|
cmd_update_binary (void)
|
||||||
|
{
|
||||||
|
int len = apdu.cmd_apdu_data_len;
|
||||||
|
|
||||||
|
DEBUG_INFO (" - UPDATE BINARY\r\n");
|
||||||
|
modify_binary (MBD_OPRATION_UPDATE, P1 (apdu), P2 (apdu), len);
|
||||||
DEBUG_INFO ("UPDATE BINARY done.\r\n");
|
DEBUG_INFO ("UPDATE BINARY done.\r\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -774,54 +872,9 @@ static void
|
|||||||
cmd_write_binary (void)
|
cmd_write_binary (void)
|
||||||
{
|
{
|
||||||
int len = apdu.cmd_apdu_data_len;
|
int len = apdu.cmd_apdu_data_len;
|
||||||
uint16_t offset;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
DEBUG_INFO (" - WRITE BINARY\r\n");
|
DEBUG_INFO (" - WRITE BINARY\r\n");
|
||||||
|
modify_binary (MBD_OPRATION_WRITE, P1 (apdu), P2 (apdu), len);
|
||||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
|
||||||
{
|
|
||||||
DEBUG_INFO ("security error.");
|
|
||||||
GPG_SECURITY_FAILURE ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((P1 (apdu) & 0x80))
|
|
||||||
if ((P1 (apdu) & 0x7f) <= FILEID_CH_CERTIFICATE)
|
|
||||||
{
|
|
||||||
file_selection = FILE_EF_SERIAL + (P1 (apdu) & 0x7f);
|
|
||||||
offset = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GPG_NO_FILE ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (file_selection != FILE_EF_SERIAL
|
|
||||||
&& file_selection != FILE_EF_CH_CERTIFICATE)
|
|
||||||
{
|
|
||||||
GPG_COMMAND_NOT_ALLOWED ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = (P1 (apdu) << 8) | P2 (apdu);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_SHORT (len);
|
|
||||||
DEBUG_SHORT (offset);
|
|
||||||
|
|
||||||
r = flash_write_binary (file_selection - FILE_EF_SERIAL,
|
|
||||||
apdu.cmd_apdu_data, len, offset);
|
|
||||||
if (r < 0)
|
|
||||||
{
|
|
||||||
DEBUG_INFO ("memory error.\r\n");
|
|
||||||
GPG_MEMORY_FAILURE ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GPG_SUCCESS ();
|
|
||||||
DEBUG_INFO ("WRITE BINARY done.\r\n");
|
DEBUG_INFO ("WRITE BINARY done.\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -837,14 +890,16 @@ cmd_external_authenticate (void)
|
|||||||
|
|
||||||
DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n");
|
DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n");
|
||||||
|
|
||||||
if (keyno > 2)
|
if (keyno > 4)
|
||||||
{
|
{
|
||||||
GPG_CONDITION_NOT_SATISFIED ();
|
GPG_CONDITION_NOT_SATISFIED ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pubkey = gpg_get_firmware_update_key (keyno);
|
pubkey = gpg_get_firmware_update_key (keyno);
|
||||||
if (pubkey == NULL || len != 256)
|
if (len != 256
|
||||||
|
|| (pubkey[0] == 0xff && pubkey[1] == 0xff) /* not registered */
|
||||||
|
|| (pubkey[0] == 0x00 && pubkey[1] == 0x00) /* removed */)
|
||||||
{
|
{
|
||||||
GPG_CONDITION_NOT_SATISFIED ();
|
GPG_CONDITION_NOT_SATISFIED ();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#define GPG_FUNCTION_NOT_SUPPORTED() set_res_sw (0x6a, 0x81)
|
#define GPG_FUNCTION_NOT_SUPPORTED() set_res_sw (0x6a, 0x81)
|
||||||
#define GPG_NO_FILE() set_res_sw (0x6a, 0x82)
|
#define GPG_NO_FILE() set_res_sw (0x6a, 0x82)
|
||||||
#define GPG_NO_RECORD() set_res_sw (0x6a, 0x88)
|
#define GPG_NO_RECORD() set_res_sw (0x6a, 0x88)
|
||||||
#define GPG_BAD_P0_P1() set_res_sw (0x6b, 0x00)
|
#define GPG_BAD_P1_P2() set_res_sw (0x6b, 0x00)
|
||||||
#define GPG_NO_INS() set_res_sw (0x6d, 0x00)
|
#define GPG_NO_INS() set_res_sw (0x6d, 0x00)
|
||||||
#define GPG_ERROR() set_res_sw (0x6f, 0x00)
|
#define GPG_ERROR() set_res_sw (0x6f, 0x00)
|
||||||
#define GPG_SUCCESS() set_res_sw (0x90, 0x00)
|
#define GPG_SUCCESS() set_res_sw (0x90, 0x00)
|
||||||
|
|||||||
Reference in New Issue
Block a user