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 The class EMVView displays data stored on emv cards. 25 */ 26 27 28 29 /** 30 * EMVView class constructor 31 * 32 * @class This class implements a viewer for data stored on emv cards 33 * @constructor 34 * @requires EMV 35 * @param {object} emv an instance of the EMV class 36 */ 37 function EMVView(emv) { 38 this.emv = emv; 39 } 40 41 42 43 /** 44 * Display the data elements into a human readable form 45 */ 46 EMVView.prototype.displayDataElements = function(){ 47 print("<----------------------------Display Data Elements-----------------------------"); 48 print(); 49 var cardDE = this.emv.getCardDataElements(); 50 51 for (var i = 0; i < cardDE.length; i++) { 52 if (cardDE[i] != undefined){ 53 var tag = i; 54 var value= cardDE[i]; 55 this.decodeDataElement(tag, value); 56 } 57 } 58 print("------------------------------------------------------------------------------>\n"); 59 } 60 61 62 63 /** 64 * Decodes a template containing TLV data object into a human readable form 65 * 66 * @param {Number} tag containing the tag name of TLV data objects 67 * @param {ASN1} value the template containing TLV data objects 68 */ 69 EMVView.prototype.decodeDataElement = function(tag, value) { 70 switch (tag) { 71 case 0x50: 72 print("Application Label: " + value.toString(HEX) + " - " + value.toString(ASCII)); 73 print("\n"); 74 break; 75 case 0x57: 76 var str = value.toString(HEX); 77 if (str.charAt(str.length-1) == 'F') { 78 str = str.substr(0, str.length-1); 79 } 80 81 var separatorOfs = str.indexOf("D"); 82 var pan = str.substr(0, separatorOfs); 83 var exDate = str.substr(separatorOfs+1, 4); 84 var serCode = str.substr(separatorOfs+5, 3); 85 var disData = str.substr(separatorOfs+8); 86 87 print("Track 2 Equivalent Data (Magnetic Strip): "); 88 print(" Primary Account Number: " + pan); 89 print(" Expiration Date (YYMM): " + exDate); 90 print(" Service Code: " + serCode); 91 print(" Discretionary Data: " + disData); 92 print("\n"); 93 break; 94 case 0x82: 95 print("Application Interchange Profile: " + value.toString(HEX)) 96 this.decodeAIP(value); 97 print(); 98 break; 99 case 0x8C: 100 print("Card Risk Management Data Object List 1 (CDOL1): " + value.toString(HEX)); 101 this.decodeDataObjectList(value); 102 print(); 103 break; 104 case 0x8D: 105 print("Card Risk Management Data Object List 2 (CDOL2): " + value.toString(HEX)); 106 this.decodeDataObjectList(value); 107 print(); 108 break; 109 case 0x8E: 110 print("Cardholder Verification Method (CVM) List: " + value.toString(HEX)); 111 this.decodeCVM(value); 112 print(); 113 break; 114 case 0x94: 115 print("Application File Locator: " + value.toString(HEX)); 116 this.decodeAFL(value); 117 print(); 118 break; 119 case 0x5F20: 120 print("Cardholder Name : " + value.toString(ASCII)); 121 break; 122 case 0x5F2D: 123 print("Language Preference : " + value.toString(ASCII)); 124 break; 125 case 0x5F30: 126 var string2 = value.toString(HEX); 127 print("Service Code: " + string2.substr(1)); 128 print(); 129 break; 130 case 0x9F07: 131 print("Application Usage Control: " + value.toString(HEX)); 132 this.decodeAUC(value); 133 print(); 134 break; 135 case 0x9F0D: 136 print("Issuer Action Code - Default: " + value.toString(HEX)); 137 this.decodeActionCode(value); 138 print(); 139 break; 140 case 0x9F0E: 141 print("Issuer Action Code - Denial: " + value.toString(HEX)); 142 this.decodeActionCode(value); 143 print(); 144 break; 145 case 0x9F0F: 146 print("Issuer Action Code - Online: " + value.toString(HEX)); 147 this.decodeActionCode(value); 148 print(); 149 break; 150 case 0x9F38: 151 print("Processing Options Data Object List (PDOL): " + value.toString(HEX)); 152 this.decodeDataObjectList(value); 153 print(); 154 break; 155 case 0x9F49: 156 print("Dynamic Data Authentication Data Object List (DDOL): " + value.toString(HEX)); 157 this.decodeDataObjectList(value); 158 print(); 159 break; 160 default: 161 if(typeof(EMVView.DE[tag]) == "undefined"){ 162 print("Unknown Class: " + tag.toString(HEX)); 163 print() 164 } 165 else{ 166 print(EMVView.DE[tag] + value.toString(HEX)); 167 print(); 168 } 169 break; 170 } 171 } 172 173 174 175 /** 176 * Decode a data object list into a human readable form 177 * 178 * <p>A data object list is a concatenation of data object identifiers, which each consist of 179 * a tag and a length field.</p> 180 * 181 * @param {ByteString} dol the data object list 182 */ 183 EMVView.prototype.decodeDataObjectList = function(dol) { 184 while (dol.length > 0) { 185 var b = dol.byteAt(0); 186 if ((b & 0x1F) == 0x1F){ 187 var tag = dol.left(2).toUnsigned(); 188 var length = dol.byteAt(2); 189 var dol = dol.bytes(3); //Remove Tag and Length Byte 190 } 191 else { 192 var tag = dol.left(1).toUnsigned(); 193 var length = dol.byteAt(1); 194 var dol = dol.bytes(2); //Remove Tag and Length Byte 195 } 196 print(" " + tag.toString(HEX) + " - " + length + " - " + DOL[tag]); 197 } 198 } 199 200 201 202 /** 203 * Decode an action code into a human readable form 204 * 205 * @param {ByteString} actionCode the Action Code 206 */ 207 EMVView.prototype.decodeActionCode = function(actionCode) { 208 209 for (var j = 0; j < 5; j++) { 210 var b = actionCode.byteAt(j); 211 print(" Byte " + (j + 1) + ": "); 212 213 for (var i = 0; i < 8; i++) { 214 var bit = 0x80 >> i; 215 if ((b & bit) == bit) { 216 print(" " + TVR[j][i]); 217 } 218 } 219 } 220 } 221 222 223 224 /** 225 * Decode an application interchange profile into a human readable form 226 * 227 * @param {ByteString} aip the Application Interchange Profile 228 */ 229 EMVView.prototype.decodeAIP = function(aip) { 230 for (var j = 0; j < 2; j++) { 231 var b = aip.byteAt(j); 232 print(" Byte " + (j + 1) + ": "); 233 234 for (var i = 0; i < 8; i++) { 235 var bit = 0x80 >> i; 236 if ((b & bit) == bit) { 237 print(" " + AIP[j][i]); 238 } 239 } 240 } 241 } 242 243 244 245 /** 246 * Decode an application file locator into a human readable form 247 * 248 * @param {ByteString} afl the Application File Locator 249 */ 250 EMVView.prototype.decodeAFL = function(afl) { 251 for (var i = 0; i < afl.length;) { 252 for (var j = 0; j < 4; j++) { 253 var b = afl.byteAt(i); 254 //print("Hex: " + b.toString(HEX)); 255 switch(j) { 256 case 0: 257 var b = b >> 3; 258 print(" SFI: " + b); 259 break; 260 case 1: 261 print(" First/Only Record Number: " + b); 262 break; 263 case 2: 264 print(" Last Record Number: " + b); 265 break; 266 case 3: 267 print(" Number of records involved in offline data authentication: " + b); 268 print(); 269 break; 270 default: 271 print(" Default: " + j); 272 break; 273 } 274 i++; 275 } 276 } 277 } 278 279 280 281 /** 282 * Decode a Cardholder Verification Method List into a human readable form 283 * 284 * @param {ByteString} cvmlist the Cardholder Verification Method List 285 */ 286 EMVView.prototype.decodeCVM = function(cvmlist) { 287 for (var i = 8; i<cvmlist.length; i = i+2) { 288 var b = cvmlist.byteAt(i); 289 if((b&0x40)==0x40) { 290 print(" Apply succeeding CV Rule if this CVM is unsucccessful"); 291 } 292 else { 293 print(" Fail cardholder verification if this CVM is unsuccessful"); 294 } 295 print(" " + CVM[b & 0x3F]); 296 print(" " + CVM2[cvmlist.byteAt(i+1)]); 297 print(); 298 } 299 } 300 301 302 303 /** 304 * Decode the Application Usage Control into a human readable form 305 * 306 * @param {ByteString} auc the Application Usage Control 307 */ 308 EMVView.prototype.decodeAUC = function(auc) { 309 var byte1 = auc.byteAt(0); 310 var byte2 = auc.byteAt(1); 311 print(" Byte 1:"); 312 for (var i = 0; i <=7; i++) { 313 if(byte1 & Math.pow(2,i) == Math.pow(2,i)) { 314 print(" " + AUC1[Math.pow(2,i)]); 315 } 316 } 317 print(" Byte 2:"); 318 for (var i = 0; i <=7; i++) { 319 if(byte2 & Math.pow(2,i) == Math.pow(2,i)) { 320 print(" " + AUC2[Math.pow(2,i)]); 321 } 322 } 323 } 324 325 326 AUC1 = []; 327 AUC1[0x01] = "Valid at terminals other than ATMs"; 328 AUC1[0x02] = "Valid at ATMs"; 329 AUC1[0x04] = "Valid for international services"; 330 AUC1[0x08] = "Valid for domestic services"; 331 AUC1[0x10] = "Valid for international goods"; 332 AUC1[0x20] = "Valid for domestic goods"; 333 AUC1[0x40] = "Valid for international cash transactions"; 334 AUC1[0x80] = "Valid for domestic cash transactions"; 335 336 AUC2 = []; 337 AUC2[0x01] = "RFU"; 338 AUC2[0x02] = "RFU"; 339 AUC2[0x04] = "RFU"; 340 AUC2[0x08] = "RFU"; 341 AUC2[0x10] = "RFU"; 342 AUC2[0x20] = "RFU"; 343 AUC2[0x40] = "International cashback allowed"; 344 AUC2[0x80] = "Domestic cashback allowed"; 345 346 TVR = [ 347 [ "Offline data authentication was not performed (b8)", 348 "SDA failed (b7)", 349 "ICC data missing (b6)", 350 "Card appears on terminal exception file (b5)", 351 "DDA failed (b4)", 352 "CDA failed (b3)", 353 "RFU (b2)", 354 "RFU (b1)" 355 ], 356 [ "ICC and terminal have different application versions (b8)", 357 "Expired application (b7)", 358 "Application not yet effective (b6)", 359 "Requested service not allowed for card product (b5)", 360 "New card (b4)", 361 "RFU (b3)", 362 "RFU (b2)", 363 "RFU (b1)", 364 ], 365 [ "Cardholder verification was not successful (b8)", 366 "Unrecognised CVM (b7)", 367 "PIN Try Limit exceeded (b6)", 368 "PIN entry required and PIN pad not present or not working (b5)", 369 "PIN entry required, PIN pad present, but PIN was not entered (b4)", 370 "Online PIN entered (b3)", 371 "RFU (b2)", 372 "RFU (b1)", 373 ], 374 [ "Transaction exceeds floor limit (b8)", 375 "Lower consecutive offline limit exceeded (b7)", 376 "Upper consecutive offline limit (b6)", 377 "Transaction selected randomly for online processing (b5)", 378 "Merchant forced transaction online (b4)", 379 "RFU (b3)", 380 "RFU (b2)", 381 "RFU (b1)", 382 ], 383 [ "Default TDOL used (b8)", 384 "Issuer authentication failed (b7)", 385 "Script processing failed before final GENERATE AC (b6)", 386 "Script processing failed after final GENERATE AC (b5)", 387 "RFU (b4)", 388 "RFU (b3)", 389 "RFU (b2)", 390 "RFU (b1)", 391 ], 392 ]; 393 394 AIP = [ 395 [ "RFU (b8)", 396 "SDA supported (b7)", 397 "DDA supported (b6)", 398 "Cardholder verification is supported (b5)", 399 "Terminal risk management is to be performed (b4)", 400 "Issuer authentication is supported (b3)", 401 "RFU (b2)", 402 "CDA supported (b1)", 403 ], 404 [ "RFU (b8)", 405 "RFU (b7)", 406 "RFU (b6)", 407 "RFU (b5)", 408 "RFU (b4)", 409 "RFU (b3)", 410 "RFU (b2)", 411 "RFU (b1)", 412 ], 413 ]; 414 415 CVM = []; 416 CVM[0] = "Fail CVM processing"; 417 CVM[1] = "Plaintext PIN verification performed by ICC"; 418 CVM[2] = "Enciphered PIN verified online"; 419 CVM[3] = "Plaintext PIN verification performed by ICC and signature (paper)"; 420 CVM[4] = "Enciphered PIN verification performed by ICC"; 421 CVM[5] = "Enciphered Pin verification performed by ICC and signature (paper)"; 422 CVM[0x1E] = "Signature (paper)"; 423 CVM[0x1F] = "No CVM required"; 424 425 CVM2 = []; 426 CVM2[0] = "Always"; 427 CVM2[1] = "If unattended cash"; 428 CVM2[2] = "If not unattended cash and not manual cash and not purchase with cashback"; 429 CVM2[3] = "If terminal supports the CVM"; 430 CVM2[4] = "If manual cash"; 431 CVM2[5] = "If purchase with cashback"; 432 CVM2[6] = "If transaction is in the application currency and is under X value"; 433 CVM2[7] = "If transaction is in the application currency and is over X value"; 434 CVM2[8] = "If transaction is in the application currency and is under Y value"; 435 CVM2[9] = "If transaction is in the application currency and is over Y value"; 436 CVM2[10] = "RFU"; 437 CVM2[11] = "Reserved for use by individual payment systems"; 438 439 440 DOL = []; 441 DOL[0x5F2A] = "Transaction Currency Code"; 442 DOL[0x8A] = "Authorisation Response Code"; 443 DOL[0x91] = "Issuer Authentication Data"; 444 DOL[0x95] = "Terminal Verification Results"; 445 DOL[0x9A] = "Transaction Date"; 446 DOL[0x9C] = "Transaction Type"; 447 DOL[0x9F02] = "Authorised amount of the transaction (excluding adjustments)"; 448 DOL[0x9F03] = "Secondary amount associated with the transaction representing a cashback amount"; 449 DOL[0x9F1A] = "Terminal Country Code"; 450 DOL[0x9F33] = "Terminal Capabilities"; 451 DOL[0x9F34] = "Cardholder Verification Method (CVM) Results"; 452 DOL[0x9F35] = "Terminal Type"; 453 DOL[0x9F37] = "Unpredictable Number"; 454 DOL[0x9F40] = "Additional Terminal Capabilities"; 455 DOL[0x9F45] = "Data Authentication Code"; 456 DOL[0x9F4C] = "ICC Dynamic Number"; 457 458 459 EMVView.DE = []; 460 EMVView.DE[0x4F] = "Application Identifier (AID) - card: "; 461 EMVView.DE[0x5A] = "Application Primary Account Number (PAN): "; 462 EMVView.DE[0x5F2D] = "Language Preference: "; 463 464 EMVView.DE[0x5F24] = "Application Expiration Date (YYMMDD): "; 465 EMVView.DE[0x5F25] = "Application Effective Date (YYMMDD): "; 466 EMVView.DE[0x5F28] = "Issuer Country Code: "; 467 EMVView.DE[0x5F34] = "Application Primary Account Number (PAN) Sequence Number: "; 468 EMVView.DE[0x87] = "Application Priority Indicator: "; 469 EMVView.DE[0x88] = "Short File Identifier (SFI): "; 470 EMVView.DE[0x8F] = "Certification Authority Public Key Index: "; 471 EMVView.DE[0x90] = "Issuer Public Key Certificate: "; 472 EMVView.DE[0x92] = "Issuer Public Key Remainder: "; 473 EMVView.DE[0x93] = "Signed Static Application Data: "; 474 EMVView.DE[0x9F07] = "Application Usage Control: "; 475 EMVView.DE[0x9F08] = "Application Version Number: "; 476 EMVView.DE[0x9F32] = "Issuer Public Key Exponent: "; 477 EMVView.DE[0x9F42] = "Application Currency Code: "; 478 EMVView.DE[0x9F44] = "Application Currency Exponent: "; 479 EMVView.DE[0x9F45] = "Data Authentication Code: "; 480 EMVView.DE[0x9F46] = "ICC Public Key Certificate: "; 481 EMVView.DE[0x9F47] = "ICC Public Key Exponent: "; 482 EMVView.DE[0x9F48] = "ICC Public Key Remainder: "; 483 EMVView.DE[0x9F4A] = "Static Data Authentication Tag List: "; 484 EMVView.DE[0x9F62] = "Track 1 Bit Map for CVC3 (Paypass): "; 485 EMVView.DE[0x9F63] = "Track 1 Bit Map for UN and ATC (Paypass): "; 486 EMVView.DE[0x9F64] = "Track 1 Number of ATC Digits (Paypass): "; 487 EMVView.DE[0x9F65] = "Track 2 Bit Map for CVC3 (Paypass): "; 488 EMVView.DE[0x9F66] = "Track 2 Bit Map for UN and ATC (Paypass): "; 489 EMVView.DE[0x9F67] = "Track 2 Number of ATC Digits (Paypass): "; 490 EMVView.DE[0x9F68] = "Mag Stripe CVM List (Paypass): "; 491 EMVView.DE[0x9F6B] = "Track 2 Data (Paypass): "; 492 EMVView.DE[0x9F6C] = "Mag Stripe Application Version Number (Card) (Paypass): "; 493 EMVView.DE[0x9F1F] = "Track 1 Discretionary Data: "; 494 EMVView.DE[0x9F6E] = "Third Party Data: "; 495 EMVView.DE[0x56] = "Track 1 Data: "; 496