/* * * * Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */ package wim_data; import java.io.*; import java.security.*; import java.security.cert.CertificateException; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; /** * This class represents WIM file system generator. It produces file * Data.java that can be used with WIM emulator. File system parameters * are defined using fields of this class. */ public class Main { /** WIM root DF. */ short[] WIMDF = {0x3f00, 0x5015}; // MUST be long name /** DF for PIN verification. */ short[] PINDF = {0x5300}; /** Path to ODF. */ short[] ODF = {0x5031}; /** Path to EF(TokenInfo). */ short[] TokenInfo = {0x5032}; /** Path to EF(UnusedSpace) */ short[] UnusedSpace = {0x5033}; /** Path to PrKDF. */ short[] PrKDF = {0x5200}; /** Path to PuKDF. */ short[] PuKDF = {0x5201}; /** Path to CDF for trusted certificates. */ short[] TrustedCDF = {0x5202}; /** Path to CDF for useful certificates. */ short[] UsefulCDF = {0x5203}; /** Path to AODF. */ short[] AODF = {0x5204}; /** Path to file with trusted certificates. */ short[] TrustedCerts = {0x5205}; /** Path to empty space. */ short[] DataFile = {0x5206}; /** Path to CDF for user certificates. */ short[] UserCDF = {0x5207}; /** Size in bytes of CDF files for user and useful certificates. */ short CDFSpace = 2048; /** Size of empty space. */ short FreeSpace = 4096; /** WIM GENERIC RSA security environment ID. */ byte WIM_GENERIC_RSA_ID = 0x44; /** RSA algorithm ID. */ byte RSA_ALGORITHM_ID = 0x55; /** If true, EF(ODF) contains entry with root directory path. */ boolean IncludeRoot = true; /** PINs. */ PIN[] PINs = { new PIN("PIN 1", 2, 11, PINDF, "1234"), new PIN("Non repudiation key 1 PIN", 6, 22, PINDF, "2345"), new PIN("Non repudiation key 2 PIN", 7, 33, PINDF, "3456")}; /** Pre-generated key pairs. */ Key[] Keys = { new Key("NR key 1", 512, 1, true, 5, new short[] {0x5301}, new short[] {0x5281}, PINs), new Key("NR key 2", 512, 2, true, 7, new short[] {0x5302}, new short[] {0x5282}, PINs), new Key("Authentication key 1", 512, 0, false, 8, new short[] {0x5303}, new short[] {0x5283}, PINs), new Key("Authentication key 2", 512, 0, false, 20, new short[] {0x5304}, new short[] {0x5284}, PINs) }; /** WIM token label. */ String tokenLabel = "WIM 1.01 SATSA RI"; /** WIM manifacturer ID. */ String manufacturerID = "SATSA RI"; /** Serial number. */ byte[] SerialNumber = {0x15, (byte) 0x97, 0x52, 0x22, 0x25, 0x15, 0x40, 0x12, 0x40}; /** The number of keys that can be generated. */ int freeKeySlots = 4; /** Identifier of file for new key. */ short newFileID = 0x5400; /** Identifier for new key. */ byte newKeyID = 40; /** The number of PINs that can be added. */ int freePINSlots = 4; /** Identifier of new PIN. */ int newPINID = 80; /** Reference of new PIN. */ int newPINRef = 60; /** File system. */ FileSystem fs; /** Stream for debug output. */ PrintStream log; /** Stream for results. */ PrintStream src; /** Output directory */ private String outputDataDir = "./output/"; private String outputDir = "./output/"; /** * Main entry point. * @param args command line arguments */ public static void main(String[] args) throws Exception { new Main().run(args); } /** * Generates the data. * @throws KeyStoreException if this exception occurs * @throws CertificateException if this exception occurs * @throws IOException if this exception occurs * @throws NoSuchAlgorithmException if this exception occurs */ public void run(String[] args) throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException { if (args.length >= 1) { outputDataDir = args[0]; } if (args.length >= 2) { outputDir = args[1]; } fs = new FileSystem(WIMDF); fs.addFile(PINDF, FileSystem.PIN, null); log = new PrintStream(new FileOutputStream(outputDir + "listing.txt")); src = new PrintStream(new FileOutputStream(outputDataDir + "Data.java")); src.print("/*\n" + " * \n" + " *\n" + " * Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved.\n" + " * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER\n" + " *\n */\n\npackage com.sun.satsa.pkiapplet;\n\n/**\n" + " * This class contains WIM PINs, private keys and file " + "system.\n" + " */\npublic class Data {\n\n /** Identifier for RSA generic " + "SE. */\n" + " static final byte WIM_GENERIC_RSA_ID = " + WIM_GENERIC_RSA_ID + ";\n\n"); src.println(" /** The number of keys that can be generated. " + "*/\n static short freeKeySlots = " + freeKeySlots + ";"); src.println(" /** Identifier of file for new key. */\n " + "static short newFileID = (short) " + newFileID + ";"); src.println(" /** Identifier for new key. */\n static " + "byte newKeyID = " + newKeyID + ";"); src.println(" /** The number of PINs that can be added. " + "*/\n static short freePINSlots = " + freePINSlots + ";"); src.println(" /** Identifier of new PIN. */\n static " + "byte newPINID = (byte) " + newPINID + ";"); src.println(" /** Reference of new PIN. */\n static " + "byte newPINRef = (byte) " + newPINRef + ";"); src.println(" /** Identifier of PIN-G. */\n static " + "final byte PIN_G_ID = (byte) " + PINs[0].id + ";"); ODF(); TokenInfo(); Unused(); TrustedCerts(); UserCerts(); AODF(); Keys(); byte[] data = fs.getEncoded(); src.println(" /** AODF data offset. */\n static final " + "short AODFOffset = (short) " + fs.getOffset("AODF") + ";"); src.println(" /** PrKDF data offset. */\n static final " + "short PrKDFOffset = (short) " + fs.getOffset("PrKDF") + ";"); src.println(" /** PuKDF data offset. */\n static final " + "short PuKDFOffset = (short) " + fs.getOffset("PuKDF") + ";"); src.println(); src.print(" /** Files. */"); Utils.writeDataArray(src, "Files", data); src.println("}"); log.close(); src.close(); } /** * Generates ODF file. */ public void ODF() { /* PKCS15Objects ::= CHOICE { privateKeys [0] PKCS15PrivateKeys, publicKeys [1] PKCS15PublicKeys, trustedCertificates [5] PKCS15Certificates, usefulCertificates [6] PKCS15Certificates, authObjects [8] PKCS15AuthObjects, dataObjects [7] PKCS15DataObjects } dataObjects : objects { opaqueDO : { commonObjectAttributes {}, classAttributes { applicationOID {wap-wsg-3} }, typeAttributes direct : OCTET STRING:'3F00 5015'H } } */ TLV odf = TLV.createSequence(); TLV t; TLV current = odf.setChild(new TLV(TLV.NULL_TYPE)); if (PrKDF != null) { t = new TLV(0xa0); t.setChild(TLV.createSequence()). setChild(TLV.createOctetString( Utils.shortToBytes(PrKDF))); current = current.setNext(t); } if (PuKDF != null) { t = new TLV(0xa1); t.setChild(TLV.createSequence()). setChild(TLV.createOctetString( Utils.shortToBytes(PuKDF))); current = current.setNext(t); } if (TrustedCDF != null) { t = new TLV(0xa5); t.setChild(TLV.createSequence()). setChild(TLV.createOctetString( Utils.shortToBytes(TrustedCDF))); current = current.setNext(t); } if (UsefulCDF != null) { t = new TLV(0xa6); t.setChild(TLV.createSequence()). setChild(TLV.createOctetString( Utils.shortToBytes(UsefulCDF))); current = current.setNext(t); } if (UserCDF != null) { t = new TLV(0xa4); t.setChild(TLV.createSequence()). setChild(TLV.createOctetString( Utils.shortToBytes(UserCDF))); current = current.setNext(t); } if (AODF != null) { t = new TLV(0xa8); t.setChild(TLV.createSequence()). setChild(TLV.createOctetString( Utils.shortToBytes(AODF))); current = current.setNext(t); } if (IncludeRoot) { t = new TLV(0xa7); current.setNext(t); t = t.setChild(new TLV(0xa0)). setChild(TLV.createSequence()). setChild(TLV.createSequence()); t = t.setChild(TLV.createSequence()); t = t.setNext(TLV.createSequence()); t.setChild(TLV.createOID("2.23.43.1.3")); t.setNext(new TLV(0xa1)).setChild( TLV.createOctetString(Utils.shortToBytes(WIMDF))); } odf.child = odf.child.next; fs.addFile(ODF, FileSystem.READ, odf.getValue()); log.println("********* ODF"); Utils.writeHex(log, odf.getValue()); log.println(); odf.child.print(log); log.println(""); } /** * Generates EF(TokenInfo) file. */ public void TokenInfo() { /* PKCS15TokenInfo ::= SEQUENCE { version INTEGER {v1(0)} (v1,...), serialNumber OCTET STRING, manufacturerID PKCS15Label OPTIONAL, label [0] PKCS15Label OPTIONAL, tokenflags PKCS15TokenFlags, seInfo SEQUENCE OF PKCS15SecurityEnvironmentInfo OPTIONAL, recordInfo [1] PKCS15RecordInfo OPTIONAL, supportedAlgorithms [2] SEQUENCE OF PKCS15AlgorithmInfo OPTIONAL, ... -- For future extensions } */ TLV t; TLV info = TLV.createSequence(); t = info.setChild(TLV.createInteger(0)); t = t.setNext(TLV.createOctetString(SerialNumber)); t = t.setNext(TLV.createUTF8String(manufacturerID)); t = t.setNext(TLV.createUTF8String(tokenLabel)).setTag(0x80); t = t.setNext(new TLV(TLV.BITSTRING_TYPE, new byte[] {0})); t = t.setNext(TLV.createSequence()); t.setChild(TLV.createSequence()). setChild(TLV.createInteger(WIM_GENERIC_RSA_ID)). setNext(TLV.createOID("2.23.43.1.1.2")); t = t.setNext(new TLV(0xa2)); t.setChild(TLV.createSequence()). setChild(TLV.createInteger(RSA_ALGORITHM_ID)). setNext(TLV.createInteger(0)). setNext(new TLV(TLV.NULL_TYPE)). setNext(new TLV(TLV.BITSTRING_TYPE, Utils.shortToBytes(0x0640))); fs.addFile(TokenInfo, FileSystem.READ, info.getDERData()); log.println("********* TokenInfo"); Utils.writeHex(log, info.getDERData()); log.println(); info.print(log); log.println(); } /** * Generates UnusedSpace file. */ public void Unused() { /* PKCS15UnusedSpace ::= SEQUENCE { path PKCS15Path, authId PKCS15Identifier OPTIONAL } */ TLV m = TLV.createSequence(); TLV v = m.setChild(TLV.createSequence()); TLV t = v.setChild(Utils.createPath(DataFile, 0, FreeSpace)); t.setNext(TLV.createOctetString(new byte[] {(byte) PINs[0].id})); byte[] data = new byte[t.getDERSize() * 19 - 4]; v.setNext(new TLV(0, data)); fs.addFile(UnusedSpace, FileSystem.UPDATE | FileSystem.EMPTY, m.getValue()); log.println("********* UnusedSpace"); Utils.writeHex(log, m.getValue()); log.println(); m.child.print(log); log.println(); } /** * Generates file with trusted certificates. * @throws IOException if this exception occurs * @throws KeyStoreException if this exception occurs * @throws CertificateException if this exception occurs * @throws NoSuchAlgorithmException if this exception occurs */ public void TrustedCerts() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException { byte[] data = CACertificate; fs.addFile(TrustedCerts, FileSystem.READ, data); log.println("********* TrustedCerts"); Utils.writeHex(log, data); log.println(); new TLV(data, 0).print(log); log.println(); /* PKCS15CertificateObject {CertAttributes} ::= PKCS15Object { PKCS15CommonCertificateAttributes, NULL, CertAttributes} PKCS15Object {ClassAttributes, SubClassAttributes, TypeAttributes} ::= SEQUENCE { commonObjectAttributes PKCS15CommonObjectAttributes, classAttributes ClassAttributes, subClassAttributes [0] SubClassAttributes OPTIONAL, typeAttributes [1] TypeAttributes } PKCS15CommonObjectAttributes ::= SEQUENCE { + label PKCS15Label OPTIONAL, + flags PKCS15CommonObjectFlags OPTIONAL, authId PKCS15Identifier OPTIONAL, ... -- For future extensions } PKCS15CommonObjectFlags ::= BIT STRING { private(0), modifiable (1) } PKCS15CommonCertificateAttributes ::= SEQUENCE { + iD PKCS15Identifier, + authority BOOLEAN DEFAULT FALSE, + requestId PKCS15KeyIdentifier OPTIONAL, thumbprint [0] PKCS15OOBCertHash OPTIONAL, ... -- For future extensions } PKCS15X509CertificateAttributes ::= SEQUENCE { value PKCS15ObjectValue { PKCS15X509Certificate }, subject Name OPTIONAL, issuer [0] Name OPTIONAL, serialNumber CertificateSerialNumber OPTIONAL, ... -- For future extensions } */ // Parse CA certificate TLV CACertPointer = new TLV(data, 0); CACertPointer = CACertPointer.child.child; if (CACertPointer.type == TLV.VERSION_TYPE) { CACertPointer = CACertPointer.next; } // CACertPointer is at SerialNumber field byte[] modulus = new TLV(CACertPointer.next.next.next.next.next. child.next.getValue(), 1).child.getValue(); byte[] id = Utils.getHash(modulus, 0, modulus.length); TLV commonAttrs = TLV.createSequence(); commonAttrs. setChild(Utils.createLabel("CA CERTIFICATE")). setNext(new TLV(TLV.BITSTRING_TYPE, Utils.shortToBytes(0))); TLV commonCertAttrs = TLV.createSequence(); commonCertAttrs. setChild(TLV.createOctetString(id)). setNext(new TLV(TLV.BOOLEAN_TYPE, new byte[] {(byte) 255})); TLV x509Attrs = new TLV(0xa1); x509Attrs.setChild(TLV.createSequence()). setChild(Utils.createPath(TrustedCerts, 0, data.length)); TLV cdf = TLV.createSequence(); cdf.setChild(commonAttrs). setNext(commonCertAttrs). setNext(x509Attrs); byte[] cdfData = cdf.getDERData(); fs.addFile(TrustedCDF, FileSystem.READ, cdfData); log.println("********* TrustedCDF"); Utils.writeHex(log, cdfData); log.println(); new TLV(cdfData, 0).print(log); log.println(); } /** * Generates user certificate files. */ public void UserCerts() { byte[] UsefulCDFData = new TLV(0, new byte[CDFSpace]).getDERData(); // There are two CDF files, one of them for 'useful', other // for user certificates. Both have the same size and content, // initially they are empty. fs.addFile(UsefulCDF, FileSystem.UPDATE | FileSystem.EMPTY, UsefulCDFData); fs.addFile(UserCDF, FileSystem.UPDATE | FileSystem.EMPTY, UsefulCDFData); log.println("********* UsefulCDF"); Utils.writeHex(log, UsefulCDFData); log.println(); new TLV(UsefulCDFData, 0).print(log); log.println(); fs.addFile(DataFile, FileSystem.UPDATE | FileSystem.EMPTY, new byte[FreeSpace]); } /** * Generates AODF file. * @throws IOException if this exception occurs */ public void AODF() throws IOException { /* PKCS15Authentication ::= CHOICE { pin PKCS15AuthenticationObject { PKCS15PinAttributes }, ... -- For future extensions, e.g. biometric authentication -- objects } PKCS15AuthenticationObject {AuthObjectAttributes} ::= PKCS15Object { PKCS15CommonAuthenticationObjectAttributes, NULL, AuthObjectAttributes } PKCS15Object {ClassAttributes, SubClassAttributes, TypeAttributes} ::= SEQUENCE { commonObjectAttributes PKCS15CommonObjectAttributes, classAttributes ClassAttributes, subClassAttributes [0] SubClassAttributes OPTIONAL, typeAttributes [1] TypeAttributes } PKCS15CommonObjectAttributes ::= SEQUENCE { + label PKCS15Label OPTIONAL, + flags PKCS15CommonObjectFlags OPTIONAL, authId PKCS15Identifier OPTIONAL, ... -- For future extensions } PKCS15CommonAuthenticationObjectAttributes ::= SEQUENCE { + authId PKCS15Identifier, ... �- For future extensions } PKCS15PinAttributes ::= SEQUENCE { + pinFlags PKCS15PinFlags, + pinType PKCS15PinType, + minLength INTEGER (pkcs15-lb-minPinLength.. pkcs15-ub-minPinLength), + storedLength INTEGER (pkcs15-lb-minPinLength.. pkcs15-ub-storedPinLength), maxLength INTEGER OPTIONAL, + pinReference [0] PKCS15Reference OPTIONAL, + padChar OCTET STRING (SIZE(1)) OPTIONAL, lastPinChange GeneralizedTime OPTIONAL, + path PKCS15Path OPTIONAL, ... -- For future extensions } PKCS15PinFlags ::= BIT STRING { case-sensitive (0), 80 local (1), 40 change-disabled (2), 20 * unblock-disabled (3), 10 initialized (4), 08 * needs-padding (5), 04 * unblockingPin (6), 02 soPin (7), 01 disable-allowed (8) } PKCS15PinType ::= ENUMERATED {bcd, ascii-numeric, utf8, ... -- bcd = one nibble contains one digit -- ascii-numeric = one byte contains one ASCII digit -- utf8 = password is stored in UTF8 encoding } */ TLV[] t = new TLV[PINs.length + freePINSlots]; for (int i = 0; i < PINs.length; i++) { t[i] = PINs[i].toTLV(); } int PINRecordSize = 0; int PINLabelOffset = 0; for (int i = 0; i < freePINSlots; i++) { PIN pin = new PIN("", newPINID + i, newPINRef + i, PINDF, "1"); t[PINs.length + i] = pin.toTLV(); if (i == 0) { PINRecordSize = t[PINs.length + i].getDERSize(); PINLabelOffset = t[PINs.length + i].copy().child.child. valueOffset; } else { if (PINRecordSize != t[PINs.length + i].getDERSize()) { System.out.println( "Error - PIN placeholder size changed."); System.exit(1); } } t[PINs.length + i].type = 0; } for (int i = 0; i < t.length - 1; i++) { t[i].next = t[i + 1]; } TLV aodf = TLV.createSequence(); aodf.setChild(t[0]); byte[] data = aodf.getValue(); fs.addFile(AODF, FileSystem.READ, data, "AODF"); src.println(" /** PIN record size. */\n static final " + "short PINRecordSize = " + PINRecordSize + ";"); src.println(" /** PIN label offset. */\n static final " + "short PINLabelOffset = " + PINLabelOffset + ";"); src.println(" /** New PIN offset in AODF. */\n static " + "short newPINOffset = " + (data.length - freePINSlots * PINRecordSize) + ";"); log.println("********* AODF"); Utils.writeHex(log, data); log.println(); aodf.child.print(log); log.println(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(baos); out.writeByte(PINs.length); for (int i = 0; i < PINs.length; i++) { out.writeByte(PINs[i].ref); byte[] PINData = PINs[i].getData(); out.writeByte(PINData.length); out.write(PINData); } src.print("\n /** PINs. */"); Utils.writeDataArray(src, "PINs", baos.toByteArray()); } /** * Generates all necessary data structures for keys. * @throws NoSuchAlgorithmException if this exception occurs * @throws IOException if this exception occurs */ public void Keys() throws NoSuchAlgorithmException, IOException { /* PKCS15PrivateKeyObject {KeyAttributes} ::= PKCS15Object { PKCS15CommonKeyAttributes, PKCS15CommonPrivateKeyAttributes, KeyAttributes } PKCS15Object {ClassAttributes, SubClassAttributes, TypeAttributes} ::= SEQUENCE { commonObjectAttributes PKCS15CommonObjectAttributes, classAttributes ClassAttributes, subClassAttributes [0] SubClassAttributes OPTIONAL, typeAttributes [1] TypeAttributes } PKCS15CommonObjectAttributes ::= SEQUENCE { + label PKCS15Label OPTIONAL, + flags PKCS15CommonObjectFlags OPTIONAL, + authId PKCS15Identifier OPTIONAL, ... -- For future extensions } PKCS15CommonKeyAttributes ::= SEQUENCE { + iD PKCS15Identifier, + usage PKCS15KeyUsageFlags, native BOOLEAN DEFAULT TRUE, accessFlags PKCS15KeyAccessFlags OPTIONAL, + keyReference PKCS15Reference OPTIONAL, startDate GeneralizedTime OPTIONAL, endDate [0] GeneralizedTime OPTIONAL, ... -- For future extensions } PKCS15KeyUsageFlags ::= BIT STRING { encrypt (0), 80 decrypt (1), 40 sign (2), 20 signRecover (3), 10 wrap (4), 08 unwrap (5), 04 verify (6), 02 verifyRecover (7), 01 derive (8), 80 nonRepudiation (9) 40 } PKCS15PrivateRSAKeyAttributes ::= SEQUENCE { value PKCS15ObjectValue {PKCS15RSAPrivateKey}, modulusLength INTEGER, -- modulus length in bits, e.g. 1024 keyInfo PKCS15KeyInfo {PKCS15RSAParameters, PKCS15PublicKeyOperations} OPTIONAL, ... �- For future extensions } PKCS15KeyInfo {ParameterType, OperationsType} ::= CHOICE { reference PKCS15Reference, paramsAndOps SEQUENCE { parameters ParameterType, supportedOperations OperationsType OPTIONAL} } PKCS15PublicKeyObject {KeyAttributes} ::= PKCS15Object { PKCS15CommonKeyAttributes, PKCS15CommonPublicKeyAttributes, KeyAttributes} PKCS15CommonPublicKeyAttributes ::= SEQUENCE { subjectName Name OPTIONAL, ... -- For future extensions } PKCS15PublicRSAKeyAttributes ::= SEQUENCE { value PKCS15ObjectValue {PKCS15RSAPublicKey}, modulusLength INTEGER, -- modulus length in bits, e.g. 1024 keyInfo PKCS15KeyInfo {PKCS15RSAParameters, PKCS15PublicKeyOperations} OPTIONAL, ... �- For future extensions } PKCS15RSAPublicKey ::= SEQUENCE { modulus INTEGER, -- n publicExponent INTEGER -- e } */ TLV[] PrK = new TLV[Keys.length + freeKeySlots]; TLV[] PuK = new TLV[Keys.length + freeKeySlots]; ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(baos); out.writeByte(Keys.length); for (int i = 0; i < Keys.length; i++) { Keys[i].init(); RSAPrivateKey priv = Keys[i].priv; RSAPublicKey pub = Keys[i].pub; int offset; int len; out.writeByte(Keys[i].id); out.writeByte(Keys[i].pinIndex); out.writeByte(Keys[i].nonRepudiation ? 0 : 1); byte[] x = priv.getModulus().toByteArray(); offset = 0; len = x.length; while (x[offset] == 0) { offset++; len--; } short keyLen = (short)(len * 8); out.writeShort(keyLen); out.writeShort(len); out.write(x, offset, len); x = priv.getPrivateExponent().toByteArray(); offset = 0; len = x.length; while (x[offset] == 0) { offset++; len--; } out.writeShort(len); out.write(x, offset, len); PrK[i] = Keys[i].getPrivate(RSA_ALGORITHM_ID); PuK[i] = Keys[i].getPublic(); byte[] keyData = new TLV(new TLV(pub.getEncoded(), 0).child. next.getValue(), 1).getDERData(); fs.addFile(Keys[i].PublicPath, FileSystem.READ, keyData); fs.addFile(Keys[i].PrivatePath, FileSystem.PrK, new byte[] {(byte) Keys[i].id}); } int privKeyRecordSize = 0; int privPINIDOffset = 0; int privHashOffset = 0; int privUsageOffset = 0; int privKeyLengthOffset = 0; int pubKeyRecordSize = 0; int pubHashOffset = 0; int pubKeyLengthOffset = 0; short FileId = newFileID; for (int i = 0; i < freeKeySlots; i++) { Key k = new Key("New key " + (i + 1), 1024, 0, true, newKeyID + i, new short[] {FileId}, new short[] {(short) (FileId + 1)}, PINs); FileId += 2; TLV prk = k.getPrivate(RSA_ALGORITHM_ID); TLV puk = k.getPublic(); if (i == 0) { TLV t = prk.copy(); privKeyRecordSize = t.getDERSize(); privPINIDOffset = t.child.child.next.next.valueOffset; privHashOffset = t.child.next.child.valueOffset; privUsageOffset = t.child.next.child.next.valueOffset; privKeyLengthOffset = t.child.next.next.child.child.next. valueOffset; t = puk.copy(); pubKeyRecordSize = t.getDERSize(); pubHashOffset = t.child.next.child.valueOffset; pubKeyLengthOffset = t.child.next.next.child.child.next. valueOffset; } prk.type = 0; PrK[Keys.length + i] = prk; puk.type = 0; PuK[Keys.length + i] = puk; fs.addFile(k.PublicPath, FileSystem.READ, new byte[0]); fs.addFile(k.PrivatePath, FileSystem.PrK, new byte[] {(byte) k.id}); } for (int i = 1; i < PrK.length; i++) { PrK[i - 1].setNext(PrK[i]); PuK[i - 1].setNext(PuK[i]); } byte[] data; TLV prkdf = TLV.createSequence(); prkdf.setChild(PrK[0]); data = prkdf.getValue(); fs.addFile(PrKDF, FileSystem.READ, data, "PrKDF"); src.println(" /** Offset from start of the first empty entry " + "in PrKDF. */\n static short newPrivKeyOffset = " + (data.length - freeKeySlots * privKeyRecordSize) + ";"); src.println(" /** The size of record in PrKDF. */\n " + "static final short privKeyRecordSize = " + privKeyRecordSize + ";"); src.println(" /** Offset of PIN identifier data in PrKDF " + "record. */\n static final short privPINIDOffset = " + privPINIDOffset + ";"); src.println(" /** Offset of key identifier data in PrKDF " + "record. */\n static final short privHashOffset = " + privHashOffset + ";"); src.println(" /** Offset of usage field data in PrKDF " + "record. */\n static final short privUsageOffset = " + privUsageOffset + ";"); src.println(" /** Offset of key length in PrKDF record. " + "*/\n static final short privKeyLengthOffset = " + privKeyLengthOffset + ";"); src.println(); log.println("********* PrKDF"); Utils.writeHex(log, data); log.println(); prkdf.child.print(log); log.println(); TLV pukdf = TLV.createSequence(); pukdf.setChild(PuK[0]); data = pukdf.getValue(); fs.addFile(PuKDF, FileSystem.READ, data, "PuKDF"); src.println(" /** Offset from start of the first empty entry " + "in PrKDF. */\n static short newPubKeyOffset = " + (data.length - freeKeySlots * pubKeyRecordSize) + ";"); src.println(" /** The size of record in PuKDF. */\n static" + " final short pubKeyRecordSize = " + pubKeyRecordSize + ";"); src.println(" /** Offset of key identifier data in PuKDF " + "record. */\n static final short pubHashOffset = " + pubHashOffset + ";"); src.println(" /** Offset of key length in PuKDF record. */\n" + " static final short pubKeyLengthOffset = " + pubKeyLengthOffset + ";"); src.println(); log.println("********* PuKDF"); Utils.writeHex(log, data); log.println(); pukdf.child.print(log); log.println(); src.print(" /** Private keys. */"); Utils.writeDataArray(src, "PrivateKeys", baos.toByteArray()); } /** * CA certificate (MIDP 2.0 RI keystore, alias dummyca). */ static byte[] CACertificate = { 48, -126, 3, 61, 48, -126, 2, 37, 2, 4, 61, 62, -50, -118, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 4, 5, 0, 48, 99, 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 116, 104, 101, 104, 111, 115, 116, 49, 12, 48, 10, 6, 3, 85, 4, 11, 19, 3, 74, 67, 84, 49, 17, 48, 15, 6, 3, 85, 4, 10, 19, 8, 100, 117, 109, 109, 121, 32, 67, 65, 49, 20, 48, 18, 6, 3, 85, 4, 7, 19, 11, 83, 97, 110, 116, 97, 32, 67, 108, 97, 114, 97, 49, 11, 48, 9, 6, 3, 85, 4, 8, 19, 2, 67, 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 30, 23, 13, 48, 50, 48, 55, 50, 52, 49, 53, 53, 56, 48, 50, 90, 23, 13, 49, 50, 48, 55, 50, 49, 49, 53, 53, 56, 48, 50, 90, 48, 99, 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 116, 104, 101, 104, 111, 115, 116, 49, 12, 48, 10, 6, 3, 85, 4, 11, 19, 3, 74, 67, 84, 49, 17, 48, 15, 6, 3, 85, 4, 10, 19, 8, 100, 117, 109, 109, 121, 32, 67, 65, 49, 20, 48, 18, 6, 3, 85, 4, 7, 19, 11, 83, 97, 110, 116, 97, 32, 67, 108, 97, 114, 97, 49, 11, 48, 9, 6, 3, 85, 4, 8, 19, 2, 67, 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, -126, 1, 34, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 3, -126, 1, 15, 0, 48, -126, 1, 10, 2, -126, 1, 1, 0, -32, -30, -97, -62, 117, 76, 16, 83, -69, 72, -53, 84, 35, -28, -111, 23, -94, -20, 89, -97, 111, 87, 127, -101, 106, 31, -109, 94, 105, -15, -44, 86, -71, 101, -98, 20, 39, -72, -79, -75, -99, -22, -42, -17, -62, 3, 78, -101, 40, 30, 27, 8, 26, 5, 77, -9, -75, -25, -110, -51, 58, 89, -40, -74, -74, 32, -13, -56, 43, -8, 30, 56, -39, -76, -12, 35, -64, 3, -55, 2, 113, 122, -84, 64, 37, 103, -2, -62, 106, -46, 59, 37, 20, 41, -11, -103, -116, -17, 81, 37, -92, 55, -38, -79, 101, -74, 73, -9, -99, 30, 90, 52, 14, 23, -14, 80, -110, -123, -69, 28, 108, -82, 106, -28, -32, 41, -27, -3, -51, 16, 26, -85, 7, -57, -92, 50, -41, -67, 112, 36, -58, 83, 115, 51, -107, 98, -124, -103, -75, 59, -125, -112, 14, -68, -111, 88, -16, -107, -106, 21, 15, -19, 104, -70, 70, 5, 34, -103, 85, 30, 57, -66, -11, 52, -51, -71, 67, -34, 28, -21, -16, 121, -18, -99, 96, -91, 80, 120, -32, 56, -7, 40, -106, -81, 7, -103, -42, -50, 124, -68, 59, 4, -3, 13, 9, 112, -79, -83, -49, -91, 70, -56, 65, 92, 7, -40, -101, -53, -41, -53, 92, -60, -106, 14, 65, -124, 59, 40, -111, 7, -59, -36, -98, 113, 120, 16, 65, -115, 5, 61, 54, 63, 120, -95, -100, -77, 55, -127, 42, -91, -48, 37, -83, -2, 113, 7, 2, 3, 1, 0, 1, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 4, 5, 0, 3, -126, 1, 1, 0, 19, -115, 51, 67, 74, -32, -104, -44, -31, 73, -70, -60, -128, -106, -88, -95, -33, -2, -100, -48, -98, -43, -110, 43, 4, 77, -63, -11, 119, -60, 121, 91, -42, -28, -61, -116, 104, 58, 120, -88, -28, 12, 64, -82, -94, 36, 27, -38, -4, 108, -20, 96, -94, 96, 82, 40, -114, -80, -65, 31, -96, -53, -90, -55, 37, 102, -79, -12, 125, 91, 102, -8, 10, -95, 26, -82, -11, 83, -31, 102, -96, -114, -40, 0, 99, -9, -34, 112, 21, 54, 105, -92, 121, 101, 5, 90, 76, -10, -119, 117, -87, 65, -54, 17, -6, 62, -36, -60, 78, -78, 45, 9, 27, -40, -78, -91, 74, -113, 80, -118, -21, 71, 88, 24, 39, -74, -40, 86, -23, -79, 68, -3, 99, 36, 122, 26, -72, 91, 55, 113, -39, -29, 84, -79, 85, 100, -93, 118, 26, 46, -86, -35, -99, 100, 113, -97, -65, -94, 47, 115, -43, 81, 16, -23, -52, 52, 88, -54, -120, 123, -25, 33, 114, 81, 24, 67, 113, 41, 105, -126, 100, 75, -90, -57, -69, 75, 96, 111, 88, 113, -18, -94, 63, 62, -105, 5, 57, -22, -34, -81, 57, -84, -121, -39, 65, 122, 100, -75, -22, -69, -92, -61, 14, -36, 126, 86, -41, 115, -25, 64, 44, 31, -124, -7, -12, -117, 83, 109, -125, -86, -46, 79, 114, -37, 107, 96, -14, -83, 101, 53, 120, 27, 52, 46, -84, -96, -21, 93, 44, 2, 33, 21, 89, -93, -128, -31}; }