* ccid-driver.c (ccid_transceive): Add T=1 chaining for sending.
authorWerner Koch <wk@gnupg.org>
Thu, 9 Oct 2003 15:08:12 +0000 (15:08 +0000)
committerWerner Koch <wk@gnupg.org>
Thu, 9 Oct 2003 15:08:12 +0000 (15:08 +0000)
* 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

g10/ChangeLog
g10/cardglue.c
g10/cardglue.h
g10/ccid-driver.c
g10/pubkey-enc.c
g10/sign.c

index 23f5db5..324b96e 100644 (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>
 
        * cardglue.c (pin_cb): Detect whether an admin or regular PIN is
index fd7cf8b..91637a7 100644 (file)
@@ -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. */
index 273b993..fcd3726 100644 (file)
@@ -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);
index b4fbc0b..35f0329 100644 (file)
 #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;
             }
         }
index 4e02ced..d61bd01 100644 (file)
@@ -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; }
 
index 9826c2a..3bfe602 100644 (file)
@@ -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 );