Implemented the --gen-key command as we can't use the gpgsm-gencert.sh under Windows.
[gnupg.git] / sm / call-agent.c
1 /* call-agent.c - divert operations to the agent
2  *      Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <unistd.h> 
28 #include <time.h>
29 #include <assert.h>
30 #ifdef HAVE_LOCALE_H
31 #include <locale.h>
32 #endif
33
34 #include "gpgsm.h"
35 #include <gcrypt.h>
36 #include <assuan.h>
37 #include "i18n.h"
38 #include "asshelp.h"
39 #include "keydb.h" /* fixme: Move this to import.c */
40 #include "membuf.h"
41
42
43 static assuan_context_t agent_ctx = NULL;
44
45
46 struct cipher_parm_s
47 {
48   assuan_context_t ctx;
49   const unsigned char *ciphertext;
50   size_t ciphertextlen;
51 };
52
53 struct genkey_parm_s
54 {
55   assuan_context_t ctx;
56   const unsigned char *sexp;
57   size_t sexplen;
58 };
59
60 struct learn_parm_s
61 {
62   int error;
63   assuan_context_t ctx;
64   membuf_t *data;
65 };
66
67
68 \f
69 /* Try to connect to the agent via socket or fork it off and work by
70    pipes.  Handle the server's initial greeting */
71 static int
72 start_agent (ctrl_t ctrl)
73 {
74   if (agent_ctx)
75     return 0; /* fixme: We need a context for each thread or serialize
76                  the access to the agent (which is suitable given that
77                  the agent is not MT. */
78
79
80   return start_new_gpg_agent (&agent_ctx,
81                               GPG_ERR_SOURCE_DEFAULT,
82                               opt.homedir,
83                               opt.agent_program,
84                               opt.display, opt.ttyname, opt.ttytype,
85                               opt.lc_ctype, opt.lc_messages,
86                               opt.verbose, DBG_ASSUAN,
87                               gpgsm_status2, ctrl);
88
89 }
90
91
92
93 static int
94 membuf_data_cb (void *opaque, const void *buffer, size_t length)
95 {
96   membuf_t *data = opaque;
97
98   if (buffer)
99     put_membuf (data, buffer, length);
100   return 0;
101 }
102   
103
104
105 \f
106 /* Call the agent to do a sign operation using the key identified by
107    the hex string KEYGRIP. */
108 int
109 gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
110                     unsigned char *digest, size_t digestlen, int digestalgo,
111                     unsigned char **r_buf, size_t *r_buflen )
112 {
113   int rc, i;
114   char *p, line[ASSUAN_LINELENGTH];
115   membuf_t data;
116   size_t len;
117
118   *r_buf = NULL;
119   rc = start_agent (ctrl);
120   if (rc)
121     return rc;
122
123   if (digestlen*2 + 50 > DIM(line))
124     return gpg_error (GPG_ERR_GENERAL);
125
126   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
127   if (rc)
128     return rc;
129
130   snprintf (line, DIM(line)-1, "SIGKEY %s", keygrip);
131   line[DIM(line)-1] = 0;
132   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
133   if (rc)
134     return rc;
135
136   if (desc)
137     {
138       snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
139       line[DIM(line)-1] = 0;
140       rc = assuan_transact (agent_ctx, line,
141                             NULL, NULL, NULL, NULL, NULL, NULL);
142       if (rc)
143         return rc;
144     }
145
146   sprintf (line, "SETHASH %d ", digestalgo);
147   p = line + strlen (line);
148   for (i=0; i < digestlen ; i++, p += 2 )
149     sprintf (p, "%02X", digest[i]);
150   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
151   if (rc)
152     return rc;
153
154   init_membuf (&data, 1024);
155   rc = assuan_transact (agent_ctx, "PKSIGN",
156                         membuf_data_cb, &data, NULL, NULL, NULL, NULL);
157   if (rc)
158     {
159       xfree (get_membuf (&data, &len));
160       return rc;
161     }
162   *r_buf = get_membuf (&data, r_buflen);
163
164   if (!gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL))
165     {
166       xfree (*r_buf); *r_buf = NULL;
167       return gpg_error (GPG_ERR_INV_VALUE);
168     }
169
170   return *r_buf? 0 : out_of_core ();
171 }
172
173
174 /* Call the scdaemon to do a sign operation using the key identified by
175    the hex string KEYID. */
176 int
177 gpgsm_scd_pksign (ctrl_t ctrl, const char *keyid, const char *desc,
178                   unsigned char *digest, size_t digestlen, int digestalgo,
179                   unsigned char **r_buf, size_t *r_buflen )
180 {
181   int rc, i;
182   char *p, line[ASSUAN_LINELENGTH];
183   membuf_t data;
184   size_t len;
185   const char *hashopt;
186   unsigned char *sigbuf;
187   size_t sigbuflen;
188
189   *r_buf = NULL;
190
191   switch(digestalgo)
192     {
193     case GCRY_MD_SHA1:  hashopt = "--hash=sha1"; break;
194     case GCRY_MD_RMD160:hashopt = "--hash=rmd160"; break;
195     case GCRY_MD_MD5:   hashopt = "--hash=md5"; break;
196     case GCRY_MD_SHA256:hashopt = "--hash=sha256"; break;
197     default: 
198       return gpg_error (GPG_ERR_DIGEST_ALGO);
199     }
200
201   rc = start_agent (ctrl);
202   if (rc)
203     return rc;
204
205   if (digestlen*2 + 50 > DIM(line))
206     return gpg_error (GPG_ERR_GENERAL);
207
208   p = stpcpy (line, "SCD SETDATA " );
209   for (i=0; i < digestlen ; i++, p += 2 )
210     sprintf (p, "%02X", digest[i]);
211   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
212   if (rc)
213     return rc;
214
215   init_membuf (&data, 1024);
216
217   snprintf (line, DIM(line)-1, "SCD PKSIGN %s %s", hashopt, keyid);
218   line[DIM(line)-1] = 0;
219   rc = assuan_transact (agent_ctx, line,
220                         membuf_data_cb, &data, NULL, NULL, NULL, NULL);
221   if (rc)
222     {
223       xfree (get_membuf (&data, &len));
224       return rc;
225     }
226   sigbuf = get_membuf (&data, &sigbuflen);
227
228   /* Create an S-expression from it which is formatted like this:
229      "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" Fixme: If a card ever
230      creates non-RSA keys we need to change things. */
231   *r_buflen = 21 + 11 + sigbuflen + 4;
232   p = xtrymalloc (*r_buflen);
233   *r_buf = (unsigned char*)p;
234   if (!p)
235     {
236       xfree (sigbuf);
237       return 0;
238     }
239   p = stpcpy (p, "(7:sig-val(3:rsa(1:s" );
240   sprintf (p, "%u:", (unsigned int)sigbuflen);
241   p += strlen (p);
242   memcpy (p, sigbuf, sigbuflen);
243   p += sigbuflen;
244   strcpy (p, ")))");
245   xfree (sigbuf);
246
247   assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
248   return  0;
249 }
250
251
252
253 \f
254 /* Handle a CIPHERTEXT inquiry.  Note, we only send the data,
255    assuan_transact talkes care of flushing and writing the end */
256 static int
257 inq_ciphertext_cb (void *opaque, const char *keyword)
258 {
259   struct cipher_parm_s *parm = opaque; 
260   int rc;
261
262   assuan_begin_confidential (parm->ctx);
263   rc = assuan_send_data (parm->ctx, parm->ciphertext, parm->ciphertextlen);
264   assuan_end_confidential (parm->ctx);
265   return rc; 
266 }
267
268
269 /* Call the agent to do a decrypt operation using the key identified by
270    the hex string KEYGRIP. */
271 int
272 gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
273                        ksba_const_sexp_t ciphertext, 
274                        char **r_buf, size_t *r_buflen )
275 {
276   int rc;
277   char line[ASSUAN_LINELENGTH];
278   membuf_t data;
279   struct cipher_parm_s cipher_parm;
280   size_t n, len;
281   char *p, *buf, *endp;
282   size_t ciphertextlen;
283   
284   if (!keygrip || strlen(keygrip) != 40 || !ciphertext || !r_buf || !r_buflen)
285     return gpg_error (GPG_ERR_INV_VALUE);
286   *r_buf = NULL;
287
288   ciphertextlen = gcry_sexp_canon_len (ciphertext, 0, NULL, NULL);
289   if (!ciphertextlen)
290     return gpg_error (GPG_ERR_INV_VALUE);
291
292   rc = start_agent (ctrl);
293   if (rc)
294     return rc;
295
296   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
297   if (rc)
298     return rc;
299
300   assert ( DIM(line) >= 50 );
301   snprintf (line, DIM(line)-1, "SETKEY %s", keygrip);
302   line[DIM(line)-1] = 0;
303   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
304   if (rc)
305     return rc;
306
307   if (desc)
308     {
309       snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
310       line[DIM(line)-1] = 0;
311       rc = assuan_transact (agent_ctx, line,
312                             NULL, NULL, NULL, NULL, NULL, NULL);
313       if (rc)
314         return rc;
315     }
316
317   init_membuf (&data, 1024);
318   cipher_parm.ctx = agent_ctx;
319   cipher_parm.ciphertext = ciphertext;
320   cipher_parm.ciphertextlen = ciphertextlen;
321   rc = assuan_transact (agent_ctx, "PKDECRYPT",
322                         membuf_data_cb, &data,
323                         inq_ciphertext_cb, &cipher_parm, NULL, NULL);
324   if (rc)
325     {
326       xfree (get_membuf (&data, &len));
327       return rc;
328     }
329
330   put_membuf (&data, "", 1); /* Make sure it is 0 terminated. */
331   buf = get_membuf (&data, &len);
332   if (!buf)
333     return gpg_error (GPG_ERR_ENOMEM);
334   assert (len); /* (we forced Nul termination.)  */
335
336   if (*buf == '(')
337     {
338       if (len < 13 || memcmp (buf, "(5:value", 8) ) /* "(5:valueN:D)\0" */
339         return gpg_error (GPG_ERR_INV_SEXP);
340       len -= 11;   /* Count only the data of the second part. */
341       p = buf + 8; /* Skip leading parenthesis and the value tag. */
342     }
343   else
344     {
345       /* For compatibility with older gpg-agents handle the old style
346          incomplete S-exps. */
347       len--;      /* Do not count the Nul. */
348       p = buf;
349     }
350
351   n = strtoul (p, &endp, 10);
352   if (!n || *endp != ':')
353     return gpg_error (GPG_ERR_INV_SEXP);
354   endp++;
355   if (endp-p+n > len)
356     return gpg_error (GPG_ERR_INV_SEXP); /* Oops: Inconsistent S-Exp. */
357   
358   memmove (buf, endp, n);
359
360   *r_buflen = n;
361   *r_buf = buf;
362   return 0;
363 }
364
365
366
367
368 \f
369 /* Handle a KEYPARMS inquiry.  Note, we only send the data,
370    assuan_transact takes care of flushing and writing the end */
371 static int
372 inq_genkey_parms (void *opaque, const char *keyword)
373 {
374   struct genkey_parm_s *parm = opaque; 
375   int rc;
376
377   rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen);
378   return rc; 
379 }
380
381
382 \f
383 /* Call the agent to generate a newkey */
384 int
385 gpgsm_agent_genkey (ctrl_t ctrl,
386                     ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
387 {
388   int rc;
389   struct genkey_parm_s gk_parm;
390   membuf_t data;
391   size_t len;
392   unsigned char *buf;
393
394   *r_pubkey = NULL;
395   rc = start_agent (ctrl);
396   if (rc)
397     return rc;
398
399   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
400   if (rc)
401     return rc;
402
403   init_membuf (&data, 1024);
404   gk_parm.ctx = agent_ctx;
405   gk_parm.sexp = keyparms;
406   gk_parm.sexplen = gcry_sexp_canon_len (keyparms, 0, NULL, NULL);
407   if (!gk_parm.sexplen)
408     return gpg_error (GPG_ERR_INV_VALUE);
409   rc = assuan_transact (agent_ctx, "GENKEY",
410                         membuf_data_cb, &data, 
411                         inq_genkey_parms, &gk_parm, NULL, NULL);
412   if (rc)
413     {
414       xfree (get_membuf (&data, &len));
415       return rc;
416     }
417   buf = get_membuf (&data, &len);
418   if (!buf)
419     return gpg_error (GPG_ERR_ENOMEM);
420   if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
421     {
422       xfree (buf);
423       return gpg_error (GPG_ERR_INV_SEXP);
424     }
425   *r_pubkey = buf;
426   return 0;
427 }
428
429 \f
430 /* Call the agent to read the public key part for a given keygrip.  If
431    FROMCARD is true, the key is directly read from the current
432    smartcard. In this case HEXKEYGRIP should be the keyID
433    (e.g. OPENPGP.3). */
434 int
435 gpgsm_agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
436                      ksba_sexp_t *r_pubkey)
437 {
438   int rc;
439   membuf_t data;
440   size_t len;
441   unsigned char *buf;
442   char line[ASSUAN_LINELENGTH];
443
444   *r_pubkey = NULL;
445   rc = start_agent (ctrl);
446   if (rc)
447     return rc;
448
449   rc = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL);
450   if (rc)
451     return rc;
452
453   snprintf (line, DIM(line)-1, "%sREADKEY %s",
454             fromcard? "SCD ":"", hexkeygrip);
455   line[DIM(line)-1] = 0;
456
457   init_membuf (&data, 1024);
458   rc = assuan_transact (agent_ctx, line,
459                         membuf_data_cb, &data, 
460                         NULL, NULL, NULL, NULL);
461   if (rc)
462     {
463       xfree (get_membuf (&data, &len));
464       return rc;
465     }
466   buf = get_membuf (&data, &len);
467   if (!buf)
468     return gpg_error (GPG_ERR_ENOMEM);
469   if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
470     {
471       xfree (buf);
472       return gpg_error (GPG_ERR_INV_SEXP);
473     }
474   *r_pubkey = buf;
475   return 0;
476 }
477
478 \f
479
480 static int
481 istrusted_status_cb (void *opaque, const char *line)
482 {
483   struct rootca_flags_s *flags = opaque;
484
485   if (!strncmp (line, "TRUSTLISTFLAG", 13) && (line[13]==' ' || !line[13]))
486     {
487       for (line += 13; *line == ' '; line++)
488         ;
489       if (!strncmp (line, "relax", 5) && (line[5] == ' ' || !line[5]))
490         flags->relax = 1;
491     }
492   return 0;
493 }
494
495
496
497 /* Ask the agent whether the certificate is in the list of trusted
498    keys.  ROOTCA_FLAGS is guaranteed to be cleared on error. */
499 int
500 gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert,
501                        struct rootca_flags_s *rootca_flags)
502 {
503   int rc;
504   char *fpr;
505   char line[ASSUAN_LINELENGTH];
506
507   memset (rootca_flags, 0, sizeof *rootca_flags);
508
509   rc = start_agent (ctrl);
510   if (rc)
511     return rc;
512
513   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
514   if (!fpr)
515     {
516       log_error ("error getting the fingerprint\n");
517       return gpg_error (GPG_ERR_GENERAL);
518     }
519
520   snprintf (line, DIM(line)-1, "ISTRUSTED %s", fpr);
521   line[DIM(line)-1] = 0;
522   xfree (fpr);
523
524   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
525                         istrusted_status_cb, rootca_flags);
526   return rc;
527 }
528
529 /* Ask the agent to mark CERT as a trusted Root-CA one */
530 int
531 gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert)
532 {
533   int rc;
534   char *fpr, *dn;
535   char line[ASSUAN_LINELENGTH];
536
537   rc = start_agent (ctrl);
538   if (rc)
539     return rc;
540
541   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
542   if (!fpr)
543     {
544       log_error ("error getting the fingerprint\n");
545       return gpg_error (GPG_ERR_GENERAL);
546     }
547
548   dn = ksba_cert_get_issuer (cert, 0);
549   if (!dn)
550     {
551       xfree (fpr);
552       return gpg_error (GPG_ERR_GENERAL);
553     }
554   snprintf (line, DIM(line)-1, "MARKTRUSTED %s S %s", fpr, dn);
555   line[DIM(line)-1] = 0;
556   ksba_free (dn);
557   xfree (fpr);
558
559   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
560   return rc;
561 }
562
563
564 \f
565 /* Ask the agent whether the a corresponding secret key is available
566    for the given keygrip */
567 int
568 gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip)
569 {
570   int rc;
571   char line[ASSUAN_LINELENGTH];
572
573   rc = start_agent (ctrl);
574   if (rc)
575     return rc;
576
577   if (!hexkeygrip || strlen (hexkeygrip) != 40)
578     return gpg_error (GPG_ERR_INV_VALUE);
579
580   snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip);
581   line[DIM(line)-1] = 0;
582
583   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
584   return rc;
585 }
586
587 \f
588 static int
589 learn_cb (void *opaque, const void *buffer, size_t length)
590 {
591   struct learn_parm_s *parm = opaque;
592   size_t len;
593   char *buf;
594   ksba_cert_t cert;
595   int rc;
596
597   if (parm->error)
598     return 0;
599
600   if (buffer)
601     {
602       put_membuf (parm->data, buffer, length);
603       return 0;
604     }
605   /* END encountered - process what we have */
606   buf = get_membuf (parm->data, &len);
607   if (!buf)
608     {
609       parm->error = gpg_error (GPG_ERR_ENOMEM);
610       return 0;
611     }
612
613
614   /* FIXME: this should go into import.c */
615   rc = ksba_cert_new (&cert);
616   if (rc)
617     {
618       parm->error = rc;
619       return 0;
620     }
621   rc = ksba_cert_init_from_mem (cert, buf, len);
622   if (rc)
623     {
624       log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
625       ksba_cert_release (cert);
626       parm->error = rc;
627       return 0;
628     }
629
630   rc = gpgsm_basic_cert_check (cert);
631   if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT)
632     { /* For later use we store it in the ephemeral database. */
633       log_info ("issuer certificate missing - storing as ephemeral\n");
634       keydb_store_cert (cert, 1, NULL);
635     }
636   else if (rc)
637     log_error ("invalid certificate: %s\n", gpg_strerror (rc));
638   else
639     {
640       int existed;
641
642       if (!keydb_store_cert (cert, 0, &existed))
643         {
644           if (opt.verbose > 1 && existed)
645             log_info ("certificate already in DB\n");
646           else if (opt.verbose && !existed)
647             log_info ("certificate imported\n");
648         }
649     }
650
651   ksba_cert_release (cert);
652   init_membuf (parm->data, 4096);
653   return 0;
654 }
655   
656 /* Call the agent to learn about a smartcard */
657 int
658 gpgsm_agent_learn (ctrl_t ctrl)
659 {
660   int rc;
661   struct learn_parm_s learn_parm;
662   membuf_t data;
663   size_t len;
664
665   rc = start_agent (ctrl);
666   if (rc)
667     return rc;
668
669   init_membuf (&data, 4096);
670   learn_parm.error = 0;
671   learn_parm.ctx = agent_ctx;
672   learn_parm.data = &data;
673   rc = assuan_transact (agent_ctx, "LEARN --send",
674                         learn_cb, &learn_parm, 
675                         NULL, NULL, NULL, NULL);
676   xfree (get_membuf (&data, &len));
677   if (rc)
678     return rc;
679   return learn_parm.error;
680 }
681
682 \f
683 /* Ask the agent to change the passphrase of the key identified by
684    HEXKEYGRIP. If DESC is not NULL, display instead of the default
685    description message. */
686 int
687 gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc)
688 {
689   int rc;
690   char line[ASSUAN_LINELENGTH];
691
692   rc = start_agent (ctrl);
693   if (rc)
694     return rc;
695
696   if (!hexkeygrip || strlen (hexkeygrip) != 40)
697     return gpg_error (GPG_ERR_INV_VALUE);
698
699   if (desc)
700     {
701       snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
702       line[DIM(line)-1] = 0;
703       rc = assuan_transact (agent_ctx, line,
704                             NULL, NULL, NULL, NULL, NULL, NULL);
705       if (rc)
706         return rc;
707     }
708
709   snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip);
710   line[DIM(line)-1] = 0;
711
712   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
713   return rc;
714 }
715
716
717 \f
718 /* Ask the agent to pop up a confirmation dialog with the text DESC
719    and an okay and cancel button.  */
720 gpg_error_t
721 gpgsm_agent_get_confirmation (ctrl_t ctrl, const char *desc)
722 {
723   int rc;
724   char line[ASSUAN_LINELENGTH];
725
726   rc = start_agent (ctrl);
727   if (rc)
728     return rc;
729
730   snprintf (line, DIM(line)-1, "GET_CONFIRMATION %s", desc);
731   line[DIM(line)-1] = 0;
732
733   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
734   return rc;
735 }