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