aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/applets/EC_Consts.java102
-rw-r--r--src/applets/SimpleECCApplet.java72
-rw-r--r--src/simpleapdu/SimpleAPDU.java42
3 files changed, 200 insertions, 16 deletions
diff --git a/src/applets/EC_Consts.java b/src/applets/EC_Consts.java
index a4164ac..dd58bed 100644
--- a/src/applets/EC_Consts.java
+++ b/src/applets/EC_Consts.java
@@ -279,7 +279,97 @@ public class EC_Consts {
// cofactor of G
public static final short EC256_FP_K = 1;
- // TODO: add parameters for longer lengths
+ // secp384r1 from http://www.secg.org/sec2-v2.pdf
+ public static final byte[] EC384_FP_P = new byte[]{
+ (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, (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, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};
+
+ public static final byte[] EC384_FP_A = new byte[]{
+ (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, (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, (byte) 0xFF, (byte) 0xFE,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFC};
+
+ public static final byte[] EC384_FP_B = new byte[]{
+ (byte) 0xB3, (byte) 0x31, (byte) 0x2F, (byte) 0xA7,
+ (byte) 0xE2, (byte) 0x3E, (byte) 0xE7, (byte) 0xE4,
+ (byte) 0x98, (byte) 0x8E, (byte) 0x05, (byte) 0x6B,
+ (byte) 0xE3, (byte) 0xF8, (byte) 0x2D, (byte) 0x19,
+ (byte) 0x18, (byte) 0x1D, (byte) 0x9C, (byte) 0x6E,
+ (byte) 0xFE, (byte) 0x81, (byte) 0x41, (byte) 0x12,
+ (byte) 0x03, (byte) 0x14, (byte) 0x08, (byte) 0x8F,
+ (byte) 0x50, (byte) 0x13, (byte) 0x87, (byte) 0x5A,
+ (byte) 0xC6, (byte) 0x56, (byte) 0x39, (byte) 0x8D,
+ (byte) 0x8A, (byte) 0x2E, (byte) 0xD1, (byte) 0x9D,
+ (byte) 0x2A, (byte) 0x85, (byte) 0xC8, (byte) 0xED,
+ (byte) 0xD3, (byte) 0xEC, (byte) 0x2A, (byte) 0xEF};
+
+ // G in compressed form / first part of ucompressed
+ public static final byte[] EC384_FP_G_X = new byte[]{
+ (byte) 0xAA, (byte) 0x87, (byte) 0xCA, (byte) 0x22,
+ (byte) 0xBE, (byte) 0x8B, (byte) 0x05, (byte) 0x37,
+ (byte) 0x8E, (byte) 0xB1, (byte) 0xC7, (byte) 0x1E,
+ (byte) 0xF3, (byte) 0x20, (byte) 0xAD, (byte) 0x74,
+ (byte) 0x6E, (byte) 0x1D, (byte) 0x3B, (byte) 0x62,
+ (byte) 0x8B, (byte) 0xA7, (byte) 0x9B, (byte) 0x98,
+ (byte) 0x59, (byte) 0xF7, (byte) 0x41, (byte) 0xE0,
+ (byte) 0x82, (byte) 0x54, (byte) 0x2A, (byte) 0x38,
+ (byte) 0x55, (byte) 0x02, (byte) 0xF2, (byte) 0x5D,
+ (byte) 0xBF, (byte) 0x55, (byte) 0x29, (byte) 0x6C,
+ (byte) 0x3A, (byte) 0x54, (byte) 0x5E, (byte) 0x38,
+ (byte) 0x72, (byte) 0x76, (byte) 0x0A, (byte) 0xB7};
+ // second part of G uncompressed
+ public static final byte[] EC384_FP_G_Y = new byte[]{
+ (byte) 0x36, (byte) 0x17, (byte) 0xDE, (byte) 0x4A,
+ (byte) 0x96, (byte) 0x26, (byte) 0x2C, (byte) 0x6F,
+ (byte) 0x5D, (byte) 0x9E, (byte) 0x98, (byte) 0xBF,
+ (byte) 0x92, (byte) 0x92, (byte) 0xDC, (byte) 0x29,
+ (byte) 0xF8, (byte) 0xF4, (byte) 0x1D, (byte) 0xBD,
+ (byte) 0x28, (byte) 0x9A, (byte) 0x14, (byte) 0x7C,
+ (byte) 0xE9, (byte) 0xDA, (byte) 0x31, (byte) 0x13,
+ (byte) 0xB5, (byte) 0xF0, (byte) 0xB8, (byte) 0xC0,
+ (byte) 0x0A, (byte) 0x60, (byte) 0xB1, (byte) 0xCE,
+ (byte) 0x1D, (byte) 0x7E, (byte) 0x81, (byte) 0x9D,
+ (byte) 0x7A, (byte) 0x43, (byte) 0x1D, (byte) 0x7C,
+ (byte) 0x90, (byte) 0xEA, (byte) 0x0E, (byte) 0x5F};
+
+ // Order of G
+ public static final byte[] EC384_FP_R = new byte[]{
+ (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, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xC7, (byte) 0x63, (byte) 0x4D, (byte) 0x81,
+ (byte) 0xF4, (byte) 0x37, (byte) 0x2D, (byte) 0xDF,
+ (byte) 0x58, (byte) 0x1A, (byte) 0x0D, (byte) 0xB2,
+ (byte) 0x48, (byte) 0xB0, (byte) 0xA7, (byte) 0x7A,
+ (byte) 0xEC, (byte) 0xEC, (byte) 0x19, (byte) 0x6A,
+ (byte) 0xCC, (byte) 0xC5, (byte) 0x29, (byte) 0x73};
+ // cofactor of G
+ public static final short EC384_FP_K = 1;
+
+ // TODO: secp521r1
+
public static void setValidECKeyParams(ECPublicKey ecPubKey, ECPrivateKey ecPrivKey, byte ecClass, short ecLength, byte[] auxBuffer) {
setECKeyParams(ecPubKey, ecPrivKey, ecClass, ecLength, auxBuffer, false);
@@ -341,6 +431,16 @@ public class EC_Consts {
EC_FP_K = EC256_FP_K;
break;
}
+ case (short) 384: {
+ EC_FP_P = EC384_FP_P;
+ EC_FP_A = EC384_FP_A;
+ EC_FP_B = EC384_FP_B;
+ EC_FP_G_X = EC384_FP_G_X;
+ EC_FP_G_Y = EC384_FP_G_Y;
+ EC_FP_R = EC384_FP_R;
+ EC_FP_K = EC384_FP_K;
+ break;
+ }
default: {
ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
}
diff --git a/src/applets/SimpleECCApplet.java b/src/applets/SimpleECCApplet.java
index ab6eede..b9fd347 100644
--- a/src/applets/SimpleECCApplet.java
+++ b/src/applets/SimpleECCApplet.java
@@ -38,6 +38,8 @@ public class SimpleECCApplet extends javacard.framework.Applet
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 byte ECTEST_ECDH_AGREEMENT_VALID_POINT = (byte) 0xc7;
+ public final static byte ECTEST_ECDH_AGREEMENT_INVALID_POINT = (byte) 0xc8;
public final static short SW_SKIPPED = (short) 0x0ee1;
/*
@@ -83,7 +85,8 @@ public class SimpleECCApplet extends javacard.framework.Applet
private KeyAgreement dhKeyAgreement = null;
// TEMPORARRY ARRAY IN RAM
- private byte m_ramArray[] = null;
+ private byte m_ramArray[] = null;
+ private byte m_ramArray2[] = null;
// PERSISTENT ARRAY IN EEPROM
private byte m_dataArray[] = null;
@@ -99,10 +102,10 @@ public class SimpleECCApplet extends javacard.framework.Applet
dataOffset++;
m_ramArray = JCSystem.makeTransientByteArray(ARRAY_LENGTH, JCSystem.CLEAR_ON_RESET);
+ m_ramArray2 = JCSystem.makeTransientByteArray(ARRAY_LENGTH, JCSystem.CLEAR_ON_RESET);
+
m_dataArray = new byte[ARRAY_LENGTH];
Util.arrayFillNonAtomic(m_dataArray, (short) 0, ARRAY_LENGTH, (byte) 0);
-
- dhKeyAgreement = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH, false);
}
register();
@@ -241,6 +244,9 @@ public class SimpleECCApplet extends javacard.framework.Applet
ecKeyPair.genKeyPair();
ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate();
+ if (dhKeyAgreement == null) {
+ dhKeyAgreement = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH, false);
+ }
dhKeyAgreement.init(ecPrivKey);
short secretLen = 0;
// Generate and export secret
@@ -347,8 +353,64 @@ public class SimpleECCApplet extends javacard.framework.Applet
Util.setShort(buffer, bufferOffset, SW_SKIPPED);
bufferOffset += 2;
}
+
+ //
+ // 5. ECDH agreement with valid public key
+ //
+ buffer[bufferOffset] = ECTEST_ECDH_AGREEMENT_VALID_POINT;
+ bufferOffset++;
+ try {
+ // Generate fresh EC keypair
+ ecKeyPair.genKeyPair();
+ ecPubKey = (ECPublicKey) ecKeyPair.getPublic();
+ ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate();
+ if (dhKeyAgreement == null) {
+ dhKeyAgreement = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH, false);
+ }
+ dhKeyAgreement.init(ecPrivKey);
+
+ short pubKeyLen = ecPubKey.getW(m_ramArray, (short) 0);
+ short secretLen = dhKeyAgreement.generateSecret(m_ramArray, (short) 0, pubKeyLen, m_ramArray2, (short) 0);
+
+ 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;
+ }
+
+ //
+ // 6. ECDH agreement with invalid public key
+ //
+ buffer[bufferOffset] = ECTEST_ECDH_AGREEMENT_VALID_POINT;
+ bufferOffset++;
+ try {
+ // Generate fresh EC keypair
+ ecKeyPair.genKeyPair();
+ ecPubKey = (ECPublicKey) ecKeyPair.getPublic();
+ ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate();
+ dhKeyAgreement.init(ecPrivKey);
+
+ short pubKeyLen = ecPubKey.getW(m_ramArray, (short) 0);
+ m_ramArray[(byte) 10] = (byte) 0xcc; // Corrupt public key
+ m_ramArray[(byte) 11] = (byte) 0xcc;
+ short secretLen = dhKeyAgreement.generateSecret(m_ramArray, (short) 0, pubKeyLen, m_ramArray2, (short) 0);
+
+ 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;
+ }
+
//
- // 5. Set invalid custom curve
+ // 7. Set invalid custom curve
//
buffer[bufferOffset] = ECTEST_SET_INVALIDCURVE;
bufferOffset++;
@@ -368,7 +430,7 @@ public class SimpleECCApplet extends javacard.framework.Applet
}
//
- // 6. Generate keypair with invalid custom curve
+ // 8. Generate keypair with invalid custom curve
//
buffer[bufferOffset] = ECTEST_GENERATE_KEYPAIR_INVALIDCUSTOMCURVE;
bufferOffset++;
diff --git a/src/simpleapdu/SimpleAPDU.java b/src/simpleapdu/SimpleAPDU.java
index 5b10cee..428d4f4 100644
--- a/src/simpleapdu/SimpleAPDU.java
+++ b/src/simpleapdu/SimpleAPDU.java
@@ -110,17 +110,37 @@ public class SimpleAPDU {
return String.format("fail\t(%s,\t0x%4x)", codeStr, code);
}
}
- static int VerifyPrintResult(String message, byte expectedTag, byte[] buffer, int bufferOffset) {
+
+ enum ExpResult {
+ SHOULD_SUCCEDD,
+ MAY_FAIL,
+ MUST_FAIL
+ }
+ static int VerifyPrintResult(String message, byte expectedTag, byte[] buffer, int bufferOffset, ExpResult expRes) {
assert (buffer[bufferOffset] == expectedTag);
bufferOffset++;
short resCode = getShort(buffer, bufferOffset);
bufferOffset += 2;
- System.out.println(String.format("%-50s%s", message, getPrintError(resCode)));
+
+ boolean bHiglight = false;
+ if ((expRes == ExpResult.MUST_FAIL) && (resCode == ISO7816.SW_NO_ERROR)) {
+ bHiglight = true;
+ }
+ if ((expRes == ExpResult.SHOULD_SUCCEDD) && (resCode != ISO7816.SW_NO_ERROR)) {
+ bHiglight = true;
+ }
+ if (bHiglight) {
+ System.out.println(String.format("!! %-50s%s", message, getPrintError(resCode)));
+ }
+ else {
+ System.out.println(String.format(" %-50s%s", message, getPrintError(resCode)));
+ }
return bufferOffset;
}
static void PrintECSupport(ResponseAPDU resp) {
byte[] buffer = resp.getData();
+ System.out.println();System.out.println();
int bufferOffset = 0;
while (bufferOffset < buffer.length) {
assert(buffer[bufferOffset] == SimpleECCApplet.ECTEST_SEPARATOR);
@@ -132,18 +152,20 @@ public class SimpleAPDU {
if (buffer[bufferOffset] == KeyPair.ALG_EC_F2M) {
ecType = "ALG_EC_F2M";
}
- System.out.println(String.format("%-50s%s", "EC type:", ecType));
+ System.out.println(String.format("%-53s%s", "EC type:", ecType));
bufferOffset++;
short keyLen = getShort(buffer, bufferOffset);
- System.out.println(String.format("%-50s%d bits", "EC key length (bits):", keyLen));
+ System.out.println(String.format("%-53s%d bits", "EC key length (bits):", keyLen));
bufferOffset += 2;
- bufferOffset = VerifyPrintResult("KeyPair object allocation:", SimpleECCApplet.ECTEST_ALLOCATE_KEYPAIR, buffer, bufferOffset);
- bufferOffset = VerifyPrintResult("Generate key with def curve (fails if no def):", SimpleECCApplet.ECTEST_GENERATE_KEYPAIR_DEFCURVE, buffer, bufferOffset);
- bufferOffset = VerifyPrintResult("Set valid custom curve:", SimpleECCApplet.ECTEST_SET_VALIDCURVE, buffer, bufferOffset);
- bufferOffset = VerifyPrintResult("Generate key with valid curve:", SimpleECCApplet.ECTEST_GENERATE_KEYPAIR_CUSTOMCURVE, buffer, bufferOffset);
- bufferOffset = VerifyPrintResult("Set invalid custom curve (fail is good):", SimpleECCApplet.ECTEST_SET_INVALIDCURVE, buffer, bufferOffset);
- bufferOffset = VerifyPrintResult("Generate key with invalid curve (fail is good):", SimpleECCApplet.ECTEST_GENERATE_KEYPAIR_INVALIDCUSTOMCURVE, buffer, bufferOffset);
+ bufferOffset = VerifyPrintResult("KeyPair object allocation:", SimpleECCApplet.ECTEST_ALLOCATE_KEYPAIR, buffer, bufferOffset, ExpResult.SHOULD_SUCCEDD);
+ bufferOffset = VerifyPrintResult("Generate key with def curve (fails if no def):", SimpleECCApplet.ECTEST_GENERATE_KEYPAIR_DEFCURVE, buffer, bufferOffset, ExpResult.MAY_FAIL);
+ bufferOffset = VerifyPrintResult("Set valid custom curve:", SimpleECCApplet.ECTEST_SET_VALIDCURVE, buffer, bufferOffset, ExpResult.SHOULD_SUCCEDD);
+ bufferOffset = VerifyPrintResult("Generate key with valid curve:", SimpleECCApplet.ECTEST_GENERATE_KEYPAIR_CUSTOMCURVE, buffer, bufferOffset, ExpResult.SHOULD_SUCCEDD);
+ bufferOffset = VerifyPrintResult("ECDH agreement with valid point:", SimpleECCApplet.ECTEST_ECDH_AGREEMENT_VALID_POINT, buffer, bufferOffset, ExpResult.SHOULD_SUCCEDD);
+ bufferOffset = VerifyPrintResult("ECDH agreement with invalid point (fail is good):", SimpleECCApplet.ECTEST_ECDH_AGREEMENT_INVALID_POINT, buffer, bufferOffset, ExpResult.MUST_FAIL);
+ bufferOffset = VerifyPrintResult("Set invalid custom curve (fail is good):", SimpleECCApplet.ECTEST_SET_INVALIDCURVE, buffer, bufferOffset, ExpResult.MUST_FAIL);
+ bufferOffset = VerifyPrintResult("Generate key with invalid curve (fail is good):", SimpleECCApplet.ECTEST_GENERATE_KEYPAIR_INVALIDCUSTOMCURVE, buffer, bufferOffset, ExpResult.MUST_FAIL);
System.out.println();
}