Search in sources :

Example 6 with CertprofileException

use of org.xipki.ca.api.profile.CertprofileException in project xipki by xipki.

the class X509SelfSignedCertBuilder method generateCertificate.

// method generateSelfSigned
private static X509Certificate generateCertificate(ConcurrentContentSigner signer, IdentifiedX509Certprofile certprofile, CertificationRequest csr, BigInteger serialNumber, SubjectPublicKeyInfo publicKeyInfo, List<String> caCertUris, List<String> ocspUris, List<String> crlUris, List<String> deltaCrlUris, ConfPairs extraControl) throws OperationException {
    SubjectPublicKeyInfo tmpPublicKeyInfo;
    try {
        tmpPublicKeyInfo = X509Util.toRfc3279Style(publicKeyInfo);
    } catch (InvalidKeySpecException ex) {
        LOG.warn("SecurityUtil.toRfc3279Style", ex);
        throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE, ex);
    }
    try {
        certprofile.checkPublicKey(tmpPublicKeyInfo);
    } catch (BadCertTemplateException ex) {
        LOG.warn("certprofile.checkPublicKey", ex);
        throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE, ex);
    }
    X500Name requestedSubject = csr.getCertificationRequestInfo().getSubject();
    SubjectInfo subjectInfo;
    // subject
    try {
        subjectInfo = certprofile.getSubject(requestedSubject);
    } catch (CertprofileException ex) {
        throw new OperationException(ErrorCode.SYSTEM_FAILURE, "exception in cert profile " + certprofile.getIdent());
    } catch (BadCertTemplateException ex) {
        LOG.warn("certprofile.getSubject", ex);
        throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE, ex);
    }
    Date notBefore = certprofile.getNotBefore(null);
    if (notBefore == null) {
        notBefore = new Date();
    }
    CertValidity validity = certprofile.getValidity();
    if (validity == null) {
        throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE, "no validity specified in the profile " + certprofile.getIdent());
    }
    Date notAfter = validity.add(notBefore);
    X500Name grantedSubject = subjectInfo.getGrantedSubject();
    X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(grantedSubject, serialNumber, notBefore, notAfter, grantedSubject, tmpPublicKeyInfo);
    PublicCaInfo publicCaInfo = new PublicCaInfo(grantedSubject, serialNumber, null, null, caCertUris, ocspUris, crlUris, deltaCrlUris, extraControl);
    Extensions extensions = null;
    ASN1Set attrs = csr.getCertificationRequestInfo().getAttributes();
    for (int i = 0; i < attrs.size(); i++) {
        Attribute attr = Attribute.getInstance(attrs.getObjectAt(i));
        if (PKCSObjectIdentifiers.pkcs_9_at_extensionRequest.equals(attr.getAttrType())) {
            extensions = Extensions.getInstance(attr.getAttributeValues()[0]);
        }
    }
    try {
        addExtensions(certBuilder, certprofile, requestedSubject, grantedSubject, extensions, tmpPublicKeyInfo, publicCaInfo, notBefore, notAfter);
        ConcurrentBagEntrySigner signer0 = signer.borrowSigner();
        X509CertificateHolder certHolder;
        try {
            certHolder = certBuilder.build(signer0.value());
        } finally {
            signer.requiteSigner(signer0);
        }
        Certificate bcCert = certHolder.toASN1Structure();
        return X509Util.parseCert(bcCert.getEncoded());
    } catch (BadCertTemplateException ex) {
        throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE, ex);
    } catch (NoIdleSignerException | CertificateException | IOException | CertprofileException ex) {
        throw new OperationException(ErrorCode.SYSTEM_FAILURE, ex);
    }
}
Also used : CertValidity(org.xipki.ca.api.profile.CertValidity) Attribute(org.bouncycastle.asn1.pkcs.Attribute) SubjectInfo(org.xipki.ca.api.profile.x509.SubjectInfo) CertificateException(java.security.cert.CertificateException) X500Name(org.bouncycastle.asn1.x500.X500Name) IOException(java.io.IOException) Extensions(org.bouncycastle.asn1.x509.Extensions) SubjectPublicKeyInfo(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo) PublicCaInfo(org.xipki.ca.api.PublicCaInfo) ConcurrentBagEntrySigner(org.xipki.security.ConcurrentBagEntrySigner) Date(java.util.Date) ASN1Set(org.bouncycastle.asn1.ASN1Set) CertprofileException(org.xipki.ca.api.profile.CertprofileException) X509v3CertificateBuilder(org.bouncycastle.cert.X509v3CertificateBuilder) BadCertTemplateException(org.xipki.ca.api.BadCertTemplateException) X509CertificateHolder(org.bouncycastle.cert.X509CertificateHolder) NoIdleSignerException(org.xipki.security.exception.NoIdleSignerException) InvalidKeySpecException(java.security.spec.InvalidKeySpecException) OperationException(org.xipki.ca.api.OperationException) X509Certificate(java.security.cert.X509Certificate) Certificate(org.bouncycastle.asn1.x509.Certificate)

Example 7 with CertprofileException

use of org.xipki.ca.api.profile.CertprofileException in project xipki by xipki.

the class X509Ca method createGrantedCertTemplate.

private GrantedCertTemplate createGrantedCertTemplate(CertTemplateData certTemplate, RequestorInfo requestor, boolean keyUpdate) throws OperationException {
    ParamUtil.requireNonNull("certTemplate", certTemplate);
    if (caInfo.getRevocationInfo() != null) {
        throw new OperationException(ErrorCode.NOT_PERMITTED, "CA is revoked");
    }
    IdentifiedX509Certprofile certprofile = getX509Certprofile(certTemplate.getCertprofileName());
    if (certprofile == null) {
        throw new OperationException(ErrorCode.UNKNOWN_CERT_PROFILE, "unknown cert profile " + certTemplate.getCertprofileName());
    }
    ConcurrentContentSigner signer = caInfo.getSigner(certprofile.getSignatureAlgorithms());
    if (signer == null) {
        throw new OperationException(ErrorCode.SYSTEM_FAILURE, "CA does not support any signature algorithm restricted by the cert profile");
    }
    final NameId certprofileIdent = certprofile.getIdent();
    if (certprofile.getVersion() != X509CertVersion.v3) {
        throw new OperationException(ErrorCode.SYSTEM_FAILURE, "unknown cert version " + certprofile.getVersion());
    }
    if (certprofile.isOnlyForRa()) {
        if (requestor == null || !requestor.isRa()) {
            throw new OperationException(ErrorCode.NOT_PERMITTED, "profile " + certprofileIdent + " not applied to non-RA");
        }
    }
    X500Name requestedSubject = removeEmptyRdns(certTemplate.getSubject());
    if (!certprofile.isSerialNumberInReqPermitted()) {
        RDN[] rdns = requestedSubject.getRDNs(ObjectIdentifiers.DN_SN);
        if (rdns != null && rdns.length > 0) {
            throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE, "subjectDN SerialNumber in request is not permitted");
        }
    }
    Date now = new Date();
    Date reqNotBefore;
    if (certTemplate.getNotBefore() != null && certTemplate.getNotBefore().after(now)) {
        reqNotBefore = certTemplate.getNotBefore();
    } else {
        reqNotBefore = now;
    }
    Date grantedNotBefore = certprofile.getNotBefore(reqNotBefore);
    // notBefore in the past is not permitted
    if (grantedNotBefore.before(now)) {
        grantedNotBefore = now;
    }
    if (certprofile.hasMidnightNotBefore()) {
        grantedNotBefore = setToMidnight(grantedNotBefore, certprofile.getTimezone());
    }
    if (grantedNotBefore.before(caInfo.getNotBefore())) {
        grantedNotBefore = caInfo.getNotBefore();
        if (certprofile.hasMidnightNotBefore()) {
            grantedNotBefore = setToMidnight(grantedNotBefore, certprofile.getTimezone());
        }
    }
    long time = caInfo.getNoNewCertificateAfter();
    if (grantedNotBefore.getTime() > time) {
        throw new OperationException(ErrorCode.NOT_PERMITTED, "CA is not permitted to issue certifate after " + new Date(time));
    }
    SubjectPublicKeyInfo grantedPublicKeyInfo;
    try {
        grantedPublicKeyInfo = X509Util.toRfc3279Style(certTemplate.getPublicKeyInfo());
    } catch (InvalidKeySpecException ex) {
        LogUtil.warn(LOG, ex, "invalid SubjectPublicKeyInfo");
        throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE, "invalid SubjectPublicKeyInfo");
    }
    // public key
    try {
        grantedPublicKeyInfo = certprofile.checkPublicKey(grantedPublicKeyInfo);
    } catch (BadCertTemplateException ex) {
        throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE, ex);
    }
    // CHECK weak public key, like RSA key (ROCA)
    if (grantedPublicKeyInfo.getAlgorithm().getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption)) {
        try {
            ASN1Sequence seq = ASN1Sequence.getInstance(grantedPublicKeyInfo.getPublicKeyData().getOctets());
            if (seq.size() != 2) {
                throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE, "invalid format of RSA public key");
            }
            BigInteger modulus = ASN1Integer.getInstance(seq.getObjectAt(0)).getPositiveValue();
            if (RSABrokenKey.isAffected(modulus)) {
                throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE, "RSA public key is too weak");
            }
        } catch (IllegalArgumentException ex) {
            throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE, "invalid format of RSA public key");
        }
    }
    Date gsmckFirstNotBefore = null;
    if (certprofile.getspecialCertprofileBehavior() == SpecialX509CertprofileBehavior.gematik_gSMC_K) {
        gsmckFirstNotBefore = grantedNotBefore;
        RDN[] cnRdns = requestedSubject.getRDNs(ObjectIdentifiers.DN_CN);
        if (cnRdns != null && cnRdns.length > 0) {
            String requestedCn = X509Util.rdnValueToString(cnRdns[0].getFirst().getValue());
            Long gsmckFirstNotBeforeInSecond = certstore.getNotBeforeOfFirstCertStartsWithCommonName(requestedCn, certprofileIdent);
            if (gsmckFirstNotBeforeInSecond != null) {
                gsmckFirstNotBefore = new Date(gsmckFirstNotBeforeInSecond * MS_PER_SECOND);
            }
            // append the commonName with '-' + yyyyMMdd
            SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMdd");
            dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
            String yyyyMMdd = dateF.format(gsmckFirstNotBefore);
            String suffix = "-" + yyyyMMdd;
            // append the -yyyyMMdd to the commonName
            RDN[] rdns = requestedSubject.getRDNs();
            for (int i = 0; i < rdns.length; i++) {
                if (ObjectIdentifiers.DN_CN.equals(rdns[i].getFirst().getType())) {
                    rdns[i] = new RDN(ObjectIdentifiers.DN_CN, new DERUTF8String(requestedCn + suffix));
                }
            }
            requestedSubject = new X500Name(rdns);
        }
    // end if
    }
    // end if
    // subject
    SubjectInfo subjectInfo;
    try {
        subjectInfo = certprofile.getSubject(requestedSubject);
    } catch (CertprofileException ex) {
        throw new OperationException(ErrorCode.SYSTEM_FAILURE, "exception in cert profile " + certprofileIdent);
    } catch (BadCertTemplateException ex) {
        throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE, ex);
    }
    X500Name grantedSubject = subjectInfo.getGrantedSubject();
    // make sure that empty subject is not permitted
    ASN1ObjectIdentifier[] attrTypes = grantedSubject.getAttributeTypes();
    if (attrTypes == null || attrTypes.length == 0) {
        throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE, "empty subject is not permitted");
    }
    // make sure that the grantedSubject does not equal the CA's subject
    if (X509Util.canonicalizName(grantedSubject).equals(caInfo.getPublicCaInfo().getC14nSubject())) {
        throw new OperationException(ErrorCode.ALREADY_ISSUED, "certificate with the same subject as CA is not allowed");
    }
    boolean duplicateKeyPermitted = caInfo.isDuplicateKeyPermitted();
    if (duplicateKeyPermitted && !certprofile.isDuplicateKeyPermitted()) {
        duplicateKeyPermitted = false;
    }
    byte[] subjectPublicKeyData = grantedPublicKeyInfo.getPublicKeyData().getBytes();
    long fpPublicKey = FpIdCalculator.hash(subjectPublicKeyData);
    if (keyUpdate) {
        CertStatus certStatus = certstore.getCertStatusForSubject(caIdent, grantedSubject);
        if (certStatus == CertStatus.REVOKED) {
            throw new OperationException(ErrorCode.CERT_REVOKED);
        } else if (certStatus == CertStatus.UNKNOWN) {
            throw new OperationException(ErrorCode.UNKNOWN_CERT);
        }
    } else {
        if (!duplicateKeyPermitted) {
            if (certstore.isCertForKeyIssued(caIdent, fpPublicKey)) {
                throw new OperationException(ErrorCode.ALREADY_ISSUED, "certificate for the given public key already issued");
            }
        }
    // duplicateSubject check will be processed later
    }
    // end if(keyUpdate)
    StringBuilder msgBuilder = new StringBuilder();
    if (subjectInfo.getWarning() != null) {
        msgBuilder.append(", ").append(subjectInfo.getWarning());
    }
    CertValidity validity = certprofile.getValidity();
    if (validity == null) {
        validity = caInfo.getMaxValidity();
    } else if (validity.compareTo(caInfo.getMaxValidity()) > 0) {
        validity = caInfo.getMaxValidity();
    }
    Date maxNotAfter = validity.add(grantedNotBefore);
    if (maxNotAfter.getTime() > MAX_CERT_TIME_MS) {
        maxNotAfter = new Date(MAX_CERT_TIME_MS);
    }
    // CHECKSTYLE:SKIP
    Date origMaxNotAfter = maxNotAfter;
    if (certprofile.getspecialCertprofileBehavior() == SpecialX509CertprofileBehavior.gematik_gSMC_K) {
        String str = certprofile.setParameter(SpecialX509CertprofileBehavior.PARAMETER_MAXLIFTIME);
        long maxLifetimeInDays = Long.parseLong(str);
        Date maxLifetime = new Date(gsmckFirstNotBefore.getTime() + maxLifetimeInDays * DAY_IN_MS - MS_PER_SECOND);
        if (maxNotAfter.after(maxLifetime)) {
            maxNotAfter = maxLifetime;
        }
    }
    Date grantedNotAfter = certTemplate.getNotAfter();
    if (grantedNotAfter != null) {
        if (grantedNotAfter.after(maxNotAfter)) {
            grantedNotAfter = maxNotAfter;
            msgBuilder.append(", notAfter modified");
        }
    } else {
        grantedNotAfter = maxNotAfter;
    }
    if (grantedNotAfter.after(caInfo.getNotAfter())) {
        ValidityMode mode = caInfo.getValidityMode();
        if (mode == ValidityMode.CUTOFF) {
            grantedNotAfter = caInfo.getNotAfter();
        } else if (mode == ValidityMode.STRICT) {
            throw new OperationException(ErrorCode.NOT_PERMITTED, "notAfter outside of CA's validity is not permitted");
        } else if (mode == ValidityMode.LAX) {
        // permitted
        } else {
            throw new RuntimeException("should not reach here, unknown CA ValidityMode " + mode);
        }
    // end if (mode)
    }
    if (certprofile.hasMidnightNotBefore() && !maxNotAfter.equals(origMaxNotAfter)) {
        Calendar cal = Calendar.getInstance(certprofile.getTimezone());
        cal.setTime(new Date(grantedNotAfter.getTime() - DAY_IN_MS));
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 0);
        grantedNotAfter = cal.getTime();
    }
    String warning = null;
    if (msgBuilder.length() > 2) {
        warning = msgBuilder.substring(2);
    }
    GrantedCertTemplate gct = new GrantedCertTemplate(certTemplate.getExtensions(), certprofile, grantedNotBefore, grantedNotAfter, requestedSubject, grantedPublicKeyInfo, fpPublicKey, subjectPublicKeyData, signer, warning);
    gct.setGrantedSubject(grantedSubject);
    return gct;
}
Also used : DERUTF8String(org.bouncycastle.asn1.DERUTF8String) NameId(org.xipki.ca.api.NameId) CertValidity(org.xipki.ca.api.profile.CertValidity) X500Name(org.bouncycastle.asn1.x500.X500Name) DERPrintableString(org.bouncycastle.asn1.DERPrintableString) DERUTF8String(org.bouncycastle.asn1.DERUTF8String) SubjectPublicKeyInfo(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo) ValidityMode(org.xipki.ca.server.mgmt.api.ValidityMode) SimpleTimeZone(java.util.SimpleTimeZone) CertprofileException(org.xipki.ca.api.profile.CertprofileException) InvalidKeySpecException(java.security.spec.InvalidKeySpecException) RDN(org.bouncycastle.asn1.x500.RDN) OperationException(org.xipki.ca.api.OperationException) Calendar(java.util.Calendar) SubjectInfo(org.xipki.ca.api.profile.x509.SubjectInfo) Date(java.util.Date) IssuingDistributionPoint(org.bouncycastle.asn1.x509.IssuingDistributionPoint) CRLDistPoint(org.bouncycastle.asn1.x509.CRLDistPoint) ConcurrentContentSigner(org.xipki.security.ConcurrentContentSigner) ASN1Sequence(org.bouncycastle.asn1.ASN1Sequence) BadCertTemplateException(org.xipki.ca.api.BadCertTemplateException) BigInteger(java.math.BigInteger) SimpleDateFormat(java.text.SimpleDateFormat) ASN1ObjectIdentifier(org.bouncycastle.asn1.ASN1ObjectIdentifier)

Example 8 with CertprofileException

use of org.xipki.ca.api.profile.CertprofileException in project xipki by xipki.

the class QaSystemManagerImpl method init.

public void init() {
    if (StringUtil.isBlank(confFile)) {
        throw new IllegalStateException("confFile must not be null and empty");
    }
    LOG.info("initializing ...");
    if (initialized.get()) {
        LOG.info("already initialized, skipping ...");
        return;
    }
    QAConfType qaConf;
    try {
        FileInputStream issuerConfStream = new FileInputStream(confFile);
        qaConf = parseQaConf(issuerConfStream);
    } catch (IOException | JAXBException | SAXException ex) {
        final String message = "could not parse the QA configuration";
        LogUtil.error(LOG, ex, message);
        return;
    }
    if (qaConf.getX509Issuers() != null) {
        List<X509IssuerType> x509IssuerTypes = qaConf.getX509Issuers().getX509Issuer();
        for (X509IssuerType issuerType : x509IssuerTypes) {
            byte[] certBytes;
            try {
                certBytes = readData(issuerType.getCert());
            } catch (IOException ex) {
                LogUtil.error(LOG, ex, "could not read the certificate bytes of issuer " + issuerType.getName());
                continue;
            }
            String str = issuerType.getValidityMode();
            boolean cutoffNotAfter;
            if (StringUtil.isBlank(str) || "CUTOFF".equalsIgnoreCase(str)) {
                cutoffNotAfter = true;
            } else if ("LAX".equalsIgnoreCase(str)) {
                cutoffNotAfter = false;
            } else {
                LOG.error("invalid validityMode {}", str);
                return;
            }
            X509IssuerInfo issuerInfo;
            try {
                issuerInfo = new X509IssuerInfo(issuerType.getCaIssuerUrl(), issuerType.getOcspUrl(), issuerType.getCrlUrl(), issuerType.getDeltaCrlUrl(), certBytes, cutoffNotAfter);
            } catch (CertificateException ex) {
                LogUtil.error(LOG, ex, "could not parse certificate of issuer " + issuerType.getName());
                continue;
            }
            x509IssuerInfoMap.put(issuerType.getName(), issuerInfo);
            LOG.info("configured X509 issuer {}", issuerType.getName());
        }
    }
    if (qaConf.getX509Certprofiles() != null) {
        List<X509CertprofileType> certprofileTypes = qaConf.getX509Certprofiles().getX509Certprofile();
        for (X509CertprofileType type : certprofileTypes) {
            String name = type.getName();
            try {
                byte[] content = readData(type);
                x509ProfileMap.put(name, new X509CertprofileQa(content));
                LOG.info("configured X509 certificate profile {}", name);
            } catch (IOException | CertprofileException ex) {
                LogUtil.error(LOG, ex, "could not parse QA certificate profile " + name);
                continue;
            }
        }
    }
    initialized.set(true);
    LOG.info("initialized");
}
Also used : JAXBException(javax.xml.bind.JAXBException) CertificateException(java.security.cert.CertificateException) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream) SAXException(org.xml.sax.SAXException) X509CertprofileType(org.xipki.ca.qa.jaxb.X509CertprofileType) X509IssuerType(org.xipki.ca.qa.jaxb.X509IssuerType) CertprofileException(org.xipki.ca.api.profile.CertprofileException) QAConfType(org.xipki.ca.qa.jaxb.QAConfType)

Example 9 with CertprofileException

use of org.xipki.ca.api.profile.CertprofileException in project xipki by xipki.

the class IdentifiedX509Certprofile method getExtensions.

/**
 * TODO.
 * @param requestedSubject
 *          Subject requested subject. Must not be {@code null}.
 * @param grantedSubject
 *          Granted subject. Must not be {@code null}.
 * @param requestedExtensions
 *          Extensions requested by the requestor. Could be {@code null}.
 * @param publicKeyInfo
 *          Subject public key. Must not be {@code null}.
 * @param publicCaInfo
 *          CA information. Must not be {@code null}.
 * @param crlSignerCert
 *          CRL signer certificate. Could be {@code null}.
 * @param notBefore
 *          NotBefore. Must not be {@code null}.
 * @param notAfter
 *          NotAfter. Must not be {@code null}.
 * @param caInfo
 *          CA information.
 * @return the extensions of the certificate to be issued.
 */
public ExtensionValues getExtensions(X500Name requestedSubject, X500Name grantedSubject, Extensions requestedExtensions, SubjectPublicKeyInfo publicKeyInfo, PublicCaInfo publicCaInfo, X509Certificate crlSignerCert, Date notBefore, Date notAfter) throws CertprofileException, BadCertTemplateException {
    ParamUtil.requireNonNull("publicKeyInfo", publicKeyInfo);
    ExtensionValues values = new ExtensionValues();
    Map<ASN1ObjectIdentifier, ExtensionControl> controls = new HashMap<>(certprofile.getExtensionControls());
    Set<ASN1ObjectIdentifier> neededExtTypes = new HashSet<>();
    Set<ASN1ObjectIdentifier> wantedExtTypes = new HashSet<>();
    if (requestedExtensions != null) {
        Extension reqExtension = requestedExtensions.getExtension(ObjectIdentifiers.id_xipki_ext_cmpRequestExtensions);
        if (reqExtension != null) {
            ExtensionExistence ee = ExtensionExistence.getInstance(reqExtension.getParsedValue());
            neededExtTypes.addAll(ee.getNeedExtensions());
            wantedExtTypes.addAll(ee.getWantExtensions());
        }
        for (ASN1ObjectIdentifier oid : neededExtTypes) {
            if (wantedExtTypes.contains(oid)) {
                wantedExtTypes.remove(oid);
            }
            if (!controls.containsKey(oid)) {
                throw new BadCertTemplateException("could not add needed extension " + oid.getId());
            }
        }
    }
    // SubjectKeyIdentifier
    ASN1ObjectIdentifier extType = Extension.subjectKeyIdentifier;
    ExtensionControl extControl = controls.remove(extType);
    if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
        byte[] encodedSpki = publicKeyInfo.getPublicKeyData().getBytes();
        byte[] skiValue = HashAlgo.SHA1.hash(encodedSpki);
        SubjectKeyIdentifier value = new SubjectKeyIdentifier(skiValue);
        addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
    }
    // Authority key identifier
    extType = Extension.authorityKeyIdentifier;
    extControl = controls.remove(extType);
    if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
        byte[] ikiValue = publicCaInfo.getSubjectKeyIdentifer();
        AuthorityKeyIdentifier value = null;
        if (ikiValue != null) {
            if (certprofile.includesIssuerAndSerialInAki()) {
                GeneralNames x509CaSubject = new GeneralNames(new GeneralName(publicCaInfo.getX500Subject()));
                value = new AuthorityKeyIdentifier(ikiValue, x509CaSubject, publicCaInfo.getSerialNumber());
            } else {
                value = new AuthorityKeyIdentifier(ikiValue);
            }
        }
        addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
    }
    // IssuerAltName
    extType = Extension.issuerAlternativeName;
    extControl = controls.remove(extType);
    if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
        GeneralNames value = publicCaInfo.getSubjectAltName();
        addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
    }
    // AuthorityInfoAccess
    extType = Extension.authorityInfoAccess;
    extControl = controls.remove(extType);
    if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
        AuthorityInfoAccessControl aiaControl = certprofile.getAiaControl();
        List<String> caIssuers = null;
        if (aiaControl == null || aiaControl.isIncludesCaIssuers()) {
            caIssuers = publicCaInfo.getCaCertUris();
        }
        List<String> ocspUris = null;
        if (aiaControl == null || aiaControl.isIncludesOcsp()) {
            ocspUris = publicCaInfo.getOcspUris();
        }
        if (CollectionUtil.isNonEmpty(caIssuers) || CollectionUtil.isNonEmpty(ocspUris)) {
            AuthorityInformationAccess value = CaUtil.createAuthorityInformationAccess(caIssuers, ocspUris);
            addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
        }
    }
    if (controls.containsKey(Extension.cRLDistributionPoints) || controls.containsKey(Extension.freshestCRL)) {
        X500Name crlSignerSubject = (crlSignerCert == null) ? null : X500Name.getInstance(crlSignerCert.getSubjectX500Principal().getEncoded());
        X500Name x500CaPrincipal = publicCaInfo.getX500Subject();
        // CRLDistributionPoints
        extType = Extension.cRLDistributionPoints;
        extControl = controls.remove(extType);
        if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
            if (CollectionUtil.isNonEmpty(publicCaInfo.getCrlUris())) {
                CRLDistPoint value = CaUtil.createCrlDistributionPoints(publicCaInfo.getCrlUris(), x500CaPrincipal, crlSignerSubject);
                addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
            }
        }
        // FreshestCRL
        extType = Extension.freshestCRL;
        extControl = controls.remove(extType);
        if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
            if (CollectionUtil.isNonEmpty(publicCaInfo.getDeltaCrlUris())) {
                CRLDistPoint value = CaUtil.createCrlDistributionPoints(publicCaInfo.getDeltaCrlUris(), x500CaPrincipal, crlSignerSubject);
                addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
            }
        }
    }
    // BasicConstraints
    extType = Extension.basicConstraints;
    extControl = controls.remove(extType);
    if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
        BasicConstraints value = CaUtil.createBasicConstraints(certprofile.getCertLevel(), certprofile.getPathLenBasicConstraint());
        addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
    }
    // KeyUsage
    extType = Extension.keyUsage;
    extControl = controls.remove(extType);
    if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
        Set<KeyUsage> usages = new HashSet<>();
        Set<KeyUsageControl> usageOccs = certprofile.getKeyUsage();
        for (KeyUsageControl k : usageOccs) {
            if (k.isRequired()) {
                usages.add(k.getKeyUsage());
            }
        }
        // the optional KeyUsage will only be set if requested explicitly
        if (requestedExtensions != null && extControl.isRequest()) {
            addRequestedKeyusage(usages, requestedExtensions, usageOccs);
        }
        org.bouncycastle.asn1.x509.KeyUsage value = X509Util.createKeyUsage(usages);
        addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
    }
    // ExtendedKeyUsage
    extType = Extension.extendedKeyUsage;
    extControl = controls.remove(extType);
    if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
        List<ASN1ObjectIdentifier> usages = new LinkedList<>();
        Set<ExtKeyUsageControl> usageOccs = certprofile.getExtendedKeyUsages();
        for (ExtKeyUsageControl k : usageOccs) {
            if (k.isRequired()) {
                usages.add(k.getExtKeyUsage());
            }
        }
        // the optional ExtKeyUsage will only be set if requested explicitly
        if (requestedExtensions != null && extControl.isRequest()) {
            addRequestedExtKeyusage(usages, requestedExtensions, usageOccs);
        }
        if (extControl.isCritical() && usages.contains(ObjectIdentifiers.id_anyExtendedKeyUsage)) {
            extControl = new ExtensionControl(false, extControl.isRequired(), extControl.isRequest());
        }
        ExtendedKeyUsage value = X509Util.createExtendedUsage(usages);
        addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
    }
    // ocsp-nocheck
    extType = ObjectIdentifiers.id_extension_pkix_ocsp_nocheck;
    extControl = controls.remove(extType);
    if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
        // the extension ocsp-nocheck will only be set if requested explicitly
        DERNull value = DERNull.INSTANCE;
        addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
    }
    // SubjectInfoAccess
    extType = Extension.subjectInfoAccess;
    extControl = controls.remove(extType);
    if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
        ASN1Sequence value = null;
        if (requestedExtensions != null && extControl.isRequest()) {
            value = createSubjectInfoAccess(requestedExtensions, certprofile.getSubjectInfoAccessModes());
        }
        addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
    }
    // remove extensions that are not required frrom the list
    List<ASN1ObjectIdentifier> listToRm = null;
    for (ASN1ObjectIdentifier extnType : controls.keySet()) {
        ExtensionControl ctrl = controls.get(extnType);
        if (ctrl.isRequired()) {
            continue;
        }
        if (neededExtTypes.contains(extnType) || wantedExtTypes.contains(extnType)) {
            continue;
        }
        if (listToRm == null) {
            listToRm = new LinkedList<>();
        }
        listToRm.add(extnType);
    }
    if (listToRm != null) {
        for (ASN1ObjectIdentifier extnType : listToRm) {
            controls.remove(extnType);
        }
    }
    ExtensionValues subvalues = certprofile.getExtensions(Collections.unmodifiableMap(controls), requestedSubject, grantedSubject, requestedExtensions, notBefore, notAfter, publicCaInfo);
    Set<ASN1ObjectIdentifier> extTypes = new HashSet<>(controls.keySet());
    for (ASN1ObjectIdentifier type : extTypes) {
        extControl = controls.remove(type);
        boolean addMe = addMe(type, extControl, neededExtTypes, wantedExtTypes);
        if (addMe) {
            ExtensionValue value = null;
            if (requestedExtensions != null && extControl.isRequest()) {
                Extension reqExt = requestedExtensions.getExtension(type);
                if (reqExt != null) {
                    value = new ExtensionValue(reqExt.isCritical(), reqExt.getParsedValue());
                }
            }
            if (value == null) {
                value = subvalues.getExtensionValue(type);
            }
            addExtension(values, type, value, extControl, neededExtTypes, wantedExtTypes);
        }
    }
    Set<ASN1ObjectIdentifier> unprocessedExtTypes = new HashSet<>();
    for (ASN1ObjectIdentifier type : controls.keySet()) {
        if (controls.get(type).isRequired()) {
            unprocessedExtTypes.add(type);
        }
    }
    if (CollectionUtil.isNonEmpty(unprocessedExtTypes)) {
        throw new CertprofileException("could not add required extensions " + toString(unprocessedExtTypes));
    }
    if (CollectionUtil.isNonEmpty(neededExtTypes)) {
        throw new BadCertTemplateException("could not add requested extensions " + toString(neededExtTypes));
    }
    return values;
}
Also used : AuthorityInformationAccess(org.bouncycastle.asn1.x509.AuthorityInformationAccess) AuthorityInfoAccessControl(org.xipki.ca.api.profile.x509.AuthorityInfoAccessControl) HashMap(java.util.HashMap) ExtendedKeyUsage(org.bouncycastle.asn1.x509.ExtendedKeyUsage) KeyUsage(org.xipki.security.KeyUsage) KeyUsageControl(org.xipki.ca.api.profile.x509.KeyUsageControl) ExtKeyUsageControl(org.xipki.ca.api.profile.x509.ExtKeyUsageControl) AuthorityKeyIdentifier(org.bouncycastle.asn1.x509.AuthorityKeyIdentifier) X500Name(org.bouncycastle.asn1.x500.X500Name) ExtensionValue(org.xipki.ca.api.profile.ExtensionValue) DERNull(org.bouncycastle.asn1.DERNull) CertprofileException(org.xipki.ca.api.profile.CertprofileException) ExtensionControl(org.xipki.ca.api.profile.ExtensionControl) ExtensionValues(org.xipki.ca.api.profile.ExtensionValues) CRLDistPoint(org.bouncycastle.asn1.x509.CRLDistPoint) ExtendedKeyUsage(org.bouncycastle.asn1.x509.ExtendedKeyUsage) HashSet(java.util.HashSet) ExtKeyUsageControl(org.xipki.ca.api.profile.x509.ExtKeyUsageControl) SubjectKeyIdentifier(org.bouncycastle.asn1.x509.SubjectKeyIdentifier) LinkedList(java.util.LinkedList) Extension(org.bouncycastle.asn1.x509.Extension) ASN1Sequence(org.bouncycastle.asn1.ASN1Sequence) GeneralNames(org.bouncycastle.asn1.x509.GeneralNames) ExtensionExistence(org.xipki.security.ExtensionExistence) BadCertTemplateException(org.xipki.ca.api.BadCertTemplateException) GeneralName(org.bouncycastle.asn1.x509.GeneralName) BasicConstraints(org.bouncycastle.asn1.x509.BasicConstraints) ASN1ObjectIdentifier(org.bouncycastle.asn1.ASN1ObjectIdentifier)

Example 10 with CertprofileException

use of org.xipki.ca.api.profile.CertprofileException in project xipki by xipki.

the class XmlX509Certprofile method getExtensions.

@Override
public ExtensionValues getExtensions(Map<ASN1ObjectIdentifier, ExtensionControl> extensionOccurences, X500Name requestedSubject, X500Name grantedSubject, Extensions requestedExtensions, Date notBefore, Date notAfter, PublicCaInfo caInfo) throws CertprofileException, BadCertTemplateException {
    ExtensionValues values = new ExtensionValues();
    if (CollectionUtil.isEmpty(extensionOccurences)) {
        return values;
    }
    ParamUtil.requireNonNull("requestedSubject", requestedSubject);
    ParamUtil.requireNonNull("notBefore", notBefore);
    ParamUtil.requireNonNull("notAfter", notAfter);
    Set<ASN1ObjectIdentifier> occurences = new HashSet<>(extensionOccurences.keySet());
    // AuthorityKeyIdentifier
    // processed by the CA
    // SubjectKeyIdentifier
    // processed by the CA
    // KeyUsage
    // processed by the CA
    // CertificatePolicies
    ASN1ObjectIdentifier type = Extension.certificatePolicies;
    if (certificatePolicies != null) {
        if (occurences.remove(type)) {
            values.addExtension(type, certificatePolicies);
        }
    }
    // Policy Mappings
    type = Extension.policyMappings;
    if (policyMappings != null) {
        if (occurences.remove(type)) {
            values.addExtension(type, policyMappings);
        }
    }
    // SubjectAltName
    type = Extension.subjectAlternativeName;
    if (occurences.contains(type)) {
        GeneralNames genNames = createRequestedSubjectAltNames(requestedSubject, grantedSubject, requestedExtensions);
        if (genNames != null) {
            ExtensionValue value = new ExtensionValue(extensionControls.get(type).isCritical(), genNames);
            values.addExtension(type, value);
            occurences.remove(type);
        }
    }
    // IssuerAltName
    // processed by the CA
    // Subject Directory Attributes
    type = Extension.subjectDirectoryAttributes;
    if (occurences.contains(type) && subjectDirAttrsControl != null) {
        Extension extension = (requestedExtensions == null) ? null : requestedExtensions.getExtension(type);
        if (extension == null) {
            throw new BadCertTemplateException("no SubjectDirecotryAttributes extension is contained in the request");
        }
        ASN1GeneralizedTime dateOfBirth = null;
        String placeOfBirth = null;
        String gender = null;
        List<String> countryOfCitizenshipList = new LinkedList<>();
        List<String> countryOfResidenceList = new LinkedList<>();
        Map<ASN1ObjectIdentifier, List<ASN1Encodable>> otherAttrs = new HashMap<>();
        Vector<?> reqSubDirAttrs = SubjectDirectoryAttributes.getInstance(extension.getParsedValue()).getAttributes();
        final int n = reqSubDirAttrs.size();
        for (int i = 0; i < n; i++) {
            Attribute attr = (Attribute) reqSubDirAttrs.get(i);
            ASN1ObjectIdentifier attrType = attr.getAttrType();
            ASN1Encodable attrVal = attr.getAttributeValues()[0];
            if (ObjectIdentifiers.DN_DATE_OF_BIRTH.equals(attrType)) {
                dateOfBirth = ASN1GeneralizedTime.getInstance(attrVal);
            } else if (ObjectIdentifiers.DN_PLACE_OF_BIRTH.equals(attrType)) {
                placeOfBirth = DirectoryString.getInstance(attrVal).getString();
            } else if (ObjectIdentifiers.DN_GENDER.equals(attrType)) {
                gender = DERPrintableString.getInstance(attrVal).getString();
            } else if (ObjectIdentifiers.DN_COUNTRY_OF_CITIZENSHIP.equals(attrType)) {
                String country = DERPrintableString.getInstance(attrVal).getString();
                countryOfCitizenshipList.add(country);
            } else if (ObjectIdentifiers.DN_COUNTRY_OF_RESIDENCE.equals(attrType)) {
                String country = DERPrintableString.getInstance(attrVal).getString();
                countryOfResidenceList.add(country);
            } else {
                List<ASN1Encodable> otherAttrVals = otherAttrs.get(attrType);
                if (otherAttrVals == null) {
                    otherAttrVals = new LinkedList<>();
                    otherAttrs.put(attrType, otherAttrVals);
                }
                otherAttrVals.add(attrVal);
            }
        }
        Vector<Attribute> attrs = new Vector<>();
        for (ASN1ObjectIdentifier attrType : subjectDirAttrsControl.getTypes()) {
            if (ObjectIdentifiers.DN_DATE_OF_BIRTH.equals(attrType)) {
                if (dateOfBirth != null) {
                    String timeStirng = dateOfBirth.getTimeString();
                    if (!SubjectDnSpec.PATTERN_DATE_OF_BIRTH.matcher(timeStirng).matches()) {
                        throw new BadCertTemplateException("invalid dateOfBirth " + timeStirng);
                    }
                    attrs.add(new Attribute(attrType, new DERSet(dateOfBirth)));
                    continue;
                }
            } else if (ObjectIdentifiers.DN_PLACE_OF_BIRTH.equals(attrType)) {
                if (placeOfBirth != null) {
                    ASN1Encodable attrVal = new DERUTF8String(placeOfBirth);
                    attrs.add(new Attribute(attrType, new DERSet(attrVal)));
                    continue;
                }
            } else if (ObjectIdentifiers.DN_GENDER.equals(attrType)) {
                if (gender != null && !gender.isEmpty()) {
                    char ch = gender.charAt(0);
                    if (!(gender.length() == 1 && (ch == 'f' || ch == 'F' || ch == 'm' || ch == 'M'))) {
                        throw new BadCertTemplateException("invalid gender " + gender);
                    }
                    ASN1Encodable attrVal = new DERPrintableString(gender);
                    attrs.add(new Attribute(attrType, new DERSet(attrVal)));
                    continue;
                }
            } else if (ObjectIdentifiers.DN_COUNTRY_OF_CITIZENSHIP.equals(attrType)) {
                if (!countryOfCitizenshipList.isEmpty()) {
                    for (String country : countryOfCitizenshipList) {
                        if (!SubjectDnSpec.isValidCountryAreaCode(country)) {
                            throw new BadCertTemplateException("invalid countryOfCitizenship code " + country);
                        }
                        ASN1Encodable attrVal = new DERPrintableString(country);
                        attrs.add(new Attribute(attrType, new DERSet(attrVal)));
                    }
                    continue;
                }
            } else if (ObjectIdentifiers.DN_COUNTRY_OF_RESIDENCE.equals(attrType)) {
                if (!countryOfResidenceList.isEmpty()) {
                    for (String country : countryOfResidenceList) {
                        if (!SubjectDnSpec.isValidCountryAreaCode(country)) {
                            throw new BadCertTemplateException("invalid countryOfResidence code " + country);
                        }
                        ASN1Encodable attrVal = new DERPrintableString(country);
                        attrs.add(new Attribute(attrType, new DERSet(attrVal)));
                    }
                    continue;
                }
            } else if (otherAttrs.containsKey(attrType)) {
                for (ASN1Encodable attrVal : otherAttrs.get(attrType)) {
                    attrs.add(new Attribute(attrType, new DERSet(attrVal)));
                }
                continue;
            }
            throw new BadCertTemplateException("could not process type " + attrType.getId() + " in extension SubjectDirectoryAttributes");
        }
        SubjectDirectoryAttributes subjDirAttrs = new SubjectDirectoryAttributes(attrs);
        ExtensionValue extValue = new ExtensionValue(extensionControls.get(type).isCritical(), subjDirAttrs);
        values.addExtension(type, extValue);
        occurences.remove(type);
    }
    // Basic Constraints
    // processed by the CA
    // Name Constraints
    type = Extension.nameConstraints;
    if (nameConstraints != null) {
        if (occurences.remove(type)) {
            values.addExtension(type, nameConstraints);
        }
    }
    // PolicyConstrains
    type = Extension.policyConstraints;
    if (policyConstraints != null) {
        if (occurences.remove(type)) {
            values.addExtension(type, policyConstraints);
        }
    }
    // ExtendedKeyUsage
    // processed by CA
    // CRL Distribution Points
    // processed by the CA
    // Inhibit anyPolicy
    type = Extension.inhibitAnyPolicy;
    if (inhibitAnyPolicy != null) {
        if (occurences.remove(type)) {
            values.addExtension(type, inhibitAnyPolicy);
        }
    }
    // Freshest CRL
    // processed by the CA
    // Authority Information Access
    // processed by the CA
    // Subject Information Access
    // processed by the CA
    // Admission
    type = ObjectIdentifiers.id_extension_admission;
    if (occurences.contains(type) && admission != null) {
        if (admission.isInputFromRequestRequired()) {
            Extension extension = (requestedExtensions == null) ? null : requestedExtensions.getExtension(type);
            if (extension == null) {
                throw new BadCertTemplateException("No Admission extension is contained in the request");
            }
            Admissions[] reqAdmissions = org.bouncycastle.asn1.isismtt.x509.AdmissionSyntax.getInstance(extension.getParsedValue()).getContentsOfAdmissions();
            final int n = reqAdmissions.length;
            List<List<String>> reqRegNumsList = new ArrayList<>(n);
            for (int i = 0; i < n; i++) {
                Admissions reqAdmission = reqAdmissions[i];
                ProfessionInfo[] reqPis = reqAdmission.getProfessionInfos();
                List<String> reqNums = new ArrayList<>(reqPis.length);
                reqRegNumsList.add(reqNums);
                for (ProfessionInfo reqPi : reqPis) {
                    String reqNum = reqPi.getRegistrationNumber();
                    reqNums.add(reqNum);
                }
            }
            values.addExtension(type, admission.getExtensionValue(reqRegNumsList));
            occurences.remove(type);
        } else {
            values.addExtension(type, admission.getExtensionValue(null));
            occurences.remove(type);
        }
    }
    // OCSP Nocheck
    // processed by the CA
    // restriction
    type = ObjectIdentifiers.id_extension_restriction;
    if (restriction != null) {
        if (occurences.remove(type)) {
            values.addExtension(type, restriction);
        }
    }
    // AdditionalInformation
    type = ObjectIdentifiers.id_extension_additionalInformation;
    if (additionalInformation != null) {
        if (occurences.remove(type)) {
            values.addExtension(type, additionalInformation);
        }
    }
    // ValidityModel
    type = ObjectIdentifiers.id_extension_validityModel;
    if (validityModel != null) {
        if (occurences.remove(type)) {
            values.addExtension(type, validityModel);
        }
    }
    // PrivateKeyUsagePeriod
    type = Extension.privateKeyUsagePeriod;
    if (occurences.contains(type)) {
        Date tmpNotAfter;
        if (privateKeyUsagePeriod == null) {
            tmpNotAfter = notAfter;
        } else {
            tmpNotAfter = privateKeyUsagePeriod.add(notBefore);
            if (tmpNotAfter.after(notAfter)) {
                tmpNotAfter = notAfter;
            }
        }
        ASN1EncodableVector vec = new ASN1EncodableVector();
        vec.add(new DERTaggedObject(false, 0, new DERGeneralizedTime(notBefore)));
        vec.add(new DERTaggedObject(false, 1, new DERGeneralizedTime(tmpNotAfter)));
        ExtensionValue extValue = new ExtensionValue(extensionControls.get(type).isCritical(), new DERSequence(vec));
        values.addExtension(type, extValue);
        occurences.remove(type);
    }
    // QCStatements
    type = Extension.qCStatements;
    if (occurences.contains(type) && (qcStatments != null || qcStatementsOption != null)) {
        if (qcStatments != null) {
            values.addExtension(type, qcStatments);
            occurences.remove(type);
        } else if (requestedExtensions != null && qcStatementsOption != null) {
            // extract the euLimit data from request
            Extension extension = requestedExtensions.getExtension(type);
            if (extension == null) {
                throw new BadCertTemplateException("No QCStatement extension is contained in the request");
            }
            ASN1Sequence seq = ASN1Sequence.getInstance(extension.getParsedValue());
            Map<String, int[]> qcEuLimits = new HashMap<>();
            final int n = seq.size();
            for (int i = 0; i < n; i++) {
                QCStatement stmt = QCStatement.getInstance(seq.getObjectAt(i));
                if (!ObjectIdentifiers.id_etsi_qcs_QcLimitValue.equals(stmt.getStatementId())) {
                    continue;
                }
                MonetaryValue monetaryValue = MonetaryValue.getInstance(stmt.getStatementInfo());
                int amount = monetaryValue.getAmount().intValue();
                int exponent = monetaryValue.getExponent().intValue();
                Iso4217CurrencyCode currency = monetaryValue.getCurrency();
                String currencyS = currency.isAlphabetic() ? currency.getAlphabetic().toUpperCase() : Integer.toString(currency.getNumeric());
                qcEuLimits.put(currencyS, new int[] { amount, exponent });
            }
            ASN1EncodableVector vec = new ASN1EncodableVector();
            for (QcStatementOption m : qcStatementsOption) {
                if (m.getStatement() != null) {
                    vec.add(m.getStatement());
                    continue;
                }
                MonetaryValueOption monetaryOption = m.getMonetaryValueOption();
                String currencyS = monetaryOption.getCurrencyString();
                int[] limit = qcEuLimits.get(currencyS);
                if (limit == null) {
                    throw new BadCertTemplateException("no EuLimitValue is specified for currency '" + currencyS + "'");
                }
                int amount = limit[0];
                Range2Type range = monetaryOption.getAmountRange();
                if (amount < range.getMin() || amount > range.getMax()) {
                    throw new BadCertTemplateException("amount for currency '" + currencyS + "' is not within [" + range.getMin() + ", " + range.getMax() + "]");
                }
                int exponent = limit[1];
                range = monetaryOption.getExponentRange();
                if (exponent < range.getMin() || exponent > range.getMax()) {
                    throw new BadCertTemplateException("exponent for currency '" + currencyS + "' is not within [" + range.getMin() + ", " + range.getMax() + "]");
                }
                MonetaryValue monetaryVale = new MonetaryValue(monetaryOption.getCurrency(), amount, exponent);
                QCStatement qcStatment = new QCStatement(m.getStatementId(), monetaryVale);
                vec.add(qcStatment);
            }
            ExtensionValue extValue = new ExtensionValue(extensionControls.get(type).isCritical(), new DERSequence(vec));
            values.addExtension(type, extValue);
            occurences.remove(type);
        } else {
            throw new RuntimeException("should not reach here");
        }
    }
    // BiometricData
    type = Extension.biometricInfo;
    if (occurences.contains(type) && biometricInfo != null) {
        Extension extension = (requestedExtensions == null) ? null : requestedExtensions.getExtension(type);
        if (extension == null) {
            throw new BadCertTemplateException("no biometricInfo extension is contained in the request");
        }
        ASN1Sequence seq = ASN1Sequence.getInstance(extension.getParsedValue());
        final int n = seq.size();
        if (n < 1) {
            throw new BadCertTemplateException("biometricInfo extension in request contains empty sequence");
        }
        ASN1EncodableVector vec = new ASN1EncodableVector();
        for (int i = 0; i < n; i++) {
            BiometricData bd = BiometricData.getInstance(seq.getObjectAt(i));
            TypeOfBiometricData bdType = bd.getTypeOfBiometricData();
            if (!biometricInfo.isTypePermitted(bdType)) {
                throw new BadCertTemplateException("biometricInfo[" + i + "].typeOfBiometricData is not permitted");
            }
            ASN1ObjectIdentifier hashAlgo = bd.getHashAlgorithm().getAlgorithm();
            if (!biometricInfo.isHashAlgorithmPermitted(hashAlgo)) {
                throw new BadCertTemplateException("biometricInfo[" + i + "].hashAlgorithm is not permitted");
            }
            int expHashValueSize;
            try {
                expHashValueSize = AlgorithmUtil.getHashOutputSizeInOctets(hashAlgo);
            } catch (NoSuchAlgorithmException ex) {
                throw new CertprofileException("should not happen, unknown hash algorithm " + hashAlgo);
            }
            byte[] hashValue = bd.getBiometricDataHash().getOctets();
            if (hashValue.length != expHashValueSize) {
                throw new BadCertTemplateException("biometricInfo[" + i + "].biometricDataHash has incorrect length");
            }
            DERIA5String sourceDataUri = bd.getSourceDataUri();
            switch(biometricInfo.getSourceDataUriOccurrence()) {
                case FORBIDDEN:
                    sourceDataUri = null;
                    break;
                case REQUIRED:
                    if (sourceDataUri == null) {
                        throw new BadCertTemplateException("biometricInfo[" + i + "].sourceDataUri is not specified in request but is required");
                    }
                    break;
                case OPTIONAL:
                    break;
                default:
                    throw new BadCertTemplateException("could not reach here, unknown tripleState");
            }
            AlgorithmIdentifier newHashAlg = new AlgorithmIdentifier(hashAlgo, DERNull.INSTANCE);
            BiometricData newBiometricData = new BiometricData(bdType, newHashAlg, new DEROctetString(hashValue), sourceDataUri);
            vec.add(newBiometricData);
        }
        ExtensionValue extValue = new ExtensionValue(extensionControls.get(type).isCritical(), new DERSequence(vec));
        values.addExtension(type, extValue);
        occurences.remove(type);
    }
    // TlsFeature
    type = ObjectIdentifiers.id_pe_tlsfeature;
    if (tlsFeature != null) {
        if (occurences.remove(type)) {
            values.addExtension(type, tlsFeature);
        }
    }
    // AuthorizationTemplate
    type = ObjectIdentifiers.id_xipki_ext_authorizationTemplate;
    if (authorizationTemplate != null) {
        if (occurences.remove(type)) {
            values.addExtension(type, authorizationTemplate);
        }
    }
    // SMIME
    type = ObjectIdentifiers.id_smimeCapabilities;
    if (smimeCapabilities != null) {
        if (occurences.remove(type)) {
            values.addExtension(type, smimeCapabilities);
        }
    }
    // constant extensions
    if (constantExtensions != null) {
        for (ASN1ObjectIdentifier m : constantExtensions.keySet()) {
            if (!occurences.remove(m)) {
                continue;
            }
            ExtensionValue extensionValue = constantExtensions.get(m);
            if (extensionValue != null) {
                values.addExtension(m, extensionValue);
            }
        }
    }
    ExtensionValues extraExtensions = getExtraExtensions(extensionOccurences, requestedSubject, grantedSubject, requestedExtensions, notBefore, notAfter, caInfo);
    if (extraExtensions != null) {
        for (ASN1ObjectIdentifier m : extraExtensions.getExtensionTypes()) {
            values.addExtension(m, extraExtensions.getExtensionValue(m));
        }
    }
    return values;
}
Also used : BiometricData(org.bouncycastle.asn1.x509.qualified.BiometricData) TypeOfBiometricData(org.bouncycastle.asn1.x509.qualified.TypeOfBiometricData) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) DERPrintableString(org.bouncycastle.asn1.DERPrintableString) DERUTF8String(org.bouncycastle.asn1.DERUTF8String) DirectoryString(org.bouncycastle.asn1.x500.DirectoryString) DEROctetString(org.bouncycastle.asn1.DEROctetString) DERIA5String(org.bouncycastle.asn1.DERIA5String) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) DEROctetString(org.bouncycastle.asn1.DEROctetString) AlgorithmIdentifier(org.bouncycastle.asn1.x509.AlgorithmIdentifier) DERSequence(org.bouncycastle.asn1.DERSequence) ExtensionValue(org.xipki.ca.api.profile.ExtensionValue) DERGeneralizedTime(org.bouncycastle.asn1.DERGeneralizedTime) Range2Type(org.xipki.ca.certprofile.x509.jaxb.Range2Type) CertprofileException(org.xipki.ca.api.profile.CertprofileException) DERPrintableString(org.bouncycastle.asn1.DERPrintableString) ASN1EncodableVector(org.bouncycastle.asn1.ASN1EncodableVector) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList) ExtensionValues(org.xipki.ca.api.profile.ExtensionValues) Vector(java.util.Vector) ASN1EncodableVector(org.bouncycastle.asn1.ASN1EncodableVector) TypeOfBiometricData(org.bouncycastle.asn1.x509.qualified.TypeOfBiometricData) HashSet(java.util.HashSet) LinkedList(java.util.LinkedList) ASN1Sequence(org.bouncycastle.asn1.ASN1Sequence) GeneralNames(org.bouncycastle.asn1.x509.GeneralNames) BadCertTemplateException(org.xipki.ca.api.BadCertTemplateException) Map(java.util.Map) HashMap(java.util.HashMap) ASN1ObjectIdentifier(org.bouncycastle.asn1.ASN1ObjectIdentifier) DERUTF8String(org.bouncycastle.asn1.DERUTF8String) QCStatement(org.bouncycastle.asn1.x509.qualified.QCStatement) Attribute(org.bouncycastle.asn1.x509.Attribute) ASN1GeneralizedTime(org.bouncycastle.asn1.ASN1GeneralizedTime) DERSet(org.bouncycastle.asn1.DERSet) Iso4217CurrencyCode(org.bouncycastle.asn1.x509.qualified.Iso4217CurrencyCode) DERIA5String(org.bouncycastle.asn1.DERIA5String) Admissions(org.bouncycastle.asn1.isismtt.x509.Admissions) ASN1Encodable(org.bouncycastle.asn1.ASN1Encodable) ProfessionInfo(org.bouncycastle.asn1.isismtt.x509.ProfessionInfo) DERTaggedObject(org.bouncycastle.asn1.DERTaggedObject) SubjectDirectoryAttributes(org.bouncycastle.asn1.x509.SubjectDirectoryAttributes) MonetaryValue(org.bouncycastle.asn1.x509.qualified.MonetaryValue) Date(java.util.Date) Extension(org.bouncycastle.asn1.x509.Extension)

Aggregations

CertprofileException (org.xipki.ca.api.profile.CertprofileException)27 ASN1ObjectIdentifier (org.bouncycastle.asn1.ASN1ObjectIdentifier)18 HashMap (java.util.HashMap)8 IOException (java.io.IOException)7 HashSet (java.util.HashSet)7 DERPrintableString (org.bouncycastle.asn1.DERPrintableString)6 DERUTF8String (org.bouncycastle.asn1.DERUTF8String)6 BadCertTemplateException (org.xipki.ca.api.BadCertTemplateException)6 ExtensionValue (org.xipki.ca.api.profile.ExtensionValue)6 ASN1Encodable (org.bouncycastle.asn1.ASN1Encodable)5 ASN1Integer (org.bouncycastle.asn1.ASN1Integer)5 DERIA5String (org.bouncycastle.asn1.DERIA5String)5 DEROctetString (org.bouncycastle.asn1.DEROctetString)5 DERTaggedObject (org.bouncycastle.asn1.DERTaggedObject)5 DirectoryString (org.bouncycastle.asn1.x500.DirectoryString)5 X500Name (org.bouncycastle.asn1.x500.X500Name)5 CRLDistPoint (org.bouncycastle.asn1.x509.CRLDistPoint)5 BigInteger (java.math.BigInteger)4 ArrayList (java.util.ArrayList)4 LinkedList (java.util.LinkedList)4