Search code examples
smartcardjavacardecdsa

Get the reason of CryptoException in JavaCard


I am trying to implement ECDSA in JavaCard (Eclipse 4.4.2, JC 2.2.1). My card is a Gemalto IDCore 3010, or at least it is supposed to be (after checking the ATR code it looks like, that it is a WM GX4 72 DHS TSA...).

Anyway, if I don't surround the objECDSAKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_192) line with try and catch I get an unknown error (send_APDU() returns 0x80206F00 (Unknown ISO7816 error: 0x6F00)), but when I do surround it, it returns no error (send_APDU() returns 0x80209000 (9000: Success. No error.)). However it must go to the catch block because the other three lines in the try block don't get executed.

How can I visualize the error message? If I go with ISOException.throwIt(reason), I get Communication error with the intelligent card. Please try it again. multiple times.

In this thread it suggests the byte reason = c.getReason() code, but it won't work, not even if I cast the right side to byte.

Thank you!

Here is the relevant part of my code.

public class ECDSATestApplet extends Applet {

    private final static byte CLS = (byte) 0xE0;
    private final static byte NOOP = (byte) 0x00;
    private final static byte GEN = (byte) 0x01;

    ...

    private final static byte[] HELLO_WORLD = new byte[] { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!' };

    private ECPrivateKey objECDSAPriKey = null;
    private ECPublicKey objECDSAPubKey = null;
    private KeyPair objECDSAKeyPair = null;
    private Signature objECDSASign = null;

    final static short BAS = 0;

    private ECDSATestApplet() {
    }

    public static void install(byte[] bArray, short bOffset, byte bLength) {
        new ECDSATestApplet().register();
    }

    public void process(APDU apdu) {
        if (this.selectingApplet())
            return;

        byte buffer[] = apdu.getBuffer();

        if (buffer[ISO7816.OFFSET_CLA] != CLS)
            ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);

        switch (buffer[ISO7816.OFFSET_INS]) {
        case NOOP:
            break;

        case GEN:
            try {
                // ------- ERROR LINE -------
                objECDSAKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_192);
//              objECDSASign = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
//              objECDSAKeyPair.genKeyPair();
//              objECDSAPriKey = (ECPrivateKey) objECDSAKeyPair.getPrivate();
//              objECDSAPubKey = (ECPublicKey) objECDSAKeyPair.getPublic();
                apdu.setIncomingAndReceive();
                Util.arrayCopyNonAtomic(HELLO_WORLD, (short) 0, buffer, (short) 0, (short) HELLO_WORLD.length);
                apdu.setOutgoingAndSend((short) 0, (short) HELLO_WORLD.length);
            } catch (CryptoException c) {
                short reason = c.getReason();
//              ISOException.throwIt(reason);
            }

            break;
        }
        return;
    }
}

Solution

  • There are two possible reasons of your troubles:

    1. Your status word does not follow status words recommended by ISO7816. Try

      ISOException.throwIt((short) ((short) (0x9C00) | reason));
      

      instead of

      ISOException.throwIt(reason);
      
    2. You forgot to set parameters of your elliptic curve before generating a new key pair. You should generate your EC key pair this way:

      KeyPair keyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_192);
      ECPrivateKey privKey = (ECPrivateKey) keyPair.getPrivate();
      ECPublicKey pubKey = (ECPublicKey) keyPair.getPublic();
      initDomainParams(pubKey);
      initDomainParams(privKey);
      keyPair.genKeyPair();
      

      where

      private void initDomainParams(ECKey key) {
          key.setFieldFP(F, (short)0, (short)F.length);
          key.setA(A, (short)0, (short)A.length);
          key.setB(B, (short)0, (short)B.length);
          key.setG(G, (short)0, (short)G.length);
          key.setR(R, (short)0, (short)R.length);
      }
      

      with F, A, B, G, R parameters of the elliptic curve you have chosen for your signature. See the list of recommended curves here: http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf