diff options
| author | J08nY | 2017-01-22 03:17:36 +0100 |
|---|---|---|
| committer | J08nY | 2017-01-22 03:17:36 +0100 |
| commit | 636306e09a84ac785d2711117640efe914ae020f (patch) | |
| tree | d626572b2e7601d015eefefe9da6a751a00001b9 | |
| parent | 2e677ed35520f4c3380461205c548fba28998c40 (diff) | |
| download | ECTester-636306e09a84ac785d2711117640efe914ae020f.tar.gz ECTester-636306e09a84ac785d2711117640efe914ae020f.tar.zst ECTester-636306e09a84ac785d2711117640efe914ae020f.zip | |
62 files changed, 973 insertions, 264 deletions
diff --git a/!uploader/ectester.cap b/!uploader/ectester.cap Binary files differindex 63dd209..a7da4dc 100644 --- a/!uploader/ectester.cap +++ b/!uploader/ectester.cap diff --git a/dist/ECTester.jar b/dist/ECTester.jar Binary files differindex a5bf4e3..b0dae23 100644 --- a/dist/ECTester.jar +++ b/dist/ECTester.jar diff --git a/src/cz/crcs/ectester/applet/ECKeyGenerator.java b/src/cz/crcs/ectester/applet/ECKeyGenerator.java index 47f9c94..417944c 100644 --- a/src/cz/crcs/ectester/applet/ECKeyGenerator.java +++ b/src/cz/crcs/ectester/applet/ECKeyGenerator.java @@ -72,6 +72,10 @@ public class ECKeyGenerator { byte alg = EC_Consts.getCurveType(curve); sw = ISO7816.SW_NO_ERROR; + if (params == EC_Consts.PARAMETERS_NONE) { + return sw; + } + short length; if (alg == KeyPair.ALG_EC_FP && (params & EC_Consts.PARAMETER_FP) != 0) { length = EC_Consts.getCurveParameter(curve, EC_Consts.PARAMETER_FP, buffer, offset); @@ -119,6 +123,9 @@ public class ECKeyGenerator { */ public short corruptCurve(KeyPair keypair, byte key, short corruptParams, byte corruption, byte[] buffer, short offset) { sw = ISO7816.SW_NO_ERROR; + if (corruptParams == EC_Consts.PARAMETERS_NONE) { + return sw; + } //go through param bit by bit, and invalidate all selected params short paramMask = EC_Consts.PARAMETER_FP; @@ -244,6 +251,9 @@ public class ECKeyGenerator { */ 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) { @@ -261,11 +271,14 @@ public class ECKeyGenerator { } /** - * @param key - * @param param - * @param outputBuffer - * @param outputOffset - * @return + * 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) { sw = ISO7816.SW_NO_ERROR; @@ -319,18 +332,25 @@ public class ECKeyGenerator { } /** - * @param keypair - * @param key - * @param params - * @param buffer - * @param offset - * @return + * 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); @@ -352,11 +372,11 @@ public class ECKeyGenerator { /** * Copies this KeyPairs curve parameters to another ECKeyGenerator. * - * @param from - * @param to - * @param buffer - * @param offset - * @return + * @param from keyPair to copy from + * @param to keyPair to copy to + * @param buffer buffer to use for copying + * @param offset offset to use in buffer + * @return sw */ public short copyCurve(KeyPair from, KeyPair to, byte[] buffer, short offset) { sw = ISO7816.SW_NO_ERROR; diff --git a/src/cz/crcs/ectester/applet/ECTesterApplet.java b/src/cz/crcs/ectester/applet/ECTesterApplet.java index dd13fc3..dfdd0f0 100644 --- a/src/cz/crcs/ectester/applet/ECTesterApplet.java +++ b/src/cz/crcs/ectester/applet/ECTesterApplet.java @@ -170,31 +170,6 @@ public class ECTesterApplet extends Applet { } /** - * @param keyPair which keyPair to use, local/remote (KEYPAIR_* | ...) - * @param keyLength key length to set - * @param keyClass key class to allocate - * @param buffer apdu buffer - * @param offset offset into apdu buffer - * @return length of data written to the buffer - */ - private short allocate(byte keyPair, short keyLength, byte keyClass, byte[] buffer, short offset) { - short length = 0; - if ((keyPair & KEYPAIR_LOCAL) != 0) { - localKeypair = keyGenerator.allocatePair(keyClass, keyLength); - Util.setShort(buffer, offset, keyGenerator.getSW()); - length += 2; - } - - if ((keyPair & KEYPAIR_REMOTE) != 0) { - remoteKeypair = keyGenerator.allocatePair(keyClass, keyLength); - Util.setShort(buffer, (short) (offset + length), keyGenerator.getSW()); - length += 2; - } - - return length; - } - - /** * Sets curve parameters on local and remote keyPairs. * returns setCurve SWs, set params if export * @@ -236,6 +211,102 @@ public class ECTesterApplet extends Applet { } /** + * Generates the local and remote keyPairs. + * returns generate SWs, pubkey and privkey if export + * + * @param apdu P1 = byte keyPair (KEYPAIR_* | ...) + * P2 = byte export (EXPORT_* | KEYPAIR_*) + */ + private void insGenerate(APDU apdu) { + apdu.setIncomingAndReceive(); + byte[] apdubuf = apdu.getBuffer(); + + byte keyPair = apdubuf[ISO7816.OFFSET_P1]; + byte export = apdubuf[ISO7816.OFFSET_P2]; + + short len = 0; + if ((keyPair & KEYPAIR_LOCAL) != 0) + len += generate(localKeypair, apdubuf, (short) 0); + if ((keyPair & KEYPAIR_REMOTE) != 0) + len += generate(remoteKeypair, apdubuf, len); + if ((export & KEYPAIR_LOCAL) != 0) + len += export(localKeypair, export, (short) (EC_Consts.PARAMETER_W | EC_Consts.PARAMETER_S), apdubuf, len); + if ((export & KEYPAIR_REMOTE) != 0) + len += export(remoteKeypair, export, (short) (EC_Consts.PARAMETER_W | EC_Consts.PARAMETER_S), apdubuf, len); + + apdu.setOutgoingAndSend((short) 0, len); + } + + /** + * Performs ECDH, between the pubkey specified in P1(local/remote) and the privkey specified in P2(local/remote). + * returns deriveSecret SW, if export != 0 => short secretlen, byte[] secret + * + * @param apdu P1 = byte pubkey (KEYPAIR_*) + * P2 = byte privkey (KEYPAIR_*) + * DATA = byte export (EXPORT_ECDH || 0) + * byte invalid (00 = valid, !00 = invalid) + */ + private void insECDH(APDU apdu) { + apdu.setIncomingAndReceive(); + byte[] apdubuf = apdu.getBuffer(); + + byte pubkey = apdubuf[ISO7816.OFFSET_P1]; + byte privkey = apdubuf[ISO7816.OFFSET_P2]; + byte export = apdubuf[ISO7816.OFFSET_CDATA]; + byte invalid = apdubuf[(short) (ISO7816.OFFSET_CDATA + 1)]; + + short len = ecdh(pubkey, privkey, export, invalid, apdubuf, (short) 0); + + apdu.setOutgoingAndSend((short) 0, len); + } + + /** + * Performs ECDSA signature and verification on data provided or random, using the keyPair in P1(local/remote). + * returns ecdsa SW, if export != 0 => short signature_length, byte[] signature + * + * @param apdu P1 = byte keyPair (KEYPAIR_*) + * P2 = byte export (EXPORT_SIG || 0) + * DATA = short dataLength (00 = random data generated, !00 = data length) + * byte[] data + */ + private void insECDSA(APDU apdu) { + apdu.setIncomingAndReceive(); + byte[] apdubuf = apdu.getBuffer(); + + byte keyPair = apdubuf[ISO7816.OFFSET_P1]; + byte export = apdubuf[ISO7816.OFFSET_P2]; + + short len = ecdsa(keyPair, export, apdubuf, ISO7816.OFFSET_CDATA, (short) 0); + + apdu.setOutgoingAndSend((short) 0, len); + } + + /** + * @param keyPair which keyPair to use, local/remote (KEYPAIR_* | ...) + * @param keyLength key length to set + * @param keyClass key class to allocate + * @param buffer apdu buffer + * @param offset offset into apdu buffer + * @return length of data written to the buffer + */ + private short allocate(byte keyPair, short keyLength, byte keyClass, byte[] buffer, short offset) { + short length = 0; + if ((keyPair & KEYPAIR_LOCAL) != 0) { + localKeypair = keyGenerator.allocatePair(keyClass, keyLength); + Util.setShort(buffer, offset, keyGenerator.getSW()); + length += 2; + } + + if ((keyPair & KEYPAIR_REMOTE) != 0) { + remoteKeypair = keyGenerator.allocatePair(keyClass, keyLength); + Util.setShort(buffer, (short) (offset + length), keyGenerator.getSW()); + length += 2; + } + + return length; + } + + /** * @param keyPair KeyPair to set params on * @param curve curve to set (EC_Consts.CURVE_*) * @param params parameters to set (EC_Consts.PARAMETER_* | ...) @@ -270,33 +341,6 @@ public class ECTesterApplet extends Applet { } /** - * Generates the local and remote keyPairs. - * returns generate SWs, pubkey and privkey if export - * - * @param apdu P1 = byte keyPair (KEYPAIR_* | ...) - * P2 = byte export (EXPORT_* | KEYPAIR_*) - */ - private void insGenerate(APDU apdu) { - apdu.setIncomingAndReceive(); - byte[] apdubuf = apdu.getBuffer(); - - byte keyPair = apdubuf[ISO7816.OFFSET_P1]; - byte export = apdubuf[ISO7816.OFFSET_P2]; - - short len = 0; - if ((keyPair & KEYPAIR_LOCAL) != 0) - len += generate(localKeypair, apdubuf, (short) 0); - if ((keyPair & KEYPAIR_REMOTE) != 0) - len += generate(remoteKeypair, apdubuf, len); - if ((export & KEYPAIR_LOCAL) != 0) - len += export(localKeypair, export, (short) (EC_Consts.PARAMETER_W | EC_Consts.PARAMETER_S), apdubuf, len); - if ((export & KEYPAIR_REMOTE) != 0) - len += export(remoteKeypair, export, (short) (EC_Consts.PARAMETER_W | EC_Consts.PARAMETER_S), apdubuf, len); - - apdu.setOutgoingAndSend((short) 0, len); - } - - /** * @param keyPair KeyPair to generate * @param buffer buffer to write sw to * @param offset output offset in buffer @@ -334,29 +378,6 @@ public class ECTesterApplet extends Applet { } /** - * Performs ECDH, between the pubkey specified in P1(local/remote) and the privkey specified in P2(local/remote). - * returns deriveSecret SW, if export != 0 => short secretlen, byte[] secret - * - * @param apdu P1 = byte pubkey (KEYPAIR_*) - * P2 = byte privkey (KEYPAIR_*) - * DATA = byte export (EXPORT_ECDH || 0) - * byte invalid (00 = valid, !00 = invalid) - */ - private void insECDH(APDU apdu) { - apdu.setIncomingAndReceive(); - byte[] apdubuf = apdu.getBuffer(); - - byte pubkey = apdubuf[ISO7816.OFFSET_P1]; - byte privkey = apdubuf[ISO7816.OFFSET_P2]; - byte export = apdubuf[ISO7816.OFFSET_CDATA]; - byte invalid = apdubuf[(short) (ISO7816.OFFSET_CDATA + 1)]; - - short len = ecdh(pubkey, privkey, export, invalid, apdubuf, (short) 0); - - apdu.setOutgoingAndSend((short) 0, len); - } - - /** * @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 @@ -392,27 +413,6 @@ public class ECTesterApplet extends Applet { } /** - * Performs ECDSA signature and verification on data provided or random, using the keyPair in P1(local/remote). - * returns ecdsa SW, if export != 0 => short signature_length, byte[] signature - * - * @param apdu P1 = byte keyPair (KEYPAIR_*) - * P2 = byte export (EXPORT_SIG || 0) - * DATA = short dataLength (00 = random data generated, !00 = data length) - * byte[] data - */ - private void insECDSA(APDU apdu) { - apdu.setIncomingAndReceive(); - byte[] apdubuf = apdu.getBuffer(); - - byte keyPair = apdubuf[ISO7816.OFFSET_P1]; - byte export = apdubuf[ISO7816.OFFSET_P2]; - - short len = ecdsa(keyPair, export, apdubuf, ISO7816.OFFSET_CDATA, (short) 0); - - apdu.setOutgoingAndSend((short) 0, len); - } - - /** * @param keyPair keyPair to use for signing and verification (KEYPAIR_LOCAL || KEYPAIR_REMOTE) * @param export whether to export ECDSA signature * @param buffer buffer to write sw to, and export ECDSA signature if (export & EXPORT_SIG) != 0 diff --git a/src/cz/crcs/ectester/data/brainpool/brainpoolP160r1.txt b/src/cz/crcs/ectester/data/brainpool/brainpoolP160r1.txt new file mode 100644 index 0000000..69abf52 --- /dev/null +++ b/src/cz/crcs/ectester/data/brainpool/brainpoolP160r1.txt @@ -0,0 +1,7 @@ +E95E4A5F737059DC60DFC7AD95B3D8139515620F, +340E7BE2A280EB74E2BE61BADA745D97E8F7C300, +1E589A8595423412134FAA2DBDEC95C8D8675E58, +BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3, +1667CB477A1A8EC338F94741669C976316DA6321, +E95E4A5F737059DC60DF5991D45029409E60FC09, +1 diff --git a/src/cz/crcs/ectester/data/brainpool/brainpoolP160t1.txt b/src/cz/crcs/ectester/data/brainpool/brainpoolP160t1.txt new file mode 100644 index 0000000..fadafdf --- /dev/null +++ b/src/cz/crcs/ectester/data/brainpool/brainpoolP160t1.txt @@ -0,0 +1,7 @@ +24DBFF5DEC9B986BBFE5295A29BFBAE45E0F5D0B, +E95E4A5F737059DC60DFC7AD95B3D8139515620C, +7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380, +B199B13B9B34EFC1397E64BAEB05ACC265FF2378, +ADD6718B7C7C1961F0991B842443772152C9E0AD, +E95E4A5F737059DC60DF5991D45029409E60FC09, +1 diff --git a/src/cz/crcs/ectester/data/brainpool/brainpoolP192r1.txt b/src/cz/crcs/ectester/data/brainpool/brainpoolP192r1.txt new file mode 100644 index 0000000..3e6bed8 --- /dev/null +++ b/src/cz/crcs/ectester/data/brainpool/brainpoolP192r1.txt @@ -0,0 +1,7 @@ +C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297, +6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF, +469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9, +C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6, +14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F, +C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1, +1 diff --git a/src/cz/crcs/ectester/data/brainpool/brainpoolP192t1.txt b/src/cz/crcs/ectester/data/brainpool/brainpoolP192t1.txt new file mode 100644 index 0000000..cd52697 --- /dev/null +++ b/src/cz/crcs/ectester/data/brainpool/brainpoolP192t1.txt @@ -0,0 +1,7 @@ +1B6F5CC8DB4DC7AF19458A9CB80DC2295E5EB9C3732104CB, +C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294, +13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79, +3AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129, +97E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9, +C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1, +1 diff --git a/src/cz/crcs/ectester/data/brainpool/brainpoolP224r1.txt b/src/cz/crcs/ectester/data/brainpool/brainpoolP224r1.txt new file mode 100644 index 0000000..12e536c --- /dev/null +++ b/src/cz/crcs/ectester/data/brainpool/brainpoolP224r1.txt @@ -0,0 +1,7 @@ +D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF, +68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43, +2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B, +D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D, +58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD, +D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F, +1 diff --git a/src/cz/crcs/ectester/data/brainpool/brainpoolP224t1.txt b/src/cz/crcs/ectester/data/brainpool/brainpoolP224t1.txt new file mode 100644 index 0000000..522d09e --- /dev/null +++ b/src/cz/crcs/ectester/data/brainpool/brainpoolP224t1.txt @@ -0,0 +1,7 @@ +2DF271E14427A346910CF7A2E6CFA7B3F484E5C2CCE1C8B730E28B3F, +D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC, +4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D, +6AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D580, +374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C, +D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F, +1 diff --git a/src/cz/crcs/ectester/data/brainpool/brainpoolP256r1.txt b/src/cz/crcs/ectester/data/brainpool/brainpoolP256r1.txt new file mode 100644 index 0000000..e0e50ad --- /dev/null +++ b/src/cz/crcs/ectester/data/brainpool/brainpoolP256r1.txt @@ -0,0 +1,7 @@ +A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377, +7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9, +26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6, +8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262, +547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997, +A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7, +1 diff --git a/src/cz/crcs/ectester/data/brainpool/brainpoolP256t1.txt b/src/cz/crcs/ectester/data/brainpool/brainpoolP256t1.txt new file mode 100644 index 0000000..f5bb2d6 --- /dev/null +++ b/src/cz/crcs/ectester/data/brainpool/brainpoolP256t1.txt @@ -0,0 +1,7 @@ +3E2D4BD9597B58639AE7AA669CAB9837CF5CF20A2C852D10F655668DFC150EF0, +A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374, +662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04, +A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4, +2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE, +A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7, +1 diff --git a/src/cz/crcs/ectester/data/brainpool/brainpoolP320r1.txt b/src/cz/crcs/ectester/data/brainpool/brainpoolP320r1.txt new file mode 100644 index 0000000..474fa9d --- /dev/null +++ b/src/cz/crcs/ectester/data/brainpool/brainpoolP320r1.txt @@ -0,0 +1,7 @@ +D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27, +3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4, +520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6, +43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611, +14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1, +D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311, +1 diff --git a/src/cz/crcs/ectester/data/brainpool/brainpoolP320t1.txt b/src/cz/crcs/ectester/data/brainpool/brainpoolP320t1.txt new file mode 100644 index 0000000..d92d52b --- /dev/null +++ b/src/cz/crcs/ectester/data/brainpool/brainpoolP320t1.txt @@ -0,0 +1,7 @@ +15F75CAF668077F7E85B42EB01F0A81FF56ECD6191D55CB82B7D861458A18FEFC3E5AB7496F3C7B1, +D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24, +A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353, +925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED52, +63BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3, +D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311, +1 diff --git a/src/cz/crcs/ectester/data/brainpool/brainpoolP384r1.txt b/src/cz/crcs/ectester/data/brainpool/brainpoolP384r1.txt new file mode 100644 index 0000000..34ed1fc --- /dev/null +++ b/src/cz/crcs/ectester/data/brainpool/brainpoolP384r1.txt @@ -0,0 +1,7 @@ +8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53, +7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826, +4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11, +1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E, +8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315, +8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565, +1 diff --git a/src/cz/crcs/ectester/data/brainpool/brainpoolP384t1.txt b/src/cz/crcs/ectester/data/brainpool/brainpoolP384t1.txt new file mode 100644 index 0000000..6bb42c9 --- /dev/null +++ b/src/cz/crcs/ectester/data/brainpool/brainpoolP384t1.txt @@ -0,0 +1,7 @@ +41DFE8DD399331F7166A66076734A89CD0D2BCDB7D068E44E1F378F41ECBAE97D2D63DBC87BCCDDCCC5DA39E8589291C, +8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50, +7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE, +18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC, +25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928, +8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565, +1 diff --git a/src/cz/crcs/ectester/data/brainpool/brainpoolP512r1.txt b/src/cz/crcs/ectester/data/brainpool/brainpoolP512r1.txt new file mode 100644 index 0000000..39e205e --- /dev/null +++ b/src/cz/crcs/ectester/data/brainpool/brainpoolP512r1.txt @@ -0,0 +1,7 @@ +AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3, +7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA, +3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723, +81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822, +7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892, +AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069, +1 diff --git a/src/cz/crcs/ectester/data/brainpool/brainpoolP512t1.txt b/src/cz/crcs/ectester/data/brainpool/brainpoolP512t1.txt new file mode 100644 index 0000000..288c2c1 --- /dev/null +++ b/src/cz/crcs/ectester/data/brainpool/brainpoolP512t1.txt @@ -0,0 +1,7 @@ +12EE58E6764838B69782136F0F2D3BA06E27695716054092E60A80BEDB212B64E585D90BCE13761F85C3F1D2A64E3BE8FEA2220F01EBA5EEB0F35DBD29D922AB, +AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0, +7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E, +640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA, +5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332, +AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069, +1 diff --git a/src/cz/crcs/ectester/data/nist/p192.txt b/src/cz/crcs/ectester/data/nist/p192.txt new file mode 100644 index 0000000..0402da7 --- /dev/null +++ b/src/cz/crcs/ectester/data/nist/p192.txt @@ -0,0 +1,7 @@ +fffffffffffffffffffffffffffffffeffffffffffffffff, +fffffffffffffffffffffffffffffffefffffffffffffffc, +64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1, +188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, +07192b95ffc8da78631011ed6b24cdd573f977a11e794811, +ffffffffffffffffffffffff99def836146bc9b1b4d22831, +1 diff --git a/src/cz/crcs/ectester/data/nist/p224.txt b/src/cz/crcs/ectester/data/nist/p224.txt new file mode 100644 index 0000000..8dca9fe --- /dev/null +++ b/src/cz/crcs/ectester/data/nist/p224.txt @@ -0,0 +1,7 @@ +ffffffffffffffffffffffffffffffff000000000000000000000001, +fffffffffffffffffffffffffffffffefffffffffffffffffffffffe, +b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4, +b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21, +bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34, +ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d, +1 diff --git a/src/cz/crcs/ectester/data/nist/p256.txt b/src/cz/crcs/ectester/data/nist/p256.txt new file mode 100644 index 0000000..bc67187 --- /dev/null +++ b/src/cz/crcs/ectester/data/nist/p256.txt @@ -0,0 +1,7 @@ +ffffffff00000001000000000000000000000000ffffffffffffffffffffffff, +ffffffff00000001000000000000000000000000fffffffffffffffffffffffc, +5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b, +6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296, +4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5, +ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551, +1 diff --git a/src/cz/crcs/ectester/data/nist/p384.txt b/src/cz/crcs/ectester/data/nist/p384.txt new file mode 100644 index 0000000..7808451 --- /dev/null +++ b/src/cz/crcs/ectester/data/nist/p384.txt @@ -0,0 +1,7 @@ +fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff, +fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc, +b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef, +aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7, +3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f, +ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973, +1 diff --git a/src/cz/crcs/ectester/data/nist/p521.txt b/src/cz/crcs/ectester/data/nist/p521.txt new file mode 100644 index 0000000..df7c46d --- /dev/null +++ b/src/cz/crcs/ectester/data/nist/p521.txt @@ -0,0 +1,7 @@ +1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, +1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc, +051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00, +c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66, +11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650, +1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409, +1 diff --git a/src/cz/crcs/ectester/data/secp192k1.txt b/src/cz/crcs/ectester/data/secg/secp192k1.txt index c408b5e..c408b5e 100644 --- a/src/cz/crcs/ectester/data/secp192k1.txt +++ b/src/cz/crcs/ectester/data/secg/secp192k1.txt diff --git a/src/cz/crcs/ectester/data/secp192r1.txt b/src/cz/crcs/ectester/data/secg/secp192r1.txt index 29305b0..29305b0 100644 --- a/src/cz/crcs/ectester/data/secp192r1.txt +++ b/src/cz/crcs/ectester/data/secg/secp192r1.txt diff --git a/src/cz/crcs/ectester/data/secp224r1.txt b/src/cz/crcs/ectester/data/secg/secp224r1.txt index f8f592e..f8f592e 100644 --- a/src/cz/crcs/ectester/data/secp224r1.txt +++ b/src/cz/crcs/ectester/data/secg/secp224r1.txt diff --git a/src/cz/crcs/ectester/data/secp256k1.txt b/src/cz/crcs/ectester/data/secg/secp256k1.txt index 19eeef7..19eeef7 100644 --- a/src/cz/crcs/ectester/data/secp256k1.txt +++ b/src/cz/crcs/ectester/data/secg/secp256k1.txt diff --git a/src/cz/crcs/ectester/data/secp256r1.txt b/src/cz/crcs/ectester/data/secg/secp256r1.txt index 060f5aa..060f5aa 100644 --- a/src/cz/crcs/ectester/data/secp256r1.txt +++ b/src/cz/crcs/ectester/data/secg/secp256r1.txt diff --git a/src/cz/crcs/ectester/data/secp384r1.txt b/src/cz/crcs/ectester/data/secg/secp384r1.txt index 08472ae..08472ae 100644 --- a/src/cz/crcs/ectester/data/secp384r1.txt +++ b/src/cz/crcs/ectester/data/secg/secp384r1.txt diff --git a/src/cz/crcs/ectester/data/secp521r1.txt b/src/cz/crcs/ectester/data/secg/secp521r1.txt index 9e0f5d3..9e0f5d3 100644 --- a/src/cz/crcs/ectester/data/secp521r1.txt +++ b/src/cz/crcs/ectester/data/secg/secp521r1.txt diff --git a/src/cz/crcs/ectester/data/sect163k1.txt b/src/cz/crcs/ectester/data/secg/sect163k1.txt index 6e5142e..6e5142e 100644 --- a/src/cz/crcs/ectester/data/sect163k1.txt +++ b/src/cz/crcs/ectester/data/secg/sect163k1.txt diff --git a/src/cz/crcs/ectester/data/sect163r1.txt b/src/cz/crcs/ectester/data/secg/sect163r1.txt index 879f79b..879f79b 100644 --- a/src/cz/crcs/ectester/data/sect163r1.txt +++ b/src/cz/crcs/ectester/data/secg/sect163r1.txt diff --git a/src/cz/crcs/ectester/data/sect163r2.txt b/src/cz/crcs/ectester/data/secg/sect163r2.txt index eb7d453..eb7d453 100644 --- a/src/cz/crcs/ectester/data/sect163r2.txt +++ b/src/cz/crcs/ectester/data/secg/sect163r2.txt diff --git a/src/cz/crcs/ectester/data/sect233k1.txt b/src/cz/crcs/ectester/data/secg/sect233k1.txt index b85fef0..b85fef0 100644 --- a/src/cz/crcs/ectester/data/sect233k1.txt +++ b/src/cz/crcs/ectester/data/secg/sect233k1.txt diff --git a/src/cz/crcs/ectester/data/sect233r1.txt b/src/cz/crcs/ectester/data/secg/sect233r1.txt index d0c6f14..d0c6f14 100644 --- a/src/cz/crcs/ectester/data/sect233r1.txt +++ b/src/cz/crcs/ectester/data/secg/sect233r1.txt diff --git a/src/cz/crcs/ectester/data/sect239k1.txt b/src/cz/crcs/ectester/data/secg/sect239k1.txt index d01bb08..d01bb08 100644 --- a/src/cz/crcs/ectester/data/sect239k1.txt +++ b/src/cz/crcs/ectester/data/secg/sect239k1.txt diff --git a/src/cz/crcs/ectester/data/sect283k1.txt b/src/cz/crcs/ectester/data/secg/sect283k1.txt index cc62698..cc62698 100644 --- a/src/cz/crcs/ectester/data/sect283k1.txt +++ b/src/cz/crcs/ectester/data/secg/sect283k1.txt diff --git a/src/cz/crcs/ectester/data/sect283r1.txt b/src/cz/crcs/ectester/data/secg/sect283r1.txt index 27e2ff2..27e2ff2 100644 --- a/src/cz/crcs/ectester/data/sect283r1.txt +++ b/src/cz/crcs/ectester/data/secg/sect283r1.txt diff --git a/src/cz/crcs/ectester/data/sect409k1.txt b/src/cz/crcs/ectester/data/secg/sect409k1.txt index aeb2e76..aeb2e76 100644 --- a/src/cz/crcs/ectester/data/sect409k1.txt +++ b/src/cz/crcs/ectester/data/secg/sect409k1.txt diff --git a/src/cz/crcs/ectester/data/sect409r1.txt b/src/cz/crcs/ectester/data/secg/sect409r1.txt index 5ac19dc..5ac19dc 100644 --- a/src/cz/crcs/ectester/data/sect409r1.txt +++ b/src/cz/crcs/ectester/data/secg/sect409r1.txt diff --git a/src/cz/crcs/ectester/data/sect571k1.txt b/src/cz/crcs/ectester/data/secg/sect571k1.txt index 7d5fdf4..7d5fdf4 100644 --- a/src/cz/crcs/ectester/data/sect571k1.txt +++ b/src/cz/crcs/ectester/data/secg/sect571k1.txt diff --git a/src/cz/crcs/ectester/data/sect571r1.txt b/src/cz/crcs/ectester/data/secg/sect571r1.txt index 850f0b9..850f0b9 100644 --- a/src/cz/crcs/ectester/data/sect571r1.txt +++ b/src/cz/crcs/ectester/data/secg/sect571r1.txt diff --git a/src/cz/crcs/ectester/data/ecsp128.txt b/src/cz/crcs/ectester/data/smallpub/ecsp128.txt index 29cfe3b..29cfe3b 100644 --- a/src/cz/crcs/ectester/data/ecsp128.txt +++ b/src/cz/crcs/ectester/data/smallpub/ecsp128.txt diff --git a/src/cz/crcs/ectester/data/ecsp128_pub.txt b/src/cz/crcs/ectester/data/smallpub/ecsp128_pub.txt index ee1f34d..ee1f34d 100644 --- a/src/cz/crcs/ectester/data/ecsp128_pub.txt +++ b/src/cz/crcs/ectester/data/smallpub/ecsp128_pub.txt diff --git a/src/cz/crcs/ectester/data/ecsp160.txt b/src/cz/crcs/ectester/data/smallpub/ecsp160.txt index 49824d9..49824d9 100644 --- a/src/cz/crcs/ectester/data/ecsp160.txt +++ b/src/cz/crcs/ectester/data/smallpub/ecsp160.txt diff --git a/src/cz/crcs/ectester/data/ecsp160_pub.txt b/src/cz/crcs/ectester/data/smallpub/ecsp160_pub.txt index e2e164e..e2e164e 100644 --- a/src/cz/crcs/ectester/data/ecsp160_pub.txt +++ b/src/cz/crcs/ectester/data/smallpub/ecsp160_pub.txt diff --git a/src/cz/crcs/ectester/data/ecsp192.txt b/src/cz/crcs/ectester/data/smallpub/ecsp192.txt index ccb5537..ccb5537 100644 --- a/src/cz/crcs/ectester/data/ecsp192.txt +++ b/src/cz/crcs/ectester/data/smallpub/ecsp192.txt diff --git a/src/cz/crcs/ectester/data/ecsp192_pub.txt b/src/cz/crcs/ectester/data/smallpub/ecsp192_pub.txt index ec7f822..ec7f822 100644 --- a/src/cz/crcs/ectester/data/ecsp192_pub.txt +++ b/src/cz/crcs/ectester/data/smallpub/ecsp192_pub.txt diff --git a/src/cz/crcs/ectester/data/ecsp224.txt b/src/cz/crcs/ectester/data/smallpub/ecsp224.txt index 894e669..894e669 100644 --- a/src/cz/crcs/ectester/data/ecsp224.txt +++ b/src/cz/crcs/ectester/data/smallpub/ecsp224.txt diff --git a/src/cz/crcs/ectester/data/ecsp224_pub.txt b/src/cz/crcs/ectester/data/smallpub/ecsp224_pub.txt index 0999b99..0999b99 100644 --- a/src/cz/crcs/ectester/data/ecsp224_pub.txt +++ b/src/cz/crcs/ectester/data/smallpub/ecsp224_pub.txt diff --git a/src/cz/crcs/ectester/data/ecsp256.txt b/src/cz/crcs/ectester/data/smallpub/ecsp256.txt index 17387a6..17387a6 100644 --- a/src/cz/crcs/ectester/data/ecsp256.txt +++ b/src/cz/crcs/ectester/data/smallpub/ecsp256.txt diff --git a/src/cz/crcs/ectester/data/ecsp256_pub.txt b/src/cz/crcs/ectester/data/smallpub/ecsp256_pub.txt index a8f0492..a8f0492 100644 --- a/src/cz/crcs/ectester/data/ecsp256_pub.txt +++ b/src/cz/crcs/ectester/data/smallpub/ecsp256_pub.txt diff --git a/src/cz/crcs/ectester/data/ecsp384.txt b/src/cz/crcs/ectester/data/smallpub/ecsp384.txt index 9acae3f..9acae3f 100644 --- a/src/cz/crcs/ectester/data/ecsp384.txt +++ b/src/cz/crcs/ectester/data/smallpub/ecsp384.txt diff --git a/src/cz/crcs/ectester/data/ecsp384_pub.txt b/src/cz/crcs/ectester/data/smallpub/ecsp384_pub.txt index 4eb4a96..4eb4a96 100644 --- a/src/cz/crcs/ectester/data/ecsp384_pub.txt +++ b/src/cz/crcs/ectester/data/smallpub/ecsp384_pub.txt diff --git a/src/cz/crcs/ectester/data/ecsp521.txt b/src/cz/crcs/ectester/data/smallpub/ecsp521.txt index 1d36bd7..1d36bd7 100644 --- a/src/cz/crcs/ectester/data/ecsp521.txt +++ b/src/cz/crcs/ectester/data/smallpub/ecsp521.txt diff --git a/src/cz/crcs/ectester/data/ecsp521_pub.txt b/src/cz/crcs/ectester/data/smallpub/ecsp521_pub.txt index 0e3f320..0e3f320 100644 --- a/src/cz/crcs/ectester/data/ecsp521_pub.txt +++ b/src/cz/crcs/ectester/data/smallpub/ecsp521_pub.txt diff --git a/src/cz/crcs/ectester/reader/CardMngr.java b/src/cz/crcs/ectester/reader/CardMngr.java index 9cdd055..d95b7e5 100644 --- a/src/cz/crcs/ectester/reader/CardMngr.java +++ b/src/cz/crcs/ectester/reader/CardMngr.java @@ -255,11 +255,13 @@ public class CardMngr { public ResponseAPDU sendAPDUSimulator(CommandAPDU apdu) { System.out.println(">>>>"); + System.out.println(apdu); System.out.println(Util.bytesToHex(apdu.getBytes())); ResponseAPDU response = simulator.transmitCommand(apdu); byte[] responseBytes = response.getBytes(); + System.out.println(response); System.out.println(Util.bytesToHex(responseBytes)); System.out.println("<<<<"); @@ -285,13 +287,4 @@ public class CardMngr { CommandAPDU commandAPDU = new CommandAPDU(apdu); return send(commandAPDU); } - - public ResponseAPDU[] send(CommandAPDU... apdus) throws CardException { - ResponseAPDU[] result = new ResponseAPDU[apdus.length]; - for (int i = 0; i < apdus.length; i++) { - result[i] = send(apdus[i]); - } - return result; - } - } diff --git a/src/cz/crcs/ectester/reader/Command.java b/src/cz/crcs/ectester/reader/Command.java new file mode 100644 index 0000000..c5fd465 --- /dev/null +++ b/src/cz/crcs/ectester/reader/Command.java @@ -0,0 +1,241 @@ +package cz.crcs.ectester.reader; + +import cz.crcs.ectester.applet.ECTesterApplet; + +import javax.smartcardio.CardException; +import javax.smartcardio.CommandAPDU; +import javax.smartcardio.ResponseAPDU; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public abstract class Command { + protected CommandAPDU cmd; + protected CardMngr cardManager; + + protected Command(CardMngr cardManager) { + this.cardManager = cardManager; + } + + public CommandAPDU getAPDU() { + return cmd; + } + + /** + * + * @return + * @throws CardException + */ + public abstract Response send() throws CardException; + + public static List<Response> sendAll(List<Command> commands) throws CardException { + List<Response> result = new ArrayList<>(); + for (Command cmd : commands) { + result.add(cmd.send()); + } + return result; + } + + /** + * + */ + public static class Allocate extends Command { + private byte keyPair; + private short keyLength; + private byte keyClass; + + /** + * Creates the INS_ALLOCATE instruction. + * + * @param cardManager + * @param keyPair which keyPair to use, local/remote (KEYPAIR_* | ...) + * @param keyLength key length to set + * @param keyClass key class to allocate + */ + public Allocate(CardMngr cardManager, byte keyPair, short keyLength, byte keyClass) { + super(cardManager); + this.keyPair = keyPair; + this.keyLength = keyLength; + this.keyClass = keyClass; + + byte[] data = new byte[]{0, 0, keyClass}; + Util.setShort(data, 0, keyLength); + this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ALLOCATE, keyPair, 0x00, data); + } + + @Override + public Response.Allocate send() throws CardException { + long elapsed = -System.nanoTime(); + ResponseAPDU response = cardManager.send(cmd); + elapsed += System.nanoTime(); + return new Response.Allocate(response, elapsed, keyPair, keyLength, keyClass); + } + } + + /** + * + */ + public static class Set extends Command { + private byte keyPair; + private byte export; + private byte curve; + private short params; + private short corrupted; + private byte corruption; + private byte[] external; + + /** + * Creates the INS_SET instruction. + * + * @param cardManager + * @param keyPair which keyPair to set params on, local/remote (KEYPAIR_* || ...) + * @param export whether to export set params from keyPair + * @param curve curve to set (EC_Consts.CURVE_*) + * @param params parameters to set (EC_Consts.PARAMETER_* | ...) + * @param corrupted parameters to corrupt (EC_Consts.PARAMETER_* | ...) + * @param corruption corruption type (EC_Consts.CORRUPTION_*) + * @param external external curve data, can be null + */ + public Set(CardMngr cardManager, byte keyPair, byte export, byte curve, short params, short corrupted, byte corruption, byte[] external) { + super(cardManager); + this.keyPair = keyPair; + this.export = export; + this.curve = curve; + this.params = params; + this.corrupted = corrupted; + this.corruption = corruption; + this.external = external; + + int len = external != null ? 6 + 2 + external.length : 6; + byte[] data = new byte[len]; + data[0] = curve; + Util.setShort(data, 1, params); + Util.setShort(data, 3, corrupted); + data[5] = corruption; + if (external != null) { + System.arraycopy(external, 0, data, 6, external.length); + } + + this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_SET, keyPair, export, data); + } + + @Override + public Response.Set send() throws CardException { + long elapsed = -System.nanoTime(); + ResponseAPDU response = cardManager.send(cmd); + elapsed += System.nanoTime(); + return new Response.Set(response, elapsed, keyPair, export, curve, params, corrupted); + } + } + + /** + * + */ + public static class Generate extends Command { + private byte keyPair; + private byte export; + + /** + * Creates the INS_GENERATE instruction. + * + * @param cardManager + * @param keyPair which keyPair to generate, local/remote (KEYPAIR_* || ...) + * @param export whether to export generated keys from keyPair + */ + public Generate(CardMngr cardManager, byte keyPair, byte export) { + super(cardManager); + this.keyPair = keyPair; + this.export = export; + + this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_GENERATE, keyPair, export); + } + + @Override + public Response.Generate send() throws CardException { + long elapsed = -System.nanoTime(); + ResponseAPDU response = cardManager.send(cmd); + elapsed += System.nanoTime(); + return new Response.Generate(response, elapsed, keyPair, export); + } + } + + /** + * + */ + public static class ECDH extends Command { + private byte pubkey; + private byte privkey; + private byte export; + private byte invalid; + + /** + * Creates the INS_ECDH instruction. + * + * @param cardManager + * @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 invalid whether to invalidate the pubkey before ECDH + */ + public ECDH(CardMngr cardManager, byte pubkey, byte privkey, byte export, byte invalid) { + super(cardManager); + this.pubkey = pubkey; + this.privkey = privkey; + this.export = export; + this.invalid = invalid; + + byte[] data = new byte[]{export, invalid}; + + this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDH, pubkey, privkey, data); + } + + @Override + public Response.ECDH send() throws CardException { + long elapsed = -System.nanoTime(); + ResponseAPDU response = cardManager.send(cmd); + elapsed += System.nanoTime(); + return new Response.ECDH(response, elapsed, pubkey, privkey, export, invalid); + } + } + + public static class ECDSA extends Command { + private byte keyPair; + private byte export; + private byte[] raw; + + /** + * Creates the INS_ECDSA instruction. + * + * @param cardManager + * @param keyPair keyPair to use for signing and verification (KEYPAIR_LOCAL || KEYPAIR_REMOTE) + * @param export whether to export ECDSA signature + * @param raw data to sign, can be null, in which case random data is signed. + */ + public ECDSA(CardMngr cardManager, byte keyPair, byte export, byte[] raw) { + super(cardManager); + this.keyPair = keyPair; + this.export = export; + this.raw = raw; + + int len = raw != null ? raw.length : 0; + byte[] data = new byte[2 + len]; + Util.setShort(data, 0, (short) len); + if (raw != null) { + System.arraycopy(raw, 0, data, 2, len); + } + + this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDSA, keyPair, export, data); + } + + @Override + public Response.ECDSA send() throws CardException { + long elapsed = -System.nanoTime(); + ResponseAPDU response = cardManager.send(cmd); + elapsed += System.nanoTime(); + return new Response.ECDSA(response, elapsed, keyPair, export, raw); + } + } +} + diff --git a/src/cz/crcs/ectester/reader/DirtyLogger.java b/src/cz/crcs/ectester/reader/DirtyLogger.java index f69557d..7a2c70d 100644 --- a/src/cz/crcs/ectester/reader/DirtyLogger.java +++ b/src/cz/crcs/ectester/reader/DirtyLogger.java @@ -2,6 +2,7 @@ package cz.crcs.ectester.reader; import java.io.FileWriter; import java.io.IOException; +import java.io.OutputStream; /** * @author Petr Svenda petr@svenda.com diff --git a/src/cz/crcs/ectester/reader/ECTester.java b/src/cz/crcs/ectester/reader/ECTester.java index 1f70d4f..e5a2b70 100644 --- a/src/cz/crcs/ectester/reader/ECTester.java +++ b/src/cz/crcs/ectester/reader/ECTester.java @@ -27,15 +27,12 @@ import javacard.security.KeyPair; import org.apache.commons.cli.*; import javax.smartcardio.CardException; -import javax.smartcardio.CommandAPDU; -import javax.smartcardio.ResponseAPDU; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; -import java.util.Comparator; import java.util.List; /** @@ -187,10 +184,8 @@ public class ECTester { } } catch (MissingArgumentException maex) { System.err.println("Option, " + maex.getOption().getOpt() + " requires an argument: " + maex.getOption().getArgName()); - } catch (AlreadySelectedException asex) { - System.err.println(asex.getMessage()); } catch (ParseException | CardException pex) { - pex.printStackTrace(); + System.err.println(pex.getMessage()); } catch (NumberFormatException nfex) { System.err.println("Not a number. " + nfex.getMessage()); nfex.printStackTrace(System.err); @@ -370,8 +365,7 @@ public class ECTester { */ private void generate() throws CardException, IOException { byte keyClass = optPrimeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M; - CommandAPDU[] prepare = prepareCurve(ECTesterApplet.KEYPAIR_LOCAL, (short) optBits, keyClass); - cardManager.send(prepare); + List<Response> prepare = Command.sendAll(prepareCurve(ECTesterApplet.KEYPAIR_LOCAL, (short) optBits, keyClass)); FileWriter keysFile = new FileWriter(optOutput); keysFile.write("index;time;pubW;privS\n"); @@ -379,30 +373,27 @@ public class ECTester { int generated = 0; int retry = 0; while (generated < optGenerateAmount || optGenerateAmount == 0) { - CommandAPDU generate = insGenerate(ECTesterApplet.KEYPAIR_LOCAL, (byte) (ECTesterApplet.EXPORT_BOTH | ECTesterApplet.KEYPAIR_LOCAL)); - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(generate); - elapsed += System.nanoTime(); + Command.Generate generate = new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, (byte) (ECTesterApplet.EXPORT_BOTH | ECTesterApplet.KEYPAIR_LOCAL)); + Response.Generate response = generate.send(); + long elapsed = response.getDuration(); - byte[] bytes = response.getData(); - if (bytes.length <= 2) { - //error, retry 10 times + if (!response.successful()) { if (retry < 10) { retry++; + continue; } else { System.err.println("Keys could not be generated."); break; } - } else { - short publicLength = Util.getShort(bytes, 2); - String pubkey = Util.bytesToHex(bytes, 4, publicLength, false); - short privateLength = Util.getShort(bytes, 4 + publicLength); - String privkey = Util.bytesToHex(bytes, 6 + publicLength, privateLength, false); - - keysFile.write(String.format("%d;%d;%s;%s\n", generated, elapsed / 1000000, pubkey, privkey)); - keysFile.flush(); - generated++; } + systemOutLogger.println(response.toString()); + + String pub = Util.bytesToHex(response.getPublic(ECTesterApplet.KEYPAIR_LOCAL), false); + String priv = Util.bytesToHex(response.getPrivate(ECTesterApplet.KEYPAIR_LOCAL), false); + String line = String.format("%d;%d;%s;%s\n", generated, elapsed / 1000000, pub, priv); + keysFile.write(line); + keysFile.flush(); + generated++; } keysFile.close(); } @@ -460,23 +451,24 @@ public class ECTester { */ private void ecdh() throws IOException, CardException { byte keyClass = optPrimeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M; - CommandAPDU[] curve = prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, keyClass); - cardManager.send(curve); + List<Response> ecdh = Command.sendAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, keyClass)); if (optPublic != null || optPrivate != null || optKey != null) { - CommandAPDU local = insGenerate(ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_NONE); - cardManager.send(local); - CommandAPDU remote = prepareKey(ECTesterApplet.KEYPAIR_REMOTE); - cardManager.send(remote); + Response local = new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_NONE).send(); + Response remote = prepareKey(ECTesterApplet.KEYPAIR_REMOTE).send(); + ecdh.add(local); + ecdh.add(remote); } else { - CommandAPDU both = insGenerate(ECTesterApplet.KEYPAIR_BOTH, ECTesterApplet.EXPORT_NONE); - cardManager.send(both); + Response both = new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_BOTH, ECTesterApplet.EXPORT_NONE).send(); + ecdh.add(both); } - CommandAPDU ecdh = insECDH(ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_ECDH, (byte) 0); - ResponseAPDU response = cardManager.send(ecdh); - //TODO print response SWs/error codes - //TODO output to file + Response.ECDH perform = new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_ECDH, (byte) 0).send(); + ecdh.add(perform); + for (Response r : ecdh) { + systemOutLogger.println(r.toString()); + } + //TODO check perform.hasSecret(), write perform.getSecret to file if -o } /** @@ -487,16 +479,15 @@ public class ECTester { */ private void ecdsa() throws CardException, IOException { byte keyClass = optPrimeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M; - CommandAPDU[] curve = prepareCurve(ECTesterApplet.KEYPAIR_LOCAL, (short) optBits, keyClass); - cardManager.send(curve); + List<Response> ecdsa = Command.sendAll(prepareCurve(ECTesterApplet.KEYPAIR_LOCAL, (short) optBits, keyClass)); + Response keys; if (optKey != null || (optPublic != null && optPrivate != null)) { - CommandAPDU set = prepareKey(ECTesterApplet.KEYPAIR_LOCAL); - cardManager.send(set); + keys = prepareKey(ECTesterApplet.KEYPAIR_LOCAL).send(); } else { - CommandAPDU generate = insGenerate(ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_NONE); - cardManager.send(generate); + keys = new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_NONE).send(); } + ecdsa.add(keys); //read file, if asked to sign byte[] data = null; @@ -509,96 +500,12 @@ public class ECTester { data = Files.readAllBytes(in.toPath()); } - CommandAPDU ecdsa = insECDSA(ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_SIG, data); - ResponseAPDU response = cardManager.send(ecdsa); - //TODO print response SWs/error codes - //TODO output to file - } - - /** - * Creates the INS_ALLOCATE instruction. - * - * @param keyPair which keyPair to use, local/remote (KEYPAIR_* | ...) - * @param keyLength key length to set - * @param keyClass key class to allocate - * @return apdu to send - */ - private CommandAPDU insAllocate(byte keyPair, short keyLength, byte keyClass) { - byte[] data = new byte[]{0, 0, keyClass}; - Util.setShort(data, 0, keyLength); - - return new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ALLOCATE, keyPair, 0x00, data); - } - - /** - * Creates the INS_SET instruction. - * - * @param keyPair which keyPair to set params on, local/remote (KEYPAIR_* || ...) - * @param export whether to export set params from keyPair - * @param curve curve to set (EC_Consts.CURVE_*) - * @param params parameters to set (EC_Consts.PARAMETER_* | ...) - * @param corrupted parameters to corrupt (EC_Consts.PARAMETER_* | ...) - * @param corruption corruption type (EC_Consts.CORRUPTION_*) - * @param external external curve data, can be null - * @return apdu to send - */ - private CommandAPDU insSet(byte keyPair, byte export, byte curve, short params, short corrupted, byte corruption, byte[] external) { - int len = external != null ? 6 + 2 + external.length : 6; - byte[] data = new byte[len]; - data[0] = curve; - Util.setShort(data, 1, params); - Util.setShort(data, 3, corrupted); - data[5] = corruption; - if (external != null) { - System.arraycopy(external, 0, data, 6, external.length); - } - - return new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_SET, keyPair, export, data); - } - - /** - * Creates the INS_GENERATE instruction. - * - * @param keyPair which keyPair to generate, local/remote (KEYPAIR_* || ...) - * @param export whether to export generated keys from keyPair - * @return apdu to send - */ - private CommandAPDU insGenerate(byte keyPair, byte export) { - return new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_GENERATE, keyPair, export); - } - - /** - * Creates the INS_ECDH instruction. - * - * @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 invalid whether to invalidate the pubkey before ECDH - * @return apdu to send - */ - private CommandAPDU insECDH(byte pubkey, byte privkey, byte export, byte invalid) { - byte[] data = new byte[]{export, invalid}; - - return new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDH, pubkey, privkey, data); - } - - /** - * Creates the INS_ECDSA instruction. - * - * @param keyPair keyPair to use for signing and verification (KEYPAIR_LOCAL || KEYPAIR_REMOTE) - * @param export whether to export ECDSA signature - * @param raw data to sign, can be null, in which case random data is signed. - * @return apdu to send - */ - private CommandAPDU insECDSA(byte keyPair, byte export, byte[] raw) { - int len = raw != null ? raw.length : 0; - byte[] data = new byte[2 + len]; - Util.setShort(data, 0, (short) len); - if (raw != null) { - System.arraycopy(raw, 0, data, 2, len); + Response.ECDSA perform = new Command.ECDSA(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_SIG, data).send(); + ecdsa.add(perform); + for (Response r : ecdsa) { + systemOutLogger.println(r.toString()); } - - return new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDSA, keyPair, export, data); + //TODO output to file } /** @@ -608,23 +515,23 @@ public class ECTester { * @return an array of CommandAPDUs to send in order to prepare the keypair/s. * @throws IOException if curve file cannot be found/opened */ - private CommandAPDU[] prepareCurve(byte keyPair, short keyLength, byte keyClass) throws IOException { - List<CommandAPDU> commands = new ArrayList<>(); - commands.add(insAllocate(keyPair, keyLength, keyClass)); + private List<Command> prepareCurve(byte keyPair, short keyLength, byte keyClass) throws IOException { + List<Command> commands = new ArrayList<>(); + commands.add(new Command.Allocate(cardManager, keyPair, keyLength, keyClass)); short domainParams = keyClass == KeyPair.ALG_EC_FP ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M; if (optNamed) { - commands.add(insSet(keyPair, ECTesterApplet.EXPORT_NONE, EC_Consts.getCurve(keyLength, keyClass), domainParams, EC_Consts.PARAMETERS_NONE, EC_Consts.CORRUPTION_NONE, null)); + commands.add(new Command.Set(cardManager, keyPair, ECTesterApplet.EXPORT_NONE, EC_Consts.getCurve(keyLength, keyClass), domainParams, EC_Consts.PARAMETERS_NONE, EC_Consts.CORRUPTION_NONE, null)); } if (optCurve != null) { byte[] external = ParamReader.flatten(domainParams, ParamReader.readFile(optCurve)); if (external == null) { throw new IOException("Couldn't read the curve file correctly."); } - commands.add(insSet(keyPair, ECTesterApplet.EXPORT_NONE, EC_Consts.CURVE_external, domainParams, EC_Consts.PARAMETERS_NONE, EC_Consts.CORRUPTION_NONE, external)); + commands.add(new Command.Set(cardManager, keyPair, ECTesterApplet.EXPORT_NONE, EC_Consts.CURVE_external, domainParams, EC_Consts.PARAMETERS_NONE, EC_Consts.CORRUPTION_NONE, external)); } - return commands.toArray(new CommandAPDU[commands.size()]); + return commands; } /** @@ -632,7 +539,7 @@ public class ECTester { * @return a CommandAPDU setting params loaded on the keyPair/s * @throws IOException if any of the key files cannot be found/opened */ - private CommandAPDU prepareKey(byte keyPair) throws IOException { + private Command prepareKey(byte keyPair) throws IOException { short params = EC_Consts.PARAMETERS_NONE; byte[] data = null; if (optKey != null) { @@ -656,7 +563,7 @@ public class ECTester { */ throw new IOException("Couldn't read the key file correctly."); } - return insSet(keyPair, ECTesterApplet.EXPORT_NONE, EC_Consts.CURVE_external, params, EC_Consts.PARAMETERS_NONE, EC_Consts.CORRUPTION_NONE, data); + return new Command.Set(cardManager, keyPair, ECTesterApplet.EXPORT_NONE, EC_Consts.CURVE_external, params, EC_Consts.PARAMETERS_NONE, EC_Consts.CORRUPTION_NONE, data); } public static void main(String[] args) { diff --git a/src/cz/crcs/ectester/reader/Response.java b/src/cz/crcs/ectester/reader/Response.java new file mode 100644 index 0000000..8f9ab9b --- /dev/null +++ b/src/cz/crcs/ectester/reader/Response.java @@ -0,0 +1,410 @@ +package cz.crcs.ectester.reader; + +import cz.crcs.ectester.applet.ECTesterApplet; +import cz.crcs.ectester.applet.EC_Consts; +import javacard.framework.ISO7816; +import javacard.security.KeyPair; + +import javax.smartcardio.ResponseAPDU; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public abstract class Response { + protected ResponseAPDU resp; + protected long time; + protected short sw1 = 0; + protected short sw2 = 0; + protected byte[][] params; + protected boolean success = true; + + protected Response(ResponseAPDU response, long time) { + this.resp = response; + this.time = time; + } + + protected void parse(int numSW, int numParams) { + byte[] data = resp.getData(); + int offset = 0; + + //parse SWs in response + if (--numSW >= 0 && getLength() >= 2) { + sw1 = Util.getShort(data, offset); + offset += 2; + if (sw1 != ISO7816.SW_NO_ERROR) + success = false; + } + if (--numSW >= 0 && getLength() >= 4) { + sw2 = Util.getShort(data, offset); + offset += 2; + if (sw2 != ISO7816.SW_NO_ERROR) + success = false; + } + + //try to parse numParams.. + params = new byte[numParams][]; + for (int i = 0; i < numParams; i++) { + if (data.length - offset < 2) { + success = false; + break; + } + short paramLength = Util.getShort(data, offset); + offset += 2; + if (data.length < offset + paramLength) { + success = false; + break; + } + params[i] = new byte[paramLength]; + System.arraycopy(data, offset, params[i], 0, paramLength); + offset += paramLength; + } + } + + protected boolean hasParam(int index) { + return params.length >= index + 1 && params[index] != null; + } + + protected int getParamLength(int index) { + return params[index].length; + } + + protected byte[] getParam(int index) { + return params[index]; + } + + public ResponseAPDU getAPDU() { + return resp; + } + + public long getDuration() { + return time; + } + + public int getNaturalSW() { + return resp.getSW(); + } + + public short getSW1() { + return sw1; + } + + public short getSW2() { + return sw2; + } + + public int getLength() { + return resp.getNr(); + } + + public boolean successful() { + return this.success; + } + + @Override + public abstract String toString(); + + + /** + * + */ + public static class Allocate extends Response { + private byte keyPair; + private short keyLength; + private byte keyClass; + + public Allocate(ResponseAPDU response, long time, byte keyPair, short keyLength, byte keyClass) { + super(response, time); + this.keyPair = keyPair; + this.keyLength = keyLength; + this.keyClass = keyClass; + + int pairs = 0; + if ((keyPair & ECTesterApplet.KEYPAIR_LOCAL) != 0) pairs++; + if ((keyPair & ECTesterApplet.KEYPAIR_REMOTE) != 0) pairs++; + parse(pairs, 0); + } + + @Override + public String toString() { + String field = keyClass == KeyPair.ALG_EC_FP ? "ALG_EC_FP" : "ALG_EC_F2M"; + String key; + if (keyPair == ECTesterApplet.KEYPAIR_BOTH) { + key = "both keypairs"; + } else { + key = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair"; + } + //TODO general response.toString alignment + 2 SWs + return String.format("Allocated %s %db %s: %#x", key, keyLength, field, getSW1()); + } + } + + /** + * + */ + public static class Set extends Response { + private byte keyPair; + private byte export; + private byte curve; + private short params; + private short corrupted; + + protected Set(ResponseAPDU response, long time, byte keyPair, byte export, byte curve, short params, short corrupted) { + super(response, time); + this.keyPair = keyPair; + this.export = export; + this.curve = curve; + this.params = params; + this.corrupted = corrupted; + + int pairs = 0; + if ((keyPair & ECTesterApplet.KEYPAIR_LOCAL) != 0) pairs++; + if ((keyPair & ECTesterApplet.KEYPAIR_REMOTE) != 0) pairs++; + int exported = 0; + if ((export & ECTesterApplet.KEYPAIR_LOCAL) != 0) exported++; + if ((export & ECTesterApplet.KEYPAIR_REMOTE) != 0) exported++; + int keys = 0; + if ((export & ECTesterApplet.EXPORT_PUBLIC) != 0) keys++; + if ((export & ECTesterApplet.EXPORT_PRIVATE) != 0) keys++; + int paramCount = 0; + short mask = EC_Consts.PARAMETER_FP; + while (mask <= EC_Consts.PARAMETER_K) { + if ((mask & params) != 0) { + paramCount++; + } + mask = (short) (mask << 1); + } + int other = 0; + if ((export & ECTesterApplet.EXPORT_PUBLIC) != 0 && (params & EC_Consts.PARAMETER_W) != 0) other++; + if ((export & ECTesterApplet.EXPORT_PRIVATE) != 0 && (params & EC_Consts.PARAMETER_S) != 0) other++; + + parse(pairs, exported * keys * paramCount + exported * other); + } + + private int getIndex(byte keyPair, short param) { + byte key = ECTesterApplet.KEYPAIR_LOCAL; + int index = 0; + while (key <= ECTesterApplet.KEYPAIR_REMOTE) { + short mask = EC_Consts.PARAMETER_FP; + while (mask <= EC_Consts.PARAMETER_S) { + if (key == keyPair && param == mask) { + return index; + } + if ((params & mask) != 0 && (key & export) != 0) { + if (mask == EC_Consts.PARAMETER_W) { + if ((export & ECTesterApplet.EXPORT_PUBLIC) != 0) + index++; + } else if (mask == EC_Consts.PARAMETER_S) { + if ((export & ECTesterApplet.EXPORT_PRIVATE) != 0) + index++; + } else { + index++; + } + } + mask = (short) (mask << 1); + } + + key = (byte) (key << 1); + } + return -1; + } + + public boolean hasParameter(byte keyPair, short param) { + return !((export & keyPair) == 0 || (params & param) == 0) && getIndex(keyPair, param) != -1; + } + + public byte[] getParameter(byte keyPair, short param) { + return getParam(getIndex(keyPair, param)); + } + + @Override + public String toString() { + String name; + switch (curve) { + case EC_Consts.CURVE_default: + name = "default"; + break; + case EC_Consts.CURVE_external: + name = "external"; + break; + default: + name = "custom"; + break; + } + String key; + if (keyPair == ECTesterApplet.KEYPAIR_BOTH) { + key = "both keypairs"; + } else { + key = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair"; + } + //TODO general response.toString alignment + 2 SWs + return String.format("Set %s curve parameters on %s: %#x", name, key, getSW1()); + } + + } + + /** + * + */ + public static class Generate extends Response { + private byte keyPair; + private byte export; + private short[] contents; + + protected Generate(ResponseAPDU response, long time, byte keyPair, byte export) { + super(response, time); + this.keyPair = keyPair; + this.export = export; + + int keys = 0; + if ((export & ECTesterApplet.EXPORT_PUBLIC) != 0) keys++; + if ((export & ECTesterApplet.EXPORT_PRIVATE) != 0) keys++; + int pairs = 0; + if ((export & ECTesterApplet.KEYPAIR_LOCAL) != 0) pairs++; + if ((export & ECTesterApplet.KEYPAIR_REMOTE) != 0) pairs++; + int generated = 0; + if ((keyPair & ECTesterApplet.KEYPAIR_LOCAL) != 0) generated++; + if ((keyPair & ECTesterApplet.KEYPAIR_REMOTE) != 0) generated++; + parse(generated, keys * pairs); + + this.contents = new short[4]; + int offset = 0; + if ((export & ECTesterApplet.KEYPAIR_LOCAL) != 0) { + if ((export & ECTesterApplet.EXPORT_PUBLIC) != 0) { + this.contents[offset] = ECTesterApplet.KEYPAIR_LOCAL | ECTesterApplet.EXPORT_PUBLIC; + offset++; + } + if ((export & ECTesterApplet.EXPORT_PRIVATE) != 0) { + this.contents[offset] = ECTesterApplet.KEYPAIR_LOCAL | ECTesterApplet.EXPORT_PRIVATE; + offset++; + } + } + if ((export & ECTesterApplet.KEYPAIR_REMOTE) != 0) { + if ((export & ECTesterApplet.EXPORT_PUBLIC) != 0) { + this.contents[offset] = ECTesterApplet.KEYPAIR_REMOTE | ECTesterApplet.EXPORT_PUBLIC; + offset++; + } + if ((export & ECTesterApplet.EXPORT_PRIVATE) != 0) { + this.contents[offset] = ECTesterApplet.KEYPAIR_REMOTE | ECTesterApplet.EXPORT_PRIVATE; + offset++; + } + } + } + + private int getIndex(byte key) { + for (int i = 0; i < contents.length; i++) { + if (key == contents[i]) + return i; + } + return -1; + } + + public boolean hasPublic(byte keyPair) { + if ((export & ECTesterApplet.EXPORT_PUBLIC) == 0 || (export & keyPair) == 0) + return false; + return getIndex((byte) (keyPair | ECTesterApplet.EXPORT_PUBLIC)) != -1; + } + + public boolean hasPrivate(byte keyPair) { + if ((export & ECTesterApplet.EXPORT_PRIVATE) == 0 || (export & keyPair) == 0) + return false; + return getIndex((byte) (keyPair | ECTesterApplet.EXPORT_PRIVATE)) != -1; + } + + public byte[] getPublic(byte keyPair) { + //calculate index and getParam + int index = getIndex((byte) (keyPair | ECTesterApplet.EXPORT_PUBLIC)); + return getParam(index); + } + + public byte[] getPrivate(byte keyPair) { + //calculate index and getParam + int index = getIndex((byte) (keyPair | ECTesterApplet.EXPORT_PRIVATE)); + return getParam(index); + } + + @Override + public String toString() { + String key; + if (keyPair == ECTesterApplet.KEYPAIR_BOTH) { + key = "both keypairs"; + } else { + key = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair"; + } + //TODO general response.toString alignment + 2 SWs + return String.format("Generated %s: %#x", key, getSW1()); + } + + } + + /** + * + */ + public static class ECDH extends Response { + private byte pubkey; + private byte privkey; + private byte export; + private byte invalid; + + protected ECDH(ResponseAPDU response, long time, byte pubkey, byte privkey, byte export, byte invalid) { + super(response, time); + this.pubkey = pubkey; + this.privkey = privkey; + this.export = export; + this.invalid = invalid; + + parse(1, (export & ECTesterApplet.EXPORT_ECDH) != 0 ? 1 : 0); + } + + public boolean hasSecret() { + return hasParam(0); + } + + public byte[] getSecret() { + return getParam(0); + } + + @Override + public String toString() { + String pub = pubkey == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote"; + String priv = privkey == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote"; + String validity = invalid != 0 ? "invalid" : "valid"; + //TODO general response.toString alignment + 2SWs + return String.format("ECDH of %s pubkey and %s privkey(%s point): %#x", pub, priv, validity, getSW1()); + } + } + + /** + * + */ + public static class ECDSA extends Response { + private byte keyPair; + private byte export; + private byte[] raw; + + protected ECDSA(ResponseAPDU response, long time, byte keyPair, byte export, byte[] raw) { + super(response, time); + this.keyPair = keyPair; + this.export = export; + this.raw = raw; + + parse(1, (export & ECTesterApplet.EXPORT_SIG) != 0 ? 1 : 0); + } + + public boolean hasSignature() { + return hasParam(0); + } + + public byte[] getSignature() { + return getParam(0); + } + + @Override + public String toString() { + String key = keyPair == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote"; + String data = raw == null ? "random" : "provided"; + //TODO general response.toString alignment + 2 SWs + return String.format("ECDSA with %s keypair(%s data): %#x", key, data, getSW1()); + } + + } +} diff --git a/src/cz/crcs/ectester/reader/Util.java b/src/cz/crcs/ectester/reader/Util.java index 1464728..38db3bf 100644 --- a/src/cz/crcs/ectester/reader/Util.java +++ b/src/cz/crcs/ectester/reader/Util.java @@ -50,18 +50,22 @@ public class Util { } public static String bytesToHex(byte[] data) { - return bytesToHex(data, 0, data.length, true); + return bytesToHex(data, true); + } + + public static String bytesToHex(byte[] data, boolean addSpace) { + return bytesToHex(data, 0, data.length, addSpace); } public static String bytesToHex(byte[] data, int offset, int len) { return bytesToHex(data, offset, len, true); } - public static String bytesToHex(byte[] data, int offset, int len, boolean bAddSpace) { + public static String bytesToHex(byte[] data, int offset, int len, boolean addSpace) { StringBuilder buf = new StringBuilder(); for (int i = offset; i < (offset + len); i++) { buf.append(byteToHex(data[i])); - if (bAddSpace && i != (offset + len - 1)) { + if (addSpace && i != (offset + len - 1)) { buf.append(" "); } } |
