diff options
author | Werner Koch <wk@gnupg.org> | 2009-07-02 11:49:31 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2009-07-02 11:49:31 +0200 |
commit | 81972ca7d53ff1996e0086702a09d4405bdc2a7e (patch) | |
tree | ef7226ff561ba3707277c1e4d3d02345a9828f9c /sm | |
parent | Alow batch ode for gpgsm --gen-key. (diff) | |
download | gnupg2-81972ca7d53ff1996e0086702a09d4405bdc2a7e.tar.xz gnupg2-81972ca7d53ff1996e0086702a09d4405bdc2a7e.zip |
Create a pkcs#10 request directly from a card.
Deprecate gpgsm-gencert.sh script.
Diffstat (limited to 'sm')
-rw-r--r-- | sm/ChangeLog | 8 | ||||
-rw-r--r-- | sm/call-agent.c | 142 | ||||
-rw-r--r-- | sm/certreqgen-ui.c | 64 | ||||
-rw-r--r-- | sm/gpgsm.h | 2 |
4 files changed, 208 insertions, 8 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog index 2913c58ee..216791556 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,11 @@ +2009-07-02 Werner Koch <wk@g10code.com> + + * certreqgen-ui.c (gpgsm_gencertreq_tty): Allow using a key from a + card. + * call-agent.c (gpgsm_agent_scd_serialno) + (scd_serialno_status_cb, store_serialno): New. + (scd_keypairinfo_status_cb, gpgsm_agent_scd_keypairinfo): New. + 2009-07-01 Werner Koch <wk@g10code.com> * certreqgen-ui.c (check_keygrip): New. diff --git a/sm/call-agent.c b/sm/call-agent.c index 1f8eecb3b..777c44cec 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -538,8 +538,150 @@ gpgsm_agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip, return 0; } + +/* Take the serial number from LINE and return it verbatim in a newly + allocated string. We make sure that only hex characters are + returned. */ +static char * +store_serialno (const char *line) +{ + const char *s; + char *p; + + for (s=line; hexdigitp (s); s++) + ; + p = xtrymalloc (s + 1 - line); + if (p) + { + memcpy (p, line, s-line); + p[s-line] = 0; + } + return p; +} + + +/* Callback for the gpgsm_agent_serialno fucntion. */ +static int +scd_serialno_status_cb (void *opaque, const char *line) +{ + char **r_serialno = opaque; + const char *keyword = line; + int keywordlen; + + for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) + ; + while (spacep (line)) + line++; + + if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen)) + { + xfree (*r_serialno); + *r_serialno = store_serialno (line); + } + + return 0; +} + + +/* Call the agent to read the serial number of the current card. */ +int +gpgsm_agent_scd_serialno (ctrl_t ctrl, char **r_serialno) +{ + int rc; + char *serialno = NULL; + + *r_serialno = NULL; + rc = start_agent (ctrl); + if (rc) + return rc; + rc = assuan_transact (agent_ctx, "SCD SERIALNO", + NULL, NULL, + default_inq_cb, ctrl, + scd_serialno_status_cb, &serialno); + if (!rc && !serialno) + rc = gpg_error (GPG_ERR_INTERNAL); + if (rc) + { + xfree (serialno); + return rc; + } + *r_serialno = serialno; + return 0; +} + + + +/* Callback for the gpgsm_agent_serialno fucntion. */ +static int +scd_keypairinfo_status_cb (void *opaque, const char *line) +{ + strlist_t *listaddr = opaque; + const char *keyword = line; + int keywordlen; + strlist_t sl; + char *p; + + for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) + ; + while (spacep (line)) + line++; + + if (keywordlen == 11 && !memcmp (keyword, "KEYPAIRINFO", keywordlen)) + { + sl = append_to_strlist (listaddr, line); + p = sl->d; + /* Make sure that we only have two tokes so that future + extensions of the format won't change the format expected by + the caller. */ + while (*p && !spacep (p)) + p++; + if (*p) + { + while (spacep (p)) + p++; + while (*p && !spacep (p)) + p++; + *p = 0; + } + } + + return 0; +} + + +/* Call the agent to read the keypairinfo lines of the current card. + The list is returned as a string made up of the keygrip, a space + and the keyid. */ +int +gpgsm_agent_scd_keypairinfo (ctrl_t ctrl, strlist_t *r_list) +{ + int rc; + strlist_t list = NULL; + + *r_list = NULL; + rc = start_agent (ctrl); + if (rc) + return rc; + + rc = assuan_transact (agent_ctx, "SCD LEARN --force", + NULL, NULL, + default_inq_cb, ctrl, + scd_keypairinfo_status_cb, &list); + if (!rc && !list) + rc = gpg_error (GPG_ERR_NO_DATA); + if (rc) + { + free_strlist (list); + return rc; + } + *r_list = list; + return 0; +} + + + static int istrusted_status_cb (void *opaque, const char *line) { diff --git a/sm/certreqgen-ui.c b/sm/certreqgen-ui.c index 868af6b0e..3e98b660f 100644 --- a/sm/certreqgen-ui.c +++ b/sm/certreqgen-ui.c @@ -97,8 +97,8 @@ check_keygrip (ctrl_t ctrl, const char *hexgrip) size_t publiclen; int algo; - if (hexgrip[0] == '0' && hexgrip[1] == 'x') - hexgrip += 2; + if (hexgrip[0] == '&') + hexgrip++; err = gpgsm_agent_readkey (ctrl, 0, hexgrip, &public); if (err) @@ -132,6 +132,7 @@ gpgsm_gencertreq_tty (ctrl_t ctrl, FILE *output_fp) int selection; estream_t fp = NULL; int method; + char *keytype_buffer = NULL; const char *keytype; char *keygrip = NULL; unsigned int nbits; @@ -205,24 +206,70 @@ gpgsm_gencertreq_tty (ctrl_t ctrl, FILE *output_fp) if (!*answer) goto again; else if (strlen (answer) != 40 && - !(answer[0] == '0' && answer[1] == 'x' - && strlen (answer+2) == 40)) + !(answer[0] == '&' && strlen (answer+1) == 40)) tty_printf (_("Not a valid keygrip (expecting 40 hex digits)\n")); else if (!(keytype = check_keygrip (ctrl, answer)) ) tty_printf (_("No key with this keygrip\n")); else break; /* Okay. */ } - nbits = 1024; /* A dummy value is sufficient. */ xfree (keygrip); keygrip = answer; answer = NULL; + nbits = 1024; /* A dummy value is sufficient. */ } else /* method == 3 */ { - tty_printf ("Not yet supported; " - "use the gpgsm-gencert.sh script instead\n"); - goto again; + char *serialno; + strlist_t keypairlist, sl; + int count; + + err = gpgsm_agent_scd_serialno (ctrl, &serialno); + if (err) + { + tty_printf (_("error reading the card: %s\n"), gpg_strerror (err)); + goto again; + } + tty_printf (_("Serial number of the card: %s\n"), serialno); + xfree (serialno); + + err = gpgsm_agent_scd_keypairinfo (ctrl, &keypairlist); + if (err) + { + tty_printf (_("error reading the card: %s\n"), gpg_strerror (err)); + goto again; + } + + do + { + tty_printf (_("Available keys:\n")); + for (count=1,sl=keypairlist; sl; sl = sl->next, count++) + tty_printf (" (%d) %s\n", count, sl->d); + xfree (answer); + answer = tty_get (_("Your selection? ")); + tty_kill_prompt (); + trim_spaces (answer); + selection = atoi (answer); + } + while (!(selection > 0 && selection < count)); + + for (count=1,sl=keypairlist; sl; sl = sl->next, count++) + if (count == selection) + break; + + s = sl->d; + while (*s && !spacep (s)) + s++; + while (spacep (s)) + s++; + + xfree (keygrip); + keygrip = NULL; + xfree (keytype_buffer); + keytype_buffer = xasprintf ("card:%s", s); + free_strlist (keypairlist); + keytype = keytype_buffer; + nbits = 1024; /* A dummy value is sufficient. */ } /* Ask for the key usage. */ @@ -358,6 +405,7 @@ gpgsm_gencertreq_tty (ctrl_t ctrl, FILE *output_fp) es_fclose (fp); xfree (answer); xfree (subject_name); + xfree (keytype_buffer); xfree (keygrip); xfree (get_membuf (&mb_email, NULL)); xfree (get_membuf (&mb_dns, NULL)); diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 781561a71..d2c38fb25 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -388,6 +388,8 @@ int gpgsm_agent_genkey (ctrl_t ctrl, ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey); int gpgsm_agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip, ksba_sexp_t *r_pubkey); +int gpgsm_agent_scd_serialno (ctrl_t ctrl, char **r_serialno); +int gpgsm_agent_scd_keypairinfo (ctrl_t ctrl, strlist_t *r_list); int gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert, const char *hexfpr, struct rootca_flags_s *rootca_flags); int gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip); |