      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 Class implementing a key store for X.509 certificate and private keys stored on a SmartCard-HSM
     25  */
     26
     27 var PublicKeyReference = require('scsh/eac/PublicKeyReference').PublicKeyReference;
     28 var SmartCardHSM = require('scsh/sc-hsm/SmartCardHSM').SmartCardHSM;
     29 var SmartCardHSMKey = require('scsh/sc-hsm/SmartCardHSM').SmartCardHSMKey;
     30 var CVC = require("scsh/eac/CVC").CVC;
     31
     32
     33
     34 /**
     35  * Create a simple key store front-end
     36  *
     37  * @class Class implementing some simple access functions to generate key pairs and store certificates
     38  * @param {SmartCardHSM} sc the SmartCard-HSM card service
     39  */
     40 function HSMKeyStore(sc) {
     41 	this.sc = sc;
     42 	this.chr = new PublicKeyReference("UTNULL00000");
     43 	this.car = new PublicKeyReference("UTNULL00000");
     44 }
     45
     46 exports.HSMKeyStore = HSMKeyStore;
     47
     48
     49
     50 /**
     51  * Generate a key pair
     52  *
     53  * @param {String} label the label under which the key pair shall be stored
     54  * @param {SmartCardHSMKeySpecGenerator} initialized key spec generator
     55  * @type CVC
     56  * @return the authenticated request
     57  */
     58 HSMKeyStore.prototype.generateKeyPair = function(label, spec) {
     59
     60 	if ((spec.keytype != Crypto.RSA) && (spec.keytype != Crypto.EC)) {
     61 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Unsupported key type");
     62 	}
     63
     64 	var key = this.sc.getKey(label);
     65 	if (key) {
     66 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Key with label " + label + " does already exist");
     67 	}
     68
     69 	var newkid = this.sc.determineFreeKeyId();
     70 	var reqbin = this.sc.generateAsymmetricKeyPair(newkid, 0, spec.encode());
     71 	var req = new CVC(reqbin);
     72 	var keyid = req.determineKeyIdentifier();
     73
     74 	switch(spec.keytype) {
     75 		case Crypto.RSA:
     76 			var keydesc = SmartCardHSM.buildPrkDforRSA(keyid, label, spec.keysize);
     77 			break;
     78 		case Crypto.EC:
     79 			var keydesc = SmartCardHSM.buildPrkDforECC(keyid, label, spec.domainParameter.getSize());
     80 			break;
     81 		default:
     82 			throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Unsupported key type");
     83 	}
     84
     85 	var fid = ByteString.valueOf((SmartCardHSM.PRKDPREFIX << 8) + newkid);
     86 	this.sc.updateBinary(fid, 0, keydesc.getBytes());
     87
     88 	var hkey = new SmartCardHSMKey(this.sc, newkid);
     89 	hkey.setDescription(keydesc);
     90 	this.sc.addKeyToMap(hkey);
     91 	return req;
     92 }
     93
     94
     95
     96 /**
     97  * Generate a symmetric key
     98  *
     99  * @param {String} label the label under which the key shall be stored
    100  * @param {SmartCardHSMKeySpecGenerator} initialized key spec generator
    101  * @type ByteString
    102  * @return the new key wrapped with the symmetric key defined with SmartCardHSMKeySpecGenerator.setWrappingKey()
    103  */
    104 HSMKeyStore.prototype.generateKey = function(label, spec) {
    105
    106 	if (spec.keytype != Crypto.AES) {
    107 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Unsupported key type");
    108 	}
    109
    110 	var key = this.sc.getKey(label);
    111 	if (key) {
    112 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Key with label " + label + " does already exist");
    113 	}
    114
    115 	var newkid = this.sc.determineFreeKeyId();
    116
    117 	var genalg;
    118 	switch(spec.keysize) {
    119 		case 128: genalg = 0xB0; break;
    120 		case 192: genalg = 0xB1; break;
    121 		case 256: genalg = 0xB2; break;
    122 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Unsupported key size");
    123 	}
    124
    125 	var wrapbin = this.sc.generateSymmetricKey(newkid, genalg, spec.encode());
    126
    127 	var deralg;
    128 	if (spec.algorithms.find(ByteString.valueOf(SmartCardHSM.ALG_CMAC)) >= 0) {
    129 		deralg = SmartCardHSM.ALG_CMAC;
    130 	} else if (spec.algorithms.find(ByteString.valueOf(SmartCardHSM.ALG_DERIVE_SP800_56C)) >= 0) {
    131 		deralg = SmartCardHSM.ALG_DERIVE_SP800_56C;
    132 	}
    133
    134 	var keyid;
    135 	if (deralg) {
    136 		keyid = this.sc.deriveSymmetricKey(newkid, deralg, new ByteString("KeyCheckValue", ASCII)).left(8);
    137 	} else {
    138 		keyid = ByteString.valueOf(newkid);
    139 	}
    140
    141 	var keydesc = SmartCardHSM.buildSKDforAES(keyid, label, spec.keysize);
    142
    143 	var fid = ByteString.valueOf((SmartCardHSM.PRKDPREFIX << 8) + newkid);
    144 	this.sc.updateBinary(fid, 0, keydesc.getBytes());
    145
    146 	var hkey = new SmartCardHSMKey(this.sc, newkid);
    147 	hkey.setDescription(keydesc);
    148 	this.sc.addKeyToMap(hkey);
    149 	return wrapbin;
    150 }
    151
    152
    153
    154 /**
    155  * Generate a RSA key pair
    156  *
    157  * @param {String} label the label under which the key pair shall be stored
    158  * @param {Number} keysize the key size in bits (1024, 1536 or 2048)
    159  */
    160 HSMKeyStore.prototype.generateRSAKeyPair = function(label, keysize) {
    161
    162 	var key = this.sc.getKey(label);
    163 	if (key) {
    164 		var newkid = key.getId();
    165 	} else {
    166 		var newkid = this.sc.determineFreeKeyId();
    167 	}
    168
    169 	var algo = new ByteString("id-TA-RSA-v1-5-SHA-256", OID);
    170
    171 	var keydata = SmartCardHSM.buildGAKPwithRSA(this.car, algo, this.chr, keysize);
    172 	var keydesc = SmartCardHSM.buildPrkDforRSA(newkid, label, keysize);
    173
    174 	var reqbin = this.sc.generateAsymmetricKeyPair(newkid, 0, keydata);
    175
    176 	var fid = ByteString.valueOf((SmartCardHSM.PRKDPREFIX << 8) + newkid);
    177 	this.sc.updateBinary(fid, 0, keydesc.getBytes());
    178 	var req = new CVC(reqbin);
    179
    180 	var hkey = new SmartCardHSMKey(this.sc, newkid);
    181 	hkey.setDescription(keydesc);
    182 	this.sc.addKeyToMap(hkey);
    183 	return req;
    184 }
    185
    186
    187
    188 /**
    189  * Generate an ECDSA key pair
    190  *
    191  * @param {String} label the label under which the key pair shall be stored
    192  * @param {String} curve the curve object identifier
    193  */
    194 HSMKeyStore.prototype.generateECCKeyPair = function(label, curve) {
    195
    196 	var key = this.sc.getKey(label);
    197 	if (key) {
    198 		var newkid = key.getId();
    199 	} else {
    200 		var newkid = this.sc.determineFreeKeyId();
    201 	}
    202
    203 	var algo = new ByteString("id-TA-ECDSA-SHA-256", OID);
    204
    205 	var dp = new Key();
    206 	dp.setComponent(Key.ECC_CURVE_OID, new ByteString(curve, OID));
    207
    208 	var keydata = SmartCardHSM.buildGAKPwithECC(this.car, algo, this.chr, dp);
    209 //	print("Keysize: " + dp.getSize());
    210 	var keydesc = SmartCardHSM.buildPrkDforECC(newkid, label, dp.getSize());
    211
    212 	var reqbin = this.sc.generateAsymmetricKeyPair(newkid, 0, keydata);
    213
    214 	var fid = ByteString.valueOf((SmartCardHSM.PRKDPREFIX << 8) + newkid);
    215 	this.sc.updateBinary(fid, 0, keydesc.getBytes());
    216 	var req = new CVC(reqbin);
    217
    218 	var hkey = new SmartCardHSMKey(this.sc, newkid);
    219 	hkey.setDescription(keydesc);
    220 	this.sc.addKeyToMap(hkey);
    221
    222 	return req;
    223 }
    224
    225
    226
    227 /**
    228  * Import a key blob, meta data and certificate
    229  *
    230  * @param {ByteString} keywrap the binary key in SmartCard-HSM format
    231  */
    232 HSMKeyStore.prototype.importKey = function(keywrap) {
    233
    234 	var a = new ASN1(keywrap);
    235
    236 	var wrap = a.get(0).value;
    237 	var id = this.sc.determineFreeKeyId();
    238
    239 	if (id < 0) {
    240 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Key identifier exhausted");
    241 	}
    242
    243 	this.sc.unwrapKey(id, wrap);
    244
    245 	var hkey = new SmartCardHSMKey(this.sc, id);
    246
    247 	if (a.elements > 1) {
    248 		var meta = a.get(1);
    249 		this.sc.updateBinary(ByteString.valueOf((SmartCardHSM.PRKDPREFIX << 8) + id), 0, meta.getBytes());
    250 		hkey.setDescription(meta);
    251 	}
    252
    253 	var bin = new ByteString("", HEX);
    254 	for (var i = 2; i < a.elements; i++) {
    255 		var cert = a.get(i);
    256 		bin = bin.concat(cert.getBytes());
    257 	}
    258 	this.sc.updateBinary(ByteString.valueOf((SmartCardHSM.EECERTIFICATEPREFIX << 8) + id), 0, bin);
    259
    260 	this.sc.addKeyToMap(hkey);
    261
    262 	return hkey;
    263 }
    264
    265
    266
    267 /**
    268  * Export a key blob, meta data and certificate
    269  *
    270  * @param {String/Number/Key} labelOrIdOrKey the label, id or object of the key to be removed
    271  * @type ByteString
    272  * @return the blob with key, meta data and certificate
    273  */
    274 HSMKeyStore.prototype.exportKey = function(labelOrIdOrKey) {
    275
    276 	var key = labelOrIdOrKey;
    277 	if (!(key instanceof SmartCardHSMKey)) {
    278 		key = this.getKey(labelOrIdOrKey);
    279 	}
    280
    281 	if (key) {
    282 		var id = key.getId();
    283 	} else {
    284 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Could not find a key with label or id " + labelOrIdOrKey);
    285 	}
    286
    287 	var wrap = this.sc.wrapKey(id);
    288 	var a = new ASN1(0x30, new ASN1(0x04, wrap));
    289
    290 	try	{
    291 		var meta = this.sc.readBinary(ByteString.valueOf((SmartCardHSM.PRKDPREFIX << 8) + id));
    292 		a.add(new ASN1(meta));
    293
    294 		var fid = ByteString.valueOf((SmartCardHSM.EECERTIFICATEPREFIX << 8) + id);
    295 		if (this.sc.hasFile(fid)) {
    296 			var cert = this.sc.readBinary(fid);
    297
    298 			// Copy list of CVCs
    299 			if ((cert.byteAt(0) == 0x67) || (cert.byteAt(0) == 0x7F)) {
    300 				var list = SmartCardHSM.parseCertificateList(cert);
    301 				for (var i = 0; i < list.length; i++) {
    302 					a.add(list[i].getASN1());
    303 				}
    304 				if ((cert.byteAt(0) == 0x67) && (list.length == 1)) {
    305 					print("Adding device and DICA certificate to export");
    306 					var devAutCert = this.sc.readBinary(SmartCardHSM.C_DevAut);
    307 					var list = SmartCardHSM.parseCertificateList(devAutCert);
    308 					for (var i = 0; i < list.length; i++) {
    309 						a.add(list[i].getASN1());
    310 					}
    311 				}
    312 			} else {
    313 				a.add(new ASN1(cert));
    314 			}
    315 		}
    316 	}
    317 	catch(e) {
    318 		print("Ignoring meta data or certificate: " + e);
    319 	}
    320
    321 	return a.getBytes();
    322 }
    323
    324
    325
    326 /**
    327  * Import a RSA key blob
    328  *
    329  * @param {String} label the key label
    330  * @param {ByteString} keyblob the binary key in SmartCard-HSM format
    331  * @param {Number} keysize in bits
    332  * @param {Number/ByteString} keyid the optional PKCS#15 key identifier.
    333  * Default value is the next free key id of the SmartCard-HSM.
    334  * @type SmartCardHSMKey
    335  */
    336 HSMKeyStore.prototype.importRSAKey = function(label, keyblob, keysize, keyid) {
    337 	var keytype = keyblob.byteAt(8);
    338 	if ((keytype != 5) && (keytype != 6)) {
    339 		throw new GPError(module.id, GPError.INVALID_DATA, 0, "keyblob does not contain a RSA key");
    340 	}
    341
    342 	var key = this.sc.getKey(label);
    343 	if (key) {
    344 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "A key with label " + label + " does already exist");
    345 	}
    346 	var newkid = this.sc.determineFreeKeyId();
    347
    348 	this.sc.unwrapKey(newkid, keyblob);
    349
    350 	if (typeof(keyid) == "undefined") {
    351 		keyid = newkid;
    352 	}
    353
    354 	var keydesc = SmartCardHSM.buildPrkDforRSA(keyid, label, keysize);
    355
    356 	var fid = ByteString.valueOf((SmartCardHSM.PRKDPREFIX << 8) + newkid);
    357 	this.sc.updateBinary(fid, 0, keydesc.getBytes());
    358
    359 	var hkey = new SmartCardHSMKey(this.sc, newkid);
    360 	hkey.setDescription(keydesc);
    361 	this.sc.addKeyToMap(hkey);
    362
    363 	return hkey;
    364 }
    365
    366
    367
    368 /**
    369  * Import an ECC key blob
    370  *
    371  * @param {String} label the key label
    372  * @param {ByteString} keyblob the binary key in SmartCard-HSM format
    373  * @param {Number} keysize in bits
    374  * @param {Number/ByteString} keyid the optional PKCS#15 key identifier.
    375  * Default value is the next free key id of the SmartCard-HSM.
    376  * @type SmartCardHSMKey
    377  */
    378 HSMKeyStore.prototype.importECCKey = function(label, keyblob, keysize, keyid) {
    379 	var keytype = keyblob.byteAt(8);
    380 	if (keytype != 12) {
    381 		throw new GPError(module.id, GPError.INVALID_DATA, 0, "keyblob does not contain an ECC key");
    382 	}
    383 	var key = this.sc.getKey(label);
    384 	if (key) {
    385 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "A key with label " + label + " does already exist");
    386 	}
    387 	var newkid = this.sc.determineFreeKeyId();
    388
    389 	this.sc.unwrapKey(newkid, keyblob);
    390
    391 	if (typeof(keyid) == "undefined") {
    392 		keyid = newkid;
    393 	}
    394
    395 	var keydesc = SmartCardHSM.buildPrkDforECC(keyid, label, keysize);
    396
    397 	var fid = ByteString.valueOf((SmartCardHSM.PRKDPREFIX << 8) + newkid);
    398 	this.sc.updateBinary(fid, 0, keydesc.getBytes());
    399
    400 	var hkey = new SmartCardHSMKey(this.sc, newkid);
    401 	hkey.setDescription(keydesc);
    402 	this.sc.addKeyToMap(hkey);
    403
    404 	return hkey;
    405 }
    406
    407
    408
    409 /**
    410  * Import an AES key blob
    411  *
    412  * @param {String} label the key label
    413  * @param {ByteString} keyblob the binary key in SmartCard-HSM format
    414  * @param {Number} keysize in bits
    415  * @param {ByteString} keyid the PKCS#15 key id (CKA_ID)
    416  * @type
    417  */
    418 HSMKeyStore.prototype.importAESKey = function(label, keyblob, keysize, keyid) {
    419
    420 	var key = this.sc.getKey(label);
    421 	if (key) {
    422 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "A key with label " + label + " does already exist");
    423 	}
    424 	var newkid = this.sc.determineFreeKeyId();
    425
    426 	this.sc.unwrapKey(newkid, keyblob);
    427
    428 	if (typeof(keyid) == "undefined") {
    429 		keyid = newkid;
    430 	}
    431
    432 	var keydesc = SmartCardHSM.buildSKDforAES(keyid, label, keysize);
    433
    434 	var fid = ByteString.valueOf((SmartCardHSM.PRKDPREFIX << 8) + newkid);
    435 	this.sc.updateBinary(fid, 0, keydesc.getBytes());
    436
    437 	var hkey = new SmartCardHSMKey(this.sc, newkid);
    438 	hkey.setDescription(keydesc);
    439 	this.sc.addKeyToMap(hkey);
    440
    441 	return hkey;
    442 }
    443
    444
    445
    446 /**
    447  * Store certificate under given label
    448  *
    449  * @param {String/Number/Key} labelOrIdOrKey the label, id or object of the key for which the certificate should be stored
    450  * @param {X509} cert the certificate
    451  */
    452 HSMKeyStore.prototype.storeEndEntityCertificate = function(labelOrIdOrKey, cert) {
    453 	var key = labelOrIdOrKey;
    454 	if (!(key instanceof SmartCardHSMKey)) {
    455 		key = this.getKey(labelOrIdOrKey);
    456 	}
    457
    458 	if (key) {
    459 		var kid = key.getId();
    460 	} else {
    461 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Could not find a key with label " + label);
    462 	}
    463
    464 	var fid = ByteString.valueOf((SmartCardHSM.EECERTIFICATEPREFIX << 8) + kid);
    465 	if (!(cert instanceof ByteString)) {
    466 		cert = cert.getBytes();
    467 	}
    468 	this.sc.updateBinary(fid, 0, cert);
    469 }
    470
    471
    472
    473 /**
    474  * Store CA certificate under given label
    475  *
    476  * @param {String} label the label under which the certificate shall be stored
    477  * @param {X509} cert the certificate
    478  */
    479 HSMKeyStore.prototype.storeCACertificate = function(label, cert) {
    480 	this.sc.enumerateCACertificates();
    481 	var id = this.sc.caidmap[label];
    482 	if (id == undefined) {
    483 		id = this.sc.determineFreeCAId();
    484 	}
    485
    486 	var fid = ByteString.valueOf((SmartCardHSM.CACERTIFICATEPREFIX << 8) + id);
    487 	this.sc.updateBinary(fid, 0, cert.getBytes());
    488
    489 	var descr = SmartCardHSM.buildCertDescription(label, null, cert.getPublicKey(), fid);
    490 	var fid = ByteString.valueOf((SmartCardHSM.CERTDPREFIX << 8) + id);
    491 	this.sc.updateBinary(fid, 0, descr.getBytes());
    492 	this.sc.addCACertificateToMap(cert, id, label);
    493 }
    494
    495
    496
    497 /**
    498  * Delete CA certificate with given label
    499  *
    500  * @param {String} label the label of certificate to be removed
    501  */
    502 HSMKeyStore.prototype.deleteCACertificate = function(label) {
    503 	var cert = this.sc.getCACertificate(label);
    504
    505 	if (!cert) {
    506 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Could not find a certificate with label " + label);
    507 	}
    508
    509 	var fid = ByteString.valueOf((SmartCardHSM.CERTDPREFIX << 8) + cert.id);
    510 	this.sc.deleteFile(fid);
    511 	var fid = ByteString.valueOf((SmartCardHSM.CACERTIFICATEPREFIX << 8) + cert.id);
    512 	this.sc.deleteFile(fid);
    513 	this.sc.enumerateCACertificates();
    514 }
    515
    516
    517
    518 /**
    519  * Delete key and certificate with given label
    520  *
    521  * @param {String/Number/Key} labelOrIdOrKey the label, id or object of the key to be removed
    522  */
    523 HSMKeyStore.prototype.deleteKey = function(labelOrIdOrKey) {
    524 	var key = labelOrIdOrKey;
    525 	if (!(key instanceof SmartCardHSMKey)) {
    526 		key = this.getKey(labelOrIdOrKey);
    527 	}
    528
    529 	if (key) {
    530 		var kid = key.getId();
    531 	} else {
    532 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Could not find a key with label " + labelOrIdOrKey);
    533 	}
    534
    535 	var fid = ByteString.valueOf((SmartCardHSM.KEYPREFIX << 8) + kid);
    536 	this.sc.deleteFile(fid);
    537
    538 	try	{
    539 		var fid = ByteString.valueOf((SmartCardHSM.PRKDPREFIX << 8) + kid);
    540 		this.sc.deleteFile(fid);
    541
    542 		var fid = ByteString.valueOf((SmartCardHSM.EECERTIFICATEPREFIX << 8) + kid);
    543 		this.sc.deleteFile(fid);
    544 	}
    545 	catch(e) {
    546 		// Ignore
    547 	}
    548
    549 	this.enumerateKeys();
    550 }
    551
    552
    553
    554 /**
    555  * Return list of keys
    556  *
    557  * @type String[]
    558  * @return the list of key names
    559  */
    560 HSMKeyStore.prototype.enumerateKeys = function() {
    561 	return this.sc.enumerateKeys();
    562 }
    563
    564
    565
    566 /**
    567  * Check if key with label exists
    568  *
    569  * @param {String / Number} the key label or id
    570  * @type Boolean
    571  * @return true if key exists
    572  */
    573 HSMKeyStore.prototype.hasKey = function(labelOrId) {
    574 	var key = this.sc.getKey(labelOrId);
    575 	return key != null;
    576 }
    577
    578
    579
    580 /**
    581  * Get key for given label
    582  *
    583  * @param {String / Number} the key label or id
    584  * @type Key
    585  * @return the key
    586  */
    587 HSMKeyStore.prototype.getKey = function(labelOrId) {
    588 	var key = this.sc.getKey(labelOrId);
    589 	if (!key) {
    590 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Could not find a key with label/id " + labelOrId);
    591 	}
    592 	return key;
    593 }
    594
    595
    596
    597 /**
    598  * Check if key has a certificate
    599  *
    600  * @param {String/Number/Key} labelOrIdOrKey the certificate label, id or key
    601  * @type Boolean
    602  * @return true of a certificate is present
    603  */
    604 HSMKeyStore.prototype.hasCertificate = function(labelOrIdOrKey) {
    605 	var key = labelOrIdOrKey;
    606 	if (!(key instanceof SmartCardHSMKey)) {
    607 		key = this.getKey(labelOrIdOrKey);
    608 	}
    609 	var kid = key.getId();
    610 	var fid = ByteString.valueOf((SmartCardHSM.EECERTIFICATEPREFIX << 8) + kid);
    611 	return this.sc.hasFile(fid);
    612 }
    613
    614
    615
    616 /**
    617  * Get raw certificate for given label
    618  *
    619  * @param {String/Number/Key} labelOrIdOrKey the certificate label, id or key
    620  * @type ByteString
    621  * @return the certificate
    622  */
    623 HSMKeyStore.prototype.getCertificate = function(labelOrIdOrKey) {
    624 	var key = labelOrIdOrKey;
    625 	if (!(key instanceof SmartCardHSMKey)) {
    626 		key = this.getKey(labelOrIdOrKey);
    627 	}
    628 	var kid = key.getId();
    629 	var fid = ByteString.valueOf((SmartCardHSM.EECERTIFICATEPREFIX << 8) + kid);
    630 	var certbin = this.sc.readBinary(fid);
    631 	return certbin;
    632 }
    633
    634
    635
    636 /**
    637  * Get certificate for given label
    638  *
    639  * @param {String/Number/Key} labelOrIdOrKey the certificate label, id or key
    640  * @type X509
    641  * @return the certificate
    642  */
    643 HSMKeyStore.prototype.getEndEntityCertificate = function(labelOrIdOrKey) {
    644 	var certbin = this.getCertificate(labelOrIdOrKey);
    645 	return new X509(certbin);
    646 }
    647