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