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>
|
||||
|
||||
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.
|
||||
* src/sys.h (unique_device_id): Define here, not as system
|
||||
service.
|
||||
|
||||
@@ -511,6 +511,11 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
|
||||
maxsize = 6;
|
||||
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)
|
||||
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);
|
||||
|
||||
#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_write_binary (uint8_t file_id, const uint8_t *data, uint16_t len, uint16_t offset);
|
||||
|
||||
|
||||
@@ -159,6 +159,9 @@ SECTIONS
|
||||
_keystore_pool = .;
|
||||
. += 512*3;
|
||||
. = ALIGN(@FLASH_PAGE_SIZE@);
|
||||
_updatekey_store = .;
|
||||
. += 1024;
|
||||
. = ALIGN(@FLASH_PAGE_SIZE@);
|
||||
} > 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_MF 2
|
||||
#define FILE_EF_DIR 3
|
||||
#define FILE_EF_SERIAL 4
|
||||
#define FILE_EF_CH_CERTIFICATE 5
|
||||
#define FILE_EF_SERIAL_NO 4
|
||||
#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;
|
||||
|
||||
@@ -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
|
||||
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");
|
||||
|
||||
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_BAD_P0_P1 ();
|
||||
else
|
||||
{
|
||||
gpg_do_get_data (0x004f, 1); /* AID */
|
||||
res_APDU[0] = 0x5a;
|
||||
}
|
||||
GPG_NO_FILE ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_short_EF)
|
||||
{
|
||||
file_selection = file_id - FILEID_SERIAL_NO + FILE_EF_SERIAL_NO;
|
||||
offset = P2 (apdu);
|
||||
}
|
||||
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
|
||||
@@ -543,7 +619,7 @@ cmd_select_file (void)
|
||||
* MF.EF-GDO -- Serial number of the card and name of the owner
|
||||
*/
|
||||
GPG_SUCCESS ();
|
||||
file_selection = FILE_EF_SERIAL;
|
||||
file_selection = FILE_EF_SERIAL_NO;
|
||||
}
|
||||
else if (apdu.cmd_apdu_data_len == 2
|
||||
&& 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");
|
||||
}
|
||||
|
||||
#define MBD_OPRATION_WRITE 0
|
||||
#define MBD_OPRATION_UPDATE 1
|
||||
|
||||
#if defined(CERTDO_SUPPORT)
|
||||
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;
|
||||
int is_short_EF = (p1 & 0x80) != 0;
|
||||
int r;
|
||||
|
||||
DEBUG_INFO (" - UPDATE BINARY\r\n");
|
||||
|
||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
@@ -722,41 +798,52 @@ cmd_update_binary (void)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((P1 (apdu) & 0x80))
|
||||
if ((P1 (apdu) & 0x7f) == FILEID_CH_CERTIFICATE)
|
||||
{
|
||||
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;
|
||||
}
|
||||
if (is_short_EF)
|
||||
file_id = (p1 & 0x1f);
|
||||
else
|
||||
{
|
||||
if (file_selection != FILE_EF_CH_CERTIFICATE)
|
||||
{
|
||||
GPG_COMMAND_NOT_ALLOWED ();
|
||||
return;
|
||||
}
|
||||
file_id = file_selection - FILE_EF_SERIAL_NO + FILEID_SERIAL_NO;
|
||||
|
||||
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 (offset);
|
||||
|
||||
r = flash_write_binary (FILEID_CH_CERTIFICATE,
|
||||
apdu.cmd_apdu_data, len, offset);
|
||||
r = flash_write_binary (file_id, apdu.cmd_apdu_data, len, offset);
|
||||
if (r < 0)
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
@@ -765,6 +852,17 @@ cmd_update_binary (void)
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
#endif
|
||||
@@ -774,54 +872,9 @@ static void
|
||||
cmd_write_binary (void)
|
||||
{
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
uint16_t offset;
|
||||
int r;
|
||||
|
||||
DEBUG_INFO (" - WRITE BINARY\r\n");
|
||||
|
||||
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 ();
|
||||
modify_binary (MBD_OPRATION_WRITE, P1 (apdu), P2 (apdu), len);
|
||||
DEBUG_INFO ("WRITE BINARY done.\r\n");
|
||||
}
|
||||
|
||||
@@ -837,14 +890,16 @@ cmd_external_authenticate (void)
|
||||
|
||||
DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n");
|
||||
|
||||
if (keyno > 2)
|
||||
if (keyno > 4)
|
||||
{
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
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 ();
|
||||
return;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define GPG_FUNCTION_NOT_SUPPORTED() set_res_sw (0x6a, 0x81)
|
||||
#define GPG_NO_FILE() set_res_sw (0x6a, 0x82)
|
||||
#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_ERROR() set_res_sw (0x6f, 0x00)
|
||||
#define GPG_SUCCESS() set_res_sw (0x90, 0x00)
|
||||
|
||||
Reference in New Issue
Block a user