0001: /*
0002: *
0003: *
0004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
0005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006: *
0007: * This program is free software; you can redistribute it and/or
0008: * modify it under the terms of the GNU General Public License version
0009: * 2 only, as published by the Free Software Foundation.
0010: *
0011: * This program is distributed in the hope that it will be useful, but
0012: * WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * General Public License version 2 for more details (a copy is
0015: * included at /legal/license.txt).
0016: *
0017: * You should have received a copy of the GNU General Public License
0018: * version 2 along with this work; if not, write to the Free Software
0019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020: * 02110-1301 USA
0021: *
0022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023: * Clara, CA 95054 or visit www.sun.com if you need additional
0024: * information or have any questions.
0025: */
0026:
0027: package wim_data;
0028:
0029: import java.io.*;
0030: import java.security.*;
0031: import java.security.cert.CertificateException;
0032: import java.security.interfaces.RSAPrivateKey;
0033: import java.security.interfaces.RSAPublicKey;
0034:
0035: /**
0036: * This class represents WIM file system generator. It produces file
0037: * Data.java that can be used with WIM emulator. File system parameters
0038: * are defined using fields of this class.
0039: */
0040: public class Main {
0041:
0042: /** WIM root DF. */
0043: short[] WIMDF = { 0x3f00, 0x5015 }; // MUST be long name
0044:
0045: /** DF for PIN verification. */
0046: short[] PINDF = { 0x5300 };
0047:
0048: /** Path to ODF. */
0049: short[] ODF = { 0x5031 };
0050: /** Path to EF(TokenInfo). */
0051: short[] TokenInfo = { 0x5032 };
0052: /** Path to EF(UnusedSpace) */
0053: short[] UnusedSpace = { 0x5033 };
0054: /** Path to PrKDF. */
0055: short[] PrKDF = { 0x5200 };
0056: /** Path to PuKDF. */
0057: short[] PuKDF = { 0x5201 };
0058: /** Path to CDF for trusted certificates. */
0059: short[] TrustedCDF = { 0x5202 };
0060: /** Path to CDF for useful certificates. */
0061: short[] UsefulCDF = { 0x5203 };
0062: /** Path to AODF. */
0063: short[] AODF = { 0x5204 };
0064: /** Path to file with trusted certificates. */
0065: short[] TrustedCerts = { 0x5205 };
0066: /** Path to empty space. */
0067: short[] DataFile = { 0x5206 };
0068: /** Path to CDF for user certificates. */
0069: short[] UserCDF = { 0x5207 };
0070:
0071: /** Size in bytes of CDF files for user and useful certificates. */
0072: short CDFSpace = 2048;
0073: /** Size of empty space. */
0074: short FreeSpace = 4096;
0075:
0076: /** WIM GENERIC RSA security environment ID. */
0077: byte WIM_GENERIC_RSA_ID = 0x44;
0078: /** RSA algorithm ID. */
0079: byte RSA_ALGORITHM_ID = 0x55;
0080:
0081: /** If true, EF(ODF) contains entry with root directory path. */
0082: boolean IncludeRoot = true;
0083:
0084: /** PINs. */
0085: PIN[] PINs = { new PIN("PIN 1", 2, 11, PINDF, "1234"),
0086: new PIN("Non repudiation key 1 PIN", 6, 22, PINDF, "2345"),
0087: new PIN("Non repudiation key 2 PIN", 7, 33, PINDF, "3456") };
0088:
0089: /** Pre-generated key pairs. */
0090: Key[] Keys = {
0091: new Key("NR key 1", 512, 1, true, 5,
0092: new short[] { 0x5301 }, new short[] { 0x5281 },
0093: PINs),
0094: new Key("NR key 2", 512, 2, true, 7,
0095: new short[] { 0x5302 }, new short[] { 0x5282 },
0096: PINs),
0097: new Key("Authentication key 1", 512, 0, false, 8,
0098: new short[] { 0x5303 }, new short[] { 0x5283 },
0099: PINs),
0100: new Key("Authentication key 2", 512, 0, false, 20,
0101: new short[] { 0x5304 }, new short[] { 0x5284 },
0102: PINs) };
0103:
0104: /** WIM token label. */
0105: String tokenLabel = "WIM 1.01 SATSA RI";
0106:
0107: /** WIM manifacturer ID. */
0108: String manufacturerID = "SATSA RI";
0109:
0110: /** Serial number. */
0111: byte[] SerialNumber = { 0x15, (byte) 0x97, 0x52, 0x22, 0x25, 0x15,
0112: 0x40, 0x12, 0x40 };
0113:
0114: /** The number of keys that can be generated. */
0115: int freeKeySlots = 4;
0116: /** Identifier of file for new key. */
0117: short newFileID = 0x5400;
0118: /** Identifier for new key. */
0119: byte newKeyID = 40;
0120:
0121: /** The number of PINs that can be added. */
0122: int freePINSlots = 4;
0123: /** Identifier of new PIN. */
0124: int newPINID = 80;
0125: /** Reference of new PIN. */
0126: int newPINRef = 60;
0127:
0128: /** File system. */
0129: FileSystem fs;
0130: /** Stream for debug output. */
0131: PrintStream log;
0132: /** Stream for results. */
0133: PrintStream src;
0134:
0135: /** Output directory */
0136: private String outputDataDir = "./output/";
0137: private String outputDir = "./output/";
0138:
0139: /**
0140: * Main entry point.
0141: * @param args command line arguments
0142: */
0143: public static void main(String[] args) throws Exception {
0144: new Main().run(args);
0145: }
0146:
0147: /**
0148: * Generates the data.
0149: * @throws KeyStoreException if this exception occurs
0150: * @throws CertificateException if this exception occurs
0151: * @throws IOException if this exception occurs
0152: * @throws NoSuchAlgorithmException if this exception occurs
0153: */
0154: public void run(String[] args) throws KeyStoreException,
0155: CertificateException, IOException, NoSuchAlgorithmException {
0156:
0157: if (args.length >= 1) {
0158: outputDataDir = args[0];
0159: }
0160:
0161: if (args.length >= 2) {
0162: outputDir = args[1];
0163: }
0164:
0165: fs = new FileSystem(WIMDF);
0166: fs.addFile(PINDF, FileSystem.PIN, null);
0167:
0168: log = new PrintStream(new FileOutputStream(outputDir
0169: + "listing.txt"));
0170: src = new PrintStream(new FileOutputStream(outputDataDir
0171: + "Data.java"));
0172:
0173: src
0174: .print("/*\n"
0175: + " * \n"
0176: + " *\n"
0177: + " * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.\n"
0178: + " * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER\n"
0179: + " *\n */\n\npackage com.sun.satsa.pkiapplet;\n\n/**\n"
0180: + " * This class contains WIM PINs, private keys and file "
0181: + "system.\n"
0182: + " */\npublic class Data {\n\n /** Identifier for RSA generic "
0183: + "SE. */\n"
0184: + " static final byte WIM_GENERIC_RSA_ID = "
0185: + WIM_GENERIC_RSA_ID + ";\n\n");
0186:
0187: src
0188: .println(" /** The number of keys that can be generated. "
0189: + "*/\n static short freeKeySlots = "
0190: + freeKeySlots + ";");
0191: src
0192: .println(" /** Identifier of file for new key. */\n "
0193: + "static short newFileID = (short) "
0194: + newFileID + ";");
0195: src.println(" /** Identifier for new key. */\n static "
0196: + "byte newKeyID = " + newKeyID + ";");
0197:
0198: src.println(" /** The number of PINs that can be added. "
0199: + "*/\n static short freePINSlots = " + freePINSlots
0200: + ";");
0201: src.println(" /** Identifier of new PIN. */\n static "
0202: + "byte newPINID = (byte) " + newPINID + ";");
0203: src.println(" /** Reference of new PIN. */\n static "
0204: + "byte newPINRef = (byte) " + newPINRef + ";");
0205: src.println(" /** Identifier of PIN-G. */\n static "
0206: + "final byte PIN_G_ID = (byte) " + PINs[0].id + ";");
0207:
0208: ODF();
0209: TokenInfo();
0210: Unused();
0211: TrustedCerts();
0212: UserCerts();
0213: AODF();
0214: Keys();
0215:
0216: byte[] data = fs.getEncoded();
0217:
0218: src.println(" /** AODF data offset. */\n static final "
0219: + "short AODFOffset = (short) " + fs.getOffset("AODF")
0220: + ";");
0221: src.println(" /** PrKDF data offset. */\n static final "
0222: + "short PrKDFOffset = (short) "
0223: + fs.getOffset("PrKDF") + ";");
0224: src.println(" /** PuKDF data offset. */\n static final "
0225: + "short PuKDFOffset = (short) "
0226: + fs.getOffset("PuKDF") + ";");
0227:
0228: src.println();
0229:
0230: src.print(" /** Files. */");
0231: Utils.writeDataArray(src, "Files", data);
0232: src.println("}");
0233:
0234: log.close();
0235: src.close();
0236: }
0237:
0238: /**
0239: * Generates ODF file.
0240: */
0241: public void ODF() {
0242:
0243: /*
0244: PKCS15Objects ::= CHOICE {
0245: privateKeys [0] PKCS15PrivateKeys,
0246: publicKeys [1] PKCS15PublicKeys,
0247: trustedCertificates [5] PKCS15Certificates,
0248: usefulCertificates [6] PKCS15Certificates,
0249: authObjects [8] PKCS15AuthObjects,
0250: dataObjects [7] PKCS15DataObjects
0251: }
0252:
0253: dataObjects : objects {
0254: opaqueDO : {
0255: commonObjectAttributes {},
0256: classAttributes {
0257: applicationOID {wap-wsg-3}
0258: },
0259: typeAttributes direct : OCTET STRING:'3F00 5015'H
0260: }
0261: }
0262:
0263: */
0264:
0265: TLV odf = TLV.createSequence();
0266:
0267: TLV t;
0268: TLV current = odf.setChild(new TLV(TLV.NULL_TYPE));
0269:
0270: if (PrKDF != null) {
0271: t = new TLV(0xa0);
0272: t.setChild(TLV.createSequence()).setChild(
0273: TLV.createOctetString(Utils.shortToBytes(PrKDF)));
0274: current = current.setNext(t);
0275: }
0276:
0277: if (PuKDF != null) {
0278: t = new TLV(0xa1);
0279: t.setChild(TLV.createSequence()).setChild(
0280: TLV.createOctetString(Utils.shortToBytes(PuKDF)));
0281: current = current.setNext(t);
0282: }
0283:
0284: if (TrustedCDF != null) {
0285: t = new TLV(0xa5);
0286: t.setChild(TLV.createSequence()).setChild(
0287: TLV.createOctetString(Utils
0288: .shortToBytes(TrustedCDF)));
0289: current = current.setNext(t);
0290: }
0291:
0292: if (UsefulCDF != null) {
0293: t = new TLV(0xa6);
0294: t.setChild(TLV.createSequence()).setChild(
0295: TLV
0296: .createOctetString(Utils
0297: .shortToBytes(UsefulCDF)));
0298: current = current.setNext(t);
0299: }
0300:
0301: if (UserCDF != null) {
0302: t = new TLV(0xa4);
0303: t.setChild(TLV.createSequence()).setChild(
0304: TLV.createOctetString(Utils.shortToBytes(UserCDF)));
0305: current = current.setNext(t);
0306: }
0307:
0308: if (AODF != null) {
0309: t = new TLV(0xa8);
0310: t.setChild(TLV.createSequence()).setChild(
0311: TLV.createOctetString(Utils.shortToBytes(AODF)));
0312: current = current.setNext(t);
0313: }
0314:
0315: if (IncludeRoot) {
0316: t = new TLV(0xa7);
0317: current.setNext(t);
0318:
0319: t = t.setChild(new TLV(0xa0))
0320: .setChild(TLV.createSequence()).setChild(
0321: TLV.createSequence());
0322:
0323: t = t.setChild(TLV.createSequence());
0324: t = t.setNext(TLV.createSequence());
0325: t.setChild(TLV.createOID("2.23.43.1.3"));
0326: t.setNext(new TLV(0xa1)).setChild(
0327: TLV.createOctetString(Utils.shortToBytes(WIMDF)));
0328: }
0329:
0330: odf.child = odf.child.next;
0331:
0332: fs.addFile(ODF, FileSystem.READ, odf.getValue());
0333:
0334: log.println("********* ODF");
0335: Utils.writeHex(log, odf.getValue());
0336: log.println();
0337: odf.child.print(log);
0338: log.println("");
0339: }
0340:
0341: /**
0342: * Generates EF(TokenInfo) file.
0343: */
0344: public void TokenInfo() {
0345:
0346: /*
0347: PKCS15TokenInfo ::= SEQUENCE {
0348: version INTEGER {v1(0)} (v1,...),
0349: serialNumber OCTET STRING,
0350: manufacturerID PKCS15Label OPTIONAL,
0351: label [0] PKCS15Label OPTIONAL,
0352: tokenflags PKCS15TokenFlags,
0353: seInfo SEQUENCE OF PKCS15SecurityEnvironmentInfo
0354: OPTIONAL,
0355: recordInfo [1] PKCS15RecordInfo OPTIONAL,
0356: supportedAlgorithms [2] SEQUENCE OF PKCS15AlgorithmInfo
0357: OPTIONAL,
0358: ... -- For future extensions
0359: }
0360: */
0361:
0362: TLV t;
0363:
0364: TLV info = TLV.createSequence();
0365:
0366: t = info.setChild(TLV.createInteger(0));
0367:
0368: t = t.setNext(TLV.createOctetString(SerialNumber));
0369:
0370: t = t.setNext(TLV.createUTF8String(manufacturerID));
0371:
0372: t = t.setNext(TLV.createUTF8String(tokenLabel)).setTag(0x80);
0373:
0374: t = t.setNext(new TLV(TLV.BITSTRING_TYPE, new byte[] { 0 }));
0375:
0376: t = t.setNext(TLV.createSequence());
0377:
0378: t.setChild(TLV.createSequence()).setChild(
0379: TLV.createInteger(WIM_GENERIC_RSA_ID)).setNext(
0380: TLV.createOID("2.23.43.1.1.2"));
0381:
0382: t = t.setNext(new TLV(0xa2));
0383:
0384: t.setChild(TLV.createSequence()).setChild(
0385: TLV.createInteger(RSA_ALGORITHM_ID)).setNext(
0386: TLV.createInteger(0)).setNext(new TLV(TLV.NULL_TYPE))
0387: .setNext(
0388: new TLV(TLV.BITSTRING_TYPE, Utils
0389: .shortToBytes(0x0640)));
0390:
0391: fs.addFile(TokenInfo, FileSystem.READ, info.getDERData());
0392:
0393: log.println("********* TokenInfo");
0394: Utils.writeHex(log, info.getDERData());
0395: log.println();
0396: info.print(log);
0397: log.println();
0398: }
0399:
0400: /**
0401: * Generates UnusedSpace file.
0402: */
0403: public void Unused() {
0404:
0405: /*
0406: PKCS15UnusedSpace ::= SEQUENCE {
0407: path PKCS15Path,
0408: authId PKCS15Identifier OPTIONAL
0409: }
0410: */
0411:
0412: TLV m = TLV.createSequence();
0413: TLV v = m.setChild(TLV.createSequence());
0414:
0415: TLV t = v.setChild(Utils.createPath(DataFile, 0, FreeSpace));
0416: t.setNext(TLV
0417: .createOctetString(new byte[] { (byte) PINs[0].id }));
0418:
0419: byte[] data = new byte[t.getDERSize() * 19 - 4];
0420:
0421: v.setNext(new TLV(0, data));
0422:
0423: fs.addFile(UnusedSpace, FileSystem.UPDATE | FileSystem.EMPTY, m
0424: .getValue());
0425:
0426: log.println("********* UnusedSpace");
0427: Utils.writeHex(log, m.getValue());
0428: log.println();
0429: m.child.print(log);
0430: log.println();
0431: }
0432:
0433: /**
0434: * Generates file with trusted certificates.
0435: * @throws IOException if this exception occurs
0436: * @throws KeyStoreException if this exception occurs
0437: * @throws CertificateException if this exception occurs
0438: * @throws NoSuchAlgorithmException if this exception occurs
0439: */
0440: public void TrustedCerts() throws IOException, KeyStoreException,
0441: CertificateException, NoSuchAlgorithmException {
0442:
0443: byte[] data = CACertificate;
0444:
0445: fs.addFile(TrustedCerts, FileSystem.READ, data);
0446:
0447: log.println("********* TrustedCerts");
0448: Utils.writeHex(log, data);
0449: log.println();
0450: new TLV(data, 0).print(log);
0451: log.println();
0452:
0453: /*
0454: PKCS15CertificateObject {CertAttributes} ::= PKCS15Object {
0455: PKCS15CommonCertificateAttributes,
0456: NULL,
0457: CertAttributes}
0458:
0459: PKCS15Object {ClassAttributes, SubClassAttributes,
0460: TypeAttributes} ::=
0461: SEQUENCE {
0462: commonObjectAttributes PKCS15CommonObjectAttributes,
0463: classAttributes ClassAttributes,
0464: subClassAttributes [0] SubClassAttributes OPTIONAL,
0465: typeAttributes [1] TypeAttributes
0466: }
0467:
0468: PKCS15CommonObjectAttributes ::= SEQUENCE {
0469: + label PKCS15Label OPTIONAL,
0470: + flags PKCS15CommonObjectFlags OPTIONAL,
0471: authId PKCS15Identifier OPTIONAL,
0472: ... -- For future extensions
0473: }
0474:
0475: PKCS15CommonObjectFlags ::= BIT STRING {
0476: private(0),
0477: modifiable (1)
0478: }
0479:
0480: PKCS15CommonCertificateAttributes ::= SEQUENCE {
0481: + iD PKCS15Identifier,
0482: + authority BOOLEAN DEFAULT FALSE,
0483: + requestId PKCS15KeyIdentifier OPTIONAL,
0484: thumbprint [0] PKCS15OOBCertHash OPTIONAL,
0485: ... -- For future extensions
0486: }
0487:
0488: PKCS15X509CertificateAttributes ::= SEQUENCE {
0489: value PKCS15ObjectValue { PKCS15X509Certificate },
0490: subject Name OPTIONAL,
0491: issuer [0] Name OPTIONAL,
0492: serialNumber CertificateSerialNumber OPTIONAL,
0493: ... -- For future extensions
0494: }
0495: */
0496:
0497: // Parse CA certificate
0498: TLV CACertPointer = new TLV(data, 0);
0499:
0500: CACertPointer = CACertPointer.child.child;
0501: if (CACertPointer.type == TLV.VERSION_TYPE) {
0502: CACertPointer = CACertPointer.next;
0503: }
0504:
0505: // CACertPointer is at SerialNumber field
0506:
0507: byte[] modulus = new TLV(
0508: CACertPointer.next.next.next.next.next.child.next
0509: .getValue(), 1).child.getValue();
0510: byte[] id = Utils.getHash(modulus, 0, modulus.length);
0511:
0512: TLV commonAttrs = TLV.createSequence();
0513: commonAttrs.setChild(Utils.createLabel("CA CERTIFICATE"))
0514: .setNext(
0515: new TLV(TLV.BITSTRING_TYPE, Utils
0516: .shortToBytes(0)));
0517:
0518: TLV commonCertAttrs = TLV.createSequence();
0519: commonCertAttrs.setChild(TLV.createOctetString(id)).setNext(
0520: new TLV(TLV.BOOLEAN_TYPE, new byte[] { (byte) 255 }));
0521:
0522: TLV x509Attrs = new TLV(0xa1);
0523: x509Attrs.setChild(TLV.createSequence()).setChild(
0524: Utils.createPath(TrustedCerts, 0, data.length));
0525:
0526: TLV cdf = TLV.createSequence();
0527: cdf.setChild(commonAttrs).setNext(commonCertAttrs).setNext(
0528: x509Attrs);
0529:
0530: byte[] cdfData = cdf.getDERData();
0531:
0532: fs.addFile(TrustedCDF, FileSystem.READ, cdfData);
0533:
0534: log.println("********* TrustedCDF");
0535: Utils.writeHex(log, cdfData);
0536: log.println();
0537: new TLV(cdfData, 0).print(log);
0538: log.println();
0539: }
0540:
0541: /**
0542: * Generates user certificate files.
0543: */
0544: public void UserCerts() {
0545:
0546: byte[] UsefulCDFData = new TLV(0, new byte[CDFSpace])
0547: .getDERData();
0548:
0549: // There are two CDF files, one of them for 'useful', other
0550: // for user certificates. Both have the same size and content,
0551: // initially they are empty.
0552: fs.addFile(UsefulCDF, FileSystem.UPDATE | FileSystem.EMPTY,
0553: UsefulCDFData);
0554: fs.addFile(UserCDF, FileSystem.UPDATE | FileSystem.EMPTY,
0555: UsefulCDFData);
0556:
0557: log.println("********* UsefulCDF");
0558: Utils.writeHex(log, UsefulCDFData);
0559: log.println();
0560: new TLV(UsefulCDFData, 0).print(log);
0561: log.println();
0562:
0563: fs.addFile(DataFile, FileSystem.UPDATE | FileSystem.EMPTY,
0564: new byte[FreeSpace]);
0565: }
0566:
0567: /**
0568: * Generates AODF file.
0569: * @throws IOException if this exception occurs
0570: */
0571: public void AODF() throws IOException {
0572:
0573: /*
0574: PKCS15Authentication ::= CHOICE {
0575: pin PKCS15AuthenticationObject { PKCS15PinAttributes },
0576: ... -- For future extensions, e.g. biometric authentication
0577: -- objects
0578: }
0579:
0580: PKCS15AuthenticationObject {AuthObjectAttributes} ::=
0581: PKCS15Object {
0582: PKCS15CommonAuthenticationObjectAttributes,
0583: NULL,
0584: AuthObjectAttributes
0585: }
0586:
0587: PKCS15Object {ClassAttributes, SubClassAttributes,
0588: TypeAttributes} ::=
0589: SEQUENCE {
0590: commonObjectAttributes PKCS15CommonObjectAttributes,
0591: classAttributes ClassAttributes,
0592: subClassAttributes [0] SubClassAttributes OPTIONAL,
0593: typeAttributes [1] TypeAttributes
0594: }
0595:
0596: PKCS15CommonObjectAttributes ::= SEQUENCE {
0597: + label PKCS15Label OPTIONAL,
0598: + flags PKCS15CommonObjectFlags OPTIONAL,
0599: authId PKCS15Identifier OPTIONAL,
0600: ... -- For future extensions
0601: }
0602:
0603: PKCS15CommonAuthenticationObjectAttributes ::= SEQUENCE {
0604: + authId PKCS15Identifier,
0605: ... –- For future extensions
0606: }
0607:
0608: PKCS15PinAttributes ::= SEQUENCE {
0609: + pinFlags PKCS15PinFlags,
0610: + pinType PKCS15PinType,
0611: + minLength INTEGER (pkcs15-lb-minPinLength..
0612: pkcs15-ub-minPinLength),
0613: + storedLength INTEGER (pkcs15-lb-minPinLength..
0614: pkcs15-ub-storedPinLength),
0615: maxLength INTEGER OPTIONAL,
0616: + pinReference [0] PKCS15Reference OPTIONAL,
0617: + padChar OCTET STRING (SIZE(1)) OPTIONAL,
0618: lastPinChange GeneralizedTime OPTIONAL,
0619: + path PKCS15Path OPTIONAL,
0620: ... -- For future extensions
0621: }
0622:
0623: PKCS15PinFlags ::= BIT STRING {
0624: case-sensitive (0), 80
0625: local (1), 40
0626: change-disabled (2), 20 *
0627: unblock-disabled (3), 10
0628: initialized (4), 08 *
0629: needs-padding (5), 04 *
0630: unblockingPin (6), 02
0631: soPin (7), 01
0632: disable-allowed (8)
0633: }
0634:
0635: PKCS15PinType ::= ENUMERATED {bcd, ascii-numeric, utf8, ...
0636: -- bcd = one nibble contains one digit
0637: -- ascii-numeric = one byte contains one ASCII digit
0638: -- utf8 = password is stored in UTF8 encoding
0639: }
0640: */
0641:
0642: TLV[] t = new TLV[PINs.length + freePINSlots];
0643: for (int i = 0; i < PINs.length; i++) {
0644: t[i] = PINs[i].toTLV();
0645: }
0646:
0647: int PINRecordSize = 0;
0648: int PINLabelOffset = 0;
0649:
0650: for (int i = 0; i < freePINSlots; i++) {
0651: PIN pin = new PIN("", newPINID + i, newPINRef + i, PINDF,
0652: "1");
0653: t[PINs.length + i] = pin.toTLV();
0654: if (i == 0) {
0655: PINRecordSize = t[PINs.length + i].getDERSize();
0656: PINLabelOffset = t[PINs.length + i].copy().child.child.valueOffset;
0657: } else {
0658: if (PINRecordSize != t[PINs.length + i].getDERSize()) {
0659: System.out
0660: .println("Error - PIN placeholder size changed.");
0661: System.exit(1);
0662: }
0663: }
0664: t[PINs.length + i].type = 0;
0665: }
0666:
0667: for (int i = 0; i < t.length - 1; i++) {
0668: t[i].next = t[i + 1];
0669: }
0670:
0671: TLV aodf = TLV.createSequence();
0672: aodf.setChild(t[0]);
0673: byte[] data = aodf.getValue();
0674: fs.addFile(AODF, FileSystem.READ, data, "AODF");
0675:
0676: src.println(" /** PIN record size. */\n static final "
0677: + "short PINRecordSize = " + PINRecordSize + ";");
0678: src.println(" /** PIN label offset. */\n static final "
0679: + "short PINLabelOffset = " + PINLabelOffset + ";");
0680: src.println(" /** New PIN offset in AODF. */\n static "
0681: + "short newPINOffset = "
0682: + (data.length - freePINSlots * PINRecordSize) + ";");
0683:
0684: log.println("********* AODF");
0685: Utils.writeHex(log, data);
0686: log.println();
0687: aodf.child.print(log);
0688: log.println();
0689:
0690: ByteArrayOutputStream baos = new ByteArrayOutputStream();
0691: DataOutputStream out = new DataOutputStream(baos);
0692:
0693: out.writeByte(PINs.length);
0694: for (int i = 0; i < PINs.length; i++) {
0695: out.writeByte(PINs[i].ref);
0696: byte[] PINData = PINs[i].getData();
0697: out.writeByte(PINData.length);
0698: out.write(PINData);
0699: }
0700: src.print("\n /** PINs. */");
0701: Utils.writeDataArray(src, "PINs", baos.toByteArray());
0702: }
0703:
0704: /**
0705: * Generates all necessary data structures for keys.
0706: * @throws NoSuchAlgorithmException if this exception occurs
0707: * @throws IOException if this exception occurs
0708: */
0709: public void Keys() throws NoSuchAlgorithmException, IOException {
0710:
0711: /*
0712: PKCS15PrivateKeyObject {KeyAttributes} ::= PKCS15Object {
0713: PKCS15CommonKeyAttributes,
0714: PKCS15CommonPrivateKeyAttributes,
0715: KeyAttributes
0716: }
0717:
0718: PKCS15Object {ClassAttributes, SubClassAttributes,
0719: TypeAttributes} ::=
0720: SEQUENCE {
0721: commonObjectAttributes PKCS15CommonObjectAttributes,
0722: classAttributes ClassAttributes,
0723: subClassAttributes [0] SubClassAttributes OPTIONAL,
0724: typeAttributes [1] TypeAttributes
0725: }
0726:
0727: PKCS15CommonObjectAttributes ::= SEQUENCE {
0728: + label PKCS15Label OPTIONAL,
0729: + flags PKCS15CommonObjectFlags OPTIONAL,
0730: + authId PKCS15Identifier OPTIONAL,
0731: ... -- For future extensions
0732: }
0733:
0734: PKCS15CommonKeyAttributes ::= SEQUENCE {
0735: + iD PKCS15Identifier,
0736: + usage PKCS15KeyUsageFlags,
0737: native BOOLEAN DEFAULT TRUE,
0738: accessFlags PKCS15KeyAccessFlags OPTIONAL,
0739: + keyReference PKCS15Reference OPTIONAL,
0740: startDate GeneralizedTime OPTIONAL,
0741: endDate [0] GeneralizedTime OPTIONAL,
0742: ... -- For future extensions
0743: }
0744:
0745: PKCS15KeyUsageFlags ::= BIT STRING {
0746: encrypt (0), 80
0747: decrypt (1), 40
0748: sign (2), 20
0749: signRecover (3), 10
0750: wrap (4), 08
0751: unwrap (5), 04
0752: verify (6), 02
0753: verifyRecover (7), 01
0754: derive (8), 80
0755: nonRepudiation (9) 40
0756: }
0757:
0758: PKCS15PrivateRSAKeyAttributes ::= SEQUENCE {
0759: value PKCS15ObjectValue {PKCS15RSAPrivateKey},
0760: modulusLength INTEGER, -- modulus length in bits, e.g. 1024
0761: keyInfo PKCS15KeyInfo {PKCS15RSAParameters,
0762: PKCS15PublicKeyOperations} OPTIONAL,
0763: ... –- For future extensions
0764: }
0765:
0766: PKCS15KeyInfo {ParameterType, OperationsType} ::= CHOICE {
0767: reference PKCS15Reference,
0768: paramsAndOps SEQUENCE {
0769: parameters ParameterType,
0770: supportedOperations OperationsType OPTIONAL}
0771: }
0772:
0773: PKCS15PublicKeyObject {KeyAttributes} ::= PKCS15Object {
0774: PKCS15CommonKeyAttributes,
0775: PKCS15CommonPublicKeyAttributes,
0776: KeyAttributes}
0777:
0778: PKCS15CommonPublicKeyAttributes ::= SEQUENCE {
0779: subjectName Name OPTIONAL,
0780: ... -- For future extensions
0781: }
0782:
0783: PKCS15PublicRSAKeyAttributes ::= SEQUENCE {
0784: value PKCS15ObjectValue {PKCS15RSAPublicKey},
0785: modulusLength INTEGER, -- modulus length in bits, e.g. 1024
0786: keyInfo PKCS15KeyInfo {PKCS15RSAParameters,
0787: PKCS15PublicKeyOperations} OPTIONAL,
0788: ... –- For future extensions
0789: }
0790:
0791: PKCS15RSAPublicKey ::= SEQUENCE {
0792: modulus INTEGER, -- n
0793: publicExponent INTEGER -- e
0794: }
0795:
0796: */
0797:
0798: TLV[] PrK = new TLV[Keys.length + freeKeySlots];
0799: TLV[] PuK = new TLV[Keys.length + freeKeySlots];
0800:
0801: ByteArrayOutputStream baos = new ByteArrayOutputStream();
0802: DataOutputStream out = new DataOutputStream(baos);
0803:
0804: out.writeByte(Keys.length);
0805:
0806: for (int i = 0; i < Keys.length; i++) {
0807:
0808: Keys[i].init();
0809:
0810: RSAPrivateKey priv = Keys[i].priv;
0811: RSAPublicKey pub = Keys[i].pub;
0812:
0813: int offset;
0814: int len;
0815:
0816: out.writeByte(Keys[i].id);
0817: out.writeByte(Keys[i].pinIndex);
0818: out.writeByte(Keys[i].nonRepudiation ? 0 : 1);
0819:
0820: byte[] x = priv.getModulus().toByteArray();
0821: offset = 0;
0822: len = x.length;
0823: while (x[offset] == 0) {
0824: offset++;
0825: len--;
0826: }
0827: short keyLen = (short) (len * 8);
0828: out.writeShort(keyLen);
0829: out.writeShort(len);
0830: out.write(x, offset, len);
0831:
0832: x = priv.getPrivateExponent().toByteArray();
0833: offset = 0;
0834: len = x.length;
0835: while (x[offset] == 0) {
0836: offset++;
0837: len--;
0838: }
0839: out.writeShort(len);
0840: out.write(x, offset, len);
0841:
0842: PrK[i] = Keys[i].getPrivate(RSA_ALGORITHM_ID);
0843: PuK[i] = Keys[i].getPublic();
0844:
0845: byte[] keyData = new TLV(
0846: new TLV(pub.getEncoded(), 0).child.next.getValue(),
0847: 1).getDERData();
0848:
0849: fs.addFile(Keys[i].PublicPath, FileSystem.READ, keyData);
0850: fs.addFile(Keys[i].PrivatePath, FileSystem.PrK,
0851: new byte[] { (byte) Keys[i].id });
0852: }
0853:
0854: int privKeyRecordSize = 0;
0855: int privPINIDOffset = 0;
0856: int privHashOffset = 0;
0857: int privUsageOffset = 0;
0858: int privKeyLengthOffset = 0;
0859:
0860: int pubKeyRecordSize = 0;
0861: int pubHashOffset = 0;
0862: int pubKeyLengthOffset = 0;
0863:
0864: short FileId = newFileID;
0865: for (int i = 0; i < freeKeySlots; i++) {
0866:
0867: Key k = new Key("New key " + (i + 1), 1024, 0, true,
0868: newKeyID + i, new short[] { FileId },
0869: new short[] { (short) (FileId + 1) }, PINs);
0870: FileId += 2;
0871:
0872: TLV prk = k.getPrivate(RSA_ALGORITHM_ID);
0873:
0874: TLV puk = k.getPublic();
0875:
0876: if (i == 0) {
0877: TLV t = prk.copy();
0878: privKeyRecordSize = t.getDERSize();
0879: privPINIDOffset = t.child.child.next.next.valueOffset;
0880: privHashOffset = t.child.next.child.valueOffset;
0881: privUsageOffset = t.child.next.child.next.valueOffset;
0882: privKeyLengthOffset = t.child.next.next.child.child.next.valueOffset;
0883:
0884: t = puk.copy();
0885: pubKeyRecordSize = t.getDERSize();
0886: pubHashOffset = t.child.next.child.valueOffset;
0887: pubKeyLengthOffset = t.child.next.next.child.child.next.valueOffset;
0888: }
0889:
0890: prk.type = 0;
0891: PrK[Keys.length + i] = prk;
0892:
0893: puk.type = 0;
0894: PuK[Keys.length + i] = puk;
0895:
0896: fs.addFile(k.PublicPath, FileSystem.READ, new byte[0]);
0897: fs.addFile(k.PrivatePath, FileSystem.PrK,
0898: new byte[] { (byte) k.id });
0899: }
0900:
0901: for (int i = 1; i < PrK.length; i++) {
0902: PrK[i - 1].setNext(PrK[i]);
0903: PuK[i - 1].setNext(PuK[i]);
0904: }
0905:
0906: byte[] data;
0907:
0908: TLV prkdf = TLV.createSequence();
0909: prkdf.setChild(PrK[0]);
0910: data = prkdf.getValue();
0911: fs.addFile(PrKDF, FileSystem.READ, data, "PrKDF");
0912:
0913: src
0914: .println(" /** Offset from start of the first empty entry "
0915: + "in PrKDF. */\n static short newPrivKeyOffset = "
0916: + (data.length - freeKeySlots
0917: * privKeyRecordSize) + ";");
0918: src.println(" /** The size of record in PrKDF. */\n "
0919: + "static final short privKeyRecordSize = "
0920: + privKeyRecordSize + ";");
0921: src
0922: .println(" /** Offset of PIN identifier data in PrKDF "
0923: + "record. */\n static final short privPINIDOffset = "
0924: + privPINIDOffset + ";");
0925: src
0926: .println(" /** Offset of key identifier data in PrKDF "
0927: + "record. */\n static final short privHashOffset = "
0928: + privHashOffset + ";");
0929: src
0930: .println(" /** Offset of usage field data in PrKDF "
0931: + "record. */\n static final short privUsageOffset = "
0932: + privUsageOffset + ";");
0933: src.println(" /** Offset of key length in PrKDF record. "
0934: + "*/\n static final short privKeyLengthOffset = "
0935: + privKeyLengthOffset + ";");
0936: src.println();
0937:
0938: log.println("********* PrKDF");
0939: Utils.writeHex(log, data);
0940: log.println();
0941: prkdf.child.print(log);
0942: log.println();
0943:
0944: TLV pukdf = TLV.createSequence();
0945: pukdf.setChild(PuK[0]);
0946: data = pukdf.getValue();
0947: fs.addFile(PuKDF, FileSystem.READ, data, "PuKDF");
0948:
0949: src
0950: .println(" /** Offset from start of the first empty entry "
0951: + "in PrKDF. */\n static short newPubKeyOffset = "
0952: + (data.length - freeKeySlots
0953: * pubKeyRecordSize) + ";");
0954: src
0955: .println(" /** The size of record in PuKDF. */\n static"
0956: + " final short pubKeyRecordSize = "
0957: + pubKeyRecordSize + ";");
0958: src.println(" /** Offset of key identifier data in PuKDF "
0959: + "record. */\n static final short pubHashOffset = "
0960: + pubHashOffset + ";");
0961: src
0962: .println(" /** Offset of key length in PuKDF record. */\n"
0963: + " static final short pubKeyLengthOffset = "
0964: + pubKeyLengthOffset + ";");
0965: src.println();
0966:
0967: log.println("********* PuKDF");
0968: Utils.writeHex(log, data);
0969: log.println();
0970: pukdf.child.print(log);
0971: log.println();
0972: src.print(" /** Private keys. */");
0973:
0974: Utils.writeDataArray(src, "PrivateKeys", baos.toByteArray());
0975: }
0976:
0977: /**
0978: * CA certificate (MIDP 2.0 RI keystore, alias dummyca).
0979: */
0980: static byte[] CACertificate = { 48, -126, 3, 61, 48, -126, 2, 37,
0981: 2, 4, 61, 62, -50, -118, 48, 13, 6, 9, 42, -122, 72, -122,
0982: -9, 13, 1, 1, 4, 5, 0, 48, 99, 49, 16, 48, 14, 6, 3, 85, 4,
0983: 3, 19, 7, 116, 104, 101, 104, 111, 115, 116, 49, 12, 48,
0984: 10, 6, 3, 85, 4, 11, 19, 3, 74, 67, 84, 49, 17, 48, 15, 6,
0985: 3, 85, 4, 10, 19, 8, 100, 117, 109, 109, 121, 32, 67, 65,
0986: 49, 20, 48, 18, 6, 3, 85, 4, 7, 19, 11, 83, 97, 110, 116,
0987: 97, 32, 67, 108, 97, 114, 97, 49, 11, 48, 9, 6, 3, 85, 4,
0988: 8, 19, 2, 67, 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85,
0989: 83, 48, 30, 23, 13, 48, 50, 48, 55, 50, 52, 49, 53, 53, 56,
0990: 48, 50, 90, 23, 13, 49, 50, 48, 55, 50, 49, 49, 53, 53, 56,
0991: 48, 50, 90, 48, 99, 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7,
0992: 116, 104, 101, 104, 111, 115, 116, 49, 12, 48, 10, 6, 3,
0993: 85, 4, 11, 19, 3, 74, 67, 84, 49, 17, 48, 15, 6, 3, 85, 4,
0994: 10, 19, 8, 100, 117, 109, 109, 121, 32, 67, 65, 49, 20, 48,
0995: 18, 6, 3, 85, 4, 7, 19, 11, 83, 97, 110, 116, 97, 32, 67,
0996: 108, 97, 114, 97, 49, 11, 48, 9, 6, 3, 85, 4, 8, 19, 2, 67,
0997: 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, -126,
0998: 1, 34, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1,
0999: 5, 0, 3, -126, 1, 15, 0, 48, -126, 1, 10, 2, -126, 1, 1, 0,
1000: -32, -30, -97, -62, 117, 76, 16, 83, -69, 72, -53, 84, 35,
1001: -28, -111, 23, -94, -20, 89, -97, 111, 87, 127, -101, 106,
1002: 31, -109, 94, 105, -15, -44, 86, -71, 101, -98, 20, 39,
1003: -72, -79, -75, -99, -22, -42, -17, -62, 3, 78, -101, 40,
1004: 30, 27, 8, 26, 5, 77, -9, -75, -25, -110, -51, 58, 89, -40,
1005: -74, -74, 32, -13, -56, 43, -8, 30, 56, -39, -76, -12, 35,
1006: -64, 3, -55, 2, 113, 122, -84, 64, 37, 103, -2, -62, 106,
1007: -46, 59, 37, 20, 41, -11, -103, -116, -17, 81, 37, -92, 55,
1008: -38, -79, 101, -74, 73, -9, -99, 30, 90, 52, 14, 23, -14,
1009: 80, -110, -123, -69, 28, 108, -82, 106, -28, -32, 41, -27,
1010: -3, -51, 16, 26, -85, 7, -57, -92, 50, -41, -67, 112, 36,
1011: -58, 83, 115, 51, -107, 98, -124, -103, -75, 59, -125,
1012: -112, 14, -68, -111, 88, -16, -107, -106, 21, 15, -19, 104,
1013: -70, 70, 5, 34, -103, 85, 30, 57, -66, -11, 52, -51, -71,
1014: 67, -34, 28, -21, -16, 121, -18, -99, 96, -91, 80, 120,
1015: -32, 56, -7, 40, -106, -81, 7, -103, -42, -50, 124, -68,
1016: 59, 4, -3, 13, 9, 112, -79, -83, -49, -91, 70, -56, 65, 92,
1017: 7, -40, -101, -53, -41, -53, 92, -60, -106, 14, 65, -124,
1018: 59, 40, -111, 7, -59, -36, -98, 113, 120, 16, 65, -115, 5,
1019: 61, 54, 63, 120, -95, -100, -77, 55, -127, 42, -91, -48,
1020: 37, -83, -2, 113, 7, 2, 3, 1, 0, 1, 48, 13, 6, 9, 42, -122,
1021: 72, -122, -9, 13, 1, 1, 4, 5, 0, 3, -126, 1, 1, 0, 19,
1022: -115, 51, 67, 74, -32, -104, -44, -31, 73, -70, -60, -128,
1023: -106, -88, -95, -33, -2, -100, -48, -98, -43, -110, 43, 4,
1024: 77, -63, -11, 119, -60, 121, 91, -42, -28, -61, -116, 104,
1025: 58, 120, -88, -28, 12, 64, -82, -94, 36, 27, -38, -4, 108,
1026: -20, 96, -94, 96, 82, 40, -114, -80, -65, 31, -96, -53,
1027: -90, -55, 37, 102, -79, -12, 125, 91, 102, -8, 10, -95, 26,
1028: -82, -11, 83, -31, 102, -96, -114, -40, 0, 99, -9, -34,
1029: 112, 21, 54, 105, -92, 121, 101, 5, 90, 76, -10, -119, 117,
1030: -87, 65, -54, 17, -6, 62, -36, -60, 78, -78, 45, 9, 27,
1031: -40, -78, -91, 74, -113, 80, -118, -21, 71, 88, 24, 39,
1032: -74, -40, 86, -23, -79, 68, -3, 99, 36, 122, 26, -72, 91,
1033: 55, 113, -39, -29, 84, -79, 85, 100, -93, 118, 26, 46, -86,
1034: -35, -99, 100, 113, -97, -65, -94, 47, 115, -43, 81, 16,
1035: -23, -52, 52, 88, -54, -120, 123, -25, 33, 114, 81, 24, 67,
1036: 113, 41, 105, -126, 100, 75, -90, -57, -69, 75, 96, 111,
1037: 88, 113, -18, -94, 63, 62, -105, 5, 57, -22, -34, -81, 57,
1038: -84, -121, -39, 65, 122, 100, -75, -22, -69, -92, -61, 14,
1039: -36, 126, 86, -41, 115, -25, 64, 44, 31, -124, -7, -12,
1040: -117, 83, 109, -125, -86, -46, 79, 114, -37, 107, 96, -14,
1041: -83, 101, 53, 120, 27, 52, 46, -84, -96, -21, 93, 44, 2,
1042: 33, 21, 89, -93, -128, -31 };
1043: }
|