aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--g10/ChangeLog11
-rw-r--r--g10/cardglue.c15
-rw-r--r--g10/cardglue.h2
-rw-r--r--g10/ccid-driver.c102
-rw-r--r--g10/pubkey-enc.c81
-rw-r--r--g10/sign.c6
6 files changed, 159 insertions, 58 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 23f5db587..324b96e07 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,14 @@
+2003-10-09 Werner Koch <[email protected]>
+
+ * ccid-driver.c (ccid_transceive): Add T=1 chaining for sending.
+
+ * sign.c (do_sign) [!ENABLE_CARD_SUPPORT]: Return an error for
+ card keys.
+
+ * cardglue.c (agent_scd_pkdecrypt): Implemented.
+ * pubkey-enc.c (get_it) [ENABLE_CARD_SUPPORT]: Divert decryption
+ to card
+
2003-10-08 Werner Koch <[email protected]>
* cardglue.c (pin_cb): Detect whether an admin or regular PIN is
diff --git a/g10/cardglue.c b/g10/cardglue.c
index fd7cf8b3d..91637a776 100644
--- a/g10/cardglue.c
+++ b/g10/cardglue.c
@@ -631,10 +631,21 @@ agent_scd_pksign (const char *serialno, int hashalgo,
int
agent_scd_pkdecrypt (const char *serialno,
const unsigned char *indata, size_t indatalen,
- char **r_buf, size_t *r_buflen)
+ unsigned char **r_buf, size_t *r_buflen)
{
- return gpg_error (GPG_ERR_CARD);
+ APP app;
+
+ *r_buf = NULL;
+ *r_buflen = 0;
+ app = current_app? current_app : open_card ();
+ if (!app)
+ return gpg_error (GPG_ERR_CARD);
+
+ return app->fnc.decipher (app, serialno,
+ pin_cb, NULL,
+ indata, indatalen,
+ r_buf, r_buflen);
}
/* Change the PIN of an OpenPGP card or reset the retry counter. */
diff --git a/g10/cardglue.h b/g10/cardglue.h
index 273b99313..fcd372682 100644
--- a/g10/cardglue.h
+++ b/g10/cardglue.h
@@ -151,7 +151,7 @@ int agent_scd_pksign (const char *keyid, int hashalgo,
/* Send a PKDECRYPT command to the SCdaemon. */
int agent_scd_pkdecrypt (const char *serialno,
const unsigned char *indata, size_t indatalen,
- char **r_buf, size_t *r_buflen);
+ unsigned char **r_buf, size_t *r_buflen);
/* Change the PIN of an OpenPGP card or reset the retry counter. */
int agent_scd_change_pin (int chvno);
diff --git a/g10/ccid-driver.c b/g10/ccid-driver.c
index b4fbc0b21..35f0329db 100644
--- a/g10/ccid-driver.c
+++ b/g10/ccid-driver.c
@@ -132,6 +132,11 @@
#endif /* This source not used by scdaemon. */
+/* Define to print information pertaining the T=1 protocol. */
+#undef DEBUG_T1 1
+
+
+
enum {
RDR_to_PC_NotifySlotChange= 0x50,
RDR_to_PC_HardwareError = 0x51,
@@ -566,7 +571,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
return -1;
}
- DEBUGOUT_3 ("status: %02X error: %02X clock-status: %02X\n"
+ DEBUGOUT_3 ("status: %02X error: %02X octet[9]: %02X\n"
" data:", buffer[7], buffer[8], buffer[9] );
for (i=10; i < msglen; i++)
DEBUGOUT_CONT_1 (" %02X", buffer[i]);
@@ -753,44 +758,62 @@ ccid_get_atr (ccid_driver_t handle,
int
ccid_transceive (ccid_driver_t handle,
- const unsigned char *apdu, size_t apdulen,
+ const unsigned char *apdu_buf, size_t apdu_buflen,
unsigned char *resp, size_t maxresplen, size_t *nresp)
{
int rc;
unsigned char send_buffer[10+258], recv_buffer[10+258];
+ const unsigned char *apdu;
+ size_t apdulen;
unsigned char *msg, *tpdu, *p;
size_t msglen, tpdulen, n;
unsigned char seqno;
int i;
unsigned char crc;
size_t dummy_nresp;
+ int next_chunk = 1;
int sending = 1;
if (!nresp)
nresp = &dummy_nresp;
-
*nresp = 0;
-
- /* Construct an I-Block. */
- if (apdulen > 254)
- return -1; /* Invalid length. */
+ tpdulen = 0; /* Avoid compiler warning about no initialization. */
msg = send_buffer;
+ for (;;)
+ {
+ if (next_chunk)
+ {
+ next_chunk = 0;
- tpdu = msg+10;
- tpdu[0] = ((1 << 4) | 0); /* NAD: DAD=1, SAD=0 */
- tpdu[1] = ((handle->t1_ns & 1) << 6); /* I-block */
- tpdu[2] = apdulen;
- memcpy (tpdu+3, apdu, apdulen);
- crc = 0;
- for (i=0,p=tpdu; i < apdulen+3; i++)
- crc ^= *p++;
- tpdu[3+apdulen] = crc;
+ apdu = apdu_buf;
+ apdulen = apdu_buflen;
+ assert (apdulen);
- tpdulen = apdulen + 4;
+ /* Construct an I-Block. */
+ if (apdulen > 254)
+ return -1; /* Invalid length. */
+
+ tpdu = msg+10;
+ tpdu[0] = ((1 << 4) | 0); /* NAD: DAD=1, SAD=0 */
+ tpdu[1] = ((handle->t1_ns & 1) << 6); /* I-block */
+ if (apdulen > 128 /* fixme: replace by ifsc */)
+ {
+ apdulen = 128;
+ apdu_buf += 128;
+ apdu_buflen -= 128;
+ tpdu[1] |= (1 << 5); /* Set more bit. */
+ }
+ tpdu[2] = apdulen;
+ memcpy (tpdu+3, apdu, apdulen);
+ crc = 0;
+ for (i=0,p=tpdu; i < apdulen+3; i++)
+ crc ^= *p++;
+ tpdu[3+apdulen] = crc;
+
+ tpdulen = apdulen + 4;
+ }
- for (;;)
- {
msg[0] = PC_to_RDR_XfrBlock;
msg[5] = 0; /* slot */
msg[6] = seqno = handle->seqno++;
@@ -804,12 +827,14 @@ ccid_transceive (ccid_driver_t handle,
for (i=0; i < msglen; i++)
DEBUGOUT_CONT_1 (" %02X", msg[i]);
DEBUGOUT_LF ();
-
-/* fprintf (stderr, "T1: put %c-block seq=%d\n", */
-/* ((msg[11] & 0xc0) == 0x80)? 'R' : */
-/* (msg[11] & 0x80)? 'S' : 'I', */
-/* ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40))); */
-
+
+#ifdef DEBUG_T1
+ fprintf (stderr, "T1: put %c-block seq=%d\n",
+ ((msg[11] & 0xc0) == 0x80)? 'R' :
+ (msg[11] & 0x80)? 'S' : 'I',
+ ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)));
+#endif
+
rc = bulk_out (handle, msg, msglen);
if (rc)
return rc;
@@ -829,12 +854,14 @@ ccid_transceive (ccid_driver_t handle,
return -1;
}
-/* fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", */
-/* ((msg[11] & 0xc0) == 0x80)? 'R' : */
-/* (msg[11] & 0x80)? 'S' : 'I', */
-/* ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)), */
-/* ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0 */
-/* ); */
+#ifdef DEBUG_T1
+ fprintf (stderr, "T1: got %c-block seq=%d err=%d\n",
+ ((msg[11] & 0xc0) == 0x80)? 'R' :
+ (msg[11] & 0x80)? 'S' : 'I',
+ ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)),
+ ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0
+ );
+#endif
if (!(tpdu[1] & 0x80))
{ /* This is an I-block. */
@@ -899,9 +926,20 @@ ccid_transceive (ccid_driver_t handle,
{ /* Error: repeat last block */
msg = send_buffer;
}
+ else if (sending && !!(tpdu[1] & 0x40) == handle->t1_ns)
+ { /* Reponse does not match our sequence number. */
+ DEBUGOUT ("R-block with wrong seqno received on more bit\n");
+ return -1;
+ }
+ else if (sending)
+ { /* Send next chunk. */
+ msg = send_buffer;
+ next_chunk = 1;
+ handle->t1_ns ^= 1;
+ }
else
{
- DEBUGOUT ("unxpectec ACK R-block received\n");
+ DEBUGOUT ("unexpected ACK R-block received\n");
return -1;
}
}
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index 4e02cedc4..d61bd0125 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -34,6 +34,7 @@
#include "options.h"
#include "main.h"
#include "i18n.h"
+#include "cardglue.h"
static int get_it( PKT_pubkey_enc *k,
DEK *dek, PKT_secret_key *sk, u32 *keyid );
@@ -132,17 +133,51 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
static int
get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid )
{
- int rc;
- MPI plain_dek = NULL;
- byte *frame = NULL;
- unsigned n, nframe;
- u16 csum, csum2;
+ int rc;
+ MPI plain_dek = NULL;
+ byte *frame = NULL;
+ unsigned n, nframe;
+ u16 csum, csum2;
+
+ int card = 0;
- rc = pubkey_decrypt(sk->pubkey_algo, &plain_dek, enc->data, sk->skey );
- if( rc )
+ if (sk->is_protected && sk->protect.s2k.mode == 1002)
+ { /* Note, that we only support RSA for now. */
+#ifdef ENABLE_CARD_SUPPORT
+ unsigned char *rbuf;
+ size_t rbuflen;
+ char *snbuf;
+ unsigned char *indata = NULL;
+ unsigned int indatalen;
+
+ snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen, sk);
+
+ indata = mpi_get_buffer (enc->data[0], &indatalen, NULL);
+ if (!indata)
+ BUG ();
+
+ rc = agent_scd_pkdecrypt (snbuf, indata, indatalen, &rbuf, &rbuflen);
+ xfree (snbuf);
+ xfree (indata);
+ if (rc)
+ goto leave;
+
+ frame = rbuf;
+ nframe = rbuflen;
+ card = 1;
+#else
+ rc = G10ERR_UNSUPPORTED;
+ goto leave;
+#endif /*!ENABLE_CARD_SUPPORT*/
+ }
+ else
+ {
+ rc = pubkey_decrypt(sk->pubkey_algo, &plain_dek, enc->data, sk->skey );
+ if( rc )
goto leave;
- frame = mpi_get_buffer( plain_dek, &nframe, NULL );
- mpi_free( plain_dek ); plain_dek = NULL;
+ frame = mpi_get_buffer( plain_dek, &nframe, NULL );
+ mpi_free( plain_dek ); plain_dek = NULL;
+ }
/* Now get the DEK (data encryption key) from the frame
*
@@ -164,18 +199,22 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid )
if( DBG_CIPHER )
log_hexdump("DEK frame:", frame, nframe );
n=0;
- if( n + 7 > nframe )
- { rc = G10ERR_WRONG_SECKEY; goto leave; }
- if( frame[n] == 1 && frame[nframe-1] == 2 ) {
- log_info(_("old encoding of the DEK is not supported\n"));
- rc = G10ERR_CIPHER_ALGO;
- goto leave;
- }
- if( frame[n] != 2 ) /* somethink is wrong */
- { rc = G10ERR_WRONG_SECKEY; goto leave; }
- for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */
- ;
- n++; /* and the zero byte */
+ if (!card)
+ {
+ if( n + 7 > nframe )
+ { rc = G10ERR_WRONG_SECKEY; goto leave; }
+ if( frame[n] == 1 && frame[nframe-1] == 2 ) {
+ log_info(_("old encoding of the DEK is not supported\n"));
+ rc = G10ERR_CIPHER_ALGO;
+ goto leave;
+ }
+ if( frame[n] != 2 ) /* somethink is wrong */
+ { rc = G10ERR_WRONG_SECKEY; goto leave; }
+ for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */
+ ;
+ n++; /* and the zero byte */
+ }
+
if( n + 4 > nframe )
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
diff --git a/g10/sign.c b/g10/sign.c
index 9826c2abf..3bfe602b2 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -306,9 +306,9 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
sig->digest_algo = digest_algo;
sig->digest_start[0] = dp[0];
sig->digest_start[1] = dp[1];
-#ifdef ENABLE_CARD_SUPPORT
if (sk->is_protected && sk->protect.s2k.mode == 1002)
{
+#ifdef ENABLE_CARD_SUPPORT
unsigned char *rbuf;
size_t rbuflen;
char *snbuf;
@@ -327,9 +327,11 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
mpi_set_buffer (sig->data[0], rbuf, rbuflen, 0);
xfree (rbuf);
}
+#else
+ return G10ERR_UNSUPPORTED;
+#endif /* ENABLE_CARD_SUPPORT */
}
else
-#endif /* ENABLE_CARD_SUPPORT */
{
frame = encode_md_value( sk->pubkey_algo, md,
digest_algo, mpi_get_nbits(sk->skey[0]), 0 );