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 			if (cert.byteAt(0) == 0x67) {
299 				var list = SmartCardHSM.parseCertificateList(cert);
300 				for (var i = 0; i < list.length; i++) {
301 					a.add(list[i].getASN1());
302 				}
303 				if (list.length == 1) {
304 					print("Adding device and DICA certificate to export");
305 					var devAutCert = this.sc.readBinary(SmartCardHSM.C_DevAut);
306 					var list = SmartCardHSM.parseCertificateList(devAutCert);
307 					for (var i = 0; i < list.length; i++) {
308 						a.add(list[i].getASN1());
309 					}
310 				}
311 			} else {
312 				a.add(new ASN1(cert));
313 			}
314 		}
315 	}
316 	catch(e) {
317 		print("Ignoring meta data or certificate: " + e);
318 	}
319 
320 	return a.getBytes();
321 }
322 
323 
324 
325 /**
326  * Import a RSA key blob
327  *
328  * @param {String} label the key label
329  * @param {ByteString} keyblob the binary key in SmartCard-HSM format
330  * @param {Number} keysize in bits
331  * @param {Number/ByteString} keyid the optional PKCS#15 key identifier.
332  * Default value is the next free key id of the SmartCard-HSM.
333  * @type SmartCardHSMKey
334  */
335 HSMKeyStore.prototype.importRSAKey = function(label, keyblob, keysize, keyid) {
336 	var keytype = keyblob.byteAt(8);
337 	if ((keytype != 5) && (keytype != 6)) {
338 		throw new GPError(module.id, GPError.INVALID_DATA, 0, "keyblob does not contain a RSA key");
339 	}
340 
341 	var key = this.sc.getKey(label);
342 	if (key) {
343 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "A key with label " + label + " does already exist");
344 	}
345 	var newkid = this.sc.determineFreeKeyId();
346 
347 	this.sc.unwrapKey(newkid, keyblob);
348 
349 	if (typeof(keyid) == "undefined") {
350 		keyid = newkid;
351 	}
352 
353 	var keydesc = SmartCardHSM.buildPrkDforRSA(keyid, label, keysize);
354 
355 	var fid = ByteString.valueOf((SmartCardHSM.PRKDPREFIX << 8) + newkid);
356 	this.sc.updateBinary(fid, 0, keydesc.getBytes());
357 
358 	var hkey = new SmartCardHSMKey(this.sc, newkid);
359 	hkey.setDescription(keydesc);
360 	this.sc.addKeyToMap(hkey);
361 
362 	return hkey;
363 }
364 
365 
366 
367 /**
368  * Import an ECC key blob
369  *
370  * @param {String} label the key label
371  * @param {ByteString} keyblob the binary key in SmartCard-HSM format
372  * @param {Number} keysize in bits
373  * @param {Number/ByteString} keyid the optional PKCS#15 key identifier.
374  * Default value is the next free key id of the SmartCard-HSM.
375  * @type SmartCardHSMKey
376  */
377 HSMKeyStore.prototype.importECCKey = function(label, keyblob, keysize, keyid) {
378 	var keytype = keyblob.byteAt(8);
379 	if (keytype != 12) {
380 		throw new GPError(module.id, GPError.INVALID_DATA, 0, "keyblob does not contain an ECC key");
381 	}
382 	var key = this.sc.getKey(label);
383 	if (key) {
384 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "A key with label " + label + " does already exist");
385 	}
386 	var newkid = this.sc.determineFreeKeyId();
387 
388 	this.sc.unwrapKey(newkid, keyblob);
389 
390 	if (typeof(keyid) == "undefined") {
391 		keyid = newkid;
392 	}
393 
394 	var keydesc = SmartCardHSM.buildPrkDforECC(keyid, label, keysize);
395 
396 	var fid = ByteString.valueOf((SmartCardHSM.PRKDPREFIX << 8) + newkid);
397 	this.sc.updateBinary(fid, 0, keydesc.getBytes());
398 
399 	var hkey = new SmartCardHSMKey(this.sc, newkid);
400 	hkey.setDescription(keydesc);
401 	this.sc.addKeyToMap(hkey);
402 
403 	return hkey;
404 }
405 
406 
407 
408 /**
409  * Import an AES key blob
410  *
411  * @param {String} label the key label
412  * @param {ByteString} keyblob the binary key in SmartCard-HSM format
413  * @param {Number} keysize in bits
414  * @param {ByteString} keyid the PKCS#15 key id (CKA_ID)
415  * @type
416  */
417 HSMKeyStore.prototype.importAESKey = function(label, keyblob, keysize, keyid) {
418 
419 	var key = this.sc.getKey(label);
420 	if (key) {
421 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "A key with label " + label + " does already exist");
422 	}
423 	var newkid = this.sc.determineFreeKeyId();
424 
425 	this.sc.unwrapKey(newkid, keyblob);
426 
427 	if (typeof(keyid) == "undefined") {
428 		keyid = newkid;
429 	}
430 
431 	var keydesc = SmartCardHSM.buildSKDforAES(keyid, label, keysize);
432 
433 	var fid = ByteString.valueOf((SmartCardHSM.PRKDPREFIX << 8) + newkid);
434 	this.sc.updateBinary(fid, 0, keydesc.getBytes());
435 
436 	var hkey = new SmartCardHSMKey(this.sc, newkid);
437 	hkey.setDescription(keydesc);
438 	this.sc.addKeyToMap(hkey);
439 
440 	return hkey;
441 }
442 
443 
444 
445 /**
446  * Store certificate under given label
447  *
448  * @param {String/Number/Key} labelOrIdOrKey the label, id or object of the key for which the certificate should be stored
449  * @param {X509} cert the certificate
450  */
451 HSMKeyStore.prototype.storeEndEntityCertificate = function(labelOrIdOrKey, cert) {
452 	var key = labelOrIdOrKey;
453 	if (!(key instanceof SmartCardHSMKey)) {
454 		key = this.getKey(labelOrIdOrKey);
455 	}
456 
457 	if (key) {
458 		var kid = key.getId();
459 	} else {
460 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Could not find a key with label " + label);
461 	}
462 
463 	var fid = ByteString.valueOf((SmartCardHSM.EECERTIFICATEPREFIX << 8) + kid);
464 	if (!(cert instanceof ByteString)) {
465 		cert = cert.getBytes();
466 	}
467 	this.sc.updateBinary(fid, 0, cert);
468 }
469 
470 
471 
472 /**
473  * Store CA certificate under given label
474  *
475  * @param {String} label the label under which the certificate shall be stored
476  * @param {X509} cert the certificate
477  */
478 HSMKeyStore.prototype.storeCACertificate = function(label, cert) {
479 	this.sc.enumerateCACertificates();
480 	var id = this.sc.caidmap[label];
481 	if (id == undefined) {
482 		id = this.sc.determineFreeCAId();
483 	}
484 
485 	var fid = ByteString.valueOf((SmartCardHSM.CACERTIFICATEPREFIX << 8) + id);
486 	this.sc.updateBinary(fid, 0, cert.getBytes());
487 
488 	var descr = SmartCardHSM.buildCertDescription(label, null, cert.getPublicKey(), fid);
489 	var fid = ByteString.valueOf((SmartCardHSM.CERTDPREFIX << 8) + id);
490 	this.sc.updateBinary(fid, 0, descr.getBytes());
491 	this.sc.addCACertificateToMap(cert, id, label);
492 }
493 
494 
495 
496 /**
497  * Delete CA certificate with given label
498  *
499  * @param {String} label the label of certificate to be removed
500  */
501 HSMKeyStore.prototype.deleteCACertificate = function(label) {
502 	var cert = this.sc.getCACertificate(label);
503 
504 	if (!cert) {
505 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Could not find a certificate with label " + label);
506 	}
507 
508 	var fid = ByteString.valueOf((SmartCardHSM.CERTDPREFIX << 8) + cert.id);
509 	this.sc.deleteFile(fid);
510 	var fid = ByteString.valueOf((SmartCardHSM.CACERTIFICATEPREFIX << 8) + cert.id);
511 	this.sc.deleteFile(fid);
512 	this.sc.enumerateCACertificates();
513 }
514 
515 
516 
517 /**
518  * Delete key and certificate with given label
519  *
520  * @param {String/Number/Key} labelOrIdOrKey the label, id or object of the key to be removed
521  */
522 HSMKeyStore.prototype.deleteKey = function(labelOrIdOrKey) {
523 	var key = labelOrIdOrKey;
524 	if (!(key instanceof SmartCardHSMKey)) {
525 		key = this.getKey(labelOrIdOrKey);
526 	}
527 
528 	if (key) {
529 		var kid = key.getId();
530 	} else {
531 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Could not find a key with label " + labelOrIdOrKey);
532 	}
533 
534 	var fid = ByteString.valueOf((SmartCardHSM.KEYPREFIX << 8) + kid);
535 	this.sc.deleteFile(fid);
536 
537 	try	{
538 		var fid = ByteString.valueOf((SmartCardHSM.PRKDPREFIX << 8) + kid);
539 		this.sc.deleteFile(fid);
540 
541 		var fid = ByteString.valueOf((SmartCardHSM.EECERTIFICATEPREFIX << 8) + kid);
542 		this.sc.deleteFile(fid);
543 	}
544 	catch(e) {
545 		// Ignore
546 	}
547 
548 	this.enumerateKeys();
549 }
550 
551 
552 
553 /**
554  * Return list of keys
555  *
556  * @type String[]
557  * @return the list of key names
558  */
559 HSMKeyStore.prototype.enumerateKeys = function() {
560 	return this.sc.enumerateKeys();
561 }
562 
563 
564 
565 /**
566  * Check if key with label exists
567  *
568  * @param {String / Number} the key label or id
569  * @type Boolean
570  * @return true if key exists
571  */
572 HSMKeyStore.prototype.hasKey = function(labelOrId) {
573 	var key = this.sc.getKey(labelOrId);
574 	return key != null;
575 }
576 
577 
578 
579 /**
580  * Get key for given label
581  *
582  * @param {String / Number} the key label or id
583  * @type Key
584  * @return the key
585  */
586 HSMKeyStore.prototype.getKey = function(labelOrId) {
587 	var key = this.sc.getKey(labelOrId);
588 	if (!key) {
589 		throw new GPError("HSMKeyStore", GPError.INVALID_DATA, 0, "Could not find a key with label/id " + labelOrId);
590 	}
591 	return key;
592 }
593 
594 
595 
596 /**
597  * Check if key has a certificate
598  *
599  * @param {String/Number/Key} labelOrIdOrKey the certificate label, id or key
600  * @type Boolean
601  * @return true of a certificate is present
602  */
603 HSMKeyStore.prototype.hasCertificate = function(labelOrIdOrKey) {
604 	var key = labelOrIdOrKey;
605 	if (!(key instanceof SmartCardHSMKey)) {
606 		key = this.getKey(labelOrIdOrKey);
607 	}
608 	var kid = key.getId();
609 	var fid = ByteString.valueOf((SmartCardHSM.EECERTIFICATEPREFIX << 8) + kid);
610 	return this.sc.hasFile(fid);
611 }
612 
613 
614 
615 /**
616  * Get raw certificate for given label
617  *
618  * @param {String/Number/Key} labelOrIdOrKey the certificate label, id or key
619  * @type ByteString
620  * @return the certificate
621  */
622 HSMKeyStore.prototype.getCertificate = function(labelOrIdOrKey) {
623 	var key = labelOrIdOrKey;
624 	if (!(key instanceof SmartCardHSMKey)) {
625 		key = this.getKey(labelOrIdOrKey);
626 	}
627 	var kid = key.getId();
628 	var fid = ByteString.valueOf((SmartCardHSM.EECERTIFICATEPREFIX << 8) + kid);
629 	var certbin = this.sc.readBinary(fid);
630 	return certbin;
631 }
632 
633 
634 
635 /**
636  * Get certificate for given label
637  *
638  * @param {String/Number/Key} labelOrIdOrKey the certificate label, id or key
639  * @type X509
640  * @return the certificate
641  */
642 HSMKeyStore.prototype.getEndEntityCertificate = function(labelOrIdOrKey) {
643 	var certbin = this.getCertificate(labelOrIdOrKey);
644 	return new X509(certbin);
645 }
646