1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-02 22:38:02 +02:00

Add readcert command.

fix reading large certificates.
This commit is contained in:
Werner Koch 2009-06-17 09:45:50 +00:00
parent bdbeb0ac2b
commit 5f8acaccc0
10 changed files with 232 additions and 67 deletions

View File

@ -575,7 +575,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
/* (int) pi.dwProcessId, (int) pi.dwThreadId); */ /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
/* Fixme: For unknown reasons AllowSetForegroundWindow returns an /* Fixme: For unknown reasons AllowSetForegroundWindow returns an
invalid argument error if we pass the the correct processID to invalid argument error if we pass the correct processID to
it. As a workaround we use -1 (ASFW_ANY). */ it. As a workaround we use -1 (ASFW_ANY). */
if ( (flags & 64) ) if ( (flags & 64) )
gnupg_allow_set_foregound_window ((pid_t)(-1)/*pi.dwProcessId*/); gnupg_allow_set_foregound_window ((pid_t)(-1)/*pi.dwProcessId*/);

View File

@ -1,3 +1,15 @@
2009-06-17 Werner Koch <wk@g10code.com>
* card-util.c (put_data_to_file, read_cert): New.
(card_edit): Add command "readcert".
(fetch_url): Allow code also for this gnupg major version 2.
* call-agent.c (agent_scd_readcert): New.
2009-06-15 Werner Koch <wk@g10code.com>
* keyserver.c (keyserver_search_prompt): No prompt in batch+colons
mode.
2009-06-09 Werner Koch <wk@g10code.com> 2009-06-09 Werner Koch <wk@g10code.com>
* card-util.c (write_sc_op_status): New. * card-util.c (write_sc_op_status): New.

View File

@ -488,7 +488,6 @@ agent_scd_writecert (const char *certidstr,
} }
/* Handle a KEYDATA inquiry. Note, we only send the data, /* Handle a KEYDATA inquiry. Note, we only send the data,
assuan_transact takes care of flushing and writing the end */ assuan_transact takes care of flushing and writing the end */
@ -539,7 +538,6 @@ agent_scd_writekey (int keyno, const char *serialno,
} }
/* Status callback for the SCD GENKEY command. */ /* Status callback for the SCD GENKEY command. */
static int static int
@ -765,6 +763,43 @@ agent_scd_pkdecrypt (const char *serialno,
} }
/* Send a READCERT command to the SCdaemon. */
int
agent_scd_readcert (const char *certidstr,
void **r_buf, size_t *r_buflen)
{
int rc;
char line[ASSUAN_LINELENGTH];
membuf_t data;
size_t len;
*r_buf = NULL;
rc = start_agent ();
if (rc)
return rc;
init_membuf (&data, 2048);
snprintf (line, DIM(line)-1, "SCD READCERT %s", certidstr);
line[DIM(line)-1] = 0;
rc = assuan_transact (agent_ctx, line,
membuf_data_cb, &data,
default_inq_cb, NULL, NULL, NULL);
if (rc)
{
xfree (get_membuf (&data, &len));
return rc;
}
*r_buf = get_membuf (&data, r_buflen);
if (!*r_buf)
return gpg_error (GPG_ERR_ENOMEM);
return 0;
}
/* Change the PIN of an OpenPGP card or reset the retry counter. /* Change the PIN of an OpenPGP card or reset the retry counter.
CHVNO 1: Change the PIN CHVNO 1: Change the PIN
2: For v1 cards: Same as 1. 2: For v1 cards: Same as 1.

View File

@ -104,6 +104,10 @@ int agent_scd_pkdecrypt (const char *serialno,
const unsigned char *indata, size_t indatalen, const unsigned char *indata, size_t indatalen,
unsigned char **r_buf, size_t *r_buflen); unsigned char **r_buf, size_t *r_buflen);
/* Send a READKEY command to the SCdaemon. */
int agent_scd_readcert (const char *certidstr,
void **r_buf, size_t *r_buflen);
/* Change the PIN of an OpenPGP card or reset the retry counter. */ /* Change the PIN of an OpenPGP card or reset the retry counter. */
int agent_scd_change_pin (int chvno, const char *serialno); int agent_scd_change_pin (int chvno, const char *serialno);

View File

@ -715,7 +715,6 @@ change_url (void)
static int static int
fetch_url(void) fetch_url(void)
{ {
#if GNUPG_MAJOR_VERSION == 1
int rc; int rc;
struct agent_card_info_s info; struct agent_card_info_s info;
@ -755,15 +754,11 @@ fetch_url(void)
} }
return rc; return rc;
#else
#warning need to implemented fucntion
return 0;
#endif
} }
/* Read data from file FNAME up to MAXLEN characters. On error return /* Read data from file FNAME up to MAXLEN characters. On error return
-1 and store NULl at R_BUFFER; on success return the number of -1 and store NULL at R_BUFFER; on success return the number of
bytes read and store the address of a newly allocated buffer at bytes read and store the address of a newly allocated buffer at
R_BUFFER. */ R_BUFFER. */
static int static int
@ -814,6 +809,39 @@ get_data_from_file (const char *fname, size_t maxlen, char **r_buffer)
} }
/* Write LENGTH bytes from BUFFER to file FNAME. Return 0 on
success. */
static int
put_data_to_file (const char *fname, const void *buffer, size_t length)
{
FILE *fp;
fp = fopen (fname, "wb");
#if GNUPG_MAJOR_VERSION == 1
if (fp && is_secured_file (fileno (fp)))
{
fclose (fp);
fp = NULL;
errno = EPERM;
}
#endif
if (!fp)
{
tty_printf (_("can't create `%s': %s\n"), fname, strerror (errno));
return -1;
}
if (length && fwrite (buffer, length, 1, fp) != 1)
{
tty_printf (_("error writing `%s': %s\n"), fname, strerror (errno));
fclose (fp);
return -1;
}
fclose (fp);
return 0;
}
static int static int
change_login (const char *args) change_login (const char *args)
{ {
@ -933,6 +961,37 @@ change_cert (const char *args)
} }
static int
read_cert (const char *args)
{
const char *fname;
void *buffer;
size_t length;
int rc;
if (args && *args == '>') /* Write it to a file */
{
for (args++; spacep (args); args++)
;
fname = args;
}
else
{
tty_printf ("usage error: redirectrion to file required\n");
return -1;
}
rc = agent_scd_readcert ("OPENPGP.3", &buffer, &length);
if (rc)
log_error ("error reading certificate from card: %s\n", gpg_strerror (rc));
else
rc = put_data_to_file (fname, buffer, length);
xfree (buffer);
write_sc_op_status (rc);
return rc;
}
static int static int
change_lang (void) change_lang (void)
{ {
@ -1447,7 +1506,7 @@ enum cmdids
cmdQUIT, cmdADMIN, cmdHELP, cmdLIST, cmdDEBUG, cmdVERIFY, cmdQUIT, cmdADMIN, cmdHELP, cmdLIST, cmdDEBUG, cmdVERIFY,
cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR, cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR,
cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT, cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT,
cmdUNBLOCK, cmdREADCERT, cmdUNBLOCK,
cmdINVCMD cmdINVCMD
}; };
@ -1481,6 +1540,7 @@ static struct
{ "unblock" , cmdUNBLOCK,0, N_("unblock the PIN using a Reset Code") }, { "unblock" , cmdUNBLOCK,0, N_("unblock the PIN using a Reset Code") },
/* Note, that we do not announce these command yet. */ /* Note, that we do not announce these command yet. */
{ "privatedo", cmdPRIVATEDO, 0, NULL }, { "privatedo", cmdPRIVATEDO, 0, NULL },
{ "readcert", cmdREADCERT, 0, NULL },
{ "writecert", cmdWRITECERT, 1, NULL }, { "writecert", cmdWRITECERT, 1, NULL },
{ NULL, cmdINVCMD, 0, NULL } { NULL, cmdINVCMD, 0, NULL }
}; };
@ -1735,6 +1795,13 @@ card_edit (strlist_t commands)
change_cert (arg_rest); change_cert (arg_rest);
break; break;
case cmdREADCERT:
if ( arg_number != 3 )
tty_printf ("usage: readcert 3 > FILE\n");
else
read_cert (arg_rest);
break;
case cmdFORCESIG: case cmdFORCESIG:
toggle_forcesig (); toggle_forcesig ();
break; break;

View File

@ -862,6 +862,9 @@ keyserver_search_prompt(IOBUF buffer,const char *searchstr)
if(i!=count) if(i!=count)
validcount=0; validcount=0;
if (opt.with_colons && opt.batch)
break;
for(;;) for(;;)
{ {
if(show_prompt(desc,i,validcount?count:0,localstr)) if(show_prompt(desc,i,validcount?count:0,localstr))

View File

@ -1,3 +1,17 @@
2009-06-17 Werner Koch <wk@g10code.com>
* iso7816.c (iso7816_get_data): Add arg EXTENDED_MODE. Change all
callers.
* app-openpgp.c (data_objects): Use bit flags. Add flag
TRY_EXTLENGTH.
(get_cached_data): Add arg TRY_EXTLEN and use it for iso7816_get_data.
(get_one_do): Use extended length APDU if necessary.
2009-06-10 Werner Koch <wk@g10code.com>
* app-openpgp.c (store_fpr): Change first arg to app_t; adjust
callers. Flush the cache.
2009-06-09 Werner Koch <wk@g10code.com> 2009-06-09 Werner Koch <wk@g10code.com>
* app-openpgp.c (do_readcert): Return NOT_FOUND if the retrieved * app-openpgp.c (do_readcert): Return NOT_FOUND if the retrieved

View File

@ -75,43 +75,45 @@ static struct {
int tag; int tag;
int constructed; int constructed;
int get_from; /* Constructed DO with this DO or 0 for direct access. */ int get_from; /* Constructed DO with this DO or 0 for direct access. */
int binary; int binary:1;
int dont_cache; int dont_cache:1;
int flush_on_error; int flush_on_error:1;
int get_immediate_in_v11; /* Enable a hack to bypass the cache of int get_immediate_in_v11:1; /* Enable a hack to bypass the cache of
this data object if it is used in 1.1 this data object if it is used in 1.1
and later versions of the card. This and later versions of the card. This
does not work with composite DO and is does not work with composite DO and
currently only useful for the CHV is currently only useful for the CHV
status bytes. */ status bytes. */
int try_extlen:1; /* Large object; try to use an extended
length APDU. */
char *desc; char *desc;
} data_objects[] = { } data_objects[] = {
{ 0x005E, 0, 0, 1, 0, 0, 0, "Login Data" }, { 0x005E, 0, 0, 1, 0, 0, 0, 0, "Login Data" },
{ 0x5F50, 0, 0, 0, 0, 0, 0, "URL" }, { 0x5F50, 0, 0, 0, 0, 0, 0, 0, "URL" },
{ 0x5F52, 0, 0, 1, 0, 0, 0, "Historical Bytes" }, { 0x5F52, 0, 0, 1, 0, 0, 0, 0, "Historical Bytes" },
{ 0x0065, 1, 0, 1, 0, 0, 0, "Cardholder Related Data"}, { 0x0065, 1, 0, 1, 0, 0, 0, 0, "Cardholder Related Data"},
{ 0x005B, 0, 0x65, 0, 0, 0, 0, "Name" }, { 0x005B, 0, 0x65, 0, 0, 0, 0, 0, "Name" },
{ 0x5F2D, 0, 0x65, 0, 0, 0, 0, "Language preferences" }, { 0x5F2D, 0, 0x65, 0, 0, 0, 0, 0, "Language preferences" },
{ 0x5F35, 0, 0x65, 0, 0, 0, 0, "Sex" }, { 0x5F35, 0, 0x65, 0, 0, 0, 0, 0, "Sex" },
{ 0x006E, 1, 0, 1, 0, 0, 0, "Application Related Data" }, { 0x006E, 1, 0, 1, 0, 0, 0, 0, "Application Related Data" },
{ 0x004F, 0, 0x6E, 1, 0, 0, 0, "AID" }, { 0x004F, 0, 0x6E, 1, 0, 0, 0, 0, "AID" },
{ 0x0073, 1, 0, 1, 0, 0, 0, "Discretionary Data Objects" }, { 0x0073, 1, 0, 1, 0, 0, 0, 0, "Discretionary Data Objects" },
{ 0x0047, 0, 0x6E, 1, 1, 0, 0, "Card Capabilities" }, { 0x0047, 0, 0x6E, 1, 1, 0, 0, 0, "Card Capabilities" },
{ 0x00C0, 0, 0x6E, 1, 1, 0, 0, "Extended Card Capabilities" }, { 0x00C0, 0, 0x6E, 1, 1, 0, 0, 0, "Extended Card Capabilities" },
{ 0x00C1, 0, 0x6E, 1, 1, 0, 0, "Algorithm Attributes Signature" }, { 0x00C1, 0, 0x6E, 1, 1, 0, 0, 0, "Algorithm Attributes Signature" },
{ 0x00C2, 0, 0x6E, 1, 1, 0, 0, "Algorithm Attributes Decryption" }, { 0x00C2, 0, 0x6E, 1, 1, 0, 0, 0, "Algorithm Attributes Decryption" },
{ 0x00C3, 0, 0x6E, 1, 1, 0, 0, "Algorithm Attributes Authentication" }, { 0x00C3, 0, 0x6E, 1, 1, 0, 0, 0, "Algorithm Attributes Authentication" },
{ 0x00C4, 0, 0x6E, 1, 0, 1, 1, "CHV Status Bytes" }, { 0x00C4, 0, 0x6E, 1, 0, 1, 1, 0, "CHV Status Bytes" },
{ 0x00C5, 0, 0x6E, 1, 0, 0, 0, "Fingerprints" }, { 0x00C5, 0, 0x6E, 1, 0, 0, 0, 0, "Fingerprints" },
{ 0x00C6, 0, 0x6E, 1, 0, 0, 0, "CA Fingerprints" }, { 0x00C6, 0, 0x6E, 1, 0, 0, 0, 0, "CA Fingerprints" },
{ 0x00CD, 0, 0x6E, 1, 0, 0, 0, "Generation time" }, { 0x00CD, 0, 0x6E, 1, 0, 0, 0, 0, "Generation time" },
{ 0x007A, 1, 0, 1, 0, 0, 0, "Security Support Template" }, { 0x007A, 1, 0, 1, 0, 0, 0, 0, "Security Support Template" },
{ 0x0093, 0, 0x7A, 1, 1, 0, 0, "Digital Signature Counter" }, { 0x0093, 0, 0x7A, 1, 1, 0, 0, 0, "Digital Signature Counter" },
{ 0x0101, 0, 0, 0, 0, 0, 0, "Private DO 1"}, { 0x0101, 0, 0, 0, 0, 0, 0, 0, "Private DO 1"},
{ 0x0102, 0, 0, 0, 0, 0, 0, "Private DO 2"}, { 0x0102, 0, 0, 0, 0, 0, 0, 0, "Private DO 2"},
{ 0x0103, 0, 0, 0, 0, 0, 0, "Private DO 3"}, { 0x0103, 0, 0, 0, 0, 0, 0, 0, "Private DO 3"},
{ 0x0104, 0, 0, 0, 0, 0, 0, "Private DO 4"}, { 0x0104, 0, 0, 0, 0, 0, 0, 0, "Private DO 4"},
{ 0x7F21, 1, 0, 1, 0, 0, 0, "Cardholder certificate"}, { 0x7F21, 1, 0, 1, 0, 0, 0, 1, "Cardholder certificate"},
{ 0 } { 0 }
}; };
@ -244,17 +246,19 @@ do_deinit (app_t app)
/* Wrapper around iso7816_get_data which first tries to get the data /* Wrapper around iso7816_get_data which first tries to get the data
from the cache. With GET_IMMEDIATE passed as true, the cache is from the cache. With GET_IMMEDIATE passed as true, the cache is
bypassed. */ bypassed. With TRY_EXTLEN extended lengths APDUs are use if
supported by the card. */
static gpg_error_t static gpg_error_t
get_cached_data (app_t app, int tag, get_cached_data (app_t app, int tag,
unsigned char **result, size_t *resultlen, unsigned char **result, size_t *resultlen,
int get_immediate) int get_immediate, int try_extlen)
{ {
gpg_error_t err; gpg_error_t err;
int i; int i;
unsigned char *p; unsigned char *p;
size_t len; size_t len;
struct cache_s *c; struct cache_s *c;
int exmode;
*result = NULL; *result = NULL;
*resultlen = 0; *resultlen = 0;
@ -279,7 +283,12 @@ get_cached_data (app_t app, int tag,
} }
} }
err = iso7816_get_data (app->slot, tag, &p, &len); if (try_extlen && app->app_local->cardcap.ext_lc_le)
exmode = app->app_local->extcap.max_rsp_data;
else
exmode = 0;
err = iso7816_get_data (app->slot, exmode, tag, &p, &len);
if (err) if (err)
return err; return err;
*result = p; *result = p;
@ -392,6 +401,7 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes,
unsigned char *value; unsigned char *value;
size_t valuelen; size_t valuelen;
int dummyrc; int dummyrc;
int exmode;
if (!r_rc) if (!r_rc)
r_rc = &dummyrc; r_rc = &dummyrc;
@ -404,7 +414,11 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes,
if (app->card_version > 0x0100 && data_objects[i].get_immediate_in_v11) if (app->card_version > 0x0100 && data_objects[i].get_immediate_in_v11)
{ {
rc = iso7816_get_data (app->slot, tag, &buffer, &buflen); if (data_objects[i].try_extlen && app->app_local->cardcap.ext_lc_le)
exmode = app->app_local->extcap.max_rsp_data;
else
exmode = 0;
rc = iso7816_get_data (app->slot, exmode, tag, &buffer, &buflen);
if (rc) if (rc)
{ {
*r_rc = rc; *r_rc = rc;
@ -422,7 +436,8 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes,
rc = get_cached_data (app, data_objects[i].get_from, rc = get_cached_data (app, data_objects[i].get_from,
&buffer, &buflen, &buffer, &buflen,
(data_objects[i].dont_cache (data_objects[i].dont_cache
|| data_objects[i].get_immediate_in_v11)); || data_objects[i].get_immediate_in_v11),
data_objects[i].try_extlen);
if (!rc) if (!rc)
{ {
const unsigned char *s; const unsigned char *s;
@ -445,7 +460,8 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes,
{ {
rc = get_cached_data (app, tag, &buffer, &buflen, rc = get_cached_data (app, tag, &buffer, &buflen,
(data_objects[i].dont_cache (data_objects[i].dont_cache
|| data_objects[i].get_immediate_in_v11)); || data_objects[i].get_immediate_in_v11),
data_objects[i].try_extlen);
if (!rc) if (!rc)
{ {
value = buffer; value = buffer;
@ -476,7 +492,9 @@ dump_all_do (int slot)
if (data_objects[i].get_from) if (data_objects[i].get_from)
continue; continue;
rc = iso7816_get_data (slot, data_objects[i].tag, &buffer, &buflen); /* We don't try extended length APDU because such large DO would
be pretty useless in a log file. */
rc = iso7816_get_data (slot, 0, data_objects[i].tag, &buffer, &buflen);
if (gpg_err_code (rc) == GPG_ERR_NO_OBJ) if (gpg_err_code (rc) == GPG_ERR_NO_OBJ)
; ;
else if (rc) else if (rc)
@ -621,13 +639,14 @@ parse_login_data (app_t app)
/* Note, that FPR must be at least 20 bytes. */ /* Note, that FPR must be at least 20 bytes. */
static gpg_error_t static gpg_error_t
store_fpr (int slot, int keynumber, u32 timestamp, store_fpr (app_t app, int keynumber, u32 timestamp,
const unsigned char *m, size_t mlen, const unsigned char *m, size_t mlen,
const unsigned char *e, size_t elen, const unsigned char *e, size_t elen,
unsigned char *fpr, unsigned int card_version) unsigned char *fpr, unsigned int card_version)
{ {
unsigned int n, nbits; unsigned int n, nbits;
unsigned char *buffer, *p; unsigned char *buffer, *p;
int tag, tag2;
int rc; int rc;
for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */ for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */
@ -662,9 +681,12 @@ store_fpr (int slot, int keynumber, u32 timestamp,
xfree (buffer); xfree (buffer);
rc = iso7816_put_data (slot, 0, tag = (card_version > 0x0007? 0xC7 : 0xC6) + keynumber;
(card_version > 0x0007? 0xC7 : 0xC6) flush_cache_item (app, tag);
+ keynumber, fpr, 20); tag2 = 0xCE + keynumber;
flush_cache_item (app, tag2);
rc = iso7816_put_data (app->slot, 0, tag, fpr, 20);
if (rc) if (rc)
log_error (_("failed to store the fingerprint: %s\n"),gpg_strerror (rc)); log_error (_("failed to store the fingerprint: %s\n"),gpg_strerror (rc));
@ -677,7 +699,7 @@ store_fpr (int slot, int keynumber, u32 timestamp,
buf[2] = timestamp >> 8; buf[2] = timestamp >> 8;
buf[3] = timestamp; buf[3] = timestamp;
rc = iso7816_put_data (slot, 0, 0xCE + keynumber, buf, 4); rc = iso7816_put_data (app->slot, 0, tag2, buf, 4);
if (rc) if (rc)
log_error (_("failed to store the creation date: %s\n"), log_error (_("failed to store the creation date: %s\n"),
gpg_strerror (rc)); gpg_strerror (rc));
@ -2131,7 +2153,7 @@ does_key_exist (app_t app, int keyidx, int force)
assert (keyidx >=0 && keyidx <= 2); assert (keyidx >=0 && keyidx <= 2);
if (iso7816_get_data (app->slot, 0x006E, &buffer, &buflen)) if (iso7816_get_data (app->slot, 0, 0x006E, &buffer, &buflen))
{ {
log_error (_("error reading application data\n")); log_error (_("error reading application data\n"));
return gpg_error (GPG_ERR_GENERAL); return gpg_error (GPG_ERR_GENERAL);
@ -2623,7 +2645,7 @@ do_writekey (app_t app, ctrl_t ctrl,
goto leave; goto leave;
} }
err = store_fpr (app->slot, keyno, created_at, err = store_fpr (app, keyno, created_at,
rsa_n, rsa_n_len, rsa_e, rsa_e_len, rsa_n, rsa_n_len, rsa_e, rsa_e_len,
fprbuf, app->card_version); fprbuf, app->card_version);
if (err) if (err)
@ -2757,7 +2779,7 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
send_status_info (ctrl, "KEY-CREATED-AT", send_status_info (ctrl, "KEY-CREATED-AT",
numbuf, (size_t)strlen(numbuf), NULL, 0); numbuf, (size_t)strlen(numbuf), NULL, 0);
rc = store_fpr (app->slot, keyno, (u32)created_at, rc = store_fpr (app, keyno, (u32)created_at,
m, mlen, e, elen, fprbuf, app->card_version); m, mlen, e, elen, fprbuf, app->card_version);
if (rc) if (rc)
goto leave; goto leave;
@ -2811,7 +2833,7 @@ compare_fingerprint (app_t app, int keyno, unsigned char *sha1fpr)
assert (keyno >= 1 && keyno <= 3); assert (keyno >= 1 && keyno <= 3);
rc = get_cached_data (app, 0x006E, &buffer, &buflen, 0); rc = get_cached_data (app, 0x006E, &buffer, &buflen, 0, 0);
if (rc) if (rc)
{ {
log_error (_("error reading application data\n")); log_error (_("error reading application data\n"));
@ -3502,7 +3524,7 @@ app_select_openpgp (app_t app)
replace a possibly already set one from a EF.GDO with this replace a possibly already set one from a EF.GDO with this
one. Note, that for current OpenPGP cards, no EF.GDO exists one. Note, that for current OpenPGP cards, no EF.GDO exists
and thus it won't matter at all. */ and thus it won't matter at all. */
rc = iso7816_get_data (slot, 0x004F, &buffer, &buflen); rc = iso7816_get_data (slot, 0, 0x004F, &buffer, &buflen);
if (rc) if (rc)
goto leave; goto leave;
if (opt.verbose) if (opt.verbose)

View File

@ -420,19 +420,27 @@ iso7816_reset_retry_counter (int slot, int chvno,
a newly allocated buffer at the address passed by RESULT. Return a newly allocated buffer at the address passed by RESULT. Return
the length of this data at the address of RESULTLEN. */ the length of this data at the address of RESULTLEN. */
gpg_error_t gpg_error_t
iso7816_get_data (int slot, int tag, iso7816_get_data (int slot, int extended_mode, int tag,
unsigned char **result, size_t *resultlen) unsigned char **result, size_t *resultlen)
{ {
int sw; int sw;
int le;
if (!result || !resultlen) if (!result || !resultlen)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
*result = NULL; *result = NULL;
*resultlen = 0; *resultlen = 0;
sw = apdu_send (slot, 0, 0x00, CMD_GET_DATA, if (extended_mode > 0 && extended_mode < 256)
((tag >> 8) & 0xff), (tag & 0xff), -1, NULL, le = 65534; /* Not 65535 in case it is used as some special flag. */
result, resultlen); else if (extended_mode > 0)
le = extended_mode;
else
le = 256;
sw = apdu_send_le (slot, extended_mode, 0x00, CMD_GET_DATA,
((tag >> 8) & 0xff), (tag & 0xff), -1, NULL, le,
result, resultlen);
if (sw != SW_SUCCESS) if (sw != SW_SUCCESS)
{ {
/* Make sure that pending buffers are released. */ /* Make sure that pending buffers are released. */

View File

@ -84,7 +84,7 @@ gpg_error_t iso7816_reset_retry_counter_kp (int slot, int chvno,
gpg_error_t iso7816_reset_retry_counter_with_rc (int slot, int chvno, gpg_error_t iso7816_reset_retry_counter_with_rc (int slot, int chvno,
const char *data, const char *data,
size_t datalen); size_t datalen);
gpg_error_t iso7816_get_data (int slot, int tag, gpg_error_t iso7816_get_data (int slot, int extended_mode, int tag,
unsigned char **result, size_t *resultlen); unsigned char **result, size_t *resultlen);
gpg_error_t iso7816_put_data (int slot, int extended_mode, int tag, gpg_error_t iso7816_put_data (int slot, int extended_mode, int tag,
const unsigned char *data, size_t datalen); const unsigned char *data, size_t datalen);