aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--NEWS2
-rw-r--r--agent/agent.h6
-rw-r--r--agent/call-scd.c30
-rw-r--r--agent/command.c12
-rw-r--r--agent/divert-scd.c9
-rw-r--r--agent/pkdecrypt.c10
-rw-r--r--doc/gpg-agent.texi5
-rw-r--r--doc/scdaemon.texi4
-rw-r--r--g10/call-agent.c29
-rw-r--r--g10/call-agent.h3
-rw-r--r--g10/pubkey-enc.c6
-rw-r--r--scd/app-common.h29
-rw-r--r--scd/app-nks.c5
-rw-r--r--scd/app-openpgp.c5
-rw-r--r--scd/app.c8
-rw-r--r--scd/command.c10
16 files changed, 134 insertions, 39 deletions
diff --git a/NEWS b/NEWS
index 3b2016f3a..eb1bdbcf6 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,8 @@ Noteworthy changes in version 2.1.0-betaN (unreleased)
* Support installation as portable application under Windows.
+ * Fixed GPG to decrypt using an OpenPGP card.
+
Noteworthy changes in version 2.1.0beta3 (2011-12-20)
-----------------------------------------------------
diff --git a/agent/agent.h b/agent/agent.h
index 885e7fe75..ae4e4686f 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -370,7 +370,7 @@ int agent_pksign (ctrl_t ctrl, const char *cache_nonce,
/*-- pkdecrypt.c --*/
int agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
const unsigned char *ciphertext, size_t ciphertextlen,
- membuf_t *outbuf);
+ membuf_t *outbuf, int *r_padding);
/*-- genkey.c --*/
int check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent);
@@ -425,7 +425,7 @@ int divert_pksign (ctrl_t ctrl,
int divert_pkdecrypt (ctrl_t ctrl,
const unsigned char *cipher,
const unsigned char *shadow_info,
- char **r_buf, size_t *r_len);
+ char **r_buf, size_t *r_len, int *r_padding);
int divert_generic_cmd (ctrl_t ctrl,
const char *cmdline, void *assuan_context);
int divert_writekey (ctrl_t ctrl, int force, const char *serialno,
@@ -459,7 +459,7 @@ int agent_card_pkdecrypt (ctrl_t ctrl,
int (*getpin_cb)(void *, const char *, char*,size_t),
void *getpin_cb_arg,
const unsigned char *indata, size_t indatalen,
- char **r_buf, size_t *r_buflen);
+ char **r_buf, size_t *r_buflen, int *r_padding);
int agent_card_readcert (ctrl_t ctrl,
const char *id, char **r_buf, size_t *r_buflen);
int agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf);
diff --git a/agent/call-scd.c b/agent/call-scd.c
index a334b15a1..a6c429c41 100644
--- a/agent/call-scd.c
+++ b/agent/call-scd.c
@@ -1,6 +1,7 @@
/* call-scd.c - fork of the scdaemon to do SC operations
* Copyright (C) 2001, 2002, 2005, 2007, 2010,
* 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2013 Werner Koch
*
* This file is part of GnuPG.
*
@@ -874,14 +875,36 @@ agent_card_pksign (ctrl_t ctrl,
return unlock_scd (ctrl, 0);
}
-/* Decipher INDATA using the current card. Note that the returned value is */
+
+
+
+/* Check whether there is any padding info from scdaemon. */
+static gpg_error_t
+padding_info_cb (void *opaque, const char *line)
+{
+ int *r_padding = opaque;
+ const char *s;
+
+ if ((s=has_leading_keyword (line, "PADDING")))
+ {
+ *r_padding = atoi (s);
+ }
+
+ return 0;
+}
+
+
+/* Decipher INDATA using the current card. Note that the returned
+ value is not an s-expression but the raw data as returned by
+ scdaemon. The padding information is stored at R_PADDING with -1
+ for not known. */
int
agent_card_pkdecrypt (ctrl_t ctrl,
const char *keyid,
int (*getpin_cb)(void *, const char *, char*, size_t),
void *getpin_cb_arg,
const unsigned char *indata, size_t indatalen,
- char **r_buf, size_t *r_buflen)
+ char **r_buf, size_t *r_buflen, int *r_padding)
{
int rc, i;
char *p, line[ASSUAN_LINELENGTH];
@@ -890,6 +913,7 @@ agent_card_pkdecrypt (ctrl_t ctrl,
size_t len;
*r_buf = NULL;
+ *r_padding = -1; /* Unknown. */
rc = start_scd (ctrl);
if (rc)
return rc;
@@ -923,7 +947,7 @@ agent_card_pkdecrypt (ctrl_t ctrl,
rc = assuan_transact (ctrl->scd_local->ctx, line,
membuf_data_cb, &data,
inq_needpin, &inqparm,
- NULL, NULL);
+ padding_info_cb, r_padding);
if (inqparm.any_inq_seen && (gpg_err_code(rc) == GPG_ERR_CANCELED ||
gpg_err_code(rc) == GPG_ERR_ASS_CANCELED))
rc = cancel_inquire (ctrl, rc);
diff --git a/agent/command.c b/agent/command.c
index 8e5d1803a..938778ac4 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -865,6 +865,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
unsigned char *value;
size_t valuelen;
membuf_t outbuf;
+ int padding;
(void)line;
@@ -879,12 +880,19 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
init_membuf (&outbuf, 512);
rc = agent_pkdecrypt (ctrl, ctrl->server_local->keydesc,
- value, valuelen, &outbuf);
+ value, valuelen, &outbuf, &padding);
xfree (value);
if (rc)
clear_outbuf (&outbuf);
else
- rc = write_and_clear_outbuf (ctx, &outbuf);
+ {
+ if (padding != -1)
+ rc = print_assuan_status (ctx, "PADDING", "%d", padding);
+ else
+ rc = 0;
+ if (!rc)
+ rc = write_and_clear_outbuf (ctx, &outbuf);
+ }
xfree (ctrl->server_local->keydesc);
ctrl->server_local->keydesc = NULL;
return leave_cmd (ctx, rc);
diff --git a/agent/divert-scd.c b/agent/divert-scd.c
index f0d847389..ceef588fb 100644
--- a/agent/divert-scd.c
+++ b/agent/divert-scd.c
@@ -383,12 +383,13 @@ divert_pksign (ctrl_t ctrl,
/* 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. */
+ allocated buffer in R_BUF. The padding information is stored at
+ R_PADDING with -1 for not known. */
int
divert_pkdecrypt (ctrl_t ctrl,
const unsigned char *cipher,
const unsigned char *shadow_info,
- char **r_buf, size_t *r_len)
+ char **r_buf, size_t *r_len, int *r_padding)
{
int rc;
char *kid;
@@ -399,6 +400,8 @@ divert_pkdecrypt (ctrl_t ctrl,
char *plaintext;
size_t plaintextlen;
+ *r_padding = -1;
+
s = cipher;
if (*s != '(')
return gpg_error (GPG_ERR_INV_SEXP);
@@ -436,7 +439,7 @@ divert_pkdecrypt (ctrl_t ctrl,
rc = agent_card_pkdecrypt (ctrl, kid, getpin_cb, ctrl,
ciphertext, ciphertextlen,
- &plaintext, &plaintextlen);
+ &plaintext, &plaintextlen, r_padding);
if (!rc)
{
*r_buf = plaintext;
diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c
index 7df7f1d38..9924d6dff 100644
--- a/agent/pkdecrypt.c
+++ b/agent/pkdecrypt.c
@@ -32,11 +32,12 @@
/* DECRYPT the stuff in ciphertext which is expected to be a S-Exp.
Try to get the key from CTRL and write the decoded stuff back to
- OUTFP. */
+ OUTFP. The padding information is stored at R_PADDING with -1
+ for not known. */
int
agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
const unsigned char *ciphertext, size_t ciphertextlen,
- membuf_t *outbuf)
+ membuf_t *outbuf, int *r_padding)
{
gcry_sexp_t s_skey = NULL, s_cipher = NULL, s_plain = NULL;
unsigned char *shadow_info = NULL;
@@ -44,6 +45,8 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
char *buf = NULL;
size_t len;
+ *r_padding = -1;
+
if (!ctrl->have_keygrip)
{
log_error ("speculative decryption not yet supported\n");
@@ -85,7 +88,8 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
goto leave;
}
- rc = divert_pkdecrypt (ctrl, ciphertext, shadow_info, &buf, &len );
+ rc = divert_pkdecrypt (ctrl, ciphertext, shadow_info,
+ &buf, &len, r_padding);
if (rc)
{
log_error ("smartcard decryption failed: %s\n", gpg_strerror (rc));
diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi
index f832b8ebd..bfb1d9353 100644
--- a/doc/gpg-agent.texi
+++ b/doc/gpg-agent.texi
@@ -897,10 +897,15 @@ Here is an example session:
C: D (b 3F444677CA)))
C: END
S: # session key follows
+ S: S PADDING 0
S: D (value 1234567890ABCDEF0)
S: OK descryption successful
@end example
+The “PADDING” status line is only send if gpg-agent can tell what kind
+of padding is used. As of now only the value 0 is used to indicate
+that the padding has been removed.
+
@node Agent PKSIGN
@subsection Signing a Hash
diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi
index f454f1428..1a4b6d7b1 100644
--- a/doc/scdaemon.texi
+++ b/doc/scdaemon.texi
@@ -600,6 +600,10 @@ using the command
where @var{keyid} is the hexified ID of the key to be used.
+If the card is ware of the apdding format a status line with padding
+information is send before the plaintext data. The key for this
+status line is @code{PADDING} with the only defined value being 0 and
+meaning padding has been removed.
@node Scdaemon GETATTR
@subsection Read an attribute's value.
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 17290ec1a..4ce6a06ab 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -1816,17 +1816,34 @@ inq_ciphertext_cb (void *opaque, const char *line)
}
+/* Check whether there is any padding info from the agent. */
+static gpg_error_t
+padding_info_cb (void *opaque, const char *line)
+{
+ int *r_padding = opaque;
+ const char *s;
+
+ if ((s=has_leading_keyword (line, "PADDING")))
+ {
+ *r_padding = atoi (s);
+ }
+
+ return 0;
+}
+
+
/* Call the agent to do a decrypt operation using the key identified
by the hex string KEYGRIP and the input data S_CIPHERTEXT. On the
success the decoded value is stored verbatim at R_BUF and its
length at R_BUF; the callers needs to release it. KEYID, MAINKEYID
and PUBKEY_ALGO are used to construct additional promots or status
- messages. */
+ messages. The padding information is stored at R_PADDING with -1
+ for not known. */
gpg_error_t
agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
u32 *keyid, u32 *mainkeyid, int pubkey_algo,
gcry_sexp_t s_ciphertext,
- unsigned char **r_buf, size_t *r_buflen)
+ unsigned char **r_buf, size_t *r_buflen, int *r_padding)
{
gpg_error_t err;
char line[ASSUAN_LINELENGTH];
@@ -1841,9 +1858,12 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
dfltparm.keyinfo.mainkeyid = mainkeyid;
dfltparm.keyinfo.pubkey_algo = pubkey_algo;
- if (!keygrip || strlen(keygrip) != 40 || !s_ciphertext || !r_buf || !r_buflen)
+ if (!keygrip || strlen(keygrip) != 40
+ || !s_ciphertext || !r_buf || !r_buflen || !r_padding)
return gpg_error (GPG_ERR_INV_VALUE);
+
*r_buf = NULL;
+ *r_padding = -1;
err = start_agent (ctrl, 0);
if (err)
@@ -1881,7 +1901,8 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
return err;
err = assuan_transact (agent_ctx, "PKDECRYPT",
membuf_data_cb, &data,
- inq_ciphertext_cb, &parm, NULL, NULL);
+ inq_ciphertext_cb, &parm,
+ padding_info_cb, r_padding);
xfree (parm.ciphertext);
}
if (err)
diff --git a/g10/call-agent.h b/g10/call-agent.h
index cce8304bc..2b944d21b 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -168,7 +168,8 @@ gpg_error_t agent_pksign (ctrl_t ctrl, const char *cache_nonce,
gpg_error_t agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
u32 *keyid, u32 *mainkeyid, int pubkey_algo,
gcry_sexp_t s_ciphertext,
- unsigned char **r_buf, size_t *r_buflen);
+ unsigned char **r_buf, size_t *r_buflen,
+ int *r_padding);
/* Retrieve a key encryption key. */
gpg_error_t agent_keywrap_key (ctrl_t ctrl, int forexport,
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index a328e1adc..1e7255711 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -146,7 +146,7 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
unsigned int n;
size_t nframe;
u16 csum, csum2;
- int card = 0;
+ int padding;
gcry_sexp_t s_data;
char *desc;
char *keygrip;
@@ -203,7 +203,7 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
desc = gpg_format_keydesc (sk, 0, 1);
err = agent_pkdecrypt (NULL, keygrip,
desc, sk->keyid, sk->main_keyid, sk->pubkey_algo,
- s_data, &frame, &nframe);
+ s_data, &frame, &nframe, &padding);
xfree (desc);
gcry_sexp_release (s_data);
if (err)
@@ -270,7 +270,7 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
}
else
{
- if (!card)
+ if (padding)
{
if (n + 7 > nframe)
{
diff --git a/scd/app-common.h b/scd/app-common.h
index e3d23c2b4..66430b61d 100644
--- a/scd/app-common.h
+++ b/scd/app-common.h
@@ -34,6 +34,9 @@
#define APP_CHANGE_FLAG_RESET 1
#define APP_CHANGE_FLAG_NULLPIN 2
+/* Bit flags set by the decipher function into R_INFO. */
+#define APP_DECIPHER_INFO_NOPAD 1 /* Padding has been removed. */
+
struct app_local_s; /* Defined by all app-*.c. */
@@ -93,10 +96,11 @@ struct app_ctx_s {
const void *indata, size_t indatalen,
unsigned char **outdata, size_t *outdatalen);
gpg_error_t (*decipher) (app_t app, const char *keyidstr,
- gpg_error_t (*pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen);
+ gpg_error_t (*pincb)(void*, const char *, char **),
+ void *pincb_arg,
+ const void *indata, size_t indatalen,
+ unsigned char **outdata, size_t *outdatalen,
+ unsigned int *r_info);
gpg_error_t (*writecert) (app_t app, ctrl_t ctrl,
const char *certid,
gpg_error_t (*pincb)(void*,const char *,char **),
@@ -168,15 +172,16 @@ gpg_error_t app_sign (app_t app, const char *keyidstr, int hashalgo,
const void *indata, size_t indatalen,
unsigned char **outdata, size_t *outdatalen );
gpg_error_t app_auth (app_t app, const char *keyidstr,
- gpg_error_t (*pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen);
+ gpg_error_t (*pincb)(void*, const char *, char **),
+ void *pincb_arg,
+ const void *indata, size_t indatalen,
+ unsigned char **outdata, size_t *outdatalen);
gpg_error_t app_decipher (app_t app, const char *keyidstr,
- gpg_error_t (*pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen );
+ gpg_error_t (*pincb)(void*, const char *, char **),
+ void *pincb_arg,
+ const void *indata, size_t indatalen,
+ unsigned char **outdata, size_t *outdatalen,
+ unsigned int *r_info);
gpg_error_t app_writecert (app_t app, ctrl_t ctrl,
const char *certidstr,
gpg_error_t (*pincb)(void*, const char *, char **),
diff --git a/scd/app-nks.c b/scd/app-nks.c
index 72e726d39..c83217fd0 100644
--- a/scd/app-nks.c
+++ b/scd/app-nks.c
@@ -985,13 +985,16 @@ do_decipher (app_t app, const char *keyidstr,
gpg_error_t (*pincb)(void*, const char *, char **),
void *pincb_arg,
const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen )
+ unsigned char **outdata, size_t *outdatalen,
+ unsigned int *r_info)
{
int rc, i;
int is_sigg = 0;
int fid;
int kid;
+ (void)r_info;
+
if (!keyidstr || !*keyidstr || !indatalen)
return gpg_error (GPG_ERR_INV_VALUE);
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 011c24840..dd4a2d91e 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -3598,7 +3598,8 @@ do_decipher (app_t app, const char *keyidstr,
gpg_error_t (*pincb)(void*, const char *, char **),
void *pincb_arg,
const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen )
+ unsigned char **outdata, size_t *outdatalen,
+ unsigned int *r_info)
{
int rc;
unsigned char tmp_sn[20]; /* actually 16 but we use it also for the fpr. */
@@ -3727,6 +3728,8 @@ do_decipher (app_t app, const char *keyidstr,
&& app->card_version == 0x0200)
log_info ("NOTE: Cards with manufacturer id 5 and s/n <= 346 (0x15a)"
" do not work with encryption keys > 2048 bits\n");
+
+ *r_info |= APP_DECIPHER_INFO_NOPAD;
}
return rc;
diff --git a/scd/app.c b/scd/app.c
index e6a663e1e..a0bb5f5ac 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -801,10 +801,13 @@ app_decipher (app_t app, const char *keyidstr,
gpg_error_t (*pincb)(void*, const char *, char **),
void *pincb_arg,
const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen )
+ unsigned char **outdata, size_t *outdatalen,
+ unsigned int *r_info)
{
gpg_error_t err;
+ *r_info = 0;
+
if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
return gpg_error (GPG_ERR_INV_VALUE);
if (!app->ref_count)
@@ -817,7 +820,8 @@ app_decipher (app_t app, const char *keyidstr,
err = app->fnc.decipher (app, keyidstr,
pincb, pincb_arg,
indata, indatalen,
- outdata, outdatalen);
+ outdata, outdatalen,
+ r_info);
unlock_reader (app->slot);
if (opt.verbose)
log_info ("operation decipher result: %s\n", gpg_strerror (err));
diff --git a/scd/command.c b/scd/command.c
index d5cc32cd9..05b50b935 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -1089,6 +1089,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
unsigned char *outdata;
size_t outdatalen;
char *keyidstr;
+ unsigned int infoflags;
if ( IS_LOCKED (ctrl) )
return gpg_error (GPG_ERR_LOCKED);
@@ -1103,7 +1104,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
keyidstr,
pin_cb, ctx,
ctrl->in_data.value, ctrl->in_data.valuelen,
- &outdata, &outdatalen);
+ &outdata, &outdatalen, &infoflags);
xfree (keyidstr);
if (rc)
@@ -1112,6 +1113,13 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
}
else
{
+ /* If the card driver told us that there is no padding, send a
+ status line. If there is a padding it is assumed that the
+ caller knows what padding is used. It would have been better
+ to always send that information but for backward
+ compatibility we can't do that. */
+ if ((infoflags & APP_DECIPHER_INFO_NOPAD))
+ send_status_direct (ctrl, "PADDING", "0");
rc = assuan_send_data (ctx, outdata, outdatalen);
xfree (outdata);
if (rc)