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 var signingTAAlgorithmIdentifier = req.getPublicKeyOID(); 469 470 if (car == null) { // No CA certificate found 471 if (this.isRootCA()) { 472 car = req.getCHR(); // Generate a self-signed root certificate 473 } else { 474 throw new GPError("CVCCA", GPError.INVALID_DATA, 0, "No current certificate found"); 475 } 476 } else { 477 var cacvc = this.certstore.getCertificate(this.path, car); 478 var signingTAAlgorithmIdentifier = cacvc.getPublicKeyOID(); 479 if (policy.shellModelForExpirationDate) { 480 maxExpDate = cacvc.getCXD(); 481 } 482 } 483 484 var generator = new EAC2CVCertificateGenerator(this.getCrypto()); 485 generator.setCAR(car); 486 generator.setCHR(req.getCHR()); 487 var effDate = new Date(); 488 if (policy.ced) { 489 effDate = policy.ced; 490 } 491 effDate.setHours(12, 0, 0, 0); 492 var expDate = new Date((policy.certificateValidityDays - 1) * (1000 * 60 * 60 * 24) + effDate.getTime()); 493 expDate.setHours(12, 0, 0, 0); 494 495 if (maxExpDate != null) { 496 if (effDate.getTime() > maxExpDate.getTime()) { 497 throw new GPError("CVCCA", GPError.INVALID_DATA, 0, "CA certificate is expired"); 498 } 499 // Expiration date of issued certificate must not exceed expiration date of issuing CA 500 if (expDate.getTime() > maxExpDate.getTime()) { 501 expDate = maxExpDate; 502 } 503 } 504 505 generator.setEffectiveDate(effDate); 506 generator.setExpiryDate(expDate); 507 generator.setChatOID(policy.chatRoleOID); 508 generator.setChatAuthorizationLevel(policy.chatRights); 509 generator.setPublicKey(req.getPublicKey()); 510 generator.setProfileIdentifier(0x00); 511 generator.setTAAlgorithmIdentifier(req.getPublicKeyOID()); 512 generator.setIncludeDomainParameters(policy.includeDomainParameter); 513 generator.setExtensions(policy.extensions); 514 var prk = this.getPrivateKey(this.path, car); 515 var cvc = generator.generateCVCertificate(prk, signingTAAlgorithmIdentifier); 516 517 return cvc; 518 } 519 520 521 522 /** 523 * Store issued certificate 524 * 525 * @param {CVC} cert a newly issued certificate 526 */ 527 CVCCA.prototype.storeCertificate = function(cert) { 528 GPSystem.log(GPSystem.DEBUG, module.id, "storeCertificate('" + cert + "')"); 529 530 var chrHolder = cert.getCHR().getHolder(); 531 this.certstore.storeCertificate(this.path + "/" + chrHolder, cert, false); 532 } 533 534 535 536 /** 537 * Remove previous key 538 * 539 * @param {PublicKeyReference} previous the previously used CHR 540 */ 541 CVCCA.prototype.removePreviouslyUsedKey = function(previous) { 542 GPSystem.log(GPSystem.DEBUG, module.id, "removePreviouslyUsedKey('" + previous + "')"); 543 544 if (previous.equals(this.certstore.getCurrentCHR(this.path))) { 545 GPSystem.log(GPSystem.INFO, module.id, "CHR " + previous + " is still the active key. Not deleting it"); 546 return; 547 } 548 549 if (this.eaccpf) { 550 var eaccp = this.eaccpf.getEACCryptoProvider(this.eaccpid, true); 551 eaccp.deletePrivateKey(this.path, previous); 552 } else { 553 this.certstore.deletePrivateKey(this.path, previous); 554 } 555 } 556 557 558 559 /** 560 * Import a certificate into the certificate store and make it the current certificate 561 * 562 * @param {CVC} cert the certificate 563 */ 564 CVCCA.prototype.importCertificate = function(cert) { 565 GPSystem.log(GPSystem.DEBUG, module.id, "importCertificate('" + cert + "')"); 566 567 var chr = cert.getCHR(); 568 var prk = this.getPrivateKey(this.path, chr); 569 if (prk == null) { 570 throw new GPError("CVCCA", GPError.INVALID_DATA, 0, "Invalid certificate, no matching private key"); 571 } 572 var c = this.certstore.getCertificate(this.path, cert.getCHR()); 573 if (c != null) { 574 GPSystem.log(GPSystem.INFO, module.id, "Certificate " + c + " already existing"); 575 } 576 577 // Save currentchr 578 var currentchr = this.certstore.getCurrentCHR(this.path); 579 580 if (this.isRootCA() && !this.isOperational()) { 581 this.certstore.storeCertificate(this.path, cert, (c == null)); 582 } else { 583 if (!this.certstore.insertCertificate(this.getCrypto(), cert, this.path)) { 584 throw new GPError("CVCCA", GPError.CRYPTO_FAILED, 0, "Could not validate certificate"); 585 } 586 } 587 if (this.removePreviousKey && currentchr) { 588 this.removePreviouslyUsedKey(currentchr); 589 } 590 } 591 592 593 594 /** 595 * Import a list of certificates into the certificate store 596 * 597 * @param {CVC[]} certs the list of certificates 598 */ 599 CVCCA.prototype.importCertificates = function(certs) { 600 GPSystem.log(GPSystem.DEBUG, module.id, "importCertificates('" + certs + "')"); 601 602 // Save currentchr 603 var currentchr = this.certstore.getCurrentCHR(this.path); 604 605 var list = this.certstore.insertCertificates(this.getCrypto(), certs, true, this.path); 606 607 if (this.removePreviousKey && currentchr) { 608 this.removePreviouslyUsedKey(currentchr); 609 } 610 611 return list; 612 } 613 614 615 616 /** 617 * Returns a list of relevant certificates. 618 * 619 * <p>If the CA is the root CA, then all self-signed and link certificates are returned.</p> 620 * <p>If the CA is a DVCA, then all certificates of the associated root and the current 621 * DVCA certificate is returned.</p> 622 * 623 * @param {PublicKeyReference} fromCAR the optional starting point for the list if not a root CA 624 */ 625 CVCCA.prototype.getCertificateList = function(fromCAR) { 626 GPSystem.log(GPSystem.DEBUG, module.id, "getCertificateList(" + fromCAR + ")"); 627 628 var list; 629 630 if (this.isRootCA()) { 631 list = this.certstore.listCertificates(this.path); 632 } else { 633 var path = this.path; 634 635 while(true) { 636 var chr = this.certstore.getCurrentCHR(path); 637 if (chr == null) { 638 var ofs = path.lastIndexOf("/"); 639 if (ofs == 0) { 640 list = []; 641 } else { 642 path = path.substr(0, ofs); 643 continue; 644 } 645 } else { 646 list = this.certstore.getCertificateChain(path, chr, fromCAR); 647 } 648 break; 649 } 650 } 651 652 return list; 653 } 654 655 656 657 /** 658 * Return certificate issued by this CA 659 * 660 * @param {PublicKeyReference} chr the certificate holder reference 661 * @returns the certificate or null if not found 662 * @type CVC 663 */ 664 CVCCA.prototype.getIssuedCertificate = function(chr) { 665 GPSystem.log(GPSystem.DEBUG, module.id, "getIssuedCertificate(" + chr + ")"); 666 667 var path = this.path + "/" + chr.getHolder(); 668 669 var cvc = this.certstore.getCertificate(path, chr); 670 if (cvc == null) { 671 GPSystem.trace("No certificate found for " + chr); 672 return null; 673 } 674 675 return cvc; 676 } 677 678 679 680 /** 681 * Return authentic public key with domain parameter for a given CHR subordinate to the CA 682 * 683 * @param {PublicKeyReference} chr the certificate holder reference 684 * @returns the public key or null 685 * @type Key 686 */ 687 CVCCA.prototype.getAuthenticPublicKey = function(chr) { 688 GPSystem.log(GPSystem.DEBUG, module.id, "getAuthenticPublicKey(" + chr + ")"); 689 690 var cvc = this.getIssuedCertificate(chr); 691 692 if (cvc == null) { 693 return null; 694 } 695 696 if (this.isRootCA()) { 697 var dp = this.certstore.getDomainParameter(cvc.getCAR()); 698 } else { 699 var dvcacvc = this.certstore.getCertificate(this.path, cvc.getCAR()); 700 if (dvcacvc == null) { 701 GPSystem.trace("No certificate found for " + cvc.getCAR()); 702 return null; 703 } 704 var dp = this.certstore.getDomainParameter(dvcacvc.getCAR()); 705 } 706 707 return(cvc.getPublicKey(dp)); 708 } 709 710 711 712 CVCCA.test = function(daofcvca, daofdvca, daofterm) { 713 714 var crypto = new Crypto(); 715 716 var ss = new CVCertificateStore(daofcvca); 717 ss.setContextMarker(0); 718 var cvca = new CVCCA(crypto, ss, null, null, "/UTCVCA"); 719 720 // Create a new request 721 var req = cvca.generateRequest(null, false); 722 GPSystem.trace("Request: " + req); 723 GPSystem.trace(req.getASN1()); 724 725 assert(req.verifyWith(crypto, req.getPublicKey())); 726 727 // Create self-signed or link certificate based on request 728 var policy = { certificateValidityDays: 2, 729 chatRoleOID: new ByteString("id-IS", OID), 730 chatRights: new ByteString("E3", HEX), 731 includeDomainParameter: true, 732 extensions: [] 733 }; 734 var cert = cvca.generateCertificate(req, policy); 735 GPSystem.trace("Certificate: " + cert); 736 GPSystem.trace(cert.getASN1()); 737 738 // Import certificate into store, making it the most current certificate 739 cvca.importCertificate(cert); 740 741 // Generate additional self-signed root certificate 742 // This must be done after the link certificate has been imported 743 var policy = { certificateValidityDays: 2, 744 chatRoleOID: new ByteString("id-IS", OID), 745 chatRights: new ByteString("E3", HEX), 746 includeDomainParameter: true, 747 extensions: [] 748 }; 749 var cert = cvca.generateCertificate(req, policy); 750 GPSystem.trace("Certificate: " + cert); 751 GPSystem.trace(cert.getASN1()); 752 753 // Import certificate into store, making it the most current certificate 754 cvca.importCertificate(cert); 755 756 var ss = new CVCertificateStore(daofdvca); 757 ss.setContextMarker(1); 758 var dvca = new CVCCA(crypto, ss, null, null, "/UTCVCA/UTDVCA"); 759 760 var certlist = cvca.getCertificateList(); 761 var list = dvca.importCertificates(certlist); 762 763 if (list.length > 0) { 764 GPSystem.trace("Warning: Could not import the following certificates"); 765 for (var i = 0; i < list.length; i++) { 766 GPSystem.trace(list[i]); 767 } 768 } 769 770 // Create a new request 771 var req = dvca.generateRequest(null, false); 772 GPSystem.trace("Request: " + req); 773 GPSystem.trace(req.getASN1()); 774 775 // Sign this request with root CA 776 // This must be done after the link certificate has been imported 777 var policy = { certificateValidityDays: 2, 778 chatRoleOID: new ByteString("id-IS", OID), 779 chatRights: new ByteString("A3", HEX), 780 includeDomainParameter: false, 781 extensions: [] 782 }; 783 var cert = cvca.generateCertificate(req, policy); 784 GPSystem.trace("Certificate: " + cert); 785 GPSystem.trace(cert.getASN1()); 786 787 cvca.storeCertificate(cert); 788 dvca.importCertificate(cert); 789 790 791 var ss = new CVCertificateStore(daofterm); 792 ss.setContextMarker(2); 793 var term = new CVCCA(crypto, ss, null, null, "/UTCVCA/UTDVCA/UTTERM"); 794 795 term.setRemovePreviousKey(true); 796 797 var certlist = dvca.getCertificateList(); 798 GPSystem.trace("Certificate list: "); 799 GPSystem.trace(certlist); 800 var list = term.importCertificates(certlist); 801 802 if (list.length > 0) { 803 GPSystem.trace("Warning: Could not import the following certificates"); 804 for (var i = 0; i < list.length; i++) { 805 GPSystem.trace(list[i]); 806 } 807 } 808 809 // Create a new request 810 var req = term.generateRequest(null, false); 811 GPSystem.trace("Request: " + req); 812 GPSystem.trace(req.getASN1()); 813 814 // Sign this request with DVCA 815 // This must be done after the link certificate has been imported 816 var policy = { certificateValidityDays: 2, 817 chatRoleOID: new ByteString("id-IS", OID), 818 chatRights: new ByteString("23", HEX), 819 includeDomainParameter: false, 820 extensions: [] 821 }; 822 var cert = dvca.generateCertificate(req, policy); 823 GPSystem.trace("Certificate: " + cert); 824 GPSystem.trace(cert.getASN1()); 825 826 dvca.storeCertificate(cert); 827 term.importCertificate(cert); 828 } 829