* 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
This commit is contained in:
Werner Koch 2003-10-09 15:08:12 +00:00
parent 72c648c035
commit f633ef17dc
6 changed files with 160 additions and 59 deletions

View File

@ -1,3 +1,14 @@
2003-10-09 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org> 2003-10-08 Werner Koch <wk@gnupg.org>
* cardglue.c (pin_cb): Detect whether an admin or regular PIN is * cardglue.c (pin_cb): Detect whether an admin or regular PIN is

View File

@ -631,10 +631,21 @@ agent_scd_pksign (const char *serialno, int hashalgo,
int int
agent_scd_pkdecrypt (const char *serialno, agent_scd_pkdecrypt (const char *serialno,
const unsigned char *indata, size_t indatalen, 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. */ /* Change the PIN of an OpenPGP card or reset the retry counter. */

View File

@ -151,7 +151,7 @@ int agent_scd_pksign (const char *keyid, int hashalgo,
/* Send a PKDECRYPT command to the SCdaemon. */ /* Send a PKDECRYPT command to the SCdaemon. */
int agent_scd_pkdecrypt (const char *serialno, int agent_scd_pkdecrypt (const char *serialno,
const unsigned char *indata, size_t indatalen, 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. */ /* Change the PIN of an OpenPGP card or reset the retry counter. */
int agent_scd_change_pin (int chvno); int agent_scd_change_pin (int chvno);

View File

@ -132,6 +132,11 @@
#endif /* This source not used by scdaemon. */ #endif /* This source not used by scdaemon. */
/* Define to print information pertaining the T=1 protocol. */
#undef DEBUG_T1 1
enum { enum {
RDR_to_PC_NotifySlotChange= 0x50, RDR_to_PC_NotifySlotChange= 0x50,
RDR_to_PC_HardwareError = 0x51, RDR_to_PC_HardwareError = 0x51,
@ -566,7 +571,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
return -1; 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] ); " data:", buffer[7], buffer[8], buffer[9] );
for (i=10; i < msglen; i++) for (i=10; i < msglen; i++)
DEBUGOUT_CONT_1 (" %02X", buffer[i]); DEBUGOUT_CONT_1 (" %02X", buffer[i]);
@ -753,44 +758,62 @@ ccid_get_atr (ccid_driver_t handle,
int int
ccid_transceive (ccid_driver_t handle, 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) unsigned char *resp, size_t maxresplen, size_t *nresp)
{ {
int rc; int rc;
unsigned char send_buffer[10+258], recv_buffer[10+258]; unsigned char send_buffer[10+258], recv_buffer[10+258];
const unsigned char *apdu;
size_t apdulen;
unsigned char *msg, *tpdu, *p; unsigned char *msg, *tpdu, *p;
size_t msglen, tpdulen, n; size_t msglen, tpdulen, n;
unsigned char seqno; unsigned char seqno;
int i; int i;
unsigned char crc; unsigned char crc;
size_t dummy_nresp; size_t dummy_nresp;
int next_chunk = 1;
int sending = 1; int sending = 1;
if (!nresp) if (!nresp)
nresp = &dummy_nresp; nresp = &dummy_nresp;
*nresp = 0; *nresp = 0;
/* Construct an I-Block. */
if (apdulen > 254)
return -1; /* Invalid length. */
tpdulen = 0; /* Avoid compiler warning about no initialization. */
msg = send_buffer; msg = send_buffer;
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;
tpdulen = apdulen + 4;
for (;;) for (;;)
{ {
if (next_chunk)
{
next_chunk = 0;
apdu = apdu_buf;
apdulen = apdu_buflen;
assert (apdulen);
/* 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;
}
msg[0] = PC_to_RDR_XfrBlock; msg[0] = PC_to_RDR_XfrBlock;
msg[5] = 0; /* slot */ msg[5] = 0; /* slot */
msg[6] = seqno = handle->seqno++; msg[6] = seqno = handle->seqno++;
@ -804,12 +827,14 @@ ccid_transceive (ccid_driver_t handle,
for (i=0; i < msglen; i++) for (i=0; i < msglen; i++)
DEBUGOUT_CONT_1 (" %02X", msg[i]); DEBUGOUT_CONT_1 (" %02X", msg[i]);
DEBUGOUT_LF (); DEBUGOUT_LF ();
/* fprintf (stderr, "T1: put %c-block seq=%d\n", */ #ifdef DEBUG_T1
/* ((msg[11] & 0xc0) == 0x80)? 'R' : */ fprintf (stderr, "T1: put %c-block seq=%d\n",
/* (msg[11] & 0x80)? 'S' : 'I', */ ((msg[11] & 0xc0) == 0x80)? 'R' :
/* ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40))); */ (msg[11] & 0x80)? 'S' : 'I',
((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)));
#endif
rc = bulk_out (handle, msg, msglen); rc = bulk_out (handle, msg, msglen);
if (rc) if (rc)
return rc; return rc;
@ -829,12 +854,14 @@ ccid_transceive (ccid_driver_t handle,
return -1; return -1;
} }
/* fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", */ #ifdef DEBUG_T1
/* ((msg[11] & 0xc0) == 0x80)? 'R' : */ fprintf (stderr, "T1: got %c-block seq=%d err=%d\n",
/* (msg[11] & 0x80)? 'S' : 'I', */ ((msg[11] & 0xc0) == 0x80)? 'R' :
/* ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)), */ (msg[11] & 0x80)? 'S' : 'I',
/* ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0 */ ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)),
/* ); */ ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0
);
#endif
if (!(tpdu[1] & 0x80)) if (!(tpdu[1] & 0x80))
{ /* This is an I-block. */ { /* This is an I-block. */
@ -899,9 +926,20 @@ ccid_transceive (ccid_driver_t handle,
{ /* Error: repeat last block */ { /* Error: repeat last block */
msg = send_buffer; 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 else
{ {
DEBUGOUT ("unxpectec ACK R-block received\n"); DEBUGOUT ("unexpected ACK R-block received\n");
return -1; return -1;
} }
} }

View File

@ -34,6 +34,7 @@
#include "options.h" #include "options.h"
#include "main.h" #include "main.h"
#include "i18n.h" #include "i18n.h"
#include "cardglue.h"
static int get_it( PKT_pubkey_enc *k, static int get_it( PKT_pubkey_enc *k,
DEK *dek, PKT_secret_key *sk, u32 *keyid ); DEK *dek, PKT_secret_key *sk, u32 *keyid );
@ -132,17 +133,51 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
static int static int
get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid )
{ {
int rc; int rc;
MPI plain_dek = NULL; MPI plain_dek = NULL;
byte *frame = NULL; byte *frame = NULL;
unsigned n, nframe; unsigned n, nframe;
u16 csum, csum2; u16 csum, csum2;
int card = 0;
rc = pubkey_decrypt(sk->pubkey_algo, &plain_dek, enc->data, sk->skey ); if (sk->is_protected && sk->protect.s2k.mode == 1002)
if( rc ) { /* 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; goto leave;
frame = mpi_get_buffer( plain_dek, &nframe, NULL ); frame = mpi_get_buffer( plain_dek, &nframe, NULL );
mpi_free( plain_dek ); plain_dek = NULL; mpi_free( plain_dek ); plain_dek = NULL;
}
/* Now get the DEK (data encryption key) from the frame /* 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 ) if( DBG_CIPHER )
log_hexdump("DEK frame:", frame, nframe ); log_hexdump("DEK frame:", frame, nframe );
n=0; n=0;
if( n + 7 > nframe ) if (!card)
{ rc = G10ERR_WRONG_SECKEY; goto leave; } {
if( frame[n] == 1 && frame[nframe-1] == 2 ) { if( n + 7 > nframe )
log_info(_("old encoding of the DEK is not supported\n")); { rc = G10ERR_WRONG_SECKEY; goto leave; }
rc = G10ERR_CIPHER_ALGO; if( frame[n] == 1 && frame[nframe-1] == 2 ) {
goto leave; log_info(_("old encoding of the DEK is not supported\n"));
} rc = G10ERR_CIPHER_ALGO;
if( frame[n] != 2 ) /* somethink is wrong */ goto leave;
{ rc = G10ERR_WRONG_SECKEY; goto leave; } }
for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */ if( frame[n] != 2 ) /* somethink is wrong */
; { rc = G10ERR_WRONG_SECKEY; goto leave; }
n++; /* and the zero byte */ for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */
;
n++; /* and the zero byte */
}
if( n + 4 > nframe ) if( n + 4 > nframe )
{ rc = G10ERR_WRONG_SECKEY; goto leave; } { rc = G10ERR_WRONG_SECKEY; goto leave; }

View File

@ -306,9 +306,9 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
sig->digest_algo = digest_algo; sig->digest_algo = digest_algo;
sig->digest_start[0] = dp[0]; sig->digest_start[0] = dp[0];
sig->digest_start[1] = dp[1]; sig->digest_start[1] = dp[1];
#ifdef ENABLE_CARD_SUPPORT
if (sk->is_protected && sk->protect.s2k.mode == 1002) if (sk->is_protected && sk->protect.s2k.mode == 1002)
{ {
#ifdef ENABLE_CARD_SUPPORT
unsigned char *rbuf; unsigned char *rbuf;
size_t rbuflen; size_t rbuflen;
char *snbuf; char *snbuf;
@ -327,9 +327,11 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
mpi_set_buffer (sig->data[0], rbuf, rbuflen, 0); mpi_set_buffer (sig->data[0], rbuf, rbuflen, 0);
xfree (rbuf); xfree (rbuf);
} }
#else
return G10ERR_UNSUPPORTED;
#endif /* ENABLE_CARD_SUPPORT */
} }
else else
#endif /* ENABLE_CARD_SUPPORT */
{ {
frame = encode_md_value( sk->pubkey_algo, md, frame = encode_md_value( sk->pubkey_algo, md,
digest_algo, mpi_get_nbits(sk->skey[0]), 0 ); digest_algo, mpi_get_nbits(sk->skey[0]), 0 );