aboutsummaryrefslogtreecommitdiff
path: root/applet
diff options
context:
space:
mode:
authorJ08nY2024-03-22 23:58:55 +0100
committerJ08nY2024-03-25 14:52:43 +0100
commit73af477a8774e1ede5dd8de6491eb353dc0b12bd (patch)
tree2d4e3b19bc5fb55308b886032312be76341736d4 /applet
parent64b95fa059295e1dc23371c849f2302c1c18f5b4 (diff)
downloadECTester-73af477a8774e1ede5dd8de6491eb353dc0b12bd.tar.gz
ECTester-73af477a8774e1ede5dd8de6491eb353dc0b12bd.tar.zst
ECTester-73af477a8774e1ede5dd8de6491eb353dc0b12bd.zip
Diffstat (limited to 'applet')
-rw-r--r--applet/GPPcScConnectionPlugin.dllbin15360 -> 0 bytes
-rw-r--r--applet/GPShell.exebin33280 -> 0 bytes
-rw-r--r--applet/GlobalPlatform.dllbin117248 -> 0 bytes
-rw-r--r--applet/build.gradle.kts136
-rw-r--r--applet/gp.exebin908346 -> 0 bytes
-rw-r--r--applet/gp.jarbin894200 -> 0 bytes
-rw-r--r--applet/gppro_upload.bat14
-rwxr-xr-xapplet/gppro_upload.sh10
-rw-r--r--applet/gppro_upload_emv.bat15
-rwxr-xr-xapplet/gppro_upload_emv.sh10
-rw-r--r--applet/libeay32.dllbin1017344 -> 0 bytes
-rw-r--r--applet/openkms-gp.jarbin78142 -> 0 bytes
-rw-r--r--applet/src/main/java/cz/crcs/ectester/applet/AppletBase.java962
-rw-r--r--applet/src/main/java/cz/crcs/ectester/applet/AppletUtil.java35
-rw-r--r--applet/src/main/java/cz/crcs/ectester/applet/CardConsts.java65
-rw-r--r--applet/src/main/java/cz/crcs/ectester/applet/ECKeyGenerator.java526
-rw-r--r--applet/src/main/java/cz/crcs/ectester/applet/ECKeyTester.java225
-rw-r--r--applet/src/main/java/cz/crcs/ectester/applet/ECTesterApplet.java63
-rw-r--r--applet/src/main/java/cz/crcs/ectester/applet/ECTesterAppletExtended.java64
-rw-r--r--applet/src/main/java/cz/crcs/ectester/applet/EC_Consts.java1512
-rw-r--r--applet/ssleay32.dllbin200704 -> 0 bytes
-rw-r--r--applet/zlib1.dllbin75264 -> 0 bytes
22 files changed, 3588 insertions, 49 deletions
diff --git a/applet/GPPcScConnectionPlugin.dll b/applet/GPPcScConnectionPlugin.dll
deleted file mode 100644
index 3b27f6b..0000000
--- a/applet/GPPcScConnectionPlugin.dll
+++ /dev/null
Binary files differ
diff --git a/applet/GPShell.exe b/applet/GPShell.exe
deleted file mode 100644
index 091eece..0000000
--- a/applet/GPShell.exe
+++ /dev/null
Binary files differ
diff --git a/applet/GlobalPlatform.dll b/applet/GlobalPlatform.dll
deleted file mode 100644
index 6dca172..0000000
--- a/applet/GlobalPlatform.dll
+++ /dev/null
Binary files differ
diff --git a/applet/build.gradle.kts b/applet/build.gradle.kts
new file mode 100644
index 0000000..d93496e
--- /dev/null
+++ b/applet/build.gradle.kts
@@ -0,0 +1,136 @@
+version "0.3.3"
+
+// Buildscript configuration for the javacard-gradle plugin.
+// Do not modify this particular block. Dependencies for the project are lower.
+buildscript {
+ repositories {
+ mavenCentral()
+ maven("https://javacard.pro/maven")
+ maven("https://deadcode.me/mvn")
+ // mavenLocal()
+ }
+ dependencies {
+ classpath("com.klinec:gradle-javacard:1.8.0")
+ }
+}
+
+plugins {
+ id("com.klinec.gradle.javacard") version "1.8.0"
+ id("java")
+}
+
+java {
+ toolchain {
+ languageVersion = JavaLanguageVersion.of(8)
+ }
+}
+
+// Common settings, definitions
+val rootPath = rootDir.absolutePath
+val libs = "$rootPath/ext/libs"
+val libsSdk = "$rootPath/ext/sdks"
+
+// Repositories for your project
+repositories {
+ mavenCentral()
+ // mavenLocal() // for local maven repository if needed
+
+ // Repository with JCardSim, Globalplatform, etc, ...
+ maven("https://javacard.pro/maven")
+ maven("https://deadcode.me/mvn")
+
+ // Local lib repository
+ flatDir {
+ dirs(libs)
+ }
+}
+
+// Dependencies for your project
+dependencies {
+ jcardsim("com.klinec:jcardsim:3.0.5.11")
+ implementation("com.klinec:jcardsim:3.0.5.11")
+
+ testImplementation(platform("org.junit:junit-bom:5.10.2"))
+ testImplementation("org.junit.jupiter:junit-jupiter")
+ testRuntimeOnly("org.junit.platform:junit-platform-launcher")
+
+ //testImplementation(group = "com.klinec", name = "javacard-tools", version = "1.0.4") {
+ // exclude group = "com.klinec", module = "jcardsim"
+ //}
+
+ // Include plugin as it has bundled GP & other tools.
+ // Alternative: include GP manually, but the included
+ // version has to be compatible with the plugin.
+ runtimeOnly("com.klinec:gradle-javacard:1.8.0")
+}
+
+//task dumpClassPath (dependsOn: listOf("idea")) {
+// doLast {
+// println "Gradle classpath:\n- "+configurations.implementation.files*.name.join("\n- ")
+// println "-------\n"
+// println "IDEA classpath: \n- "+file(project.name+".iml").readLines()
+// .grep(~ / . * "jar:.*/).collect { it.split("listOf(\\/)")[-3].trim() }.join("\n-")
+// println "-------\n"
+// }
+//}
+
+tasks.named<Test>("test") {
+ useJUnitPlatform()
+}
+
+// JavaCard SDKs and libraries
+val JC212 = libsSdk + "/jc212_kit"
+val JC221 = libsSdk + "/jc221_kit"
+val JC222 = libsSdk + "/jc222_kit"
+val JC303 = libsSdk + "/jc303_kit"
+val JC304 = libsSdk + "/jc304_kit"
+val JC305 = libsSdk + "/jc305u1_kit"
+val JC305u2 = libsSdk + "/jc305u2_kit"
+val JC305u3 = libsSdk + "/jc305u3_kit"
+
+// Which JavaCard SDK to use - select
+// In order to compile JC222 and lower you have to have Java SDK <= 1.8
+// For more info on JavaCard vs JDK version requirements inspect:
+// https://github.com/martinpaljak/ant-javacard/wiki/Version-compatibility
+//
+// JC310b43 supports building also for lower versions (cap.targetsdk).
+// If another SDK is selected, please comment the cap.targetsdk setting.
+val JC_SELECTED = JC222
+
+
+javacard {
+
+ config {
+ jckit(JC_SELECTED)
+
+ // Using custom repo with jcardsim
+ debugGpPro(true)
+ addImplicitJcardSim(false)
+ addImplicitJcardSimJunit(false)
+
+ cap {
+ packageName("cz.crcs.ectester.applet")
+ version("0.3.3")
+ aid("01:ff:ff:04:05:06:07:08:09")
+ output("applet.cap")
+
+ // JC310b43 supports compilation targeting for lower API versions.
+ // Here you can specify path to the SDK you want to use.
+ // Only JC304 and higher are supported for targeting.
+ // If JC310b43 is not used, targetsdk cannot be set.
+ targetsdk(JC_SELECTED)
+
+ // Override java bytecode version if needed.
+ // javaversion "1.7"
+
+ applet {
+ className("applet.MainApplet")
+ aid("01:ff:ff:04:05:06:07:08:09:01:02")
+ }
+
+ // dependencies {
+ // remote "com.klinec:globalplatform:2.1.1"
+ // }
+ }
+ }
+} \ No newline at end of file
diff --git a/applet/gp.exe b/applet/gp.exe
deleted file mode 100644
index 6478bf2..0000000
--- a/applet/gp.exe
+++ /dev/null
Binary files differ
diff --git a/applet/gp.jar b/applet/gp.jar
deleted file mode 100644
index 774d81a..0000000
--- a/applet/gp.jar
+++ /dev/null
Binary files differ
diff --git a/applet/gppro_upload.bat b/applet/gppro_upload.bat
deleted file mode 100644
index 50a41d7..0000000
--- a/applet/gppro_upload.bat
+++ /dev/null
@@ -1,14 +0,0 @@
-if "%1" == "" {
- set err=yes
-}
-if "%2" == "" {
- set err=yes
-}
-if "%err" == "yes" {
- echo "gppro_upload.bat <AID> <CAP file>"
- exit
-}
-gp.exe -deletedeps -verbose -delete %1
-gp.exe -install %2 -verbose -d
-
-
diff --git a/applet/gppro_upload.sh b/applet/gppro_upload.sh
deleted file mode 100755
index 055d51d..0000000
--- a/applet/gppro_upload.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env bash
-if [ "$#" -ne 2 ]; then
- echo "gppro_upload.sh <AID> <CAP file>" >&2
- exit 1
-fi
-
-java -jar gp.jar -deletedeps -verbose -delete $1
-java -jar gp.jar -install $2 -verbose -d
-
-
diff --git a/applet/gppro_upload_emv.bat b/applet/gppro_upload_emv.bat
deleted file mode 100644
index 4094623..0000000
--- a/applet/gppro_upload_emv.bat
+++ /dev/null
@@ -1,15 +0,0 @@
-if "%1" == "" {
- set err=yes
-}
-if "%2" == "" {
- set err=yes
-}
-if "%err" == "yes" {
- echo "gppro_upload_emv.bat <AID> <CAP file>"
- exit
-}
-
-gp.exe -deletedeps -verbose -emv -delete %1
-gp.exe -install %2 -verbose -emv -d
-
-
diff --git a/applet/gppro_upload_emv.sh b/applet/gppro_upload_emv.sh
deleted file mode 100755
index 9e1a62e..0000000
--- a/applet/gppro_upload_emv.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env bash
-if [ "$#" -ne 2 ]; then
- echo "gppro_upload.sh <AID> <CAP file>" >&2
- exit 1
-fi
-
-java -jar gp.jar --deletedeps --verbose -emv --delete $1
-java -jar gp.jar --install $2 --verbose --emv -d
-
-
diff --git a/applet/libeay32.dll b/applet/libeay32.dll
deleted file mode 100644
index b59a6b4..0000000
--- a/applet/libeay32.dll
+++ /dev/null
Binary files differ
diff --git a/applet/openkms-gp.jar b/applet/openkms-gp.jar
deleted file mode 100644
index 9cd5de5..0000000
--- a/applet/openkms-gp.jar
+++ /dev/null
Binary files differ
diff --git a/applet/src/main/java/cz/crcs/ectester/applet/AppletBase.java b/applet/src/main/java/cz/crcs/ectester/applet/AppletBase.java
new file mode 100644
index 0000000..411e5a1
--- /dev/null
+++ b/applet/src/main/java/cz/crcs/ectester/applet/AppletBase.java
@@ -0,0 +1,962 @@
+package cz.crcs.ectester.applet;
+
+import javacard.framework.*;
+import javacard.security.*;
+
+/**
+ * Applet base class, that handles instructions, given
+ * either basic or extended length APDUs.
+ *
+ * @author Petr Svenda petr@svenda.com
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public abstract class AppletBase extends Applet {
+ public static final byte[] VERSION = {'v', '0', '.', '3', '.', '3'};
+
+ public static final short ARRAY_LENGTH = 0x100;
+ public static final short APDU_MAX_LENGTH = 1024;//512
+
+ // TEMPORARRY ARRAY IN RAM
+ byte[] ramArray = null;
+ byte[] ramArray2 = null;
+ byte[] apduArray = null;
+ short apduEnd = 0;
+ short cdata = 0;
+
+ RandomData randomData = null;
+
+ ECKeyTester keyTester = null;
+ ECKeyGenerator keyGenerator = null;
+ KeyPair localKeypair = null;
+ KeyPair remoteKeypair = null;
+
+ protected AppletBase(byte[] buffer, short offset, byte length) {
+ if (length > 9) {
+ /*
+ short dataOffset = offset;
+ // shift to privilege offset
+ dataOffset += (short) (1 + buffer[offset]);
+ // finally shift to Application specific offset
+ dataOffset += (short) (1 + buffer[dataOffset]);
+ // go to proprietary data
+ dataOffset++;
+ */
+ short resetMemory = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
+ short deselectMemory = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);
+ short bigMem;
+ short smallMem;
+ byte bigMemType;
+ byte smallMemType;
+ if (resetMemory >= deselectMemory) {
+ bigMem = resetMemory;
+ smallMem = deselectMemory;
+ bigMemType = JCSystem.CLEAR_ON_RESET;
+ smallMemType = JCSystem.CLEAR_ON_DESELECT;
+ } else {
+ bigMem = deselectMemory;
+ smallMem = resetMemory;
+ bigMemType = JCSystem.CLEAR_ON_DESELECT;
+ smallMemType = JCSystem.CLEAR_ON_RESET;
+ }
+ short[] lensBig = new short[]{APDU_MAX_LENGTH + 2 * ARRAY_LENGTH, APDU_MAX_LENGTH + ARRAY_LENGTH, APDU_MAX_LENGTH,};
+ short[] lensSmall = new short[]{0, ARRAY_LENGTH, 2 * ARRAY_LENGTH};
+ byte[] allocsBig = new byte[]{0x07, 0x03, 0x01};
+ boolean done = false;
+ for (short i = 0; i < 3; ++i) {
+ if (lensBig[i] <= bigMem && lensSmall[i] <= smallMem) {
+ byte allocI = 1;
+ while (allocI < 0x08) {
+ byte type = ((allocI & allocsBig[i]) != 0) ? bigMemType : smallMemType;
+ switch (allocI) {
+ case 0x01:
+ apduArray = JCSystem.makeTransientByteArray(APDU_MAX_LENGTH, type);
+ break;
+ case 0x02:
+ ramArray = JCSystem.makeTransientByteArray(ARRAY_LENGTH, type);
+ break;
+ case 0x04:
+ ramArray2 = JCSystem.makeTransientByteArray(ARRAY_LENGTH, type);
+ break;
+ }
+ allocI = (byte) (allocI << 1);
+ }
+ done = true;
+ break;
+ }
+ }
+ if (!done) {
+ ISOException.throwIt((short) 0x6a84);
+ }
+
+ randomData = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
+ EC_Consts.randomData = randomData;
+
+ keyGenerator = new ECKeyGenerator();
+ keyTester = new ECKeyTester();
+ }
+ }
+
+ public void process(APDU apdu) throws ISOException {
+ // get the APDU buffer
+ byte[] apduBuffer = apdu.getBuffer();
+ byte cla = apduBuffer[ISO7816.OFFSET_CLA];
+ byte ins = apduBuffer[ISO7816.OFFSET_INS];
+
+ // ignore the applet select command dispatched to the process
+ if (selectingApplet()) {
+ return;
+ }
+
+ if (cla == CardConsts.CLA_ECTESTERAPPLET) {
+ try {
+ if (ins == CardConsts.INS_BUFFER) {
+ short read = readAPDU(apdu, true);
+ if (read == -1) {
+ ISOException.throwIt(CardConsts.SW_CANNOT_FIT);
+ return;
+ }
+ apduEnd += read;
+ apdu.setOutgoingAndSend((short) 0, (short) 0);
+ return;
+ } else {
+ apduEnd = 0;
+ if (ins == CardConsts.INS_PERFORM) {
+ ins = apduArray[ISO7816.OFFSET_INS];
+ apdu.setIncomingAndReceive();
+ } else {
+ if (readAPDU(apdu, false) == -1) {
+ ISOException.throwIt(CardConsts.SW_CANNOT_FIT);
+ return;
+ }
+ }
+ }
+
+ short length = 0;
+ switch (ins) {
+ case CardConsts.INS_ALLOCATE_KA:
+ length = insAllocateKA(apdu);
+ break;
+ case CardConsts.INS_ALLOCATE_SIG:
+ length = insAllocateSig(apdu);
+ break;
+ case CardConsts.INS_ALLOCATE:
+ length = insAllocate(apdu);
+ break;
+ case CardConsts.INS_CLEAR:
+ length = insClear(apdu);
+ break;
+ case CardConsts.INS_SET:
+ length = insSet(apdu);
+ break;
+ case CardConsts.INS_TRANSFORM:
+ length = insTransform(apdu);
+ break;
+ case CardConsts.INS_GENERATE:
+ length = insGenerate(apdu);
+ break;
+ case CardConsts.INS_EXPORT:
+ length = insExport(apdu);
+ break;
+ case CardConsts.INS_ECDH:
+ length = insECDH(apdu);
+ break;
+ case CardConsts.INS_ECDH_DIRECT:
+ length = insECDH_direct(apdu);
+ break;
+ case CardConsts.INS_ECDSA:
+ length = insECDSA(apdu);
+ break;
+ case CardConsts.INS_ECDSA_SIGN:
+ length = insECDSA_sign(apdu);
+ break;
+ case CardConsts.INS_ECDSA_VERIFY:
+ length = insECDSA_verify(apdu);
+ break;
+ case CardConsts.INS_CLEANUP:
+ length = insCleanup(apdu);
+ break;
+ case CardConsts.INS_GET_INFO:
+ length = insGetInfo(apdu);
+ break;
+ case CardConsts.INS_SET_DRY_RUN_MODE:
+ length = insSetDryRunMode(apdu);
+ break;
+ default:
+ // The INS code is not supported by the dispatcher
+ ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
+ break;
+ }
+ apdu.setOutgoingAndSend((short) 0, length);
+
+ } catch (ISOException e) {
+ throw e; // Our exception from code, just re-emit
+ } catch (ArrayIndexOutOfBoundsException e) {
+ ISOException.throwIt(CardConsts.SW_ArrayIndexOutOfBoundsException);
+ } catch (ArithmeticException e) {
+ ISOException.throwIt(CardConsts.SW_ArithmeticException);
+ } catch (ArrayStoreException e) {
+ ISOException.throwIt(CardConsts.SW_ArrayStoreException);
+ } catch (NullPointerException e) {
+ ISOException.throwIt(CardConsts.SW_NullPointerException);
+ } catch (NegativeArraySizeException e) {
+ ISOException.throwIt(CardConsts.SW_NegativeArraySizeException);
+ } catch (CryptoException e) {
+ ISOException.throwIt((short) (CardConsts.SW_CryptoException_prefix | e.getReason()));
+ } catch (SystemException e) {
+ ISOException.throwIt((short) (CardConsts.SW_SystemException_prefix | e.getReason()));
+ } catch (PINException e) {
+ ISOException.throwIt((short) (CardConsts.SW_PINException_prefix | e.getReason()));
+ } catch (TransactionException e) {
+ ISOException.throwIt((short) (CardConsts.SW_TransactionException_prefix | e.getReason()));
+ } catch (CardRuntimeException e) {
+ ISOException.throwIt((short) (CardConsts.SW_CardRuntimeException_prefix | e.getReason()));
+ } catch (Exception e) {
+ ISOException.throwIt(CardConsts.SW_Exception);
+ }
+
+ } else ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
+ }
+
+ private short readAPDU(APDU apdu, boolean skipHeader) {
+ byte[] apduBuffer = apdu.getBuffer();
+
+ /* How much stuff is in apduBuffer */
+ short read = apdu.setIncomingAndReceive();
+ short cdataOffset = getOffsetCdata(apdu);
+ read += cdataOffset;
+
+ /* Where to start reading from? */
+ short offset = 0;
+ if (skipHeader) {
+ offset = cdataOffset;
+ cdata = CardConsts.CDATA_EXTENDED;
+ } else {
+ cdata = CardConsts.CDATA_BASIC;
+ }
+
+ /* How much stuff was really sent in this APDU? */
+ short total = (short) (getIncomingLength(apdu) + cdataOffset);
+ short todo = (short) (total - offset);
+ /* Can we fit? */
+ if (todo > (short) (apduArray.length - apduEnd)) {
+ return -1;
+ }
+
+ /* How much stuff was copied over. */
+ short written = 0;
+ while (written < todo) {
+ Util.arrayCopyNonAtomic(apduBuffer, offset, apduArray, (short) (apduEnd + written), (short) (read - offset));
+ written += (short) (read - offset);
+ offset = 0;
+ read = apdu.receiveBytes((short) 0);
+ }
+ return written;
+ }
+
+ abstract short getOffsetCdata(APDU apdu);
+
+ abstract short getIncomingLength(APDU apdu);
+
+ abstract short getBase();
+
+ /**
+ * Allocates KeyAgreement object, returns allocate SW.
+ *
+ * @param apdu DATA = byte KeyAgreementType
+ * @return length of response
+ */
+ private short insAllocateKA(APDU apdu) {
+ byte kaType = apduArray[cdata];
+ short sw = keyTester.allocateKA(kaType);
+ Util.setShort(apdu.getBuffer(), (short) 0, sw);
+ return 2;
+ }
+
+ /**
+ * Allocates a Signature object, returns allocate SW.
+ *
+ * @param apdu DATA = byte SignatureType
+ * @return length of response
+ */
+ private short insAllocateSig(APDU apdu) {
+ byte sigType = apduArray[cdata];
+ short sw = keyTester.allocateSig(sigType);
+ Util.setShort(apdu.getBuffer(), (short) 0, sw);
+ return 2;
+ }
+
+ /**
+ * Allocates local and remote keyPairs.
+ * returns allocate SWs
+ *
+ * @param apdu P1 = byte keyPair (KEYPAIR_* | ...)
+ * P2 = byte build
+ * DATA = short keyLength
+ * byte keyClass
+ * @return length of response
+ */
+ private short insAllocate(APDU apdu) {
+ byte keyPair = apduArray[ISO7816.OFFSET_P1];
+ byte build = apduArray[ISO7816.OFFSET_P2];
+ short keyLength = Util.getShort(apduArray, cdata);
+ byte keyClass = apduArray[(short) (cdata + 2)];
+
+ return allocate(keyPair, build, keyLength, keyClass, apdu.getBuffer(), (short) 0);
+ }
+
+ /**
+ * Clears local and remote keyPair's keys {@code .clearKey()}.
+ * returns clearKey SWs
+ *
+ * @param apdu P1 = byte keyPair (KEYPAIR_* | ...)
+ * P2 =
+ * @return length of response
+ */
+ private short insClear(APDU apdu) {
+ byte keyPair = apduArray[ISO7816.OFFSET_P1];
+
+ short len = 0;
+ if ((keyPair & CardConsts.KEYPAIR_LOCAL) != 0) {
+ len += clear(localKeypair, apdu.getBuffer(), (short) 0);
+ }
+ if ((keyPair & CardConsts.KEYPAIR_REMOTE) != 0) {
+ len += clear(remoteKeypair, apdu.getBuffer(), len);
+ }
+
+ return len;
+ }
+
+ /**
+ * Sets curve parameters on local and remote keyPairs.
+ * returns setCurve SWs
+ *
+ * @param apdu P1 = byte keyPair (KEYPAIR_* | ...)
+ * P2 = byte curve (EC_Consts.CURVE_*)
+ * DATA = short params (EC_Consts.PARAMETER_* | ...)
+ * <p>
+ * if curveID = CURVE_EXTERNAL:
+ * [short paramLength, byte[] param],
+ * for all params in params,
+ * in order: field,a,b,g,r,k,w,s
+ * @return length of response
+ */
+ private short insSet(APDU apdu) {
+ byte keyPair = apduArray[ISO7816.OFFSET_P1];
+ byte curve = apduArray[ISO7816.OFFSET_P2];
+ short params = Util.getShort(apduArray, cdata);
+
+ short len = 0;
+
+ if ((keyPair & CardConsts.KEYPAIR_LOCAL) != 0) {
+ len += set(localKeypair, curve, params, apduArray, (short) (cdata + 2), apdu.getBuffer(), (short) 0);
+ }
+ if ((keyPair & CardConsts.KEYPAIR_REMOTE) != 0) {
+ len += set(remoteKeypair, curve, params, apduArray, (short) (cdata + 2), apdu.getBuffer(), len);
+ }
+
+ return len;
+ }
+
+ /**
+ * Transforms curve paramaters of local and remote keyPairs.
+ * returns transformCurve SWs
+ *
+ * @param apdu P1 = byte keyPair (KEYPAIR_* | ...)
+ * P2 = byte key (EC_Consts.KEY_* | ...)
+ * DATA = short params (EC_Consts.PARAMETER_* | ...)
+ * short transformation (EC_Consts.TRANSFORMATION_* || ...)
+ * @return length of response
+ */
+ private short insTransform(APDU apdu) {
+ byte keyPair = apduArray[ISO7816.OFFSET_P1];
+ byte key = apduArray[ISO7816.OFFSET_P2];
+ short params = Util.getShort(apduArray, cdata);
+ short transformation = Util.getShort(apduArray, (short) (cdata + 2));
+
+ short len = 0;
+ if ((keyPair & CardConsts.KEYPAIR_LOCAL) != 0) {
+ len += transform(localKeypair, key, params, transformation, apdu.getBuffer(), (short) 0);
+ }
+
+ if ((keyPair & CardConsts.KEYPAIR_REMOTE) != 0) {
+ len += transform(remoteKeypair, key, params, transformation, apdu.getBuffer(), len);
+ }
+
+ return len;
+ }
+
+ /**
+ * Generates the local and remote keyPairs.
+ * returns generate SWs
+ *
+ * @param apdu P1 = byte keyPair (KEYPAIR_* | ...)
+ * P2 =
+ * @return length of response
+ */
+ private short insGenerate(APDU apdu) {
+ byte keyPair = apduArray[ISO7816.OFFSET_P1];
+
+ short len = 0;
+ if ((keyPair & CardConsts.KEYPAIR_LOCAL) != 0) {
+ len += generate(localKeypair, apdu.getBuffer(), (short) 0);
+ }
+ if ((keyPair & CardConsts.KEYPAIR_REMOTE) != 0) {
+ len += generate(remoteKeypair, apdu.getBuffer(), len);
+ }
+
+ return len;
+ }
+
+ /**
+ * Exports selected key and domain parameters from the selected keyPair and key.
+ *
+ * @param apdu P1 = byte keyPair (KEYPAIR_* | ...)
+ * P2 = byte key (EC_Consts.KEY_* | ...)
+ * DATA = short params
+ * @return length of response
+ */
+ private short insExport(APDU apdu) {
+ byte keyPair = apduArray[ISO7816.OFFSET_P1];
+ byte key = apduArray[ISO7816.OFFSET_P2];
+ short params = Util.getShort(apduArray, cdata);
+
+ short swOffset = 0;
+ short len = (short) (keyPair == CardConsts.KEYPAIR_BOTH ? 4 : 2);
+
+ if ((keyPair & CardConsts.KEYPAIR_LOCAL) != 0) {
+ len += export(localKeypair, key, params, apdu.getBuffer(), swOffset, len);
+ swOffset += 2;
+ }
+ if ((keyPair & CardConsts.KEYPAIR_REMOTE) != 0) {
+ len += export(remoteKeypair, key, params, apdu.getBuffer(), swOffset, len);
+ }
+
+ return len;
+ }
+
+ /**
+ * Performs ECDH, between the pubkey specified in P1(local/remote) and the privkey specified in P2(local/remote).
+ * returns deriveSecret SW, {@code if(export == EXPORT_TRUE)} => short secretlen, byte[] secret
+ *
+ * @param apdu P1 = byte pubkey (KEYPAIR_*)
+ * P2 = byte privkey (KEYPAIR_*)
+ * DATA = byte export (EXPORT_TRUE || EXPORT_FALSE)
+ * short transformation (EC_Consts.TRANSFORMATION_* | ...)
+ * byte type (EC_Consts.KA_* | ...)
+ * @return length of response
+ */
+ private short insECDH(APDU apdu) {
+ byte pubkey = apduArray[ISO7816.OFFSET_P1];
+ byte privkey = apduArray[ISO7816.OFFSET_P2];
+ byte export = apduArray[cdata];
+ short transformation = Util.getShort(apduArray, (short) (cdata + 1));
+ byte type = apduArray[(short) (cdata + 3)];
+
+ return ecdh(pubkey, privkey, export, transformation, type, apdu.getBuffer(), (short) 0);
+ }
+
+ /**
+ * Performs ECDH, directly between the privkey specified in P1(local/remote) and the raw data
+ *
+ * @param apdu P1 = byte privkey (KEYPAIR_*)
+ * P2 = byte export (EXPORT_TRUE || EXPORT_FALSE)
+ * DATA = short transformation (EC_Consts.TRANSFORMATION_* | ...)
+ * byte type (EC_Consts.KA_* | ...)
+ * short length
+ * byte[] pubkey
+ * @return length of response
+ */
+ private short insECDH_direct(APDU apdu) {
+ byte privkey = apduArray[ISO7816.OFFSET_P1];
+ byte export = apduArray[ISO7816.OFFSET_P2];
+ short transformation = Util.getShort(apduArray, cdata);
+ byte type = apduArray[(short) (cdata + 2)];
+ short length = Util.getShort(apduArray, (short) (cdata + 3));
+
+ return ecdh_direct(privkey, export, transformation, type, (short) (cdata + 5), length, apdu.getBuffer(), (short) 0);
+ }
+
+ /**
+ * Performs ECDSA signature and verification on data provided or random, using the keyPair in P1(local/remote).
+ * returns ecdsa SW, {@code if(export == EXPORT_TRUE)} => short signature_length, byte[] signature
+ *
+ * @param apdu P1 = byte keyPair (KEYPAIR_*)
+ * P2 = byte export (EXPORT_TRUE || EXPORT_FALSE)
+ * DATA = byte sigType
+ * short dataLength (00 = random data generated, !00 = data length)
+ * byte[] data
+ * @return length of response
+ */
+ private short insECDSA(APDU apdu) {
+ byte keyPair = apduArray[ISO7816.OFFSET_P1];
+ byte export = apduArray[ISO7816.OFFSET_P2];
+ byte sigType = apduArray[cdata];
+
+ short len = 0;
+ if ((keyPair & CardConsts.KEYPAIR_LOCAL) != 0) {
+ len += ecdsa(localKeypair, sigType, export, apduArray, (short) (cdata + 1), apdu.getBuffer(), (short) 0);
+ }
+ if ((keyPair & CardConsts.KEYPAIR_REMOTE) != 0) {
+ len += ecdsa(remoteKeypair, sigType, export, apduArray, (short) (cdata + 1), apdu.getBuffer(), len);
+ }
+
+ return len;
+ }
+
+ /**
+ * @param apdu P1 = byte keyPair (KEYPAIR_*)
+ * P2 = byte export (EXPORT_TRUE || EXPORT_FALSE)
+ * DATA = byte sigType
+ * short dataLength (00 = random data generated, !00 = data length)
+ * byte[] data
+ * @return length of response
+ */
+ private short insECDSA_sign(APDU apdu) {
+ byte keyPair = apduArray[ISO7816.OFFSET_P1];
+ byte export = apduArray[ISO7816.OFFSET_P2];
+ byte sigType = apduArray[cdata];
+
+ short len = 0;
+ if ((keyPair & CardConsts.KEYPAIR_LOCAL) != 0) {
+ len += ecdsa_sign(localKeypair, sigType, export, apduArray, (short) (cdata + 1), apdu.getBuffer(), (short) 0);
+ }
+ if ((keyPair & CardConsts.KEYPAIR_REMOTE) != 0) {
+ len += ecdsa_sign(remoteKeypair, sigType, export, apduArray, (short) (cdata + 1), apdu.getBuffer(), len);
+ }
+ return len;
+ }
+
+ /**
+ * @param apdu P1 = byte keyPair (KEYPAIR_*)
+ * P2 = byte sigType
+ * DATA = short dataLength (00 = random data generated, !00 = data length)
+ * byte[] data
+ * short sigLength
+ * byte[] signature
+ * @return length of response
+ */
+ private short insECDSA_verify(APDU apdu) {
+ byte keyPair = apduArray[ISO7816.OFFSET_P1];
+ byte sigType = apduArray[ISO7816.OFFSET_P2];
+
+ short len = 0;
+ if ((keyPair & CardConsts.KEYPAIR_LOCAL) != 0) {
+ len += ecdsa_verify(localKeypair, sigType, apduArray, cdata, apdu.getBuffer(), (short) 0);
+ }
+ if ((keyPair & CardConsts.KEYPAIR_REMOTE) != 0) {
+ len += ecdsa_verify(remoteKeypair, sigType, apduArray, cdata, apdu.getBuffer(), len);
+ }
+ return len;
+ }
+
+
+ /**
+ * Performs card memory cleanup via JCSystem.requestObjectDeletion()
+ *
+ * @param apdu no data
+ * @return length of response
+ */
+ private short insCleanup(APDU apdu) {
+ byte[] apdubuf = apdu.getBuffer();
+
+ return cleanup(apdubuf, (short) 0);
+ }
+
+ /**
+ * Gathers info about the applet and the card environment.
+ *
+ * @param apdu no data
+ * @return length of response
+ */
+ private short insGetInfo(APDU apdu) {
+ byte[] apdubuf = apdu.getBuffer();
+
+ return getInfo(apdubuf, (short) 0);
+ }
+
+ /**
+ * Set the dry run mode of the applet.
+ *
+ * @param apdu P1 = byte mode (MODE_* || ...)
+ * @return length of response
+ */
+ private short insSetDryRunMode(APDU apdu) {
+ byte[] apdubuf = apdu.getBuffer();
+ byte mode = apduArray[ISO7816.OFFSET_P1];
+
+ short len = 0;
+ if (mode == CardConsts.MODE_NORMAL) {
+ len = setDryRunMode(apdubuf, false, (short) 0);
+ }
+ if (mode == CardConsts.MODE_DRY_RUN) {
+ len = setDryRunMode(apdubuf, true, (short) 0);
+ }
+ return len;
+ }
+
+ /**
+ * @param keyPair which keyPair to use, local/remote (KEYPAIR_* | ...)
+ * @param build whether to use KeyBuilder or Keypair alloc
+ * @param keyLength key length to set
+ * @param keyClass key class to allocate
+ * @param outBuffer buffer to write sw to
+ * @param outOffset offset into buffer
+ * @return length of data written to the buffer
+ */
+ private short allocate(byte keyPair, byte build, short keyLength, byte keyClass, byte[] outBuffer, short outOffset) {
+ short length = 0;
+ if ((keyPair & CardConsts.KEYPAIR_LOCAL) != 0) {
+ if ((build & CardConsts.BUILD_KEYPAIR) != 0) {
+ localKeypair = keyGenerator.allocatePair(keyClass, keyLength);
+ if (keyGenerator.getSW() != ISO7816.SW_NO_ERROR && (build & CardConsts.BUILD_KEYBUILDER) != 0) {
+ localKeypair = keyGenerator.constructPair(keyClass, keyLength);
+ }
+ } else if ((build & CardConsts.BUILD_KEYBUILDER) != 0) {
+ localKeypair = keyGenerator.constructPair(keyClass, keyLength);
+ }
+ Util.setShort(outBuffer, outOffset, keyGenerator.getSW());
+ length += 2;
+ }
+
+ if ((keyPair & CardConsts.KEYPAIR_REMOTE) != 0) {
+ if ((build & CardConsts.BUILD_KEYPAIR) != 0) {
+ remoteKeypair = keyGenerator.allocatePair(keyClass, keyLength);
+ if (keyGenerator.getSW() != ISO7816.SW_NO_ERROR && (build & CardConsts.BUILD_KEYBUILDER) != 0) {
+ remoteKeypair = keyGenerator.constructPair(keyClass, keyLength);
+ }
+ } else if ((build & CardConsts.BUILD_KEYBUILDER) != 0) {
+ remoteKeypair = keyGenerator.constructPair(keyClass, keyLength);
+ }
+ Util.setShort(outBuffer, (short) (outOffset + length), keyGenerator.getSW());
+ length += 2;
+ }
+
+ return length;
+ }
+
+ /**
+ * @param keyPair KeyPair to clear
+ * @param outBuffer buffer to write sw to
+ * @param outOffset offset into buffer
+ * @return length of data written to the buffer
+ */
+ private short clear(KeyPair keyPair, byte[] outBuffer, short outOffset) {
+ short sw = keyGenerator.clearPair(keyPair, EC_Consts.KEY_BOTH);
+ Util.setShort(outBuffer, outOffset, sw);
+
+ return 2;
+ }
+
+ /**
+ * @param keyPair KeyPair to set params on
+ * @param curve curve to set (EC_Consts.CURVE_*)
+ * @param params parameters to set (EC_Consts.PARAMETER_* | ...)
+ * @param inBuffer buffer to read params from
+ * @param inOffset input offset in buffer
+ * @param outBuffer buffer to write sw to
+ * @param outOffset output offset in buffer
+ * @return length of data written to the buffer
+ */
+ private short set(KeyPair keyPair, byte curve, short params, byte[] inBuffer, short inOffset, byte[] outBuffer, short outOffset) {
+ short sw = ISO7816.SW_NO_ERROR;
+
+ switch (curve) {
+ case EC_Consts.CURVE_default:
+ //default, dont set anything
+ break;
+ case EC_Consts.CURVE_external:
+ //external
+ sw = keyGenerator.setExternalCurve(keyPair, params, inBuffer, inOffset);
+ break;
+ default:
+ //custom
+ sw = keyGenerator.setCurve(keyPair, curve, params, ramArray, (short) 0);
+ break;
+ }
+
+ Util.setShort(outBuffer, outOffset, sw);
+ return 2;
+ }
+
+ /**
+ * @param keyPair KeyPair to transform
+ * @param key key to transform (EC_Consts.KEY_* | ...)
+ * @param params parameters to transform (EC_Consts.PARAMETER_* | ...)
+ * @param transformation transformation type (EC_Consts.TRANSFORMATION_*)
+ * @param outBuffer buffer to output sw to
+ * @param outOffset output offset in buffer
+ * @return length of data written to the buffer
+ */
+ private short transform(KeyPair keyPair, byte key, short params, short transformation, byte[] outBuffer, short outOffset) {
+ short sw = keyGenerator.transformCurve(keyPair, key, params, transformation, ramArray, (short) 0);
+ Util.setShort(outBuffer, outOffset, sw);
+ return 2;
+ }
+
+ /**
+ * @param keyPair KeyPair to generate
+ * @param outBuffer buffer to output sw to
+ * @param outOffset output offset in buffer
+ * @return length of data written to the buffer
+ */
+ private short generate(KeyPair keyPair, byte[] outBuffer, short outOffset) {
+ short sw = keyGenerator.generatePair(keyPair);
+ Util.setShort(outBuffer, outOffset, sw);
+
+ return 2;
+ }
+
+ /**
+ * @param keyPair KeyPair to export from
+ * @param key which key to export from (EC_Consts.KEY_PUBLIC | EC_Consts.KEY_PRIVATE)
+ * @param params which params to export (EC_Consts.PARAMETER_* | ...)
+ * @param outBuffer buffer to export params to
+ * @param swOffset offset to output sw to buffer
+ * @param outOffset output offset in buffer
+ * @return length of data written to the buffer
+ */
+ private short export(KeyPair keyPair, byte key, short params, byte[] outBuffer, short swOffset, short outOffset) {
+ short length = 0;
+
+ short sw = ISO7816.SW_NO_ERROR;
+ if ((key & EC_Consts.KEY_PUBLIC) != 0) {
+ //export params from public
+ length += keyGenerator.exportParameters(keyPair, EC_Consts.KEY_PUBLIC, params, outBuffer, outOffset);
+ sw = keyGenerator.getSW();
+ }
+ if ((key & EC_Consts.KEY_PRIVATE) != 0 && sw == ISO7816.SW_NO_ERROR) {
+ //export params from private
+ length += keyGenerator.exportParameters(keyPair, EC_Consts.KEY_PRIVATE, params, outBuffer, (short) (outOffset + length));
+ sw = keyGenerator.getSW();
+ }
+ Util.setShort(outBuffer, swOffset, sw);
+
+ return length;
+ }
+
+ /**
+ * @param pubkey keyPair to use for public key, (KEYPAIR_LOCAL || KEYPAIR_REMOTE)
+ * @param privkey keyPair to use for private key, (KEYPAIR_LOCAL || KEYPAIR_REMOTE)
+ * @param export whether to export ECDH secret
+ * @param transformation whether to transform the pubkey before ECDH
+ * @param type KeyAgreement type to test
+ * @param outBuffer buffer to write sw to, and export ECDH secret {@code if(export == EXPORT_TRUE)}
+ * @param outOffset output offset in buffer
+ * @return length of data written to the buffer
+ */
+ private short ecdh(byte pubkey, byte privkey, byte export, short transformation, byte type, byte[] outBuffer, short outOffset) {
+ short length = 0;
+
+ KeyPair pub = ((pubkey & CardConsts.KEYPAIR_LOCAL) != 0) ? localKeypair : remoteKeypair;
+ KeyPair priv = ((privkey & CardConsts.KEYPAIR_LOCAL) != 0) ? localKeypair : remoteKeypair;
+
+ short secretLength = 0;
+ if (keyTester.getKaType() == type) {
+ secretLength = keyTester.testKA(priv, pub, ramArray, (short) 0, ramArray2, (short) 0, transformation);
+ } else {
+ short allocateSW = keyTester.allocateKA(type);
+ if (allocateSW == ISO7816.SW_NO_ERROR) {
+ secretLength = keyTester.testKA(priv, pub, ramArray, (short) 0, ramArray2, (short) 0, transformation);
+ }
+ }
+ Util.setShort(outBuffer, outOffset, keyTester.getSW());
+ length += 2;
+
+ if ((export == CardConsts.EXPORT_TRUE)) {
+ Util.setShort(outBuffer, (short) (outOffset + length), secretLength);
+ length += 2;
+ Util.arrayCopyNonAtomic(ramArray2, (short) 0, outBuffer, (short) (outOffset + length), secretLength);
+ length += secretLength;
+ }
+
+ return length;
+ }
+
+ private short ecdh_direct(byte privkey, byte export, short transformation, byte type, short keyOffset, short keyLength, byte[] outBuffer, short outOffset) {
+ short length = 0;
+
+ KeyPair priv = ((privkey & CardConsts.KEYPAIR_LOCAL) != 0) ? localKeypair : remoteKeypair;
+
+ short secretLength = 0;
+ if (keyTester.getKaType() == type) {
+ secretLength = keyTester.testKA_direct(priv, apduArray, keyOffset, keyLength, ramArray2, (short) 0, transformation);
+ } else {
+ short allocateSW = keyTester.allocateKA(type);
+ if (allocateSW == ISO7816.SW_NO_ERROR) {
+ secretLength = keyTester.testKA_direct(priv, apduArray, keyOffset, keyLength, ramArray2, (short) 0, transformation);
+ }
+ }
+
+ Util.setShort(outBuffer, outOffset, keyTester.getSW());
+ length += 2;
+
+ if ((export == CardConsts.EXPORT_TRUE)) {
+ Util.setShort(outBuffer, (short) (outOffset + length), secretLength);
+ length += 2;
+ Util.arrayCopyNonAtomic(ramArray2, (short) 0, outBuffer, (short) (outOffset + length), secretLength);
+ length += secretLength;
+ }
+ return length;
+ }
+
+ /**
+ * @param sign keyPair to use for signing and verification
+ * @param sigType Signature type to use
+ * @param export whether to export ECDSA signature
+ * @param inBuffer buffer to read dataLength and data to sign from
+ * @param inOffset input offset in buffer
+ * @param outBuffer buffer to write sw to, and export ECDSA signature {@code if(export == EXPORT_TRUE)}
+ * @param outOffset output offset in buffer
+ * @return length of data written to the buffer
+ */
+ private short ecdsa(KeyPair sign, byte sigType, byte export, byte[] inBuffer, short inOffset, byte[] outBuffer, short outOffset) {
+ short length = 0;
+
+ short dataLength = Util.getShort(inBuffer, inOffset);
+ if (dataLength == 0) { //no data to sign
+ //generate random
+ dataLength = 64;
+ randomData.generateData(ramArray, (short) 0, dataLength);
+ } else {
+ Util.arrayCopyNonAtomic(inBuffer, (short) (inOffset + 2), ramArray, (short) 0, dataLength);
+ }
+
+ short signatureLength = 0;
+ if (keyTester.getSigType() == sigType) {
+ signatureLength = keyTester.testECDSA((ECPrivateKey) sign.getPrivate(), (ECPublicKey) sign.getPublic(), ramArray, (short) 0, dataLength, ramArray2, (short) 0);
+ } else {
+ short allocateSW = keyTester.allocateSig(sigType);
+ if (allocateSW == ISO7816.SW_NO_ERROR) {
+ signatureLength = keyTester.testECDSA((ECPrivateKey) sign.getPrivate(), (ECPublicKey) sign.getPublic(), ramArray, (short) 0, dataLength, ramArray2, (short) 0);
+ }
+ }
+ Util.setShort(outBuffer, outOffset, keyTester.getSW());
+ length += 2;
+
+ if (export == CardConsts.EXPORT_TRUE) {
+ Util.setShort(outBuffer, (short) (outOffset + length), signatureLength);
+ length += 2;
+
+ Util.arrayCopyNonAtomic(ramArray2, (short) 0, outBuffer, (short) (outOffset + length), signatureLength);
+ length += signatureLength;
+ }
+
+ return length;
+ }
+
+ private short ecdsa_sign(KeyPair sign, byte sigType, byte export, byte[] inBuffer, short inOffset, byte[] outBuffer, short outOffset) {
+ short length = 0;
+
+ short dataLength = Util.getShort(inBuffer, inOffset);
+ if (dataLength == 0) { //no data to sign
+ //generate random
+ dataLength = 64;
+ randomData.generateData(ramArray, (short) 0, dataLength);
+ } else {
+ Util.arrayCopyNonAtomic(inBuffer, (short) (inOffset + 2), ramArray, (short) 0, dataLength);
+ }
+
+ short signatureLength = 0;
+ if (keyTester.getSigType() == sigType) {
+ signatureLength = keyTester.testECDSA_sign((ECPrivateKey) sign.getPrivate(), ramArray, (short) 0, dataLength, ramArray2, (short) 0);
+ } else {
+ short allocateSW = keyTester.allocateSig(sigType);
+ if (allocateSW == ISO7816.SW_NO_ERROR) {
+ signatureLength = keyTester.testECDSA_sign((ECPrivateKey) sign.getPrivate(), ramArray, (short) 0, dataLength, ramArray2, (short) 0);
+ }
+ }
+ Util.setShort(outBuffer, outOffset, keyTester.getSW());
+ length += 2;
+
+ if (export == CardConsts.EXPORT_TRUE) {
+ Util.setShort(outBuffer, (short) (outOffset + length), signatureLength);
+ length += 2;
+
+ Util.arrayCopyNonAtomic(ramArray2, (short) 0, outBuffer, (short) (outOffset + length), signatureLength);
+ length += signatureLength;
+ }
+
+ return length;
+ }
+
+ private short ecdsa_verify(KeyPair verify, byte sigType, byte[] inBuffer, short inOffset, byte[] outBuffer, short outOffset) {
+ short length = 0;
+
+ short dataLength = Util.getShort(inBuffer, inOffset);
+ short dataOffset = (short) (inOffset + 2);
+ short sigLength = Util.getShort(inBuffer, (short) (dataOffset + dataLength));
+ short sigOffset = (short) (dataOffset + dataLength + 2);
+
+ if (keyTester.getSigType() == sigType) {
+ keyTester.testECDSA_verify((ECPublicKey) verify.getPublic(), inBuffer, dataOffset, dataLength, inBuffer, sigOffset, sigLength);
+ } else {
+ short allocateSW = keyTester.allocateSig(sigType);
+ if (allocateSW == ISO7816.SW_NO_ERROR) {
+ keyTester.testECDSA_verify((ECPublicKey) verify.getPublic(), inBuffer, dataOffset, dataLength, inBuffer, sigOffset, sigLength);
+ }
+ }
+ Util.setShort(outBuffer, outOffset, keyTester.getSW());
+ length += 2;
+
+ return length;
+ }
+
+ /**
+ * @param buffer buffer to write sw to
+ * @param offset output offset in buffer
+ * @return length of data written to the buffer
+ */
+ private short cleanup(byte[] buffer, short offset) {
+ short sw = ISO7816.SW_NO_ERROR;
+ try {
+ if (JCSystem.isObjectDeletionSupported())
+ JCSystem.requestObjectDeletion();
+ } catch (CardRuntimeException crex) {
+ sw = crex.getReason();
+ }
+
+ Util.setShort(buffer, offset, sw);
+ return 2;
+ }
+
+ /**
+ * @param buffer buffer to write sw to
+ * @param offset output offset in buffer
+ * @return length of data written to the buffer
+ */
+ private short getInfo(byte[] buffer, short offset) {
+ short length = 0;
+ Util.setShort(buffer, (short) (offset + length), ISO7816.SW_NO_ERROR);
+ length += 2;
+ Util.setShort(buffer, (short) (offset + length), (short) VERSION.length);
+ length += 2;
+ Util.arrayCopyNonAtomic(VERSION, (short) 0, buffer, (short) (offset + length), (short) (VERSION.length));
+ length += VERSION.length;
+ Util.setShort(buffer, (short) (offset + length), getBase());
+ length += 2;
+ Util.setShort(buffer, (short) (offset + length), JCSystem.getVersion());
+ length += 2;
+ Util.setShort(buffer, (short) (offset + length), (short) (JCSystem.isObjectDeletionSupported() ? 1 : 0));
+ length += 2;
+ Util.setShort(buffer, (short) (offset + length), (short) buffer.length);
+ length += 2;
+ Util.setShort(buffer, (short) (offset + length), (short) ramArray.length);
+ length += 2;
+ Util.setShort(buffer, (short) (offset + length), (short) ramArray2.length);
+ length += 2;
+ Util.setShort(buffer, (short) (offset + length), (short) apduArray.length);
+ length += 2;
+ return length;
+ }
+
+ private short setDryRunMode(byte[] buffer, boolean mode, short offset) {
+ if (keyTester != null) {
+ keyTester.setDryRun(mode);
+ }
+ if (keyGenerator != null) {
+ keyGenerator.setDryRun(mode);
+ }
+ Util.setShort(buffer, offset, ISO7816.SW_NO_ERROR);
+ return 2;
+ }
+}
diff --git a/applet/src/main/java/cz/crcs/ectester/applet/AppletUtil.java b/applet/src/main/java/cz/crcs/ectester/applet/AppletUtil.java
new file mode 100644
index 0000000..c4a6744
--- /dev/null
+++ b/applet/src/main/java/cz/crcs/ectester/applet/AppletUtil.java
@@ -0,0 +1,35 @@
+package cz.crcs.ectester.applet;
+
+import javacard.framework.ISO7816;
+import javacard.framework.ISOException;
+import javacard.security.KeyAgreement;
+import javacard.security.KeyPair;
+import javacard.security.Signature;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class AppletUtil {
+
+ private static short nullCheck(Object obj, short sw) {
+ if (obj == null)
+ ISOException.throwIt(sw);
+ return ISO7816.SW_NO_ERROR;
+ }
+
+ public static short objCheck(Object obj) {
+ return nullCheck(obj, CardConsts.SW_OBJECT_NULL);
+ }
+
+ public static short keypairCheck(KeyPair keyPair) {
+ return nullCheck(keyPair, CardConsts.SW_KEYPAIR_NULL);
+ }
+
+ public static short kaCheck(KeyAgreement keyAgreement) {
+ return nullCheck(keyAgreement, CardConsts.SW_KA_NULL);
+ }
+
+ public static short signCheck(Signature signature) {
+ return nullCheck(signature, CardConsts.SW_SIGNATURE_NULL);
+ }
+}
diff --git a/applet/src/main/java/cz/crcs/ectester/applet/CardConsts.java b/applet/src/main/java/cz/crcs/ectester/applet/CardConsts.java
new file mode 100644
index 0000000..abac8e7
--- /dev/null
+++ b/applet/src/main/java/cz/crcs/ectester/applet/CardConsts.java
@@ -0,0 +1,65 @@
+package cz.crcs.ectester.applet;
+
+public class CardConsts {
+ // MAIN INSTRUCTION CLASS
+ public static final byte CLA_ECTESTERAPPLET = (byte) 0xB0;
+
+ // INSTRUCTIONS
+ public static final byte INS_ALLOCATE = (byte) 0x5a;
+ public static final byte INS_CLEAR = (byte) 0x5b;
+ public static final byte INS_SET = (byte) 0x5c;
+ public static final byte INS_TRANSFORM = (byte) 0x5d;
+ public static final byte INS_GENERATE = (byte) 0x5e;
+ public static final byte INS_EXPORT = (byte) 0x5f;
+ public static final byte INS_ECDH = (byte) 0x70;
+ public static final byte INS_ECDH_DIRECT = (byte) 0x71;
+ public static final byte INS_ECDSA = (byte) 0x72;
+ public static final byte INS_ECDSA_SIGN = (byte) 0x73;
+ public static final byte INS_ECDSA_VERIFY = (byte) 0x74;
+ public static final byte INS_CLEANUP = (byte) 0x75;
+ public static final byte INS_ALLOCATE_KA = (byte) 0x76;
+ public static final byte INS_ALLOCATE_SIG = (byte) 0x77;
+ public static final byte INS_GET_INFO = (byte) 0x78;
+ public static final byte INS_SET_DRY_RUN_MODE = (byte) 0x79;
+ public static final byte INS_BUFFER = (byte) 0x7a;
+ public static final byte INS_PERFORM = (byte) 0x7b;
+
+ // PARAMETERS for P1 and P2
+ public static final byte KEYPAIR_LOCAL = (byte) 0x01;
+ public static final byte KEYPAIR_REMOTE = (byte) 0x02;
+ public static final byte KEYPAIR_BOTH = KEYPAIR_LOCAL | KEYPAIR_REMOTE;
+ public static final byte BUILD_KEYPAIR = (byte) 0x01;
+ public static final byte BUILD_KEYBUILDER = (byte) 0x02;
+ public static final byte EXPORT_TRUE = (byte) 0xff;
+ public static final byte EXPORT_FALSE = (byte) 0x00;
+ public static final byte MODE_NORMAL = (byte) 0xaa;
+ public static final byte MODE_DRY_RUN = (byte) 0xbb;
+
+ // STATUS WORDS
+ public static final short SW_SIG_VERIFY_FAIL = (short) 0x0ee1;
+ public static final short SW_DH_DHC_MISMATCH = (short) 0x0ee2;
+ public static final short SW_KEYPAIR_NULL = (short) 0x0ee3;
+ public static final short SW_KA_NULL = (short) 0x0ee4;
+ public static final short SW_SIGNATURE_NULL = (short) 0x0ee5;
+ public static final short SW_OBJECT_NULL = (short) 0x0ee6;
+ public static final short SW_CANNOT_FIT = (short) 0x0ee7;
+ public static final short SW_Exception = (short) 0xff01;
+ public static final short SW_ArrayIndexOutOfBoundsException = (short) 0xff02;
+ public static final short SW_ArithmeticException = (short) 0xff03;
+ public static final short SW_ArrayStoreException = (short) 0xff04;
+ public static final short SW_NullPointerException = (short) 0xff05;
+ public static final short SW_NegativeArraySizeException = (short) 0xff06;
+ public static final short SW_CryptoException_prefix = (short) 0xf100;
+ public static final short SW_SystemException_prefix = (short) 0xf200;
+ public static final short SW_PINException_prefix = (short) 0xf300;
+ public static final short SW_TransactionException_prefix = (short) 0xf400;
+ public static final short SW_CardRuntimeException_prefix = (short) 0xf500;
+
+ //
+ public static final short BASE_221 = (short) 0x0221;
+ public static final short BASE_222 = (short) 0x0222;
+
+ //
+ public static final short CDATA_BASIC = (short) 5;
+ public static final short CDATA_EXTENDED = (short) 7;
+}
diff --git a/applet/src/main/java/cz/crcs/ectester/applet/ECKeyGenerator.java b/applet/src/main/java/cz/crcs/ectester/applet/ECKeyGenerator.java
new file mode 100644
index 0000000..601654a
--- /dev/null
+++ b/applet/src/main/java/cz/crcs/ectester/applet/ECKeyGenerator.java
@@ -0,0 +1,526 @@
+package cz.crcs.ectester.applet;
+
+import javacard.framework.CardRuntimeException;
+import javacard.framework.ISO7816;
+import javacard.framework.ISOException;
+import javacard.framework.Util;
+import javacard.security.*;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class ECKeyGenerator {
+
+ private short sw = ISO7816.SW_NO_ERROR;
+ private boolean dryRun = false;
+
+ /**
+ * @param keyClass
+ * @param keyLength
+ * @return
+ */
+ public KeyPair allocatePair(byte keyClass, short keyLength) {
+ sw = ISO7816.SW_NO_ERROR;
+ KeyPair ecKeyPair = null;
+ try {
+ if (!dryRun) {
+ ecKeyPair = new KeyPair(keyClass, keyLength);
+
+ if (ecKeyPair.getPublic() == null || ecKeyPair.getPrivate() == null) {
+ try {
+ ecKeyPair.genKeyPair();
+ } catch (Exception ignored) {
+ }
+ }
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return ecKeyPair;
+ }
+
+ /**
+ * @param keyClass
+ * @param keyLength
+ * @return
+ */
+ public KeyPair constructPair(byte keyClass, short keyLength) {
+ sw = ISO7816.SW_NO_ERROR;
+ KeyPair ecKeyPair = null;
+ byte privKeyType;
+ byte pubKeyType;
+ if (keyClass == KeyPair.ALG_EC_FP) {
+ privKeyType = KeyBuilder.TYPE_EC_FP_PRIVATE;
+ pubKeyType = KeyBuilder.TYPE_EC_FP_PUBLIC;
+ } else {
+ privKeyType = KeyBuilder.TYPE_EC_F2M_PRIVATE;
+ pubKeyType = KeyBuilder.TYPE_EC_F2M_PUBLIC;
+ }
+ try {
+ if (!dryRun) {
+ ECPrivateKey privateKey = (ECPrivateKey) KeyBuilder.buildKey(privKeyType, keyLength, false);
+ ECPublicKey publicKey = (ECPublicKey) KeyBuilder.buildKey(pubKeyType, keyLength, false);
+
+ ecKeyPair = new KeyPair(publicKey, privateKey);
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return ecKeyPair;
+ }
+
+ /**
+ * @param keypair
+ * @param key
+ * @return
+ */
+ public short clearPair(KeyPair keypair, byte key) {
+ try {
+ sw = AppletUtil.keypairCheck(keypair);
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PUBLIC) != 0) keypair.getPublic().clearKey();
+ if ((key & EC_Consts.KEY_PRIVATE) != 0) keypair.getPrivate().clearKey();
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return sw;
+ }
+
+ /**
+ * @param keypair
+ * @return
+ */
+ public short generatePair(KeyPair keypair) {
+ try {
+ sw = AppletUtil.keypairCheck(keypair);
+ if (!dryRun) {
+ keypair.genKeyPair();
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return sw;
+ }
+
+ /**
+ * @param keypair
+ * @param curve
+ * @param buffer
+ * @param offset
+ * @return
+ */
+ public short setCurve(KeyPair keypair, byte curve, byte[] buffer, short offset) {
+ return setCurve(keypair, curve, EC_Consts.PARAMETERS_ALL, buffer, offset);
+ }
+
+ /**
+ * @param keypair
+ * @param curve
+ * @param params
+ * @param buffer
+ * @param offset
+ * @return
+ */
+ public short setCurve(KeyPair keypair, byte curve, short params, byte[] buffer, short offset) {
+ return setCurve(keypair, EC_Consts.KEY_BOTH, curve, params, buffer, offset);
+ }
+
+ /**
+ * @param keypair
+ * @param key
+ * @param curve
+ * @param params
+ * @param buffer
+ * @param offset
+ * @return
+ */
+ public short setCurve(KeyPair keypair, byte key, byte curve, short params, byte[] buffer, short offset) {
+ byte alg = EC_Consts.getCurveType(curve);
+ sw = ISO7816.SW_NO_ERROR;
+
+ if (params == EC_Consts.PARAMETERS_NONE) {
+ return sw;
+ }
+
+ short length;
+ //handle fp and f2m differently, as a FP KeyPair doesnt contain a F2M field and vice versa.
+ if (alg == KeyPair.ALG_EC_FP && (params & EC_Consts.PARAMETER_FP) != 0) {
+ length = EC_Consts.getCurveParameter(curve, EC_Consts.PARAMETER_FP, buffer, offset);
+ sw = setParameter(keypair, key, EC_Consts.PARAMETER_FP, buffer, offset, length);
+ } else if (alg == KeyPair.ALG_EC_F2M && (params & EC_Consts.PARAMETER_F2M) != 0) {
+ length = EC_Consts.getCurveParameter(curve, EC_Consts.PARAMETER_F2M, buffer, offset);
+ sw = setParameter(keypair, key, EC_Consts.PARAMETER_F2M, buffer, offset, length);
+ }
+ if (sw != ISO7816.SW_NO_ERROR) return sw;
+
+ //go through all params
+ short paramMask = EC_Consts.PARAMETER_A;
+ while (paramMask <= EC_Consts.PARAMETER_S) {
+ short masked = (short) (paramMask & params);
+ if (masked != 0) {
+ length = EC_Consts.getCurveParameter(curve, masked, buffer, offset);
+ sw = setParameter(keypair, key, masked, buffer, offset, length);
+ if (sw != ISO7816.SW_NO_ERROR) break;
+ }
+ paramMask = (short) (paramMask << 1);
+ }
+ return sw;
+ }
+
+ /**
+ * @param keypair
+ * @param params
+ * @param transformation
+ * @param buffer
+ * @param offset
+ * @return
+ */
+ public short transformCurve(KeyPair keypair, short params, short transformation, byte[] buffer, short offset) {
+ return transformCurve(keypair, EC_Consts.KEY_BOTH, params, transformation, buffer, offset);
+ }
+
+ /**
+ * @param keypair
+ * @param key
+ * @param params
+ * @param transformation
+ * @param buffer
+ * @param offset
+ * @return
+ */
+ public short transformCurve(KeyPair keypair, byte key, short params, short transformation, byte[] buffer, short offset) {
+ sw = ISO7816.SW_NO_ERROR;
+ if (params == EC_Consts.PARAMETERS_NONE) {
+ return sw;
+ }
+
+ //go through param bit by bit, and invalidate all selected params
+ short paramMask = EC_Consts.PARAMETER_FP;
+ while (paramMask <= EC_Consts.PARAMETER_S) {
+ short masked = (short) (paramMask & params);
+ if (masked != 0) {
+ short length = exportParameter(keypair, key, masked, buffer, offset);
+ length = EC_Consts.transformParameter(transformation, buffer, offset, length);
+ sw = setParameter(keypair, key, masked, buffer, offset, length);
+ if (sw != ISO7816.SW_NO_ERROR) break;
+ }
+ paramMask = (short) (paramMask << 1);
+ }
+ return sw;
+ }
+
+ /**
+ * @param key
+ * @param param
+ * @param data
+ * @param offset
+ * @param length
+ * @return
+ */
+ public short setParameter(KeyPair keypair, byte key, short param, byte[] data, short offset, short length) {
+ try {
+ sw = AppletUtil.keypairCheck(keypair);
+
+ ECPublicKey ecPublicKey = null;
+ ECPrivateKey ecPrivateKey = null;
+ if (!dryRun) {
+ ecPublicKey = (ECPublicKey) keypair.getPublic();
+ ecPrivateKey = (ECPrivateKey) keypair.getPrivate();
+ }
+
+ switch (param) {
+ case EC_Consts.PARAMETER_FP:
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setFieldFP(data, offset, length);
+ if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setFieldFP(data, offset, length);
+ }
+ break;
+ case EC_Consts.PARAMETER_F2M:
+ if (length == 4) {
+ short i = Util.getShort(data, (short) (offset + 2));
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setFieldF2M(i);
+ if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setFieldF2M(i);
+ }
+ } else if (length == 8) {
+ short i1 = Util.getShort(data, (short) (offset + 2));
+ short i2 = Util.getShort(data, (short) (offset + 4));
+ short i3 = Util.getShort(data, (short) (offset + 6));
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setFieldF2M(i1, i2, i3);
+ if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setFieldF2M(i1, i2, i3);
+ }
+ // if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setFieldF2M(i3, i2, i1);
+ // if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setFieldF2M(i3, i2, i1);
+ } else {
+ sw = ISO7816.SW_UNKNOWN;
+ }
+ break;
+ case EC_Consts.PARAMETER_A:
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setA(data, offset, length);
+ if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setA(data, offset, length);
+ }
+ break;
+ case EC_Consts.PARAMETER_B:
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setB(data, offset, length);
+ if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setB(data, offset, length);
+ }
+ break;
+ case EC_Consts.PARAMETER_G:
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setG(data, offset, length);
+ if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setG(data, offset, length);
+ }
+ break;
+ case EC_Consts.PARAMETER_R:
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setR(data, offset, length);
+ if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setR(data, offset, length);
+ }
+ break;
+ case EC_Consts.PARAMETER_K:
+ short k = 0;
+ if (length > 2 || length <= 0) {
+ sw = ISO7816.SW_UNKNOWN;
+ break;
+ } else if (length == 2) {
+ k = Util.getShort(data, offset);
+ } else if (length == 1) {
+ k = data[offset];
+ }
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setK(k);
+ if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setK(k);
+ }
+ break;
+ case EC_Consts.PARAMETER_S:
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setS(data, offset, length);
+ }
+ break;
+ case EC_Consts.PARAMETER_W:
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setW(data, offset, length);
+ }
+ break;
+ default:
+ ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return sw;
+ }
+
+ /**
+ * @param keypair
+ * @param params
+ * @param inBuffer
+ * @param inOffset
+ * @return
+ */
+ public short setExternalCurve(KeyPair keypair, short params, byte[] inBuffer, short inOffset) {
+ return setExternalCurve(keypair, EC_Consts.KEY_BOTH, params, inBuffer, inOffset);
+ }
+
+ /**
+ * @param keypair
+ * @param key
+ * @param params
+ * @param inBuffer
+ * @param inOffset
+ * @return
+ */
+ public short setExternalCurve(KeyPair keypair, byte key, short params, byte[] inBuffer, short inOffset) {
+ sw = ISO7816.SW_NO_ERROR;
+ if (params == EC_Consts.PARAMETERS_NONE) {
+ return sw;
+ }
+
+ short paramMask = EC_Consts.PARAMETER_FP;
+ while (paramMask <= EC_Consts.PARAMETER_S) {
+ short masked = (short) (paramMask & params);
+ if (masked != 0) {
+ short paramLength = Util.getShort(inBuffer, inOffset);
+ inOffset += 2;
+ sw = setParameter(keypair, key, masked, inBuffer, inOffset, paramLength);
+ inOffset += paramLength;
+ if (sw != ISO7816.SW_NO_ERROR) break;
+ }
+ paramMask = (short) (paramMask << 1);
+ }
+ return sw;
+ }
+
+ /**
+ * Exports a selected parameter from a given keyPairs key.
+ *
+ * @param keypair keypair to export from
+ * @param key key to export from (KEY_PUBLIC || KEY_PRIVATE)
+ * @param param parameter to export (EC_Consts.PARAMETER_* || ...)
+ * @param outputBuffer buffer to write to
+ * @param outputOffset offset to start writing in buffer
+ * @return length of data written
+ */
+ public short exportParameter(KeyPair keypair, byte key, short param, byte[] outputBuffer, short outputOffset) {
+ short length = 0;
+ try {
+ sw = AppletUtil.keypairCheck(keypair);
+
+ ECPublicKey ecPublicKey = null;
+ ECPrivateKey ecPrivateKey = null;
+ if (!dryRun) {
+ ecPublicKey = (ECPublicKey) keypair.getPublic();
+ ecPrivateKey = (ECPrivateKey) keypair.getPrivate();
+ }
+
+ switch (param) {
+ case EC_Consts.PARAMETER_FP:
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PUBLIC) != 0)
+ length = ecPublicKey.getField(outputBuffer, outputOffset);
+ if ((key & EC_Consts.KEY_PRIVATE) != 0)
+ length = ecPrivateKey.getField(outputBuffer, outputOffset);
+ }
+ break;
+ case EC_Consts.PARAMETER_F2M:
+ if ((key & EC_Consts.KEY_PUBLIC) != 0 && !dryRun) {
+ Util.setShort(outputBuffer, outputOffset, ecPublicKey.getSize());
+ length = 2;
+ length += ecPublicKey.getField(outputBuffer, (short) (outputOffset + 2));
+ }
+ if ((key & EC_Consts.KEY_PRIVATE) != 0 && !dryRun) {
+ Util.setShort(outputBuffer, outputOffset, ecPrivateKey.getSize());
+ length = 2;
+ length += ecPrivateKey.getField(outputBuffer, (short) (outputOffset + 2));
+ }
+ break;
+ case EC_Consts.PARAMETER_A:
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PUBLIC) != 0) length = ecPublicKey.getA(outputBuffer, outputOffset);
+ if ((key & EC_Consts.KEY_PRIVATE) != 0) length = ecPrivateKey.getA(outputBuffer, outputOffset);
+ }
+ break;
+ case EC_Consts.PARAMETER_B:
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PUBLIC) != 0) length = ecPublicKey.getB(outputBuffer, outputOffset);
+ if ((key & EC_Consts.KEY_PRIVATE) != 0) length = ecPrivateKey.getB(outputBuffer, outputOffset);
+ }
+ break;
+ case EC_Consts.PARAMETER_G:
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PUBLIC) != 0) length = ecPublicKey.getG(outputBuffer, outputOffset);
+ if ((key & EC_Consts.KEY_PRIVATE) != 0) length = ecPrivateKey.getG(outputBuffer, outputOffset);
+ }
+ break;
+ case EC_Consts.PARAMETER_R:
+ if (!dryRun) {
+ if ((key & EC_Consts.KEY_PUBLIC) != 0) length = ecPublicKey.getR(outputBuffer, outputOffset);
+ if ((key & EC_Consts.KEY_PRIVATE) != 0) length = ecPrivateKey.getR(outputBuffer, outputOffset);
+ }
+ break;
+ case EC_Consts.PARAMETER_K:
+ if (!dryRun) {
+ length = 2;
+ if ((key & EC_Consts.KEY_PUBLIC) != 0)
+ Util.setShort(outputBuffer, outputOffset, ecPublicKey.getK());
+ if ((key & EC_Consts.KEY_PRIVATE) != 0)
+ Util.setShort(outputBuffer, outputOffset, ecPrivateKey.getK());
+ }
+ break;
+ case EC_Consts.PARAMETER_W:
+ if ((key & EC_Consts.KEY_PUBLIC) != 0 && !dryRun)
+ length = ecPublicKey.getW(outputBuffer, outputOffset);
+ break;
+ case EC_Consts.PARAMETER_S:
+ if ((key & EC_Consts.KEY_PRIVATE) != 0 && !dryRun)
+ length = ecPrivateKey.getS(outputBuffer, outputOffset);
+ break;
+ default:
+ ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return length;
+ }
+
+ /**
+ * Exports selected parameters from a given keyPairs key.
+ * Raw parameter data is always prepended by its length as a
+ * short value. The order of parameters is the usual one from
+ * EC_Consts: field,a,b,g,r,k,w,s.
+ *
+ * @param keypair keyPair to export from
+ * @param key key to export from (KEY_PUBLIC || KEY_PRIVATE)
+ * @param params params to export (EC_Consts.PARAMETER_* | ...)
+ * @param buffer buffer to export to
+ * @param offset offset to start writing in buffer
+ * @return length of data written
+ */
+ public short exportParameters(KeyPair keypair, byte key, short params, byte[] buffer, short offset) {
+ sw = ISO7816.SW_NO_ERROR;
+ if (params == EC_Consts.PARAMETERS_NONE) {
+ return sw;
+ }
+
+ short length = 0;
+ short paramMask = EC_Consts.PARAMETER_FP;
+ while (paramMask <= EC_Consts.PARAMETER_S) {
+ short masked = (short) (paramMask & params);
+ if (masked != 0) {
+ short len = exportParameter(keypair, key, masked, buffer, (short) (offset + 2));
+ if (len == 0) {
+ paramMask = (short) (paramMask << 1);
+ continue;
+ }
+ Util.setShort(buffer, offset, len);
+ offset += len + 2;
+ length += len + 2;
+ }
+ paramMask = (short) (paramMask << 1);
+ }
+ return length;
+ }
+
+ /**
+ * Copies this KeyPairs curve parameters to another ECKeyGenerator.
+ *
+ * @param from keyPair to copy from
+ * @param to keyPair to copy to
+ * @param params parameters to copy
+ * @param buffer buffer to use for copying
+ * @param offset offset to use in buffer
+ * @return sw
+ */
+ public short copyCurve(KeyPair from, KeyPair to, short params, byte[] buffer, short offset) {
+ try {
+ sw = AppletUtil.keypairCheck(from);
+ sw = AppletUtil.keypairCheck(to);
+
+ short param = EC_Consts.PARAMETER_FP;
+ while (param <= EC_Consts.PARAMETER_K) {
+ short masked = (short) (param & params);
+ if (masked != 0) {
+ short paramLength = exportParameter(from, EC_Consts.KEY_PUBLIC, masked, buffer, offset);
+ setParameter(to, EC_Consts.KEY_BOTH, masked, buffer, offset, paramLength);
+ }
+ param = (short) (param << 1);
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return sw;
+ }
+
+ public short getSW() {
+ return sw;
+ }
+
+ public void setDryRun(boolean dryRun) {
+ this.dryRun = dryRun;
+ }
+}
diff --git a/applet/src/main/java/cz/crcs/ectester/applet/ECKeyTester.java b/applet/src/main/java/cz/crcs/ectester/applet/ECKeyTester.java
new file mode 100644
index 0000000..3af1cca
--- /dev/null
+++ b/applet/src/main/java/cz/crcs/ectester/applet/ECKeyTester.java
@@ -0,0 +1,225 @@
+package cz.crcs.ectester.applet;
+
+
+import javacard.framework.CardRuntimeException;
+import javacard.framework.ISO7816;
+import javacard.security.*;
+
+/**
+ * Class capable of testing ECDH/C and ECDSA.
+ * Note that ECDH and ECDHC output should equal, only the algorithm is different.
+ *
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class ECKeyTester {
+ private KeyAgreement ecKeyAgreement = null;
+ private short kaType = 0;
+ private Signature ecdsaSignature = null;
+ private short sigType = 0;
+
+ private short sw = ISO7816.SW_NO_ERROR;
+ private boolean dryRun = false;
+
+ public short allocateKA(byte algorithm) {
+ sw = ISO7816.SW_NO_ERROR;
+ try {
+ if (!dryRun) {
+ ecKeyAgreement = KeyAgreement.getInstance(algorithm, false);
+ kaType = algorithm;
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return sw;
+ }
+
+ public short allocateSig(byte algorithm) {
+ sw = ISO7816.SW_NO_ERROR;
+ try {
+ if (!dryRun) {
+ ecdsaSignature = Signature.getInstance(algorithm, false);
+ sigType = algorithm;
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return sw;
+ }
+
+ /**
+ * Tests ECDH secret generation with keys from given {@code privatePair} and {@code publicPair}.
+ * Uses {@code pubkeyBuffer} at {@code pubkeyOffset} for computations.
+ * Output should equal with ECDHC output.
+ *
+ * @param privatePair KeyPair from which the private key is used
+ * @param publicPair KeyPair from which the public key is used
+ * @param pubkeyBuffer buffer to be used for the public key
+ * @param pubkeyOffset offset into pubkeyBuffer that can be used for the public key
+ * @param outputBuffer buffer to be used for the secret output
+ * @param outputOffset offset into the outputBuffer
+ * @param transformation (EC_Consts.TRANSFORMATION_* | ...)
+ * @return derived secret length
+ **/
+ public short testKA(KeyPair privatePair, KeyPair publicPair, byte[] pubkeyBuffer, short pubkeyOffset, byte[] outputBuffer, short outputOffset, short transformation) {
+ short length = 0;
+ try {
+ sw = AppletUtil.kaCheck(ecKeyAgreement);
+ sw = AppletUtil.keypairCheck(privatePair);
+ sw = AppletUtil.keypairCheck(publicPair);
+ if (!dryRun) {
+ short pubkeyLength = ((ECPublicKey) publicPair.getPublic()).getW(pubkeyBuffer, pubkeyOffset);
+ ecKeyAgreement.init(privatePair.getPrivate());
+
+ pubkeyLength = EC_Consts.transformParameter(transformation, pubkeyBuffer, pubkeyOffset, pubkeyLength);
+ length = ecKeyAgreement.generateSecret(pubkeyBuffer, pubkeyOffset, pubkeyLength, outputBuffer, outputOffset);
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return length;
+ }
+
+ /**
+ * @param privatePair
+ * @param pubkey
+ * @param pubkeyOffset
+ * @param pubkeyLength
+ * @param outpuBuffer
+ * @param outputOffset
+ * @param transformation
+ * @return
+ */
+ public short testKA_direct(KeyPair privatePair, byte[] pubkey, short pubkeyOffset, short pubkeyLength, byte[] outpuBuffer, short outputOffset, short transformation) {
+ short length = 0;
+ try {
+ sw = AppletUtil.kaCheck(ecKeyAgreement);
+ sw = AppletUtil.keypairCheck(privatePair);
+
+ if (!dryRun) {
+ ecKeyAgreement.init(privatePair.getPrivate());
+ pubkeyLength = EC_Consts.transformParameter(transformation, pubkey, pubkeyOffset, pubkeyLength);
+ length = ecKeyAgreement.generateSecret(pubkey, pubkeyOffset, pubkeyLength, outpuBuffer, outputOffset);
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return length;
+ }
+
+ /**
+ * Uses {@code signKey} to sign data from {@code inputBuffer} at {@code inputOffset} with {@code inputOffset}.
+ * Then checks for correct signature length.
+ * Then tries verifying the data with {@code verifyKey}.
+ *
+ * @param signKey key to use for signing
+ * @param verifyKey key to use for verifying the signature
+ * @param inputBuffer buffer to sign data from
+ * @param inputOffset offset into inputBuffer to sign data from
+ * @param inputLength length of data to sign
+ * @param sigBuffer buffer to output signature to
+ * @param sigOffset offset into sigBuffer to output to
+ * @return signature length
+ */
+ public short testECDSA(ECPrivateKey signKey, ECPublicKey verifyKey, byte[] inputBuffer, short inputOffset, short inputLength, byte[] sigBuffer, short sigOffset) {
+ short length = 0;
+ try {
+ sw = AppletUtil.signCheck(ecdsaSignature);
+
+ if (!dryRun) {
+ ecdsaSignature.init(signKey, Signature.MODE_SIGN);
+ length = ecdsaSignature.sign(inputBuffer, inputOffset, inputLength, sigBuffer, sigOffset);
+
+ ecdsaSignature.init(verifyKey, Signature.MODE_VERIFY);
+ if (!ecdsaSignature.verify(inputBuffer, inputOffset, inputLength, sigBuffer, sigOffset, length)) {
+ sw = CardConsts.SW_SIG_VERIFY_FAIL;
+ }
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return length;
+ }
+
+ /**
+ * @param signKey
+ * @param inputBuffer
+ * @param inputOffset
+ * @param inputLength
+ * @param sigBuffer
+ * @param sigOffset
+ * @return
+ */
+ public short testECDSA_sign(ECPrivateKey signKey, byte[] inputBuffer, short inputOffset, short inputLength, byte[] sigBuffer, short sigOffset) {
+ short length = 0;
+ try {
+ sw = AppletUtil.signCheck(ecdsaSignature);
+
+ if (!dryRun) {
+ ecdsaSignature.init(signKey, Signature.MODE_SIGN);
+ length = ecdsaSignature.sign(inputBuffer, inputOffset, inputLength, sigBuffer, sigOffset);
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return length;
+ }
+
+ /**
+ * @param verifyKey
+ * @param inputBuffer
+ * @param inputOffset
+ * @param inputLength
+ * @param sigBuffer
+ * @param sigOffset
+ * @param sigLength
+ * @return
+ */
+ public short testECDSA_verify(ECPublicKey verifyKey, byte[] inputBuffer, short inputOffset, short inputLength, byte[] sigBuffer, short sigOffset, short sigLength) {
+ short length = 0;
+ try {
+ sw = AppletUtil.signCheck(ecdsaSignature);
+
+ if (!dryRun) {
+ ecdsaSignature.init(verifyKey, Signature.MODE_VERIFY);
+ if (!ecdsaSignature.verify(inputBuffer, inputOffset, inputLength, sigBuffer, sigOffset, sigLength)) {
+ sw = CardConsts.SW_SIG_VERIFY_FAIL;
+ }
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return length;
+ }
+
+ public KeyAgreement getKA() {
+ return ecKeyAgreement;
+ }
+
+ public Signature getSig() {
+ return ecdsaSignature;
+ }
+
+ public boolean hasKA() {
+ return ecKeyAgreement != null;
+ }
+
+ public boolean hasSig() {
+ return ecdsaSignature != null;
+ }
+
+ public short getKaType() {
+ return kaType;
+ }
+
+ public short getSigType() {
+ return sigType;
+ }
+
+ public short getSW() {
+ return sw;
+ }
+
+ public void setDryRun(boolean dryRun) {
+ this.dryRun = dryRun;
+ }
+}
diff --git a/applet/src/main/java/cz/crcs/ectester/applet/ECTesterApplet.java b/applet/src/main/java/cz/crcs/ectester/applet/ECTesterApplet.java
new file mode 100644
index 0000000..8eabd54
--- /dev/null
+++ b/applet/src/main/java/cz/crcs/ectester/applet/ECTesterApplet.java
@@ -0,0 +1,63 @@
+/*
+ * ECTester, tool for testing Elliptic curve cryptography implementations.
+ * Copyright (c) 2016-2019 Petr Svenda <petr@svenda.com>
+ * Copyright (c) 2016-2019 Jan Jancar <johny@neuromancer.sk>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+/*
+ * PACKAGEID: 4543546573746572
+ * APPLETID: 454354657374657230333362 // VERSION v0.3.3
+ */
+package cz.crcs.ectester.applet;
+
+import javacard.framework.APDU;
+import javacard.framework.ISO7816;
+import javacard.framework.ISOException;
+
+/**
+ * Applet part of ECTester, a tool for testing Elliptic curve support on javacards.
+ *
+ * @author Petr Svenda petr@svenda.com
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class ECTesterApplet extends AppletBase {
+ protected ECTesterApplet(byte[] buffer, short offset, byte length) {
+ super(buffer, offset, length);
+ register();
+ }
+
+ public static void install(byte[] bArray, short bOffset, byte bLength) throws ISOException {
+ // applet instance creation
+ new ECTesterApplet(bArray, bOffset, bLength);
+ }
+
+ short getOffsetCdata(APDU apdu) {
+ return ISO7816.OFFSET_CDATA;
+ }
+
+ short getIncomingLength(APDU apdu) {
+ byte[] apduBuffer = apdu.getBuffer();
+ return (short) (0xff & apduBuffer[ISO7816.OFFSET_LC]);
+ }
+
+ short getBase() {
+ return CardConsts.BASE_221;
+ }
+}
diff --git a/applet/src/main/java/cz/crcs/ectester/applet/ECTesterAppletExtended.java b/applet/src/main/java/cz/crcs/ectester/applet/ECTesterAppletExtended.java
new file mode 100644
index 0000000..8ab5520
--- /dev/null
+++ b/applet/src/main/java/cz/crcs/ectester/applet/ECTesterAppletExtended.java
@@ -0,0 +1,64 @@
+/*
+ * ECTester, tool for testing Elliptic curve cryptography implementations.
+ * Copyright (c) 2016-2019 Petr Svenda <petr@svenda.com>
+ * Copyright (c) 2016-2019 Jan Jancar <johny@neuromancer.sk>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+/*
+ * PACKAGEID: 4543546573746572
+ * APPLETID: 454354657374657230333378 // VERSION v0.3.3
+ */
+package cz.crcs.ectester.applet;
+
+import javacard.framework.APDU;
+import javacard.framework.CardRuntimeException;
+import javacard.framework.ISO7816;
+import javacard.framework.ISOException;
+import javacardx.apdu.ExtendedLength;
+
+/**
+ * Applet part of ECTester, a tool for testing Elliptic curve support on javacards.
+ *
+ * @author Petr Svenda petr@svenda.com
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class ECTesterAppletExtended extends AppletBase implements ExtendedLength {
+ protected ECTesterAppletExtended(byte[] buffer, short offset, byte length) {
+ super(buffer, offset, length);
+ register();
+ }
+
+ public static void install(byte[] bArray, short bOffset, byte bLength) throws ISOException {
+ // applet instance creation
+ new ECTesterAppletExtended(bArray, bOffset, bLength);
+ }
+
+ short getOffsetCdata(APDU apdu) {
+ return apdu.getOffsetCdata();
+ }
+
+ short getIncomingLength(APDU apdu) {
+ return apdu.getIncomingLength();
+ }
+
+ short getBase() {
+ return CardConsts.BASE_222;
+ }
+}
diff --git a/applet/src/main/java/cz/crcs/ectester/applet/EC_Consts.java b/applet/src/main/java/cz/crcs/ectester/applet/EC_Consts.java
new file mode 100644
index 0000000..81016ac
--- /dev/null
+++ b/applet/src/main/java/cz/crcs/ectester/applet/EC_Consts.java
@@ -0,0 +1,1512 @@
+package cz.crcs.ectester.applet;
+
+import javacard.framework.ISO7816;
+import javacard.framework.ISOException;
+import javacard.framework.Util;
+import javacard.security.KeyPair;
+import javacard.security.RandomData;
+
+/**
+ * @author Petr Svenda petr@svenda.com
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class EC_Consts {
+
+ public static final byte KeyAgreement_ALG_EC_SVDP_DH_KDF = 1;
+ public static final byte KeyAgreement_ALG_EC_SVDP_DHC_KDF = 2;
+ private static byte[] EC_FP_P = null; //p
+ private static byte[] EC_A = null; //a
+ private static byte[] EC_B = null; //b
+ private static byte[] EC_G_X = null; //G[x,y]
+ private static byte[] EC_G_Y = null; //
+ private static byte[] EC_R = null; //n
+ private static short EC_K = 1; //h
+
+ private static byte[] EC_W_X = null; //Pubkey[x,y]
+ private static byte[] EC_W_Y = null;
+ private static byte[] EC_S = null; //Private
+
+ private static byte[] EC_F2M_F2M = null; //[short i1, short i2, short i3], f = x^m + x^i1 + x^i2 + x^i3 + 1
+
+ // EC domain parameter identifiers (bit flags)
+ public static final short PARAMETER_FP = 0x0001;
+ public static final short PARAMETER_F2M = 0x0002;
+
+ public static final short PARAMETER_A = 0x0004;
+ public static final short PARAMETER_B = 0x0008;
+ public static final short PARAMETER_G = 0x0010;
+ public static final short PARAMETER_R = 0x0020;
+ public static final short PARAMETER_K = 0x0040;
+ public static final short PARAMETER_W = 0x0080;
+ public static final short PARAMETER_S = 0x0100;
+
+ public static final short PARAMETERS_NONE = 0x0000;
+ /**
+ * FP,A,B,G,R,K
+ */
+ public static final short PARAMETERS_DOMAIN_FP = 0x007d;
+ /**
+ * F2M,A,B,G,R,K
+ */
+ public static final short PARAMETERS_DOMAIN_F2M = 0x007e;
+ /**
+ * W,S
+ */
+ public static final short PARAMETERS_KEYPAIR = 0x0180;
+ public static final short PARAMETERS_ALL = 0x01ff;
+
+
+ // EC key identifiers
+ public static final byte KEY_PUBLIC = 0x01;
+ public static final byte KEY_PRIVATE = 0x02;
+ public static final byte KEY_BOTH = KEY_PUBLIC | KEY_PRIVATE;
+
+ public static RandomData randomData = null;
+
+ // secp112r1
+ public static final byte[] EC112_FP_P = new byte[]{
+ (byte) 0xdb, (byte) 0x7c, (byte) 0x2a, (byte) 0xbf,
+ (byte) 0x62, (byte) 0xe3, (byte) 0x5e, (byte) 0x66,
+ (byte) 0x80, (byte) 0x76, (byte) 0xbe, (byte) 0xad,
+ (byte) 0x20, (byte) 0x8b
+ };
+
+ public static final byte[] EC112_FP_A = new byte[]{
+ (byte) 0xdb, (byte) 0x7c, (byte) 0x2a, (byte) 0xbf,
+ (byte) 0x62, (byte) 0xe3, (byte) 0x5e, (byte) 0x66,
+ (byte) 0x80, (byte) 0x76, (byte) 0xbe, (byte) 0xad,
+ (byte) 0x20, (byte) 0x88
+ };
+
+ public static final byte[] EC112_FP_B = new byte[]{
+ (byte) 0x65, (byte) 0x9e, (byte) 0xf8, (byte) 0xba,
+ (byte) 0x04, (byte) 0x39, (byte) 0x16, (byte) 0xee,
+ (byte) 0xde, (byte) 0x89, (byte) 0x11, (byte) 0x70,
+ (byte) 0x2b, (byte) 0x22
+ };
+
+ public static final byte[] EC112_FP_G_X = new byte[]{
+ (byte) 0x09, (byte) 0x48, (byte) 0x72, (byte) 0x39,
+ (byte) 0x99, (byte) 0x5a, (byte) 0x5e, (byte) 0xe7,
+ (byte) 0x6b, (byte) 0x55, (byte) 0xf9, (byte) 0xc2,
+ (byte) 0xf0, (byte) 0x98
+ };
+
+ public static final byte[] EC112_FP_G_Y = new byte[]{
+ (byte) 0xa8, (byte) 0x9c, (byte) 0xe5, (byte) 0xaf,
+ (byte) 0x87, (byte) 0x24, (byte) 0xc0, (byte) 0xa2,
+ (byte) 0x3e, (byte) 0x0e, (byte) 0x0f, (byte) 0xf7,
+ (byte) 0x75, (byte) 0x00
+ };
+
+ public static final byte[] EC112_FP_R = new byte[]{
+ (byte) 0xdb, (byte) 0x7c, (byte) 0x2a, (byte) 0xbf,
+ (byte) 0x62, (byte) 0xe3, (byte) 0x5e, (byte) 0x76,
+ (byte) 0x28, (byte) 0xdf, (byte) 0xac, (byte) 0x65,
+ (byte) 0x61, (byte) 0xc5
+ };
+
+ public static final short EC112_FP_K = 1;
+
+
+ // secp128r1 from http://www.secg.org/sec2-v2.pdf
+ public static final byte[] EC128_FP_P = new byte[]{
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFD,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF
+ };
+
+ public static final byte[] EC128_FP_A = new byte[]{
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFD,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFC
+ };
+
+ public static final byte[] EC128_FP_B = new byte[]{
+ (byte) 0xE8, (byte) 0x75, (byte) 0x79, (byte) 0xC1,
+ (byte) 0x10, (byte) 0x79, (byte) 0xF4, (byte) 0x3D,
+ (byte) 0xD8, (byte) 0x24, (byte) 0x99, (byte) 0x3C,
+ (byte) 0x2C, (byte) 0xEE, (byte) 0x5E, (byte) 0xD3
+ };
+
+ // G in compressed form / first part of ucompressed
+ public static final byte[] EC128_FP_G_X = new byte[]{
+ (byte) 0x16, (byte) 0x1F, (byte) 0xF7, (byte) 0x52,
+ (byte) 0x8B, (byte) 0x89, (byte) 0x9B, (byte) 0x2D,
+ (byte) 0x0C, (byte) 0x28, (byte) 0x60, (byte) 0x7C,
+ (byte) 0xA5, (byte) 0x2C, (byte) 0x5B, (byte) 0x86
+ };
+
+ // second part of G uncompressed
+ public static final byte[] EC128_FP_G_Y = new byte[]{
+ (byte) 0xCF, (byte) 0x5A, (byte) 0xC8, (byte) 0x39,
+ (byte) 0x5B, (byte) 0xAF, (byte) 0xEB, (byte) 0x13,
+ (byte) 0xC0, (byte) 0x2D, (byte) 0xA2, (byte) 0x92,
+ (byte) 0xDD, (byte) 0xED, (byte) 0x7A, (byte) 0x83
+ };
+ // Order of G
+ public static final byte[] EC128_FP_R = new byte[]{
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFE,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x75, (byte) 0xA3, (byte) 0x0D, (byte) 0x1B,
+ (byte) 0x90, (byte) 0x38, (byte) 0xA1, (byte) 0x15
+ };
+ // cofactor of G
+ public static final short EC128_FP_K = 1;
+
+ // secp160r1 from http://www.secg.org/sec2-v2.pdf
+ public static final byte[] EC160_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) 0x7F, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF
+ };
+
+ public static final byte[] EC160_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) 0x7F, (byte) 0xFF, (byte) 0xFF, (byte) 0xFC
+ };
+
+ public static final byte[] EC160_FP_B = new byte[]{
+ (byte) 0x1C, (byte) 0x97, (byte) 0xBE, (byte) 0xFC,
+ (byte) 0x54, (byte) 0xBD, (byte) 0x7A, (byte) 0x8B,
+ (byte) 0x65, (byte) 0xAC, (byte) 0xF8, (byte) 0x9F,
+ (byte) 0x81, (byte) 0xD4, (byte) 0xD4, (byte) 0xAD,
+ (byte) 0xC5, (byte) 0x65, (byte) 0xFA, (byte) 0x45
+ };
+
+ // G in compressed form / first part of ucompressed
+ public static final byte[] EC160_FP_G_X = new byte[]{
+ (byte) 0x4A, (byte) 0x96, (byte) 0xB5, (byte) 0x68,
+ (byte) 0x8E, (byte) 0xF5, (byte) 0x73, (byte) 0x28,
+ (byte) 0x46, (byte) 0x64, (byte) 0x69, (byte) 0x89,
+ (byte) 0x68, (byte) 0xC3, (byte) 0x8B, (byte) 0xB9,
+ (byte) 0x13, (byte) 0xCB, (byte) 0xFC, (byte) 0x82
+ };
+
+ // second part of G uncompressed
+ public static final byte[] EC160_FP_G_Y = new byte[]{
+ (byte) 0x23, (byte) 0xA6, (byte) 0x28, (byte) 0x55,
+ (byte) 0x31, (byte) 0x68, (byte) 0x94, (byte) 0x7D,
+ (byte) 0x59, (byte) 0xDC, (byte) 0xC9, (byte) 0x12,
+ (byte) 0x04, (byte) 0x23, (byte) 0x51, (byte) 0x37,
+ (byte) 0x7A, (byte) 0xC5, (byte) 0xFB, (byte) 0x32
+ };
+ // Order of G
+ public static final byte[] EC160_FP_R = new byte[]{
+ (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x01, (byte) 0xF4, (byte) 0xC8,
+ (byte) 0xF9, (byte) 0x27, (byte) 0xAE, (byte) 0xD3,
+ (byte) 0xCA, (byte) 0x75, (byte) 0x22, (byte) 0x57
+ };
+ // cofactor of G
+ public static final short EC160_FP_K = 1;
+
+
+ // secp192r1 from http://www.secg.org/sec2-v2.pdf
+ public static final byte[] EC192_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) 0xFE,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF
+ };
+ public static final byte[] EC192_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) 0xFE,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFC
+ };
+ public static final byte[] EC192_FP_B = new byte[]{
+ (byte) 0x64, (byte) 0x21, (byte) 0x05, (byte) 0x19,
+ (byte) 0xE5, (byte) 0x9C, (byte) 0x80, (byte) 0xE7,
+ (byte) 0x0F, (byte) 0xA7, (byte) 0xE9, (byte) 0xAB,
+ (byte) 0x72, (byte) 0x24, (byte) 0x30, (byte) 0x49,
+ (byte) 0xFE, (byte) 0xB8, (byte) 0xDE, (byte) 0xEC,
+ (byte) 0xC1, (byte) 0x46, (byte) 0xB9, (byte) 0xB1
+ };
+ // G in compressed form / first part of ucompressed
+ public static final byte[] EC192_FP_G_X = new byte[]{
+ (byte) 0x18, (byte) 0x8D, (byte) 0xA8, (byte) 0x0E,
+ (byte) 0xB0, (byte) 0x30, (byte) 0x90, (byte) 0xF6,
+ (byte) 0x7C, (byte) 0xBF, (byte) 0x20, (byte) 0xEB,
+ (byte) 0x43, (byte) 0xA1, (byte) 0x88, (byte) 0x00,
+ (byte) 0xF4, (byte) 0xFF, (byte) 0x0A, (byte) 0xFD,
+ (byte) 0x82, (byte) 0xFF, (byte) 0x10, (byte) 0x12
+ };
+ // second part of G uncompressed
+ public static final byte[] EC192_FP_G_Y = new byte[]{
+ (byte) 0x07, (byte) 0x19, (byte) 0x2B, (byte) 0x95,
+ (byte) 0xFF, (byte) 0xC8, (byte) 0xDA, (byte) 0x78,
+ (byte) 0x63, (byte) 0x10, (byte) 0x11, (byte) 0xED,
+ (byte) 0x6B, (byte) 0x24, (byte) 0xCD, (byte) 0xD5,
+ (byte) 0x73, (byte) 0xF9, (byte) 0x77, (byte) 0xA1,
+ (byte) 0x1E, (byte) 0x79, (byte) 0x48, (byte) 0x11
+ };
+ // Order of G
+ public static final byte[] EC192_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) 0x99, (byte) 0xDE, (byte) 0xF8, (byte) 0x36,
+ (byte) 0x14, (byte) 0x6B, (byte) 0xC9, (byte) 0xB1,
+ (byte) 0xB4, (byte) 0xD2, (byte) 0x28, (byte) 0x31
+ };
+ // cofactor of G
+ public static final short EC192_FP_K = 1;
+
+ // secp224r1 from http://www.secg.org/sec2-v2.pdf
+ public static final byte[] EC224_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) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01
+ };
+
+ public static final byte[] EC224_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) 0xFE,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFE
+ };
+
+ public static final byte[] EC224_FP_B = new byte[]{
+ (byte) 0xB4, (byte) 0x05, (byte) 0x0A, (byte) 0x85,
+ (byte) 0x0C, (byte) 0x04, (byte) 0xB3, (byte) 0xAB,
+ (byte) 0xF5, (byte) 0x41, (byte) 0x32, (byte) 0x56,
+ (byte) 0x50, (byte) 0x44, (byte) 0xB0, (byte) 0xB7,
+ (byte) 0xD7, (byte) 0xBF, (byte) 0xD8, (byte) 0xBA,
+ (byte) 0x27, (byte) 0x0B, (byte) 0x39, (byte) 0x43,
+ (byte) 0x23, (byte) 0x55, (byte) 0xFF, (byte) 0xB4
+ };
+
+ // G in compressed form / first part of ucompressed
+ public static final byte[] EC224_FP_G_X = new byte[]{
+ (byte) 0xB7, (byte) 0x0E, (byte) 0x0C, (byte) 0xBD,
+ (byte) 0x6B, (byte) 0xB4, (byte) 0xBF, (byte) 0x7F,
+ (byte) 0x32, (byte) 0x13, (byte) 0x90, (byte) 0xB9,
+ (byte) 0x4A, (byte) 0x03, (byte) 0xC1, (byte) 0xD3,
+ (byte) 0x56, (byte) 0xC2, (byte) 0x11, (byte) 0x22,
+ (byte) 0x34, (byte) 0x32, (byte) 0x80, (byte) 0xD6,
+ (byte) 0x11, (byte) 0x5C, (byte) 0x1D, (byte) 0x21
+ };
+ // second part of G uncompressed
+ public static final byte[] EC224_FP_G_Y = new byte[]{
+ (byte) 0xBD, (byte) 0x37, (byte) 0x63, (byte) 0x88,
+ (byte) 0xB5, (byte) 0xF7, (byte) 0x23, (byte) 0xFB,
+ (byte) 0x4C, (byte) 0x22, (byte) 0xDF, (byte) 0xE6,
+ (byte) 0xCD, (byte) 0x43, (byte) 0x75, (byte) 0xA0,
+ (byte) 0x5A, (byte) 0x07, (byte) 0x47, (byte) 0x64,
+ (byte) 0x44, (byte) 0xD5, (byte) 0x81, (byte) 0x99,
+ (byte) 0x85, (byte) 0x00, (byte) 0x7E, (byte) 0x34
+ };
+ // Order of G
+ public static final byte[] EC224_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) 0x16, (byte) 0xA2,
+ (byte) 0xE0, (byte) 0xB8, (byte) 0xF0, (byte) 0x3E,
+ (byte) 0x13, (byte) 0xDD, (byte) 0x29, (byte) 0x45,
+ (byte) 0x5C, (byte) 0x5C, (byte) 0x2A, (byte) 0x3D
+ };
+ // cofactor of G
+ public static final short EC224_FP_K = 1;
+
+ // secp256r1 from http://www.secg.org/sec2-v2.pdf
+ public static final byte[] EC256_FP_P = new byte[]{
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF
+ };
+ public static final byte[] EC256_FP_A = new byte[]{
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFC
+ };
+ public static final byte[] EC256_FP_B = new byte[]{
+ (byte) 0x5A, (byte) 0xC6, (byte) 0x35, (byte) 0xD8,
+ (byte) 0xAA, (byte) 0x3A, (byte) 0x93, (byte) 0xE7,
+ (byte) 0xB3, (byte) 0xEB, (byte) 0xBD, (byte) 0x55,
+ (byte) 0x76, (byte) 0x98, (byte) 0x86, (byte) 0xBC,
+ (byte) 0x65, (byte) 0x1D, (byte) 0x06, (byte) 0xB0,
+ (byte) 0xCC, (byte) 0x53, (byte) 0xB0, (byte) 0xF6,
+ (byte) 0x3B, (byte) 0xCE, (byte) 0x3C, (byte) 0x3E,
+ (byte) 0x27, (byte) 0xD2, (byte) 0x60, (byte) 0x4B
+ };
+ // G in compressed form / first part of ucompressed
+ public static final byte[] EC256_FP_G_X = new byte[]{
+ (byte) 0x6B, (byte) 0x17, (byte) 0xD1, (byte) 0xF2,
+ (byte) 0xE1, (byte) 0x2C, (byte) 0x42, (byte) 0x47,
+ (byte) 0xF8, (byte) 0xBC, (byte) 0xE6, (byte) 0xE5,
+ (byte) 0x63, (byte) 0xA4, (byte) 0x40, (byte) 0xF2,
+ (byte) 0x77, (byte) 0x03, (byte) 0x7D, (byte) 0x81,
+ (byte) 0x2D, (byte) 0xEB, (byte) 0x33, (byte) 0xA0,
+ (byte) 0xF4, (byte) 0xA1, (byte) 0x39, (byte) 0x45,
+ (byte) 0xD8, (byte) 0x98, (byte) 0xC2, (byte) 0x96
+ };
+ // second part of G uncompressed
+ public static final byte[] EC256_FP_G_Y = new byte[]{
+ (byte) 0x4F, (byte) 0xE3, (byte) 0x42, (byte) 0xE2,
+ (byte) 0xFE, (byte) 0x1A, (byte) 0x7F, (byte) 0x9B,
+ (byte) 0x8E, (byte) 0xE7, (byte) 0xEB, (byte) 0x4A,
+ (byte) 0x7C, (byte) 0x0F, (byte) 0x9E, (byte) 0x16,
+ (byte) 0x2B, (byte) 0xCE, (byte) 0x33, (byte) 0x57,
+ (byte) 0x6B, (byte) 0x31, (byte) 0x5E, (byte) 0xCE,
+ (byte) 0xCB, (byte) 0xB6, (byte) 0x40, (byte) 0x68,
+ (byte) 0x37, (byte) 0xBF, (byte) 0x51, (byte) 0xF5
+ };
+ // Order of G
+ public static final byte[] EC256_FP_R = new byte[]{
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xBC, (byte) 0xE6, (byte) 0xFA, (byte) 0xAD,
+ (byte) 0xA7, (byte) 0x17, (byte) 0x9E, (byte) 0x84,
+ (byte) 0xF3, (byte) 0xB9, (byte) 0xCA, (byte) 0xC2,
+ (byte) 0xFC, (byte) 0x63, (byte) 0x25, (byte) 0x51
+ };
+ // cofactor of G
+ public static final short EC256_FP_K = 1;
+
+ // 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) 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) 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;
+
+
+ // secp521r1 from http://www.secg.org/sec2-v2.pdf
+ public static final byte[] EC521_FP_P = new byte[]{
+ (byte) 0x01, (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) 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
+ };
+
+ public static final byte[] EC521_FP_A = new byte[]{
+ (byte) 0x01, (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) 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) 0xFC
+ };
+
+ public static final byte[] EC521_FP_B = new byte[]{
+ (byte) 0x00, (byte) 0x51, (byte) 0x95, (byte) 0x3E,
+ (byte) 0xB9, (byte) 0x61, (byte) 0x8E, (byte) 0x1C,
+ (byte) 0x9A, (byte) 0x1F, (byte) 0x92, (byte) 0x9A,
+ (byte) 0x21, (byte) 0xA0, (byte) 0xB6, (byte) 0x85,
+ (byte) 0x40, (byte) 0xEE, (byte) 0xA2, (byte) 0xDA,
+ (byte) 0x72, (byte) 0x5B, (byte) 0x99, (byte) 0xB3,
+ (byte) 0x15, (byte) 0xF3, (byte) 0xB8, (byte) 0xB4,
+ (byte) 0x89, (byte) 0x91, (byte) 0x8E, (byte) 0xF1,
+ (byte) 0x09, (byte) 0xE1, (byte) 0x56, (byte) 0x19,
+ (byte) 0x39, (byte) 0x51, (byte) 0xEC, (byte) 0x7E,
+ (byte) 0x93, (byte) 0x7B, (byte) 0x16, (byte) 0x52,
+ (byte) 0xC0, (byte) 0xBD, (byte) 0x3B, (byte) 0xB1,
+ (byte) 0xBF, (byte) 0x07, (byte) 0x35, (byte) 0x73,
+ (byte) 0xDF, (byte) 0x88, (byte) 0x3D, (byte) 0x2C,
+ (byte) 0x34, (byte) 0xF1, (byte) 0xEF, (byte) 0x45,
+ (byte) 0x1F, (byte) 0xD4, (byte) 0x6B, (byte) 0x50,
+ (byte) 0x3F, (byte) 0x00
+ };
+
+ // G in compressed form / first part of ucompressed
+ public static final byte[] EC521_FP_G_X = new byte[]{
+ (byte) 0x00, (byte) 0xC6, (byte) 0x85, (byte) 0x8E,
+ (byte) 0x06, (byte) 0xB7, (byte) 0x04, (byte) 0x04,
+ (byte) 0xE9, (byte) 0xCD, (byte) 0x9E, (byte) 0x3E,
+ (byte) 0xCB, (byte) 0x66, (byte) 0x23, (byte) 0x95,
+ (byte) 0xB4, (byte) 0x42, (byte) 0x9C, (byte) 0x64,
+ (byte) 0x81, (byte) 0x39, (byte) 0x05, (byte) 0x3F,
+ (byte) 0xB5, (byte) 0x21, (byte) 0xF8, (byte) 0x28,
+ (byte) 0xAF, (byte) 0x60, (byte) 0x6B, (byte) 0x4D,
+ (byte) 0x3D, (byte) 0xBA, (byte) 0xA1, (byte) 0x4B,
+ (byte) 0x5E, (byte) 0x77, (byte) 0xEF, (byte) 0xE7,
+ (byte) 0x59, (byte) 0x28, (byte) 0xFE, (byte) 0x1D,
+ (byte) 0xC1, (byte) 0x27, (byte) 0xA2, (byte) 0xFF,
+ (byte) 0xA8, (byte) 0xDE, (byte) 0x33, (byte) 0x48,
+ (byte) 0xB3, (byte) 0xC1, (byte) 0x85, (byte) 0x6A,
+ (byte) 0x42, (byte) 0x9B, (byte) 0xF9, (byte) 0x7E,
+ (byte) 0x7E, (byte) 0x31, (byte) 0xC2, (byte) 0xE5,
+ (byte) 0xBD, (byte) 0x66
+ };
+
+ // second part of G uncompressed
+ public static final byte[] EC521_FP_G_Y = new byte[]{
+ (byte) 0x01, (byte) 0x18, (byte) 0x39, (byte) 0x29,
+ (byte) 0x6A, (byte) 0x78, (byte) 0x9A, (byte) 0x3B,
+ (byte) 0xC0, (byte) 0x04, (byte) 0x5C, (byte) 0x8A,
+ (byte) 0x5F, (byte) 0xB4, (byte) 0x2C, (byte) 0x7D,
+ (byte) 0x1B, (byte) 0xD9, (byte) 0x98, (byte) 0xF5,
+ (byte) 0x44, (byte) 0x49, (byte) 0x57, (byte) 0x9B,
+ (byte) 0x44, (byte) 0x68, (byte) 0x17, (byte) 0xAF,
+ (byte) 0xBD, (byte) 0x17, (byte) 0x27, (byte) 0x3E,
+ (byte) 0x66, (byte) 0x2C, (byte) 0x97, (byte) 0xEE,
+ (byte) 0x72, (byte) 0x99, (byte) 0x5E, (byte) 0xF4,
+ (byte) 0x26, (byte) 0x40, (byte) 0xC5, (byte) 0x50,
+ (byte) 0xB9, (byte) 0x01, (byte) 0x3F, (byte) 0xAD,
+ (byte) 0x07, (byte) 0x61, (byte) 0x35, (byte) 0x3C,
+ (byte) 0x70, (byte) 0x86, (byte) 0xA2, (byte) 0x72,
+ (byte) 0xC2, (byte) 0x40, (byte) 0x88, (byte) 0xBE,
+ (byte) 0x94, (byte) 0x76, (byte) 0x9F, (byte) 0xD1,
+ (byte) 0x66, (byte) 0x50
+ };
+
+ // Order of G
+ public static final byte[] EC521_FP_R = new byte[]{
+ (byte) 0x01, (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) 0xFA,
+ (byte) 0x51, (byte) 0x86, (byte) 0x87, (byte) 0x83,
+ (byte) 0xBF, (byte) 0x2F, (byte) 0x96, (byte) 0x6B,
+ (byte) 0x7F, (byte) 0xCC, (byte) 0x01, (byte) 0x48,
+ (byte) 0xF7, (byte) 0x09, (byte) 0xA5, (byte) 0xD0,
+ (byte) 0x3B, (byte) 0xB5, (byte) 0xC9, (byte) 0xB8,
+ (byte) 0x89, (byte) 0x9C, (byte) 0x47, (byte) 0xAE,
+ (byte) 0xBB, (byte) 0x6F, (byte) 0xB7, (byte) 0x1E,
+ (byte) 0x91, (byte) 0x38, (byte) 0x64, (byte) 0x09
+ };
+
+ // cofactor of G
+ public static final short EC521_FP_K = 1;
+
+ //sect163r1 from http://www.secg.org/sec2-v2.pdf
+ // [short i1, short i2, short i3] f = x^163 + x^i1 + x^i2 + x^i3 + 1
+ public static final byte[] EC163_F2M_F = new byte[]{
+ (byte) 0x00, (byte) 0x07,
+ (byte) 0x00, (byte) 0x06,
+ (byte) 0x00, (byte) 0x03
+ };
+
+ public static final byte[] EC163_F2M_A = new byte[]{
+ (byte) 0x07, (byte) 0xB6, (byte) 0x88, (byte) 0x2C,
+ (byte) 0xAA, (byte) 0xEF, (byte) 0xA8, (byte) 0x4F,
+ (byte) 0x95, (byte) 0x54, (byte) 0xFF, (byte) 0x84,
+ (byte) 0x28, (byte) 0xBD, (byte) 0x88, (byte) 0xE2,
+ (byte) 0x46, (byte) 0xD2, (byte) 0x78, (byte) 0x2A,
+ (byte) 0xE2
+ };
+
+ public static final byte[] EC163_F2M_B = new byte[]{
+ (byte) 0x07, (byte) 0x13, (byte) 0x61, (byte) 0x2D,
+ (byte) 0xCD, (byte) 0xDC, (byte) 0xB4, (byte) 0x0A,
+ (byte) 0xAB, (byte) 0x94, (byte) 0x6B, (byte) 0xDA,
+ (byte) 0x29, (byte) 0xCA, (byte) 0x91, (byte) 0xF7,
+ (byte) 0x3A, (byte) 0xF9, (byte) 0x58, (byte) 0xAF,
+ (byte) 0xD9
+ };
+
+ // G in compressed form / first part of ucompressed
+ public static final byte[] EC163_F2M_G_X = new byte[]{
+ (byte) 0x03, (byte) 0x69, (byte) 0x97, (byte) 0x96,
+ (byte) 0x97, (byte) 0xAB, (byte) 0x43, (byte) 0x89,
+ (byte) 0x77, (byte) 0x89, (byte) 0x56, (byte) 0x67,
+ (byte) 0x89, (byte) 0x56, (byte) 0x7F, (byte) 0x78,
+ (byte) 0x7A, (byte) 0x78, (byte) 0x76, (byte) 0xA6,
+ (byte) 0x54
+ };
+
+ // second part of G uncompressed
+ public static final byte[] EC163_F2M_G_Y = new byte[]{
+ (byte) 0x00, (byte) 0x43, (byte) 0x5E, (byte) 0xDB,
+ (byte) 0x42, (byte) 0xEF, (byte) 0xAF, (byte) 0xB2,
+ (byte) 0x98, (byte) 0x9D, (byte) 0x51, (byte) 0xFE,
+ (byte) 0xFC, (byte) 0xE3, (byte) 0xC8, (byte) 0x09,
+ (byte) 0x88, (byte) 0xF4, (byte) 0x1F, (byte) 0xF8,
+ (byte) 0x83
+ };
+
+ // order of G
+ public static final byte[] EC163_F2M_R = new byte[]{
+ (byte) 0x03, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x48,
+ (byte) 0xAA, (byte) 0xB6, (byte) 0x89, (byte) 0xC2,
+ (byte) 0x9C, (byte) 0xA7, (byte) 0x10, (byte) 0x27,
+ (byte) 0x9B
+ };
+
+ // cofactor of G
+ public static final short EC163_F2M_K = 2;
+
+ //sect233r1 from http://www.secg.org/sec2-v2.pdf
+ // [short i1, short i2, short i3] f = x^233 + x^i1 + 1
+ public static final byte[] EC233_F2M_F = new byte[]{
+ (byte) 0x00, (byte) 0x4a
+ };
+
+ public static final byte[] EC233_F2M_A = new byte[]{
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x01
+ };
+
+ public static final byte[] EC233_F2M_B = new byte[]{
+ (byte) 0x00, (byte) 0x66, (byte) 0x64, (byte) 0x7E,
+ (byte) 0xDE, (byte) 0x6C, (byte) 0x33, (byte) 0x2C,
+ (byte) 0x7F, (byte) 0x8C, (byte) 0x09, (byte) 0x23,
+ (byte) 0xBB, (byte) 0x58, (byte) 0x21, (byte) 0x3B,
+ (byte) 0x33, (byte) 0x3B, (byte) 0x20, (byte) 0xE9,
+ (byte) 0xCE, (byte) 0x42, (byte) 0x81, (byte) 0xFE,
+ (byte) 0x11, (byte) 0x5F, (byte) 0x7D, (byte) 0x8F,
+ (byte) 0x90, (byte) 0xAD
+ };
+
+ // G in compressed form / first part of ucompressed
+ public static final byte[] EC233_F2M_G_X = new byte[]{
+ (byte) 0x00, (byte) 0xFA, (byte) 0xC9, (byte) 0xDF,
+ (byte) 0xCB, (byte) 0xAC, (byte) 0x83, (byte) 0x13,
+ (byte) 0xBB, (byte) 0x21, (byte) 0x39, (byte) 0xF1,
+ (byte) 0xBB, (byte) 0x75, (byte) 0x5F, (byte) 0xEF,
+ (byte) 0x65, (byte) 0xBC, (byte) 0x39, (byte) 0x1F,
+ (byte) 0x8B, (byte) 0x36, (byte) 0xF8, (byte) 0xF8,
+ (byte) 0xEB, (byte) 0x73, (byte) 0x71, (byte) 0xFD,
+ (byte) 0x55, (byte) 0x8B
+ };
+
+ // second part of G uncompressed
+ public static final byte[] EC233_F2M_G_Y = new byte[]{
+ (byte) 0x01, (byte) 0x00, (byte) 0x6A, (byte) 0x08,
+ (byte) 0xA4, (byte) 0x19, (byte) 0x03, (byte) 0x35,
+ (byte) 0x06, (byte) 0x78, (byte) 0xE5, (byte) 0x85,
+ (byte) 0x28, (byte) 0xBE, (byte) 0xBF, (byte) 0x8A,
+ (byte) 0x0B, (byte) 0xEF, (byte) 0xF8, (byte) 0x67,
+ (byte) 0xA7, (byte) 0xCA, (byte) 0x36, (byte) 0x71,
+ (byte) 0x6F, (byte) 0x7E, (byte) 0x01, (byte) 0xF8,
+ (byte) 0x10, (byte) 0x52
+ };
+
+ // order of G
+ public static final byte[] EC233_F2M_R = new byte[]{
+ (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x13,
+ (byte) 0xE9, (byte) 0x74, (byte) 0xE7, (byte) 0x2F,
+ (byte) 0x8A, (byte) 0x69, (byte) 0x22, (byte) 0x03,
+ (byte) 0x1D, (byte) 0x26, (byte) 0x03, (byte) 0xCF,
+ (byte) 0xE0, (byte) 0xD7
+ };
+
+ // cofactor of G
+ public static final short EC233_F2M_K = 2;
+
+ //sect283r1 from http://www.secg.org/sec2-v2.pdf
+ // [short i1, short i2, short i3] f = x^283 + x^i1 + x^i2 + x^i3 + 1
+ public static final byte[] EC283_F2M_F = new byte[]{
+ (byte) 0x00, (byte) 0x0c,
+ (byte) 0x00, (byte) 0x07,
+ (byte) 0x00, (byte) 0x05
+ };
+
+ public static final byte[] EC283_F2M_A = new byte[]{
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01
+ };
+
+ public static final byte[] EC283_F2M_B = new byte[]{
+ (byte) 0x02, (byte) 0x7B, (byte) 0x68, (byte) 0x0A,
+ (byte) 0xC8, (byte) 0xB8, (byte) 0x59, (byte) 0x6D,
+ (byte) 0xA5, (byte) 0xA4, (byte) 0xAF, (byte) 0x8A,
+ (byte) 0x19, (byte) 0xA0, (byte) 0x30, (byte) 0x3F,
+ (byte) 0xCA, (byte) 0x97, (byte) 0xFD, (byte) 0x76,
+ (byte) 0x45, (byte) 0x30, (byte) 0x9F, (byte) 0xA2,
+ (byte) 0xA5, (byte) 0x81, (byte) 0x48, (byte) 0x5A,
+ (byte) 0xF6, (byte) 0x26, (byte) 0x3E, (byte) 0x31,
+ (byte) 0x3B, (byte) 0x79, (byte) 0xA2, (byte) 0xF5
+ };
+
+ // G in compressed form / first part of ucompressed
+ public static final byte[] EC283_F2M_G_X = new byte[]{
+ (byte) 0x05, (byte) 0xF9, (byte) 0x39, (byte) 0x25,
+ (byte) 0x8D, (byte) 0xB7, (byte) 0xDD, (byte) 0x90,
+ (byte) 0xE1, (byte) 0x93, (byte) 0x4F, (byte) 0x8C,
+ (byte) 0x70, (byte) 0xB0, (byte) 0xDF, (byte) 0xEC,
+ (byte) 0x2E, (byte) 0xED, (byte) 0x25, (byte) 0xB8,
+ (byte) 0x55, (byte) 0x7E, (byte) 0xAC, (byte) 0x9C,
+ (byte) 0x80, (byte) 0xE2, (byte) 0xE1, (byte) 0x98,
+ (byte) 0xF8, (byte) 0xCD, (byte) 0xBE, (byte) 0xCD,
+ (byte) 0x86, (byte) 0xB1, (byte) 0x20, (byte) 0x53
+ };
+
+ // second part of G uncompressed
+ public static final byte[] EC283_F2M_G_Y = new byte[]{
+ (byte) 0x03, (byte) 0x67, (byte) 0x68, (byte) 0x54,
+ (byte) 0xFE, (byte) 0x24, (byte) 0x14, (byte) 0x1C,
+ (byte) 0xB9, (byte) 0x8F, (byte) 0xE6, (byte) 0xD4,
+ (byte) 0xB2, (byte) 0x0D, (byte) 0x02, (byte) 0xB4,
+ (byte) 0x51, (byte) 0x6F, (byte) 0xF7, (byte) 0x02,
+ (byte) 0x35, (byte) 0x0E, (byte) 0xDD, (byte) 0xB0,
+ (byte) 0x82, (byte) 0x67, (byte) 0x79, (byte) 0xC8,
+ (byte) 0x13, (byte) 0xF0, (byte) 0xDF, (byte) 0x45,
+ (byte) 0xBE, (byte) 0x81, (byte) 0x12, (byte) 0xF4
+ };
+
+ // order of G
+ public static final byte[] EC283_F2M_R = new byte[]{
+ (byte) 0x03, (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) 0xEF, (byte) 0x90,
+ (byte) 0x39, (byte) 0x96, (byte) 0x60, (byte) 0xFC,
+ (byte) 0x93, (byte) 0x8A, (byte) 0x90, (byte) 0x16,
+ (byte) 0x5B, (byte) 0x04, (byte) 0x2A, (byte) 0x7C,
+ (byte) 0xEF, (byte) 0xAD, (byte) 0xB3, (byte) 0x07
+ };
+
+ // cofactor of G
+ public static final short EC283_F2M_K = 2;
+
+ //sect409r1 from http://www.secg.org/sec2-v2.pdf
+ // [short i1, short i2, short i3] f = x^409 + x^i1 + 1
+ public static final byte[] EC409_F2M_F = new byte[]{
+ (byte) 0x00, (byte) 0x57
+ };
+
+ public static final byte[] EC409_F2M_A = new byte[]{
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01
+ };
+
+ public static final byte[] EC409_F2M_B = new byte[]{
+ (byte) 0x00, (byte) 0x21, (byte) 0xA5, (byte) 0xC2,
+ (byte) 0xC8, (byte) 0xEE, (byte) 0x9F, (byte) 0xEB,
+ (byte) 0x5C, (byte) 0x4B, (byte) 0x9A, (byte) 0x75,
+ (byte) 0x3B, (byte) 0x7B, (byte) 0x47, (byte) 0x6B,
+ (byte) 0x7F, (byte) 0xD6, (byte) 0x42, (byte) 0x2E,
+ (byte) 0xF1, (byte) 0xF3, (byte) 0xDD, (byte) 0x67,
+ (byte) 0x47, (byte) 0x61, (byte) 0xFA, (byte) 0x99,
+ (byte) 0xD6, (byte) 0xAC, (byte) 0x27, (byte) 0xC8,
+ (byte) 0xA9, (byte) 0xA1, (byte) 0x97, (byte) 0xB2,
+ (byte) 0x72, (byte) 0x82, (byte) 0x2F, (byte) 0x6C,
+ (byte) 0xD5, (byte) 0x7A, (byte) 0x55, (byte) 0xAA,
+ (byte) 0x4F, (byte) 0x50, (byte) 0xAE, (byte) 0x31,
+ (byte) 0x7B, (byte) 0x13, (byte) 0x54, (byte) 0x5F
+ };
+
+ // G in compressed form / first part of ucompressed
+ public static final byte[] EC409_F2M_G_X = new byte[]{
+ (byte) 0x01, (byte) 0x5D, (byte) 0x48, (byte) 0x60,
+ (byte) 0xD0, (byte) 0x88, (byte) 0xDD, (byte) 0xB3,
+ (byte) 0x49, (byte) 0x6B, (byte) 0x0C, (byte) 0x60,
+ (byte) 0x64, (byte) 0x75, (byte) 0x62, (byte) 0x60,
+ (byte) 0x44, (byte) 0x1C, (byte) 0xDE, (byte) 0x4A,
+ (byte) 0xF1, (byte) 0x77, (byte) 0x1D, (byte) 0x4D,
+ (byte) 0xB0, (byte) 0x1F, (byte) 0xFE, (byte) 0x5B,
+ (byte) 0x34, (byte) 0xE5, (byte) 0x97, (byte) 0x03,
+ (byte) 0xDC, (byte) 0x25, (byte) 0x5A, (byte) 0x86,
+ (byte) 0x8A, (byte) 0x11, (byte) 0x80, (byte) 0x51,
+ (byte) 0x56, (byte) 0x03, (byte) 0xAE, (byte) 0xAB,
+ (byte) 0x60, (byte) 0x79, (byte) 0x4E, (byte) 0x54,
+ (byte) 0xBB, (byte) 0x79, (byte) 0x96, (byte) 0xA7
+ };
+
+ // second part of G uncompressed
+ public static final byte[] EC409_F2M_G_Y = new byte[]{
+ (byte) 0x00, (byte) 0x61, (byte) 0xB1, (byte) 0xCF,
+ (byte) 0xAB, (byte) 0x6B, (byte) 0xE5, (byte) 0xF3,
+ (byte) 0x2B, (byte) 0xBF, (byte) 0xA7, (byte) 0x83,
+ (byte) 0x24, (byte) 0xED, (byte) 0x10, (byte) 0x6A,
+ (byte) 0x76, (byte) 0x36, (byte) 0xB9, (byte) 0xC5,
+ (byte) 0xA7, (byte) 0xBD, (byte) 0x19, (byte) 0x8D,
+ (byte) 0x01, (byte) 0x58, (byte) 0xAA, (byte) 0x4F,
+ (byte) 0x54, (byte) 0x88, (byte) 0xD0, (byte) 0x8F,
+ (byte) 0x38, (byte) 0x51, (byte) 0x4F, (byte) 0x1F,
+ (byte) 0xDF, (byte) 0x4B, (byte) 0x4F, (byte) 0x40,
+ (byte) 0xD2, (byte) 0x18, (byte) 0x1B, (byte) 0x36,
+ (byte) 0x81, (byte) 0xC3, (byte) 0x64, (byte) 0xBA,
+ (byte) 0x02, (byte) 0x73, (byte) 0xC7, (byte) 0x06
+ };
+
+ // order of G
+ public static final byte[] EC409_F2M_R = new byte[]{
+ (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0xE2,
+ (byte) 0xAA, (byte) 0xD6, (byte) 0xA6, (byte) 0x12,
+ (byte) 0xF3, (byte) 0x33, (byte) 0x07, (byte) 0xBE,
+ (byte) 0x5F, (byte) 0xA4, (byte) 0x7C, (byte) 0x3C,
+ (byte) 0x9E, (byte) 0x05, (byte) 0x2F, (byte) 0x83,
+ (byte) 0x81, (byte) 0x64, (byte) 0xCD, (byte) 0x37,
+ (byte) 0xD9, (byte) 0xA2, (byte) 0x11, (byte) 0x73
+ };
+
+ // cofactor of G
+ public static final short EC409_F2M_K = 2;
+
+ //sect571r1 from http://www.secg.org/sec2-v2.pdf
+ // [short i1, short i2, short i3] f = x^571 + x^i1 + x^i2 + x^i3 + 1
+ public static final byte[] EC571_F2M_F = new byte[]{
+ (byte) 0x00, (byte) 0x0a,
+ (byte) 0x00, (byte) 0x05,
+ (byte) 0x00, (byte) 0x02,
+ };
+
+ public static final byte[] EC571_F2M_A = new byte[]{
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01
+ };
+
+ public static final byte[] EC571_F2M_B = new byte[]{
+ (byte) 0x02, (byte) 0xF4, (byte) 0x0E, (byte) 0x7E,
+ (byte) 0x22, (byte) 0x21, (byte) 0xF2, (byte) 0x95,
+ (byte) 0xDE, (byte) 0x29, (byte) 0x71, (byte) 0x17,
+ (byte) 0xB7, (byte) 0xF3, (byte) 0xD6, (byte) 0x2F,
+ (byte) 0x5C, (byte) 0x6A, (byte) 0x97, (byte) 0xFF,
+ (byte) 0xCB, (byte) 0x8C, (byte) 0xEF, (byte) 0xF1,
+ (byte) 0xCD, (byte) 0x6B, (byte) 0xA8, (byte) 0xCE,
+ (byte) 0x4A, (byte) 0x9A, (byte) 0x18, (byte) 0xAD,
+ (byte) 0x84, (byte) 0xFF, (byte) 0xAB, (byte) 0xBD,
+ (byte) 0x8E, (byte) 0xFA, (byte) 0x59, (byte) 0x33,
+ (byte) 0x2B, (byte) 0xE7, (byte) 0xAD, (byte) 0x67,
+ (byte) 0x56, (byte) 0xA6, (byte) 0x6E, (byte) 0x29,
+ (byte) 0x4A, (byte) 0xFD, (byte) 0x18, (byte) 0x5A,
+ (byte) 0x78, (byte) 0xFF, (byte) 0x12, (byte) 0xAA,
+ (byte) 0x52, (byte) 0x0E, (byte) 0x4D, (byte) 0xE7,
+ (byte) 0x39, (byte) 0xBA, (byte) 0xCA, (byte) 0x0C,
+ (byte) 0x7F, (byte) 0xFE, (byte) 0xFF, (byte) 0x7F,
+ (byte) 0x29, (byte) 0x55, (byte) 0x72, (byte) 0x7A
+ };
+
+ // G in compressed form / first part of ucompressed
+ public static final byte[] EC571_F2M_G_X = new byte[]{
+ (byte) 0x03, (byte) 0x03, (byte) 0x00, (byte) 0x1D,
+ (byte) 0x34, (byte) 0xB8, (byte) 0x56, (byte) 0x29,
+ (byte) 0x6C, (byte) 0x16, (byte) 0xC0, (byte) 0xD4,
+ (byte) 0x0D, (byte) 0x3C, (byte) 0xD7, (byte) 0x75,
+ (byte) 0x0A, (byte) 0x93, (byte) 0xD1, (byte) 0xD2,
+ (byte) 0x95, (byte) 0x5F, (byte) 0xA8, (byte) 0x0A,
+ (byte) 0xA5, (byte) 0xF4, (byte) 0x0F, (byte) 0xC8,
+ (byte) 0xDB, (byte) 0x7B, (byte) 0x2A, (byte) 0xBD,
+ (byte) 0xBD, (byte) 0xE5, (byte) 0x39, (byte) 0x50,
+ (byte) 0xF4, (byte) 0xC0, (byte) 0xD2, (byte) 0x93,
+ (byte) 0xCD, (byte) 0xD7, (byte) 0x11, (byte) 0xA3,
+ (byte) 0x5B, (byte) 0x67, (byte) 0xFB, (byte) 0x14,
+ (byte) 0x99, (byte) 0xAE, (byte) 0x60, (byte) 0x03,
+ (byte) 0x86, (byte) 0x14, (byte) 0xF1, (byte) 0x39,
+ (byte) 0x4A, (byte) 0xBF, (byte) 0xA3, (byte) 0xB4,
+ (byte) 0xC8, (byte) 0x50, (byte) 0xD9, (byte) 0x27,
+ (byte) 0xE1, (byte) 0xE7, (byte) 0x76, (byte) 0x9C,
+ (byte) 0x8E, (byte) 0xEC, (byte) 0x2D, (byte) 0x19
+ };
+
+ // second part of G uncompressed
+ public static final byte[] EC571_F2M_G_Y = new byte[]{
+ (byte) 0x03, (byte) 0x7B, (byte) 0xF2, (byte) 0x73,
+ (byte) 0x42, (byte) 0xDA, (byte) 0x63, (byte) 0x9B,
+ (byte) 0x6D, (byte) 0xCC, (byte) 0xFF, (byte) 0xFE,
+ (byte) 0xB7, (byte) 0x3D, (byte) 0x69, (byte) 0xD7,
+ (byte) 0x8C, (byte) 0x6C, (byte) 0x27, (byte) 0xA6,
+ (byte) 0x00, (byte) 0x9C, (byte) 0xBB, (byte) 0xCA,
+ (byte) 0x19, (byte) 0x80, (byte) 0xF8, (byte) 0x53,
+ (byte) 0x39, (byte) 0x21, (byte) 0xE8, (byte) 0xA6,
+ (byte) 0x84, (byte) 0x42, (byte) 0x3E, (byte) 0x43,
+ (byte) 0xBA, (byte) 0xB0, (byte) 0x8A, (byte) 0x57,
+ (byte) 0x62, (byte) 0x91, (byte) 0xAF, (byte) 0x8F,
+ (byte) 0x46, (byte) 0x1B, (byte) 0xB2, (byte) 0xA8,
+ (byte) 0xB3, (byte) 0x53, (byte) 0x1D, (byte) 0x2F,
+ (byte) 0x04, (byte) 0x85, (byte) 0xC1, (byte) 0x9B,
+ (byte) 0x16, (byte) 0xE2, (byte) 0xF1, (byte) 0x51,
+ (byte) 0x6E, (byte) 0x23, (byte) 0xDD, (byte) 0x3C,
+ (byte) 0x1A, (byte) 0x48, (byte) 0x27, (byte) 0xAF,
+ (byte) 0x1B, (byte) 0x8A, (byte) 0xC1, (byte) 0x5B
+ };
+
+ // order of G
+ public static final byte[] EC571_F2M_R = new byte[]{
+ (byte) 0x03, (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) 0xE6, (byte) 0x61, (byte) 0xCE, (byte) 0x18,
+ (byte) 0xFF, (byte) 0x55, (byte) 0x98, (byte) 0x73,
+ (byte) 0x08, (byte) 0x05, (byte) 0x9B, (byte) 0x18,
+ (byte) 0x68, (byte) 0x23, (byte) 0x85, (byte) 0x1E,
+ (byte) 0xC7, (byte) 0xDD, (byte) 0x9C, (byte) 0xA1,
+ (byte) 0x16, (byte) 0x1D, (byte) 0xE9, (byte) 0x3D,
+ (byte) 0x51, (byte) 0x74, (byte) 0xD6, (byte) 0x6E,
+ (byte) 0x83, (byte) 0x82, (byte) 0xE9, (byte) 0xBB,
+ (byte) 0x2F, (byte) 0xE8, (byte) 0x4E, (byte) 0x47
+ };
+
+ // cofactor of G
+ public static final short EC571_F2M_K = 2;
+
+
+ // transformParameter TRANSFORMATION types
+ public static final short TRANSFORMATION_NONE = (short) 0x00;
+ public static final short TRANSFORMATION_FIXED = (short) 0x01;
+ public static final short TRANSFORMATION_FULLRANDOM = (short) 0x02;
+ public static final short TRANSFORMATION_ONEBYTERANDOM = (short) 0x04;
+ public static final short TRANSFORMATION_ZERO = (short) 0x08;
+ public static final short TRANSFORMATION_ONE = (short) 0x10;
+ public static final short TRANSFORMATION_MAX = (short) 0x20;
+ public static final short TRANSFORMATION_INCREMENT = (short) 0x40;
+ public static final short TRANSFORMATION_INFINITY = (short) 0x80;
+ public static final short TRANSFORMATION_COMPRESS = (short) 0x0100;
+ public static final short TRANSFORMATION_COMPRESS_HYBRID = (short) 0x0200;
+ public static final short TRANSFORMATION_04_MASK = (short) 0x0400;
+
+ // toX962 FORM types
+ public static final byte X962_UNCOMPRESSED = (byte) 0x00;
+ public static final byte X962_COMPRESSED = (byte) 0x01;
+ public static final byte X962_HYBRID = (byte) 0x02;
+
+ // Supported embedded curves, getCurveParameter
+ public static final byte CURVE_default = (byte) 0;
+ public static final byte CURVE_external = (byte) 0xff;
+
+ // SECG recommended curves over FP
+ public static final byte CURVE_secp112r1 = (byte) 1;
+ public static final byte CURVE_secp128r1 = (byte) 2;
+ public static final byte CURVE_secp160r1 = (byte) 3;
+ public static final byte CURVE_secp192r1 = (byte) 4;
+ public static final byte CURVE_secp224r1 = (byte) 5;
+ public static final byte CURVE_secp256r1 = (byte) 6;
+ public static final byte CURVE_secp384r1 = (byte) 7;
+ public static final byte CURVE_secp521r1 = (byte) 8;
+
+ public static final byte FP_CURVES = (byte) 8;
+
+ // SECG recommended curves over F2M
+ public static final byte CURVE_sect163r1 = (byte) 9;
+ public static final byte CURVE_sect233r1 = (byte) 10;
+ public static final byte CURVE_sect283r1 = (byte) 11;
+ public static final byte CURVE_sect409r1 = (byte) 12;
+ public static final byte CURVE_sect571r1 = (byte) 13;
+
+ public static final byte F2M_CURVES = (byte) 13;
+
+ public static final short[] FP_SIZES = new short[]{112, 128, 160, 192, 224, 256, 384, 521};
+ public static final short[] F2M_SIZES = new short[]{163, 233, 283, 409, 571};
+
+ // Class javacard.security.KeyAgreement
+ // javacard.security.KeyAgreement Fields:
+ public static final byte KeyAgreement_ALG_EC_SVDP_DH = 1;
+ public static final byte KeyAgreement_ALG_EC_SVDP_DHC = 2;
+ public static final byte KeyAgreement_ALG_EC_SVDP_DH_PLAIN = 3;
+ public static final byte KeyAgreement_ALG_EC_SVDP_DHC_PLAIN = 4;
+ public static final byte KeyAgreement_ALG_EC_PACE_GM = 5;
+ public static final byte KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY = 6;
+
+ public static final byte[] KA_TYPES = new byte[]{
+ KeyAgreement_ALG_EC_SVDP_DH,
+ //KeyAgreement_ALG_EC_SVDP_DH_KDF, //duplicate
+ KeyAgreement_ALG_EC_SVDP_DHC,
+ //KeyAgreement_ALG_EC_SVDP_DHC_KDF, //duplicate
+ KeyAgreement_ALG_EC_SVDP_DH_PLAIN,
+ KeyAgreement_ALG_EC_SVDP_DHC_PLAIN,
+ KeyAgreement_ALG_EC_PACE_GM,
+ KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY
+ };
+
+ // Class javacard.security.Signature
+ // javacard.security.Signature Fields:
+ public static final byte Signature_ALG_ECDSA_SHA = 17;
+ public static final byte Signature_ALG_ECDSA_SHA_224 = 37;
+ public static final byte Signature_ALG_ECDSA_SHA_256 = 33;
+ public static final byte Signature_ALG_ECDSA_SHA_384 = 34;
+ public static final byte Signature_ALG_ECDSA_SHA_512 = 38;
+
+ public static final byte[] SIG_TYPES = new byte[]{
+ Signature_ALG_ECDSA_SHA,
+ Signature_ALG_ECDSA_SHA_224,
+ Signature_ALG_ECDSA_SHA_256,
+ Signature_ALG_ECDSA_SHA_384,
+ Signature_ALG_ECDSA_SHA_512
+ };
+
+ public static byte getCurve(short keyLength, byte keyClass) {
+ if (keyClass == KeyPair.ALG_EC_FP) {
+ switch (keyLength) {
+ case (short) 112:
+ return CURVE_secp112r1;
+ case (short) 128:
+ return CURVE_secp128r1;
+ case (short) 160:
+ return CURVE_secp160r1;
+ case (short) 192:
+ return CURVE_secp192r1;
+ case (short) 224:
+ return CURVE_secp224r1;
+ case (short) 256:
+ return CURVE_secp256r1;
+ case (short) 384:
+ return CURVE_secp384r1;
+ case (short) 521:
+ return CURVE_secp521r1;
+ default:
+ ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
+ }
+ } else if (keyClass == KeyPair.ALG_EC_F2M) {
+ switch (keyLength) {
+ case (short) 163:
+ return CURVE_sect163r1;
+ case (short) 233:
+ return CURVE_sect233r1;
+ case (short) 283:
+ return CURVE_sect283r1;
+ case (short) 409:
+ return CURVE_sect409r1;
+ case (short) 571:
+ return CURVE_sect571r1;
+ default:
+ ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
+ }
+ } else {
+ ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
+ }
+ return 0;
+ }
+
+ public static short getCurveParameter(byte curve, short param, byte[] outputBuffer, short outputOffset) {
+ byte alg = getCurveType(curve);
+ switch (curve) {
+ case CURVE_secp112r1: {
+ EC_FP_P = EC112_FP_P;
+ EC_A = EC112_FP_A;
+ EC_B = EC112_FP_B;
+ EC_G_X = EC112_FP_G_X;
+ EC_G_Y = EC112_FP_G_Y;
+ EC_R = EC112_FP_R;
+ EC_K = EC112_FP_K;
+ EC_W_X = null;
+ EC_W_Y = null;
+ EC_S = null;
+ break;
+ }
+ case CURVE_secp128r1: {
+ EC_FP_P = EC128_FP_P;
+ EC_A = EC128_FP_A;
+ EC_B = EC128_FP_B;
+ EC_G_X = EC128_FP_G_X;
+ EC_G_Y = EC128_FP_G_Y;
+ EC_R = EC128_FP_R;
+ EC_K = EC128_FP_K;
+ EC_W_X = null;
+ EC_W_Y = null;
+ EC_S = null;
+ break;
+ }
+ case CURVE_secp160r1: {
+ EC_FP_P = EC160_FP_P;
+ EC_A = EC160_FP_A;
+ EC_B = EC160_FP_B;
+ EC_G_X = EC160_FP_G_X;
+ EC_G_Y = EC160_FP_G_Y;
+ EC_R = EC160_FP_R;
+ EC_K = EC160_FP_K;
+ EC_W_X = null;
+ EC_W_Y = null;
+ EC_S = null;
+ break;
+ }
+ case CURVE_secp192r1: {
+ EC_FP_P = EC192_FP_P;
+ EC_A = EC192_FP_A;
+ EC_B = EC192_FP_B;
+ EC_G_X = EC192_FP_G_X;
+ EC_G_Y = EC192_FP_G_Y;
+ EC_R = EC192_FP_R;
+ EC_K = EC192_FP_K;
+ EC_W_X = null;
+ EC_W_Y = null;
+ EC_S = null;
+ break;
+ }
+ case CURVE_secp224r1: {
+ EC_FP_P = EC224_FP_P;
+ EC_A = EC224_FP_A;
+ EC_B = EC224_FP_B;
+ EC_G_X = EC224_FP_G_X;
+ EC_G_Y = EC224_FP_G_Y;
+ EC_R = EC224_FP_R;
+ EC_K = EC224_FP_K;
+ EC_S = null;
+ break;
+ }
+ case CURVE_secp256r1: {
+ EC_FP_P = EC256_FP_P;
+ EC_A = EC256_FP_A;
+ EC_B = EC256_FP_B;
+ EC_G_X = EC256_FP_G_X;
+ EC_G_Y = EC256_FP_G_Y;
+ EC_R = EC256_FP_R;
+ EC_K = EC256_FP_K;
+ EC_W_X = null;
+ EC_W_Y = null;
+ EC_S = null;
+ break;
+ }
+ case CURVE_secp384r1: {
+ EC_FP_P = EC384_FP_P;
+ EC_A = EC384_FP_A;
+ EC_B = EC384_FP_B;
+ EC_G_X = EC384_FP_G_X;
+ EC_G_Y = EC384_FP_G_Y;
+ EC_R = EC384_FP_R;
+ EC_K = EC384_FP_K;
+ EC_W_X = null;
+ EC_W_Y = null;
+ EC_S = null;
+ break;
+ }
+ case CURVE_secp521r1: {
+ EC_FP_P = EC521_FP_P;
+ EC_A = EC521_FP_A;
+ EC_B = EC521_FP_B;
+ EC_G_X = EC521_FP_G_X;
+ EC_G_Y = EC521_FP_G_Y;
+ EC_R = EC521_FP_R;
+ EC_K = EC521_FP_K;
+ EC_W_X = null;
+ EC_W_Y = null;
+ EC_S = null;
+ break;
+ }
+ case CURVE_sect163r1: {
+ EC_F2M_F2M = EC163_F2M_F;
+ EC_A = EC163_F2M_A;
+ EC_B = EC163_F2M_B;
+ EC_G_X = EC163_F2M_G_X;
+ EC_G_Y = EC163_F2M_G_Y;
+ EC_R = EC163_F2M_R;
+ EC_K = EC163_F2M_K;
+ EC_W_X = null;
+ EC_W_Y = null;
+ EC_S = null;
+ break;
+ }
+ case CURVE_sect233r1: {
+ EC_F2M_F2M = EC233_F2M_F;
+ EC_A = EC233_F2M_A;
+ EC_B = EC233_F2M_B;
+ EC_G_X = EC233_F2M_G_X;
+ EC_G_Y = EC233_F2M_G_Y;
+ EC_R = EC233_F2M_R;
+ EC_K = EC233_F2M_K;
+ EC_W_X = null;
+ EC_W_Y = null;
+ EC_S = null;
+ break;
+ }
+ case CURVE_sect283r1: {
+ EC_F2M_F2M = EC283_F2M_F;
+ EC_A = EC283_F2M_A;
+ EC_B = EC283_F2M_B;
+ EC_G_X = EC283_F2M_G_X;
+ EC_G_Y = EC283_F2M_G_Y;
+ EC_R = EC283_F2M_R;
+ EC_K = EC283_F2M_K;
+ EC_W_X = null;
+ EC_W_Y = null;
+ EC_S = null;
+ break;
+ }
+ case CURVE_sect409r1: {
+ EC_F2M_F2M = EC409_F2M_F;
+ EC_A = EC409_F2M_A;
+ EC_B = EC409_F2M_B;
+ EC_G_X = EC409_F2M_G_X;
+ EC_G_Y = EC409_F2M_G_Y;
+ EC_R = EC409_F2M_R;
+ EC_K = EC409_F2M_K;
+ EC_W_X = null;
+ EC_W_Y = null;
+ EC_S = null;
+ break;
+ }
+ case CURVE_sect571r1: {
+ EC_F2M_F2M = EC571_F2M_F;
+ EC_A = EC571_F2M_A;
+ EC_B = EC571_F2M_B;
+ EC_G_X = EC571_F2M_G_X;
+ EC_G_Y = EC571_F2M_G_Y;
+ EC_R = EC571_F2M_R;
+ EC_K = EC571_F2M_K;
+ EC_W_X = null;
+ EC_W_Y = null;
+ EC_S = null;
+ break;
+ }
+ default:
+ ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
+ }
+ short length = 0;
+ switch (param) {
+ case PARAMETER_FP:
+ if (alg == KeyPair.ALG_EC_FP) {
+ length = Util.arrayCopyNonAtomic(EC_FP_P, (short) 0, outputBuffer, outputOffset, (short) EC_FP_P.length);
+ }
+ break;
+ case PARAMETER_F2M:
+ if (alg == KeyPair.ALG_EC_F2M) {
+ length = Util.arrayCopyNonAtomic(EC_F2M_F2M, (short) 0, outputBuffer, outputOffset, (short) EC_F2M_F2M.length);
+ }
+ break;
+ case PARAMETER_A:
+ length = Util.arrayCopyNonAtomic(EC_A, (short) 0, outputBuffer, outputOffset, (short) EC_A.length);
+ break;
+ case PARAMETER_B:
+ length = Util.arrayCopyNonAtomic(EC_B, (short) 0, outputBuffer, outputOffset, (short) EC_B.length);
+ break;
+ case PARAMETER_G:
+ length = toX962(X962_UNCOMPRESSED, outputBuffer, outputOffset, EC_G_X, (short) 0, (short) EC_G_X.length, EC_G_Y, (short) 0, (short) EC_G_Y.length);
+ break;
+ case PARAMETER_R:
+ length = Util.arrayCopyNonAtomic(EC_R, (short) 0, outputBuffer, outputOffset, (short) EC_R.length);
+ break;
+ case PARAMETER_K:
+ length = 2;
+ Util.setShort(outputBuffer, outputOffset, EC_K);
+ break;
+ case PARAMETER_W:
+ if (EC_W_X == null || EC_W_Y == null) {
+ return 0;
+ }
+ length = toX962(X962_UNCOMPRESSED, outputBuffer, outputOffset, EC_W_X, (short) 0, (short) EC_W_X.length, EC_W_Y, (short) 0, (short) EC_W_Y.length);
+ break;
+ case PARAMETER_S:
+ if (EC_S == null) {
+ return 0;
+ }
+ length = Util.arrayCopyNonAtomic(EC_S, (short) 0, outputBuffer, outputOffset, (short) EC_S.length);
+ break;
+ default:
+ ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
+ }
+ return length;
+ }
+
+ public static short transformParameter(short transformation, byte[] buffer, short offset, short length) {
+ if (transformation == TRANSFORMATION_NONE) {
+ return length;
+ }
+
+ short transformationMask = TRANSFORMATION_FIXED;
+ while (transformationMask <= TRANSFORMATION_04_MASK) {
+ short transformationPart = (short) (transformationMask & transformation);
+ switch (transformationPart) {
+ case (short) 0:
+ break;
+ case TRANSFORMATION_FIXED:
+ if (length >= 1) {
+ buffer[offset] = (byte) 0xcc;
+ buffer[(short) (offset + length - 1)] = (byte) 0xcc;
+ }
+ break;
+ case TRANSFORMATION_FULLRANDOM:
+ randomData.generateData(buffer, offset, length);
+ break;
+ case TRANSFORMATION_ONEBYTERANDOM:
+ short first = Util.getShort(buffer, (short) 0); // save first two bytes
+
+ randomData.generateData(buffer, (short) 0, (short) 2); // generate position
+ short rngPos = Util.getShort(buffer, (short) 0); // save generated position
+
+ Util.setShort(buffer, (short) 0, first); // restore first two bytes
+
+ if (rngPos < 0) { // make positive
+ rngPos = (short) -rngPos;
+ }
+ rngPos %= length; // make < param length
+
+ byte original = buffer[rngPos];
+ do {
+ randomData.generateData(buffer, rngPos, (short) 1);
+ } while (original == buffer[rngPos]);
+ break;
+ case TRANSFORMATION_ZERO:
+ Util.arrayFillNonAtomic(buffer, offset, length, (byte) 0);
+ break;
+ case TRANSFORMATION_ONE:
+ Util.arrayFillNonAtomic(buffer, offset, length, (byte) 0);
+ buffer[(short) (offset + length)] = (byte) 1;
+ break;
+ case TRANSFORMATION_MAX:
+ Util.arrayFillNonAtomic(buffer, offset, length, (byte) 1);
+ break;
+ case TRANSFORMATION_INCREMENT:
+ short index = (short) (offset + length - 1);
+ byte value;
+ do {
+ value = buffer[index];
+ buffer[index--] = ++value;
+ } while (value == (byte) 0 && index >= offset);
+ break;
+ case TRANSFORMATION_INFINITY:
+ Util.arrayFillNonAtomic(buffer, offset, length, (byte) 0);
+ length = 1;
+ break;
+ case TRANSFORMATION_COMPRESS_HYBRID:
+ case TRANSFORMATION_COMPRESS:
+ if ((short) (length % 2) != 1) {
+ // an uncompressed point should have odd length (since 1 byte type, + 2 * coords)
+ ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
+ }
+ short half = (short) ((short) (length - 1) / 2);
+ byte yLSB = buffer[(short) (offset + length)];
+ byte yBit = (byte) (yLSB & 0x01);
+ if (yBit == 1) {
+ buffer[offset] = 3;
+ } else {
+ buffer[offset] = 2;
+ }
+
+ if (transformationPart == TRANSFORMATION_COMPRESS) {
+ length = (short) (half + 1);
+ } else {
+ buffer[offset] += 4;
+ }
+ break;
+ case TRANSFORMATION_04_MASK:
+ buffer[offset] = 4;
+ break;
+ default:
+ ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
+ }
+ transformationMask = (short) (transformationMask << 1);
+ }
+ return length;
+ }
+
+ public static byte getCurveType(byte curve) {
+ return curve <= FP_CURVES ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M;
+ }
+
+ @SuppressWarnings("fallthrough")
+ public static short toX962(byte form, byte[] outputBuffer, short outputOffset, byte[] xBuffer, short xOffset, short xLength, byte[] yBuffer, short yOffset, short yLength) {
+ short size = 1;
+ size += xLength;
+
+ short offset = outputOffset;
+ outputBuffer[offset] = 0;
+ switch (form) {
+ case X962_UNCOMPRESSED:
+ outputBuffer[offset] = 4;
+ break;
+ case X962_HYBRID:
+ outputBuffer[offset] = 4;
+ case X962_COMPRESSED: /* fallthrough */
+ byte yLSB = yBuffer[(short) (yOffset + yLength)];
+ byte yBit = (byte) (yLSB & 0x01);
+
+ if (yBit == 1) {
+ outputBuffer[offset] += 3;
+ } else {
+ outputBuffer[offset] += 2;
+ }
+ break;
+ default:
+ ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
+ }
+ offset += 1;
+
+ offset = Util.arrayCopyNonAtomic(xBuffer, xOffset, outputBuffer, offset, xLength);
+ if (form == X962_HYBRID || form == X962_UNCOMPRESSED) {
+ Util.arrayCopyNonAtomic(yBuffer, yOffset, outputBuffer, offset, yLength);
+ size += yLength;
+ }
+
+ return size;
+ }
+
+}
diff --git a/applet/ssleay32.dll b/applet/ssleay32.dll
deleted file mode 100644
index e8fabb6..0000000
--- a/applet/ssleay32.dll
+++ /dev/null
Binary files differ
diff --git a/applet/zlib1.dll b/applet/zlib1.dll
deleted file mode 100644
index 31996cd..0000000
--- a/applet/zlib1.dll
+++ /dev/null
Binary files differ