AESKey LinkedList/Array in Java Card

Deadly 提交于 2019-12-11 10:56:23

问题


This post is related to a question I asked a few days ago: Store symmetric keys in Java Card

I want to implement LinkedList in Java Card to store AESKey. So I wrote a class KeyElement this way:

package LinkedList;

import javacard.security.AESKey;
import javacard.security.KeyBuilder;


class KeyElement {
    private KeyElement next;
    private short id;
    private AESKey key;
    private boolean isUsed;

    /**
     * Constructor.
     * 
     * @param upperBound
     *            An upper bound to indicate of many elements it cans contain at
     *            maximum. It is essential to instanciate the structure this way
     *            to reserve all the necessary memory at the installation time.
     */
    public KeyElement(short upperBound) {
       this.id = (short) 0x0000;
       this.key = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES,
           KeyBuilder.LENGTH_AES_256, false);
       this.isUsed = false;
       this.next = null;
       for (short i = (short) 0x0001; i < upperBound; i++) {
           KeyElement e = new KeyElement();
           this.addKeyElement(e);
       }
    }

    public KeyElement() {
       this.id = (short) 0x0000;
       this.key = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES,
           KeyBuilder.LENGTH_AES_256, false);
       this.isUsed = false;
       this.next = null;
    }

    public KeyElement getNext() {
       return this.next;
    }

    public short getID() {
       return this.id;
    }

    public boolean isUsed() {
       return isUsed;
    }

    public void setNext(KeyElement e) {
       this.next = e;
    }

    public static boolean addKey(KeyElement main, final short id, byte[] key) {
       for (KeyElement p = main; p != null; p = p.getNext()) {
            if (!p.isUsed()) {
              p.isUsed = true;
              p.id = id;
              p.key.setKey(key, (short) 0x0000);
              return true;
           }
       }
       return false;
    }



    public void addKeyElement(KeyElement e) {
       e.setNext(this.getNext());
       this.setNext(e);
    }


    public static boolean getKey(final KeyElement e, final short id,
        byte[] key) {
       for (KeyElement p = e; p != null; p = p.getNext()) {
           if (p.id == id) {
              p.key.getKey(key, (short) 0x0000);
              return true;
           }
       }
       return false;
    }
}

And I have an applet LinkedListKey which uses the class KeyElement described before.

package LinkedList;

import javacard.framework.APDU;
import javacard.framework.APDUException;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.PINException;
import javacard.framework.SystemException;
import javacard.framework.TransactionException;
import javacard.framework.Util;
import javacard.framework.service.ServiceException;
import javacard.security.CryptoException;
import javacard.security.RandomData;

public class LinkedListKey extends Applet {

    byte[] rdm;
    RandomData rand;
    KeyElement e;

    private LinkedListKey(final byte[] aidArray, final short aidOffset,
        final byte aidLength, final byte[] dataArray, short dataOffset,
        final short dataLength) throws ISOException {

       e = new KeyElement((short) 0x0064);

       rdm = new byte[(short) 0x0020];

       KeyElement.addKey(e, (short) 0x7514, new byte[] { (byte) 0x75, (byte) 0x14,
        (byte) 0x75, (byte) 0x14, (byte) 0x75, (byte) 0x14,
        (byte) 0x75, (byte) 0x14, (byte) 0x14, (byte) 0x14,
        (byte) 0x75, (byte) 0x14, (byte) 0x75, (byte) 0x14,
        (byte) 0x75, (byte) 0x14, (byte) 0x75, (byte) 0x14,
        (byte) 0x75, (byte) 0x14, (byte) 0x14, (byte) 0x14,
        (byte) 0x75, (byte) 0x14, (byte) 0x75, (byte) 0x14,
        (byte) 0x75, (byte) 0x14, (byte) 0x75, (byte) 0x14,
        (byte) 0x75, (byte) 0x14 });

       register();
    }

    public static void install(final byte[] buffer, short offset,
        final byte length) throws ISOException {
       if (length == 0) {
          ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
       }

       short remainingBytes = makeShort(length);

       // Save instance AID.
       byte aidLength = buffer[offset++];
       short aidOffset = offset;

       // Skip instance AID.
       offset += makeShort(aidLength);

       remainingBytes--;
       remainingBytes -= makeShort(aidLength);

       if (remainingBytes <= (short) 0x0000) {
           ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
       }

       // Skip control data.
       byte infoLength = buffer[offset++];

       offset += makeShort(infoLength);

       remainingBytes--;
       remainingBytes -= makeShort(infoLength);

       if (remainingBytes <= (short) 0x0000) {
           ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
       }

       // Instantiate the application.
       // The length of the application data maybe greater than 127 bytes.
       short dataLength = makeShort(buffer[offset++]);

       remainingBytes--;

       if (remainingBytes != dataLength) {
           ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
       }

       new LinkedListKey(buffer, aidOffset, aidLength, buffer, offset,
           dataLength);
    }

    public void process(final APDU apdu) throws ISOException {
       byte[] apduBuffer = apdu.getBuffer();

       if (selectingApplet()) {
           apdu.setOutgoingAndSend((short) 0x0000, (short) 0x0019);

           return;
        }

    // Send result.
    try {
        if (apduBuffer[ISO7816.OFFSET_INS] == (byte) 0x00) {
           for (short i = 0x0000; i < (short) 0x0008; i++) {
               rand.generateData(rdm, (short) 0x0000, (short) rdm.length);
               KeyElement.addKey(e, i, rdm);
           }
           KeyElement.addKey(e, (short) 0x7503, new byte[] { (byte) 0x75, (byte) 0x03,
            (byte) 0x75, (byte) 0x03, (byte) 0x75, (byte) 0x03,
            (byte) 0x75, (byte) 0x03, (byte) 0x14, (byte) 0x03,
            (byte) 0x75, (byte) 0x03, (byte) 0x75, (byte) 0x03,
            (byte) 0x75, (byte) 0x03, (byte) 0x75, (byte) 0x03,
            (byte) 0x75, (byte) 0x03, (byte) 0x14, (byte) 0x03,
            (byte) 0x75, (byte) 0x03, (byte) 0x75, (byte) 0x03,
            (byte) 0x75, (byte) 0x03, (byte) 0x75, (byte) 0x03,
            (byte) 0x75, (byte) 0x03 });
        }
        else if (apduBuffer[ISO7816.OFFSET_INS] == (byte) 0x01){
           KeyElement.getKey(e, (short) 0x7503, apduBuffer);
           setOutgoingAndSend((short) 0x0000, (short) 0x0020);
        }
        else {
           KeyElement.getKey(e, (short) 0x7514, apduBuffer);
           setOutgoingAndSend((short) 0x0000, (short) 0x0020);
        }
    } catch (ArithmeticException e) {
        ISOException.throwIt((short) 0x0100);
    } catch (ArrayStoreException e) {
        ISOException.throwIt((short) 0x0200);
    } catch (APDUException e) {
        ISOException.throwIt(Util.makeShort((byte) 0x03,
            (byte) e.getReason()));
    } catch (CryptoException e) {
        ISOException.throwIt(Util.makeShort((byte) 0x04,
            (byte) e.getReason()));
    } catch (ISOException e) {
        ISOException.throwIt(Util.makeShort((byte) 0x05,
            (byte) e.getReason()));
    } catch (PINException e) {
        ISOException.throwIt(Util.makeShort((byte) 0x06,
            (byte) e.getReason()));
    } catch (ServiceException e) {
        ISOException.throwIt(Util.makeShort((byte) 0x07,
            (byte) e.getReason()));
    } catch (SystemException e) {
        ISOException.throwIt(Util.makeShort((byte) 0x08,
            (byte) e.getReason()));
    } catch (TransactionException e) {
        ISOException.throwIt(Util.makeShort((byte) 0x09,
            (byte) e.getReason()));
    } catch (ClassCastException e) {
        ISOException.throwIt((short) 0x0A00);
    } catch (IndexOutOfBoundsException e) {
        ISOException.throwIt((short) 0x0B00);
    } catch (NegativeArraySizeException e) {
        ISOException.throwIt((short) 0x0C00);
    } catch (NullPointerException e) {
        ISOException.throwIt((short) 0x0D00);
    } catch (SecurityException e) {
        ISOException.throwIt((short) 0x0E00);
    } catch (RuntimeException e) {
    }
 }


    static private short makeShort(final byte value) {
    return Util.makeShort((byte) 0x00, value);
    }

    private void setOutgoingAndSend(final short dataOffset, short dataLength) throws ISOException {
    APDU.getCurrentAPDU().setOutgoingAndSend(dataOffset, dataLength);
    }
}

So I wrote if/else conditions to bench how many time it takes to:

  • Fill the list (INS = 0x00)
  • get the last element of the list (when INS = 0x01)
  • get the first element of the list (when INS = 0x02)

So with the code given above, I can install my applet on a Java Card without problems.

But when I run my applet, I get an exception 0x0D00 which makes reference to a NullPointerException.

So, what? Do I have to conclude that my KeyElement object instanciation failed? But, as it's made at the installation time, I thought it should return me an error during the installation but it didn't.

More precisely it fails at step:

// Send result.
 try {
   if (apduBuffer[ISO7816.OFFSET_INS] == (byte) 0x00) {
      for (short i = 0x0000; i < (short) 0x0008; i++) {
         rand.generateData(rdm, (short) 0x0000, (short) rdm.length);
         KeyElement.addKey(e, i, rdm);
      }
...

And more precisely at KeyElement.addKey(e, i, rdm); that's why it seems that e raises the NullPointerException even the installation was sucessfull...


回答1:


You have not create the instance of rand, which generates the NullPointerException. You need to use:

RandomData.getInstance(byte algorithm) 

with algorithm

public static final byte    ALG_PSEUDO_RANDOM   1
public static final byte    ALG_SECURE_RANDOM   2



回答2:


I didn't browse through all the code in detail because you didn't really get the point of a linked list regarding

public KeyElement(short upperBound)

Have a look at some sample Java Linked List implementations and be safe towards EERPOM consumption by either catching exception or checking the remaining space before allocation



来源:https://stackoverflow.com/questions/32698283/aeskey-linkedlist-array-in-java-card

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!