Thanks for the suggestions Sylvain. I've created a small patch that tries to allocate the extended buffer on RAM, but fallbacks to EEPROM memory if something should fail.

The extended APDU buffer size is 268 bytes to accommodate for the entire received APDU. Ideally this could be only 256 bytes for a 2048 bit key, but that implies more changes to the existing code and, at this time, I'm trying to make this code the least intrusive as possible.

I've compiled the applet, loaded it and can confirm that is working correctly with OpenSC on an Aladdin eToken 72K (engineering version).

According to (very non scientific tests), the running time of "pkcs11-tool --login --test" appears to be ~ 1.2 seconds faster using RAM vs EEPROM.

If you anyone can comment, I'll be grateful :)

Best regards,
Joao

"s.ferey" <[email protected]> wrote:

Joao Pedro a écrit :

This is a very good point.
I understand what you mean, and this was a major concern of mine. If I'm mistaken please correct me but, after looking at the rest of the code, this kind of "memory usage pattern" is used many times, at least in the ComputeCrypt() method.

my previous point ! there a lot of EEPROM uses in the applet that
shall be avoided!

based on a quick review, the ObjectManager & MemoryManager classes
are a very bad idea, now there are may be some reasons to use them
for instance to store some "session objects" that stay alive across
several APDU, so my last question regarding a specification that
explains how, why and when such 'semi-persistent' objects may exist
(or not).

Regarding the extended APDU buffer, maybe declaring it as transient would be a good alternative? This card, at least, has 8KB of RAM... I guess all new cards, that support extended APDU, should have plenty of RAM too... Your feedback here would be really great! :)

it could be a solution, it depends on use of the transient memory
by other applets, if one allocate a big transient reset buffer,
that memory won't be available for other applets.

it also depends on the actual need of memory, only some very specific
cryptographic functions may require to have "huge" data all available
at one time in a buffer, for instance if your card / applet supports
4096-bit signature in RAW mode, you need to store the 512-byte to be
signed, but I don't know a lot of card that supports 4096-bit keys.

the easier context to manage extended length functions is the checksum
or digest functions, you need to input a lot of data but you will return
a short amount of data. for instance for a digest process, you will use:
(one can write the loop according different rules).

short part = apdu.setIncomingAndReceive();
short length = apdu.getIncomingLength();
if (length == part)
   length = digest.doFinal(buffer, apdu.getOffsetCdata(),
         length, buffer, (short) 5);
else {
   digest.update(buffer, apdu.getOffsetCdata(), part);
   length -= part;
   for (;;){
      part = apdu.receiveBytes((short) 5);
      if (part == length){
         length = digest.doFinal(
            buffer, (short) 5, part, buffer, (short) 5);
         break;
      }
      else {
         digest.update(buffer, (short) 5, part);
         length -= part;
      }
   }
}
apdu.setOutgoingAndSend((short) 5, length);


regarding a "stream function" like encrypt or decrypt, you can not
start to return the ciphertext while you will continue to receive
the next plain text; something likes

for (;;){
  apdu.receiveBytes()
  cipher.update();
  apdu.sendBytes();
}
is of course invalid.

so you have no choice and must limit the amount of transmitted data
to fit the maximal length of APDU buffer or to use - as suggested -
a transient buffer; both options would require a "get card/applet
capabilities" function (a dedicated APDU) to let the terminal aware
of how many bytes it can send per APDU (and thus it obvioulsy means
a tailored middleware).

as an exemple, the Cosmo v.7 card I was dealing with has a transient
deselect buffer of 1536 bytes - and most of cards issued in 2007-2008
certainly offer at least 1024 bytes, so at least, you can encrypt /
decrypt by block of 1024 bytes (instead of 256) w/o any EEPROM writing.


More generic question, is there a specification that
describes the requierments for the CardEdge applet ?
(reverse understanding is still possible but paintful).

I did not understand your question. Could you please clarify?

well, as explained at the beginning some points are not that obvious
and easy to understand when one just looks at the source code of the
CardEdge applet; I beleive someone wrote a sort of specifications
before coding it this way and these functionality and behaviors,
the guys that had implemented by CardEgde middleware had certainly
used that guide to know wich APDU are supported, what are their
syntax, what kind of containers (tagged data object or binary files)
can be created and used, and so on. I'm looking for such document.

Sylvain.



--- CardEdge.src.orig	2009-05-29 09:27:57.000000000 +0100
+++ CardEdge.src	2009-05-29 10:21:07.000000000 +0100
@@ -71,8 +71,12 @@
 
 
 #ifdef WITH_EXT_APDU
-    // Maximum size for the extended APDU buffer
-    private final static short EXT_APDU_BUFFER_SIZE = (short) 512;
+    // Maximum size for the extended APDU buffer for a 2048 bit key:
+    // CLA [1 byte] + INS [1 byte] + P1 [1 byte] + P2 [1 byte] +
+    // LC [3 bytes] + cipher_mode[1 byte] + cipher_direction [1 byte] +
+    // data_location [1 byte] + data_size [2 bytes] + data [256 bytes]
+    // = 268 bytes
+    private final static short EXT_APDU_BUFFER_SIZE = (short) 268;
 #endif
     /* Pin policies constants (OR-ed in var pinPolicies) */
     /** Enable pin size check		*/
@@ -607,7 +611,16 @@
   	    Util.setShort(STD_PUBLIC_ACL, i, (short)0x0000);
 #ifdef WITH_EXT_APDU
 	// Initialize the extended APDU buffer
-	recvBuffer = new byte[EXT_APDU_BUFFER_SIZE];	
+	try {
+   	 // Try to allocate the extended APDU buffer on RAM memory
+	    recvBuffer = JCSystem.makeTransientByteArray((short)EXT_APDU_BUFFER_SIZE,
+                                               JCSystem.CLEAR_ON_DESELECT);
+	} catch (SystemException e) {
+	    // Allocate the extended APDU buffer on EEPROM memory
+	    // This is the fallback method, but its usage is really not recommended
+	    // as after ~ 100000 writes it will kill the EEPROM cells...
+	    recvBuffer = new byte[EXT_APDU_BUFFER_SIZE];
+	}	
 #endif
 
 	setupDone = true;
_______________________________________________
Muscle mailing list
[email protected]
http://lists.drizzle.com/mailman/listinfo/muscle

Reply via email to