OpenPGP: stricter validity checks in PKCS15 init

Only add private/public keys that habe been defined:
check finger prints & algorithm identifier
This commit is contained in:
Peter Marschall 2012-05-27 11:29:24 +02:00 committed by Viktor Tarasov
parent 742186f32f
commit f04a1c5fef
1 changed files with 45 additions and 15 deletions

View File

@ -152,7 +152,8 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
sc_card_t *card = p15card->card;
sc_context_t *ctx = card->ctx;
char string[256];
u8 buffer[256];
u8 c4data[10];
u8 c5data[70];
int r, i;
const pgp_pin_cfg_t *pin_cfg = (card->type == SC_CARD_TYPE_OPENPGP_V2) ? pin_cfg_v2 : pin_cfg_v1;
@ -190,7 +191,7 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
* 01-03: max length of pins 1-3
* 04-07: tries left for pins 1-3
*/
if ((r = read_file(card, "006E:0073:00C4", buffer, sizeof(buffer))) < 0)
if ((r = read_file(card, "006E:0073:00C4", c4data, sizeof(c4data))) < 0)
goto failed;
if (r != 7) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
@ -213,10 +214,10 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
pin_info.attrs.pin.flags = pin_cfg[i].flags;
pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_UTF8;
pin_info.attrs.pin.min_length = pin_cfg[i].min_length;
pin_info.attrs.pin.stored_length = buffer[1 + pin_cfg[i].do_index];
pin_info.attrs.pin.max_length = buffer[1 + pin_cfg[i].do_index];
pin_info.attrs.pin.stored_length = c4data[1 + pin_cfg[i].do_index];
pin_info.attrs.pin.max_length = c4data[1 + pin_cfg[i].do_index];
pin_info.attrs.pin.pad_char = '\0';
pin_info.tries_left = buffer[4 + pin_cfg[i].do_index];
pin_info.tries_left = c4data[4 + pin_cfg[i].do_index];
sc_format_path("3F00", &pin_info.path);
@ -228,31 +229,52 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
return SC_ERROR_INTERNAL;
}
/* Get private key finger prints from DO 006E/0073/00C5:
* 00-19: finger print for SIG key
* 20-39: finger print for ENC key
* 40-59: finger print for AUT key
*/
if ((r = read_file(card, "006E:0073:00C5", c5data, sizeof(c5data))) < 0)
goto failed;
if (r != 60) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
"finger print bytes have unexpected length (expected 60, got %d)\n", r);
return SC_ERROR_OBJECT_NOT_VALID;
}
/* XXX: check if "halfkeys" can be stored with gpg2. If not, add keypairs in one loop */
for (i = 0; i < 3; i++) {
sc_pkcs15_prkey_info_t prkey_info;
sc_pkcs15_object_t prkey_obj;
char path_template[] = "006E:0073:00C0";
u8 cxdata[10];
char path_template[] = "006E:0073:00Cx";
int j;
memset(&prkey_info, 0, sizeof(prkey_info));
memset(&prkey_obj, 0, sizeof(prkey_obj));
path_template[13] = '1' + i; /* The needed tags are C1 C2 and C3 */
if ((r = read_file(card, path_template, buffer, sizeof(buffer))) < 0)
if ((r = read_file(card, path_template, cxdata, sizeof(cxdata))) < 0)
goto failed;
if (r != 6) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Key info bytes have unexpected length(expected 6, got %d)\n", r);
return SC_ERROR_INTERNAL;
}
/* only add valid keys, i.e. those with a legal algorithm identifier */
if (buffer[0] != 0) {
/* check validity using finger prints */
for (j = 19; j >= 0; j--) {
if (c5data[20 * i + j] != '\0')
break;
}
/* only add valid keys, i.e. those with a legal algorithm identifier & finger print */
if (j >= 0 && cxdata[0] != 0) {
prkey_info.id.len = 1;
prkey_info.id.value[0] = i + 1;
prkey_info.usage = key_cfg[i].prkey_usage;
prkey_info.native = 1;
prkey_info.key_reference = i;
prkey_info.modulus_length = bebytes2ushort(buffer + 1);
prkey_info.modulus_length = bebytes2ushort(cxdata + 1);
strlcpy(prkey_obj.label, key_cfg[i].label, sizeof(prkey_obj.label));
prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE | SC_PKCS15_CO_FLAG_MODIFIABLE;
@ -268,24 +290,32 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
for (i = 0; i < 3; i++) {
sc_pkcs15_pubkey_info_t pubkey_info;
sc_pkcs15_object_t pubkey_obj;
char path_template[] = "006E:0073:00C0";
u8 cxdata[10];
char path_template[] = "006E:0073:00Cx";
int j;
memset(&pubkey_info, 0, sizeof(pubkey_info));
memset(&pubkey_obj, 0, sizeof(pubkey_obj));
path_template[13] = '1' + i; /* The needed tags are C1 C2 and C3 */
if ((r = read_file(card, path_template, buffer, sizeof(buffer))) < 0)
if ((r = read_file(card, path_template, cxdata, sizeof(cxdata))) < 0)
goto failed;
if (r != 6) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Key info bytes have unexpected length(expected 6, got %d)\n", r);
return SC_ERROR_INTERNAL;
}
/* only add valid keys, i.e. those with a legal algorithm identifier */
if (buffer[0] != 0) {
/* check validity using finger prints */
for (j = 19; j >= 0; j--) {
if (c5data[20 * i + j] != '\0')
break;
}
/* only add valid keys, i.e. those with a legal algorithm identifier & finger print */
if (j >= 0 && cxdata[0] != 0) {
pubkey_info.id.len = 1;
pubkey_info.id.value[0] = i + 1;
pubkey_info.modulus_length = bebytes2ushort(buffer + 1);
pubkey_info.modulus_length = bebytes2ushort(cxdata + 1);
pubkey_info.usage = key_cfg[i].pubkey_usage;
sc_format_path(key_cfg[i].pubkey_path, &pubkey_info.path);