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 Explore an MRTD using Basic Access Control
 25  */
 26 
 27 
 28 var mrzlist = [	"L898902C<3UTO6908061F9406236ZE184226B<<<<<14", 
 29 		"WG30004036UTO6007078M0511014<<<<<<<<<<<<<<06",
 30 		];
 31 
 32 var mrz2 = mrzlist[0];
 33 var bacforced = false;
 34 
 35 load("tools.js");
 36 load("tools/OutlineCore.js");
 37 
 38 
 39 
 40 //
 41 // CTOR - Outline node for DFs
 42 //
 43 function OutlineLDS(card, id, name, profile) {
 44         this.card = card;
 45         this.id = id;
 46 
 47         // Create OutlineNode object and register in OutlineDF object
 48         var view = new OutlineNode(name, true);
 49         view.setUserObject(this);
 50         view.setToolTip("Click right mouse button to select MRZ for BAC");
 51         view.setContextMenu(mrzlist);
 52         this.view = view;
 53         
 54         this.profile = profile;
 55 }
 56 
 57 
 58 
 59 //
 60 // Event handler for expand notifications
 61 //
 62 OutlineLDS.prototype.expandListener = function() {
 63 
 64         if (this.expanded)
 65                 return;
 66 
 67         var view = this.view;
 68         var eflist = this.profile.EF;
 69         
 70         try	{
 71         	var df = new CardFile(this.card, this.id);
 72 		this.df = df;
 73 				
 74 		var fcp = df.getFCPBytes();
 75 		if (fcp && (fcp.length > 1)) {
 76 			var fcpmodel = new OutlineFCP(fcp);
 77 			view.insert(fcpmodel.view);	
 78 		}
 79 		
 80 		// Try reading EF_COM to figure out if BAC is needed
 81 		this.card.sendApdu(0x00, 0xB0, 0x9E, 0x00, 0x01);
 82 
 83 		var secureChannel = null;
 84 		
 85 		if (bacforced || (this.card.SW != 0x9000)) {
 86 			// Calculate kenc and kmac for mutual authentication from the MRZ data
 87 			print("Trying BAC with MRZ2=" + mrz2);
 88 	
 89 			var crypto = new Crypto();
 90 			var kenc = calculateBACKey(crypto, mrz2, 1);
 91 			var kmac = calculateBACKey(crypto, mrz2, 2);
 92 
 93 			// Dummy to load crypto libraries (Saves some time later)
 94 			crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("0000000000000000", HEX), new ByteString("0000000000000000", HEX));
 95 
 96 			secureChannel = openSecureChannel(this.card, crypto, kenc, kmac);
 97 		}
 98 				
 99 		for (var i = 0; i < eflist.length; i++) {
100 		        var ef = new OutlineSMEF(this.df, eflist[i].name, eflist[i], secureChannel);
101 		        view.insert(ef.view);
102 		}
103 	}
104 	catch(e) {
105 		print(e);
106 	}
107         
108         this.expanded = true;
109 }
110 
111 
112 
113 //
114 // Event handler for expand notifications
115 //
116 OutlineLDS.prototype.collapseListener = function() {
117         var view = this.view;
118         while(view.childs.length > 0) {
119         	view.remove(view.childs[0]);
120         }
121         this.expanded = false;
122 }
123 
124 
125 //
126 // Event handler for selection from context menu
127 //
128 OutlineLDS.prototype.actionListener = function(node, action) {
129 	if (this.expanded) {
130 		print("Please collapse and expand LDS to execute BAC again");
131 	}
132 	
133 	mrz2 = action;
134 	print("Selected MRZ2 = " + mrz2);
135 	bacforced = true;
136 }
137 
138 
139 
140 //
141 // CTOR - Outline node for EFs
142 //
143 function OutlineSMEF(df, name, profile, secureChannel) {
144         this.df = df;
145 	this.secureChannel = secureChannel;
146 	
147         // Create OutlineNode object and register in OutlineEF object
148         var view = new OutlineNode(name, true);
149         view.setIcon("document");
150         view.setUserObject(this);
151         this.view = view;
152         
153         this.profile = profile;
154 }
155 
156 
157 
158 //
159 // Event handler for expand notification
160 //
161 OutlineSMEF.prototype.expandListener = function() {
162         if (this.expanded)
163                 return;
164 
165         var view = this.view;
166         var efdesc = this.profile;
167 
168 	try	{        
169 	        var ef = new CardFile(this.df, ":" + efdesc.fid);
170 	        if (this.secureChannel) {	
171 			// Set secure channel as credential for read access
172 			ef.setCredential(CardFile.READ, Card.ALL, this.secureChannel);
173 		}
174 	}
175 	catch(e) {
176 		print(e);
177 		return;
178 	}
179 		
180 	var isTransparent = true;
181 	
182 	if (efdesc.fid.length > 2) {  // Select by FID or SFI
183 		var fcp = ef.getFCPBytes();
184 		if (fcp && (fcp.length > 1)) {
185 			var fcpmodel = new OutlineFCP(fcp);
186 			view.insert(fcpmodel.view);
187 			isTransparent = ef.isTransparent();
188 		} else {
189 			isTransparent = (efdesc.type == "T");
190 		}
191 	}
192 		
193         if (isTransparent) {
194         	if (fcp) {
195 	        	var filesize = ef.getLength();
196 	       	
197 	        	if (filesize > 1024)
198 	        		print("Please wait, reading " + filesize + " bytes...");
199 	        } else {
200         		print("Please wait, reading card...");
201 	        }
202         		
203 		try	{
204 	                var bs = ef.readBinary();
205 	        }
206 	        catch(e) {
207 	       		print(e);
208 	       		this.expanded = true;
209 	       		return;
210 		}
211 		print("Reading done...");
212 		
213 		var bindata = new DataOutline(bs, efdesc.format);
214 		view.insert(bindata.view);
215 		
216         } else {
217                 for (var rec = 1; rec < 255; rec++) {
218                         try     {
219                                 ef.readRecord(rec);
220                                 var record = new OutlineRecord(ef, rec, efdesc);
221                                 view.insert(record.view);
222                         }
223                         catch(e) {
224                               	if ((e instanceof GPError) && (e.reason == 0x6A83))
225                 			break;
226                                 print(e);
227                                 break;
228                         }
229                 }
230         }
231         
232         this.expanded = true;
233 }
234 
235 
236 
237 
238 function MRTDOutlineCard() {
239 
240         // Create card object
241         var card = new Card(_scsh3.reader);
242         this.atr = card.reset(Card.RESET_COLD);
243 
244         this.card = card;
245 
246         // Create OutlineNode object and register in MRTD object
247         this.view = new OutlineNode("ICAO MRTD");
248         
249         // Register MRTD object in OutlineNode object
250         this.view.model = this;
251         
252         // Set a wrapper to receive expand() notifications from the OutlineNode object
253         this.view.expand = function() { var model = this.model; model.expand() };
254 }
255 
256 
257 
258 //
259 // Expand clicked on node
260 //
261 function MRTDOutlineCard_expand() {
262         if (this.expanded)
263                 return;
264                 
265         var view = this.view;
266 
267 		//
268 		// Display ATR
269 		//
270 		var atrnode = new OutlineATR(this.atr);
271 		view.insert(atrnode.view);
272 
273         //
274         // Explore files in MF
275         //
276         
277         var struct_lds = GPXML.parse("lds.xml");
278         this.lds = new OutlineLDS(this.card, "#A0000002471001", "LDS", struct_lds);
279         
280         view.insert(this.lds.view);
281 
282         this.expanded = true;
283 }
284 
285 
286 MRTDOutlineCard.prototype.expand = MRTDOutlineCard_expand;
287 
288 
289 
290 //
291 // Outline root node erzeugen
292 // 
293 var mrtd = new MRTDOutlineCard();
294 
295 mrtd.view.show();
296