📜 ⬆️ ⬇️

Use Java smart cards to protect software. Chapter 4. We write the first applet

image

1. Introduction


In this series of articles we will discuss the use of Java smart cards (cheaper analog keys of electronic keys) to protect software. The cycle is divided into several chapters.

To read and understand the information from the articles you will need the following skills:

The purpose of the cycle is to acquaint the reader with Java maps (there is very little literature in Russian on their use). The cycle does not claim the status of "Guidelines for the development of software protection based on Java cards" or the title of "Handbook of Java cards."
')

The composition of the cycle:




1. Example applet


In fact, we will not write anything. I’ll just give here a terribly commented source test card applet. And then I will tell about some subtleties of implementation.

package test; //   import javacard.framework.APDU; import javacard.framework.Applet; import javacard.framework.ISO7816; import javacard.framework.ISOException; import javacard.framework.Util; import javacard.security.*; import javacardx.crypto.*; //  public class Test extends Applet { //   (CLA)    private static final byte CLA_TEST = (byte) 0x80; //      private static final byte INS_TESTSPEED = (byte) 0x20; //      private static final byte INS_TEST3DES = (byte) 0x30; //       private static byte[] enryptBuffer = new byte[120]; //   ,  . ,   // DES  CBC  private static Cipher cipher = Cipher.getInstance(Cipher.ALG_DES_CBC_NOPAD, false); //   ,      3DES3. private static DESKey key = (DESKey) KeyBuilder.buildKey( KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_3KEY, false); //      3DES3 private static byte[] keyarr = new byte[24]; //  .         protected Test() { //      0xAA Util.arrayFillNonAtomic(enryptBuffer, (short) 0, (short) enryptBuffer.length, (byte) 0xAA); //    0xBB Util.arrayFillNonAtomic(keyarr, (short) 0, (short) keyarr.length, (byte) 0xBB); //      keyarr    //  key.setKey(keyarr, (short) 0); } // ,   . public static void install(byte bArray[], short bOffset, byte bLength) throws ISOException { new Test().register(); } // ,        public void process(APDU apdu) throws ISOException { //        byte buffer[] = apdu.getBuffer(); //     - SELECT,   // CardManager if ((buffer[ISO7816.OFFSET_CLA] == 0x00) && (buffer[ISO7816.OFFSET_INS] == (byte) (0xA4))) return; //  CLA    -   if (buffer[ISO7816.OFFSET_CLA] != CLA_TEST) { ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED); } // ,         //   switch (buffer[ISO7816.OFFSET_INS]) { case INS_TEST3DES: processTest3DES(apdu); case INS_TESTSPEED: processTestSpeed(apdu); default: //     INS    ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); } } // ,       private void processTestSpeed(APDU apdu) { //     byte[] buffer = apdu.getBuffer(); //     for (byte i = 0; i < 120; i++) { buffer[i] = i; } //  Java ,      process   //    //         0   120 // . //  ,       process. //     apdu.setOutgoingAndSend((short) 0, (short) 120); } private void processTest3DES(APDU apdu) { //     byte[] buffer = apdu.getBuffer(); //   enryptBuffer,    buffer cipher.doFinal(this.enryptBuffer, (short) 0, (short) this.enryptBuffer.length, buffer, (short) 0); //     apdu.setOutgoingAndSend((short) 0, (short) this.enryptBuffer.length); } } 


2. Some subtleties


The applet class constructor is called only once - when the applet is loaded into the map and installed.

The first thing you need to know about when developing your applet is whether the implementation of the Java Card API on the garbage collector supports the card. If the garbage collector is not supported, then any object created with the new operator will remain in the memory card forever. It will be impossible to destroy it and free the occupied memory (except by removing the applet from the card).

One simple conclusion follows from this: if your card does not support garbage collection, all new operators must be located inside the applet class constructor (inside a method, with a name like that of the class itself). Outside of this method, new operators will not be used. If you break this rule, after some time when executing commands, the applet will start to “spit” with errors and it will have to be overwritten.

But even if the garbage collector is supported by a map, it most likely will not work automatically. It will need to be called in the applet manually. And this is quite a long process, leading to fragmentation of the memory card.

The second point is the fragmentation of the memory card when managing applets. The applet in the memory card is that file on the hard disk. If you delete an applet recorded before any other, a “hole” of free space the size of the deleted applet will remain in the memory card. Therefore, you need to follow simple rules:


The same goes for dynamic memory allocation on maps supporting garbage collection. Although the collector destroys unused objects, it may not defragment the memory, since in the case of an EEPROM card this is a very long process.

The implementation of the Java language for maps does not support at least:

Moreover, the lack of support for the int type leads to a rather ridiculous format for calling methods: apdu.setOutgoingAndSend ((short) 0, (short) 120) since in Java, numeric literals are the default int.

Errors in the writing of the applet can appear on each of the three levels: compilation (* .java -> * .class), conversion (* .class -> * .cap), linking the applet in the map (* .cap -> map). Be careful. You can write a huge applet, compile and convert, and then discover that it is not flooded on the map for some reason. Since with the debugging of applets, everything is difficult in this case, you can advise commenting on parts of the applet and pouring it into the card until you stumble upon a part that caused an error.

Some cards have a verifier (for example, CodeShield on the latest installments of Schlumberger / Gemalto egate). This verifier additionally checks the applet's code after loading it into the card at the installation stage (a characteristic sign of its presence — a long pause before receiving a response to the last download command — can reach a full minute), creating additional hemorrhoids. For example, this verifier may require the presence of a break in each case of the switch statement, preventing the two cases from being grouped into one.

All members of the applet class are stored in the EEPROM card. The number of rewriting cycles of this memory, although large (several hundred thousand cycles), is still limited. The cards have a certain amount of RAM that can be allocated by calling Util.makeTransientArray (as the name implies, memory is allocated as an array and this allocation is also available on cards without garbage collection. The memory allocated by makeTransientArray is in all cases correctly released (see documentation )). Usually about 1Kb. Of course, working with this memory is faster than with an EEPROM.

To imagine the possibilities that are available to the applet, I suggest simply browsing through the documentation included in the Javacard SDK.

3. Gratitude to patient readers.


Thanks to everyone who read to this place. Gratitude and indignation are accepted.

I will welcome any questions in the comments and try to update the article so that it includes the answers.

Source: https://habr.com/ru/post/255535/


All Articles