ccid_driver_improvement

NIIBE Yutaka gniibe at fsij.org
Wed Dec 21 03:10:56 CET 2011


On 2011-12-20 at 12:51 +0900, NIIBE Yutaka wrote:
> commit 37fadead90e985b544c9f817cf7c7b0ada797d3c

Let me explain this commit a bit.

Note that this is not the patch to fully support extended APDU
exchange level communication, but to support most of cases.

I think that full support requires to have 64KiB buffer, but for
almost all cases for OpenPGP card interaction (I mean, Gnuk), it
doesn't require such a big buffer.

The maximum case is for handling of Data Object of 0x7f21 ("CERT-3"),
This commit doesn't handle this case.  I will write another mail about
Data Object of 0x7f21 ("CERT-3").

Next maximum case is to store key from host to card.  The magic number
289 comes from for 2048-bit key:

	7 (header of CCID message)
	+ 22  (Extended header list, kind of key, private key template, tag)
	+ 4   (E : 00 01 00 01)
	+ 128 (P)
	+ 128 (Q)

Besides, the commit supports packets in a chain.

With these changes, OpenPGP card v2 with extended APDU exchange level
communication (== Gnuk) works well (except DO 0x7f21).

I paste output of "git show 37fadead90e985b544c9f817cf7c7b0ada797d3c"
to ask your review and comment.

commit 37fadead90e985b544c9f817cf7c7b0ada797d3c
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Mon Dec 5 12:00:14 2011 +0900

    Support extended APDU exchange level somehow.
    
    * ccid-driver.c (ccid_transceive_apdu_level): Permit sending packet
    where apdulen <= 289.  Support receiving packets in a chain.

diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index 7338ccc..5755b07 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -2590,8 +2590,8 @@ ccid_transceive_apdu_level (ccid_driver_t handle,
 
   /* The maximum length for a short APDU T=1 block is 261.  For an
      extended APDU T=1 block the maximum length 65544; however
-     extended APDU exchange level is not yet supported.  */
-  if (apdulen > 261)
+     extended APDU exchange level is not fully supported yet.  */
+  if (apdulen > 289)
     return CCID_DRIVER_ERR_INV_VALUE; /* Invalid length. */
 
   msg[0] = PC_to_RDR_XfrBlock;
@@ -2614,8 +2614,51 @@ ccid_transceive_apdu_level (ccid_driver_t handle,
   if (rc)
     return rc;
 
-  apdu = msg + 10;
-  apdulen = msglen - 10;
+  if (msg[9] == 1)
+    {
+      size_t total_msglen = msglen;
+
+      while (1)
+        {
+          unsigned char status;
+
+          msg = recv_buffer + total_msglen;
+
+          msg[0] = PC_to_RDR_XfrBlock;
+          msg[5] = 0; /* slot */
+          msg[6] = seqno = handle->seqno++;
+          msg[7] = bwi; /* bBWI */
+          msg[8] = 0x10;                /* Request next data block */
+          msg[9] = 0;
+          set_msg_len (msg, 0);
+          msglen = 10;
+
+          rc = bulk_out (handle, msg, msglen, 0);
+          if (rc)
+            return rc;
+
+          rc = bulk_in (handle, msg, sizeof recv_buffer - total_msglen, &msglen,
+                        RDR_to_PC_DataBlock, seqno, 5000, 0);
+          if (rc)
+            return rc;
+          status = msg[9];
+          memmove (msg, msg+10, msglen - 10);
+          total_msglen += msglen - 10;
+          if (total_msglen >= sizeof recv_buffer)
+            return CCID_DRIVER_ERR_OUT_OF_CORE;
+
+          if (status == 0x02)
+            break;
+        }
+
+      apdu = recv_buffer + 10;
+      apdulen = total_msglen - 10;
+    }
+  else
+    {
+      apdu = msg + 10;
+      apdulen = msglen - 10;
+    }
 
   if (resp)
     {
-- 





More information about the Gnupg-devel mailing list