cvcca.js
Summary
Simple CVC-CA
Class Summary
|
CVCCA |
Class supporting a certification authority that can issue CVC certificates
for the EAC protocol. |
if (typeof(__ScriptingServer) == "undefined") {
load("cvcertstore.js");
load("EAC2CVRequestGenerator.js");
load("EAC2CVCertificateGenerator.js");
}
function CVCCA(crypto, certstore, holderId, parentId, path) {
this.crypto = crypto;
this.certstore = certstore;
if (typeof(path) == "undefined") {
this.holderId = holderId;
this.parentId = parentId;
if (this.isRootCA()) {
this.path = "/" + holderId;
} else {
this.path = "/" + parentId + "/" + holderId;
}
} else {
this.path = path;
var pe = path.substr(1).split("/");
var l = pe.length;
assert(l >= 1);
this.holderId = pe[l - 1];
if (l > 1) {
this.parentId = pe[l - 2];
} else {
this.parentId = this.holderId;
}
}
this.keyspec = new Key();
this.keyspec.setComponent(Key.ECC_CURVE_OID, new ByteString("brainpoolP256r1", OID));
this.taAlgorithmIdentifier = new ByteString("id-TA-ECDSA-SHA-256", OID);
this.countryseq = null;
}
CVCCA.prototype.isRootCA = function() {
return this.holderId == this.parentId;
}
CVCCA.prototype.isOperational = function() {
var currentchr = this.certstore.getCurrentCHR(this.path);
if (currentchr == null) {
return false;
}
var cvc = this.certstore.getCertificate(this.path, currentchr);
return !cvc.isExpired();
}
CVCCA.prototype.setKeySpec = function(keyparam, algorithm) {
this.keyspec = keyparam;
this.taAlgorithmIdentifier = algorithm;
}
CVCCA.prototype.setRemovePreviousKey = function(removePreviousKey) {
this.removePreviousKey = removePreviousKey;
}
CVCCA.prototype.setCountryCodeForSequence = function(countryseq) {
this.countryseq = countryseq;
}
CVCCA.prototype.generateRequest = function(car, forceinitial, signinitial) {
if (this.certstore.sc != undefined) {
return this.generateRequestHSM(car, forceinitial, signinitial);
} else {
return this.generateRequestPKCS8(car, forceinitial, signinitial);
}
}
CVCCA.prototype.generateRequestPKCS8 = function(car, forceinitial, signinitial) {
if (typeof(this.keyspec.getComponent(Key.ECC_P)) != "undefined") {
var prk = new Key(this.keyspec);
prk.setType(Key.PRIVATE);
var keyalg = Crypto.EC;
} else {
var prk = new Key();
prk.setType(Key.PRIVATE);
var keyalg = Crypto.RSA;
}
var puk = new Key(this.keyspec);
puk.setType(Key.PUBLIC);
var currentchr = this.certstore.getCurrentCHR(this.path);
var nextchr = this.certstore.getNextCHR(this.path, this.countryseq);
this.crypto.generateKeyPair(keyalg, puk, prk);
this.certstore.storePrivateKey(this.path, nextchr, prk);
var reqGenerator = new EAC2CVRequestGenerator(this.crypto);
reqGenerator.setProfileIdentifier(0x00);
reqGenerator.setPublicKey(puk);
reqGenerator.setTAAlgorithmIdentifier(this.taAlgorithmIdentifier);
reqGenerator.setCHR(nextchr);
if ((typeof(car) != "undefined") && (car != null)) {
reqGenerator.setCAR(car);
}
if ((currentchr != null) && !forceinitial) {
var previousprk = this.certstore.getPrivateKey(this.path, currentchr);
var previouscvc = this.certstore.getCertificate(this.path, currentchr);
var req = reqGenerator.generateAuthenticatedCVRequest(prk, previousprk, currentchr, previouscvc.getPublicKeyOID());
} else {
if (signinitial) {
var initialchr = new PublicKeyReference(nextchr.getHolder() + "00000");
var firstprk = this.certstore.getPrivateKey(this.path, initialchr);
var req = reqGenerator.generateAuthenticatedCVRequest(prk, firstprk, initialchr);
} else {
var req = reqGenerator.generateCVRequest(prk);
}
}
req = new CVC(req);
this.certstore.storeRequest(this.path, req);
return req;
}
CVCCA.prototype.generateRequestHSM = function(car, forceinitial, signinitial) {
var req = this.certstore.generateRequest(this.path, car, forceinitial, signinitial, this.keyspec, this.taAlgorithmIdentifier);
this.certstore.storeRequest(this.path, req);
return req;
}
CVCCA.prototype.counterSignRequest = function(request) {
assert(!request.isAuthenticatedRequest());
var car = this.certstore.getCurrentCHR(this.path);
assert(car != null);
var cacvc = this.certstore.getCertificate(this.path, car);
assert(cacvc != null);
var signingTAAlgorithmIdentifier = cacvc.getPublicKeyOID();
var prk = this.certstore.getPrivateKey(this.path, car);
var req = EAC2CVRequestGenerator.signAuthenticatedCVRequest(this.crypto, request.getASN1(), prk, car, signingTAAlgorithmIdentifier);
return new CVC(req);
}
CVCCA.prototype.generateInitialRequest = function(car) {
return this.generateRequest(car, true, false);
}
CVCCA.prototype.generateSignedInitialRequest = function(car) {
return this.generateRequest(car, true, true);
}
CVCCA.prototype.generateCertificate = function(req, policy) {
var car = this.certstore.getCurrentCHR(this.path);
var maxExpDate = null;
var signingTAAlgorithmIdentifier = req.getPublicKeyOID();
if (car == null) {
if (this.isRootCA()) {
car = req.getCHR();
} else {
throw new GPError("CVCCA", GPError.INVALID_DATA, 0, "No current certificate found");
}
} else {
var cacvc = this.certstore.getCertificate(this.path, car);
var signingTAAlgorithmIdentifier = cacvc.getPublicKeyOID();
if (policy.shellModelForExpirationDate) {
maxExpDate = cacvc.getCXD();
}
}
var generator = new EAC2CVCertificateGenerator(this.crypto);
generator.setCAR(car);
generator.setCHR(req.getCHR());
var effDate = new Date();
if (policy.ced) {
effDate = policy.ced;
}
effDate.setHours(12, 0, 0, 0);
var expDate = new Date((policy.certificateValidityDays - 1) * (1000 * 60 * 60 * 24) + effDate.getTime());
expDate.setHours(12, 0, 0, 0);
if (maxExpDate != null) {
if (effDate.getTime() > maxExpDate.getTime()) {
throw new GPError("CVCCA", GPError.INVALID_DATA, 0, "CA certificate is expired");
}
if (expDate.getTime() > maxExpDate.getTime()) {
expDate = maxExpDate;
}
}
generator.setEffectiveDate(effDate);
generator.setExpiryDate(expDate);
generator.setChatOID(policy.chatRoleOID);
generator.setChatAuthorizationLevel(policy.chatRights);
generator.setPublicKey(req.getPublicKey());
generator.setProfileIdentifier(0x00);
generator.setTAAlgorithmIdentifier(req.getPublicKeyOID());
generator.setIncludeDomainParameters(policy.includeDomainParameter);
generator.setExtensions(policy.extensions);
var prk = this.certstore.getPrivateKey(this.path, car);
var cvc = generator.generateCVCertificate(prk, signingTAAlgorithmIdentifier);
return cvc;
}
CVCCA.prototype.storeCertificate = function(cert) {
var chrHolder = cert.getCHR().getHolder();
this.certstore.storeCertificate(this.path + "/" + chrHolder, cert, false);
}
CVCCA.prototype.importCertificate = function(cert) {
var chr = cert.getCHR();
var prk = this.certstore.getPrivateKey(this.path, chr);
if (prk == null) {
throw new GPError("CVCCA", GPError.INVALID_DATA, 0, "Invalid certificate, not matching private key");
}
var c = this.certstore.getCertificate(this.path, cert.getCHR());
if (c != null) {
GPSystem.trace("### Certificate " + c + " already stored");
}
if (this.isRootCA() && !this.isOperational()) {
this.certstore.storeCertificate(this.path, cert, (c == null));
} else {
if (!this.certstore.insertCertificate(this.crypto, cert, this.path)) {
throw new GPError("CVCCA", GPError.CRYPTO_FAILED, 0, "Could not validate certificate");
}
}
}
CVCCA.prototype.importCertificates = function(certs) {
var list = this.certstore.insertCertificates2(this.crypto, certs, true, this.path);
for (var i = 0; i < certs.length; i++) {
var cert = certs[i];
var chr = cert.getCHR();
if (this.holderId == chr.getHolder()) {
var prk = this.certstore.getPrivateKey(this.path, chr);
if (prk == null) {
GPSystem.trace("We do not have a key for " + cert.toString() + " - ignored...");
} else {
if (this.removePreviousKey) {
var req = this.certstore.getRequest(this.path, chr);
var previous = req.getOuterCAR();
if ((previous != null) && (previous.getSequenceNo() != "00000")) {
this.certstore.deleteCertificate(this.path, previous, false);
this.certstore.deleteRequest(this.path, previous);
this.certstore.deletePrivateKey(this.path, previous);
}
}
}
}
}
return list;
}
CVCCA.prototype.getCertificateList = function(fromCAR) {
var list;
if (this.isRootCA()) {
list = this.certstore.listCertificates(this.path);
} else {
var path = this.path;
while(true) {
var chr = this.certstore.getCurrentCHR(path);
if (chr == null) {
var ofs = path.lastIndexOf("/");
if (ofs == 0) {
list = [];
} else {
path = path.substr(0, ofs);
continue;
}
} else {
list = this.certstore.getCertificateChain(path, chr, fromCAR);
}
break;
}
}
return list;
}
CVCCA.prototype.getIssuedCertificate = function(chr) {
var path = this.path + "/" + chr.getHolder();
var cvc = this.certstore.getCertificate(path, chr);
if (cvc == null) {
GPSystem.trace("No certificate found for " + chr);
return null;
}
return cvc;
}
CVCCA.prototype.getAuthenticPublicKey = function(chr) {
var cvc = this.getIssuedCertificate(chr);
if (cvc == null) {
return null;
}
if (this.isRootCA()) {
var dp = this.certstore.getDomainParameter(cvc.getCAR());
} else {
var dvcacvc = this.certstore.getCertificate(this.path, cvc.getCAR());
if (dvcacvc == null) {
GPSystem.trace("No certificate found for " + cvc.getCAR());
return null;
}
var dp = this.certstore.getDomainParameter(dvcacvc.getCAR());
}
return(cvc.getPublicKey(dp));
}
CVCCA.testPath = GPSystem.mapFilename("testca", GPSystem.CWD);
CVCCA.test = function() {
var crypto = new Crypto();
var ss = new CVCertificateStore(CVCCA.testPath + "/cvca");
var cvca = new CVCCA(crypto, ss, null, null, "/UTCVCA");
var req = cvca.generateRequest(null, false);
print("Request: " + req);
print(req.getASN1());
assert(req.verifyWith(crypto, req.getPublicKey()));
var policy = { certificateValidityDays: 2,
chatRoleOID: new ByteString("id-IS", OID),
chatRights: new ByteString("E3", HEX),
includeDomainParameter: true,
extensions: []
};
var cert = cvca.generateCertificate(req, policy);
print("Certificate: " + cert);
print(cert.getASN1());
cvca.storeCertificate(cert);
var policy = { certificateValidityDays: 2,
chatRoleOID: new ByteString("id-IS", OID),
chatRights: new ByteString("E3", HEX),
includeDomainParameter: true,
extensions: []
};
var cert = cvca.generateCertificate(req, policy);
print("Certificate: " + cert);
print(cert.getASN1());
cvca.storeCertificate(cert);
var ss = new CVCertificateStore(CVCCA.testPath + "/dvca");
var dvca = new CVCCA(crypto, ss, null, null, "/UTCVCA/UTDVCA");
var certlist = cvca.getCertificateList();
var list = dvca.importCertificates(certlist);
if (list.length > 0) {
print("Warning: Could not import the following certificates");
for (var i = 0; i < list.length; i++) {
print(list[i]);
}
}
var req = dvca.generateRequest(null, false);
print("Request: " + req);
print(req.getASN1());
var policy = { certificateValidityDays: 2,
chatRoleOID: new ByteString("id-IS", OID),
chatRights: new ByteString("A3", HEX),
includeDomainParameter: false,
extensions: []
};
var cert = cvca.generateCertificate(req, policy);
print("Certificate: " + cert);
print(cert.getASN1());
cvca.storeCertificate(cert);
dvca.importCertificate(cert);
var ss = new CVCertificateStore(CVCCA.testPath + "/term");
var term = new CVCCA(crypto, ss, null, null, "/UTCVCA/UTDVCA/UTTERM");
var certlist = dvca.getCertificateList();
print("Certificate list: ");
print(certlist);
var list = term.importCertificates(certlist);
if (list.length > 0) {
print("Warning: Could not import the following certificates");
for (var i = 0; i < list.length; i++) {
print(list[i]);
}
}
var req = term.generateRequest(null, false);
print("Request: " + req);
print(req.getASN1());
var policy = { certificateValidityDays: 2,
chatRoleOID: new ByteString("id-IS", OID),
chatRights: new ByteString("23", HEX),
includeDomainParameter: false,
extensions: []
};
var cert = dvca.generateCertificate(req, policy);
print("Certificate: " + cert);
print(cert.getASN1());
dvca.storeCertificate(cert);
term.importCertificate(cert);
}
Documentation generated by
JSDoc on Tue Sep 3 22:29:38 2013