1 /* divert-scd.c - divert operations to the scdaemon
2 * Copyright (C) 2002, 2003, 2009 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 3 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, see <https://www.gnu.org/licenses/>.
32 #include "sexp-parse.h"
36 ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
42 char *want_sn, *want_kid;
47 rc = parse_shadow_info (shadow_info, &want_sn, &want_kid, NULL);
51 /* We assume that a 20 byte serial number is a standard one which
52 has the property to have a zero in the last nibble (Due to BCD
53 representation). We don't display this '0' because it may
55 want_sn_displen = strlen (want_sn);
56 if (want_sn_displen == 20 && want_sn[19] == '0')
61 rc = agent_card_serialno (ctrl, &serialno);
64 log_debug ("detected card with S/N %s\n", serialno);
65 i = strcmp (serialno, want_sn);
72 return 0; /* yes, we have the correct card */
75 else if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT)
77 log_debug ("no card present\n");
83 log_error ("error accessing card: %s\n", gpg_strerror (rc));
92 ? L_("Please insert the card with serial number")
93 : L_("Please remove the current card and "
94 "insert the one with serial number"),
95 want_sn_displen, want_sn) < 0)
101 rc = agent_get_confirmation (ctrl, desc, NULL, NULL, 0);
102 if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK &&
103 gpg_err_code (rc) == GPG_ERR_NO_PIN_ENTRY)
104 rc = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
119 /* Put the DIGEST into an DER encoded container and return it in R_VAL. */
121 encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
122 unsigned char **r_val, size_t *r_len)
124 unsigned char *frame;
125 unsigned char asn[100];
132 if (!algo || gcry_md_test_algo (algo))
133 return gpg_error (GPG_ERR_DIGEST_ALGO);
134 if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
136 log_error ("no object identifier for algo %d\n", algo);
137 return gpg_error (GPG_ERR_INTERNAL);
140 frame = xtrymalloc (asnlen + digestlen);
142 return out_of_core ();
143 memcpy (frame, asn, asnlen);
144 memcpy (frame+asnlen, digest, digestlen);
146 log_printhex ("encoded hash:", frame, asnlen+digestlen);
149 *r_len = asnlen+digestlen;
154 /* Callback used to ask for the PIN which should be set into BUF. The
155 buf has been allocated by the caller and is of size MAXBUF which
156 includes the terminating null. The function should return an UTF-8
157 string with the passphrase, the buffer may optionally be padded
158 with arbitrary characters.
160 INFO gets displayed as part of a generic string. However if the
161 first character of INFO is a vertical bar all up to the next
162 verical bar are considered flags and only everything after the
163 second vertical bar gets displayed as the full prompt.
167 'N' = New PIN, this requests a second prompt to repeat the
168 PIN. If the PIN is not correctly repeated it starts from
170 'A' = The PIN is an Admin PIN, SO-PIN or alike.
171 'P' = The PIN is a PUK (Personal Unblocking Key).
172 'R' = The PIN is a Reset Code.
176 "|AN|Please enter the new security officer's PIN"
178 The text "Please ..." will get displayed and the flags 'A' and 'N'
182 getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
184 struct pin_entry_info_s *pi;
186 ctrl_t ctrl = opaque;
187 const char *ends, *s;
192 const char *again_text = NULL;
193 const char *prompt = "PIN";
195 if (buf && maxbuf < 2)
196 return gpg_error (GPG_ERR_INV_VALUE);
198 /* Parse the flags. */
199 if (info && *info =='|' && (ends=strchr (info+1, '|')))
201 for (s=info+1; s < ends; s++)
204 prompt = L_("Admin PIN");
207 /* TRANSLATORS: A PUK is the Personal Unblocking Code
208 used to unblock a PIN. */
216 prompt = L_("Reset Code");
223 else if (info && *info == '|')
224 log_debug ("pin_cb called without proper PIN info hack\n");
226 /* If BUF has been passed as NULL, we are in pinpad mode: The
227 callback opens the popup and immediately returns. */
230 if (maxbuf == 0) /* Close the pinentry. */
232 agent_popup_message_stop (ctrl);
235 else if (maxbuf == 1) /* Open the pinentry. */
241 if ( asprintf (&desc,
242 L_("%s%%0A%%0AUse the reader's pinpad for input."),
244 rc = gpg_error_from_syserror ();
247 rc = agent_popup_message_start (ctrl, desc, NULL);
252 rc = agent_popup_message_start (ctrl, NULL, NULL);
255 rc = gpg_error (GPG_ERR_INV_VALUE);
259 /* FIXME: keep PI and TRIES in OPAQUE. Frankly this is a whole
260 mess because we should call the card's verify function from the
261 pinentry check pin CB. */
263 pi = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10);
265 return gpg_error_from_syserror ();
266 pi->max_length = maxbuf-1;
267 pi->min_digits = 0; /* we want a real passphrase */
273 rc = agent_askpin (ctrl, info, prompt, again_text, pi, NULL, 0);
277 struct pin_entry_info_s *pi2;
278 pi2 = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10);
281 rc = gpg_error_from_syserror ();
285 pi2->max_length = maxbuf-1;
287 pi2->max_digits = 16;
289 rc = agent_askpin (ctrl,
291 L_("Repeat this Reset Code"):
293 L_("Repeat this PUK"):
294 L_("Repeat this PIN")),
295 prompt, NULL, pi2, NULL, 0);
296 if (!rc && strcmp (pi->pin, pi2->pin))
298 again_text = (resetcode?
299 L_("Reset Code not correctly repeated; try again"):
301 L_("PUK not correctly repeated; try again"):
302 L_("PIN not correctly repeated; try again"));
313 if ( asprintf (&desc,
314 L_("Please enter the PIN%s%s%s to unlock the card"),
319 rc = agent_askpin (ctrl, desc?desc:info, prompt, NULL, pi, NULL, 0);
325 strncpy (buf, pi->pin, maxbuf-1);
336 divert_pksign (ctrl_t ctrl,
337 const unsigned char *digest, size_t digestlen, int algo,
338 const unsigned char *shadow_info, unsigned char **r_sig,
344 unsigned char *sigval = NULL;
346 rc = ask_for_card (ctrl, shadow_info, &kid);
350 if (algo == MD_USER_TLS_MD5SHA1)
352 int save = ctrl->use_auth_call;
353 ctrl->use_auth_call = 1;
354 rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl,
355 algo, digest, digestlen, &sigval, &siglen);
356 ctrl->use_auth_call = save;
363 rc = encode_md_for_card (digest, digestlen, algo, &data, &ndata);
366 rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl,
367 algo, data, ndata, &sigval, &siglen);
384 /* Decrypt the the value given asn an S-expression in CIPHER using the
385 key identified by SHADOW_INFO and return the plaintext in an
386 allocated buffer in R_BUF. The padding information is stored at
387 R_PADDING with -1 for not known. */
389 divert_pkdecrypt (ctrl_t ctrl,
390 const unsigned char *cipher,
391 const unsigned char *shadow_info,
392 char **r_buf, size_t *r_len, int *r_padding)
396 const unsigned char *s;
398 const unsigned char *ciphertext;
399 size_t ciphertextlen;
407 return gpg_error (GPG_ERR_INV_SEXP);
411 return gpg_error (GPG_ERR_INV_SEXP);
412 if (!smatch (&s, n, "enc-val"))
413 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
415 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
419 return gpg_error (GPG_ERR_INV_SEXP);
420 if (smatch (&s, n, "rsa"))
423 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
427 return gpg_error (GPG_ERR_INV_SEXP);
428 if (!smatch (&s, n, "a"))
429 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
432 else if (smatch (&s, n, "ecdh"))
435 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
439 return gpg_error (GPG_ERR_INV_SEXP);
440 if (smatch (&s, n, "s"))
445 return gpg_error (GPG_ERR_INV_SEXP);
447 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
450 return gpg_error (GPG_ERR_INV_SEXP);
452 if (!smatch (&s, n, "e"))
453 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
457 return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
460 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
464 rc = ask_for_card (ctrl, shadow_info, &kid);
468 rc = agent_card_pkdecrypt (ctrl, kid, getpin_cb, ctrl,
469 ciphertext, ciphertextlen,
470 &plaintext, &plaintextlen, r_padding);
474 *r_len = plaintextlen;
481 divert_writekey (ctrl_t ctrl, int force, const char *serialno,
482 const char *id, const char *keydata, size_t keydatalen)
484 return agent_card_writekey (ctrl, force, serialno, id, keydata, keydatalen,
489 divert_generic_cmd (ctrl_t ctrl, const char *cmdline, void *assuan_context)
491 return agent_card_scd (ctrl, cmdline, getpin_cb, ctrl, assuan_context);