5

I'm trying to get Elliptic Curve Diffie Hellman to work on a JavaCard (version 2.2.1).

On the JavaCard, I have the following code right now:

byte temp[] = new byte[100];
byte secret[] = new byte[100];
byte size = buf[ISO7816.OFFSET_LC];

Util.arrayCopy(buf, ISO7816.OFFSET_CDATA, temp, (byte) 0, size);

// the public key is in temp
short len = dh.generateSecret(temp, (byte) 0, size, secret, (byte) 0);

Util.arrayCopy(temp, (byte) 0, buf, ISO7816.OFFSET_CDATA, size);
//Util.arrayCopy(secret, (byte) 0, buf, ISO7816.OFFSET_CDATA, len);
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, size);

And I initialize dh as follows:

keyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_F2M_163);
keyPair.genKeyPair();
dh = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH, false);
dh.init(keyPair.getPrivate());

All of this seems to work, except for the dh.generateSecret call, where the applet simply seems to crash. If I leave the call out, and return other data, that works nicely. In which I import the data that is sent by the terminal. In the terminal, I have the following:

// generate an ecdh keypair
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
keyGen.initialize(163);
KeyPair keyPair = keyGen.generateKeyPair();

// initialize DH
KeyAgreement dh = KeyAgreement.getInstance("ECDH");
dh.init(keyPair.getPrivate());

//byte encKey[] = keyPair.getPublic().getEncoded();

// X9.62 encoding, no compression
int qLength = (163+7)/8;
byte[] xArr = ((ECPublicKey) keyPair.getPublic()).getW().getAffineX().toByteArray();
byte[] yArr = ((ECPublicKey) keyPair.getPublic()).getW().getAffineY().toByteArray();
byte[] enc2 = new byte[1+2*qLength];
enc2[0] = (byte) 0x04;
System.arraycopy(xArr, 0, enc2, qLength - xArr.length, xArr.length);
System.arraycopy(yArr, 0, enc2, 2* qLength - yArr.length, yArr.length);

byte res[] =send((byte) 0x00, enc2).getData();

I have tried several things. Right now, the code that sends the public key tries to encode it in X9.62 encoding (uncompressed) as specified by the JavaCard docs. However, I've also tried the default encode method, which gives exactly the same result.

I don't seem to be able to get any error out of the JavaCard about what is going wrong. Does anyone know what is going wrong? Or does anyone have a working example on how to do a key-exchange on a JavaCard?

kokx
  • 1,706
  • 13
  • 19
  • Do you have any APDU logs? – Paul Bastian Jun 01 '16 at 13:37
  • 1
    Just a few notes: `KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_F2M_163` - algorithm and length do not match. Do you specify elliptic curve domain parameters somewhere in your code? There is no default elliptic curve, so you should fill the parameters to both private and public key before generating a new keypair. – vojta Jun 02 '16 at 06:19

1 Answers1

1

As vojta already indicated:

keyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_F2M_163);

just tries to generate a key pair, and it probably works up to a point. But an Fp curve is different from a F2m curve, and to my knowledge there are no 163 bit Fp curves (to my knowledge anyway).

This means that you never actually installed the domain parameters, unless you generated your own, and I would call that unlikely.

Use a Fp curve with a known key length and set the parameters, at least for the public key (for JCOP cards you may have to set them for the private key as well). You'd normally use a 224 bit key size or higher to be secure.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263