-/* divert-scd.c - divert operations to the scdaemon
- * Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* divert-scd.c - divert operations to the scdaemon
+ * Copyright (C) 2002, 2003, 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <sys/stat.h>
#include "agent.h"
-#include "sexp-parse.h"
#include "i18n.h"
+#include "sexp-parse.h"
static int
ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
{
int rc, i;
- const unsigned char *s;
- size_t n;
char *serialno;
int no_card = 0;
char *desc;
int want_sn_displen;
*r_kid = NULL;
- s = shadow_info;
- if (*s != '(')
- return gpg_error (GPG_ERR_INV_SEXP);
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- want_sn = xtrymalloc (n*2+1);
- if (!want_sn)
- return out_of_core ();
- for (i=0; i < n; i++)
- sprintf (want_sn+2*i, "%02X", s[i]);
- s += n;
+
+ rc = parse_shadow_info (shadow_info, &want_sn, &want_kid, NULL);
+ if (rc)
+ return rc;
+
/* We assume that a 20 byte serial number is a standard one which
- seems to have the property to have a zero in the last nibble. We
- don't display this '0' because it may confuse the user */
+ has the property to have a zero in the last nibble (Due to BCD
+ representation). We don't display this '0' because it may
+ confuse the user. */
want_sn_displen = strlen (want_sn);
if (want_sn_displen == 20 && want_sn[19] == '0')
want_sn_displen--;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- want_kid = xtrymalloc (n+1);
- if (!want_kid)
- {
- gpg_error_t tmperr = out_of_core ();
- xfree (want_sn);
- return tmperr;
- }
- memcpy (want_kid, s, n);
- want_kid[n] = 0;
-
for (;;)
{
rc = agent_card_serialno (ctrl, &serialno);
}
else
{
- log_error ("error accesing card: %s\n", gpg_strerror (rc));
+ log_error ("error accessing card: %s\n", gpg_strerror (rc));
}
if (!rc)
if (asprintf (&desc,
"%s:%%0A%%0A"
" \"%.*s\"",
- no_card? "Please insert the card with serial number"
- : "Please remove the current card and "
- "insert the one with serial number",
+ no_card
+ ? _("Please insert the card with serial number")
+ : _("Please remove the current card and "
+ "insert the one with serial number"),
want_sn_displen, want_sn) < 0)
{
rc = out_of_core ();
}
else
{
- rc = agent_get_confirmation (ctrl, desc, NULL, NULL);
- free (desc);
+ rc = agent_get_confirmation (ctrl, desc, NULL, NULL, 0);
+ if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK &&
+ gpg_err_code (rc) == GPG_ERR_NO_PIN_ENTRY)
+ rc = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
+
+ xfree (desc);
}
}
if (rc)
memcpy (frame+asnlen, digest, digestlen);
if (DBG_CRYPTO)
log_printhex ("encoded hash:", frame, asnlen+digestlen);
-
+
*r_val = frame;
*r_len = asnlen+digestlen;
return 0;
Flags:
- 'N' = New PIN, this requests a second prompt to repeat the the
+ 'N' = New PIN, this requests a second prompt to repeat the
PIN. If the PIN is not correctly repeated it starts from
all over.
- 'A' = The PIN is an Admin PIN, SO-PIN, PUK or alike.
+ 'A' = The PIN is an Admin PIN, SO-PIN or alike.
+ 'P' = The PIN is a PUK (Personal Unblocking Key).
+ 'R' = The PIN is a Reset Code.
Example:
"|AN|Please enter the new security officer's PIN"
-
+
The text "Please ..." will get displayed and the flags 'A' and 'N'
are considered.
*/
-static int
+static int
getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
{
struct pin_entry_info_s *pi;
const char *ends, *s;
int any_flags = 0;
int newpin = 0;
+ int resetcode = 0;
+ int is_puk = 0;
const char *again_text = NULL;
const char *prompt = "PIN";
{
if (*s == 'A')
prompt = _("Admin PIN");
+ else if (*s == 'P')
+ {
+ /* TRANSLATORS: A PUK is the Personal Unblocking Code
+ used to unblock a PIN. */
+ prompt = _("PUK");
+ is_puk = 1;
+ }
else if (*s == 'N')
newpin = 1;
+ else if (*s == 'R')
+ {
+ prompt = _("Reset Code");
+ resetcode = 1;
+ }
}
info = ends+1;
any_flags = 1;
else if (info && *info == '|')
log_debug ("pin_cb called without proper PIN info hack\n");
- /* If BUF has been passed as NULL, we are in keypad mode: The
+ /* If BUF has been passed as NULL, we are in pinpad mode: The
callback opens the popup and immediatley returns. */
if (!buf)
{
}
else if (maxbuf == 1) /* Open the pinentry. */
{
- rc = agent_popup_message_start (ctrl, info, NULL, NULL);
+ if (info)
+ {
+ char *desc;
+
+ if ( asprintf (&desc,
+ _("%s%%0A%%0AUse the reader's pinpad for input."),
+ info) < 0 )
+ rc = gpg_error_from_syserror ();
+ else
+ {
+ rc = agent_popup_message_start (ctrl, desc, NULL);
+ xfree (desc);
+ }
+ }
+ else
+ rc = agent_popup_message_start (ctrl, NULL, NULL);
}
else
rc = gpg_error (GPG_ERR_INV_VALUE);
return gpg_error_from_syserror ();
pi->max_length = maxbuf-1;
pi->min_digits = 0; /* we want a real passphrase */
- pi->max_digits = 8;
+ pi->max_digits = 16;
pi->max_tries = 3;
if (any_flags)
}
pi2->max_length = maxbuf-1;
pi2->min_digits = 0;
- pi2->max_digits = 8;
+ pi2->max_digits = 16;
pi2->max_tries = 1;
- rc = agent_askpin (ctrl, _("Repeat this PIN"), prompt, NULL, pi2);
+ rc = agent_askpin (ctrl,
+ (resetcode?
+ _("Repeat this Reset Code"):
+ is_puk?
+ _("Repeat this PUK"):
+ _("Repeat this PIN")),
+ prompt, NULL, pi2);
if (!rc && strcmp (pi->pin, pi2->pin))
{
- again_text = N_("PIN not correctly repeated; try again");
+ again_text = (resetcode?
+ N_("Reset Code not correctly repeated; try again"):
+ is_puk?
+ N_("PUK not correctly repeated; try again"):
+ N_("PIN not correctly repeated; try again"));
xfree (pi2);
xfree (pi);
goto again;
{
char *desc;
if ( asprintf (&desc,
- _("Please enter the PIN%s%s%s to unlock the card"),
- info? " (`":"",
+ _("Please enter the PIN%s%s%s to unlock the card"),
+ info? " (":"",
info? info:"",
- info? "')":"") < 0)
+ info? ")":"") < 0)
desc = NULL;
rc = agent_askpin (ctrl, desc?desc:info, prompt, NULL, pi);
- free (desc);
+ xfree (desc);
}
if (!rc)
int
-divert_pksign (ctrl_t ctrl,
+divert_pksign (ctrl_t ctrl,
const unsigned char *digest, size_t digestlen, int algo,
- const unsigned char *shadow_info, unsigned char **r_sig)
+ const unsigned char *shadow_info, unsigned char **r_sig,
+ size_t *r_siglen)
{
int rc;
char *kid;
if (rc)
return rc;
- if (algo == GCRY_MD_USER_TLS_MD5SHA1)
+ if (algo == MD_USER_TLS_MD5SHA1)
{
+ int save = ctrl->use_auth_call;
+ ctrl->use_auth_call = 1;
rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl,
- digest, digestlen, &sigval, &siglen);
+ algo, digest, digestlen, &sigval, &siglen);
+ ctrl->use_auth_call = save;
}
else
{
if (!rc)
{
rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl,
- data, ndata, &sigval, &siglen);
+ algo, data, ndata, &sigval, &siglen);
xfree (data);
}
}
if (!rc)
- *r_sig = sigval;
+ {
+ *r_sig = sigval;
+ *r_siglen = siglen;
+ }
xfree (kid);
/* Decrypt the the value given asn an S-expression in CIPHER using the
key identified by SHADOW_INFO and return the plaintext in an
allocated buffer in R_BUF. */
-int
+int
divert_pkdecrypt (ctrl_t ctrl,
const unsigned char *cipher,
const unsigned char *shadow_info,
s++;
n = snext (&s);
if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
+ return gpg_error (GPG_ERR_INV_SEXP);
if (!smatch (&s, n, "enc-val"))
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
+ return gpg_error (GPG_ERR_UNKNOWN_SEXP);
if (*s != '(')
return gpg_error (GPG_ERR_UNKNOWN_SEXP);
s++;
n = snext (&s);
if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
+ return gpg_error (GPG_ERR_INV_SEXP);
if (!smatch (&s, n, "rsa"))
- return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+ return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
if (*s != '(')
return gpg_error (GPG_ERR_UNKNOWN_SEXP);
s++;
n = snext (&s);
if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
+ return gpg_error (GPG_ERR_INV_SEXP);
if (!smatch (&s, n, "a"))
return gpg_error (GPG_ERR_UNKNOWN_SEXP);
n = snext (&s);
if (!n)
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
+ return gpg_error (GPG_ERR_UNKNOWN_SEXP);
ciphertext = s;
ciphertextlen = n;
return rc;
}
+int
+divert_writekey (ctrl_t ctrl, int force, const char *serialno,
+ const char *id, const char *keydata, size_t keydatalen)
+{
+ return agent_card_writekey (ctrl, force, serialno, id, keydata, keydatalen,
+ getpin_cb, ctrl);
+}
-int
+int
divert_generic_cmd (ctrl_t ctrl, const char *cmdline, void *assuan_context)
{
return agent_card_scd (ctrl, cmdline, getpin_cb, ctrl, assuan_context);
}
-
-
-
-
-