agent: Stop scdaemon after reload when disable_scdaemon.
[gnupg.git] / tools / card-misc.c
1 /* card-misc.c - Helper functions for gpg-card
2  * Copyright (C) 2019 g10 Code GmbH
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 3 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, see <https://www.gnu.org/licenses/>.
18  * SPDX-License-Identifier: GPL-3.0-or-later
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h>
27
28 #include "../common/util.h"
29 #include "../common/i18n.h"
30 #include "../common/openpgpdefs.h"
31 #include "gpg-card.h"
32
33 /* Return the key info object for the key KEYREF.  If it is not found
34  * NULL is returned.  */
35 key_info_t
36 find_kinfo (card_info_t info, const char *keyref)
37 {
38   key_info_t kinfo;
39
40   for (kinfo = info->kinfo; kinfo; kinfo = kinfo->next)
41     if (!strcmp (kinfo->keyref, keyref))
42       return kinfo;
43   return NULL;
44 }
45
46
47 /* Convert STRING into a newly allocated buffer while translating the
48  * hex numbers.  Blanks and colons are allowed to separate pairs of
49  * hex digits.  Returns NULL on error or a newly malloced buffer and
50  * its length in LENGTH.  */
51 void *
52 hex_to_buffer (const char *string, size_t *r_length)
53 {
54   unsigned char *buffer;
55   const char *s;
56   size_t n;
57
58   buffer = xtrymalloc (strlen (string)+1);
59   if (!buffer)
60     return NULL;
61   for (s=string, n=0; *s; s++)
62     {
63       if (ascii_isspace (*s) || *s == ':')
64         continue;
65       if (hexdigitp (s) && hexdigitp (s+1))
66         {
67           buffer[n++] = xtoi_2 (s);
68           s++;
69         }
70       else
71         {
72           xfree (buffer);
73           gpg_err_set_errno (EINVAL);
74           return NULL;
75         }
76     }
77   *r_length = n;
78   return buffer;
79 }
80
81
82 /* Direct sending of an hex encoded APDU with error printing.  This is
83  * a simple wrapper around scd_apdu.  */
84 gpg_error_t
85 send_apdu (const char *hexapdu, const char *desc, unsigned int ignore,
86            unsigned char **r_data, size_t *r_datalen)
87 {
88   gpg_error_t err;
89   unsigned int sw;
90
91   err = scd_apdu (hexapdu, &sw, r_data, r_datalen);
92   if (err)
93     log_error ("sending card command %s failed: %s\n", desc,
94                gpg_strerror (err));
95   else if (!hexapdu || !strcmp (hexapdu, "undefined"))
96     ;
97   else if (ignore == 0xffff)
98     ; /* Ignore all status words.  */
99   else if (sw != 0x9000)
100     {
101       switch (sw)
102         {
103         case 0x6285: err = gpg_error (GPG_ERR_OBJ_TERM_STATE); break;
104         case 0x6982: err = gpg_error (GPG_ERR_BAD_PIN); break;
105         case 0x6985: err = gpg_error (GPG_ERR_USE_CONDITIONS); break;
106         default: err = gpg_error (GPG_ERR_CARD);
107         }
108       if (!(ignore && ignore == sw))
109         log_error ("card command %s failed: %s (0x%04x)\n", desc,
110                    gpg_strerror (err),  sw);
111     }
112   return err;
113 }