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