Search in sources :

Example 1 with ExtensionControl

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;
}
Also used : DEROctetString(org.bouncycastle.asn1.DEROctetString) DEROctetString(org.bouncycastle.asn1.DEROctetString) ExtensionValue(org.xipki.ca.api.profile.ExtensionValue) CertprofileException(org.xipki.ca.api.profile.CertprofileException) ExtensionControl(org.xipki.ca.api.profile.Certprofile.ExtensionControl) ExtensionValues(org.xipki.ca.api.profile.ExtensionValues) IOException(java.io.IOException) CertIOException(org.bouncycastle.cert.CertIOException) CertIOException(org.bouncycastle.cert.CertIOException) Extension(org.bouncycastle.asn1.x509.Extension) X509v3CertificateBuilder(org.bouncycastle.cert.X509v3CertificateBuilder) X509CertificateHolder(org.bouncycastle.cert.X509CertificateHolder) BigInteger(java.math.BigInteger) SignedCertificateTimestampList(org.xipki.security.ctlog.CtLog.SignedCertificateTimestampList) ASN1ObjectIdentifier(org.bouncycastle.asn1.ASN1ObjectIdentifier)

Example 2 with ExtensionControl

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;
}
Also used : IOException(java.io.IOException) Extensions(org.bouncycastle.asn1.x509.Extensions) ValidationIssue(org.xipki.qa.ValidationIssue) Extension(org.bouncycastle.asn1.x509.Extension) X509Cert(org.xipki.security.X509Cert) ExtensionControl(org.xipki.ca.api.profile.Certprofile.ExtensionControl) BadCertTemplateException(org.xipki.ca.api.BadCertTemplateException)

Example 3 with ExtensionControl

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);
}
Also used : CertprofileException(org.xipki.ca.api.profile.CertprofileException) ExtensionControl(org.xipki.ca.api.profile.Certprofile.ExtensionControl) ASN1ObjectIdentifier(org.bouncycastle.asn1.ASN1ObjectIdentifier)

Aggregations

ExtensionControl (org.xipki.ca.api.profile.Certprofile.ExtensionControl)3 IOException (java.io.IOException)2 ASN1ObjectIdentifier (org.bouncycastle.asn1.ASN1ObjectIdentifier)2 Extension (org.bouncycastle.asn1.x509.Extension)2 CertprofileException (org.xipki.ca.api.profile.CertprofileException)2 BigInteger (java.math.BigInteger)1 DEROctetString (org.bouncycastle.asn1.DEROctetString)1 Extensions (org.bouncycastle.asn1.x509.Extensions)1 CertIOException (org.bouncycastle.cert.CertIOException)1 X509CertificateHolder (org.bouncycastle.cert.X509CertificateHolder)1 X509v3CertificateBuilder (org.bouncycastle.cert.X509v3CertificateBuilder)1 BadCertTemplateException (org.xipki.ca.api.BadCertTemplateException)1 ExtensionValue (org.xipki.ca.api.profile.ExtensionValue)1 ExtensionValues (org.xipki.ca.api.profile.ExtensionValues)1 ValidationIssue (org.xipki.qa.ValidationIssue)1 X509Cert (org.xipki.security.X509Cert)1 SignedCertificateTimestampList (org.xipki.security.ctlog.CtLog.SignedCertificateTimestampList)1