I am using latest Oracle javacard simulator: https://docs.oracle.com/en/java/javacard/3.2 - And my applet build also target `3.2`.
I tested all my code started from the `HelloWorld` sample.
Bug 1: First bug is related to retrieving EC Public Key
To duplicate the bug, I generate a EC key pair and try to retrieve the public key representation using ECPublicKey.getW().
First test:
// Create ECC key pair (P-256 / secp256r1)
KeyPair eccKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256);
eccKeyPair.genKeyPair();
ECPublicKey eccPublicKey = (ECPublicKey)eccKeyPair.getPublic();
short wLength = eccPublicKey.getW(buffer, (short)2);
apdu.setOutgoing();
apdu.setOutgoingLength((short)(2 + wLength));
buffer[0] = (byte)((wLength >> 8) & 0xFF);
buffer[1] = (byte)(wLength & 0xFF);
apdu.sendBytes((short) 0, (short)(2 + wLength));
I received `00210424603E79077F33047A46079DABB6155E0F9A46B70D570E52B61831AFB9AAAAF4`. So the public key is 33 bytes long.
So 33 bytes long is valid for a compressed EC Public key. But the first byte should either be `02` or `03` - not 04. `04` is for uncompressed key and it should be 65-byte long.
I have read in different places that the EC Private and Public keys must have their parameters set before calling genKeyPair. So I tried:
ECPrivateKey eccPrivateKey = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256, false /* keyEncryption */);
setCurveParameters(eccPrivateKey); // Set SecP256r1 parameters
ECPublicKey eccPublicKey = (ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256, false /* keyEncryption */);
setCurveParameters(eccPublicKey); // Set SecP256r1 parameters
KeyPair eccKeyPair = new KeyPair(eccPublicKey, eccPrivateKey);
eccKeyPair.genKeyPair();
short wLength = eccPublicKey.getW(buffer, (short)2);
And similar result: `002104B792239DBD35FC129592F258E8231232B30D2FA8907E984788290BC0B7100049`
Bug 2: EC Public key not correctly initialized by javacard simulator
So I was assuming the bug 1 could be ignored and I could overwrite the 04 by 02 - even if it is risky (it could also be 03).
And I wanted to check ECDSA signature and its verification:
try {
ECPrivateKey eccPrivateKey = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256, false /* keyEncryption */);
setCurveParameters(eccPrivateKey);
ECPublicKey eccPublicKey = (ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256, false /* keyEncryption */);
setCurveParameters(eccPublicKey);
KeyPair eccKeyPair = new KeyPair(eccPublicKey, eccPrivateKey);
eccKeyPair.genKeyPair();
byte[] messageBytes = new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B};
Signature eccSignature = Signature.getInstance(Signature.ALG_ECDSA_SHA_256, false);
eccSignature.init(eccPrivateKey, Signature.MODE_SIGN);
short signatureLength = eccSignature.sign(
messageBytes, (short)0, (short)messageBytes.length, // input
buffer, (short)0 // output (reuse buffer)
);
Signature eccVerificationSignature = Signature.getInstance(Signature.ALG_ECDSA_SHA_256, false);
eccVerificationSignature.init(eccPublicKey, Signature.MODE_VERIFY); // <<<<<< CryptoException here: 'javacard.security.CryptoException (reason=0x0001)' - EC_POINT not created: error:08000066:elliptic curve routines::invalid encoding
apdu.setOutgoing();
apdu.setOutgoingLength(signatureLength);
apdu.sendBytes((short) 0, signatureLength);
} catch (CryptoException e) {
ISOException.throwIt((short)0x6F01);
}
My code actually throws an exception when calling `eccSignature.init(eccPublicKey, Signature.MODE_VERIFY);`
The exception is javacard.security.CryptoException (reason=0x0001)
Here are the logs from Oracle Javacard simulator for this sample:
SEVERE |msg|000598|grp:hal | EC_POINT not created: error:08000066:elliptic curve routines::invalid encoding
WARNING|msg|000599|grp:jcre| Exception:
WARNING|msg|000599|grp:jcre| javacard.security.CryptoException (reason=0x0001)
WARNING|msg|000599|grp:jcre| at javacard.security.CryptoException.throwIt_S (pc=@0x63c02b92)
WARNING|msg|000599|grp:jcre| at javacard.security.<anonymous> (pc=@0x63c035ee)
WARNING|msg|000599|grp:jcre| at <unknown> (pc=@0x63c2b09b)
WARNING|msg|000599|grp:jcre| at <unknown> (pc=@(nil))
WARNING|msg|000600|grp:jcre| Exception:
WARNING|msg|000600|grp:jcre| javacard.framework.ISOException (reason=0x6F01)
WARNING|msg|000600|grp:jcre| at javacard.framework.ISOException.throwIt_S (pc=@0x63c00e5e)
WARNING|msg|000600|grp:jcre| at <unknown> (pc=@0x63c2b0b7)
WARNING|msg|000600|grp:jcre| at <unknown> (pc=@(nil))