1 /** 2 * --------- 3 * |.##> <##.| Open Smart Card Development Platform (www.openscdp.org) 4 * |# #| 5 * |# #| Copyright (c) 1999-2011 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 Functions for initialization and loading data on a Mifare 1K card 25 */ 26 27 load("mifare.js"); 28 29 function Loader() { 30 31 } 32 33 /** 34 * Initialize an application directory 35 */ 36 Loader.prototype.initialize = function() { 37 var card = new Card(_scsh3.reader); 38 39 card.reset(Card.RESET_COLD); 40 41 this.mif = new Mifare(card); 42 43 print("UID: " + this.mif.getUID()); 44 45 if (_scsh3.reader.substr(0, 3) != "SCM") { 46 var keyaid = 0x00; // Use for ACR and Omnikey readers 47 } else { 48 print("SCM Reader detected."); 49 var keyaid = 0x60; // Use for SCS SDI 010 and 011 50 } 51 52 var key = new ByteString("FFFFFFFFFFFF", HEX); 53 this.mif.loadKey(keyaid, key); 54 var s = this.mif.newSector(0); 55 s.setKeyId(keyaid); 56 s.readAll(Mifare.KEY_A); 57 print(s.toString()); 58 59 s.setKeyA(new ByteString("A0A1A2A3A4A5", HEX)); 60 s.setKeyB(new ByteString("B0B1B2B3B4B5", HEX)); 61 s.setHeaderDataByte(new ByteString("C1", HEX)); 62 63 s.setACforBlock(0, Sector.AC_UPDATEKEYB); 64 s.setACforBlock(1, Sector.AC_UPDATEKEYB); 65 s.setACforBlock(2, Sector.AC_UPDATEKEYB); 66 s.setACforBlock(3, Sector.AC_UPDATE_WITH_KEYB); 67 68 var mad = new ByteString("0103E103E103E103E103E103E103E103E103E103E103E103E103E103E103E1", HEX); 69 var crc = Mifare.crc8(mad); 70 var mad = ByteString.valueOf(crc,1).concat(mad); 71 72 s.update(1, mad.bytes(0, 16)); 73 s.update(2, mad.bytes(16, 16)); 74 s.update(3); 75 76 print(s.toString()); 77 } 78 79 80 /** 81 * Loading the data into the card 82 */ 83 Loader.prototype.load = function(data) { 84 var empty = new ByteString("00000000000000000000000000000000", HEX); 85 var arr = Loader.splitData(data); 86 var countSectors = Math.round(arr.length / 3) + (arr.length % 3); 87 assert(countSectors <= 15); 88 89 for (var i = 1; i <= countSectors ; i++) { 90 print("Write in sector " + i); 91 var s = this.mif.newSector(i); 92 s.setKeyId(keyaid); 93 s.readAll(Mifare.KEY_A); 94 95 s.setKeyA(new ByteString("D3F7D3F7D3F7", HEX)); 96 s.setKeyB(new ByteString("B0B1B2B3B4B5", HEX)); 97 s.setHeaderDataByte(new ByteString("40", HEX)); //muss laut spec auf 0x40 stehen 98 99 s.setACforBlock(0, Sector.AC_UPDATEKEYB); 100 s.setACforBlock(1, Sector.AC_UPDATEKEYB); 101 s.setACforBlock(2, Sector.AC_UPDATEKEYB); 102 s.setACforBlock(3, Sector.AC_UPDATE_WITH_KEYB); 103 104 if (arr.length != 0) { 105 s.update(0, arr.pop()); 106 } 107 if (arr.length != 0) { 108 s.update(1, arr.pop()); 109 } 110 else { 111 s.update(1, empty); 112 } 113 if (arr.length != 0) { 114 s.update(2, arr.pop()); 115 } 116 else { 117 s.update(2, empty); 118 } 119 s.update(3); 120 print(s.toString()); 121 } 122 } 123 124 125 /** 126 * Encode data in TLV structure and split it in 16 Byte ByteStrings. 127 * @return {Array} 128 */ 129 Loader.splitData = function(data) { 130 var b = new ByteBuffer(); 131 //insert tag byte 132 b.append(new ByteString("03", HEX)); 133 134 var length = data.length; 135 if (length < 14) { 136 b.append(ByteString.valueOf(length)); 137 b.append(data.bytes(0)); 138 //padding 139 for (var i = b.length; i < 16; i++) { 140 b.append(ByteString.valueOf(0)); 141 } 142 } 143 else if (length <= 0xFE) { 144 b.append(ByteString.valueOf(length)); 145 b.append(data.bytes(0, 14)); 146 data = data.bytes(14); 147 } 148 else { 149 b.append(new ByteString("FF", HEX)); 150 b.append(ByteString.valueOf(length)) 151 b.append(data.bytes(0, 12)); 152 data = data.bytes(12); 153 } 154 155 var arr = new Array(b.toByteString()); 156 157 158 while (data.length != 0) { 159 if (data.length == 16) { 160 arr.push(data.bytes(0, 16)); 161 return arr.reverse(); 162 } 163 else if (data.length > 16) { 164 arr.push(data.bytes(0, 16)); 165 data = data.bytes(16); 166 } 167 else { 168 var tmp = data.bytes(0); 169 //padding 170 tmp = tmp.concat(new ByteString("FE", HEX)); 171 var pad = new ByteString("00000000000000000000000000000000", HEX); 172 tmp = tmp.concat(pad.bytes(0, 16 - tmp.length)); 173 arr.push(tmp); 174 return arr.reverse(); 175 } 176 } 177 return arr.reverse(); 178 } 179 180