1 /* call-scd.c - fork of the scdaemon to do SC operations
2 * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 /* Fixme: For now we have serialized all access to the scdaemon which
22 make sense becuase the scdaemon can't handle concurrent connections
23 right now. We should however keep a list of connections and lock
24 just that connection - it migth make sense to implemtn parts of
36 #include <sys/types.h>
45 #ifdef _POSIX_OPEN_MAX
46 #define MAX_OPEN_FDS _POSIX_OPEN_MAX
48 #define MAX_OPEN_FDS 20
51 static ASSUAN_CONTEXT scd_ctx
= NULL
;
53 static pth_mutex_t scd_lock
= PTH_MUTEX_INIT
;
55 /* We need to keep track of the connection currently using the SCD.
56 For a pipe server this is all a NOP because the connection will
57 always have the connection indicator -1. agent_reset_scd releases
58 the active connection; i.e. sets it back to -1, so that a new
59 connection can start using the SCD. If we eventually allow
60 multiple SCD session we will either make scdaemon multi-threaded or
61 fork of a new scdaemon and let it see how it can get access to a
64 static int active_connection_fd
= -1;
65 static int active_connection
= 0;
67 /* callback parameter for learn card */
69 void (*kpinfo_cb
)(void*, const char *);
71 void (*certinfo_cb
)(void*, const char *);
72 void *certinfo_cb_arg
;
73 void (*sinfo_cb
)(void*, const char *, size_t, const char *);
77 struct inq_needpin_s
{
79 int (*getpin_cb
)(void *, const char *, char*, size_t);
92 /* A simple implementation of a dynamic buffer. Use init_membuf() to
93 create a buffer, put_membuf to append bytes and get_membuf to
94 release and return the buffer. Allocation errors are detected but
95 only returned at the final get_membuf(), this helps not to clutter
96 the code with out of core checks. */
99 init_membuf (struct membuf
*mb
, int initiallen
)
102 mb
->size
= initiallen
;
104 mb
->buf
= xtrymalloc (initiallen
);
110 put_membuf (struct membuf
*mb
, const void *buf
, size_t len
)
115 if (mb
->len
+ len
>= mb
->size
)
119 mb
->size
+= len
+ 1024;
120 p
= xtryrealloc (mb
->buf
, mb
->size
);
128 memcpy (mb
->buf
+ mb
->len
, buf
, len
);
133 get_membuf (struct membuf
*mb
, size_t *len
)
147 mb
->out_of_core
= 1; /* don't allow a reuse */
158 if (!pth_mutex_release (&scd_lock
))
160 log_error ("failed to release the SCD lock\n");
162 rc
= gpg_error (GPG_ERR_INTERNAL
);
168 /* To make sure we leave no secrets in our image after forking of the
169 scdaemon, we use this callback. */
171 atfork_cb (void *opaque
, int where
)
174 gcry_control (GCRYCTL_TERM_SECMEM
);
178 /* Fork off the SCdaemon if this has not already been done. Note that
179 this fucntion alos locks the daemon. */
181 start_scd (ctrl_t ctrl
)
187 int no_close_list
[3];
191 if (!pth_mutex_acquire (&scd_lock
, 0, NULL
))
193 log_error ("failed to acquire the SCD lock\n");
194 return gpg_error (GPG_ERR_INTERNAL
);
202 /* If we are not the connection currently using the SCD, return
204 if (!active_connection
)
206 active_connection_fd
= ctrl
->connection_fd
;
207 active_connection
= 1;
209 else if (ctrl
->connection_fd
!= active_connection_fd
)
210 return unlock_scd (gpg_error (GPG_ERR_CONFLICT
));
212 /* Okay, we already started the scdaemon and it is used by us.*/
214 /* We better do a sanity check now to see whether it has
216 pid
= assuan_get_pid (scd_ctx
);
217 if (pid
!= (pid_t
)(-1) && pid
218 && ((rc
=waitpid (pid
, NULL
, WNOHANG
))==-1 || (rc
== pid
)) )
220 assuan_disconnect (scd_ctx
);
228 log_info ("no running SCdaemon - starting it\n");
232 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
233 log_error ("error flushing pending output: %s\n", strerror (errno
));
234 return unlock_scd (tmperr
);
237 if (!opt
.scdaemon_program
|| !*opt
.scdaemon_program
)
238 opt
.scdaemon_program
= GNUPG_DEFAULT_SCDAEMON
;
239 if ( !(pgmname
= strrchr (opt
.scdaemon_program
, '/')))
240 pgmname
= opt
.scdaemon_program
;
245 argv
[1] = "--server";
249 if (!opt
.running_detached
)
251 if (log_get_fd () != -1)
252 no_close_list
[i
++] = log_get_fd ();
253 no_close_list
[i
++] = fileno (stderr
);
255 no_close_list
[i
] = -1;
257 /* Connect to the pinentry and perform initial handshaking */
258 rc
= assuan_pipe_connect2 (&ctx
, opt
.scdaemon_program
, (char**)argv
,
259 no_close_list
, atfork_cb
, NULL
);
262 log_error ("can't connect to the SCdaemon: %s\n",
263 assuan_strerror (rc
));
264 return unlock_scd (gpg_error (GPG_ERR_NO_SCDAEMON
));
267 active_connection_fd
= ctrl
->connection_fd
;
268 active_connection
= 1;
271 log_debug ("connection to SCdaemon established\n");
273 /* Tell the scdaemon that we want him to send us an event signal.
274 But only do this if we are running as a regular sever and not
275 simply as a pipe server. */
276 if (ctrl
->connection_fd
!= -1)
280 sprintf (buf
, "OPTION event-signal=%d", SIGUSR2
);
281 assuan_transact (scd_ctx
, buf
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
289 /* Reset the SCD if it has been used. */
291 agent_reset_scd (ctrl_t ctrl
)
296 if (!pth_mutex_acquire (&scd_lock
, 0, NULL
))
298 log_error ("failed to acquire the SCD lock for reset\n");
299 return gpg_error (GPG_ERR_INTERNAL
);
302 if (active_connection
&& active_connection_fd
== ctrl
->connection_fd
)
305 rc
= assuan_transact (scd_ctx
, "RESET", NULL
, NULL
,
306 NULL
, NULL
, NULL
, NULL
);
307 active_connection_fd
= -1;
308 active_connection
= 0;
311 return unlock_scd (map_assuan_err (rc
));
319 learn_status_cb (void *opaque
, const char *line
)
321 struct learn_parm_s
*parm
= opaque
;
322 const char *keyword
= line
;
325 for (keywordlen
=0; *line
&& !spacep (line
); line
++, keywordlen
++)
327 while (spacep (line
))
329 if (keywordlen
== 8 && !memcmp (keyword
, "CERTINFO", keywordlen
))
331 parm
->certinfo_cb (parm
->certinfo_cb_arg
, line
);
333 else if (keywordlen
== 11 && !memcmp (keyword
, "KEYPAIRINFO", keywordlen
))
335 parm
->kpinfo_cb (parm
->kpinfo_cb_arg
, line
);
337 else if (keywordlen
&& *line
)
339 parm
->sinfo_cb (parm
->sinfo_cb_arg
, keyword
, keywordlen
, line
);
345 /* Perform the learn command and return a list of all private keys
346 stored on the card. */
348 agent_card_learn (ctrl_t ctrl
,
349 void (*kpinfo_cb
)(void*, const char *),
351 void (*certinfo_cb
)(void*, const char *),
352 void *certinfo_cb_arg
,
353 void (*sinfo_cb
)(void*, const char *, size_t, const char *),
357 struct learn_parm_s parm
;
359 rc
= start_scd (ctrl
);
363 memset (&parm
, 0, sizeof parm
);
364 parm
.kpinfo_cb
= kpinfo_cb
;
365 parm
.kpinfo_cb_arg
= kpinfo_cb_arg
;
366 parm
.certinfo_cb
= certinfo_cb
;
367 parm
.certinfo_cb_arg
= certinfo_cb_arg
;
368 parm
.sinfo_cb
= sinfo_cb
;
369 parm
.sinfo_cb_arg
= sinfo_cb_arg
;
370 rc
= assuan_transact (scd_ctx
, "LEARN --force",
371 NULL
, NULL
, NULL
, NULL
,
372 learn_status_cb
, &parm
);
374 return unlock_scd (map_assuan_err (rc
));
376 return unlock_scd (0);
382 get_serialno_cb (void *opaque
, const char *line
)
384 char **serialno
= opaque
;
385 const char *keyword
= line
;
389 for (keywordlen
=0; *line
&& !spacep (line
); line
++, keywordlen
++)
391 while (spacep (line
))
394 if (keywordlen
== 8 && !memcmp (keyword
, "SERIALNO", keywordlen
))
397 return ASSUAN_Unexpected_Status
;
398 for (n
=0,s
=line
; hexdigitp (s
); s
++, n
++)
400 if (!n
|| (n
&1)|| !(spacep (s
) || !*s
) )
401 return ASSUAN_Invalid_Status
;
402 *serialno
= xtrymalloc (n
+1);
404 return ASSUAN_Out_Of_Core
;
405 memcpy (*serialno
, line
, n
);
412 /* Return the serial number of the card or an appropriate error. The
413 serial number is returned as a hexstring. */
415 agent_card_serialno (ctrl_t ctrl
, char **r_serialno
)
418 char *serialno
= NULL
;
420 rc
= start_scd (ctrl
);
424 /* Hmm, do we really need this reset - scddaemon should do this or
425 we can do this if we for some reason figure out that the
426 operation might have failed due to a missing RESET. Hmmm, I feel
427 this is really SCdaemon's duty */
428 /* rc = assuan_transact (scd_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL); */
430 /* return unlock_scd (map_assuan_err (rc)); */
432 rc
= assuan_transact (scd_ctx
, "SERIALNO",
433 NULL
, NULL
, NULL
, NULL
,
434 get_serialno_cb
, &serialno
);
438 return unlock_scd (map_assuan_err (rc
));
440 *r_serialno
= serialno
;
441 return unlock_scd (0);
446 membuf_data_cb (void *opaque
, const void *buffer
, size_t length
)
448 struct membuf
*data
= opaque
;
451 put_membuf (data
, buffer
, length
);
455 /* Handle the NEEDPIN inquiry. */
457 inq_needpin (void *opaque
, const char *line
)
459 struct inq_needpin_s
*parm
= opaque
;
464 if (!(!strncmp (line
, "NEEDPIN", 7) && (line
[7] == ' ' || !line
[7])))
466 log_error ("unsupported inquiry `%s'\n", line
);
467 return ASSUAN_Inquire_Unknown
;
472 pin
= gcry_malloc_secure (pinlen
);
474 return ASSUAN_Out_Of_Core
;
476 rc
= parm
->getpin_cb (parm
->getpin_cb_arg
, line
, pin
, pinlen
);
478 rc
= ASSUAN_Canceled
;
480 rc
= assuan_send_data (parm
->ctx
, pin
, pinlen
);
488 /* Create a signature using the current card */
490 agent_card_pksign (ctrl_t ctrl
,
492 int (*getpin_cb
)(void *, const char *, char*, size_t),
494 const unsigned char *indata
, size_t indatalen
,
495 char **r_buf
, size_t *r_buflen
)
498 char *p
, line
[ASSUAN_LINELENGTH
];
500 struct inq_needpin_s inqparm
;
502 unsigned char *sigbuf
;
506 rc
= start_scd (ctrl
);
510 if (indatalen
*2 + 50 > DIM(line
))
511 return unlock_scd (gpg_error (GPG_ERR_GENERAL
));
513 sprintf (line
, "SETDATA ");
514 p
= line
+ strlen (line
);
515 for (i
=0; i
< indatalen
; i
++, p
+= 2 )
516 sprintf (p
, "%02X", indata
[i
]);
517 rc
= assuan_transact (scd_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
519 return unlock_scd (map_assuan_err (rc
));
521 init_membuf (&data
, 1024);
522 inqparm
.ctx
= scd_ctx
;
523 inqparm
.getpin_cb
= getpin_cb
;
524 inqparm
.getpin_cb_arg
= getpin_cb_arg
;
525 snprintf (line
, DIM(line
)-1, "PKSIGN %s", keyid
);
526 line
[DIM(line
)-1] = 0;
527 rc
= assuan_transact (scd_ctx
, line
,
528 membuf_data_cb
, &data
,
529 inq_needpin
, &inqparm
,
533 xfree (get_membuf (&data
, &len
));
534 return unlock_scd (map_assuan_err (rc
));
536 sigbuf
= get_membuf (&data
, &sigbuflen
);
538 /* create an S-expression from it which is formatted like this:
539 "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" */
540 *r_buflen
= 21 + 11 + sigbuflen
+ 4;
541 *r_buf
= xtrymalloc (*r_buflen
);
544 gpg_error_t tmperr
= out_of_core ();
546 return unlock_scd (tmperr
);
548 p
= stpcpy (*r_buf
, "(7:sig-val(3:rsa(1:s" );
549 sprintf (p
, "%u:", (unsigned int)sigbuflen
);
551 memcpy (p
, sigbuf
, sigbuflen
);
556 assert (gcry_sexp_canon_len (*r_buf
, *r_buflen
, NULL
, NULL
));
557 return unlock_scd (0);
560 /* Decipher INDATA using the current card. Note that the returned value is */
562 agent_card_pkdecrypt (ctrl_t ctrl
,
564 int (*getpin_cb
)(void *, const char *, char*, size_t),
566 const unsigned char *indata
, size_t indatalen
,
567 char **r_buf
, size_t *r_buflen
)
570 char *p
, line
[ASSUAN_LINELENGTH
];
572 struct inq_needpin_s inqparm
;
576 rc
= start_scd (ctrl
);
580 /* FIXME: use secure memory where appropriate */
581 if (indatalen
*2 + 50 > DIM(line
))
582 return unlock_scd (gpg_error (GPG_ERR_GENERAL
));
584 sprintf (line
, "SETDATA ");
585 p
= line
+ strlen (line
);
586 for (i
=0; i
< indatalen
; i
++, p
+= 2 )
587 sprintf (p
, "%02X", indata
[i
]);
588 rc
= assuan_transact (scd_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
590 return unlock_scd (map_assuan_err (rc
));
592 init_membuf (&data
, 1024);
593 inqparm
.ctx
= scd_ctx
;
594 inqparm
.getpin_cb
= getpin_cb
;
595 inqparm
.getpin_cb_arg
= getpin_cb_arg
;
596 snprintf (line
, DIM(line
)-1, "PKDECRYPT %s", keyid
);
597 line
[DIM(line
)-1] = 0;
598 rc
= assuan_transact (scd_ctx
, line
,
599 membuf_data_cb
, &data
,
600 inq_needpin
, &inqparm
,
604 xfree (get_membuf (&data
, &len
));
605 return unlock_scd (map_assuan_err (rc
));
607 *r_buf
= get_membuf (&data
, r_buflen
);
609 return unlock_scd (gpg_error (GPG_ERR_ENOMEM
));
611 return unlock_scd (0);
616 /* Read a certificate with ID into R_BUF and R_BUFLEN. */
618 agent_card_readcert (ctrl_t ctrl
,
619 const char *id
, char **r_buf
, size_t *r_buflen
)
622 char line
[ASSUAN_LINELENGTH
];
627 rc
= start_scd (ctrl
);
631 init_membuf (&data
, 1024);
632 snprintf (line
, DIM(line
)-1, "READCERT %s", id
);
633 line
[DIM(line
)-1] = 0;
634 rc
= assuan_transact (scd_ctx
, line
,
635 membuf_data_cb
, &data
,
640 xfree (get_membuf (&data
, &len
));
641 return unlock_scd (map_assuan_err (rc
));
643 *r_buf
= get_membuf (&data
, r_buflen
);
645 return unlock_scd (gpg_error (GPG_ERR_ENOMEM
));
647 return unlock_scd (0);
652 /* Read a key with ID and return it in an allocate buffer pointed to
653 by r_BUF as a valid S-expression. */
655 agent_card_readkey (ctrl_t ctrl
, const char *id
, unsigned char **r_buf
)
658 char line
[ASSUAN_LINELENGTH
];
663 rc
= start_scd (ctrl
);
667 init_membuf (&data
, 1024);
668 snprintf (line
, DIM(line
)-1, "READKEY %s", id
);
669 line
[DIM(line
)-1] = 0;
670 rc
= assuan_transact (scd_ctx
, line
,
671 membuf_data_cb
, &data
,
676 xfree (get_membuf (&data
, &len
));
677 return unlock_scd (map_assuan_err (rc
));
679 *r_buf
= get_membuf (&data
, &buflen
);
681 return unlock_scd (gpg_error (GPG_ERR_ENOMEM
));
683 if (!gcry_sexp_canon_len (*r_buf
, buflen
, NULL
, NULL
))
685 xfree (*r_buf
); *r_buf
= NULL
;
686 return unlock_scd (gpg_error (GPG_ERR_INV_VALUE
));
689 return unlock_scd (0);
696 pass_status_thru (void *opaque
, const char *line
)
698 ASSUAN_CONTEXT ctx
= opaque
;
702 for (i
=0; *line
&& !spacep (line
) && i
< DIM(keyword
)-1; line
++, i
++)
705 /* truncate any remaining keyword stuff. */
706 for (; *line
&& !spacep (line
); line
++)
708 while (spacep (line
))
711 assuan_write_status (ctx
, keyword
, line
);
716 pass_data_thru (void *opaque
, const void *buffer
, size_t length
)
718 ASSUAN_CONTEXT ctx
= opaque
;
720 assuan_send_data (ctx
, buffer
, length
);
725 /* Send the line CMDLINE with command for the SCDdaemon to it and send
726 all status messages back. This command is used as a general quoting
727 mechanism to pass everything verbatim to SCDAEMOPN. The PIN
728 inquirey is handled inside gpg-agent. */
730 agent_card_scd (ctrl_t ctrl
, const char *cmdline
,
731 int (*getpin_cb
)(void *, const char *, char*, size_t),
732 void *getpin_cb_arg
, void *assuan_context
)
735 struct inq_needpin_s inqparm
;
737 rc
= start_scd (ctrl
);
741 inqparm
.ctx
= scd_ctx
;
742 inqparm
.getpin_cb
= getpin_cb
;
743 inqparm
.getpin_cb_arg
= getpin_cb_arg
;
744 rc
= assuan_transact (scd_ctx
, cmdline
,
745 pass_data_thru
, assuan_context
,
746 inq_needpin
, &inqparm
,
747 pass_status_thru
, assuan_context
);
750 return unlock_scd (map_assuan_err (rc
));
753 return unlock_scd (0);