diff options
| author | petrs | 2016-09-08 16:36:03 +0200 |
|---|---|---|
| committer | petrs | 2016-09-08 16:36:03 +0200 |
| commit | 1796567aada62e02bb262340a166555b632f3d15 (patch) | |
| tree | 90f7169c9d7903e9fa6076d923a41c2fdc870e39 /src/applets/SimpleECCApplet.java | |
| parent | b97597bf20f5b44fb024c994cd3961c0a10d204b (diff) | |
| download | ECTester-1796567aada62e02bb262340a166555b632f3d15.tar.gz ECTester-1796567aada62e02bb262340a166555b632f3d15.tar.zst ECTester-1796567aada62e02bb262340a166555b632f3d15.zip | |
Diffstat (limited to 'src/applets/SimpleECCApplet.java')
| -rw-r--r-- | src/applets/SimpleECCApplet.java | 394 |
1 files changed, 287 insertions, 107 deletions
diff --git a/src/applets/SimpleECCApplet.java b/src/applets/SimpleECCApplet.java index 325d834..ab6eede 100644 --- a/src/applets/SimpleECCApplet.java +++ b/src/applets/SimpleECCApplet.java @@ -16,9 +16,13 @@ public class SimpleECCApplet extends javacard.framework.Applet // INSTRUCTIONS final static byte INS_GENERATEKEY = (byte) 0x5a; final static byte INS_ALLOCATEKEYPAIRS = (byte) 0x5b; + final static byte INS_ALLOCATEKEYPAIR = (byte) 0x5c; final static byte INS_DERIVEECDHSECRET = (byte) 0x5d; + final static byte INS_TESTECSUPPORTALL = (byte) 0x5e; + + final static short ARRAY_LENGTH = (short) 0xff; final static byte AES_BLOCK_LENGTH = (short) 0x16; @@ -26,6 +30,16 @@ public class SimpleECCApplet extends javacard.framework.Applet final static short EC_LENGTH_BITS = KeyBuilder.LENGTH_EC_FP_192; //final static short EC_LENGTH_BITS = KeyBuilder.LENGTH_EC_FP_160; //final static short EC_LENGTH_BITS = (short) 256; + + public final static byte ECTEST_SEPARATOR = (byte) 0xff; + public final static byte ECTEST_ALLOCATE_KEYPAIR = (byte) 0xc1; + public final static byte ECTEST_GENERATE_KEYPAIR_DEFCURVE = (byte) 0xc2; + public final static byte ECTEST_SET_VALIDCURVE = (byte) 0xc3; + public final static byte ECTEST_GENERATE_KEYPAIR_CUSTOMCURVE = (byte) 0xc4; + public final static byte ECTEST_SET_INVALIDCURVE = (byte) 0xc5; + public final static byte ECTEST_GENERATE_KEYPAIR_INVALIDCUSTOMCURVE = (byte) 0xc6; + + public final static short SW_SKIPPED = (short) 0x0ee1; /* public static final byte[] EC192_FP_PUBLICW = new byte[]{ (byte) 0x04, (byte) 0xC9, (byte) 0xC0, (byte) 0xED, (byte) 0xFB, (byte) 0x27, @@ -118,6 +132,9 @@ public class SimpleECCApplet extends javacard.framework.Applet if (apduBuffer[ISO7816.OFFSET_CLA] == CLA_SIMPLEECCAPPLET) { switch ( apduBuffer[ISO7816.OFFSET_INS] ) { + case INS_TESTECSUPPORTALL: + TestECSupportAllLengths(apdu); + break; case INS_ALLOCATEKEYPAIR: AllocateKeyPairReturnDefCourve(apdu); break; @@ -141,6 +158,274 @@ public class SimpleECCApplet extends javacard.framework.Applet else ISOException.throwIt( ISO7816.SW_CLA_NOT_SUPPORTED); } + + void AllocateKeyPairReturnDefCourve(APDU apdu) { + byte[] apdubuf = apdu.getBuffer(); + apdu.setIncomingAndReceive(); + + short bitLen = Util.getShort(apdubuf, ISO7816.OFFSET_CDATA); + + // Note: all locations shoudl happen in constructor. But here it is intentional + // as we like to test for result of allocation + ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, bitLen); + + // If required, generate also new key pair + if (apdubuf[ISO7816.OFFSET_P1] == (byte) 1) { + ecPubKey = (ECPublicKey) ecKeyPair.getPublic(); + ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate(); + // Some implementation wil not return valid pub key until ecKeyPair.genKeyPair() is called + // Other implementation will fail with exception if same is called => try catch + try { + if (ecPubKey == null) { + ecKeyPair.genKeyPair(); + } + } catch (Exception e) { + } // do nothing + + // If required, initialize curve parameters first + if (apdubuf[ISO7816.OFFSET_P2] == (byte) 2) { + EC_Consts.setValidECKeyParams(ecPubKey, ecPrivKey, KeyPair.ALG_EC_FP, bitLen, m_ramArray); + } + + // Now generate new keypair with either default or custom curve + ecKeyPair.genKeyPair(); + ecPubKey = (ECPublicKey) ecKeyPair.getPublic(); + ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate(); + + short len = 0; + short offset = 0; + + // Export curve public parameters + offset += 2; // reserve space for length + len = ecPubKey.getField(apdubuf, offset); + Util.setShort(apdubuf, (short) (offset - 2), len); + offset += len; + offset += 2; // reserve space for length + len = ecPubKey.getA(apdubuf, offset); + Util.setShort(apdubuf, (short) (offset - 2), len); + offset += len; + + offset += 2; // reserve space for length + len = ecPubKey.getB(apdubuf, offset); + Util.setShort(apdubuf, (short) (offset - 2), len); + offset += len; + offset += 2; // reserve space for length + len = ecPubKey.getR(apdubuf, offset); + Util.setShort(apdubuf, (short) (offset - 2), len); + offset += len; + /* + offset += 2; // reserve space for length + len = ecPubKey.getW(apdubuf, offset); + Util.setShort(apdubuf, (short) (offset - 2), len); + offset += len; + */ + apdu.setOutgoingAndSend((short) 0, offset); + } + } + + + + void DeriveECDHSecret(APDU apdu) { + byte[] apdubuf = apdu.getBuffer(); + short len = apdu.setIncomingAndReceive(); + + // Assumption: proper EC keyPair is already allocated + // If public key point is provided, then use it + if (len == 0) { + // if not provided, use build-in one (valid for for 192 only) + Util.arrayCopyNonAtomic(EC192_FP_PUBLICW, (short) 0, apdubuf, ISO7816.OFFSET_CDATA, (short) EC192_FP_PUBLICW.length); + len = (short) EC192_FP_PUBLICW.length; + } + + // Generate fresh EC keypair + ecKeyPair.genKeyPair(); + ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate(); + + dhKeyAgreement.init(ecPrivKey); + short secretLen = 0; + // Generate and export secret + secretLen = dhKeyAgreement.generateSecret(apdubuf, ISO7816.OFFSET_CDATA, len, m_ramArray, (short) 0); + Util.arrayCopyNonAtomic(m_ramArray, (short) 0, apdubuf, (short) 0, secretLen); + + apdu.setOutgoingAndSend((short) 0, secretLen); + } + + short TestECSupport(byte keyClass, short keyLen, byte[] buffer, short bufferOffset) { + short baseOffset = bufferOffset; + + ecKeyPair = null; + ecPubKey = null; + ecPrivKey = null; + + buffer[bufferOffset] = ECTEST_SEPARATOR; bufferOffset++; + buffer[bufferOffset] = keyClass; bufferOffset++; + Util.setShort(buffer, bufferOffset, keyLen); bufferOffset += 2; + // + // 1. Allocate KeyPair object + // + buffer[bufferOffset] = ECTEST_ALLOCATE_KEYPAIR; bufferOffset++; + try { + ecKeyPair = new KeyPair(keyClass, keyLen); + Util.setShort(buffer, bufferOffset, ISO7816.SW_NO_ERROR); bufferOffset += 2; + } + catch (CryptoException e) { + Util.setShort(buffer, bufferOffset, e.getReason()); bufferOffset += 2; + } + catch (Exception e) { + Util.setShort(buffer, bufferOffset, ISO7816.SW_UNKNOWN); + bufferOffset += 2; + } + + // + // 2. Test keypair generation without explicit curve (=> default curve preset) + // + buffer[bufferOffset] = ECTEST_GENERATE_KEYPAIR_DEFCURVE; bufferOffset++; + try { + ecKeyPair.genKeyPair(); + Util.setShort(buffer, bufferOffset, ISO7816.SW_NO_ERROR); + bufferOffset += 2; + } catch (CryptoException e) { + Util.setShort(buffer, bufferOffset, e.getReason()); + bufferOffset += 2; + } + catch (Exception e) { + Util.setShort(buffer, bufferOffset, ISO7816.SW_UNKNOWN); + bufferOffset += 2; + } + + // + // 3. Set valid custom curve + // + buffer[bufferOffset] = ECTEST_SET_VALIDCURVE; + bufferOffset++; + boolean bGenerateKey = false; + try { + ecPubKey = (ECPublicKey) ecKeyPair.getPublic(); + ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate(); + // Some implementation wil not return valid pub key until ecKeyPair.genKeyPair() is called + // Other implementation will fail with exception if same is called => try catch + try { + if (ecPubKey == null) { + ecKeyPair.genKeyPair(); + } + } catch (Exception e) {} // do intentionally nothing + + // Initialize curve parameters + EC_Consts.setValidECKeyParams(ecPubKey, ecPrivKey, keyClass, keyLen, m_ramArray); + Util.setShort(buffer, bufferOffset, ISO7816.SW_NO_ERROR); + bufferOffset += 2; + + bGenerateKey = true; + } catch (CryptoException e) { + Util.setShort(buffer, bufferOffset, e.getReason()); + bufferOffset += 2; + } + catch (Exception e) { + Util.setShort(buffer, bufferOffset, ISO7816.SW_UNKNOWN); + bufferOffset += 2; + } + + // + // 4. Generate keypair with custom curve + // + buffer[bufferOffset] = ECTEST_GENERATE_KEYPAIR_CUSTOMCURVE; + bufferOffset++; + if (bGenerateKey) { + try { + ecKeyPair.genKeyPair(); + Util.setShort(buffer, bufferOffset, ISO7816.SW_NO_ERROR); + bufferOffset += 2; + } catch (CryptoException e) { + Util.setShort(buffer, bufferOffset, e.getReason()); + bufferOffset += 2; + } catch (Exception e) { + Util.setShort(buffer, bufferOffset, ISO7816.SW_UNKNOWN); + bufferOffset += 2; + } + } + else { + Util.setShort(buffer, bufferOffset, SW_SKIPPED); + bufferOffset += 2; + } + // + // 5. Set invalid custom curve + // + buffer[bufferOffset] = ECTEST_SET_INVALIDCURVE; + bufferOffset++; + bGenerateKey = false; + try { + // Initialize curve parameters + EC_Consts.setInValidECKeyParams(ecPubKey, ecPrivKey, keyClass, keyLen, m_ramArray); + Util.setShort(buffer, bufferOffset, ISO7816.SW_NO_ERROR); + bufferOffset += 2; + bGenerateKey = true; + } catch (CryptoException e) { + Util.setShort(buffer, bufferOffset, e.getReason()); + bufferOffset += 2; + } catch (Exception e) { + Util.setShort(buffer, bufferOffset, ISO7816.SW_UNKNOWN); + bufferOffset += 2; + } + + // + // 6. Generate keypair with invalid custom curve + // + buffer[bufferOffset] = ECTEST_GENERATE_KEYPAIR_INVALIDCUSTOMCURVE; + bufferOffset++; + if (bGenerateKey) { + try { + ecKeyPair.genKeyPair(); + Util.setShort(buffer, bufferOffset, ISO7816.SW_NO_ERROR); + bufferOffset += 2; + } catch (CryptoException e) { + Util.setShort(buffer, bufferOffset, e.getReason()); + bufferOffset += 2; + } catch (Exception e) { + Util.setShort(buffer, bufferOffset, ISO7816.SW_UNKNOWN); + bufferOffset += 2; + } + } else { + Util.setShort(buffer, bufferOffset, SW_SKIPPED); + bufferOffset += 2; + } + + return (short) (bufferOffset - baseOffset); + } + void TestECSupportAllLengths(APDU apdu) { + byte[] apdubuf = apdu.getBuffer(); + short len = apdu.setIncomingAndReceive(); + + short dataOffset = 0; + // FP - + dataOffset += TestECSupport(KeyPair.ALG_EC_FP, (short) 128, apdubuf, dataOffset); + dataOffset += TestECSupport(KeyPair.ALG_EC_FP, (short) 160, apdubuf, dataOffset); + dataOffset += TestECSupport(KeyPair.ALG_EC_FP, (short) 192, apdubuf, dataOffset); + dataOffset += TestECSupport(KeyPair.ALG_EC_FP, (short) 224, apdubuf, dataOffset); + dataOffset += TestECSupport(KeyPair.ALG_EC_FP, (short) 256, apdubuf, dataOffset); + dataOffset += TestECSupport(KeyPair.ALG_EC_FP, (short) 384, apdubuf, dataOffset); + dataOffset += TestECSupport(KeyPair.ALG_EC_FP, (short) 521, apdubuf, dataOffset); + + apdu.setOutgoingAndSend((short) 0, dataOffset); + } + + + + + + + + + + + + + + + + + + + void AllocateKeyPair(byte algorithm, short bitLen) { // Select proper attributes switch (bitLen) { @@ -185,7 +470,7 @@ public class SimpleECCApplet extends javacard.framework.Applet ecPubKey = (ECPublicKey) ecKeyPair.getPublic(); ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate(); // Set required EC parameters - EC_Consts.setECKeyParams(ecPubKey, ecPrivKey, bitLen, m_ramArray); + EC_Consts.setValidECKeyParams(ecPubKey, ecPrivKey, KeyPair.ALG_EC_FP, bitLen, m_ramArray); } short TryAllocateKeyPair(byte algorithm, short bitLen, byte[] buffer, short offset) { @@ -215,114 +500,9 @@ public class SimpleECCApplet extends javacard.framework.Applet apdu.setOutgoingAndSend((short) 0, offset); } - void AllocateKeyPairReturnDefCourve(APDU apdu) { - byte[] apdubuf = apdu.getBuffer(); - apdu.setIncomingAndReceive(); - - short bitLen = Util.getShort(apdubuf, ISO7816.OFFSET_CDATA); - - // Note: all locations shoudl happen in constructor. But here it is intentional - // as we like to test for result of allocation - ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, bitLen); - - // If required, generate also new key pair - if (apdubuf[ISO7816.OFFSET_P1] == (byte) 1) { - ecPubKey = (ECPublicKey) ecKeyPair.getPublic(); - ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate(); - // Some implementation wil not return valid pub key until ecKeyPair.genKeyPair() is called - // Other implementation will fail with exception if same is called => try catch - try { - if (ecPubKey == null) {ecKeyPair.genKeyPair();} - } - catch (Exception e) {} // do nothing - - - // If required, initialize curve parameters first - if (apdubuf[ISO7816.OFFSET_P2] == (byte) 2) { - EC_Consts.setECKeyParams(ecPubKey, ecPrivKey, bitLen, m_ramArray); - } - - // Now generate new keypair with either default or custom curve - ecKeyPair.genKeyPair(); - ecPubKey = (ECPublicKey) ecKeyPair.getPublic(); - ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate(); - - short len = 0; - short offset = 0; - - // Export curve public parameters - offset += 2; // reserve space for length - len = ecPubKey.getField(apdubuf, offset); - Util.setShort(apdubuf, (short) (offset - 2), len); - offset += len; - offset += 2; // reserve space for length - len = ecPubKey.getA(apdubuf, offset); - Util.setShort(apdubuf, (short) (offset - 2), len); - offset += len; - offset += 2; // reserve space for length - len = ecPubKey.getB(apdubuf, offset); - Util.setShort(apdubuf, (short) (offset - 2), len); - offset += len; - offset += 2; // reserve space for length - len = ecPubKey.getR(apdubuf, offset); - Util.setShort(apdubuf, (short) (offset - 2), len); - offset += len; -/* - offset += 2; // reserve space for length - len = ecPubKey.getW(apdubuf, offset); - Util.setShort(apdubuf, (short) (offset - 2), len); - offset += len; -*/ - apdu.setOutgoingAndSend((short) 0, offset); - } - } -/** - For a first quick test, this would be the workflow: - * - * 1. Import a given ECC public key (i.e. a point that is not on the curve) - * - * 2. Generate a fresh ECC keypair - * - * 3. Perform a ECDH key-derivation with the keys from steps 1 and 2 - * - * 4. Repeat steps 2 & 3 a couple of times and record the generated secrets - * - * - * - * If the card is vulnerable, then the generated secrets will repeat. For - * example, we have points of order 5. With such a point and a vulnerable - * card, there are only 5 (or even less) different possible values for the - * generated secrets. This is pretty obvious, if you do a couple of (e.g. - * +-10) key-derivations ;) - * @param apdu - */ - void DeriveECDHSecret(APDU apdu) { - byte[] apdubuf = apdu.getBuffer(); - short len = apdu.setIncomingAndReceive(); - - // Assumption: proper EC keyPair is already allocated - - // If public key point is provided, then use it - if (len == 0) { - // if not provided, use build-in one - Util.arrayCopyNonAtomic(EC192_FP_PUBLICW, (short) 0, apdubuf, ISO7816.OFFSET_CDATA, (short) EC192_FP_PUBLICW.length); - len = (short) EC192_FP_PUBLICW.length; - } - - // Generate fresh EC keypair - ecKeyPair.genKeyPair(); - ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate(); - - dhKeyAgreement.init(ecPrivKey); - short secretLen = 0; - // Generate and export secret - secretLen = dhKeyAgreement.generateSecret(apdubuf, ISO7816.OFFSET_CDATA, len, m_ramArray, (short) 0); - Util.arrayCopyNonAtomic(m_ramArray, (short) 0, apdubuf, (short) 0, secretLen); - - apdu.setOutgoingAndSend((short) 0, secretLen); - } + void GenerateKey(APDU apdu) { |
