1 /**
  2  *  ---------
  3  * |.##> <##.|  Open Smart Card Development Platform (www.openscdp.org)
  4  * |#       #|  
  5  * |#       #|  Copyright (c) 1999-2009 CardContact Software & System Consulting
  6  * |'##> <##'|  Andreas Schwier, 32429 Minden, Germany (www.cardcontact.de)
  7  *  --------- 
  8  *
  9  *  This file is part of OpenSCDP.
 10  *
 11  *  OpenSCDP is free software; you can redistribute it and/or modify
 12  *  it under the terms of the GNU General Public License version 2 as
 13  *  published by the Free Software Foundation.
 14  *
 15  *  OpenSCDP is distributed in the hope that it will be useful,
 16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18  *  GNU General Public License for more details.
 19  *
 20  *  You should have received a copy of the GNU General Public License
 21  *  along with OpenSCDP; if not, write to the Free Software
 22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 23  *
 24  * @fileoverview A simple card simulation
 25  */
 26 
 27 load("filesystem.js");
 28 load("commandinterpreter.js");
 29 load("securechannel.js");
 30 
 31 
 32 /**
 33  * Create a card simulation object
 34  *
 35  * @class Class implementing a simple ISO 7816-4 card simulation
 36  * @constructor
 37  */
 38 function SimpleCardSimulator() {
 39 	var aid = new ByteString("A0000000010101", HEX);
 40 
 41 	var efdir_example = new ASN1(0x61,
 42 								new ASN1(0x4F, aid),
 43 								new ASN1(0x50, new ByteString("Example Application", ASCII))
 44 							);
 45 
 46 	var efdir = [ efdir_example.getBytes() ];
 47 
 48 	this.mf = new DF(FCP.newDF("3F00", null),
 49 						new LinearEF(FCP.newLinearEF("2F00", 30, FCP.LINEARVARIABLE, 20, 10), efdir),
 50 						new TransparentEF(FCP.newTransparentEF("2F02", 1, 100), new ByteString("5A0A00010203040506070809", HEX)),
 51 						new TransparentEF(FCP.newTransparentEF("EF01", 2, 100), new ByteString("4041424344", HEX)),
 52 						new DF(FCP.newDF("DF01", this.aid),
 53 							new TransparentEF(FCP.newTransparentEF("EF01", 0, 100)),
 54 							new TransparentEF(FCP.newTransparentEF("EF02", 0, 100))
 55 						)
 56 					);
 57 
 58 	print(this.mf.dump(""));
 59 	
 60 	this.initialize();
 61 }
 62 
 63 
 64 
 65 /**
 66  * Initialize card runtime
 67  */
 68 SimpleCardSimulator.prototype.initialize = function() {
 69 	this.fileSelector = new FileSelector(this.mf);
 70 	this.commandInterpreter = new CommandInterpreter(this.fileSelector);
 71 	
 72 	var sm = new SecureChannel(new Crypto());
 73 	
 74 	sm.setSendSequenceCounterPolicy(IsoSecureChannel.SSC_SYNC_ENC_POLICY);
 75 
 76 	var k = new Key();
 77 	k.setComponent(Key.AES, new ByteString("7CA110454A1A6E570131D9619DC1376E4A1A6E570131D961", HEX));
 78 	sm.setMacKey(k);
 79 
 80 	var k = new Key();
 81 	k.setComponent(Key.AES, new ByteString("0131D9619DC1376E7CA110454A1A6E579DC1376E7CA11045", HEX));
 82 	sm.setEncKey(k);
 83 	
 84 	sm.setMACSendSequenceCounter(new ByteString("00000000000000000000000000000000", HEX));
 85 	
 86 	this.commandInterpreter.setSecureChannel(sm);
 87 }
 88 
 89 
 90 
 91 /**
 92  * Process an inbound APDU
 93  *
 94  * @param {ByteString} capdu the command APDU
 95  * @type ByteString
 96  * @return the response APDU
 97  */ 
 98 SimpleCardSimulator.prototype.processAPDU = function(capdu) {
 99 	print("Command APDU : " + capdu);
100 
101 	var apdu;
102 	
103 	try	{
104 		apdu = new APDU(capdu);
105 	}
106 	catch(e) {
107 		GPSystem.trace(e);
108 		var sw = APDU.SW_GENERALERROR;
109 		if (e instanceof GPError) {
110 			sw = e.reason;
111 		}
112 		var bb = new ByteBuffer();
113 		bb.append(sw >> 8);
114 		bb.append(sw & 0xFF);
115 		return bb.toByteString();
116 	}
117 
118 	this.commandInterpreter.processAPDU(apdu);
119 	
120 	var rapdu = apdu.getResponseAPDU();
121 	print("Response APDU: " + rapdu);
122 	return rapdu;
123 }
124 
125 
126 
127 /**
128  * Respond to reset request
129  *
130  * @param {Number} type reset type (One of Card.RESET_COLD or Card.RESET.WARM)
131  * @type ByteString
132  * @return answer to reset
133  */
134 SimpleCardSimulator.prototype.reset = function(type) {
135 	print("Reset type: " + type);
136 
137 	this.initialize();
138 
139 	var atr = new ByteString("3B600000", HEX);
140 	return atr;
141 }
142 
143 
144 
145 /**
146  * Create new simulation and register with existing or newly created adapter singleton.
147  *
148  */
149 SimpleCardSimulator.newInstance = function() {
150 	var sim = new SimpleCardSimulator();
151 
152 	if (typeof(CARDSIM) == "undefined") {
153 		var adapter = new CardSimulationAdapter("JCOPSimulation", "8050");
154 		adapter.setSimulationObject(sim);
155 		adapter.start();
156 		CARDSIM = adapter;
157 		print("Simulation running...");
158 	} else {
159 		CARDSIM.setSimulationObject(sim);
160 		print("Simulation replaced...");
161 	}
162 }
163 
164 
165 
166 SimpleCardSimulator.newInstance();
167