From 7231ee09bb628f0401939778decce818ef6e3665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?= Date: Fri, 5 Apr 2013 17:18:50 +0700 Subject: [PATCH 11/18] OpenPGP: Provide enough buffer to read pubkey from Gnuk. --- src/libopensc/card-openpgp.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 9b08bbb..8a1a270 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -263,7 +263,12 @@ static struct do_info pgp2_objects[] = { /* OpenPGP card spec 2.0 */ /* The DO holding X.509 certificate is constructed but does not contain child DO. * We should notice this when building fake file system later. */ -#define DO_CERT 0x7f21 +#define DO_CERT 0x7f21 +/* Maximum length for response buffer when reading pubkey. This value is calculated with + * 4096-bit key length */ +#define MAXLEN_RESP_PUBKEY 527 +/* Gnuk only support 1 key length (2048 bit) */ +#define MAXLEN_RESP_PUBKEY_GNUK 271 #define DRVDATA(card) ((struct pgp_priv_data *) ((card)->drv_data)) struct pgp_priv_data { @@ -729,6 +734,14 @@ pgp_read_blob(sc_card_t *card, struct blob *blob) u8 buffer[2048]; size_t buf_len = (card->caps & SC_CARD_CAP_APDU_EXT) ? sizeof(buffer) : 256; + + /* Buffer length for Gnuk pubkey */ + if (card->type == SC_CARD_TYPE_OPENPGP_GNUK && + (blob->id == 0xa400 || blob->id == 0xb600 || blob->id == 0xb800 + || blob->id == 0xa401 || blob->id == 0xb601 || blob->id == 0xb801)) { + buf_len = MAXLEN_RESP_PUBKEY_GNUK; + } + int r = blob->info->get_fn(card, blob->id, buffer, buf_len); if (r < 0) { /* an error occurred */ @@ -1830,6 +1843,7 @@ static int pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in u8 apdu_case; u8 *apdu_data; size_t apdu_le; + size_t resplen = 0; int r = SC_SUCCESS; LOG_FUNC_CALLED(card->ctx); @@ -1868,23 +1882,27 @@ static int pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in apdu_case = SC_APDU_CASE_4_EXT; } else { - apdu_le = 256; apdu_case = SC_APDU_CASE_4_SHORT; + apdu_le = 256; + resplen = MAXLEN_RESP_PUBKEY; + } + if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) { + resplen = MAXLEN_RESP_PUBKEY_GNUK; } /* Prepare APDU */ - sc_format_apdu(card, &apdu, apdu_case, 0x47, 0x80, 0); + sc_format_apdu(card, &apdu, apdu_case, 0x47, 0x80, 0); apdu.data = apdu_data; apdu.datalen = 2; /* Data = B600 */ apdu.lc = 2; apdu.le = apdu_le; /* Buffer to receive response */ - apdu.resp = calloc(apdu.le, 1); + apdu.resplen = (resplen > 0) ? resplen : apdu_le; + apdu.resp = calloc(apdu.resplen, 1); if (apdu.resp == NULL) { LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY); } - apdu.resplen = apdu.le; /* Send */ sc_log(card->ctx, "Waiting for the card to generate key..."); -- 1.9.3