1 /**
  2  *  ---------
  3  * |.##> <##.|  SmartCard-HSM Support Scripts
  4  * |#       #|
  5  * |#       #|  Copyright (c) 2011-2012 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 SmartCard-HSM Card Service
 25  */
 26 
 27 // Imports
 28 var CVC = require("scsh/eac/CVC").CVC;
 29 var PublicKeyReference = require("scsh/eac/PublicKeyReference").PublicKeyReference;
 30 var ChipAuthentication = require("scsh/eac/ChipAuthentication").ChipAuthentication;
 31 var PKCS1 = require("scsh/pkcs/PKCS1").PKCS1;
 32 var DKEK = require("scsh/sc-hsm/DKEK").DKEK;
 33 
 34 
 35 
 36 /**
 37  * Create a SmartCard-HSM access object
 38  * @class Class implementing support for SmartCard-HSM access
 39  * @constructor
 40  * @param {Card} card the card object
 41  */
 42 function SmartCardHSM(card) {
 43 	this.card = card;
 44 
 45 	this.maxCAPDU = 1232;			// APDU buffer limit in JCOP 3
 46 	this.maxRAPDU = 1232;
 47 	this.limitedAPDUTransport = false;	// The APDU transport does not support the full response side
 48 
 49 	if (card.readerName.indexOf("Secure Flash Card") == 0) {
 50 		this.maxCAPDU = 478;
 51 		this.maxRAPDU = 506;
 52 		this.limitedAPDUTransport = true;
 53 	} else if (card.readerName.indexOf("REINER SCT cyberJack") == 0) {
 54 		this.maxCAPDU = 1014;
 55 		this.maxRAPDU = 1014;
 56 		this.limitedAPDUTransport = true;
 57 	} else if (card.readerName.indexOf("ACS APG8201") == 0) {
 58 		this.maxCAPDU = 1141;
 59 		this.maxRAPDU = 1141;
 60 		this.limitedAPDUTransport = true;
 61 	} else if (card.readerName.indexOf("Gemalto IDBridge") == 0) {
 62 		this.maxCAPDU = 262;
 63 		this.maxRAPDU = 499;
 64 		this.limitedAPDUTransport = true;
 65 	}
 66 
 67 	if (typeof(this.card.maxReaderCAPDU) != "undefined") {
 68 		if (this.card.maxReaderCAPDU < this.maxCAPDU) {
 69 			this.maxCAPDU = this.card.maxReaderCAPDU;
 70 			this.limitedAPDUTransport = true;
 71 		}
 72 	}
 73 
 74 	if (typeof(this.card.maxReaderRAPDU) != "undefined") {
 75 		if (this.card.maxReaderRAPDU < this.maxRAPDU) {
 76 			this.maxRAPDU = this.card.maxReaderRAPDU;
 77 			this.limitedAPDUTransport = true;
 78 		}
 79 	}
 80 
 81 	// 9 Byte CLA|INS|P1|P2|LcEx||LeEx
 82 	// 19 Byte SM overhead (Tag 85, 3 byte length, 1 byte padding indicator, tag 97 02 <Le> and tag 8E 08 <mac>
 83 	// 1 byte required for padding
 84 	this.maxCData = Math.floor((this.maxCAPDU - 9 - 19) / 16) * 16 - 1;
 85 //	print("maxCData=" + this.maxCData);
 86 
 87 	// 19 Byte SM overhead (Tag 85, 3 byte length, 1 byte padding indicator, tag 99 02 SW1SW2 and tag 8E 08 <mac>
 88 	// 2 byte SW1/SW2
 89 	// 1 byte required for padding
 90 	this.maxRData = Math.floor((this.maxRAPDU - 18 - 2) / 16) * 16 - 1;
 91 //	print("maxRData=" + this.maxRData);
 92 
 93 	this.useExternalHashInECDSA = false;	// Disable hashing in card if affected by bug #93
 94 
 95 	// Check if SmartCard-HSM is already selected and authenticated
 96 	this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x20, 0x00, 0x81, 0);
 97 
 98 	if (this.card.SW != 0x9000) {
 99 		this.logout();		// Select application
100 	}
101 
102 	this.namemap = [];
103 	this.idmap = [];
104 }
105 
106 exports.SmartCardHSM = SmartCardHSM;
107 
108 
109 SmartCardHSM.C_DevAut = new ByteString("2F02", HEX);
110 SmartCardHSM.EF_TokenInfo = new ByteString("2F03", HEX);
111 SmartCardHSM.EF_StaticTokenInfo = new ByteString("CB00", HEX);
112 
113 SmartCardHSM.PrK_DevAut = 0;
114 SmartCardHSM.PIN_User = 0x81;
115 
116 SmartCardHSM.PRKDPREFIX = 0xC4;
117 SmartCardHSM.CERTDPREFIX = 0xC8;
118 SmartCardHSM.KEYMETAPREFIX = 0xCB;	// Changed in V2.3
119 SmartCardHSM.READONLYDATAPREFIX = 0xCB;	// Starting with V2.3
120 SmartCardHSM.KEYPREFIX = 0xCC;
121 SmartCardHSM.CONFIDENTIALDATAPREFIX = 0xCD;
122 SmartCardHSM.EECERTIFICATEPREFIX = 0xCE;
123 SmartCardHSM.CACERTIFICATEPREFIX = 0xCA;
124 
125 SmartCardHSM.ALGORITHMS = [];
126 
127 // Symmetric
128 SmartCardHSM.ALG_CBC_ENC = 0x10;
129 SmartCardHSM.ALG_CBC_DEC = 0x11;
130 SmartCardHSM.ALG_CMAC = 0x18;
131 
132 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_CBC_ENC] = "CBC_ENC";
133 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_CBC_DEC] = "CBC_DEC";
134 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_CMAC] = "CMAC";
135 
136 
137 // RSA Block
138 SmartCardHSM.ALG_RSA_SIGN_RAW = 0x20;
139 SmartCardHSM.ALG_RSA_DECRYPT_RAW = 0x21;
140 SmartCardHSM.ALG_RSA_DECRYPT_V15 = 0x22;
141 SmartCardHSM.ALG_RSA_DECRYPT_OAEP = 0x23;
142 
143 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_RSA_SIGN_RAW] = "RSA_RAW";
144 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_RSA_DECRYPT_RAW] = "RSA_DECRYPT_RAW";
145 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_RSA_DECRYPT_V15] = "RSA_DECRYPT_V15";
146 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_RSA_DECRYPT_OAEP] = "RSA_DECRYPT_OAEP";
147 
148 
149 // RSA Sign with hash and PKCS#1 V1.5
150 SmartCardHSM.ALG_RSA_SIGN_V15_SHA1 = 0x31;
151 SmartCardHSM.ALG_RSA_SIGN_V15_SHA256 = 0x33;
152 SmartCardHSM.ALG_RSA_SIGN_V15_SHA512 = 0x35;
153 
154 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_RSA_SIGN_V15_SHA1] = "RSA_V15_SHA1";
155 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_RSA_SIGN_V15_SHA256] = "RSA_V15_SHA256";
156 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_RSA_SIGN_V15_SHA512] = "RSA_V15_SHA512";
157 
158 
159 // RSA Sign with hash and PSS
160 SmartCardHSM.ALG_RSA_SIGN_PSS = 0x40;
161 SmartCardHSM.ALG_RSA_SIGN_PSS_SHA1 = 0x41;
162 SmartCardHSM.ALG_RSA_SIGN_PSS_SHA256 = 0x43;
163 SmartCardHSM.ALG_RSA_SIGN_PSS_SHA512 = 0x45;
164 
165 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_RSA_SIGN_PSS] = "RSA_PSS";
166 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_RSA_SIGN_PSS_SHA1] = "RSA_PSS_SHA1";
167 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_RSA_SIGN_PSS_SHA256] = "RSA_PSS_SHA256";
168 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_RSA_SIGN_PSS_SHA512] = "RSA_PSS_SHA512";
169 
170 
171 // ECDSA
172 SmartCardHSM.ALG_ECDSA = 0x70;
173 SmartCardHSM.ALG_ECDSA_SHA1 = 0x71;
174 SmartCardHSM.ALG_ECDSA_SHA224 = 0x72;
175 SmartCardHSM.ALG_ECDSA_SHA256 = 0x73;
176 SmartCardHSM.ALG_ECDSA_SHA384 = 0x74;
177 SmartCardHSM.ALG_ECDSA_SHA512 = 0x75;
178 
179 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_ECDSA] = "ECDSA";
180 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_ECDSA_SHA1] = "ECDSA_SHA1";
181 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_ECDSA_SHA224] = "ECDSA_SHA224";
182 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_ECDSA_SHA256] = "ECDSA_SHA256";
183 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_ECDSA_SHA384] = "ECDSA_SHA384";
184 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_ECDSA_SHA512] = "ECDSA_SHA512";
185 
186 
187 // ECDH
188 SmartCardHSM.ALG_ECDH = 0x80;
189 SmartCardHSM.ALG_ECDHAutPuk = 0x83;
190 SmartCardHSM.ALG_ECDHXKEK = 0x84;
191 
192 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_ECDH] = "ECDH";
193 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_ECDHAutPuk] = "ECDH_AUTPUK";
194 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_ECDHXKEK] = "ECDH_XKEK";
195 
196 
197 // Wrap
198 SmartCardHSM.ALG_WRAP = 0x92;
199 SmartCardHSM.ALG_UNWRAP = 0x93;
200 SmartCardHSM.ALG_REPLACE = 0x94;
201 
202 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_WRAP] = "WRAP";
203 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_UNWRAP] = "UNWRAP";
204 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_REPLACE] = "REPLACE";
205 
206 
207 // Derive
208 SmartCardHSM.ALG_DERIVE_EC_KEY = 0x98;
209 SmartCardHSM.ALG_DERIVE_SP800_56C = 0x99;
210 
211 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_DERIVE_EC_KEY] = "DERIVE_EC";
212 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_DERIVE_SP800_56C] = "DERIVE_SP800_56C";
213 
214 
215 SmartCardHSM.ALG_SIGN_DEFAULT = 0xA0;
216 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_SIGN_DEFAULT] = "SIGN_DEFAULT";
217 
218 
219 // Key Generation
220 SmartCardHSM.ALG_GENERATE_AES128 = 0xB0;
221 SmartCardHSM.ALG_GENERATE_AES192 = 0xB1;
222 SmartCardHSM.ALG_GENERATE_AES256 = 0xB2;
223 
224 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_GENERATE_AES128] = "GENERATE_AES128";
225 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_GENERATE_AES192] = "GENERATE_AES192";
226 SmartCardHSM.ALGORITHMS[SmartCardHSM.ALG_GENERATE_AES256] = "GENERATE_AES256";
227 
228 
229 SmartCardHSM.ALGOMAP = {};
230 for (var i = 0; i < SmartCardHSM.ALGORITHMS.length; i++) {
231 	var name = SmartCardHSM.ALGORITHMS[i];
232 	if (typeof(name) != "undefined") {
233 		SmartCardHSM.ALGOMAP[name] = i;
234 	}
235 }
236 
237 
238 SmartCardHSM.rootCerts = {
239 	DESRCACC100001: new CVC(new ByteString("7F218201B47F4E82016C5F290100420E44455352434143433130303030317F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A78641046D025A8026CDBA245F10DF1B72E9880FFF746DAB40A43A3D5C6BEBF27707C30F6DEA72430EE3287B0665C1EAA6EAA4FA26C46303001983F82BD1AA31E03DA0628701015F200E44455352434143433130303030317F4C10060B2B0601040181C31F0301015301C05F25060102010100095F24060302010100085F37409DBB382B1711D2BAACB0C623D40C6267D0B52BA455C01F56333DC9554810B9B2878DAF9EC3ADA19C7B065D780D6C9C3C2ECEDFD78DEB18AF40778ADF89E861CA", HEX)),
240 	UTSRCACC100001: new CVC(new ByteString("7F218201B47F4E82016C5F290100420E55545352434143433130303030317F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7864104A041FEB2FD116B2AD19CA6B7EACD71C9892F941BB88D67DCEEC92501F070011957E22122BA6C2CF5FF02936F482E35A6129CCBBA8E9383836D3106879C408EF08701015F200E55545352434143433130303030317F4C10060B2B0601040181C31F0301015301C05F25060102010100095F24060302010100085F3740914DD0FA00615C44048D1467435400423A4AD1BD37FD98D6DE84FD8037489582325C72956D4FDFABC6EDBA48184A754F37F1BE5142DD1C27D66569308CE19AAF", HEX))
241 }
242 
243 SmartCardHSM.devAutPuk = new Key();
244 SmartCardHSM.devAutPuk.setType(Key.PUBLIC);
245 SmartCardHSM.devAutPuk.setComponent(Key.ECC_CURVE_OID, new ByteString("brainpoolP256r1", OID));
246 SmartCardHSM.devAutPuk.setComponent(Key.ECC_QX, new ByteString("4C01EA36C5065FF47E8F0676A77CDCED6C8F745E6784F7807F5520124F81ED05", HEX));
247 SmartCardHSM.devAutPuk.setComponent(Key.ECC_QY, new ByteString("4112DCE471CA003442830A10C75B31F9BFADD60628F47131628C7254AD8B956A", HEX));
248 
249 
250 
251 /**
252  * Remove Root Certificate of Development SRCA
253  *
254  * Always call this on a productive system
255  */
256 SmartCardHSM.disableUTSRCA = function() {
257 	delete SmartCardHSM.rootCerts.UTSRCACC100001;
258 }
259 
260 
261 
262 /**
263  * Parse list of CVC in a binary blob
264  *
265  * @param {ByteString} a binary blob (e.g an EF) containing concatenated CVCs
266  * @type CVC[]
267  * @return the list of CVCs
268  */
269 SmartCardHSM.parseCertificateList = function(bin) {
270 	var a = new ASN1((new ASN1(0x30, bin)).getBytes());
271 	var list = [];
272 	for (var i = 0; i < a.elements; i++) {
273 		list.push(new CVC(a.get(i)));
274 	}
275 	return list;
276 }
277 
278 
279 
280 /**
281  * Validate device certificate chain
282  *
283  * @param {Crypto} crypto the crypto provider to use
284  * @param {ByteString} devAutCert the device certificate chain read from EF.C_DevAut
285  * @type Key
286  * @return the device authentication public key
287  */
288 SmartCardHSM.validateCertificateChain = function(crypto, devAutCert) {
289 	// Device device certificate
290 	var cvc = new CVC(devAutCert);
291 	GPSystem.trace("Device Certificate    : " + cvc);
292 
293 	if (cvc.getCAR().toString() == "DECA00001") {		// CA used for development version up to 0.17
294 		if (typeof(SmartCardHSM.rootCerts.UTSRCACC100001) == "undefined") {
295 			GPSystem.trace("Device certificate DECA00001 disabled");
296 			return null;
297 		}
298 		if (!cvc.verifyWith(crypto, SmartCardHSM.devAutPuk)) {
299 			GPSystem.trace("Device certificate verification failed for CAR=DECA00001");
300 			return null;
301 		}
302 		var path = "/" + cvc.getCAR().getHolder() + "/" + cvc.getCHR().getHolder();
303 		return { devicecert: cvc, publicKey:cvc.getPublicKey(), path:path };
304 	}
305 
306 	// Decode device issuer certificate
307 	var len = cvc.getASN1().size;
308 	var cvc = new CVC(devAutCert.left(len));
309 	var dica = new CVC(devAutCert.bytes(len));
310 	GPSystem.trace("Device Issuer CA      : " + dica);
311 
312 	if (typeof(SmartCardHSM.rootCerts[dica.getCAR()]) == "undefined") {
313 		GPSystem.trace("Unknown or disabled root CA " + dica.getCAR());
314 		return null;
315 	}
316 
317 	// Determine root certificateSmartCardHSM.rootCerts[dica.getCAR()]
318 	var srca = SmartCardHSM.rootCerts[dica.getCAR()];
319 	GPSystem.trace("SmartCard-HSM Root CA : " + srca);
320 
321 	// Validate chain
322 	var srcapuk = srca.getPublicKey();
323 	var oid = srca.getPublicKeyOID();
324 	if (!dica.verifyWith(crypto, srcapuk, oid)) {
325 		GPSystem.trace("DICA certificate not verified");
326 		return null;
327 	}
328 
329 	var dicapuk = dica.getPublicKey(srcapuk);
330 	if (!cvc.verifyWith(crypto, dicapuk, oid)) {
331 		GPSystem.trace("Device certificate verification failed");
332 		return null;
333 	}
334 
335 	var path = "/" + srca.getCHR().getHolder() + "/" + dica.getCHR().getHolder() + "/" + cvc.getCHR().getHolder();
336 	return { srca: srca, dica: dica, devicecert: cvc, publicKey:cvc.getPublicKey(srcapuk), path:path };
337 }
338 
339 
340 
341 /**
342  * Decode algorithm list and return string array with names
343  *
344  * @param {ByteString} list the algorithm list, e.g. as returned in the key meta data
345  * @type String[]
346  * @return the list of algorithm names
347  */
348 SmartCardHSM.decodeAlgorithmList = function(list) {
349 	var a = [];
350 	for (var i = 0; i < list.length; i++) {
351 		a.push(SmartCardHSM.ALGORITHMS[list.byteAt(i)]);
352 	}
353 
354 	return a;
355 }
356 
357 
358 
359 /**
360  * Parse and encode the algorithm list containing either algorithm ids or names
361  *
362  * @param {String | String[]} list the list of algorithms
363  * @type ByteString
364  * @return the algorithm list
365  */
366 SmartCardHSM.encodeAlgorithmList = function(list) {
367 	if (typeof(list) == "string") {
368 		if (list.indexOf(".") != -1) {
369 			list = list.split(".");
370 		} else {
371 			list = list.split(",");
372 		}
373 	}
374 
375 	var bb = new ByteBuffer();
376 
377 	for (var i = 0; i < list.length; i++) {
378 		var e = list[i].trim();
379 		var id = NaN;
380 		if (e.length == 2) {
381 			id = parseInt(e, 16);
382 		}
383 		if (isNaN(id)) {
384 			var id = SmartCardHSM.ALGOMAP[e.toUpperCase()];
385 			if (typeof(id) == "undefined") {
386 				print("Unknown keyword or number " + list[i]);
387 				return null;
388 			}
389 		}
390 		bb.append(id);
391 	}
392 
393 	return bb.toByteString();
394 }
395 
396 
397 
398 /**
399  * Return a string describing the SmartCard-HSM Version
400  *
401  * @type String
402  * @return the version string
403  */
404 SmartCardHSM.prototype.getVersionInfo = function() {
405 	if (typeof(this.major) == "undefined") {
406 		return "Version unknown";
407 	}
408 
409 	var str = "Version " + this.major + "." + this.minor;
410 
411 	if (typeof(this.platform) != "undefined") {
412 		switch(this.platform) {
413 			case 0: str += " on JCOP"; break;
414 			case 1: str += " Demo on JCOP"; break;
415 			case 2: str += " on JCOP 2.4.1r3"; break;
416 			case 3: str += " on JCOP 2.4.2r3"; break;
417 			case 4: str += " on JCOP 2.4.2r1"; break;
418 			case 5: str += " on JCOP 3"; break;
419 			case 6: str += " on JCOP 4"; break;
420 		}
421 	}
422 	return str;
423 }
424 
425 
426 
427 /**
428  * Return the native OCF SmartCardHSMCardService
429  *
430  * @type de.cardcontact.opencard.service.smartcardhsm.SmartCardHSMCardService
431  * @return the OCF SmartCardHSMCardService
432  */
433 SmartCardHSM.prototype.getNativeCardService = function() {
434 	if (this.nativeCardService) {
435 		return this.nativeCardService;
436 	}
437 	this.nativeCardService = this.card.getCardService("de.cardcontact.opencard.service.smartcardhsm.SmartCardHSMCardService");
438 
439 	return this.nativeCardService;
440 }
441 
442 
443 
444 /**
445  * Validate device certificate chain
446  *
447  * @param {Crypto} crypto the crypto provider to use
448  * @type Key
449  * @return the device authentication public key
450  */
451 SmartCardHSM.prototype.validateCertificateChain = function(crypto) {
452 	// Read concatenation of both certificates
453 	var devAutCert = this.readBinary(SmartCardHSM.C_DevAut);
454 	var chain = SmartCardHSM.validateCertificateChain(crypto, devAutCert);
455 	if (chain == null) {
456 		return null;
457 	}
458 	return chain.publicKey;
459 }
460 
461 
462 
463 /**
464  * Open a secure channel using device authentication
465  *
466  * @param {Crypto} crypto the crypto provider to use
467  * @param {Key} devAuthPK the device authentication public key
468  * @param {Number} Key.AES or Key.DES to request AES or DES secure messaging (Default probe)
469  * @type ISOSecureChannel
470  * @return the initialized secure channel
471  */
472 SmartCardHSM.prototype.openSecureChannel = function(crypto, devAuthPK, smtype) {
473 
474 	var type;
475 
476 	if (smtype) {
477 		type = smtype;
478 	} else {
479 		type = Key.AES;
480 	}
481 
482 	if (type == Key.DES) {
483 		var protocol = new ByteString("id-CA-ECDH-3DES-CBC-CBC", OID);
484 	} else {
485 		var protocol = new ByteString("id-CA-ECDH-AES-CBC-CMAC-128", OID);
486 	}
487 
488 	// Try AES first and fallback to DES is not supported by card
489 
490 	var bb = new ByteBuffer();
491 	bb.append(new ASN1(0x80, protocol).getBytes());
492 
493 	this.card.sendSecMsgApdu(Card.CPRO|Card.CENC|Card.RPRO, 0x00, 0x22, 0x41, 0xA4, bb.toByteString(), [0x9000, 0x6A80]);
494 
495 	if (this.card.SW == 0x6A80) {
496 		if (smtype) {
497 			throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 3, "Requested secure messaging not supported");
498 		}
499 
500 		type = Key.DES;
501 
502 		var protocol = new ByteString("id-CA-ECDH-3DES-CBC-CBC", OID);
503 
504 		var bb = new ByteBuffer();
505 		bb.append(new ASN1(0x80, protocol).getBytes());
506 
507 		this.card.sendSecMsgApdu(Card.CPRO|Card.CENC|Card.RPRO, 0x00, 0x22, 0x41, 0xA4, bb.toByteString(), [0x9000]);
508 	}
509 
510 	var ca = new ChipAuthentication(crypto, protocol, devAuthPK);	// For domain parameter
511 	ca.noPadding = true;
512 	ca.generateEphemeralCAKeyPair();
513 
514 	var ephemeralPublicKeyIfd = ca.getEphemeralPublicKey();
515 
516 	var dado = new ASN1(0x7C, new ASN1(0x80, ephemeralPublicKeyIfd));
517 
518 	var dadobin = this.card.sendSecMsgApdu(Card.CPRO|Card.CENC|Card.RPRO|Card.RENC, 0x00, 0x86, 0x00, 0x00, dado.getBytes(), 0, [0x9000]);
519 
520 //	GPSystem.trace(dadobin);
521 
522 	var dado = new ASN1(dadobin);
523 	assert(dado.tag == 0x7C);
524 	assert(dado.elements == 2);
525 	var nonceDO = dado.get(0);
526 	assert(nonceDO.tag == 0x81);
527 	var nonce = nonceDO.value;
528 
529 	var authTokenDO = dado.get(1);
530 	assert(authTokenDO.tag == 0x82);
531 	var authToken = authTokenDO.value;
532 
533 	var enc = new ByteString("04", HEX);
534 	enc = enc.concat(devAuthPK.getComponent(Key.ECC_QX));
535 	enc = enc.concat(devAuthPK.getComponent(Key.ECC_QY));
536 
537 	GPSystem.trace("Encoded CA public key: " + enc);
538 	ca.performKeyAgreement(enc, nonce);
539 	var result = ca.verifyAuthenticationToken(authToken);
540 
541 	if (!result) {
542 		GPSystem.trace("Authentication token invalid");
543 		throw new Error("Authentication token invalid");
544 	}
545 	GPSystem.trace("Authentication token valid");
546 
547 	if (type == Key.DES) {
548 		var sm = new IsoSecureChannel(crypto);
549 		sm.setEncKey(ca.kenc);
550 		sm.setMacKey(ca.kmac);
551 		sm.setMACSendSequenceCounter(new ByteString("0000000000000000", HEX));
552 	} else {
553 		var sm = new IsoSecureChannel(crypto, IsoSecureChannel.SSC_SYNC_ENC_POLICY);
554 		sm.setEncKey(ca.kenc);
555 		sm.setMacKey(ca.kmac);
556 		sm.setMACSendSequenceCounter(new ByteString("00000000000000000000000000000000", HEX));
557 	}
558 
559 	this.card.setCredential(sm);
560 	this.smactive = true;
561 	return sm;
562 }
563 
564 
565 
566 /**
567  * Update transparent EF referenced by file identifier
568  *
569  * @param {ByteString} fid the two byte file identifier
570  * @param {Number} offset the offset into the EF
571  * @param {ByteString} data the data to write
572  */
573 SmartCardHSM.prototype.updateBinary = function(fid, offset, data) {
574 	if (typeof(offset) == "undefined") {
575 		offset = 0;
576 	}
577 
578 	var bytesLeft = data.length;
579 	var sent = 0;
580 
581 	// 8 bytes are required for T54(4) and T53(4)
582 	var blksize = this.maxCData - 8;
583 
584 	while (bytesLeft > 0) {
585 		var toSend = bytesLeft >= blksize ? blksize : bytesLeft;
586 
587 		var t54 = new ASN1(0x54, ByteString.valueOf(offset, 2));
588 		var t53 = new ASN1(0x53, data.bytes(sent, toSend));
589 
590 		var cdata = t54.getBytes().concat(t53.getBytes());
591 		this.card.sendSecMsgApdu(Card.ALL, 0x00, 0xD7, fid.byteAt(0), fid.byteAt(1), cdata, [0x9000]);
592 
593 		bytesLeft -= toSend;
594 		offset += toSend;
595 		sent += toSend;
596 	}
597 }
598 
599 
600 
601 /**
602  * Read transparent EF referenced by file identifier
603  *
604  * @param {ByteString} fid the two byte file identifier (optional - use currently selected EF if absent)
605  * @param {Number} offset the offset into the EF (optional)
606  * @param {Number} length the number of byte to read (optional)
607  * @type ByteString
608  * @return the data read from the EF
609  */
610 SmartCardHSM.prototype.readBinary = function(fid, offset, length) {
611 	if (typeof(offset) == "undefined") {
612 		offset = 0;
613 	}
614 	if (typeof(fid) == "undefined") {
615 		fid = new ByteString("0000", HEX);
616 	}
617 
618 	var rsp = new ByteBuffer();
619 	do	{
620 		var t54 = new ASN1(0x54, ByteString.valueOf(offset, 2));
621 
622 		if (length || this.limitedAPDUTransport || this.smactive) {				// Is a length defined ?
623 			var le = (!length || (length > this.maxRData)) ? this.maxRData: length;		// Truncate if larger than maximum APDU size ?
624 		} else {
625 			var le = this.maxRAPDU <= 256 ? 0 : 65536;					// Get all with Le=0 in either short or extended APDU mode
626 		}
627 
628 		var data = this.card.sendSecMsgApdu(Card.ALL, 0x00, 0xB1, fid.byteAt(0), fid.byteAt(1), t54.getBytes(), le, [0x9000, 0x6282]);
629 
630 		if (data.length == 0) {
631 			break;
632 		}
633 
634 		rsp.append(data);
635 		offset += data.length;
636 
637 		if (length) {					// Length was defined, see if we already got everything
638 			length -= data.length;
639 			if (length <= 0) {
640 				break;
641 			}
642 		}
643 	} while ((this.card.SW == 0x9000) || (this.card.SW == 0x6282));
644 
645 	return rsp.toByteString();
646 }
647 
648 
649 
650 /**
651  * Select the file or key an return the FCP
652  *
653  * @param {ByteString} fid the two byte file object identifier
654  */
655 SmartCardHSM.prototype.selectFile = function(fid) {
656 	var fcp = this.card.sendSecMsgApdu(Card.ALL, 0x00, 0xA4, 0x00, 0x04, fid, 0, [0x9000]);
657 	return fcp;
658 }
659 
660 
661 
662 /**
663  * Try selecting the file to see if is present
664  *
665  * @param {ByteString} fid the two byte file object identifier
666  */
667 SmartCardHSM.prototype.hasFile = function(fid) {
668 	this.card.sendSecMsgApdu(Card.ALL, 0x00, 0xA4, 0x00, 0x04, fid, 0);
669 	return this.card.SW == 0x9000;
670 }
671 
672 
673 
674 /**
675  * Delete file system object (EF or key)
676  *
677  * @param {ByteString} fid the two byte file object identifier
678  */
679 SmartCardHSM.prototype.deleteFile = function(fid) {
680 	return this.card.sendSecMsgApdu(Card.ALL, 0x00, 0xE4, 0x02, 0x00, fid, [0x9000]);
681 }
682 
683 
684 
685 /**
686  * Strips leading zeros of a ByteString
687  *
688  * @param {ByteString} value the ByteString value
689  * @return the stripped ByteString object, may be an empty ByteString
690  * @type ByteString
691  */
692 SmartCardHSM.stripLeadingZeros = function(value) {
693 	var i = 0;
694 	for (; (i < value.length) && (value.byteAt(i) == 0); i++);
695 
696 	return value.right(value.length - i);
697 }
698 
699 
700 
701 /**
702  * Build input for Generate Asymmetric Key Pair command for generating an ECC key pair
703  *
704  * @param {PublicKeyReference} innerCAR the CA the request shall be directed to
705  * @param {ByteString} algo the public key algorithm
706  * @param {PublicKeyReference} chr the certificate holder reference associated with this key
707  * @param {Key} dp the domain parameter for the key
708  * @param {PublicKeyReference} outerCAR the certificate holder reference of the public key for verifying the outer signature
709  * @param {Key} privateKey optional parameter to supply a private key value for import. This only works with the development version
710  *              of the SmartCard-HSM.
711  * @type ByteString
712  * @return the encoded C-Data for GENERATE ASYMMETRIC KEY PAIR
713  */
714 SmartCardHSM.buildGAKPwithECC = function(innerCAR, algo, chr, dp, outerCAR, priKey) {
715 
716 	// Encode G
717 	var bb = new ByteBuffer();
718 	// uncompressed encoding
719 	bb.append(new ByteString("04", HEX));
720 	bb.append(dp.getComponent(Key.ECC_GX));
721 	bb.append(dp.getComponent(Key.ECC_GY));
722 	var G = bb.toByteString();
723 
724 	var t = new ASN1(0x30,
725 				new ASN1("CPI", 0x5F29, new ByteString("00", HEX)),
726 				new ASN1("CAR", 0x42, innerCAR.getBytes()),
727 				new ASN1("Public Key", 0x7F49,
728 					new ASN1("Object Identifier", 0x06, algo),
729 					new ASN1("Prime Modulus", 0x81, dp.getComponent(Key.ECC_P)),
730 					new ASN1("First coefficient a", 0x82, dp.getComponent(Key.ECC_A)),
731 					new ASN1("Second coefficient b", 0x83, dp.getComponent(Key.ECC_B)),
732 					new ASN1("Base Point G", 0x84, G),
733 					new ASN1("Order of the base point", 0x85, dp.getComponent(Key.ECC_N)),
734 					new ASN1("Cofactor f", 0x87, SmartCardHSM.stripLeadingZeros(dp.getComponent(Key.ECC_H)))
735 				),
736 				new ASN1("CHR", 0x5F20, chr.getBytes())
737 			);
738 
739 	if (typeof(outerCAR) != "undefined") {
740 		t.add(new ASN1("OuterCAR", 0x45, outerCAR.getBytes()));
741 	}
742 
743 	if (priKey != undefined) {
744 		var d = new ASN1("Private Key", 0x8A, priKey.getComponent(Key.ECC_D));
745 		t.get(2).add(d);
746 //		GPSystem.trace(t);
747 	}
748 	return t.value;
749 }
750 
751 
752 
753 /**
754  * Build input for Generate Asymmetric Key Pair command for generating a RSA key pair
755  *
756  * @param {PublicKeyReference} innerCAR the CA the request shall be directed to
757  * @param {ByteString} algo the public key algorithm
758  * @param {PublicKeyReference} chr the certificate holder reference associated with this key
759  * @param {Number} keysize the module size in bits (1024, 1536 or 2048)
760  * @param {PublicKeyReference} outerCAR the certificate holder reference of the public key for verifying the outer signature
761  * @type ByteString
762  * @return the encoded C-Data for GENERATE ASYMMETRIC KEY PAIR
763  */
764 SmartCardHSM.buildGAKPwithRSA = function(innerCAR, algo, chr, keysize, outerCAR) {
765 
766 	var t = new ASN1(0x30,
767 				new ASN1("CPI", 0x5F29, new ByteString("00", HEX)),
768 				new ASN1("CAR", 0x42, innerCAR.getBytes()),
769 				new ASN1("Public Key", 0x7F49,
770 					new ASN1("Object Identifier", 0x06, algo),
771 					new ASN1("Public Key Exponent", 0x82, ByteString.valueOf(65537)),
772 					new ASN1("Key Size", 0x02, ByteString.valueOf(keysize))
773 				),
774 				new ASN1("CHR", 0x5F20, chr.getBytes())
775 			);
776 
777 	if (typeof(outerCAR) != "undefined") {
778 		t.add(new ASN1("OuterCAR", 0x45, outerCAR.getBytes()));
779 	}
780 	return t.value;
781 }
782 
783 
784 
785 /**
786  * Create a PKCS#15 PrivateECCKey description
787  *
788  * @param {Number/ByteString} keyid the key identifier
789  * @param {String} label the key label
790  * @type ASN1
791  * @return the PrivateECCKey description
792  */
793 SmartCardHSM.buildPrkDforECC = function(keyid, label, keysize) {
794 	if (typeof(keyid) == "number") {
795 		keyid = ByteString.valueOf(keyid);
796 	}
797 
798 	var prkd = 	new ASN1(0xA0,
799 					new ASN1(ASN1.SEQUENCE,
800 						new ASN1(ASN1.UTF8String, new ByteString(label, UTF8))
801 //						new ASN1(ASN1.BIT_STRING, new ByteString("0780", HEX)),
802 //						new ASN1(ASN1.OCTET_STRING, new ByteString("01", HEX))
803 					),
804 					new ASN1(ASN1.SEQUENCE,
805 						new ASN1(ASN1.OCTET_STRING, keyid),
806 						new ASN1(ASN1.BIT_STRING, new ByteString("072080", HEX))
807 					),
808 					new ASN1(0xA1,
809 						new ASN1(ASN1.SEQUENCE,
810 							new ASN1(ASN1.SEQUENCE,
811 								new ASN1(ASN1.OCTET_STRING, new ByteString("", HEX))
812 							)
813 						)
814 					)
815 				);
816 
817 	if (keysize != undefined) {
818 		assert(keysize > 0, "Key size must be > 0");
819 		var tlvint = ByteString.valueOf(keysize);
820 		if (tlvint.byteAt(0) >= 0x80) {
821 			tlvint = (new ByteString("00", HEX)).concat(tlvint);
822 		}
823 		prkd.get(2).get(0).add(new ASN1(ASN1.INTEGER, tlvint));
824 	}
825 
826 //	GPSystem.trace(prkd);
827 	return prkd;
828 }
829 
830 
831 
832 /**
833  * Create a PKCS#15 PrivateRSAKey description
834  *
835  * @param {Number/ByteString} keyid the key identifier
836  * @param {String} label the key label
837  * @param {Number} modulussize
838  * @type ASN1
839  * @return the PrivateECCKey description
840  */
841 SmartCardHSM.buildPrkDforRSA = function(keyid, label, modulussize) {
842 	if (typeof(keyid) == "number") {
843 		keyid = ByteString.valueOf(keyid);
844 	}
845 
846 	var prkd = 	new ASN1(0x30,
847 					new ASN1(ASN1.SEQUENCE,
848 						new ASN1(ASN1.UTF8String, new ByteString(label, UTF8))
849 //						new ASN1(ASN1.BIT_STRING, new ByteString("0780", HEX)),
850 //						new ASN1(ASN1.OCTET_STRING, new ByteString("01", HEX))
851 					),
852 					new ASN1(ASN1.SEQUENCE,
853 						new ASN1(ASN1.OCTET_STRING, keyid),
854 						new ASN1(ASN1.BIT_STRING, new ByteString("0274", HEX))
855 					),
856 					new ASN1(0xA1,
857 						new ASN1(ASN1.SEQUENCE,
858 							new ASN1(ASN1.SEQUENCE,
859 								new ASN1(ASN1.OCTET_STRING, new ByteString("", HEX))
860 							),
861 							new ASN1(ASN1.INTEGER, ByteString.valueOf(modulussize))
862 						)
863 					)
864 				);
865 //	GPSystem.trace(prkd);
866 	return prkd;
867 }
868 
869 
870 
871 /**
872  * Create a PKCS#15 SecretKey description
873  *
874  * @param {Number/ByteString} keyid the key identifier
875  * @param {String} label the key label
876  * @param {Number} keysize
877  * @type ASN1
878  * @return the secret key description
879  */
880 SmartCardHSM.buildSKDforAES = function(keyid, label, keysize) {
881 	if (typeof(keyid) == "number") {
882 		keyid = ByteString.valueOf(keyid);
883 	}
884 
885 	var skd =
886 		new ASN1(0xA8,
887 			// CommonObjectAttributes
888 			new ASN1(ASN1.SEQUENCE,
889 				new ASN1(ASN1.UTF8String, new ByteString(label, UTF8))
890 				//						new ASN1(ASN1.BIT_STRING, new ByteString("0780", HEX)),
891 				//						new ASN1(ASN1.OCTET_STRING, new ByteString("01", HEX))
892 			),
893 			// ClassAttributes: CommonKeyAttributes
894 			new ASN1(ASN1.SEQUENCE,
895 				new ASN1(ASN1.OCTET_STRING, keyid),
896 				new ASN1(ASN1.BIT_STRING, new ByteString("07C010", HEX))
897 			),
898 			// SubClassAttribute: CommonSecretKeyAttributes
899 			new ASN1(0xA0,
900 				new ASN1(ASN1.SEQUENCE,
901 					new ASN1(ASN1.INTEGER, ByteString.valueOf(keysize, 2))
902 				)
903 			),
904 			new ASN1(0xA1,
905 				new ASN1(ASN1.SEQUENCE,
906 					new ASN1(ASN1.SEQUENCE,
907 						new ASN1(ASN1.OCTET_STRING, new ByteString("", HEX))
908 					)
909 				)
910 			)
911 
912 		);
913 //	GPSystem.trace(skd);
914 	return skd;
915 }
916 
917 
918 
919 /**
920  * Create a PKCS#15 certificate description
921  *
922  * @param {ByteString} commonObjectFlags default value is '0640'
923  * @param {String} label the key label
924  * @param {Key} pubKey the public key
925  * @param {ByteString} certFID the file identifier of the certificate
926  * @type ASN1
927  * @return the PrivateECCKey description
928  */
929 SmartCardHSM.buildCertDescription = function(label, commonObjectFlags, pubKey, certFID) {
930 	if (!commonObjectFlags) {
931 		commonObjectFlags = new ByteString("0x0640", HEX);
932 	}
933 
934 	// generate subject key id
935 	var qx = pubKey.getComponent(Key.ECC_QX)
936 	if (qx) {
937 	  var enc = qx;
938 	} else {
939 	  var enc = pubKey.getComponent(Key.MODULUS);
940 	}
941 	var crypto = new Crypto();
942 	var subjectKeyID = crypto.digest(Crypto.SHA_1, enc);
943 
944 	var desc = 	new ASN1(ASN1.SEQUENCE,
945 				new ASN1(ASN1.SEQUENCE,			// common object attributes
946 					new ASN1(ASN1.UTF8String, new ByteString(label, UTF8)),
947 					new ASN1(ASN1.BIT_STRING, commonObjectFlags)
948 				),
949 				new ASN1(ASN1.SEQUENCE,			// common certificate attributes
950 					  new ASN1(ASN1.OCTET_STRING, subjectKeyID)
951 				),
952 				new ASN1(0xA1,					// type attributes
953 					new ASN1(ASN1.SEQUENCE,			// x.509 certificate attributes
954 						new ASN1(ASN1.SEQUENCE,			// path
955 							new ASN1(ASN1.OCTET_STRING, certFID)
956 						)
957 					)
958 				)
959 			);
960 	return desc;
961 }
962 
963 
964 
965 /**
966  * Dump C-Data of Generate Asymmetric Key Pair command
967  *
968  * @param {ByteString} keydata the content of C-Data
969  */
970 SmartCardHSM.dumpKeyData = function(keydata) {
971 	GPSystem.trace(keydata);
972 	var a = new ASN1(0x30, keydata);
973 	var a = new ASN1(a.getBytes());
974 	for (var i = 0; i < a.elements; i++) {
975 		GPSystem.trace(a.get(i));
976 	}
977 }
978 
979 
980 
981 /**
982  * Generate an asymmetric key pair
983  *
984  * @param {Number} newkid key identifier for new key
985  * @param {Number} signkid key identifier for signing the new public key
986  * @param {ByteString} keydata the key data template
987  * @type ByteString
988  * @return the certificate signing request containing the new public key
989  */
990 SmartCardHSM.prototype.generateAsymmetricKeyPair = function(newkid, signkid, keydata) {
991 
992 	if (!this.limitedAPDUTransport) { // Use extended length
993 		var rsp = this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x46, newkid, signkid, keydata, 65536, [0x9000]);
994 	} else {
995 		this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x46, newkid, signkid, keydata, [0x9000]);
996 		var rsp = this.readBinary(ByteString.valueOf(0xCE00 + newkid), 0);
997 	}
998 
999 	return rsp;
1000 }
1001 
1002 
1003 
1004 /**
1005  * Generate a symmetric key
1006  *
1007  * @param {Number} newkid key identifier for new key
1008  * @param {Number} algo key generation algorithm
1009  * @param {ByteString} keydata the key data template
1010  * @type ByteString
1011  * @return
1012  */
1013 SmartCardHSM.prototype.generateSymmetricKey = function(newkid, algo, keydata) {
1014 
1015 	var rsp = this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x48, newkid, algo, keydata, 0, [0x9000]);
1016 	return rsp;
1017 }
1018 
1019 
1020 
1021 /**
1022  * Return true is SmartCard-HSM is initialized
1023  *
1024  * @type Boolean
1025  * @return true if initialized
1026  */
1027 SmartCardHSM.prototype.isInitialized = function() {
1028 	var sw = this.queryUserPINStatus();
1029 	if ((sw == 0x6984) || (sw == 0x6A88)) {		// V1.2: Not initialized / V2.0: Transport PIN
1030 		var sw = this.queryInitializationCodeStatus();
1031 		if (sw == 0x6A88) {
1032 			return false;
1033 		}
1034 	}
1035 	return true;
1036 }
1037 
1038 
1039 
1040 /**
1041  * Initialize device and clear all keys and files
1042  *
1043  * @param {ByteString} options two byte option mask
1044  * @param {ByteString} initialPIN initial user PIN value
1045  * @param {ByteString} initializationCode secret code for device initialization (set during first use)
1046  * @param {Number} retryCounterInitial retry counter for user PIN
1047  * @param {Number} keyshares number of device key encryption key shares (optional)
1048  */
1049 SmartCardHSM.prototype.initDevice = function(options, initialPIN, initializationCode, retryCounterInitial, keyshares) {
1050 	var s = new ASN1(0x30,
1051 				new ASN1(0x80, options),
1052 				new ASN1(0x81, initialPIN),
1053 				new ASN1(0x82, initializationCode),
1054 				new ASN1(0x91, ByteString.valueOf(retryCounterInitial))
1055 				);
1056 
1057 	if (typeof(keyshares) != "undefined") {
1058 		s.add(new ASN1(0x92, ByteString.valueOf(keyshares)));
1059 	}
1060 	this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x50, 0x00, 0x00, s.value, [0x9000]);
1061 }
1062 
1063 
1064 
1065 /**
1066  * Determine free memory
1067  *
1068  * @type Number
1069  * @return the number of available bytes (this values is capped to 32767 on JCOP 2.4.1)
1070  */
1071 SmartCardHSM.prototype.getFreeMemory = function() {
1072 	var rsp = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x50, 0x00, 0x00, 0, [0x9000, 0x6700]);
1073 
1074 	if (this.card.SW != 0x9000) {
1075 		return -1;
1076 	}
1077 
1078 	this.major = rsp.byteAt(rsp.length - 2);
1079 	this.minor = rsp.byteAt(rsp.length - 1);
1080 	this.platform = rsp.byteAt(rsp.length - 3);
1081 	return rsp.bytes(rsp.length - 7, 4).toUnsigned();
1082 }
1083 
1084 
1085 
1086 /**
1087  * Parse the key domain status returned from the device
1088  *
1089  * @param {ByteString} status the R-DATA from the MANAGE KEY DOMAIN command
1090  * @type object
1091  * @return the decoded status Info
1092  */
1093 SmartCardHSM.prototype.parseKeyDomainStatus = function(status) {
1094 	if (status.length == 0) {
1095 		return { sw: this.card.SW };
1096 	}
1097 
1098 	var statusObject = {
1099 		sw: this.card.SW,
1100 		shares: status.byteAt(0),
1101 		outstanding: status.byteAt(1),
1102 		kcv: status.bytes(2, 8)
1103 	}
1104 
1105 	if (status.length > 10) {
1106 		statusObject.keyDomain = status.bytes(10);
1107 	}
1108 
1109 	return statusObject;
1110 }
1111 
1112 
1113 
1114 /*
1115  * Create DKEK Key Domain
1116  *
1117  * @param {Number} keyDomain number of key domain in the range 0 to the maximum defined in the INITIALIZE DEVICE command
1118  * @param {Number} shares the number of DKEK shares to import
1119  * @type Object
1120  * @return object with properties sw{Number}, shares{Number}, outstanding{Number} and kcv{ByteString}
1121  */
1122 SmartCardHSM.prototype.createDKEKKeyDomain = function(keyDomain, shares) {
1123 	if (typeof(keyDomain) != "number") {
1124 		throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 1, "keyDomain must be a number");
1125 	}
1126 	if (typeof(shares) != "number") {
1127 		throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 1, "shares must be a number");
1128 	}
1129 
1130 	var status = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x52, 0x01, keyDomain, ByteString.valueOf(shares), 0);
1131 
1132 	return this.parseKeyDomainStatus(status);
1133 }
1134 
1135 
1136 
1137 /**
1138  * Create XKEK Key Domain
1139  *
1140  * @param {Number} keyDomain number of key domain in the range 0 to the maximum defined in the INITIALIZE DEVICE command
1141  * @param {ByteString} keyDomainMembership either a 64 byte signature (old format) or a encoded TLV object with tag 54 or 55
1142  * @return object with properties sw{Number}, shares{Number}, outstanding{Number}, kcv{ByteString} and the key domain UID{ByteString}
1143  * @type Object
1144  */
1145 SmartCardHSM.prototype.createXKEKKeyDomain = function(keyDomain, groupSignerPublicKey, keyDomainMembership) {
1146 	if (typeof(keyDomain) != "number") {
1147 		throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 1, "keyDomain must be a number");
1148 	}
1149 	if ((keyDomain < 0) || (keyDomain > 0xFF)) {
1150 		throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 1, "keyDomain must be between 0 and 255");
1151 	}
1152 	if (!(groupSignerPublicKey instanceof CVC)) {
1153 		throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 1, "groupSignerPublicKey must be a CVC instance");
1154 	}
1155 	if (!(keyDomainMembership instanceof ByteString)) {
1156 		throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 1, "keyDomainMembership must be a ByteString");
1157 	}
1158 
1159 	var car = groupSignerPublicKey.getOuterCAR().getBytes();
1160 
1161 	var pukrefdo = new ASN1(0x83, car);
1162 	var pukref = pukrefdo.getBytes();
1163 
1164 	this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x22, 0x81, 0xB6, pukref, [0x9000]);
1165 
1166 	if (keyDomainMembership.length == 64) {
1167 		keyDomainMembership = new ASN1(0x53, keyDomainMembership).getBytes();
1168 	}
1169 	var cdata = groupSignerPublicKey.getASN1().value.concat(keyDomainMembership);
1170 
1171 	if (cdata.length <= this.maxCData) {
1172 		var status = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x52, 0x02, keyDomain, cdata, 0);
1173 	} else {
1174 		this.updateBinary(ByteString.valueOf(0x2F10), 0, cdata);
1175 		var status = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x52, 0x02, keyDomain, 0);
1176 	}
1177 
1178 	return this.parseKeyDomainStatus(status);
1179 }
1180 
1181 
1182 
1183 /**
1184  * Associate XKEK Key Domain
1185  *
1186  * @param {Number} keyDomain number of key domain in the range 0 to the maximum defined in the INITIALIZE DEVICE command
1187  * @param {ByteString} keyDomainUID a encoded TLV object with tag 51 containing the key domain uid of the associated domain
1188  * @param {ByteString} keyDomainAssociation a encoded TLV object with tag 56 or 57
1189  * @return object with properties sw{Number}, shares{Number}, outstanding{Number}, kcv{ByteString} and the key domain UID{ByteString}
1190  * @type Object
1191  */
1192 SmartCardHSM.prototype.associateXKEKKeyDomain = function(keyDomain, groupSignerPublicKey, keyDomainUID, keyDomainAssociation) {
1193 	if (typeof(keyDomain) != "number") {
1194 		throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 1, "keyDomain must be a number");
1195 	}
1196 	if ((keyDomain < 0) || (keyDomain > 0xFF)) {
1197 		throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 1, "keyDomain must be between 0 and 255");
1198 	}
1199 	if (!(groupSignerPublicKey instanceof CVC)) {
1200 		throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 1, "groupSignerPublicKey must be a ByteString");
1201 	}
1202 	if (!(keyDomainUID instanceof ByteString)) {
1203 		throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 1, "keyDomainUID must be a ByteString");
1204 	}
1205 	if (!(keyDomainAssociation instanceof ByteString)) {
1206 		throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 1, "keyDomainAssociation must be a ByteString");
1207 	}
1208 
1209 	var car = groupSignerPublicKey.getOuterCAR().getBytes();
1210 
1211 	var pukrefdo = new ASN1(0x83, car);
1212 	var pukref = pukrefdo.getBytes();
1213 
1214 	this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x22, 0x81, 0xB6, pukref, [0x9000]);
1215 
1216 	var cdata = groupSignerPublicKey.getASN1().value.concat(keyDomainUID).concat(keyDomainAssociation);
1217 
1218 	if (cdata.length <= this.maxCData) {
1219 		var status = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x52, 0x05, keyDomain, cdata, 0);
1220 	} else {
1221 		this.updateBinary(ByteString.valueOf(0x2F10), 0, cdata);
1222 		var status = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x52, 0x05, keyDomain, 0);
1223 	}
1224 
1225 	return this.parseKeyDomainStatus(status);
1226 }
1227 
1228 
1229 
1230 /**
1231  * Derive XKEK
1232  *
1233  * @param {Number} keyDomain number of key domain in the range 0 to the maximum defined in the INITIALIZE DEVICE command
1234  * @param {ByteString} derivationParam
1235  * @return object with properties sw{Number}, shares{Number}, outstanding{Number}, kcv{ByteString} and the key domain UID{ByteString}
1236  * @type Object
1237  */
1238 SmartCardHSM.prototype.deriveXKEK = function(keyid, peerPublicKey, derivationParam) {
1239 	if (typeof(keyid) != "number") {
1240 		throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 1, "keyid must be a number");
1241 	}
1242 	if ((keyid < 1) || (keyid > 0xFF)) {
1243 		throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 1, "keyid must be between 1 and 255");
1244 	}
1245 	if (!(peerPublicKey instanceof CVC)) {
1246 		throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 1, "peerPublicKey must be a CVC");
1247 	}
1248 	if (!(derivationParam instanceof ByteString)) {
1249 		throw new GPError("SmartCardHSM", GPError.INVALID_DATA, 1, "derivationParam must be a ByteString");
1250 	}
1251 
1252 	var car = peerPublicKey.getOuterCAR().getBytes();
1253 
1254 	var pukrefdo = new ASN1(0x83, car);
1255 	var pukref = pukrefdo.getBytes();
1256 
1257 	this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x22, 0x81, 0xB6, pukref, [0x9000]);
1258 
1259 	var kdp = new ASN1(0x50, derivationParam).getBytes();
1260 	var cdata = peerPublicKey.getASN1().value.concat(kdp);
1261 
1262 	if (cdata.length <= this.maxCData) {
1263 		// Le is usually not required, but versions 3.1 to 3.3 fail without Le (#178)
1264 		this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x62, keyid, 0x84, cdata, 0, [0x9000]);
1265 	} else {
1266 		this.updateBinary(ByteString.valueOf(0x2F10), 0, cdata);
1267 		this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x62, keyid, 0x84, [0x9000]);
1268 	}
1269 }
1270 
1271 
1272 
1273 /**
1274  * Query the status of the key domain
1275  *
1276  * @param {Number} keyDomain the number of the key domain which will be queried, default is 0
1277  * @type Object
1278  * @return object with properties sw{Number}, shares{Number}, outstanding{Number}, kcv{ByteString} and for a XKEK key domain the key domain UID{ByteString}
1279  */
1280 SmartCardHSM.prototype.queryKeyDomainStatus = function(keyDomain) {
1281 	if (!keyDomain) {
1282 		keyDomain = 0;
1283 	}
1284 
1285 	var status = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x52, 0x00, keyDomain, 0);
1286 
1287 	return this.parseKeyDomainStatus(status);
1288 }
1289 
1290 
1291 
1292 /**
1293  * Delete the key encryption key in a key domain
1294  *
1295  * @param {Number} keyDomain the number of the key domain
1296  */
1297 SmartCardHSM.prototype.deleteKEK = function(keyDomain) {
1298 	var status = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x52, 0x04, keyDomain, [0x9000]);
1299 
1300 	return this.parseKeyDomainStatus(status);
1301 }
1302 
1303 
1304 
1305 /**
1306  * Delete the empty key domain
1307  *
1308  * @param {Number} keyDomain the number of the key domain
1309  */
1310 SmartCardHSM.prototype.deleteKeyDomain = function(keyDomain) {
1311 	this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x52, 0x03, keyDomain, [0x9000]);
1312 }
1313 
1314 
1315 
1316 /**
1317  * Import DKEK share or query status
1318  *
1319  * @param {Number} keyDomain the number of the key domain
1320  * @param {ByteString} keyshare 32 byte key share
1321  * @type Object
1322  * @return object with properties sw{Number}, shares{Number}, outstanding{Number} and kcv{ByteString}
1323  */
1324 SmartCardHSM.prototype.importKeyShare = function(keyDomain, keyshare) {
1325 	if (typeof(keyDomain) != "number") {
1326 		keyshare = keyDomain;
1327 		keyDomain = 0;
1328 	}
1329 	if (typeof(keyshare) != "undefined") {
1330 		var status = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x52, 0x00, keyDomain, keyshare, 0, [0x9000]);
1331 	} else {
1332 		var status = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x52, 0x00, keyDomain, 0);
1333 	}
1334 	if (status.length == 0) {
1335 		return { sw: this.card.SW };
1336 	}
1337 
1338 	var statusObject = {
1339 		sw: this.card.SW,
1340 		shares: status.byteAt(0),
1341 		outstanding: status.byteAt(1),
1342 		kcv: status.bytes(2, 8)
1343 	}
1344 
1345 	if (status.length > 10) {
1346 		statusObject.keyDomain = status.bytes(10);
1347 	}
1348 
1349 	return statusObject;
1350 }
1351 
1352 
1353 
1354 /**
1355  * Decrypt and import a DKEK share
1356  *
1357  * @param {ByteString} keyshare the encrypted key share as read from the .pbe file
1358  * @param {ByteString} password the password
1359  * @param {Number} keyDomain the number of the key domain
1360  * @return object with properties sw{Number}, shares{Number}, outstanding{Number} and kcv{ByteString}
1361  */
1362 SmartCardHSM.prototype.importEncryptedKeyShare = function(keyshare, password, keyDomain) {
1363 	if (typeof(keyDomain) == "undefined") {
1364 		keyDomain = 0;
1365 	}
1366 
1367 	var dkek = DKEK.decryptKeyShare(keyshare, password);
1368 //	print("Importing into SmartCard-HSM");
1369 	var r = this.importKeyShare(keyDomain, dkek);
1370 	dkek.clear();
1371 	return r;
1372 }
1373 
1374 
1375 
1376 /**
1377  * Wrap key under DKEK
1378  *
1379  * @param {Number} id key id
1380  * @type ByteString
1381  * @return key blob with encrypted key value
1382  */
1383 SmartCardHSM.prototype.wrapKey = function(id) {
1384 	var keyblob = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x72, id, 0x92, 65536, [0x9000]);
1385 	return keyblob;
1386 }
1387 
1388 
1389 
1390 /**
1391  * Unwrap key with DKEK
1392  *
1393  * @param {Number} id key id
1394  * @param {ByteString} keyblob the wrapped key
1395  */
1396 SmartCardHSM.prototype.unwrapKey = function(id, keyblob) {
1397 	if (keyblob.length < this.maxCData) {
1398 		this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x74, id, 0x93, keyblob, [0x9000]);
1399 	} else {
1400 		this.updateBinary(ByteString.valueOf(0x2F10), 0, keyblob);
1401 		this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x74, id, 0x93, [0x9000]);
1402 	}
1403 }
1404 
1405 
1406 
1407 /**
1408  * Replace symmetric key value encrypted under current key
1409  *
1410  * @param {Number} id key id
1411  * @param {ByteString} keyblob the wrapped key
1412  */
1413 SmartCardHSM.prototype.unwrapAndReplaceKey = function(id, keyblob) {
1414 	this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x74, id, 0x94, keyblob, [0x9000]);
1415 }
1416 
1417 
1418 
1419 /**
1420  * Derive Symmetric Key
1421  *
1422  * @param {Number} id key id
1423  * @param {Number} algo algorithm id (one of ALG_CBC_ENC, ALG_CBC_DEC, ALG_CMAC or ALG_DERIVE_SP800_56C)
1424  * @param {ByteString} derivationParam the derivation parameter
1425  * @type ByteString
1426  * @return derived key value
1427  */
1428 SmartCardHSM.prototype.deriveSymmetricKey = function(id, algo, derivationParam) {
1429 	var derivedKeyValue = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x78, id, algo, derivationParam, 0, [0x9000]);
1430 	return derivedKeyValue;
1431 }
1432 
1433 
1434 
1435 /**
1436  * Verify User PIN
1437  *
1438  * @param {ByteString} userPIN user PIN value
1439  * @return the status word SW1/SW2 returned by the device
1440  */
1441 SmartCardHSM.prototype.verifyUserPIN = function(userPIN) {
1442 	if (userPIN) {
1443 		this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x20, 0x00, 0x81, userPIN);
1444 		return this.card.SW;
1445 	} else {
1446 		var cs = this.getNativeCardService();
1447 		cs.verifyPassword();
1448 		return this.queryUserPINStatus();
1449 	}
1450 }
1451 
1452 
1453 
1454 /**
1455  * Logout
1456  *
1457  */
1458 SmartCardHSM.prototype.logout = function() {
1459 	this.card.clearCredential();
1460 	var fcp = this.card.sendApdu(0x00, 0xA4, 0x04, 0x04, new ByteString("E82B0601040181C31F0201", HEX), 0, [0x9000]);
1461 	var a = new ASN1(fcp);
1462 	var v = a.find(0x85).value;
1463 	this.options = v.bytes(0, 2).toUnsigned();
1464 	this.major = v.byteAt(v.length - 2);
1465 	this.minor = v.byteAt(v.length - 1);
1466 	if (v.length >= 5) {
1467 		this.platform = v.byteAt(v.length - 3);
1468 	}
1469 }
1470 
1471 
1472 
1473 /**
1474  * Change User PIN
1475  *
1476  * @param {ByteString} currentPIN current user PIN value
1477  * @param {ByteString} newPIN new user PIN value
1478  */
1479 SmartCardHSM.prototype.changeUserPIN = function(currentPIN, newPIN) {
1480 	this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x24, 0x00, 0x81, currentPIN.concat(newPIN), [0x9000]);
1481 }
1482 
1483 
1484 
1485 /**
1486  * Unblock and set User PIN
1487  *
1488  * @param {ByteString} initializationCode the initialization code
1489  * @param {ByteString} newPIN new user PIN value (optional)
1490  */
1491 SmartCardHSM.prototype.unblockUserPIN = function(initializationCode, newPIN) {
1492 	if (newPIN) {
1493 		this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x2C, 0x00, 0x81, initializationCode.concat(newPIN), [0x9000]);
1494 	} else {
1495 		this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x2C, 0x01, 0x81, initializationCode, [0x9000]);
1496 	}
1497 }
1498 
1499 
1500 
1501 /**
1502  * Change InitializationCode
1503  *
1504  * @param {ByteString} initializationCode current initialization code
1505  * @param {ByteString} newInitializationCode new initialization code
1506  */
1507 SmartCardHSM.prototype.changeInitializationCode = function(initializationCode, newInitializationCode) {
1508 	this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x24, 0x00, 0x88, initializationCode.concat(newInitializationCode), [0x9000]);
1509 }
1510 
1511 
1512 
1513 SmartCardHSM.describePINStatus = function(sw, name) {
1514 	var str;
1515 	switch(sw) {
1516 	case 0x9000:
1517 		str = name + " authenticated";
1518 		break;
1519 	case 0x6984:
1520 		str = name + " in transport mode or device not initialized";
1521 		break;
1522 	case 0x6A88:
1523 		str = name + " not initialized";
1524 		break;
1525 	case 0x6983:
1526 		str = name + " blocked";
1527 		break;
1528 	case 0x6300:
1529 		str = name + " not authenticated";
1530 		break;
1531 	default:
1532 		str = name + " not verified, " + (sw & 0xF) + " tries remaining";
1533 		break;
1534 	}
1535 	return str + " (" + ByteString.valueOf(sw).toString(HEX) + ")";
1536 }
1537 
1538 
1539 
1540 /**
1541  * Request PIN Status Information
1542  *
1543  * @param {Number} p2 the PIN object id
1544  * @type Number
1545  * @return the status word SW1/SW2 returned by the device
1546  */
1547 SmartCardHSM.prototype.queryPINStatus = function(p2) {
1548 	this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x20, 0x00, p2, 0);
1549 	return this.card.SW;
1550 }
1551 
1552 
1553 
1554 /**
1555  * Request PIN Status Information
1556  *
1557  * @type Number
1558  * @return the status word SW1/SW2 returned by the device
1559  */
1560 SmartCardHSM.prototype.queryUserPINStatus = function() {
1561 	return this.queryPINStatus(0x81);
1562 }
1563 
1564 
1565 
1566 /**
1567  * Request Initialization Code Status
1568  *
1569  * @type Number
1570  * @return the status word SW1/SW2 returned by the device
1571  */
1572 SmartCardHSM.prototype.queryInitializationCodeStatus = function() {
1573 	return this.queryPINStatus(0x88);
1574 }
1575 
1576 
1577 
1578 /**
1579  * Enumerate Objects
1580  *
1581  * @return the enumeration
1582  */
1583 SmartCardHSM.prototype.enumerateObjects = function() {
1584 	var rsp = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x58, 0x00, 0x00, 65536, [0x9000]);
1585 	return rsp;
1586 }
1587 
1588 
1589 
1590 /**
1591  * Generate random data
1592  *
1593  * @param {Number} length number of bytes
1594  * @return the random bytes
1595  */
1596 SmartCardHSM.prototype.generateRandom = function(length) {
1597 	var rsp = this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x84, 0x00, 0x00, length, [0x9000]);
1598 	return rsp;
1599 }
1600 
1601 
1602 
1603 /**
1604  * Sign data using referenced key
1605  *
1606  * @param {Number} keyid the key identifier for signing
1607  * @param {algo} algo the algorithm identifier
1608  * @param {ByteString} data the data to be signed
1609  * @return the signature value
1610  */
1611 SmartCardHSM.prototype.sign = function(keyid, algo, data) {
1612 	if (data.length <= this.maxCData) {
1613 		var rsp = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x68, keyid, algo, data, 0x10000, [0x9000]);
1614 	} else {
1615 		this.updateBinary(ByteString.valueOf(0x2F10), 0, data);
1616 		var rsp = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x68, keyid, algo, 0x10000, [0x9000]);
1617 	}
1618 
1619 	return rsp;
1620 }
1621 
1622 
1623 
1624 /**
1625  * Decipher cryptogram or agree shared secret using Diffie-Hellman
1626  *
1627  * @param {Number} keyid the key identifier
1628  * @param {Number} algo the algorithm identifier
1629  * @param {ByteString} data the the cryptogram or concatenation of x || y of ECC public key
1630  * @return the plain output
1631  */
1632 SmartCardHSM.prototype.decipher = function(keyid, algo, data) {
1633 	var rsp = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x62, keyid, algo, data, 0x00, [0x9000]);
1634 	return rsp;
1635 }
1636 
1637 
1638 
1639 /**
1640  * Verify card verifiable certificate
1641  *
1642  * @param {CVC} cvc the card verifiable certificate
1643  **/
1644 SmartCardHSM.prototype.verifyCertificate = function(cvc) {
1645 
1646 	// Check if public key is already known
1647 	var chr = cvc.getCHR().getBytes();
1648 
1649 	var pukrefdo = new ASN1(0x83, chr);
1650 	var pukref = pukrefdo.getBytes();
1651 
1652 	this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x22, 0x81, 0xB6, pukref, [0x9000, 0x6A88]);
1653 
1654 	if (this.card.SW == 0x9000) {
1655 		return;
1656 	}
1657 
1658 	// Select public key for verification
1659 	var car = cvc.getCAR().getBytes();
1660 
1661 	var pukrefdo = new ASN1(0x83, car);
1662 	var pukref = pukrefdo.getBytes();
1663 
1664 	this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x22, 0x81, 0xB6, pukref, [0x9000]);
1665 
1666 	// Extract value of 7F21
1667 	var tl = new TLVList(cvc.getBytes(), TLV.EMV);
1668 	var t = tl.index(0);
1669 	var v = t.getValue();
1670 
1671 	this.card.sendSecMsgApdu(Card.ALL, 0x00, 0x2A, 0x00, 0xBE, v, [0x9000]);
1672 }
1673 
1674 
1675 
1676 /**
1677  * Enumerate CA certificates
1678  *
1679  * @type String[]
1680  * @return the list of certificate labels
1681  */
1682 SmartCardHSM.prototype.enumerateCACertificates = function() {
1683 	this.canamemap = [];
1684 	this.caidmap = []
1685 	this.caids = [];
1686 	var certlist = [];
1687 
1688 	var fobs = this.enumerateObjects();
1689 
1690 	// Process PKCS#15 certificate descriptions
1691 	for (var i = 0; i < fobs.length; i+= 2) {
1692 		if (fobs.byteAt(i) == SmartCardHSM.CERTDPREFIX) {
1693 			var id = fobs.byteAt(i + 1);
1694 			this.caids.push(id);
1695 			var fid = ByteString.valueOf((SmartCardHSM.CACERTIFICATEPREFIX << 8) + id);
1696 			var descbin = this.readBinary(fobs.bytes(i, 2));
1697 			var asn = new ASN1(descbin);
1698 			var coa = asn.get(0);
1699 			if (coa.elements > 0) {
1700 				var label = coa.get(0).value.toString(ASCII);
1701 			} else {
1702 				var label = "No label (" + i + ")";
1703 			}
1704 			var cert = this.readBinary(fid);
1705 			certlist.push(label);
1706 			this.canamemap[label] = cert;
1707 			cert.id = id;
1708 			this.caidmap[label] = id;
1709 		}
1710 	}
1711 
1712 	return certlist;
1713 }
1714 
1715 
1716 
1717 /**
1718  * Return CA certificate with label
1719  *
1720  * @param {String} label the certificate label
1721  * @type ByteString
1722  * @return the encoded certificate
1723  */
1724 SmartCardHSM.prototype.getCACertificate = function(label) {
1725 	if (typeof(this.caids) == "undefined") {
1726 		this.enumerateCACertificates();
1727 	}
1728 
1729 	return this.canamemap[label];
1730 }
1731 
1732 
1733 
1734 /**
1735  * Determine an unused CA certificate identifier
1736  *
1737  * @type Number
1738  * @return a free CA certificate identifier or -1 if all identifier in use
1739  */
1740 SmartCardHSM.prototype.determineFreeCAId = function() {
1741 	if (typeof(this.caids) == "undefined") {
1742 		this.enumerateCACertificates();
1743 	}
1744 
1745 	if (this.caids.length == 0) {
1746 		return 0;
1747 	}
1748 
1749 	var id = Math.max.apply(null, this.caids) + 1;
1750 	if (id > 256) {
1751 		return -1;
1752 	}
1753 	return id;
1754 }
1755 
1756 
1757 
1758 /**
1759  * Add a new CA certificate to the map
1760  *
1761  * @param {X509} cert the CA certificate
1762  * @param {Number} id the corresponding id
1763  * @param {String} label the corresponding label
1764  */
1765 SmartCardHSM.prototype.addCACertificateToMap = function(cert, id, label) {
1766 	if (!this.caidmap[label]) {
1767 		// new id
1768 		this.caids.push(id);
1769 		this.caidmap[label] = id;
1770 	}
1771 	this.canamemap[label] = cert;
1772 }
1773 
1774 
1775 
1776 /**
1777  * Enumerate key objects in the SmartCard-HSM and build the map of keys
1778  *
1779  * @type String[]
1780  * @return the list of key labels
1781  */
1782 SmartCardHSM.prototype.enumerateKeys = function() {
1783 	this.namemap = [];
1784 	this.idmap = [];
1785 	this.idlist = [];
1786 	this.p15idmap = [];
1787 
1788 	var fobs = this.enumerateObjects();
1789 
1790 	// Process keys
1791 	for (var i = 0; i < fobs.length; i += 2) {
1792 		if ((fobs.byteAt(i) == SmartCardHSM.KEYPREFIX) || (fobs.byteAt(i) == 0xFF)) {
1793 			var kid = fobs.byteAt(i + 1);
1794 			if (kid > 0) {
1795 //				GPSystem.trace("Found key: " + kid);
1796 				var key = new SmartCardHSMKey(this, kid);
1797 				this.idmap[kid] = key;
1798 				this.idlist.push(kid);
1799 				this.updateKey(key);
1800 			}
1801 		}
1802 	}
1803 
1804 	var keylist = [];
1805 	// Process PKCS#15 private key descriptions
1806 	for (var i = 0; i < fobs.length; i += 2) {
1807 		if (fobs.byteAt(i) == SmartCardHSM.PRKDPREFIX) {
1808 			var kid = fobs.byteAt(i + 1);
1809 			var descbin = this.readBinary(fobs.bytes(i, 2));
1810 			if (descbin.length > 2) {
1811 				try {
1812 					var desc = new ASN1(descbin);
1813 					if (desc.elements < 3) {
1814 						continue;
1815 					}
1816 				}
1817 				catch(e) {
1818 					continue;
1819 				}
1820 				var key = this.idmap[kid];
1821 				if (key) {
1822 					key.setDescription(desc);
1823 					var label = key.getLabel();
1824 //					GPSystem.trace(key.getId() + " - " + label);
1825 					if (label) {
1826 						keylist.push(label);
1827 						this.namemap[label] = key;
1828 					}
1829 					var p15id = key.getPKCS15Id();
1830 					this.p15idmap[p15id.toString(HEX)] = key;
1831 				}
1832 			}
1833 		}
1834 	}
1835 
1836 	return keylist;
1837 }
1838 
1839 
1840 
1841 /**
1842  * Get key ids
1843  *
1844  * @type Number[]
1845  * @return a list of key identifier
1846  */
1847 SmartCardHSM.prototype.getKeyIds = function() {
1848 	if (typeof(this.idlist) == "undefined") {
1849 		this.enumerateKeys();
1850 	}
1851 	return this.idlist;
1852 }
1853 
1854 
1855 
1856 /**
1857  * Determine an unused key identifier
1858  *
1859  * @type Number
1860  * @return a free key identifier or -1 if all key identifier in use
1861  */
1862 SmartCardHSM.prototype.determineFreeKeyId = function() {
1863 	if (typeof(this.idlist) == "undefined") {
1864 		this.enumerateKeys();
1865 	}
1866 	for (var i = 1; i < 256; i++) {
1867 		if (this.idmap[i] == undefined) {
1868 			return i;
1869 		}
1870 	}
1871 	throw new GPError("SmartCardHSM", GPError.OUT_OF_MEMORY, 1, "Key idx exhausted");
1872 }
1873 
1874 
1875 
1876 /**
1877  * Update key attributes, in particular the use counter
1878  *
1879  * @param {HSMKey} key the HSM key
1880  */
1881 SmartCardHSM.prototype.updateKey = function(key) {
1882 	var fid = ByteString.valueOf((SmartCardHSM.KEYPREFIX << 8) + key.getId());
1883 	try	{
1884 		var fcp = this.selectFile(fid);
1885 	}
1886 	catch(e) {
1887 		return;
1888 	}
1889 	var a = new ASN1(fcp);
1890 	var pi = a.find(0xA5);
1891 	if (!pi) {
1892 		return;
1893 	}
1894 	var kc = pi.find(0x90);
1895 	if (kc) {
1896 		var c = kc.value.toUnsigned();
1897 
1898 		if (c != 0xFFFFFFFF) {
1899 			key.useCounter = c;
1900 		}
1901 	}
1902 
1903 	var kd = pi.find(0x91);
1904 	if (kd) {
1905 		key.algorithms = kd.value;
1906 	}
1907 
1908 	var kd = pi.find(0x92);
1909 	if (kd) {
1910 		key.keyDomain = kd.value.toUnsigned();
1911 	}
1912 }
1913 
1914 
1915 
1916 /**
1917  * Add a new key to the map of keys
1918  *
1919  * @param {HSMKey} key the HSM key
1920  */
1921 SmartCardHSM.prototype.addKeyToMap = function(key) {
1922 	var id = key.getId();
1923 	this.idmap[id] = key;
1924 
1925 	var label = key.getLabel();
1926 	if (label) {
1927 		this.namemap[label] = key;
1928 	}
1929 
1930 	var p15id = key.getPKCS15Id();
1931 	if (p15id) {
1932 		this.p15idmap[p15id.toString(HEX)] = key;
1933 	}
1934 }
1935 
1936 
1937 
1938 /**
1939  * Get a key reference object
1940  *
1941  * @param {String/Number/ByteString} labelOrId label or id of key
1942  * @returns the key or null if not found
1943  * @type Key
1944  */
1945 SmartCardHSM.prototype.getKey = function(labelOrId) {
1946 	if (typeof(this.idlist) == "undefined") {
1947 		this.enumerateKeys();
1948 	}
1949 
1950 	if (typeof(labelOrId) == "number") {
1951 		var key = this.idmap[labelOrId];
1952 	} else if (typeof(labelOrId) == "string") {
1953 		var key = this.namemap[labelOrId];
1954 	} else {
1955 		var key = this.p15idmap[labelOrId.toString(HEX)];
1956 	}
1957 
1958 	if (key == undefined) {
1959 		return null;
1960 	}
1961 	return key;
1962 }
1963 
1964 
1965 
1966 /**
1967  * Return a list of key objects
1968  *
1969  * @type SmartCardHSMKey[]
1970  * @return the list of keys
1971  */
1972 SmartCardHSM.prototype.getKeys = function() {
1973 	if (typeof(this.idlist) == "undefined") {
1974 		this.enumerateKeys();
1975 	}
1976 
1977 	var keylist = [];
1978 	for (var i in this.idmap) {
1979 		keylist.push(this.idmap[i]);
1980 	}
1981 	return keylist;
1982 }
1983 
1984 
1985 
1986 /**
1987  * Get crypto object
1988  *
1989  * @type HSMCrypto
1990  * @return the HSMCrypto object
1991  */
1992 SmartCardHSM.prototype.getCrypto = function() {
1993 	if (this.crypto == undefined) {
1994 		this.crypto = new SmartCardHSMCrypto(new Crypto());
1995 	}
1996 	return this.crypto;
1997 }
1998 
1999 
2000 
2001 /**
2002  * @private
2003  */
2004 SmartCardHSM.prototype.getTokenInfo = function() {
2005 	if (this.tokenInfo != undefined) {
2006 		return this.tokenInfo;
2007 	}
2008 
2009 	if (!this.hasFile(SmartCardHSM.EF_TokenInfo)) {
2010 		return;
2011 	}
2012 
2013 	var bin = this.readBinary(SmartCardHSM.EF_TokenInfo);
2014 	this.tokenInfo = new ASN1(bin);
2015 	return this.tokenInfo;
2016 }
2017 
2018 
2019 
2020 /**
2021  * Get Token Label
2022  *
2023  * @type String
2024  * @return the token label from CIAInfo
2025  */
2026 SmartCardHSM.prototype.getLabel = function() {
2027 	var ti = this.getTokenInfo();
2028 	if (!ti) {
2029 		return;
2030 	}
2031 
2032 	var a = ti.find(0x80);
2033 	if (!a) {
2034 		return;
2035 	}
2036 	return a.value.toString(UTF8);
2037 }
2038 
2039 
2040 
2041 /**
2042  * @private
2043  */
2044 SmartCardHSM.prototype.getStaticTokenInfo = function() {
2045 	if (this.staticTokenInfo != undefined) {
2046 		return this.staticTokenInfo;
2047 	}
2048 
2049 	if (!this.hasFile(SmartCardHSM.EF_StaticTokenInfo)) {
2050 		return;
2051 	}
2052 
2053 	var bin = this.readBinary(SmartCardHSM.EF_StaticTokenInfo);
2054 	this.staticTokenInfo = new ASN1(bin);
2055 	return this.staticTokenInfo;
2056 }
2057 
2058 
2059 
2060 /**
2061  * Get ProvisioningURL
2062  *
2063  * @type String
2064  * @return the configured ProvisioningURL or undefined
2065  */
2066 SmartCardHSM.prototype.getProvisioningURL = function() {
2067 	var ti = this.getStaticTokenInfo();
2068 	if (!ti) {
2069 		return;
2070 	}
2071 
2072 	var a = ti.find(0x80);
2073 	if (!a) {
2074 		return;
2075 	}
2076 	return a.value.toString(UTF8);
2077 }
2078 
2079 
2080 
2081 /**
2082  * Get Key Check Value of Token Management Key
2083  *
2084  * @type ByteString
2085  * @return the configured KCV of the Token Management Key or undefined
2086  */
2087 SmartCardHSM.prototype.getTokenManagementKeyKCV = function() {
2088 	var ti = this.getStaticTokenInfo();
2089 	if (!ti) {
2090 		return;
2091 	}
2092 
2093 	var a = ti.find(0x81);
2094 	if (!a) {
2095 		return;
2096 	}
2097 	return a.value;
2098 }
2099 
2100 
2101 
2102 /**
2103  * Get salt for SO-PIN derivation using  the Token Management Key
2104  *
2105  * @type ByteString
2106  * @return the configured salt
2107  */
2108 SmartCardHSM.prototype.getTokenManagementKeySalt = function() {
2109 	var ti = this.getStaticTokenInfo();
2110 	if (!ti) {
2111 		return;
2112 	}
2113 
2114 	var a = ti.find(0x82);
2115 	if (!a) {
2116 		return;
2117 	}
2118 	return a.value;
2119 }
2120 
2121 
2122 
2123 /**
2124  * Create crypto object implementing access to the SmartCard-HSM
2125  *
2126  * @class Wrapper to provide Crypto interface to SmartCard-HSM
2127  * @constructor
2128  * @param {Crypto} crypto the backend crypto provider
2129  */
2130 function SmartCardHSMCrypto(crypto) {
2131 	this.crypto = crypto;
2132 }
2133 
2134 
2135 
2136 /**
2137  * Sign a message using the defined mechanism and key
2138  *
2139  * @param {HSMKey} key the private key
2140  * @param {Number} mech the mechanism (e.g. Crypto.ECDSA)
2141  * @param {ByteString} message the message to be signed
2142  * @type ByteString
2143  * @return the signature
2144  */
2145 SmartCardHSMCrypto.prototype.sign = function(key, mech, message) {
2146 	if (key instanceof SmartCardHSMKey) {
2147 		return key.sign(mech, message);
2148 	} else {
2149 		return this.crypto.sign(key, mech, message);
2150 	}
2151 }
2152 
2153 
2154 
2155 /**
2156  * Decrypt a message using the defined mechanism and key
2157  *
2158  * @param {HSMKey} key the private key
2159  * @param {Number} mech the mechanism (e.g. Crypto.RSA_PKCS1)
2160  * @param {ByteString} data the cryptogram
2161  * @param {ByteString} iv the initialization vector for symmetric ciphers
2162  * @type ByteString
2163  * @return the plain text
2164  */
2165 SmartCardHSMCrypto.prototype.decrypt = function(key, mech, data, iv) {
2166 	if (key instanceof SmartCardHSMKey) {
2167 		return key.decrypt(mech, data);
2168 	} else {
2169 		return this.crypto.decrypt(key, mech, data, iv);
2170 	}
2171 }
2172 
2173 
2174 
2175 /**
2176  * Verify a message using the defined mechanism and key
2177  *
2178  * @param {Key} key the public key
2179  * @param {Number} mech the mechanism (e.g. Crypto.ECDSA)
2180  * @param {ByteString} message the message to be signed
2181  * @param {ByteString} signature the signature to verify
2182  * @type Boolean
2183  * @return true if signature is valid
2184  */
2185 SmartCardHSMCrypto.prototype.verify = function(key, mech, message, signature) {
2186 	return this.crypto.verify(key, mech, message, signature);
2187 }
2188 
2189 
2190 
2191 /**
2192  * Create a key access object
2193  *
2194  * @class Class implementing key access
2195  * @param {SmartCardHSM} sc the card access object
2196  * @param {Number} id the key identifier
2197  */
2198 function SmartCardHSMKey(sc, id) {
2199 	this.sc = sc;
2200 	this.id = id;
2201 	if (this.sc.useExternalHashInECDSA) {
2202 		this.crypto = new Crypto();
2203 	}
2204 }
2205 
2206 exports.SmartCardHSMKey = SmartCardHSMKey;
2207 
2208 
2209 /**
2210  * Set the PKCS#15 private key description
2211  *
2212  * @param {ASN1} desc the description
2213  */
2214 SmartCardHSMKey.prototype.setDescription = function(desc) {
2215 	this.desc = desc;
2216 }
2217 
2218 
2219 
2220 /**
2221  * Return the key identifier
2222  *
2223  * @type Number
2224  * @return the key identifier
2225  */
2226 SmartCardHSMKey.prototype.getId = function() {
2227 	return this.id;
2228 }
2229 
2230 
2231 
2232 /**
2233  * Return the key label as encoded in the PKCS#15 structure
2234  *
2235  * @type String
2236  * @return the key label
2237  */
2238 SmartCardHSMKey.prototype.getLabel = function() {
2239 	if (this.desc == undefined) {
2240 		return undefined;
2241 	}
2242 	if ((this.desc.get(0).elements == 0) || this.desc.get(0).get(0).tag != 0x0C) {
2243 		return undefined;
2244 	}
2245 
2246 	return this.desc.get(0).get(0).value.toString(UTF8);
2247 }
2248 
2249 
2250 
2251 /**
2252  * Return the key id as encoded in the PKCS#15 structure
2253  *
2254  * @type ByteString
2255  * @return the key identifier
2256  */
2257 SmartCardHSMKey.prototype.getPKCS15Id = function() {
2258 	if (this.desc == undefined) {
2259 		return undefined;
2260 	}
2261 	return this.desc.get(1).get(0).value;
2262 }
2263 
2264 
2265 
2266 /**
2267  * Return the key size in bits
2268  *
2269  * @type Number
2270  * @return the key size in bits
2271  */
2272 SmartCardHSMKey.prototype.getSize = function() {
2273 	if (this.desc == undefined) {
2274 		return undefined;
2275 	}
2276 //	GPSystem.trace(this.desc);
2277 	if (this.desc.get(2).elements > 1) {	// Fix a bug from early versions
2278 		return this.desc.get(2).get(1).value.toUnsigned();
2279 	} else {
2280 		return this.desc.get(2).get(0).get(1).value.toUnsigned();
2281 	}
2282 }
2283 
2284 
2285 
2286 /**
2287  * Return the key size in bits
2288  *
2289  * @type Number
2290  * @return the key size in bits
2291  */
2292 SmartCardHSMKey.prototype.getType = function() {
2293 	if (this.desc == undefined) {
2294 		return undefined;
2295 	}
2296 
2297 	if (this.desc.tag == 0xA0) {
2298 		return "EC";
2299 	} else if (this.desc.tag == 0x30) {
2300 		return "RSA";
2301 	} else if (this.desc.tag == 0xA8) {
2302 		return "AES";
2303 	}
2304 
2305 	return undefined;
2306 }
2307 
2308 
2309 
2310 /**
2311  * Sign data using a key in the SmartCard-HSM
2312  *
2313  * @param {Number} mech the signing mechanism
2314  * @param {ByteString} data to be signed
2315  * @type ByteString
2316  * @return the signature
2317  */
2318 SmartCardHSMKey.prototype.sign = function(mech, data) {
2319 	var algo;
2320 	if (mech) {
2321 		switch(mech) {
2322 		case Crypto.RSA:
2323 			algo = 0x20;
2324 			break;
2325 		case Crypto.RSA_SHA1:
2326 			algo = 0x31;
2327 			break;
2328 		case Crypto.RSA_SHA256:
2329 			algo = 0x33;
2330 			break;
2331 		case Crypto.RSA_PKCS1:
2332 			algo = 0x20;
2333 			var keysize = this.getSize();
2334 			if (!keysize) {
2335 				throw new GPError(module.id, GPError.INVALID_DATA, 0, "Can't determine key size");
2336 			}
2337 			data = PKCS1.encode_EMSA_V15(keysize, data);
2338 			break;
2339 //		case Crypto.RSA_PSS:
2340 		case 0x80:
2341 			algo = 0x40;
2342 			break;
2343 		case Crypto.RSA_PSS_SHA1:
2344 			algo = 0x41;
2345 			break;
2346 		case Crypto.RSA_PSS_SHA256:
2347 			algo = 0x43;
2348 			break;
2349 		case Crypto.ECDSA:
2350 			algo = 0x70;
2351 			break;
2352 		case Crypto.ECDSA_SHA1:
2353 			if (this.sc.useExternalHashInECDSA) {
2354 				algo = 0x70;
2355 				var data = this.crypto.digest(Crypto.SHA_1, data);
2356 			} else {
2357 				algo = 0x71;
2358 			}
2359 			break;
2360 		case Crypto.ECDSA_SHA224:
2361 			if (this.sc.useExternalHashInECDSA) {
2362 				algo = 0x70;
2363 				var data = this.crypto.digest(Crypto.SHA_224, data);
2364 			} else {
2365 				algo = 0x72;
2366 			}
2367 			break;
2368 		case Crypto.ECDSA_SHA256:
2369 			if (this.sc.useExternalHashInECDSA) {
2370 				algo = 0x70;
2371 				var data = this.crypto.digest(Crypto.SHA_256, data);
2372 			} else {
2373 				algo = 0x73;
2374 			}
2375 			break;
2376 		case Crypto.AES_CMAC:
2377 			return this.sc.deriveSymmetricKey(this.id, SmartCardHSM.ALG_CMAC, data);
2378 		default:
2379 			throw new GPError("SmartCardHSMKey", GPError.INVALID_DATA, mech, "Unsupported crypto mechanism");
2380 		}
2381 	}
2382 
2383 	return this.sc.sign(this.id, algo, data);
2384 }
2385 
2386 
2387 
2388 /**
2389  * Decrypt data using a key in the SmartCard-HSM
2390  *
2391  * @param {Number} mech the decipher mechanism
2392  * @param {ByteString} data to be deciphered
2393  * @type ByteString
2394  * @return the plain message
2395  */
2396 SmartCardHSMKey.prototype.decrypt = function(mech, data) {
2397 	var algo;
2398 	if (mech) {
2399 		switch(mech) {
2400 		case Crypto.RSA:
2401 			break;
2402 		case Crypto.RSA_PKCS1:
2403 			break;
2404 		case Crypto.RSA_OAEP_SHA224:
2405 			algo = Crypto.SHA_224;
2406 			break;
2407 		case Crypto.RSA_OAEP_SHA256:
2408 			algo = Crypto.SHA_256;
2409 			break;
2410 		case Crypto.RSA_OAEP_SHA384:
2411 			algo = Crypto.SHA_384;
2412 			break;
2413 		case Crypto.RSA_OAEP_SHA512:
2414 			algo = Crypto.SHA_512;
2415 			break;
2416 		default:
2417 			throw new GPError("SmartCardHSMKey", GPError.INVALID_DATA, mech, "Unsupported crypto mechanism");
2418 		}
2419 	}
2420 
2421 	var em = this.sc.decipher(this.id, 0x21, data);
2422 
2423 	var plain = em;
2424 
2425 	if (mech != Crypto.RSA) {
2426 		if (mech == Crypto.RSA_PKCS1) {
2427 			var plain = PKCS1.decode_EME_V15(em);
2428 		} else {
2429 			var crypto = this.sc.getCrypto().crypto;
2430 
2431 			var plain = PKCS1.decode_EME_OAEP(crypto, null, algo, em);
2432 		}
2433 
2434 		if (!plain) {
2435 			throw new GPError("SmartCardHSMKey", GPError.CRYPTO_FAILED, mech, "Decryption failed");
2436 		}
2437 	}
2438 
2439 	return plain;
2440 }
2441 
2442 
2443 
2444 /**
2445  * Return human readable string
2446  */
2447 SmartCardHSMKey.prototype.toString = function() {
2448 	return "SmartCardHSMKey(id=" + this.id + ")";
2449 }
2450 
2451 
2452 
2453 /**
2454  * Initialize SmartCard-HSM
2455  *
2456  * @class Class implementing the device initialization methods
2457  * @param {Card} card the card object
2458  */
2459 function SmartCardHSMInitializer(card) {
2460 	this.card = card;
2461 	this.initializationCode = new ByteString("57621880", ASCII);
2462 	this.userPIN = new ByteString("648219", ASCII);
2463 	this.userPINSet = false;
2464 	this.useDefaultUserPIN = true;
2465 	this.retryCounterInitial = 3;
2466 	this.options = 0x0001;
2467 	this.keyshares = -1;
2468 	this.keyDomains = -1;
2469 	this.numberOfPublicKeys = 0;
2470 	this.requiredPublicKeysForAuthentication = 0;
2471 	this.bioslot = [];
2472 	this.label = undefined;
2473 }
2474 
2475 exports.SmartCardHSMInitializer = SmartCardHSMInitializer;
2476 
2477 
2478 
2479 /**
2480  * Set the initialization code
2481  *
2482  * @param {ByteString} initializationCode an 8 byte code
2483  */
2484 SmartCardHSMInitializer.prototype.setInitializationCode = function(initializationCode) {
2485 	if (!(initializationCode instanceof ByteString)) {
2486 		throw new GPError("SmartCardHSMInitializer", GPError.INVALID_DATA, 1, "initializationCode must be a ByteString");
2487 	}
2488 	if (initializationCode.length != 8) {
2489 		throw new GPError("SmartCardHSMInitializer", GPError.INVALID_DATA, 1, "initializationCode must have 8 bytes");
2490 	}
2491 
2492 	this.initializationCode = initializationCode;
2493 }
2494 
2495 
2496 
2497 /**
2498  * Set the User PIN
2499  *
2500  * @param {ByteString} userPIN a 6 to 16 byte code
2501  */
2502 SmartCardHSMInitializer.prototype.setUserPIN = function(userPIN) {
2503 	if (!(userPIN instanceof ByteString)) {
2504 		throw new GPError("SmartCardHSMInitializer", GPError.INVALID_DATA, 1, "userPIN must be a ByteString");
2505 	}
2506 	if ((userPIN.length < 6) || (userPIN.length > 16)) {
2507 		throw new GPError("SmartCardHSMInitializer", GPError.INVALID_DATA, 1, "userPIN must be between 6 and 16 bytes");
2508 	}
2509 
2510 	this.userPIN = userPIN;
2511 	this.userPINSet = true;
2512 	this.useDefaultUserPIN = false;
2513 }
2514 
2515 
2516 
2517 /**
2518  * Set the retry counter
2519  *
2520  * The SmartCard-HSM enforces a retry counter <= 3 for PIN length 6
2521  * The SmartCard-HSM enforces a retry counter <= 5 for PIN length 7
2522  * The SmartCard-HSM enforces a retry counter <= 10 for PIN length larger than 7
2523  *
2524  * @param {Number} retryCounterInitial in the range 1 to 10.
2525  */
2526 SmartCardHSMInitializer.prototype.setRetryCounterInitial = function(retryCounterInitial) {
2527 	if (typeof(retryCounterInitial) != "number") {
2528 		throw new GPError("SmartCardHSMInitializer", GPError.INVALID_DATA, 1, "retryCounterInitial must be a number");
2529 	}
2530 	if ((retryCounterInitial < 1) || (retryCounterInitial > 10)) {
2531 		throw new GPError("SmartCardHSMInitializer", GPError.INVALID_DATA, 1, "retryCounterInitial must be between 1 and 10");
2532 	}
2533 	this.retryCounterInitial = retryCounterInitial;
2534 }
2535 
2536 
2537 
2538 /**
2539  * Set the number of DKEK shares
2540  *
2541  * @param {Number} keyshares number of DKEK shares in the range 0 to 255
2542  */
2543 SmartCardHSMInitializer.prototype.setDKEKShares = function(keyshares) {
2544 	if (typeof(keyshares) != "number") {
2545 		throw new GPError("SmartCardHSMInitializer", GPError.INVALID_DATA, 1, "keyshares must be a number");
2546 	}
2547 	if ((keyshares < 0) || (keyshares > 255)) {
2548 		throw new GPError("SmartCardHSMInitializer", GPError.INVALID_DATA, 1, "keyshares must be between 0 and 255");
2549 	}
2550 	this.keyshares = keyshares;
2551 	this.keyDomains = -1;
2552 }
2553 
2554 
2555 
2556 /**
2557  * Set the number of key domains
2558  *
2559  * @param {Number} keyDomains number of key domains
2560  */
2561 SmartCardHSMInitializer.prototype.setKeyDomains = function(keyDomains) {
2562 	if (typeof(keyDomains) != "number") {
2563 		throw new GPError("SmartCardHSMInitializer", GPError.INVALID_DATA, 1, "keyDomains must be a number");
2564 	}
2565 
2566 	this.keyDomains = keyDomains;
2567 	this.keyshares = -1;
2568 }
2569 
2570 
2571 
2572 /**
2573  * Enable or disable RESET RETRY COUNTER command
2574  *
2575  * @param {Boolean} enable true (default) to allow RESET RETRY COUNTER command to reset user PIN using the initialization code
2576  */
2577 SmartCardHSMInitializer.prototype.setResetRetryCounterMode = function(enable) {
2578 	if (typeof(enable) == "undefined") {
2579 		var enable = false;
2580 	}
2581 
2582 	this.options = (this.options & 0xFFFE) + (enable ? 1 : 0);
2583 }
2584 
2585 
2586 
2587 /**
2588  * Enable or disable transport PIN mode
2589  *
2590  * @param {Boolean} enable true (non-default) to set user PIN to transport state
2591  */
2592 SmartCardHSMInitializer.prototype.setTransportPINMode = function(enable) {
2593 	if (typeof(enable) == "undefined") {
2594 		var enable = true;
2595 	}
2596 
2597 	this.options = (this.options & 0xFFFD) + (enable ? 2 : 0);
2598 }
2599 
2600 
2601 
2602 /**
2603  * Enable or disable session PIN mode
2604  *
2605  * @param {Number} 0 - disable, 1 - enable with clear-on-reset 3 - enable with explicit clearing
2606  */
2607 SmartCardHSMInitializer.prototype.setSessionPINMode = function(mode) {
2608 	assert(typeof(mode) == "number", "Argument mode must be number");
2609 	assert(mode >= 0 && mode <= 3 && mode != 2, "Argument mode must be 0, 1 or 3");
2610 
2611 	this.options = (this.options & 0xFFF3) + (mode << 2);
2612 }
2613 
2614 
2615 
2616 /**
2617  * Enable or disable replacing of a PKA key
2618  *
2619  * @param {Boolean} enable true (non-default) to allow replacing of a PKA key
2620  */
2621 SmartCardHSMInitializer.prototype.setReplacePKAKeyMode = function(enable) {
2622 	if (typeof(enable) == "undefined") {
2623 		var enable = false;
2624 	}
2625 
2626 	this.options = (this.options & 0xFFF7) + (enable ? 8 : 0);
2627 }
2628 
2629 
2630 
2631 /**
2632  * Enable the combined authentication mode of user pin and public key authentication.
2633  *
2634  * @param {Boolean} enable true (non-default) to require public key authentication and user authentication
2635  */
2636 SmartCardHSMInitializer.prototype.setCombinedAuthenticationMode = function(enable) {
2637 	if (typeof(enable) == "undefined") {
2638 		var enable = false;
2639 	}
2640 
2641 	this.options = (this.options & 0xFFEF) + (enable ? 16 : 0);
2642 }
2643 
2644 
2645 
2646 /**
2647  * If enabled RESET RETRY COUNTER only resets the error counter.
2648  * Otherwise  RRC allows changing the PIN
2649  *
2650  * @param {Boolean} resetOnly true to only reset the error counter, false otherwise (default)
2651  */
2652 SmartCardHSMInitializer.prototype.setResetRetryCounterResetOnlyMode = function(resetOnly) {
2653 	if (typeof(resetOnly) == "undefined") {
2654 		var resetOnly = false;
2655 	}
2656 
2657 	this.options = (this.options & 0xFFDF) + (resetOnly ? 32 : 0);
2658 }
2659 
2660 
2661 
2662 /**
2663  * Set parameter for public key authentication with n-of-m scheme, namely the values for n and m
2664  *
2665  * @param {Number} requiredPublicKeysForAuthentication number of key that must be authenticated for access
2666  * @param {Number} numberOfPublicKeys to register
2667  */
2668 SmartCardHSMInitializer.prototype.setPublicKeyAuthenticationParameter = function(requiredPublicKeysForAuthentication, numberOfPublicKeys) {
2669 	if ((numberOfPublicKeys < 1) || (numberOfPublicKeys > 90)) {
2670 		throw new GPError("SmartCardHSMInitializer", GPError.INVALID_DATA, 1, "numberOfPublicKeys must be between 1 and 90");
2671 	}
2672 	if ((requiredPublicKeysForAuthentication < 1) || (requiredPublicKeysForAuthentication > numberOfPublicKeys)) {
2673 		throw new GPError("SmartCardHSMInitializer", GPError.INVALID_DATA, 2, "requiredPublicKeysForAuthentication must be between 1 and " + numberOfPublicKeys);
2674 	}
2675 	this.numberOfPublicKeys = numberOfPublicKeys;
2676 	this.requiredPublicKeysForAuthentication = requiredPublicKeysForAuthentication;
2677 	this.useDefaultUserPIN = false;
2678 }
2679 
2680 
2681 
2682 /**
2683  * Select the biometric matching server for a one of the biometric templates
2684  *
2685  * @param {Number} slot either 0 or 1 for first or second template
2686  * @param {ByteString} aid the application identifier of the on-card biometric server
2687  * @param {Number} param one byte parameter passed to the server during initialization
2688  */
2689 SmartCardHSMInitializer.prototype.setBioTemplate = function(slot, aid, param) {
2690 	assert(typeof(slot) == "number", "slot must be a number");
2691 	assert(slot >= 0 && slot <= 1, "slot must be either 0 or 1");
2692 	assert(aid instanceof ByteString, "aid must be a ByteString");
2693 	assert(typeof(param) == "number", "param must be a number");
2694 	assert(param >= 0 && param <= 255, "param must be between 0 and 255");
2695 
2696 	this.bioslot[slot] = { aid: aid, param: param };
2697 	this.useDefaultUserPIN = false;
2698 }
2699 
2700 
2701 
2702 /**
2703  * Set the label to be written to a minimal CIAInfo in EF 2F03
2704  *
2705  * @param {String} label the label
2706  */
2707 SmartCardHSMInitializer.prototype.setLabel = function(label) {
2708 	this.label = label;
2709 }
2710 
2711 
2712 
2713 /**
2714  * Set the provisioning URL to be written to fixed parameter in CB00.
2715  *
2716  * @param {String} provisioningURL the URL at which this SE will be provisioned
2717  */
2718 SmartCardHSMInitializer.prototype.setProvisioningURL = function(provisioningURL) {
2719 	this.provisioningURL = provisioningURL;
2720 }
2721 
2722 
2723 
2724 /**
2725  * Set the key check value of the token management key and the optional salt
2726  * used for SO-PIN derivation
2727  *
2728  * @param {ByteString} kcv the key check value of the token management key
2729  * @param {ByteString} salt the salt used to derive the SO-PIN
2730  */
2731 SmartCardHSMInitializer.prototype.setTokenManagementKey = function(kcv, salt) {
2732 	this.tokenManagementKeyKCV = kcv;
2733 	this.tokenManagementKeySalt = salt;
2734 }
2735 
2736 
2737 
2738 /**
2739  * Perform Initialization
2740  */
2741 SmartCardHSMInitializer.prototype.initialize = function() {
2742 	var s = new ASN1(0x30,	new ASN1(0x80, ByteString.valueOf(this.options, 2)));
2743 
2744 	if (this.userPINSet || this.useDefaultUserPIN) {
2745 		s.add(new ASN1(0x81, this.userPIN));
2746 	}
2747 
2748 	s.add(new ASN1(0x82, this.initializationCode));
2749 
2750 	if (this.userPINSet || this.useDefaultUserPIN) {
2751 		s.add(new ASN1(0x91, ByteString.valueOf(this.retryCounterInitial)));
2752 	}
2753 
2754 	if (this.keyshares != -1) {
2755 		s.add(new ASN1(0x92, ByteString.valueOf(this.keyshares)));
2756 	}
2757 
2758 	if (this.keyDomains != -1) {
2759 		s.add(new ASN1(0x97, ByteString.valueOf(this.keyDomains)));
2760 	}
2761 
2762 	if (this.numberOfPublicKeys > 0) {
2763 		s.add(new ASN1(0x93, ByteString.valueOf(this.numberOfPublicKeys).concat(ByteString.valueOf(this.requiredPublicKeysForAuthentication))));
2764 	}
2765 
2766 	if (this.bioslot[0]) {
2767 		var o = this.bioslot[0];
2768 		s.add(new ASN1(0x95, ByteString.valueOf(o.param).concat(o.aid)));
2769 	}
2770 
2771 	if (this.bioslot[1]) {
2772 		var o = this.bioslot[1];
2773 		s.add(new ASN1(0x96, ByteString.valueOf(o.param).concat(o.aid)));
2774 	}
2775 
2776 	this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x50, 0x00, 0x00, s.value, [0x9000, 0x6A84]);
2777 
2778 	if (this.card.SW == 0x6A84) {
2779 		// Due to the nature of the JCRE, a first call to initialize may run out of memory,
2780 		// as the garbage collector for the removed objects is only run during the next
2781 		// APDU invocation.
2782 		this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x50, 0x00, 0x00, s.value, [0x9000]);
2783 	}
2784 
2785 	if (this.label) {
2786 		var a = new ASN1(0x30,
2787 				new ASN1(0x54, new ByteString("0000", HEX)),
2788 				new ASN1(0x53,
2789 					new ASN1(0x30,
2790 						new ASN1(0x02, new ByteString("00", HEX)),
2791 						new ASN1(0x80, new ByteString(this.label, UTF8)),
2792 						new ASN1(0x03, new ByteString("0500", HEX)))
2793 				)
2794 			);
2795 
2796 		var p1 = SmartCardHSM.EF_TokenInfo.byteAt(0);
2797 		var p2 = SmartCardHSM.EF_TokenInfo.byteAt(1);
2798 		this.card.sendSecMsgApdu(Card.ALL, 0x00, 0xD7, p1, p2, a.value, [0x9000]);
2799 	}
2800 
2801 	if (this.provisioningURL || this.tokenManagementKeyKCV || this.tokenManagementKeySalt) {
2802 		var l = new ASN1(ASN1.SEQUENCE);
2803 		if (this.provisioningURL) {
2804 			l.add(new ASN1(0x80, new ByteString(this.provisioningURL, UTF8)));
2805 		}
2806 		if (this.tokenManagementKeyKCV) {
2807 			l.add(new ASN1(0x81, this.tokenManagementKeyKCV));
2808 		}
2809 		if (this.tokenManagementKeySalt) {
2810 			l.add(new ASN1(0x82, this.tokenManagementKeySalt));
2811 		}
2812 
2813 		var a = new ASN1(0x30,
2814 				new ASN1(0x54, new ByteString("0000", HEX)),
2815 				new ASN1(0x53, l)
2816 			);
2817 
2818 		var p1 = SmartCardHSM.EF_StaticTokenInfo.byteAt(0);
2819 		var p2 = SmartCardHSM.EF_StaticTokenInfo.byteAt(1);
2820 		this.card.sendSecMsgApdu(Card.ALL, 0x00, 0xD7, p1, p2, a.value, [0x9000]);
2821 	}
2822 }
2823 
2824 
2825 
2826 /**
2827  * Create a key specification generator instance
2828  *
2829  * @class Class implementing an encoder for the C-Data required in GENERATE ASYMMETRIC KEY PAIR
2830  * @param {Number} keytype must be either Crypto.RSA, Crypto.EC or Crypto.AES
2831  * @param {Number/Key} keysizeOrDP must be 1024, 1536, 2048, 3072 or 4096 for RSA, 128, 192 or 256 for AES and key object with Key.ECC_CURVE_OID set for EC
2832  */
2833 function SmartCardHSMKeySpecGenerator(keytype, keysizeOrDP) {
2834 	this.keytype = keytype;
2835 
2836 	switch(keytype) {
2837 		case Crypto.RSA:
2838 			if (typeof(keysizeOrDP) != "number") {
2839 				throw new GPError("SmartCardHSMKeySpecGenerator", GPError.INVALID_DATA, 3, "keysizeIdDP must be of a number for RSA keys");
2840 			}
2841 			this.keysize = keysizeOrDP;
2842 			this.defaultAlgo = new ByteString("id-TA-RSA-v1-5-SHA-256", OID);
2843 			break;
2844 		case Crypto.EC:
2845 			if ((typeof(keysizeOrDP) != "object") || !(keysizeOrDP instanceof Key)) {
2846 				throw new GPError("SmartCardHSMKeySpecGenerator", GPError.INVALID_DATA, 3, "keysizeIdDP must be a Key instance");
2847 			}
2848 			this.domainParameter = keysizeOrDP;
2849 			this.defaultAlgo = new ByteString("id-TA-ECDSA-SHA-256", OID);
2850 			break;
2851 		case Crypto.AES:
2852 			if (typeof(keysizeOrDP) != "number") {
2853 				throw new GPError("SmartCardHSMKeySpecGenerator", GPError.INVALID_DATA, 3, "keysizeIdDP must be of a number for AES keys");
2854 			}
2855 			this.keysize = keysizeOrDP;
2856 			break;
2857 		default:
2858 			throw new GPError("SmartCardHSMKeySpecGenerator", GPError.INVALID_DATA, 3, "keytype must be Crypto.RSA or Crypto.EC");
2859 	}
2860 	this.CHR = new PublicKeyReference("UTDUMMY00001");
2861 	this.innerCAR = new PublicKeyReference("UTDUMMY00001");
2862 }
2863 
2864 exports.SmartCardHSMKeySpecGenerator = SmartCardHSMKeySpecGenerator;
2865 
2866 
2867 
2868 /**
2869  * Set key use counter for key
2870  *
2871  * @param {keyUseCounter} keyUseCounter in the range 1 to 2^64 - 2
2872  */
2873 SmartCardHSMKeySpecGenerator.prototype.setKeyUseCounter = function(keyUseCounter) {
2874 	if ((keyUseCounter < 0) || (keyUseCounter >= 0xFFFFFFFF)) {
2875 		throw new GPError("SmartCardHSMKeySpecGenerator", GPError.INVALID_DATA, 1, "keyUseCounter must be between 0 and 0xFFFFFFFF");
2876 	}
2877 	this.keyUseCounter = keyUseCounter;
2878 }
2879 
2880 
2881 
2882 /**
2883  * Set key domain
2884  *
2885  * @param {Number} keyDomain the key domain to which the key shall be added
2886  */
2887 SmartCardHSMKeySpecGenerator.prototype.setKeyDomain = function(keyDomain) {
2888 	this.keyDomain = keyDomain;
2889 }
2890 
2891 
2892 
2893 /**
2894  * Set wrapping key
2895  *
2896  * @param {Number} wrappingKey the key to used for wrapping a newly generated symmetric key
2897  */
2898 SmartCardHSMKeySpecGenerator.prototype.setWrappingKey = function(wrappingKey) {
2899 	this.wrappingKey = wrappingKey;
2900 }
2901 
2902 
2903 
2904 /**
2905  * Set algorithm list
2906  *
2907  * @param {ByteString} algorithms the list of algorithms allowed for this key
2908  */
2909 SmartCardHSMKeySpecGenerator.prototype.setAlgorithms = function(algorithms) {
2910 	this.algorithms = algorithms;
2911 }
2912 
2913 
2914 
2915 /**
2916  * Set certificate holder reference for key
2917  *
2918  * @param {PublicKeyReference} CHR certificate holder reference
2919  */
2920 SmartCardHSMKeySpecGenerator.prototype.setCHR = function(CHR) {
2921 	this.CHR = CHR;
2922 }
2923 
2924 
2925 
2926 /**
2927  * Set certificate holder reference of CA this request shall be sent to
2928  *
2929  * @param {PublicKeyReference} CAR certificate holder reference
2930  */
2931 SmartCardHSMKeySpecGenerator.prototype.setInnerCAR = function(CAR) {
2932 	this.innerCAR = CAR;
2933 }
2934 
2935 
2936 
2937 /**
2938  * Set holder reference of the key signing this request
2939  *
2940  * @param {PublicKeyReference} CAR certificate holder reference
2941  */
2942 SmartCardHSMKeySpecGenerator.prototype.setOuterCAR = function(CAR) {
2943 	this.outerCAR = CAR;
2944 }
2945 
2946 
2947 
2948 /**
2949  * @private
2950  */
2951 SmartCardHSMKeySpecGenerator.prototype.encodeRSAKeySpec = function() {
2952 	var p = new ASN1("Public Key", 0x7F49,
2953 			new ASN1("Object Identifier", 0x06, this.defaultAlgo),
2954 			new ASN1("Public Key Exponent", 0x82, ByteString.valueOf(65537)),
2955 			new ASN1("Key Size", 0x02, ByteString.valueOf(this.keysize))
2956 		);
2957 	return p;
2958 }
2959 
2960 
2961 
2962 /**
2963  * @private
2964  */
2965 SmartCardHSMKeySpecGenerator.prototype.encodeECKeySpec = function() {
2966 	// Encode G
2967 	var bb = new ByteBuffer();
2968 	// uncompressed encoding
2969 	bb.append(new ByteString("04", HEX));
2970 	bb.append(this.domainParameter.getComponent(Key.ECC_GX));
2971 	bb.append(this.domainParameter.getComponent(Key.ECC_GY));
2972 	var G = bb.toByteString();
2973 
2974 	var p = new ASN1("Public Key", 0x7F49,
2975 			new ASN1("Object Identifier", 0x06, this.defaultAlgo),
2976 			new ASN1("Prime Modulus", 0x81, this.domainParameter.getComponent(Key.ECC_P)),
2977 			new ASN1("First coefficient a", 0x82, this.domainParameter.getComponent(Key.ECC_A)),
2978 			new ASN1("Second coefficient b", 0x83, this.domainParameter.getComponent(Key.ECC_B)),
2979 			new ASN1("Base Point G", 0x84, G),
2980 			new ASN1("Order of the base point", 0x85, this.domainParameter.getComponent(Key.ECC_N)),
2981 			new ASN1("Cofactor f", 0x87, SmartCardHSM.stripLeadingZeros(this.domainParameter.getComponent(Key.ECC_H)))
2982 		);
2983 	return p;
2984 }
2985 
2986 
2987 
2988 /**
2989  * @private
2990  */
2991 SmartCardHSMKeySpecGenerator.prototype.encodeKeySpec = function() {
2992 	if (this.keytype == Crypto.RSA) {
2993 		return this.encodeRSAKeySpec();
2994 	} else {
2995 		return this.encodeECKeySpec();
2996 	}
2997 }
2998 
2999 
3000 
3001 /**
3002  * Return the encoded key specification
3003  *
3004  * @type ByteString
3005  * @return the encoded C-Data for GENERATE ASYMMETRIC KEY PAIR
3006  */
3007 SmartCardHSMKeySpecGenerator.prototype.encode = function() {
3008 	var t = new ASN1(0x30);
3009 
3010 	if (this.keytype != Crypto.AES) {
3011 		t.add(new ASN1("CPI", 0x5F29, new ByteString("00", HEX)));
3012 
3013 		if ((typeof(this.innerCAR) != "undefined") && (this.innerCAR)) {
3014 			t.add(new ASN1("CAR", 0x42, this.innerCAR.getBytes()));
3015 		}
3016 
3017 		t.add(this.encodeKeySpec());
3018 		t.add(new ASN1("CHR", 0x5F20, this.CHR.getBytes()));
3019 
3020 		if (typeof(this.outerCAR) != "undefined") {
3021 			t.add(new ASN1("OuterCAR", 0x45, this.outerCAR.getBytes()));
3022 		}
3023 	}
3024 
3025 	if (typeof(this.keyUseCounter) != "undefined") {
3026 		t.add(new ASN1("Key use counter", 0x90, ByteString.valueOf(this.keyUseCounter, 4)));
3027 	}
3028 
3029 	if (typeof(this.algorithms) != "undefined") {
3030 		t.add(new ASN1("Algorithms", 0x91, this.algorithms));
3031 	}
3032 
3033 	if (typeof(this.keyDomain) != "undefined") {
3034 		t.add(new ASN1("KeyDomain", 0x92, ByteString.valueOf(this.keyDomain)));
3035 	}
3036 
3037 	if (typeof(this.wrappingKey) != "undefined") {
3038 		t.add(new ASN1("Wrapping Key", 0x93, ByteString.valueOf(this.wrappingKey)));
3039 	}
3040 
3041 	return t.value;
3042 }
3043 
3044 
3045 
3046 /**
3047  * Create a key specification generator instance for AES keys
3048  *
3049  * @class Class implementing an encoder for the C-Data required in Generate Symmetric Key
3050  * @param {ByteString} allowedAlgorithms the list of allowed algorithm identifier
3051  */
3052 function SmartCardHSMSymmetricKeySpecGenerator(allowedAlgorithms) {
3053 	this.algorithms = allowedAlgorithms;
3054 }
3055 
3056 exports.SmartCardHSMSymmetricKeySpecGenerator = SmartCardHSMSymmetricKeySpecGenerator;
3057 
3058 
3059 
3060 /**
3061  * Set key domain
3062  *
3063  * @param {Number} keyDomain the key domain to which the key shall be added
3064  */
3065 SmartCardHSMSymmetricKeySpecGenerator.prototype.setKeyDomain = function(keyDomain) {
3066 	this.keyDomain = keyDomain;
3067 }
3068 
3069 
3070 
3071 /**
3072  * Return the encoded AES key specification
3073  *
3074  * @type ByteString
3075  * @return the encoded C-Data for Generate Symmetric Key
3076  */
3077 SmartCardHSMSymmetricKeySpecGenerator.prototype.encode = function() {
3078 	var t = new ASN1(0x30);
3079 
3080 	t.add(new ASN1("Algorithms", 0x91, this.algorithms));
3081 
3082 	if (typeof(this.keyUseCounter) != "undefined") {
3083 		t.add(new ASN1("Key use counter", 0x90, ByteString.valueOf(this.keyUseCounter, 4)));
3084 	}
3085 
3086 	if (typeof(this.keyDomain) != "undefined") {
3087 		t.add(new ASN1("Key Domain", 0x92, ByteString.valueOf(this.keyDomain)));
3088 	}
3089 
3090 	if (typeof(this.wrappingKey) != "undefined") {
3091 		t.add(new ASN1("Wrapping Key", 0x93, this.wrappingKey));
3092 	}
3093 
3094 	return t.value;
3095 }
3096 
3097 
3098 
3099 SmartCardHSM.test = function() {
3100 	var crypto = new Crypto();
3101 	var card = new Card(_scsh3.reader);
3102 	var sc = new SmartCardHSM(card);
3103 
3104 	var sci = new SmartCardHSMInitializer(card);
3105 	sci.initialize();
3106 
3107 	var pubKey = sc.validateCertificateChain(crypto);
3108 	sc.openSecureChannel(crypto, pubKey);
3109 
3110 	sc.verifyUserPIN(sci.userPIN);
3111 
3112 	var kg = new SmartCardHSMKeySpecGenerator(Crypto.RSA, 1024);
3113 	sc.generateAsymmetricKeyPair(1, 0, kg.encode());
3114 
3115 	var dp = new Key();
3116 	dp.setComponent(Key.ECC_CURVE_OID, new ByteString("brainpoolP256r1", OID));
3117 
3118 	var kg = new SmartCardHSMKeySpecGenerator(Crypto.EC, dp);
3119 	sc.generateAsymmetricKeyPair(2, 0, kg.encode());
3120 
3121 	var list = sc.enumerateKeys();
3122 	GPSystem.trace("Keys on device: " + list);
3123 
3124 	var crypto = sc.getCrypto();
3125 	var message = new ByteString("Hello World", ASCII);
3126 
3127 	var key = sc.getKey(1);
3128 	var signature = crypto.sign(key, Crypto.RSA_SHA256, message);
3129 	GPSystem.trace("Signature: " + signature);
3130 
3131 	var key = sc.getKey(2);
3132 	var signature = crypto.sign(key, Crypto.ECDSA, message);
3133 	GPSystem.trace("Signature: " + signature);
3134 }
3135