From de1736c211dc8d27961ef0495c82d25fbf813e05 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sun, 26 Mar 2017 00:20:29 +0100 Subject: Refactored EC_Params, renamed EC_Data, added first test vectors. --- src/cz/crcs/ectester/applet/ECKeyGenerator.java | 2 +- src/cz/crcs/ectester/applet/ECKeyTester.java | 5 +- src/cz/crcs/ectester/data/EC_Data.java | 246 --------------------- src/cz/crcs/ectester/data/EC_Store.java | 246 +++++++++++++++++++++ src/cz/crcs/ectester/data/categories.xml | 5 + src/cz/crcs/ectester/data/invalid/curves.xml | 4 + src/cz/crcs/ectester/data/test/keys.xml | 16 ++ .../ectester/data/test/secg/secp160r1-dh-kdf.csv | 1 + .../ectester/data/test/secg/secp160r1-dh-raw.csv | 1 + .../ectester/data/test/secg/secp160r1-dh-sha1.csv | 1 + .../ectester/data/test/secg/secp160r1-keyU.csv | 1 + .../ectester/data/test/secg/secp160r1-keyV.csv | 1 + src/cz/crcs/ectester/reader/ECTester.java | 139 +++++++----- src/cz/crcs/ectester/reader/ec/EC_Data.java | 135 +++++++++++ src/cz/crcs/ectester/reader/ec/EC_Params.java | 111 ++-------- 15 files changed, 516 insertions(+), 398 deletions(-) delete mode 100644 src/cz/crcs/ectester/data/EC_Data.java create mode 100644 src/cz/crcs/ectester/data/EC_Store.java create mode 100644 src/cz/crcs/ectester/data/invalid/curves.xml create mode 100644 src/cz/crcs/ectester/data/test/keys.xml create mode 100644 src/cz/crcs/ectester/data/test/secg/secp160r1-dh-kdf.csv create mode 100644 src/cz/crcs/ectester/data/test/secg/secp160r1-dh-raw.csv create mode 100644 src/cz/crcs/ectester/data/test/secg/secp160r1-dh-sha1.csv create mode 100644 src/cz/crcs/ectester/data/test/secg/secp160r1-keyU.csv create mode 100644 src/cz/crcs/ectester/data/test/secg/secp160r1-keyV.csv create mode 100644 src/cz/crcs/ectester/reader/ec/EC_Data.java (limited to 'src') diff --git a/src/cz/crcs/ectester/applet/ECKeyGenerator.java b/src/cz/crcs/ectester/applet/ECKeyGenerator.java index da6142f..b412370 100644 --- a/src/cz/crcs/ectester/applet/ECKeyGenerator.java +++ b/src/cz/crcs/ectester/applet/ECKeyGenerator.java @@ -170,7 +170,7 @@ public class ECKeyGenerator { short i = Util.makeShort(data[(short) (offset + 2)], data[(short) (offset + 3)]); if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setFieldF2M(i); if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setFieldF2M(i); - } else if (length == 8){ + } else if (length == 8) { short i1 = Util.makeShort(data[(short) (offset + 2)], data[(short) (offset + 3)]); short i2 = Util.makeShort(data[(short) (offset + 4)], data[(short) (offset + 5)]); short i3 = Util.makeShort(data[(short) (offset + 6)], data[(short) (offset + 7)]); diff --git a/src/cz/crcs/ectester/applet/ECKeyTester.java b/src/cz/crcs/ectester/applet/ECKeyTester.java index 057d357..7ef6150 100644 --- a/src/cz/crcs/ectester/applet/ECKeyTester.java +++ b/src/cz/crcs/ectester/applet/ECKeyTester.java @@ -3,7 +3,10 @@ package cz.crcs.ectester.applet; import javacard.framework.CardRuntimeException; import javacard.framework.ISO7816; -import javacard.security.*; +import javacard.security.ECPrivateKey; +import javacard.security.ECPublicKey; +import javacard.security.KeyAgreement; +import javacard.security.Signature; /** * Class capable of testing ECDH/C and ECDSA. diff --git a/src/cz/crcs/ectester/data/EC_Data.java b/src/cz/crcs/ectester/data/EC_Data.java deleted file mode 100644 index 98b2d59..0000000 --- a/src/cz/crcs/ectester/data/EC_Data.java +++ /dev/null @@ -1,246 +0,0 @@ -package cz.crcs.ectester.data; - -import cz.crcs.ectester.reader.ec.EC_Curve; -import cz.crcs.ectester.reader.ec.EC_Key; -import cz.crcs.ectester.reader.ec.EC_Keypair; -import cz.crcs.ectester.reader.ec.EC_Params; -import javacard.security.KeyPair; -import org.omg.PortableInterceptor.SYSTEM_EXCEPTION; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.ErrorHandler; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; - -import javax.xml.XMLConstants; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; -import java.io.IOException; -import java.io.InputStream; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class EC_Data { - - private DocumentBuilder db; - - private Map categories; - - public EC_Data() { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - - try { - SchemaFactory scf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); - Schema sch = scf.newSchema(this.getClass().getResource("/cz/crcs/ectester/data/schema.xsd")); - dbf.setSchema(sch); - dbf.setNamespaceAware(true); - dbf.setIgnoringComments(true); - dbf.setIgnoringElementContentWhitespace(true); - db = dbf.newDocumentBuilder(); - db.setErrorHandler(new ErrorHandler() { - @Override - public void warning(SAXParseException exception) throws SAXException { - System.err.println("EC_Data | Warning : " + exception); - } - - @Override - public void error(SAXParseException exception) throws SAXException { - System.err.println("EC_Data | Error : " + exception); - } - - @Override - public void fatalError(SAXParseException exception) throws SAXException { - System.err.println("EC_Data | Fatal : " + exception); - } - }); - - parse(); - } catch (ParserConfigurationException | IOException | SAXException e) { - e.printStackTrace(); - } - } - - private void parse() throws SAXException, ParserConfigurationException, IOException { - - Document categoriesDoc = db.parse(this.getClass().getResourceAsStream("/cz/crcs/ectester/data/categories.xml")); - categoriesDoc.normalize(); - - NodeList catList = categoriesDoc.getElementsByTagName("category"); - - this.categories = new HashMap<>(catList.getLength()); - for (int i = 0; i < catList.getLength(); ++i) { - Node catNode = catList.item(i); - if (catNode instanceof Element) { - Element catElem = (Element) catNode; - Node name = catElem.getElementsByTagName("name").item(0); - Node dir = catElem.getElementsByTagName("directory").item(0); - Node desc = catElem.getElementsByTagName("desc").item(0); - - EC_Category category = parseCategory(name.getTextContent(), dir.getTextContent(), desc.getTextContent()); - this.categories.put(name.getTextContent(), category); - } else { - throw new SAXException("?"); - } - } - } - - private EC_Category parseCategory(String name, String dir, String desc) throws ParserConfigurationException, IOException, SAXException { - - Map objMap = new HashMap<>(); - - InputStream curvesStream = this.getClass().getResourceAsStream("/cz/crcs/ectester/data/" + dir + "/curves.xml"); - if (curvesStream != null) { - Document curvesDoc = db.parse(curvesStream); - curvesDoc.normalize(); - - NodeList curveList = curvesDoc.getElementsByTagName("curve"); - - for (int i = 0; i < curveList.getLength(); ++i) { - Node curveNode = curveList.item(i); - if (curveNode instanceof Element) { - Element curveElem = (Element) curveNode; - Node id = curveElem.getElementsByTagName("id").item(0); - Node bits = curveElem.getElementsByTagName("bits").item(0); - Node field = curveElem.getElementsByTagName("field").item(0); - Node file = curveElem.getElementsByTagName("file").item(0); - - NodeList descc = curveElem.getElementsByTagName("desc"); - String descs = null; - if (descc.getLength() != 0) { - descs = descc.item(0).getTextContent(); - } - - byte alg; - if (field.getTextContent().equalsIgnoreCase("prime")) { - alg = KeyPair.ALG_EC_FP; - } else { - alg = KeyPair.ALG_EC_F2M; - } - short bitsize = Short.parseShort(bits.getTextContent()); - - EC_Curve curve = new EC_Curve(bitsize, alg, descs); - if (!curve.readCSV(this.getClass().getResourceAsStream("/cz/crcs/ectester/data/" + dir + "/" + file.getTextContent()))) { - throw new IOException("Invalid csv data."); - } - - objMap.put(id.getTextContent(), curve); - } else { - throw new SAXException("?"); - } - } - } - - InputStream keysStream = this.getClass().getResourceAsStream("/cz/crcs/ectester/data/" + dir + "/keys.xml"); - if (keysStream != null) { - Document keysDoc = db.parse(keysStream); - keysDoc.normalize(); - - NodeList directs = keysDoc.getDocumentElement().getChildNodes(); - for (int i = 0; i < directs.getLength(); ++i) { - Node direct = directs.item(i); - if (direct instanceof Element) { - Element elem = (Element) direct; - - NodeList childs = elem.getChildNodes(); - String id = null; - for (int j = 0; j < childs.getLength(); ++j) { - Node child = childs.item(j); - if (child instanceof Element) { - Element childElem = (Element) child; - if (childElem.getTagName().equals("id")) { - id = childElem.getTextContent(); - break; - } - } - } - if (id == null) { - throw new SAXException("key no id?"); - } - - EC_Params result = parseKeylike(dir, elem); - - objMap.put(id, result); - } else { - throw new SAXException("?"); - } - } - } - - return new EC_Category(name, dir, desc, objMap); - } - - private EC_Params parseKeylike(String dir, Element elem) throws SAXException { - Node file = elem.getElementsByTagName("file").item(0); - Node curve = elem.getElementsByTagName("curve").item(0); - - NodeList desc = elem.getElementsByTagName("desc"); - String descs = null; - if (desc.getLength() != 0) { - descs = desc.item(0).getTextContent(); - } - - EC_Params result; - if (elem.getTagName().equals("pubkey")) { - result = new EC_Key.Public(curve.getTextContent(), descs); - } else if (elem.getTagName().equals("privkey")) { - result = new EC_Key.Private(curve.getTextContent(), descs); - } else if (elem.getTagName().equals("keypair")) { - result = new EC_Keypair(curve.getTextContent(), descs); - } else { - throw new SAXException("?"); - } - result.readCSV(this.getClass().getResourceAsStream("/cz/crcs/ectester/data/" + dir + "/" + file.getTextContent())); - return result; - } - - public Map getCategories() { - return Collections.unmodifiableMap(categories); - } - - public EC_Category getCategory(String category) { - return categories.get(category); - } - - public Map getObjects(String category) { - EC_Category cat = categories.get(category); - if (cat != null) { - return cat.getObjects(); - } - return null; - } - - public Map getObjects(Class objClass, String category) { - EC_Category cat = categories.get(category); - if (cat != null) { - return cat.getObjects(objClass); - } - return null; - } - - public T getObject(Class objClass, String category, String id) { - EC_Category cat = categories.get(category); - if (cat != null) { - return cat.getObject(objClass, id); - } - return null; - } - - public T getObject(Class objClass, String query) { - String[] parts = query.split("/"); - if (parts.length != 2) { - return null; - } - return getObject(objClass, parts[0], parts[1]); - } - - -} diff --git a/src/cz/crcs/ectester/data/EC_Store.java b/src/cz/crcs/ectester/data/EC_Store.java new file mode 100644 index 0000000..60a1065 --- /dev/null +++ b/src/cz/crcs/ectester/data/EC_Store.java @@ -0,0 +1,246 @@ +package cz.crcs.ectester.data; + +import cz.crcs.ectester.reader.ec.EC_Curve; +import cz.crcs.ectester.reader.ec.EC_Key; +import cz.crcs.ectester.reader.ec.EC_Keypair; +import cz.crcs.ectester.reader.ec.EC_Params; +import javacard.security.KeyPair; +import org.omg.PortableInterceptor.SYSTEM_EXCEPTION; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class EC_Store { + + private DocumentBuilder db; + + private Map categories; + + public EC_Store() { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + + try { + SchemaFactory scf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + Schema sch = scf.newSchema(this.getClass().getResource("/cz/crcs/ectester/data/schema.xsd")); + dbf.setSchema(sch); + dbf.setNamespaceAware(true); + dbf.setIgnoringComments(true); + dbf.setIgnoringElementContentWhitespace(true); + db = dbf.newDocumentBuilder(); + db.setErrorHandler(new ErrorHandler() { + @Override + public void warning(SAXParseException exception) throws SAXException { + System.err.println("EC_Store | Warning : " + exception); + } + + @Override + public void error(SAXParseException exception) throws SAXException { + System.err.println("EC_Store | Error : " + exception); + } + + @Override + public void fatalError(SAXParseException exception) throws SAXException { + System.err.println("EC_Store | Fatal : " + exception); + } + }); + + parse(); + } catch (ParserConfigurationException | IOException | SAXException e) { + e.printStackTrace(); + } + } + + private void parse() throws SAXException, ParserConfigurationException, IOException { + + Document categoriesDoc = db.parse(this.getClass().getResourceAsStream("/cz/crcs/ectester/data/categories.xml")); + categoriesDoc.normalize(); + + NodeList catList = categoriesDoc.getElementsByTagName("category"); + + this.categories = new HashMap<>(catList.getLength()); + for (int i = 0; i < catList.getLength(); ++i) { + Node catNode = catList.item(i); + if (catNode instanceof Element) { + Element catElem = (Element) catNode; + Node name = catElem.getElementsByTagName("name").item(0); + Node dir = catElem.getElementsByTagName("directory").item(0); + Node desc = catElem.getElementsByTagName("desc").item(0); + + EC_Category category = parseCategory(name.getTextContent(), dir.getTextContent(), desc.getTextContent()); + this.categories.put(name.getTextContent(), category); + } else { + throw new SAXException("?"); + } + } + } + + private EC_Category parseCategory(String name, String dir, String desc) throws ParserConfigurationException, IOException, SAXException { + + Map objMap = new HashMap<>(); + + InputStream curvesStream = this.getClass().getResourceAsStream("/cz/crcs/ectester/data/" + dir + "/curves.xml"); + if (curvesStream != null) { + Document curvesDoc = db.parse(curvesStream); + curvesDoc.normalize(); + + NodeList curveList = curvesDoc.getElementsByTagName("curve"); + + for (int i = 0; i < curveList.getLength(); ++i) { + Node curveNode = curveList.item(i); + if (curveNode instanceof Element) { + Element curveElem = (Element) curveNode; + Node id = curveElem.getElementsByTagName("id").item(0); + Node bits = curveElem.getElementsByTagName("bits").item(0); + Node field = curveElem.getElementsByTagName("field").item(0); + Node file = curveElem.getElementsByTagName("file").item(0); + + NodeList descc = curveElem.getElementsByTagName("desc"); + String descs = null; + if (descc.getLength() != 0) { + descs = descc.item(0).getTextContent(); + } + + byte alg; + if (field.getTextContent().equalsIgnoreCase("prime")) { + alg = KeyPair.ALG_EC_FP; + } else { + alg = KeyPair.ALG_EC_F2M; + } + short bitsize = Short.parseShort(bits.getTextContent()); + + EC_Curve curve = new EC_Curve(bitsize, alg, descs); + if (!curve.readCSV(this.getClass().getResourceAsStream("/cz/crcs/ectester/data/" + dir + "/" + file.getTextContent()))) { + throw new IOException("Invalid csv data."); + } + + objMap.put(id.getTextContent(), curve); + } else { + throw new SAXException("?"); + } + } + } + + InputStream keysStream = this.getClass().getResourceAsStream("/cz/crcs/ectester/data/" + dir + "/keys.xml"); + if (keysStream != null) { + Document keysDoc = db.parse(keysStream); + keysDoc.normalize(); + + NodeList directs = keysDoc.getDocumentElement().getChildNodes(); + for (int i = 0; i < directs.getLength(); ++i) { + Node direct = directs.item(i); + if (direct instanceof Element) { + Element elem = (Element) direct; + + NodeList childs = elem.getChildNodes(); + String id = null; + for (int j = 0; j < childs.getLength(); ++j) { + Node child = childs.item(j); + if (child instanceof Element) { + Element childElem = (Element) child; + if (childElem.getTagName().equals("id")) { + id = childElem.getTextContent(); + break; + } + } + } + if (id == null) { + throw new SAXException("key no id?"); + } + + EC_Params result = parseKeylike(dir, elem); + + objMap.put(id, result); + } else { + throw new SAXException("?"); + } + } + } + + return new EC_Category(name, dir, desc, objMap); + } + + private EC_Params parseKeylike(String dir, Element elem) throws SAXException { + Node file = elem.getElementsByTagName("file").item(0); + Node curve = elem.getElementsByTagName("curve").item(0); + + NodeList desc = elem.getElementsByTagName("desc"); + String descs = null; + if (desc.getLength() != 0) { + descs = desc.item(0).getTextContent(); + } + + EC_Params result; + if (elem.getTagName().equals("pubkey")) { + result = new EC_Key.Public(curve.getTextContent(), descs); + } else if (elem.getTagName().equals("privkey")) { + result = new EC_Key.Private(curve.getTextContent(), descs); + } else if (elem.getTagName().equals("keypair")) { + result = new EC_Keypair(curve.getTextContent(), descs); + } else { + throw new SAXException("?"); + } + result.readCSV(this.getClass().getResourceAsStream("/cz/crcs/ectester/data/" + dir + "/" + file.getTextContent())); + return result; + } + + public Map getCategories() { + return Collections.unmodifiableMap(categories); + } + + public EC_Category getCategory(String category) { + return categories.get(category); + } + + public Map getObjects(String category) { + EC_Category cat = categories.get(category); + if (cat != null) { + return cat.getObjects(); + } + return null; + } + + public Map getObjects(Class objClass, String category) { + EC_Category cat = categories.get(category); + if (cat != null) { + return cat.getObjects(objClass); + } + return null; + } + + public T getObject(Class objClass, String category, String id) { + EC_Category cat = categories.get(category); + if (cat != null) { + return cat.getObject(objClass, id); + } + return null; + } + + public T getObject(Class objClass, String query) { + String[] parts = query.split("/"); + if (parts.length != 2) { + return null; + } + return getObject(objClass, parts[0], parts[1]); + } + + +} diff --git a/src/cz/crcs/ectester/data/categories.xml b/src/cz/crcs/ectester/data/categories.xml index 5913d42..d0c9f39 100644 --- a/src/cz/crcs/ectester/data/categories.xml +++ b/src/cz/crcs/ectester/data/categories.xml @@ -31,4 +31,9 @@ wrong Wrong field curves. These should definitely give an error when used. Since the "prime" used for the field are not prime, and the field polynomials are also not irreducible. Simply put these parameters don't specify a valid elliptic curve. + + test + test + Test vectors + \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/invalid/curves.xml b/src/cz/crcs/ectester/data/invalid/curves.xml new file mode 100644 index 0000000..e87269f --- /dev/null +++ b/src/cz/crcs/ectester/data/invalid/curves.xml @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/test/keys.xml b/src/cz/crcs/ectester/data/test/keys.xml new file mode 100644 index 0000000..56fc4e2 --- /dev/null +++ b/src/cz/crcs/ectester/data/test/keys.xml @@ -0,0 +1,16 @@ + + + + secp160r1-U + secg/secp160r1-keyU.csv + secg/secp160r1 + + + secp160r1-V + secg/secp160r1-keyV.csv + secg/secp160r1 + + \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-kdf.csv b/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-kdf.csv new file mode 100644 index 0000000..e8060e1 --- /dev/null +++ b/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-kdf.csv @@ -0,0 +1 @@ +744AB703F5BC082E59185F6D049D2D367DB245C2 diff --git a/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-raw.csv b/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-raw.csv new file mode 100644 index 0000000..3eac8d9 --- /dev/null +++ b/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-raw.csv @@ -0,0 +1 @@ +CA7C0F8C3FFA87A96E1B74AC8E6AF594347BB40A diff --git a/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-sha1.csv b/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-sha1.csv new file mode 100644 index 0000000..97735e7 --- /dev/null +++ b/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-sha1.csv @@ -0,0 +1 @@ +D248313E865A1AE677782B54B24D8ABAF11A53C2 diff --git a/src/cz/crcs/ectester/data/test/secg/secp160r1-keyU.csv b/src/cz/crcs/ectester/data/test/secg/secp160r1-keyU.csv new file mode 100644 index 0000000..bbf9e62 --- /dev/null +++ b/src/cz/crcs/ectester/data/test/secg/secp160r1-keyU.csv @@ -0,0 +1 @@ +51B4496FECC406ED0E75A24A3C03206251419DC0,C28DCB4B73A514B468D793894F381CCC1756AA6C,AA374FFC3CE144E6B073307972CB6D57B2A4E982 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/test/secg/secp160r1-keyV.csv b/src/cz/crcs/ectester/data/test/secg/secp160r1-keyV.csv new file mode 100644 index 0000000..6d9bc31 --- /dev/null +++ b/src/cz/crcs/ectester/data/test/secg/secp160r1-keyV.csv @@ -0,0 +1 @@ +49B41E0E9C0369C2328739D90F63D56707C6E5BC,26E008B567015ED96D232A03111C3EDC0E9C8F83,45FB58A92A17AD4B15101C66E74F277E2B460866 diff --git a/src/cz/crcs/ectester/reader/ECTester.java b/src/cz/crcs/ectester/reader/ECTester.java index 2f26275..247a260 100644 --- a/src/cz/crcs/ectester/reader/ECTester.java +++ b/src/cz/crcs/ectester/reader/ECTester.java @@ -24,7 +24,7 @@ package cz.crcs.ectester.reader; import cz.crcs.ectester.applet.ECTesterApplet; import cz.crcs.ectester.applet.EC_Consts; import cz.crcs.ectester.data.EC_Category; -import cz.crcs.ectester.data.EC_Data; +import cz.crcs.ectester.data.EC_Store; import cz.crcs.ectester.reader.ec.EC_Curve; import cz.crcs.ectester.reader.ec.EC_Key; import cz.crcs.ectester.reader.ec.EC_Keypair; @@ -47,7 +47,7 @@ public class ECTester { private CardMngr cardManager; private DirtyLogger systemOutLogger; - private EC_Data dataDB; + private EC_Store dataStore; //Options private int optBits; @@ -108,7 +108,7 @@ public class ECTester { return; } - dataDB = new EC_Data(); + dataStore = new EC_Store(); //if list, print and quit if (cli.hasOption("list-named")) { list(); @@ -462,7 +462,7 @@ public class ECTester { * List categories and named curves. */ private void list() { - Map categories = dataDB.getCategories(); + Map categories = dataStore.getCategories(); for (EC_Category cat : categories.values()) { System.out.println("\t- " + cat.getName() + ": " + (cat.getDesc() == null ? "" : cat.getDesc())); @@ -597,34 +597,16 @@ public class ECTester { List commands = new LinkedList<>(); if (optTestCase.equalsIgnoreCase("default")) { - if (optAll) { - if (optNamedCurve != null) { - Map curves = dataDB.getObjects(EC_Curve.class, optNamedCurve); - if (optPrimeField) { - for (Map.Entry entry : curves.entrySet()) { - EC_Curve curve = entry.getValue(); - if (curve.getField() == KeyPair.ALG_EC_FP) { - commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), KeyPair.ALG_EC_FP)); - byte[] external = curve.flatten(); - commands.add(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), external)); - commands.addAll(testCurve()); - commands.add(new Command.Cleanup(cardManager)); - } - } - } - if (optBinaryField) { - for (Map.Entry entry : curves.entrySet()) { - EC_Curve curve = entry.getValue(); - if (curve.getField() == KeyPair.ALG_EC_F2M) { - commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), KeyPair.ALG_EC_F2M)); - byte[] external = curve.flatten(); - commands.add(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), external)); - commands.addAll(testCurve()); - commands.add(new Command.Cleanup(cardManager)); - } - } - } - } else { + + if (optNamedCurve != null) { + if (optPrimeField) { + commands.addAll(testCurves(optNamedCurve, KeyPair.ALG_EC_FP)); + } + if (optBinaryField) { + commands.addAll(testCurves(optNamedCurve, KeyPair.ALG_EC_F2M)); + } + } else { + if (optAll) { if (optPrimeField) { //iterate over prime curve sizes used: EC_Consts.FP_SIZES for (short keyLength : EC_Consts.FP_SIZES) { @@ -643,32 +625,41 @@ public class ECTester { commands.add(new Command.Cleanup(cardManager)); } } - } - } else { - if (optPrimeField) { - commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_FP)); - commands.addAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_FP)); - commands.addAll(testCurve()); - commands.add(new Command.Cleanup(cardManager)); - } + } else { + if (optPrimeField) { + commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_FP)); + commands.addAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_FP)); + commands.addAll(testCurve()); + commands.add(new Command.Cleanup(cardManager)); + } - if (optBinaryField) { - commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_F2M)); - commands.addAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_F2M)); - commands.addAll(testCurve()); - commands.add(new Command.Cleanup(cardManager)); + if (optBinaryField) { + commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_F2M)); + commands.addAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_F2M)); + commands.addAll(testCurve()); + commands.add(new Command.Cleanup(cardManager)); + } } } } else if (optTestCase.equalsIgnoreCase("wrong")) { - + if (optPrimeField) { + commands.addAll(testCurves("wrong", KeyPair.ALG_EC_FP)); + } + if (optBinaryField) { + commands.addAll(testCurves("wrong", KeyPair.ALG_EC_F2M)); + } } else if (optTestCase.equalsIgnoreCase("non-prime")) { + } else if (optTestCase.equalsIgnoreCase("smallpub")) { + } else if (optTestCase.equalsIgnoreCase("invalid")) { } List test = Command.sendAll(commands); systemOutLogger.println(Response.toString(test)); + + // } /** @@ -685,15 +676,14 @@ public class ECTester { systemOutLogger.println(Response.toString(prepare)); + byte pubkey = (optAnyPublic || optAnyKey) ? ECTesterApplet.KEYPAIR_REMOTE : ECTesterApplet.KEYPAIR_LOCAL; + byte privkey = (optAnyPrivate || optAnyKey) ? ECTesterApplet.KEYPAIR_REMOTE : ECTesterApplet.KEYPAIR_LOCAL; + List generate = new LinkedList<>(); + generate.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_BOTH)); if (optAnyPublic || optAnyPrivate || optAnyKey) { - generate.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL)); generate.add(prepareKey(ECTesterApplet.KEYPAIR_REMOTE)); - } else { - generate.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_BOTH)); } - byte pubkey = (optAnyPublic || optAnyKey) ? ECTesterApplet.KEYPAIR_REMOTE : ECTesterApplet.KEYPAIR_LOCAL; - byte privkey = (optAnyPrivate || optAnyKey) ? ECTesterApplet.KEYPAIR_REMOTE : ECTesterApplet.KEYPAIR_LOCAL; FileWriter out = null; if (optOutput != null) { @@ -816,7 +806,7 @@ public class ECTester { } else if (optNamedCurve != null) { // Set a named curve. // parse optNamedCurve -> cat / id | cat | id - EC_Curve curve = dataDB.getObject(EC_Curve.class, optNamedCurve); + EC_Curve curve = dataStore.getObject(EC_Curve.class, optNamedCurve); if (curve == null) { throw new IOException("Curve could no be found."); } @@ -873,7 +863,7 @@ public class ECTester { keypair.readCSV(in); in.close(); } else { - keypair = dataDB.getObject(EC_Keypair.class, optNamedKey); + keypair = dataStore.getObject(EC_Keypair.class, optNamedKey); } data = keypair.flatten(); @@ -892,12 +882,15 @@ public class ECTester { pub.readCSV(in); in.close(); } else { - pub = dataDB.getObject(EC_Key.Public.class, optNamedPublic); + pub = dataStore.getObject(EC_Key.Public.class, optNamedPublic); + if (pub == null) { + pub = dataStore.getObject(EC_Keypair.class, optNamedPublic); + } } - byte[] pubkey = pub.flatten(); + byte[] pubkey = pub.flatten(EC_Consts.PARAMETER_W); if (pubkey == null) { - throw new IOException("Couldn't read the key file correctly."); + throw new IOException("Couldn't read the public key file correctly."); } data = pubkey; } @@ -911,12 +904,15 @@ public class ECTester { priv.readCSV(in); in.close(); } else { - priv = dataDB.getObject(EC_Key.Public.class, optNamedPrivate); + priv = dataStore.getObject(EC_Key.Public.class, optNamedPrivate); + if (priv == null) { + priv = dataStore.getObject(EC_Keypair.class, optNamedPrivate); + } } - byte[] privkey = priv.flatten(); + byte[] privkey = priv.flatten(EC_Consts.PARAMETER_S); if (privkey == null) { - throw new IOException("Couldn't read the key file correctly."); + throw new IOException("Couldn't read the private key file correctly."); } data = Util.concatenate(data, privkey); } @@ -939,6 +935,31 @@ public class ECTester { return commands; } + /** + * @param category + * @param field + * @return + * @throws IOException + */ + private List testCurves(String category, byte field) throws IOException { + List commands = new LinkedList<>(); + Map curves = dataStore.getObjects(EC_Curve.class, category); + if (curves == null) + return commands; + for (Map.Entry entry : curves.entrySet()) { + EC_Curve curve = entry.getValue(); + if (curve.getField() == field && (curve.getBits() == optBits || optAll)) { + commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), field)); + byte[] external = curve.flatten(); + commands.add(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), external)); + commands.addAll(testCurve()); + commands.add(new Command.Cleanup(cardManager)); + } + } + + return commands; + } + public static void main(String[] args) { ECTester app = new ECTester(); app.run(args); diff --git a/src/cz/crcs/ectester/reader/ec/EC_Data.java b/src/cz/crcs/ectester/reader/ec/EC_Data.java new file mode 100644 index 0000000..c1fb54c --- /dev/null +++ b/src/cz/crcs/ectester/reader/ec/EC_Data.java @@ -0,0 +1,135 @@ +package cz.crcs.ectester.reader.ec; + +import cz.crcs.ectester.reader.Util; + +import java.io.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Scanner; +import java.util.regex.Pattern; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class EC_Data { + private static final Pattern hex = Pattern.compile("(0x|0X)?[a-fA-F\\d]+"); + + int count; + byte[][] data; + + EC_Data() { + } + + public EC_Data(int count) { + this.count = count; + this.data = new byte[count][]; + } + + public EC_Data(byte[][] data) { + this.count = data.length; + this.data = data; + } + + public byte[][] getData() { + return data; + } + + public boolean hasData() { + return data != null; + } + + public byte[] flatten() { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (byte[] param : data) { + byte[] length = new byte[2]; + Util.setShort(length, 0, (short) param.length); + + out.write(length, 0, 2); + out.write(param, 0, param.length); + } + + return out.toByteArray(); + } + + public String[] expand() { + List out = new ArrayList<>(count); + for (byte[] param : data) { + out.add(Util.bytesToHex(param, false)); + } + + return out.toArray(new String[out.size()]); + } + + private static byte[] pad(byte[] data) { + if (data.length == 1) { + return new byte[]{(byte) 0, data[0]}; + } else if (data.length == 0 || data.length > 2) { + return data; + } + return null; + } + + private static byte[] parse(String param) { + byte[] data; + if (param.startsWith("0x") || param.startsWith("0X")) { + data = Util.hexToBytes(param.substring(2)); + } else { + data = Util.hexToBytes(param); + } + if (data == null) + return new byte[0]; + if (data.length < 2) + return pad(data); + return data; + } + + private boolean readHex(String[] hex) { + if (hex.length != count) { + return false; + } + + for (int i = 0; i < count; ++i) { + this.data[i] = parse(hex[i]); + } + return true; + } + + public boolean readCSV(InputStream in) { + Scanner s = new Scanner(in); + + s.useDelimiter(",|;"); + List data = new LinkedList<>(); + while (s.hasNext()) { + String field = s.next(); + data.add(field.replaceAll("\\s+", "")); + } + + if (data.isEmpty()) { + return false; + } + for (String param : data) { + if (!hex.matcher(param).matches()) { + return false; + } + } + return readHex(data.toArray(new String[data.size()])); + } + + public boolean readBytes(byte[] data) { + //TODO + return false; + } + + public void writeCSV(OutputStream out) throws IOException { + String[] hex = expand(); + Writer w = new OutputStreamWriter(out); + for (int i = 0; i < hex.length; ++i) { + w.write(hex[i]); + if (i < hex.length - 1) { + w.write(","); + } + } + w.flush(); + } +} diff --git a/src/cz/crcs/ectester/reader/ec/EC_Params.java b/src/cz/crcs/ectester/reader/ec/EC_Params.java index fa5515c..00747b1 100644 --- a/src/cz/crcs/ectester/reader/ec/EC_Params.java +++ b/src/cz/crcs/ectester/reader/ec/EC_Params.java @@ -3,29 +3,25 @@ package cz.crcs.ectester.reader.ec; import cz.crcs.ectester.applet.EC_Consts; import cz.crcs.ectester.reader.Util; -import java.io.*; +import java.io.ByteArrayOutputStream; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; -import java.util.Scanner; -import java.util.regex.Pattern; /** * @author Jan Jancar johny@neuromancer.sk */ -public class EC_Params { - private static final Pattern hex = Pattern.compile("(0x|0X)?[a-fA-F\\d]+"); - +public class EC_Params extends EC_Data { private short params; - private byte[][] data; public EC_Params(short params) { this.params = params; - this.data = new byte[numParams()][]; + this.count = numParams(); + this.data = new byte[this.count][]; } public EC_Params(short params, byte[][] data) { this.params = params; + this.count = data.length; this.data = data; } @@ -45,7 +41,7 @@ public class EC_Params { if (paramMask == EC_Consts.PARAMETER_F2M) { num += 3; } - if (paramMask == EC_Consts.PARAMETER_W || paramMask == EC_Consts.PARAMETER_G){ + if (paramMask == EC_Consts.PARAMETER_W || paramMask == EC_Consts.PARAMETER_G) { num += 1; } ++num; @@ -55,32 +51,29 @@ public class EC_Params { return num; } - public byte[][] getData() { - return data; - } - - public boolean hasData() { - return data != null; + @Override + public byte[] flatten() { + return flatten(params); } - public byte[] flatten() { + public byte[] flatten(short params) { ByteArrayOutputStream out = new ByteArrayOutputStream(); short paramMask = EC_Consts.PARAMETER_FP; int i = 0; while (paramMask <= EC_Consts.PARAMETER_S) { - short masked = (short) (params & paramMask); + short masked = (short) (this.params & params & paramMask); + short shallow = (short) (this.params & paramMask); if (masked != 0) { byte[] param = data[i]; if (masked == EC_Consts.PARAMETER_F2M) { //add m, e_1, e_2, e_3 param = Util.concatenate(param, data[i + 1], data[i + 2], data[i + 3]); - i += 3; if (param.length != 8) throw new RuntimeException("PARAMETER_F2M length is not 8.(should be)"); } if (masked == EC_Consts.PARAMETER_G || masked == EC_Consts.PARAMETER_W) { //read another param (the y coord) and put into X962 format. - byte[] y = data[++i]; + byte[] y = data[i + 1]; param = Util.concatenate(new byte[]{4}, param, y); //<- ugly but works! } if (param.length == 0) @@ -92,6 +85,12 @@ public class EC_Params { out.write(length, 0, 2); //write data out.write(param, 0, param.length); + } + if (shallow == EC_Consts.PARAMETER_F2M) { + i += 4; + } else if (shallow == EC_Consts.PARAMETER_G || shallow == EC_Consts.PARAMETER_W) { + i += 2; + } else if (shallow != 0) { i++; } paramMask = (short) (paramMask << 1); @@ -100,6 +99,7 @@ public class EC_Params { return (out.size() == 0) ? null : out.toByteArray(); } + @Override public String[] expand() { List out = new ArrayList<>(); @@ -136,75 +136,4 @@ public class EC_Params { return out.toArray(new String[out.size()]); } - private static byte[] pad(byte[] data) { - if (data.length == 1) { - return new byte[]{(byte) 0, data[0]}; - } else if (data.length == 0 || data.length > 2) { - return data; - } - return null; - } - - private static byte[] parse(String param) { - byte[] data; - if (param.startsWith("0x") || param.startsWith("0X")) { - data = Util.hexToBytes(param.substring(2)); - } else { - data = Util.hexToBytes(param); - } - if (data == null) - return new byte[0]; - if (data.length < 2) - return pad(data); - return data; - } - - private boolean readHex(String[] hex) { - if (hex.length != numParams()) { - return false; - } - - for (int i = 0; i < numParams(); ++i) { - this.data[i] = parse(hex[i]); - } - return true; - } - - public boolean readCSV(InputStream in) { - Scanner s = new Scanner(in); - - s.useDelimiter(",|;"); - List data = new LinkedList(); - while (s.hasNext()) { - String field = s.next(); - data.add(field.replaceAll("\\s+", "")); - } - - if (data.isEmpty()) { - return false; - } - for (String param : data) { - if (!hex.matcher(param).matches()) { - return false; - } - } - return readHex(data.toArray(new String[data.size()])); - } - - public void writeCSV(OutputStream out) throws IOException { - String[] hex = expand(); - Writer w = new OutputStreamWriter(out); - for (int i = 0; i < hex.length; ++i) { - w.write(hex[i]); - if (i < hex.length - 1) { - w.write(","); - } - } - w.flush(); - } - - public boolean readBytes(byte[] data) { - //TODO - return false; - } } -- cgit v1.2.3-70-g09d2