[svn] GnuPG - r5043 - in trunk: common g10 scd
svn author wk
cvs at cvs.gnupg.org
Wed Jun 17 11:45:51 CEST 2009
Author: wk
Date: 2009-06-17 11:45:50 +0200 (Wed, 17 Jun 2009)
New Revision: 5043
Modified:
trunk/common/exechelp.c
trunk/g10/ChangeLog
trunk/g10/call-agent.c
trunk/g10/call-agent.h
trunk/g10/card-util.c
trunk/g10/keyserver.c
trunk/scd/ChangeLog
trunk/scd/app-openpgp.c
trunk/scd/iso7816.c
trunk/scd/iso7816.h
Log:
Add readcert command.
fix reading large certificates.
Modified: trunk/g10/ChangeLog
===================================================================
--- trunk/g10/ChangeLog 2009-06-09 23:07:48 UTC (rev 5042)
+++ trunk/g10/ChangeLog 2009-06-17 09:45:50 UTC (rev 5043)
@@ -1,3 +1,15 @@
+2009-06-17 Werner Koch <wk at 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 at g10code.com>
+
+ * keyserver.c (keyserver_search_prompt): No prompt in batch+colons
+ mode.
+
2009-06-09 Werner Koch <wk at g10code.com>
* card-util.c (write_sc_op_status): New.
Modified: trunk/scd/ChangeLog
===================================================================
--- trunk/scd/ChangeLog 2009-06-09 23:07:48 UTC (rev 5042)
+++ trunk/scd/ChangeLog 2009-06-17 09:45:50 UTC (rev 5043)
@@ -1,3 +1,17 @@
+2009-06-17 Werner Koch <wk at 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 at g10code.com>
+
+ * app-openpgp.c (store_fpr): Change first arg to app_t; adjust
+ callers. Flush the cache.
+
2009-06-09 Werner Koch <wk at g10code.com>
* app-openpgp.c (do_readcert): Return NOT_FOUND if the retrieved
Modified: trunk/common/exechelp.c
===================================================================
--- trunk/common/exechelp.c 2009-06-09 23:07:48 UTC (rev 5042)
+++ trunk/common/exechelp.c 2009-06-17 09:45:50 UTC (rev 5043)
@@ -575,7 +575,7 @@
/* (int) pi.dwProcessId, (int) pi.dwThreadId); */
/* 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). */
if ( (flags & 64) )
gnupg_allow_set_foregound_window ((pid_t)(-1)/*pi.dwProcessId*/);
Modified: trunk/g10/call-agent.c
===================================================================
--- trunk/g10/call-agent.c 2009-06-09 23:07:48 UTC (rev 5042)
+++ trunk/g10/call-agent.c 2009-06-17 09:45:50 UTC (rev 5043)
@@ -488,7 +488,6 @@
}
-
/* Handle a KEYDATA inquiry. Note, we only send the data,
assuan_transact takes care of flushing and writing the end */
@@ -539,7 +538,6 @@
}
-
/* Status callback for the SCD GENKEY command. */
static int
@@ -765,6 +763,43 @@
}
+
+/* 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.
CHVNO 1: Change the PIN
2: For v1 cards: Same as 1.
Modified: trunk/g10/call-agent.h
===================================================================
--- trunk/g10/call-agent.h 2009-06-09 23:07:48 UTC (rev 5042)
+++ trunk/g10/call-agent.h 2009-06-17 09:45:50 UTC (rev 5043)
@@ -104,6 +104,10 @@
const unsigned char *indata, size_t indatalen,
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. */
int agent_scd_change_pin (int chvno, const char *serialno);
Modified: trunk/g10/card-util.c
===================================================================
--- trunk/g10/card-util.c 2009-06-09 23:07:48 UTC (rev 5042)
+++ trunk/g10/card-util.c 2009-06-17 09:45:50 UTC (rev 5043)
@@ -715,7 +715,6 @@
static int
fetch_url(void)
{
-#if GNUPG_MAJOR_VERSION == 1
int rc;
struct agent_card_info_s info;
@@ -755,15 +754,11 @@
}
return rc;
-#else
- #warning need to implemented fucntion
- return 0;
-#endif
}
/* 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
R_BUFFER. */
static int
@@ -814,7 +809,40 @@
}
+/* 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
change_login (const char *args)
{
char *data;
@@ -934,6 +962,37 @@
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
change_lang (void)
{
char *data, *p;
@@ -1447,7 +1506,7 @@
cmdQUIT, cmdADMIN, cmdHELP, cmdLIST, cmdDEBUG, cmdVERIFY,
cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR,
cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT,
- cmdUNBLOCK,
+ cmdREADCERT, cmdUNBLOCK,
cmdINVCMD
};
@@ -1481,6 +1540,7 @@
{ "unblock" , cmdUNBLOCK,0, N_("unblock the PIN using a Reset Code") },
/* Note, that we do not announce these command yet. */
{ "privatedo", cmdPRIVATEDO, 0, NULL },
+ { "readcert", cmdREADCERT, 0, NULL },
{ "writecert", cmdWRITECERT, 1, NULL },
{ NULL, cmdINVCMD, 0, NULL }
};
@@ -1735,6 +1795,13 @@
change_cert (arg_rest);
break;
+ case cmdREADCERT:
+ if ( arg_number != 3 )
+ tty_printf ("usage: readcert 3 > FILE\n");
+ else
+ read_cert (arg_rest);
+ break;
+
case cmdFORCESIG:
toggle_forcesig ();
break;
Modified: trunk/g10/keyserver.c
===================================================================
--- trunk/g10/keyserver.c 2009-06-09 23:07:48 UTC (rev 5042)
+++ trunk/g10/keyserver.c 2009-06-17 09:45:50 UTC (rev 5043)
@@ -862,6 +862,9 @@
if(i!=count)
validcount=0;
+ if (opt.with_colons && opt.batch)
+ break;
+
for(;;)
{
if(show_prompt(desc,i,validcount?count:0,localstr))
Modified: trunk/scd/app-openpgp.c
===================================================================
--- trunk/scd/app-openpgp.c 2009-06-09 23:07:48 UTC (rev 5042)
+++ trunk/scd/app-openpgp.c 2009-06-17 09:45:50 UTC (rev 5043)
@@ -75,43 +75,45 @@
int tag;
int constructed;
int get_from; /* Constructed DO with this DO or 0 for direct access. */
- int binary;
- int dont_cache;
- int flush_on_error;
- int get_immediate_in_v11; /* Enable a hack to bypass the cache of
- this data object if it is used in 1.1
- and later versions of the card. This
- does not work with composite DO and is
- currently only useful for the CHV
- status bytes. */
+ int binary:1;
+ int dont_cache:1;
+ int flush_on_error:1;
+ int get_immediate_in_v11:1; /* Enable a hack to bypass the cache of
+ this data object if it is used in 1.1
+ and later versions of the card. This
+ does not work with composite DO and
+ is currently only useful for the CHV
+ status bytes. */
+ int try_extlen:1; /* Large object; try to use an extended
+ length APDU. */
char *desc;
} data_objects[] = {
- { 0x005E, 0, 0, 1, 0, 0, 0, "Login Data" },
- { 0x5F50, 0, 0, 0, 0, 0, 0, "URL" },
- { 0x5F52, 0, 0, 1, 0, 0, 0, "Historical Bytes" },
- { 0x0065, 1, 0, 1, 0, 0, 0, "Cardholder Related Data"},
- { 0x005B, 0, 0x65, 0, 0, 0, 0, "Name" },
- { 0x5F2D, 0, 0x65, 0, 0, 0, 0, "Language preferences" },
- { 0x5F35, 0, 0x65, 0, 0, 0, 0, "Sex" },
- { 0x006E, 1, 0, 1, 0, 0, 0, "Application Related Data" },
- { 0x004F, 0, 0x6E, 1, 0, 0, 0, "AID" },
- { 0x0073, 1, 0, 1, 0, 0, 0, "Discretionary Data Objects" },
- { 0x0047, 0, 0x6E, 1, 1, 0, 0, "Card Capabilities" },
- { 0x00C0, 0, 0x6E, 1, 1, 0, 0, "Extended Card Capabilities" },
- { 0x00C1, 0, 0x6E, 1, 1, 0, 0, "Algorithm Attributes Signature" },
- { 0x00C2, 0, 0x6E, 1, 1, 0, 0, "Algorithm Attributes Decryption" },
- { 0x00C3, 0, 0x6E, 1, 1, 0, 0, "Algorithm Attributes Authentication" },
- { 0x00C4, 0, 0x6E, 1, 0, 1, 1, "CHV Status Bytes" },
- { 0x00C5, 0, 0x6E, 1, 0, 0, 0, "Fingerprints" },
- { 0x00C6, 0, 0x6E, 1, 0, 0, 0, "CA Fingerprints" },
- { 0x00CD, 0, 0x6E, 1, 0, 0, 0, "Generation time" },
- { 0x007A, 1, 0, 1, 0, 0, 0, "Security Support Template" },
- { 0x0093, 0, 0x7A, 1, 1, 0, 0, "Digital Signature Counter" },
- { 0x0101, 0, 0, 0, 0, 0, 0, "Private DO 1"},
- { 0x0102, 0, 0, 0, 0, 0, 0, "Private DO 2"},
- { 0x0103, 0, 0, 0, 0, 0, 0, "Private DO 3"},
- { 0x0104, 0, 0, 0, 0, 0, 0, "Private DO 4"},
- { 0x7F21, 1, 0, 1, 0, 0, 0, "Cardholder certificate"},
+ { 0x005E, 0, 0, 1, 0, 0, 0, 0, "Login Data" },
+ { 0x5F50, 0, 0, 0, 0, 0, 0, 0, "URL" },
+ { 0x5F52, 0, 0, 1, 0, 0, 0, 0, "Historical Bytes" },
+ { 0x0065, 1, 0, 1, 0, 0, 0, 0, "Cardholder Related Data"},
+ { 0x005B, 0, 0x65, 0, 0, 0, 0, 0, "Name" },
+ { 0x5F2D, 0, 0x65, 0, 0, 0, 0, 0, "Language preferences" },
+ { 0x5F35, 0, 0x65, 0, 0, 0, 0, 0, "Sex" },
+ { 0x006E, 1, 0, 1, 0, 0, 0, 0, "Application Related Data" },
+ { 0x004F, 0, 0x6E, 1, 0, 0, 0, 0, "AID" },
+ { 0x0073, 1, 0, 1, 0, 0, 0, 0, "Discretionary Data Objects" },
+ { 0x0047, 0, 0x6E, 1, 1, 0, 0, 0, "Card Capabilities" },
+ { 0x00C0, 0, 0x6E, 1, 1, 0, 0, 0, "Extended Card Capabilities" },
+ { 0x00C1, 0, 0x6E, 1, 1, 0, 0, 0, "Algorithm Attributes Signature" },
+ { 0x00C2, 0, 0x6E, 1, 1, 0, 0, 0, "Algorithm Attributes Decryption" },
+ { 0x00C3, 0, 0x6E, 1, 1, 0, 0, 0, "Algorithm Attributes Authentication" },
+ { 0x00C4, 0, 0x6E, 1, 0, 1, 1, 0, "CHV Status Bytes" },
+ { 0x00C5, 0, 0x6E, 1, 0, 0, 0, 0, "Fingerprints" },
+ { 0x00C6, 0, 0x6E, 1, 0, 0, 0, 0, "CA Fingerprints" },
+ { 0x00CD, 0, 0x6E, 1, 0, 0, 0, 0, "Generation time" },
+ { 0x007A, 1, 0, 1, 0, 0, 0, 0, "Security Support Template" },
+ { 0x0093, 0, 0x7A, 1, 1, 0, 0, 0, "Digital Signature Counter" },
+ { 0x0101, 0, 0, 0, 0, 0, 0, 0, "Private DO 1"},
+ { 0x0102, 0, 0, 0, 0, 0, 0, 0, "Private DO 2"},
+ { 0x0103, 0, 0, 0, 0, 0, 0, 0, "Private DO 3"},
+ { 0x0104, 0, 0, 0, 0, 0, 0, 0, "Private DO 4"},
+ { 0x7F21, 1, 0, 1, 0, 0, 0, 1, "Cardholder certificate"},
{ 0 }
};
@@ -244,17 +246,19 @@
/* Wrapper around iso7816_get_data which first tries to get the data
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
get_cached_data (app_t app, int tag,
unsigned char **result, size_t *resultlen,
- int get_immediate)
+ int get_immediate, int try_extlen)
{
gpg_error_t err;
int i;
unsigned char *p;
size_t len;
struct cache_s *c;
+ int exmode;
*result = NULL;
*resultlen = 0;
@@ -279,7 +283,12 @@
}
}
- 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)
return err;
*result = p;
@@ -392,6 +401,7 @@
unsigned char *value;
size_t valuelen;
int dummyrc;
+ int exmode;
if (!r_rc)
r_rc = &dummyrc;
@@ -404,7 +414,11 @@
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)
{
*r_rc = rc;
@@ -422,7 +436,8 @@
rc = get_cached_data (app, data_objects[i].get_from,
&buffer, &buflen,
(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)
{
const unsigned char *s;
@@ -445,7 +460,8 @@
{
rc = get_cached_data (app, tag, &buffer, &buflen,
(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)
{
value = buffer;
@@ -476,7 +492,9 @@
if (data_objects[i].get_from)
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)
;
else if (rc)
@@ -621,13 +639,14 @@
/* Note, that FPR must be at least 20 bytes. */
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 *e, size_t elen,
unsigned char *fpr, unsigned int card_version)
{
unsigned int n, nbits;
unsigned char *buffer, *p;
+ int tag, tag2;
int rc;
for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */
@@ -662,9 +681,12 @@
xfree (buffer);
- rc = iso7816_put_data (slot, 0,
- (card_version > 0x0007? 0xC7 : 0xC6)
- + keynumber, fpr, 20);
+ tag = (card_version > 0x0007? 0xC7 : 0xC6) + keynumber;
+ flush_cache_item (app, tag);
+ tag2 = 0xCE + keynumber;
+ flush_cache_item (app, tag2);
+
+ rc = iso7816_put_data (app->slot, 0, tag, fpr, 20);
if (rc)
log_error (_("failed to store the fingerprint: %s\n"),gpg_strerror (rc));
@@ -677,7 +699,7 @@
buf[2] = timestamp >> 8;
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)
log_error (_("failed to store the creation date: %s\n"),
gpg_strerror (rc));
@@ -2131,7 +2153,7 @@
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"));
return gpg_error (GPG_ERR_GENERAL);
@@ -2623,7 +2645,7 @@
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,
fprbuf, app->card_version);
if (err)
@@ -2757,7 +2779,7 @@
send_status_info (ctrl, "KEY-CREATED-AT",
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);
if (rc)
goto leave;
@@ -2811,7 +2833,7 @@
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)
{
log_error (_("error reading application data\n"));
@@ -3502,7 +3524,7 @@
replace a possibly already set one from a EF.GDO with this
one. Note, that for current OpenPGP cards, no EF.GDO exists
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)
goto leave;
if (opt.verbose)
Modified: trunk/scd/iso7816.c
===================================================================
--- trunk/scd/iso7816.c 2009-06-09 23:07:48 UTC (rev 5042)
+++ trunk/scd/iso7816.c 2009-06-17 09:45:50 UTC (rev 5043)
@@ -420,19 +420,27 @@
a newly allocated buffer at the address passed by RESULT. Return
the length of this data at the address of RESULTLEN. */
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)
{
int sw;
+ int le;
if (!result || !resultlen)
return gpg_error (GPG_ERR_INV_VALUE);
*result = NULL;
*resultlen = 0;
- sw = apdu_send (slot, 0, 0x00, CMD_GET_DATA,
- ((tag >> 8) & 0xff), (tag & 0xff), -1, NULL,
- result, resultlen);
+ if (extended_mode > 0 && extended_mode < 256)
+ le = 65534; /* Not 65535 in case it is used as some special flag. */
+ 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)
{
/* Make sure that pending buffers are released. */
Modified: trunk/scd/iso7816.h
===================================================================
--- trunk/scd/iso7816.h 2009-06-09 23:07:48 UTC (rev 5042)
+++ trunk/scd/iso7816.h 2009-06-17 09:45:50 UTC (rev 5043)
@@ -84,7 +84,7 @@
gpg_error_t iso7816_reset_retry_counter_with_rc (int slot, int chvno,
const char *data,
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);
gpg_error_t iso7816_put_data (int slot, int extended_mode, int tag,
const unsigned char *data, size_t datalen);
More information about the Gnupg-commits
mailing list