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