3

I want to implement ECDSA algorithm on Java Card (JCOP 2.4.2). This is my source code:

package hashPack;

import javacard.framework.*;
import javacard.security.*;
import javacardx.crypto.*;

public class MyECDSA extends Applet{

    private byte[] PLAINTEXT ;

    private ECPrivateKey            objECDSAPriKey=null;    // Object for ECDSA Private Key
    private ECPublicKey             objECDSAPubKey=null;    // Object for ECDSA Public Key
    private KeyPair                 objECDSAKeyPair=null;   // Object for ECDSA Key Pair
    private Signature               objECDSASign=null;      // Object for ECDSA Signature

    final static short  BAS     =  0;

    final static byte[] SecP192r1_P = {     // 24
        (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
        (byte)0xFE,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
        (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
    final static byte[] SecP192r1_A = {     // 24
        (byte)0xFC,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
        (byte)0xFE,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
        (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
    final static byte[] SecP192r1_B = {     // 24
      (byte)0xB1,(byte)0xB9,(byte)0x46,(byte)0xC1,(byte)0xEC,(byte)0xDE,(byte)0xB8,(byte)0xFE,
      (byte)0x49,(byte)0x30,(byte)0x24,(byte)0x72,(byte)0xAB,(byte)0xE9,(byte)0xA7,(byte)0x0F,
      (byte)0xE7,(byte)0x80,(byte)0x9C,(byte)0xE5,(byte)0x19,(byte)0x05,(byte)0x21,(byte)0x64};
    final static byte[] SecP192r1_S = {     // 20
      (byte)0xD5,(byte)0x96,(byte)0x21,(byte)0xE1,(byte)0xEA,(byte)0x20,(byte)0x81,(byte)0xD3,
      (byte)0x28,(byte)0x95,(byte)0x57,(byte)0xED,(byte)0x64,(byte)0x2F,(byte)0x42,(byte)0xC8,
      (byte)0x6F,(byte)0xAE,(byte)0x45,(byte)0x30};
    final static byte[] SecP192r1_G = {     // 25
      (byte)0x12,(byte)0x10,(byte)0xFF,(byte)0x82,(byte)0xFD,(byte)0x0A,(byte)0xFF,(byte)0xF4,
      (byte)0x00,(byte)0x88,(byte)0xA1,(byte)0x43,(byte)0xEB,(byte)0x20,(byte)0xBF,(byte)0x7C,
      (byte)0xF6,(byte)0x90,(byte)0x30,(byte)0xB0,(byte)0x0E,(byte)0xA8,(byte)0x8D,(byte)0x18,(byte)0x03};
    final static byte[] SecP192r1_N = {     // 24
      (byte)0x31,(byte)0x28,(byte)0xD2,(byte)0xB4,(byte)0xB1,(byte)0xC9,(byte)0x6B,(byte)0x14,
      (byte)0x36,(byte)0xF8,(byte)0xDE,(byte)0x99,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
      (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
    final static short  SecP192r1_H =  1;

    //======================================================================================
    public static void install(byte[] bArray, short bOffset, byte bLength){
        new MyECDSA(bArray, bOffset, bLength);
    }

    private MyECDSA(byte bArray[], short bOffset, byte bLength){    

        PLAINTEXT       = new byte[0x100] ;         // Data file

        Util.arrayFillNonAtomic(PLAINTEXT,  BAS, (short)0x100, (byte)0);

        register();
    }

    //======================================================================================
    public void process(APDU apdu){
        byte buf[] = apdu.getBuffer();

        switch(buf[1])
        {
            //--------------------------------------------------------
            case (byte)0xA4:                    break;  

            case (byte)0x46:

                // Create ECDSA Keys and Pair
             /*   try {
            // <<<<<<<<<<<<<<<< Here is the problem >>>>>>>>>>>>>>>>>
                    objECDSAPriKey = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE,      KeyBuilder.LENGTH_EC_FP_192, true);
                }
            catch(CryptoException c)
            {    
              short reason = c.getReason();   
              ISOException.throwIt(reason);       // for check
            }     // for check*/
                   // objECDSAPubKey = (ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC,      KeyBuilder.LENGTH_EC_FP_192, true);

                    // set EC Domain Parameters
                    objECDSAPubKey.setFieldFP(SecP192r1_P, BAS, (short)24);
                    objECDSAPubKey.setA(SecP192r1_A, BAS, (short)24);
                    objECDSAPubKey.setB(SecP192r1_B, BAS, (short)24);
                    objECDSAPubKey.setG(SecP192r1_G, BAS, (short)25);
                    objECDSAPubKey.setK(SecP192r1_H);
                    objECDSAPubKey.setR(SecP192r1_N, BAS, (short)24);

                    objECDSAKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_192);


                // On-Card Key Generation Process
                objECDSAKeyPair.genKeyPair();

                // Obtain Key References
                objECDSAPriKey = (ECPrivateKey)objECDSAKeyPair.getPrivate();
                objECDSAPubKey = (ECPublicKey)objECDSAKeyPair.getPublic();  

                // Create Signature Object
                objECDSASign = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);

            break;

            case (byte)0x2E:                        
                short       Le              = apdu.setOutgoing();   
                short   sSignLen=0 ;

                // Init with Private Key
                objECDSASign.init(objECDSAPriKey, Signature.MODE_SIGN);

                // Sign Data
                sSignLen = objECDSASign.sign(PLAINTEXT, BAS, Le, buf, BAS);

                apdu.setOutgoingLength(sSignLen);
                apdu.sendBytes(BAS, sSignLen);

            break;      
            //--------------------------------------------------------
            default:
                ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }

        return; 
    }
}

I am running this source code using this script script code:

#/term SCComm:2
/mode trace=on
/atr
/card
/select |ecdsa
/send 00A4040007D4106509900090
/send 0046000000
/send 002E00000A30313233343031323334

When I am calling /send 0046000000 for signing the plain text message I get the response code 6F00.

Could you help me to find out what is wrong with this?

How to properly implement this algorithm on a JCOP card?

Michael Roland
  • 39,663
  • 10
  • 99
  • 206
  • From where you have chosen your ECC parameter,Please refer [NIST](http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf) for P-192 curve,Seems like your parameters are wrong.if you still not able to figure out please let me know. – Anurag Sharma Feb 15 '16 at 11:22
  • do not comment this line..." // objECDSAPubKey = (ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_192, true);" otherwise it will be always null and you will keep getting 0x6F00. – Anurag Sharma Feb 15 '16 at 11:42
  • Is there anything missing from the answers given, priyanka? If not, could you select and accept one as the question stays open otherwise. You can accept by clicking a V mark to the left of the answer. – Maarten Bodewes Feb 24 '16 at 09:28

3 Answers3

2

I'm not an expert on JCOP but I have experience with ISO7816:

Statusword 0x6F00 means "General Error". I suppose a CryptoException is thrown, but the value of "reason" is between 1-5 (according to the documentation). It's not possible to return arbitrary values as ISO7816 statusword.

Therefore I would suggest to send the reason using apdu.sendBytes(...), then you know what really is the problem

Best way would be to debug the code

villain
  • 33
  • 4
1

Since you indicate that your call to KeyBuilder.buildKey(...) fails, I would assume that this call throws a CryptoException with reason code NO_SUCH_ALGORITHM. As you do not handle that exception in your code, this results in the status word 0x6F00 being retuned by the card (0x6F00 is typically returned in case of unhandled exceptions).

So the CryptoException indicates that the requested key algorithm is not supported. Since you use the following parameters

KeyBuilder.buildKey(
    KeyBuilder.TYPE_EC_FP_PRIVATE,  // key type
    KeyBuilder.LENGTH_EC_FP_192,    // key length
    true);                          // key encryption

this could mean that

  • the card does not support the EC_FP (elliptic curve over large prime field) key type / algorithm,
  • the card does not support a key length of 192, or
  • the card does not support key encryption.

As the FIPS 140-2 Cryptographic Module Security Policy for both JCOP 2.4.2 R2 and JCOP 2.4.2 R3 indicate that ECDSA key pair generation is supported for P-192 (besides P-224 and P-256), I would assume that your card does not support key encryption. Hence, you could instead try

KeyBuilder.buildKey(
    KeyBuilder.TYPE_EC_FP_PRIVATE,  // key type
    KeyBuilder.LENGTH_EC_FP_192,    // key length
    false);                         // key encryption
Michael Roland
  • 39,663
  • 10
  • 99
  • 206
1

I can see two different issues:

  • JCOP (mistakenly) requires you to set the private key parameters as well;
  • base point G seems to be in compressed format, which may not be supported, it is required to convert to a 49 byte uncompressed point instead.

Furthermore it should be noted that:

  • you should indeed first build the public key using KeyBuilder (currently commented out);
  • there is no reason to have a parameter S in there (the seed is of no consequence - at least I presume it's not a private key with that size);
  • you should really wrap key generation with a try / catch statement and (in the end) convert to an ISOException with a valid status word;
  • having a debugger available is of vital importance.
Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263