1 /** 2 * --------- 3 * |.##> <##.| Open Smart Card Development Platform (www.openscdp.org) 4 * |# #| 5 * |# #| Copyright (c) 1999-2010 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 Simple CVC-CA 25 */ 26 27 28 // Imports 29 var CVC = require('scsh/eac/CVC').CVC; 30 var CVCertificateStore = require('scsh/eac/CVCertificateStore').CVCertificateStore; 31 var PublicKeyReference = require('scsh/eac/PublicKeyReference').PublicKeyReference; 32 var EAC2CVRequestGenerator = require('scsh/eac/EAC2CVRequestGenerator').EAC2CVRequestGenerator; 33 var EAC2CVCertificateGenerator = require('scsh/eac/EAC2CVCertificateGenerator').EAC2CVCertificateGenerator; 34 35 36 37 /** 38 * Creates a new CVC-CA instance 39 * 40 * @class Class supporting a certification authority that can issue CVC certificates 41 * for the EAC protocol. 42 * 43 * @constructor 44 * @param {Crypto} crypto the crypto provider to use 45 * @param {CVCertificateStore} certstore the certificate store to use 46 * @param {String} path the path of holderIDs (eg. "/UTCVCA/UTDVCA/UTTERM") 47 */ 48 function CVCCA(crypto, certstore, holderId, parentId, path) { 49 GPSystem.log(GPSystem.DEBUG, module.id, "new(" + crypto + "," + certstore + "," + holderId + "," + parentId + "," + path + ")"); 50 51 this.crypto = crypto; 52 this.certstore = certstore; 53 54 if (typeof(path) == "undefined") { // ToDo: Remove after migration 55 this.holderId = holderId; 56 this.parentId = parentId; 57 58 if (this.isRootCA()) { // CVCA 59 this.path = "/" + holderId; 60 } else { // DVCA 61 this.path = "/" + parentId + "/" + holderId; 62 } 63 } else { 64 this.path = path; 65 var pe = path.substr(1).split("/"); 66 var l = pe.length; 67 assert(l >= 1); 68 this.holderId = pe[l - 1]; 69 if (l > 1) { 70 this.parentId = pe[l - 2]; 71 } else { 72 this.parentId = this.holderId; 73 } 74 } 75 this.keyspec = new Key(); 76 this.keyspec.setComponent(Key.ECC_CURVE_OID, new ByteString("brainpoolP256r1", OID)); 77 this.taAlgorithmIdentifier = new ByteString("id-TA-ECDSA-SHA-256", OID); 78 this.countryseq = null; 79 } 80 81 exports.CVCCA = CVCCA; 82 83 84 85 /** 86 * Set factory generating EACCryptoProvider for private key operations (create, use, delete) 87 * 88 * @param {EACCryptoProvider} eaccp the EAC Crypto Provider for this instance 89 * @param {String} eaccpid the instance id 90 */ 91 CVCCA.prototype.setEACCryptoProviderFactory = function(eaccpf, eaccpid) { 92 this.eaccpf = eaccpf; 93 this.eaccpid = eaccpid; 94 } 95 96 97 98 /** 99 * Return a suitable crypto instance 100 * 101 */ 102 CVCCA.prototype.getCrypto = function() { 103 GPSystem.log(GPSystem.DEBUG, module.id, "getCrypto()"); 104 105 if (this.crypto) { 106 return this.crypto; 107 } 108 109 if (this.eaccpf) { 110 var eaccp = this.eaccpf.getEACCryptoProvider(this.eaccpid, true); 111 return eaccp.getCrypto(); 112 } 113 114 return this.certstore.getCrypto() 115 } 116 117 118 119 /** 120 * Returns true if this is a root CA 121 * 122 * @returns true if this is a root CA 123 * @type boolean 124 */ 125 CVCCA.prototype.isRootCA = function() { 126 GPSystem.log(GPSystem.DEBUG, module.id, "isRootCA()"); 127 128 return this.holderId == this.parentId; 129 } 130 131 132 133 /** 134 * Returns true if this CA has a certificate. 135 * 136 * @returns true if this CA is operational 137 * @type boolean 138 */ 139 CVCCA.prototype.hasCertificate = function() { 140 GPSystem.log(GPSystem.DEBUG, module.id, "hasCertificate()"); 141 142 var currentchr = this.certstore.getCurrentCHR(this.path); 143 return currentchr != null; 144 } 145 146 147 148 /** 149 * Returns true if this CA is operational. 150 * 151 * @returns true if this CA is operational 152 * @type boolean 153 */ 154 CVCCA.prototype.isOperational = function() { 155 GPSystem.log(GPSystem.DEBUG, module.id, "isOperational()"); 156 157 var currentchr = this.certstore.getCurrentCHR(this.path); 158 if (currentchr == null) { 159 return false; 160 } 161 var cvc = this.certstore.getCertificate(this.path, currentchr); 162 return !cvc.isExpired(); 163 } 164 165 166 167 /** 168 * Sets the key specification for generating requests 169 * 170 * @param {Key} keyparam a key object containing key parameters (e.g. EC Curve) 171 * @param {ByteString} algorithm the terminal authentication algorithm object identifier 172 */ 173 CVCCA.prototype.setKeySpec = function(keyparam, algorithm) { 174 GPSystem.log(GPSystem.DEBUG, module.id, "setKeySpec(" + keyparam + "," + algorithm + ")"); 175 176 this.keyspec = keyparam; 177 this.taAlgorithmIdentifier = algorithm; 178 } 179 180 181 182 /** 183 * Set flags that controls the removal of the previous key if the certificate for the new key is imported 184 * 185 * @param {boolean} removePreviousKey true to remove, false to keep 186 */ 187 CVCCA.prototype.setRemovePreviousKey = function(removePreviousKey) { 188 GPSystem.log(GPSystem.DEBUG, module.id, "setRemovePreviousKey(" + removePreviousKey + ")"); 189 190 this.removePreviousKey = removePreviousKey; 191 } 192 193 194 195 /** 196 * Set country code to be included in sequence number of public key reference 197 * 198 * @param {String} countryseq the two character country code 199 */ 200 CVCCA.prototype.setCountryCodeForSequence = function(countryseq) { 201 GPSystem.log(GPSystem.DEBUG, module.id, "setCountryCodeForSequence(" + countryseq + ")"); 202 203 this.countryseq = countryseq; 204 } 205 206 207 208 /** 209 * Return private key handle, either from EACCryptoProvider or Certificate Store 210 * 211 */ 212 CVCCA.prototype.getPrivateKey = function(path, chr) { 213 GPSystem.log(GPSystem.DEBUG, module.id, "getPrivateKey(" + path + "," + chr + ")"); 214 215 if (this.eaccpf) { 216 var eaccp = this.eaccpf.getEACCryptoProvider(this.eaccpid, true); 217 218 var blob = this.certstore.getSigner(path, chr); 219 var prkey = eaccp.getPrivateKey(path, chr, blob); 220 221 if (prkey && !blob) { // Have a key but no matching signer 222 GPSystem.log(GPSystem.DEBUG, module.id, "Signer " + chr + " not found in database, but on crypto device. Creating signer now."); 223 224 // Calculate current signer number 225 var seq = chr.getSequenceNo(); 226 var cnt = parseInt(seq.substr(-5), 10); // Full 5 digit sequence 227 if (isNaN(cnt)) { 228 var cnt = parseInt(seq.substr(-3), 10); // 3 Digit sequence number 229 } 230 231 GPSystem.log(GPSystem.DEBUG, module.id, "Setting signer number to " + cnt); 232 this.certstore.setSignerNo(path, cnt); 233 this.certstore.newSigner(path, chr); 234 } 235 return prkey; 236 } else { 237 return this.certstore.getPrivateKey(path, chr); 238 } 239 } 240 241 242 243 /** 244 * Generate a certificate request 245 * 246 * @param {PublicKeyReference} car the CA at which this request is addressed 247 * @param {boolean} forceInitial force an initial request, even if a current certificate is available 248 * @param {boolean} signinitial sign with initial key (sequence = 00000) 249 * @return the certificate request 250 * @type CVC 251 */ 252 CVCCA.prototype.generateRequest = function(car, forceinitial, signinitial) { 253 GPSystem.log(GPSystem.DEBUG, module.id, "generateRequest(" + car + "," + forceinitial + "," + signinitial + ")"); 254 255 if (typeof(this.certstore.sc) != "undefined") { 256 return this.generateRequestHSM(car, forceinitial, signinitial); 257 } 258 259 if (this.eaccpf) { 260 var eaccp = this.eaccpf.getEACCryptoProvider(this.eaccpid, true); 261 if (typeof(eaccp.generateRequest) == "function") { 262 return this.generateRequestHSMCP(eaccp, car, forceinitial, signinitial); 263 } 264 } 265 266 // Obtain key parameter 267 268 if (typeof(this.keyspec.getComponent(Key.ECC_P)) != "undefined") { 269 var prk = new Key(this.keyspec); 270 prk.setType(Key.PRIVATE); 271 var keyalg = Crypto.EC; 272 } else { 273 var prk = new Key(); 274 prk.setType(Key.PRIVATE); 275 var keyalg = Crypto.RSA; 276 } 277 var puk = new Key(this.keyspec); 278 puk.setType(Key.PUBLIC); 279 280 // Determine CHR 281 var currentchr = this.certstore.getCurrentCHR(this.path); 282 var nextchr = this.certstore.getNextCHR(this.path, this.countryseq); 283 284 // Generate key pair 285 if (this.eaccpf) { 286 var eaccp = this.eaccpf.getEACCryptoProvider(this.eaccpid, true); 287 eaccp.generateKeyPair(this.path, nextchr, keyalg, prk, puk); 288 } else { 289 this.certstore.generateKeyPair(this.path, nextchr, keyalg, prk, puk); 290 } 291 292 // Generate certificate request 293 var reqGenerator = new EAC2CVRequestGenerator(this.getCrypto()); 294 295 // Set CPI 296 reqGenerator.setProfileIdentifier(0x00); 297 298 // Set public key for request 299 reqGenerator.setPublicKey(puk); 300 301 // Set oid of algorithm 302 reqGenerator.setTAAlgorithmIdentifier(this.taAlgorithmIdentifier); 303 304 // Set CHR for the request 305 reqGenerator.setCHR(nextchr); 306 307 if ((typeof(car) != "undefined") && (car != null)) { 308 reqGenerator.setCAR(car); 309 } 310 311 if ((currentchr != null) && !forceinitial) { 312 var previousprk = this.getPrivateKey(this.path, currentchr); 313 var previouscvc = this.certstore.getCertificate(this.path, currentchr); 314 var req = reqGenerator.generateAuthenticatedCVRequest(prk, previousprk, currentchr, previouscvc.getPublicKeyOID()); 315 } else { 316 // Generate the request 317 if (signinitial) { 318 var initialchr = new PublicKeyReference(nextchr.getHolder() + "00000"); 319 var firstprk = this.getPrivateKey(this.path, initialchr); 320 var req = reqGenerator.generateAuthenticatedCVRequest(prk, firstprk, initialchr); 321 } else { 322 var req = reqGenerator.generateCVRequest(prk); 323 } 324 } 325 326 req = new CVC(req); 327 328 this.certstore.storeRequest(this.path, req); 329 330 return req; 331 } 332 333 334 335 /** 336 * Generate a certificate request using a SmartCard-HSM based private key 337 * 338 * @param {PublicKeyReference} car the CA at which this request is addressed 339 * @param {boolean} forceInitial force an initial request, even if a current certificate is available 340 * @param {boolean} signinitial sign with initial key (sequence = 00000) 341 * @return the certificate request 342 * @type CVC 343 */ 344 CVCCA.prototype.generateRequestHSM = function(car, forceinitial, signinitial) { 345 GPSystem.log(GPSystem.DEBUG, module.id, "generateRequestHSM(" + car + "," + forceinitial + "," + signinitial + ")"); 346 347 var req = this.certstore.generateRequest(this.path, car, forceinitial, signinitial, this.keyspec, this.taAlgorithmIdentifier, this.countryseq); 348 this.certstore.storeRequest(this.path, req); 349 350 return req; 351 } 352 353 354 355 /** 356 * Generate a certificate request using a SmartCard-HSM based private key via EACCryptoProvider 357 * 358 * @param {EACCryptoProvider} prov the EACCryptoProvider 359 * @param {PublicKeyReference} car the CA at which this request is addressed 360 * @param {boolean} forceInitial force an initial request, even if a current certificate is available 361 * @param {boolean} signinitial sign with initial key (sequence = 00000) 362 * @return the certificate request 363 * @type CVC 364 */ 365 CVCCA.prototype.generateRequestHSMCP = function(prov, car, forceinitial, signinitial) { 366 GPSystem.log(GPSystem.DEBUG, module.id, "generateRequestHSM(" + car + "," + forceinitial + "," + signinitial + ")"); 367 368 // Determine CHR 369 var currentchr = this.certstore.getCurrentCHR(this.path); 370 do { 371 var nextchr = this.certstore.getNextCHR(this.path, this.countryseq); 372 var prk = this.getPrivateKey(this.path, nextchr); 373 if (!prk) { 374 break; 375 } 376 GPSystem.log(GPSystem.INFO, module.id, "CHR " + nextchr + " already in use, skipping to next CHR"); 377 } while (true); 378 379 var req = prov.generateRequest(this.path, currentchr, nextchr, car, forceinitial, signinitial, this.keyspec, this.taAlgorithmIdentifier); 380 this.certstore.storeRequest(this.path, req); 381 this.certstore.newSigner(this.path, nextchr); 382 383 return req; 384 } 385 386 387 388 /** 389 * Counter-sign a request 390 * 391 * @param {CVC} req the initial request 392 * @return the certificate request 393 * @type CVC 394 */ 395 CVCCA.prototype.counterSignRequest = function(request) { 396 GPSystem.log(GPSystem.DEBUG, module.id, "counterSignRequest('" + request + "')"); 397 398 assert(!request.isAuthenticatedRequest()); 399 400 var car = this.certstore.getCurrentCHR(this.path); 401 assert(car != null); 402 403 var cacvc = this.certstore.getCertificate(this.path, car); 404 assert(cacvc != null); 405 406 var signingTAAlgorithmIdentifier = cacvc.getPublicKeyOID(); 407 var prk = this.getPrivateKey(this.path, car); 408 409 var req = EAC2CVRequestGenerator.signAuthenticatedCVRequest(this.getCrypto(), request.getASN1(), prk, car, signingTAAlgorithmIdentifier); 410 return new CVC(req); 411 } 412 413 414 415 /** 416 * Generate an initial certificate request 417 * 418 * @param {PublicKeyReference} car the CA at which this request is addressed 419 * @return the certificate request 420 * @type CVC 421 */ 422 CVCCA.prototype.generateInitialRequest = function(car) { 423 GPSystem.log(GPSystem.DEBUG, module.id, "generateInitialRequest(" + car + ")"); 424 425 return this.generateRequest(car, true, false); 426 } 427 428 429 430 /** 431 * Generate a signed initial certificate request 432 * 433 * @param {PublicKeyReference} car the CA at which this request is addressed 434 * @return the certificate request 435 * @type CVC 436 */ 437 CVCCA.prototype.generateSignedInitialRequest = function(car) { 438 GPSystem.log(GPSystem.DEBUG, module.id, "generateSignedInitialRequest(" + car + ")"); 439 440 return this.generateRequest(car, true, true); 441 } 442 443 444 445 /** 446 * Generate certificate for certificate request 447 * 448 * <p>Certificate contents is defined through the policy object:</p> 449 * <pre> 450 * var policy = { certificateValidityDays: 2, 451 * chatRoleOID: new ByteString("id-IS", OID), 452 * chatRights: new ByteString("E3", HEX), 453 * includeDomainParameter: true, 454 * extensions: [] 455 * }; 456 * </pre> 457 * 458 * @param {CVC} req the certificate request 459 * @param {Object} policy the object with policy settings 460 * @returns the certificate 461 * @type CVC 462 */ 463 CVCCA.prototype.generateCertificate = function(req, policy) { 464 GPSystem.log(GPSystem.DEBUG, module.id, "generateCertificate('" + req + "'" + policy + ")"); 465 466 var car = this.certstore.getCurrentCHR(this.path); 467 var maxExpDate = null; 468 469 if (car == null) { // No CA certificate found 470 if (this.isRootCA()) { 471 car = req.getCHR(); // Generate a self-signed root certificate 472 } else { 473 throw new GPError("CVCCA", GPError.INVALID_DATA, 0, "No current certificate found"); 474 } 475 if (policy.publicKeyOID) { 476 var signingTAAlgorithmIdentifier = policy.publicKeyOID; 477 } else { 478 var signingTAAlgorithmIdentifier = req.getPublicKeyOID(); 479 } 480 } else { 481 var cacvc = this.certstore.getCertificate(this.path, car); 482 var signingTAAlgorithmIdentifier = cacvc.getPublicKeyOID(); 483 if (policy.shellModelForExpirationDate) { 484 maxExpDate = cacvc.getCXD(); 485 } 486 } 487 488 var generator = new EAC2CVCertificateGenerator(this.getCrypto()); 489 generator.setCAR(car); 490 generator.setCHR(req.getCHR()); 491 var effDate = new Date(); 492 if (policy.ced) { 493 effDate = policy.ced; 494 } 495 effDate.setHours(12, 0, 0, 0); 496 var expDate = new Date((policy.certificateValidityDays - 1) * (1000 * 60 * 60 * 24) + effDate.getTime()); 497 expDate.setHours(12, 0, 0, 0); 498 499 if (maxExpDate != null) { 500 if (effDate.getTime() > maxExpDate.getTime()) { 501 throw new GPError("CVCCA", GPError.INVALID_DATA, 0, "CA certificate is expired"); 502 } 503 // Expiration date of issued certificate must not exceed expiration date of issuing CA 504 if (expDate.getTime() > maxExpDate.getTime()) { 505 expDate = maxExpDate; 506 } 507 } 508 509 generator.setEffectiveDate(effDate); 510 generator.setExpiryDate(expDate); 511 generator.setChatOID(policy.chatRoleOID); 512 generator.setChatAuthorizationLevel(policy.chatRights); 513 generator.setPublicKey(req.getPublicKey()); 514 generator.setProfileIdentifier(0x00); 515 if (policy.publicKeyOID) { 516 generator.setTAAlgorithmIdentifier(policy.publicKeyOID); 517 } else { 518 generator.setTAAlgorithmIdentifier(req.getPublicKeyOID()); 519 } 520 521 generator.setIncludeDomainParameters(policy.includeDomainParameter); 522 generator.setExtensions(policy.extensions); 523 var prk = this.getPrivateKey(this.path, car); 524 var cvc = generator.generateCVCertificate(prk, signingTAAlgorithmIdentifier); 525 526 return cvc; 527 } 528 529 530 531 /** 532 * Store issued certificate 533 * 534 * @param {CVC} cert a newly issued certificate 535 */ 536 CVCCA.prototype.storeCertificate = function(cert) { 537 GPSystem.log(GPSystem.DEBUG, module.id, "storeCertificate('" + cert + "')"); 538 539 var chrHolder = cert.getCHR().getHolder(); 540 this.certstore.storeCertificate(this.path + "/" + chrHolder, cert, false); 541 } 542 543 544 545 /** 546 * Remove previous key 547 * 548 * @param {PublicKeyReference} previous the previously used CHR 549 */ 550 CVCCA.prototype.removePreviouslyUsedKey = function(previous) { 551 GPSystem.log(GPSystem.DEBUG, module.id, "removePreviouslyUsedKey('" + previous + "')"); 552 553 if (previous.equals(this.certstore.getCurrentCHR(this.path))) { 554 GPSystem.log(GPSystem.INFO, module.id, "CHR " + previous + " is still the active key. Not deleting it"); 555 return; 556 } 557 558 if (this.eaccpf) { 559 var eaccp = this.eaccpf.getEACCryptoProvider(this.eaccpid, true); 560 eaccp.deletePrivateKey(this.path, previous); 561 } else { 562 this.certstore.deletePrivateKey(this.path, previous); 563 } 564 } 565 566 567 568 /** 569 * Import a certificate into the certificate store and make it the current certificate 570 * 571 * @param {CVC} cert the certificate 572 */ 573 CVCCA.prototype.importCertificate = function(cert) { 574 GPSystem.log(GPSystem.DEBUG, module.id, "importCertificate('" + cert + "')"); 575 576 var chr = cert.getCHR(); 577 var prk = this.getPrivateKey(this.path, chr); 578 if (prk == null) { 579 throw new GPError("CVCCA", GPError.INVALID_DATA, 0, "Invalid certificate, no matching private key"); 580 } 581 var c = this.certstore.getCertificate(this.path, cert.getCHR()); 582 if (c != null) { 583 GPSystem.log(GPSystem.INFO, module.id, "Certificate " + c + " already existing"); 584 } 585 586 // Save currentchr 587 var currentchr = this.certstore.getCurrentCHR(this.path); 588 589 if (this.isRootCA() && !this.isOperational()) { 590 this.certstore.storeCertificate(this.path, cert, (c == null)); 591 } else { 592 if (!this.certstore.insertCertificate(this.getCrypto(), cert, this.path)) { 593 throw new GPError("CVCCA", GPError.CRYPTO_FAILED, 0, "Could not validate certificate"); 594 } 595 } 596 if (this.removePreviousKey && currentchr) { 597 this.removePreviouslyUsedKey(currentchr); 598 } 599 } 600 601 602 603 /** 604 * Import a list of certificates into the certificate store 605 * 606 * @param {CVC[]} certs the list of certificates 607 */ 608 CVCCA.prototype.importCertificates = function(certs) { 609 GPSystem.log(GPSystem.DEBUG, module.id, "importCertificates('" + certs + "')"); 610 611 // Save currentchr 612 var currentchr = this.certstore.getCurrentCHR(this.path); 613 614 var list = this.certstore.insertCertificates(this.getCrypto(), certs, true, this.path); 615 616 if (this.removePreviousKey && currentchr) { 617 this.removePreviouslyUsedKey(currentchr); 618 } 619 620 return list; 621 } 622 623 624 625 /** 626 * Returns a list of relevant certificates. 627 * 628 * <p>If the CA is the root CA, then all self-signed and link certificates are returned.</p> 629 * <p>If the CA is a DVCA, then all certificates of the associated root and the current 630 * DVCA certificate is returned.</p> 631 * 632 * @param {PublicKeyReference} fromCAR the optional starting point for the list if not a root CA 633 */ 634 CVCCA.prototype.getCertificateList = function(fromCAR) { 635 GPSystem.log(GPSystem.DEBUG, module.id, "getCertificateList(" + fromCAR + ")"); 636 637 var list; 638 639 if (this.isRootCA()) { 640 list = this.certstore.listCertificates(this.path); 641 } else { 642 var path = this.path; 643 644 while(true) { 645 var chr = this.certstore.getCurrentCHR(path); 646 if (chr == null) { 647 var ofs = path.lastIndexOf("/"); 648 if (ofs == 0) { 649 list = []; 650 } else { 651 path = path.substr(0, ofs); 652 continue; 653 } 654 } else { 655 list = this.certstore.getCertificateChain(path, chr, fromCAR); 656 } 657 break; 658 } 659 } 660 661 return list; 662 } 663 664 665 666 /** 667 * Return certificate issued by this CA 668 * 669 * @param {PublicKeyReference} chr the certificate holder reference 670 * @returns the certificate or null if not found 671 * @type CVC 672 */ 673 CVCCA.prototype.getIssuedCertificate = function(chr) { 674 GPSystem.log(GPSystem.DEBUG, module.id, "getIssuedCertificate(" + chr + ")"); 675 676 var path = this.path + "/" + chr.getHolder(); 677 678 var cvc = this.certstore.getCertificate(path, chr); 679 if (cvc == null) { 680 GPSystem.trace("No certificate found for " + chr); 681 return null; 682 } 683 684 return cvc; 685 } 686 687 688 689 /** 690 * Return authentic public key with domain parameter for a given CHR subordinate to the CA 691 * 692 * @param {PublicKeyReference} chr the certificate holder reference 693 * @returns the public key or null 694 * @type Key 695 */ 696 CVCCA.prototype.getAuthenticPublicKey = function(chr) { 697 GPSystem.log(GPSystem.DEBUG, module.id, "getAuthenticPublicKey(" + chr + ")"); 698 699 var cvc = this.getIssuedCertificate(chr); 700 701 if (cvc == null) { 702 return null; 703 } 704 705 if (this.isRootCA()) { 706 var dp = this.certstore.getDomainParameter(cvc.getCAR()); 707 } else { 708 var dvcacvc = this.certstore.getCertificate(this.path, cvc.getCAR()); 709 if (dvcacvc == null) { 710 GPSystem.trace("No certificate found for " + cvc.getCAR()); 711 return null; 712 } 713 var dp = this.certstore.getDomainParameter(dvcacvc.getCAR()); 714 } 715 716 return(cvc.getPublicKey(dp)); 717 } 718 719 720 721 CVCCA.test = function(daofcvca, daofdvca, daofterm) { 722 723 var crypto = new Crypto(); 724 725 var ss = new CVCertificateStore(daofcvca); 726 ss.setContextMarker(0); 727 var cvca = new CVCCA(crypto, ss, null, null, "/UTCVCA"); 728 729 // Create a new request 730 var req = cvca.generateRequest(null, false); 731 GPSystem.trace("Request: " + req); 732 GPSystem.trace(req.getASN1()); 733 734 assert(req.verifyWith(crypto, req.getPublicKey())); 735 736 // Create self-signed or link certificate based on request 737 var policy = { certificateValidityDays: 2, 738 chatRoleOID: new ByteString("id-IS", OID), 739 chatRights: new ByteString("E3", HEX), 740 includeDomainParameter: true, 741 extensions: [] 742 }; 743 var cert = cvca.generateCertificate(req, policy); 744 GPSystem.trace("Certificate: " + cert); 745 GPSystem.trace(cert.getASN1()); 746 747 // Import certificate into store, making it the most current certificate 748 cvca.importCertificate(cert); 749 750 // Generate additional self-signed root certificate 751 // This must be done after the link certificate has been imported 752 var policy = { certificateValidityDays: 2, 753 chatRoleOID: new ByteString("id-IS", OID), 754 chatRights: new ByteString("E3", HEX), 755 includeDomainParameter: true, 756 extensions: [] 757 }; 758 var cert = cvca.generateCertificate(req, policy); 759 GPSystem.trace("Certificate: " + cert); 760 GPSystem.trace(cert.getASN1()); 761 762 // Import certificate into store, making it the most current certificate 763 cvca.importCertificate(cert); 764 765 var ss = new CVCertificateStore(daofdvca); 766 ss.setContextMarker(1); 767 var dvca = new CVCCA(crypto, ss, null, null, "/UTCVCA/UTDVCA"); 768 769 var certlist = cvca.getCertificateList(); 770 var list = dvca.importCertificates(certlist); 771 772 if (list.length > 0) { 773 GPSystem.trace("Warning: Could not import the following certificates"); 774 for (var i = 0; i < list.length; i++) { 775 GPSystem.trace(list[i]); 776 } 777 } 778 779 // Create a new request 780 var req = dvca.generateRequest(null, false); 781 GPSystem.trace("Request: " + req); 782 GPSystem.trace(req.getASN1()); 783 784 // Sign this request with root CA 785 // This must be done after the link certificate has been imported 786 var policy = { certificateValidityDays: 2, 787 chatRoleOID: new ByteString("id-IS", OID), 788 chatRights: new ByteString("A3", HEX), 789 includeDomainParameter: false, 790 extensions: [] 791 }; 792 var cert = cvca.generateCertificate(req, policy); 793 GPSystem.trace("Certificate: " + cert); 794 GPSystem.trace(cert.getASN1()); 795 796 cvca.storeCertificate(cert); 797 dvca.importCertificate(cert); 798 799 800 var ss = new CVCertificateStore(daofterm); 801 ss.setContextMarker(2); 802 var term = new CVCCA(crypto, ss, null, null, "/UTCVCA/UTDVCA/UTTERM"); 803 804 term.setRemovePreviousKey(true); 805 806 var certlist = dvca.getCertificateList(); 807 GPSystem.trace("Certificate list: "); 808 GPSystem.trace(certlist); 809 var list = term.importCertificates(certlist); 810 811 if (list.length > 0) { 812 GPSystem.trace("Warning: Could not import the following certificates"); 813 for (var i = 0; i < list.length; i++) { 814 GPSystem.trace(list[i]); 815 } 816 } 817 818 // Create a new request 819 var req = term.generateRequest(null, false); 820 GPSystem.trace("Request: " + req); 821 GPSystem.trace(req.getASN1()); 822 823 // Sign this request with DVCA 824 // This must be done after the link certificate has been imported 825 var policy = { certificateValidityDays: 2, 826 chatRoleOID: new ByteString("id-IS", OID), 827 chatRights: new ByteString("23", HEX), 828 includeDomainParameter: false, 829 extensions: [] 830 }; 831 var cert = dvca.generateCertificate(req, policy); 832 GPSystem.trace("Certificate: " + cert); 833 GPSystem.trace(cert.getASN1()); 834 835 dvca.storeCertificate(cert); 836 term.importCertificate(cert); 837 } 838