String msg = intres.getLocalizedMessage("caadmin.errorcertresp", Integer.valueOf(caid));
logSession.log(admin, caid, LogConstants.MODULE_CA, new java.util.Date(), null, null, LogConstants.EVENT_ERROR_CAEDITED, msg);
throw new EjbcaException(msg);
}
try {
CA ca = cadata.getCA();
try {
if (responsemessage instanceof X509ResponseMessage) {
cacert = ((X509ResponseMessage) responsemessage).getCertificate();
} else {
String msg = intres.getLocalizedMessage("caadmin.errorcertrespillegalmsg", responsemessage != null ? responsemessage.getClass().getName()
: "null");
logSession.log(admin, caid, LogConstants.MODULE_CA, new java.util.Date(), null, null, LogConstants.EVENT_ERROR_CAEDITED, msg);
throw new EjbcaException(msg);
}
// If signed by external CA, process the received certificate
// and store it, activating the CA
if (ca.getSignedBy() == CAInfo.SIGNEDBYEXTERNALCA) {
// Check that CA DN is equal to the certificate response.
if (!CertTools.getSubjectDN(cacert).equals(CertTools.stringToBCDNString(ca.getSubjectDN()))) {
String msg = intres.getLocalizedMessage("caadmin.errorcertrespwrongdn", CertTools.getSubjectDN(cacert), ca.getSubjectDN());
logSession.log(admin, caid, LogConstants.MODULE_CA, new java.util.Date(), null, null, LogConstants.EVENT_ERROR_CAEDITED, msg);
throw new EjbcaException(msg);
}
ArrayList<Certificate> tmpchain = new ArrayList<Certificate>();
tmpchain.add(cacert);
// If we have a chain given as parameter, we will use that.
// If no parameter is given we assume that the request chain
// was stored when the request was created.
Collection<Certificate> reqchain = null;
if ((cachain != null) && (cachain.size() > 0)) {
reqchain = CertTools.createCertChain(cachain);
log.debug("Using CA certificate chain from parameter of size: " + reqchain.size());
} else {
reqchain = ca.getRequestCertificateChain();
log.debug("Using pre-stored CA certificate chain.");
if (reqchain == null) {
String msg = intres.getLocalizedMessage("caadmin.errornorequestchain", caid, ca.getSubjectDN());
log.info(msg);
throw new CertPathValidatorException(msg);
}
}
log.debug("Picked up request certificate chain of size: " + reqchain.size());
tmpchain.addAll(reqchain);
Collection<Certificate> chain = CertTools.createCertChain(tmpchain);
log.debug("Storing certificate chain of size: " + chain.size());
// Before importing the certificate we want to make sure
// that the public key matches the CAs private key
CATokenContainer catoken = ca.getCAToken();
// If it is a DV certificate signed by a CVCA, enrich the
// public key for EC parameters from the CVCA's certificate
PublicKey pk = cacert.getPublicKey();
if (StringUtils.equals(cacert.getType(), "CVC")) {
if (pk.getAlgorithm().equals("ECDSA")) {
CardVerifiableCertificate cvccert = (CardVerifiableCertificate) cacert;
try {
if ((cvccert.getCVCertificate().getCertificateBody().getAuthorizationTemplate().getAuthorizationField().getRole() == AuthorizationRoleEnum.DV_D)
|| (cvccert.getCVCertificate().getCertificateBody().getAuthorizationTemplate().getAuthorizationField().getRole() == AuthorizationRoleEnum.DV_F)) {
log.debug("Enriching DV public key with EC parameters from CVCA");
Certificate cvcacert = (Certificate) reqchain.iterator().next();
pk = KeyTools.getECPublicKeyWithParams(pk, cvcacert.getPublicKey());
}
} catch (InvalidKeySpecException e) {
log.debug("Strange CVCA certificate that we can't get the key from, continuing anyway...", e);
} catch (NoSuchFieldException e) {
log.debug("Strange DV certificate with no AutheorizationRole, continuing anyway...", e);
}
} else {
log.debug("Key is not ECDSA, don't try to enrich with EC parameters.");
}
} else {
log.debug("Cert is not CVC, no need to enrich with EC parameters.");
}
try {
KeyTools.testKey(catoken.getPrivateKey(SecConst.CAKEYPURPOSE_CERTSIGN), pk, catoken.getProvider());
} catch (Exception e1) {
log.debug("The received certificate response does not match the CAs private signing key for purpose CAKEYPURPOSE_CERTSIGN, trying CAKEYPURPOSE_CERTSIGN_NEXT...");
if (e1 instanceof InvalidKeyException) {
log.trace(e1);
} else {
// If it's not invalid key, we want to see more of
// the error
log.debug("Error: ", e1);
}
try {
KeyTools.testKey(catoken.getPrivateKey(SecConst.CAKEYPURPOSE_CERTSIGN_NEXT), pk, catoken.getProvider());
// This was OK, so we must also activate the next
// signing key when importing this certificate
catoken.activateNextSignKey(tokenAuthenticationCode);
ca.setCAToken(catoken);
// In order to generate a certificate with this
// keystore we must make sure it is activated
ca.getCAToken().activate(tokenAuthenticationCode);
} catch (Exception e2) {
log.debug("The received certificate response does not match the CAs private signing key for purpose CAKEYPURPOSE_CERTSIGN_NEXT either, giving up.");
if ((e2 instanceof InvalidKeyException) || (e2 instanceof IllegalArgumentException)) {
log.trace(e2);
} else {
// If it's not invalid key or missing authentication code,
// we want to see more of the error
log.debug("Error: ", e2);
}
throw new EjbcaException(ErrorCode.INVALID_KEY, e2);
}
}
ca.setCertificateChain(chain);
// Publish CA Certificate
publishCACertificate(admin, chain, ca.getCRLPublishers(), ca.getSubjectDN());
// Set status to active, so we can sign certificates for the
// external services below.
cadata.setStatus(SecConst.CA_ACTIVE);
ca.setStatus(SecConst.CA_ACTIVE);
// activate External CA Services
Iterator<Integer> iter = ca.getExternalCAServiceTypes().iterator();
while (iter.hasNext()) {
int type = iter.next().intValue();
try {
ca.initExternalService(type, ca);
ArrayList<Certificate> extcacertificate = new ArrayList<Certificate>();
ExtendedCAServiceInfo info = null;
if (type == ExtendedCAServiceInfo.TYPE_OCSPEXTENDEDSERVICE) {
info = (OCSPCAServiceInfo) ca.getExtendedCAServiceInfo(ExtendedCAServiceInfo.TYPE_OCSPEXTENDEDSERVICE);
// The OCSP certificate is the same as the
// singing certificate
}
if (type == ExtendedCAServiceInfo.TYPE_XKMSEXTENDEDSERVICE) {
info = ca.getExtendedCAServiceInfo(ExtendedCAServiceInfo.TYPE_XKMSEXTENDEDSERVICE);
extcacertificate.add(((XKMSCAServiceInfo) info).getXKMSSignerCertificatePath().get(0));
}
if (type == ExtendedCAServiceInfo.TYPE_CMSEXTENDEDSERVICE) {
info = ca.getExtendedCAServiceInfo(ExtendedCAServiceInfo.TYPE_CMSEXTENDEDSERVICE);
extcacertificate.add(((CmsCAServiceInfo) info).getCertificatePath().get(0));
}
// Publish the extended service certificate, but
// only for active services
if ((info != null) && (info.getStatus() == ExtendedCAServiceInfo.STATUS_ACTIVE) && (!extcacertificate.isEmpty())) {
publishCACertificate(admin, extcacertificate, ca.getCRLPublishers(), ca.getSubjectDN());
}
} catch (CATokenOfflineException e) {
String msg = intres.getLocalizedMessage("caadmin.errorcreatecaservice", Integer.valueOf(caid));
logSession.log(admin, admin.getCaId(), LogConstants.MODULE_CA, new java.util.Date(), null, null,
LogConstants.EVENT_ERROR_CACREATED, msg, e);
throw e;
} catch (Exception fe) {
String msg = intres.getLocalizedMessage("caadmin.errorcreatecaservice", Integer.valueOf(caid));
logSession.log(admin, admin.getCaId(), LogConstants.MODULE_CA, new java.util.Date(), null, null,
LogConstants.EVENT_ERROR_CACREATED, msg, fe);
throw new EJBException(fe);
}
}
// Set expire time
ca.setExpireTime(CertTools.getNotAfter(cacert));
cadata.setExpireTime(CertTools.getNotAfter(cacert).getTime());
// Save CA
cadata.setCA(ca);
// Create initial CRL
crlCreateSession.createCRLs(admin, ca, ca.getCAInfo());
} else {
String msg = intres.getLocalizedMessage("caadmin.errorcreatecaservice", Integer.valueOf(caid));
// Cannot create certificate request for internal CA
logSession.log(admin, caid, LogConstants.MODULE_CA, new java.util.Date(), null, null, LogConstants.EVENT_ERROR_CAEDITED, msg);
throw new EjbcaException(msg);