use of org.xipki.ca.api.profile.Certprofile.ExtensionControl in project xipki by xipki.
the class X509Ca method generateCert0.
private CertificateInfo generateCert0(GrantedCertTemplate gct, RequestorInfo requestor, RequestType reqType, byte[] transactionId, AuditEvent event) throws OperationException {
notNull(gct, "gct");
event.addEventData(CaAuditConstants.NAME_req_subject, X509Util.getRfc4519Name(gct.requestedSubject));
event.addEventData(CaAuditConstants.NAME_certprofile, gct.certprofile.getIdent().getName());
event.addEventData(CaAuditConstants.NAME_not_before, DateUtil.toUtcTimeyyyyMMddhhmmss(gct.grantedNotBefore));
event.addEventData(CaAuditConstants.NAME_not_after, DateUtil.toUtcTimeyyyyMMddhhmmss(gct.grantedNotAfter));
IdentifiedCertprofile certprofile = gct.certprofile;
ExtensionControl extnSctCtrl = certprofile.getExtensionControls().get(Extn.id_SCTs);
boolean ctlogEnabled = caInfo.getCtlogControl() != null && caInfo.getCtlogControl().isEnabled();
if (!ctlogEnabled) {
if (extnSctCtrl != null && extnSctCtrl.isRequired()) {
throw new OperationException(SYSTEM_FAILURE, "extension " + ObjectIdentifiers.getName(Extn.id_SCTs) + " is required but CTLog of the CA is not activated");
}
}
String serialNumberMode = certprofile.getSerialNumberMode();
BigInteger serialNumber = null;
while (true) {
if (StringUtil.isBlank(serialNumberMode) || "CA".equalsIgnoreCase(serialNumberMode)) {
serialNumber = caInfo.nextSerial();
} else if ("PROFILE".equalsIgnoreCase(serialNumberMode)) {
try {
BigInteger previousSerialNumber = serialNumber;
ConfPairs extraControl = caInfo.getExtraControl();
serialNumber = certprofile.generateSerialNumber(caInfo.getCert().getSubject(), caInfo.getCert().getSubjectPublicKeyInfo(), gct.requestedSubject, gct.grantedPublicKey, extraControl == null ? null : extraControl.unmodifiable());
// do not repeat this process.
if (serialNumber.equals(previousSerialNumber)) {
break;
}
} catch (CertprofileException ex) {
LogUtil.error(LOG, ex, "error generateSerialNumber");
throw new OperationException(SYSTEM_FAILURE, "unknown SerialNumberMode '" + serialNumberMode + "'");
}
} else {
throw new OperationException(BAD_CERT_TEMPLATE, "unknown SerialNumberMode '" + serialNumberMode + "'");
}
if (certstore.getCertId(caIdent, serialNumber) == 0) {
break;
}
}
X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(caInfo.getPublicCaInfo().getSubject(), serialNumber, gct.grantedNotBefore, gct.grantedNotAfter, gct.grantedSubject, gct.grantedPublicKey);
CertificateInfo ret;
try {
SignerEntryWrapper crlSigner = crlModule.getCrlSigner();
X509Cert crlSignerCert = (crlSigner == null) ? null : crlSigner.getSigner().getCertificate();
ExtensionValues extensionTuples = certprofile.getExtensions(gct.requestedSubject, gct.grantedSubject, gct.extensions, gct.grantedPublicKey, caInfo.getPublicCaInfo(), crlSignerCert, gct.grantedNotBefore, gct.grantedNotAfter);
if (extensionTuples != null) {
for (ASN1ObjectIdentifier extensionType : extensionTuples.getExtensionTypes()) {
ExtensionValue extValue = extensionTuples.getExtensionValue(extensionType);
certBuilder.addExtension(extensionType, extValue.isCritical(), extValue.getValue());
}
}
boolean addCtlog = ctlogEnabled && extnSctCtrl != null;
if (addCtlog) {
certBuilder.addExtension(Extn.id_precertificate, true, DERNull.INSTANCE);
ConcurrentBagEntrySigner signer0;
try {
signer0 = gct.signer.borrowSigner();
} catch (NoIdleSignerException ex) {
throw new OperationException(SYSTEM_FAILURE, ex);
}
X509CertificateHolder precert;
try {
precert = certBuilder.build(signer0.value());
} finally {
// returns the signer after the signing so that it can be used by others
gct.signer.requiteSigner(signer0);
}
CtLogPublicKeyFinder finder = caManager.getCtLogPublicKeyFinder();
if (finder == null) {
throw new OperationException(SYSTEM_FAILURE, "ctLog not configured for CA " + caInfo.getIdent().getName());
}
SignedCertificateTimestampList scts = ctlogClient.getCtLogScts(precert, caCert, caInfo.getCertchain(), finder);
// remove the precertificate extension
certBuilder.removeExtension(Extn.id_precertificate);
// add the SCTs extension
DEROctetString extnValue;
try {
extnValue = new DEROctetString(new DEROctetString(scts.getEncoded()).getEncoded());
} catch (IOException ex) {
throw new CertIOException("could not encode SCT extension", ex);
}
certBuilder.addExtension(new Extension(Extn.id_SCTs, extnSctCtrl.isCritical(), extnValue));
}
ConcurrentBagEntrySigner signer0;
try {
signer0 = gct.signer.borrowSigner();
} catch (NoIdleSignerException ex) {
throw new OperationException(SYSTEM_FAILURE, ex);
}
X509CertificateHolder bcCert;
try {
bcCert = certBuilder.build(signer0.value());
} finally {
gct.signer.requiteSigner(signer0);
}
byte[] encodedCert = bcCert.getEncoded();
int maxCertSize = gct.certprofile.getMaxCertSize();
if (maxCertSize > 0) {
int certSize = encodedCert.length;
if (certSize > maxCertSize) {
throw new OperationException(NOT_PERMITTED, String.format("certificate exceeds the maximal allowed size: %d > %d", certSize, maxCertSize));
}
}
X509Cert cert = new X509Cert(bcCert, encodedCert);
if (!verifySignature(cert)) {
throw new OperationException(SYSTEM_FAILURE, "could not verify the signature of generated certificate");
}
CertWithDbId certWithMeta = new CertWithDbId(cert);
ret = new CertificateInfo(certWithMeta, gct.privateKey, caIdent, caCert, gct.certprofile.getIdent(), requestor.getIdent());
if (requestor instanceof RequestorInfo.ByUserRequestorInfo) {
ret.setUser((((RequestorInfo.ByUserRequestorInfo) requestor).getUserId()));
}
ret.setReqType(reqType);
ret.setTransactionId(transactionId);
ret.setRequestedSubject(gct.requestedSubject);
if (saveCert && publisherModule.publishCert(ret) == 1) {
throw new OperationException(SYSTEM_FAILURE, "could not save certificate");
}
} catch (BadCertTemplateException ex) {
throw new OperationException(BAD_CERT_TEMPLATE, ex);
} catch (OperationException ex) {
throw ex;
} catch (Throwable th) {
LogUtil.error(LOG, th, "could not generate certificate");
throw new OperationException(SYSTEM_FAILURE, th);
}
if (gct.warning != null) {
ret.setWarningMessage(gct.warning);
}
return ret;
}
use of org.xipki.ca.api.profile.Certprofile.ExtensionControl in project xipki by xipki.
the class ExtensionsChecker method checkExtensions.
public List<ValidationIssue> checkExtensions(Certificate cert, IssuerInfo issuerInfo, Extensions requestedExtns, X500Name requestedSubject) {
notNull(cert, "cert");
notNull(issuerInfo, "issuerInfo");
X509Cert jceCert = new X509Cert(cert);
List<ValidationIssue> result = new LinkedList<>();
// detect the list of extension types in certificate
Set<ASN1ObjectIdentifier> presentExtenionTypes = getExensionTypes(cert, issuerInfo, requestedExtns);
Extensions extensions = cert.getTBSCertificate().getExtensions();
ASN1ObjectIdentifier[] oids = extensions.getExtensionOIDs();
if (oids == null) {
ValidationIssue issue = new ValidationIssue("X509.EXT.GEN", "extension general");
result.add(issue);
issue.setFailureMessage("no extension is present");
return result;
}
List<ASN1ObjectIdentifier> certExtTypes = Arrays.asList(oids);
for (ASN1ObjectIdentifier extType : presentExtenionTypes) {
if (!certExtTypes.contains(extType)) {
ValidationIssue issue = createExtensionIssue(extType);
result.add(issue);
issue.setFailureMessage("extension is absent but is required");
}
}
Map<ASN1ObjectIdentifier, ExtensionControl> extnControls = certprofile.getExtensionControls();
for (ASN1ObjectIdentifier oid : certExtTypes) {
ValidationIssue issue = createExtensionIssue(oid);
result.add(issue);
if (!presentExtenionTypes.contains(oid)) {
issue.setFailureMessage("extension is present but is not permitted");
continue;
}
Extension ext = extensions.getExtension(oid);
StringBuilder failureMsg = new StringBuilder();
ExtensionControl extnControl = extnControls.get(oid);
if (extnControl.isCritical() != ext.isCritical()) {
addViolation(failureMsg, "critical", ext.isCritical(), extnControl.isCritical());
}
byte[] extnValue = ext.getExtnValue().getOctets();
try {
if (extensionSyntaxes != null && extensionSyntaxes.containsKey(oid)) {
Extension requestedExtn = requestedExtns.getExtension(oid);
if (!Arrays.equals(requestedExtn.getExtnValue().getOctets(), extnValue)) {
failureMsg.append("extension in certificate does not equal the one contained in the request");
} else {
ExtnSyntax syntax = extensionSyntaxes.get(oid);
String extnName = "extension " + ObjectIdentifiers.oidToDisplayName(oid);
try {
ExtensionSyntaxChecker.checkExtension(extnName, ext.getParsedValue(), syntax);
} catch (BadCertTemplateException ex) {
failureMsg.append(ex.getMessage());
}
}
} else if (Extension.authorityKeyIdentifier.equals(oid)) {
a2gChecker.checkExtnAuthorityKeyId(failureMsg, extnValue, issuerInfo);
} else if (Extension.subjectKeyIdentifier.equals(oid)) {
// SubjectKeyIdentifier
o2tChecker.checkExtnSubjectKeyIdentifier(failureMsg, extnValue, cert.getSubjectPublicKeyInfo());
} else if (Extension.keyUsage.equals(oid)) {
h2nChecker.checkExtnKeyUsage(failureMsg, jceCert.getKeyUsage(), requestedExtns, extnControl);
} else if (Extension.certificatePolicies.equals(oid)) {
a2gChecker.checkExtnCertificatePolicies(failureMsg, extnValue, requestedExtns, extnControl);
} else if (Extension.policyMappings.equals(oid)) {
o2tChecker.checkExtnPolicyMappings(failureMsg, extnValue, requestedExtns, extnControl);
} else if (Extension.subjectAlternativeName.equals(oid)) {
o2tChecker.checkExtnSubjectAltNames(failureMsg, extnValue, requestedExtns, extnControl, requestedSubject);
} else if (Extension.subjectDirectoryAttributes.equals(oid)) {
o2tChecker.checkExtnSubjectDirAttrs(failureMsg, extnValue, requestedExtns, extnControl);
} else if (Extension.issuerAlternativeName.equals(oid)) {
h2nChecker.checkExtnIssuerAltNames(failureMsg, extnValue, issuerInfo);
} else if (Extension.basicConstraints.equals(oid)) {
a2gChecker.checkExtnBasicConstraints(failureMsg, extnValue);
} else if (Extension.nameConstraints.equals(oid)) {
h2nChecker.checkExtnNameConstraints(failureMsg, extnValue, requestedExtns, extnControl);
} else if (Extension.policyConstraints.equals(oid)) {
o2tChecker.checkExtnPolicyConstraints(failureMsg, extnValue, requestedExtns, extnControl);
} else if (Extension.extendedKeyUsage.equals(oid)) {
a2gChecker.checkExtnExtendedKeyUsage(failureMsg, extnValue, requestedExtns, extnControl);
} else if (Extension.cRLDistributionPoints.equals(oid)) {
a2gChecker.checkExtnCrlDistributionPoints(failureMsg, extnValue, issuerInfo);
} else if (Extension.inhibitAnyPolicy.equals(oid)) {
h2nChecker.checkExtnInhibitAnyPolicy(failureMsg, extnValue, extensions, extnControl);
} else if (Extension.freshestCRL.equals(oid)) {
a2gChecker.checkExtnDeltaCrlDistributionPoints(failureMsg, extnValue, issuerInfo);
} else if (Extension.authorityInfoAccess.equals(oid)) {
a2gChecker.checkExtnAuthorityInfoAccess(failureMsg, extnValue, issuerInfo);
} else if (Extension.subjectInfoAccess.equals(oid)) {
o2tChecker.checkExtnSubjectInfoAccess(failureMsg, extnValue, requestedExtns, extnControl);
} else if (Extn.id_extension_admission.equals(oid)) {
a2gChecker.checkExtnAdmission(failureMsg, extnValue, requestedExtns, requestedSubject, extnControl);
} else if (Extn.id_extension_pkix_ocsp_nocheck.equals(oid)) {
o2tChecker.checkExtnOcspNocheck(failureMsg, extnValue);
} else if (Extn.id_extension_restriction.equals(oid)) {
o2tChecker.checkExtnRestriction(failureMsg, extnValue, requestedExtns, extnControl);
} else if (Extn.id_extension_additionalInformation.equals(oid)) {
a2gChecker.checkExtnAdditionalInformation(failureMsg, extnValue, requestedExtns, extnControl);
} else if (Extn.id_extension_validityModel.equals(oid)) {
u2zChecker.checkExtnValidityModel(failureMsg, extnValue, requestedExtns, extnControl);
} else if (Extension.privateKeyUsagePeriod.equals(oid)) {
o2tChecker.checkExtnPrivateKeyUsagePeriod(failureMsg, extnValue, jceCert.getNotBefore(), jceCert.getNotAfter());
} else if (Extension.qCStatements.equals(oid)) {
o2tChecker.checkExtnQcStatements(failureMsg, extnValue, requestedExtns, extnControl);
} else if (Extension.biometricInfo.equals(oid)) {
a2gChecker.checkExtnBiometricInfo(failureMsg, extnValue, requestedExtns);
} else if (Extn.id_pe_tlsfeature.equals(oid)) {
o2tChecker.checkExtnTlsFeature(failureMsg, extnValue, requestedExtns, extnControl);
} else if (Extn.id_smimeCapabilities.equals(oid)) {
o2tChecker.checkSmimeCapabilities(failureMsg, extnValue, extnControl);
} else if (Extn.id_SCTs.equals(oid)) {
o2tChecker.checkScts(failureMsg, extnValue, extnControl);
} else if (Extn.id_GMT_0015_ICRegistrationNumber.equals(oid) || Extn.id_GMT_0015_InsuranceNumber.equals(oid) || Extn.id_GMT_0015_OrganizationCode.equals(oid) || Extn.id_GMT_0015_TaxationNumber.equals(oid) || Extn.id_GMT_0015_IdentityCode.equals(oid)) {
a2gChecker.checkExtnGmt0015(failureMsg, extnValue, requestedExtns, extnControl, oid, requestedSubject);
} else {
byte[] expected = getExpectedExtValue(oid, requestedExtns, extnControl);
if (!Arrays.equals(expected, extnValue)) {
addViolation(failureMsg, "extension value", hex(extnValue), (expected == null) ? "not present" : hex(expected));
}
}
if (failureMsg.length() > 0) {
issue.setFailureMessage(failureMsg.toString());
}
} catch (IllegalArgumentException | ClassCastException | IOException | ArrayIndexOutOfBoundsException ex) {
LOG.debug("extension value does not have correct syntax", ex);
issue.setFailureMessage("extension value does not have correct syntax");
}
}
return result;
}
use of org.xipki.ca.api.profile.Certprofile.ExtensionControl in project xipki by xipki.
the class X509ProfileType method buildExtensionControls.
// buildExtesionsWithSyntax
public Map<ASN1ObjectIdentifier, ExtensionControl> buildExtensionControls() throws CertprofileException {
// Extension controls
Map<ASN1ObjectIdentifier, ExtensionControl> controls = new HashMap<>();
for (ExtensionType extn : getExtensions()) {
ASN1ObjectIdentifier oid = extn.getType().toXiOid();
if (controls.containsKey(oid)) {
throw new CertprofileException("duplicated definition of extension " + oid.getId());
}
boolean permittedInReq = extn.isPermittedInRequest();
if (permittedInReq && extn.getConstant() != null) {
throw new CertprofileException("constant Extension is not permitted in request");
}
if (!permittedInReq && extn.getSyntax() != null) {
throw new CertprofileException("Extension with syntax must be permitted in request");
}
ExtensionControl ctrl = new ExtensionControl(extn.isCritical(), extn.isRequired(), permittedInReq);
controls.put(oid, ctrl);
}
return Collections.unmodifiableMap(controls);
}
Aggregations