Example usage for org.bouncycastle.asn1.crmf CertTemplate getExtensions

List of usage examples for org.bouncycastle.asn1.crmf CertTemplate getExtensions

Introduction

In this page you can find the example usage for org.bouncycastle.asn1.crmf CertTemplate getExtensions.

Prototype

public Extensions getExtensions() 

Source Link

Usage

From source file:org.ejbca.core.protocol.cmp.CrmfRequestMessage.java

License:Open Source License

@Override
public String getRequestAltNames() {
    String ret = null;//from  w w  w  . j a v a2 s  .c  om
    final CertTemplate templ = getReq().getCertReq().getCertTemplate();
    final Extensions exts = templ.getExtensions();
    if (exts != null) {
        final Extension ext = exts.getExtension(Extension.subjectAlternativeName);
        if (ext != null) {
            ret = CertTools.getAltNameStringFromExtension(ext);
        }
    }
    if (log.isDebugEnabled()) {
        log.debug("Request altName is: " + ret);
    }
    return ret;
}

From source file:org.ejbca.core.protocol.cmp.CrmfRequestMessage.java

License:Open Source License

@Override
public Extensions getRequestExtensions() {
    final CertTemplate templ = getReq().getCertReq().getCertTemplate();
    final Extensions exts = templ.getExtensions();
    if (log.isDebugEnabled()) {
        if (exts != null) {
            log.debug("Request contains extensions");
        } else {//from w  ww . j  a v a 2 s  .c  om
            log.debug("Request does not contain extensions");
        }
    }
    return exts;
}

From source file:org.xipki.ca.server.impl.X509CACmpResponder.java

License:Open Source License

private CertRepMessage processCertReqMessages(final CmpRequestorInfo requestor, final String user,
        final ASN1OctetString tid, final PKIHeader reqHeader, final CertReqMessages kur,
        final boolean keyUpdate, final long confirmWaitTime, final boolean sendCaCert,
        final AuditEvent auditEvent) throws InsuffientPermissionException {
    CmpRequestorInfo _requestor = (CmpRequestorInfo) requestor;

    CertReqMsg[] certReqMsgs = kur.toCertReqMsgArray();
    CertResponse[] certResponses = new CertResponse[certReqMsgs.length];

    for (int i = 0; i < certReqMsgs.length; i++) {
        AuditChildEvent childAuditEvent = null;
        if (auditEvent != null) {
            childAuditEvent = new AuditChildEvent();
            auditEvent.addChildAuditEvent(childAuditEvent);
        }/*from   w  w w. ja  v a2s .com*/

        CertReqMsg reqMsg = certReqMsgs[i];
        CertificateRequestMessage req = new CertificateRequestMessage(reqMsg);
        ASN1Integer certReqId = reqMsg.getCertReq().getCertReqId();
        if (childAuditEvent != null) {
            childAuditEvent
                    .addEventData(new AuditEventData("certReqId", certReqId.getPositiveValue().toString()));
        }

        if (req.hasProofOfPossession() == false) {
            PKIStatusInfo status = generateCmpRejectionStatus(PKIFailureInfo.badPOP, null);
            certResponses[i] = new CertResponse(certReqId, status);

            if (childAuditEvent != null) {
                childAuditEvent.setStatus(AuditStatus.FAILED);
                childAuditEvent.addEventData(new AuditEventData("message", "no POP"));
            }
            continue;
        }

        if (verifyPOP(req, _requestor.isRA()) == false) {
            LOG.warn("could not validate POP for requst {}", certReqId.getValue());
            PKIStatusInfo status = generateCmpRejectionStatus(PKIFailureInfo.badPOP, null);
            certResponses[i] = new CertResponse(certReqId, status);
            if (childAuditEvent != null) {
                childAuditEvent.setStatus(AuditStatus.FAILED);
                childAuditEvent.addEventData(new AuditEventData("message", "invalid POP"));
            }
            continue;
        }

        CertTemplate certTemp = req.getCertTemplate();
        Extensions extensions = certTemp.getExtensions();
        X500Name subject = certTemp.getSubject();
        SubjectPublicKeyInfo publicKeyInfo = certTemp.getPublicKey();
        OptionalValidity validity = certTemp.getValidity();

        try {
            CmpUtf8Pairs keyvalues = CmpUtil.extract(reqMsg.getRegInfo());
            String certprofileName = keyvalues == null ? null
                    : keyvalues.getValue(CmpUtf8Pairs.KEY_CERT_PROFILE);
            if (certprofileName == null) {
                throw new CMPException("no certificate profile is specified");
            }

            if (childAuditEvent != null) {
                childAuditEvent.addEventData(new AuditEventData("certprofile", certprofileName));
            }

            checkPermission(_requestor, certprofileName);
            certResponses[i] = generateCertificate(_requestor, user, tid, certReqId, subject, publicKeyInfo,
                    validity, extensions, certprofileName, keyUpdate, confirmWaitTime, childAuditEvent);
        } catch (CMPException e) {
            final String message = "generateCertificate";
            if (LOG.isWarnEnabled()) {
                LOG.warn(LogUtil.buildExceptionLogFormat(message), e.getClass().getName(), e.getMessage());
            }
            LOG.debug(message, e);

            certResponses[i] = new CertResponse(certReqId,
                    generateCmpRejectionStatus(PKIFailureInfo.badCertTemplate, e.getMessage()));

            if (childAuditEvent != null) {
                childAuditEvent.setStatus(AuditStatus.FAILED);
                childAuditEvent.addEventData(new AuditEventData("message", "badCertTemplate"));
            }
        } // end try
    } // end for

    CMPCertificate[] caPubs = sendCaCert ? new CMPCertificate[] { getCA().getCAInfo().getCertInCMPFormat() }
            : null;
    return new CertRepMessage(caPubs, certResponses);
}

From source file:org.xipki.ca.server.impl.X509CACmpResponder.java

License:Open Source License

private PKIBody revokeOrUnrevokeOrRemoveCertificates(final RevReqContent rr, final AuditEvent auditEvent,
        final Permission permission) {
    RevDetails[] revContent = rr.toRevDetailsArray();

    RevRepContentBuilder repContentBuilder = new RevRepContentBuilder();

    final int n = revContent.length;
    // test the reques
    for (int i = 0; i < n; i++) {
        RevDetails revDetails = revContent[i];

        CertTemplate certDetails = revDetails.getCertDetails();
        X500Name issuer = certDetails.getIssuer();
        ASN1Integer serialNumber = certDetails.getSerialNumber();

        try {/*  w  w w . j  ava 2 s.c om*/
            X500Name caSubject = getCA().getCAInfo().getCertificate().getSubjectAsX500Name();

            if (issuer == null) {
                return createErrorMsgPKIBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate,
                        "issuer is not present");
            } else if (issuer.equals(caSubject) == false) {
                return createErrorMsgPKIBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate,
                        "issuer not targets at the CA");
            } else if (serialNumber == null) {
                return createErrorMsgPKIBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate,
                        "serialNumber is not present");
            } else if (certDetails.getSigningAlg() != null || certDetails.getValidity() != null
                    || certDetails.getSubject() != null || certDetails.getPublicKey() != null
                    || certDetails.getIssuerUID() != null || certDetails.getSubjectUID() != null
                    || certDetails.getExtensions() != null) {
                return createErrorMsgPKIBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate,
                        "only version, issuer and serialNumber in RevDetails.certDetails are allowed, "
                                + "but more is specified");
            }
        } catch (IllegalArgumentException e) {
            return createErrorMsgPKIBody(PKIStatus.rejection, PKIFailureInfo.badRequest,
                    "the request is not invalid");
        }
    }

    for (int i = 0; i < n; i++) {
        AuditChildEvent childAuditEvent = null;
        if (auditEvent != null) {
            childAuditEvent = new AuditChildEvent();
            auditEvent.addChildAuditEvent(childAuditEvent);
        }

        RevDetails revDetails = revContent[i];

        CertTemplate certDetails = revDetails.getCertDetails();
        ASN1Integer serialNumber = certDetails.getSerialNumber();
        // serialNumber is not null due to the check in the previous for-block.

        X500Name caSubject = getCA().getCAInfo().getCertificate().getSubjectAsX500Name();
        BigInteger snBigInt = serialNumber.getPositiveValue();
        CertId certId = new CertId(new GeneralName(caSubject), serialNumber);

        if (childAuditEvent != null) {
            AuditEventData eventData = new AuditEventData("serialNumber", snBigInt.toString());
            childAuditEvent.addEventData(eventData);
        }

        PKIStatusInfo status;

        try {
            Object returnedObj = null;
            X509CA ca = getCA();
            if (Permission.UNREVOKE_CERT == permission) {
                // unrevoke
                returnedObj = ca.unrevokeCertificate(snBigInt);
            } else if (Permission.REMOVE_CERT == permission) {
                // remove
                returnedObj = ca.removeCertificate(snBigInt);
            } else {
                // revoke
                Date invalidityDate = null;
                CRLReason reason = null;

                Extensions crlDetails = revDetails.getCrlEntryDetails();
                if (crlDetails != null) {
                    ASN1ObjectIdentifier extId = Extension.reasonCode;
                    ASN1Encodable extValue = crlDetails.getExtensionParsedValue(extId);
                    if (extValue != null) {
                        int reasonCode = ((ASN1Enumerated) extValue).getValue().intValue();
                        reason = CRLReason.forReasonCode(reasonCode);
                    }

                    extId = Extension.invalidityDate;
                    extValue = crlDetails.getExtensionParsedValue(extId);
                    if (extValue != null) {
                        try {
                            invalidityDate = ((ASN1GeneralizedTime) extValue).getDate();
                        } catch (ParseException e) {
                            throw new OperationException(ErrorCode.INVALID_EXTENSION,
                                    "invalid extension " + extId.getId());
                        }
                    }
                } // end if(crlDetails)

                if (reason == null) {
                    reason = CRLReason.UNSPECIFIED;
                }

                if (childAuditEvent != null) {
                    childAuditEvent.addEventData(new AuditEventData("reason", reason.getDescription()));
                    if (invalidityDate != null) {
                        String value;
                        synchronized (dateFormat) {
                            value = dateFormat.format(invalidityDate);
                        }
                        childAuditEvent.addEventData(new AuditEventData("invalidityDate", value));
                    }
                }

                returnedObj = ca.revokeCertificate(snBigInt, reason, invalidityDate);
            } // end if(permission)

            if (returnedObj == null) {
                throw new OperationException(ErrorCode.UNKNOWN_CERT, "cert not exists");
            }

            status = new PKIStatusInfo(PKIStatus.granted);
            if (childAuditEvent != null) {
                childAuditEvent.setStatus(AuditStatus.SUCCESSFUL);
            }
        } catch (OperationException e) {
            ErrorCode code = e.getErrorCode();
            LOG.warn("{} certificate, OperationException: code={}, message={}",
                    new Object[] { permission.name(), code.name(), e.getErrorMessage() });

            String auditMessage;

            int failureInfo;
            switch (code) {
            case BAD_REQUEST:
                failureInfo = PKIFailureInfo.badRequest;
                auditMessage = "BAD_REQUEST";
                break;
            case CERT_REVOKED:
                failureInfo = PKIFailureInfo.certRevoked;
                auditMessage = "CERT_REVOKED";
                break;
            case CERT_UNREVOKED:
                failureInfo = PKIFailureInfo.notAuthorized;
                auditMessage = "CERT_UNREVOKED";
                break;
            case DATABASE_FAILURE:
                failureInfo = PKIFailureInfo.systemFailure;
                auditMessage = "DATABASE_FAILURE";
                break;
            case INVALID_EXTENSION:
                failureInfo = PKIFailureInfo.unacceptedExtension;
                auditMessage = "INVALID_EXTENSION";
                break;
            case INSUFFICIENT_PERMISSION:
                failureInfo = PKIFailureInfo.notAuthorized;
                auditMessage = "INSUFFICIENT_PERMISSION";
                break;
            case NOT_PERMITTED:
                failureInfo = PKIFailureInfo.notAuthorized;
                auditMessage = "NOT_PERMITTED";
                break;
            case SYSTEM_FAILURE:
                failureInfo = PKIFailureInfo.systemFailure;
                auditMessage = "System_Failure";
                break;
            case SYSTEM_UNAVAILABLE:
                failureInfo = PKIFailureInfo.systemUnavail;
                auditMessage = "System_Unavailable";
                break;
            case UNKNOWN_CERT:
                failureInfo = PKIFailureInfo.badCertId;
                auditMessage = "UNKNOWN_CERT";
                break;
            default:
                failureInfo = PKIFailureInfo.systemFailure;
                auditMessage = "InternalErrorCode " + e.getErrorCode();
                break;
            } // end switch(code)

            if (childAuditEvent != null) {
                childAuditEvent.setStatus(AuditStatus.FAILED);
                childAuditEvent.addEventData(new AuditEventData("message", auditMessage));
            }

            String errorMessage;
            switch (code) {
            case DATABASE_FAILURE:
            case SYSTEM_FAILURE:
                errorMessage = code.name();
                break;
            default:
                errorMessage = code.name() + ": " + e.getErrorMessage();
                break;
            } // end switch(code)

            status = generateCmpRejectionStatus(failureInfo, errorMessage);
        } // end try

        repContentBuilder.add(status, certId);
    } // end for

    return new PKIBody(PKIBody.TYPE_REVOCATION_REP, repContentBuilder.build());
}

From source file:org.xipki.pki.ca.server.impl.cmp.X509CaCmpResponder.java

License:Open Source License

private CertRepMessage processCertReqMessages(final PKIMessage request, final CmpRequestorInfo requestor,
        final String user, final ASN1OctetString tid, final PKIHeader reqHeader, final CertReqMessages kur,
        final boolean keyUpdate, final CmpControl cmpControl, final String msgId, final AuditEvent event) {
    CmpRequestorInfo tmpRequestor = (CmpRequestorInfo) requestor;

    CertReqMsg[] certReqMsgs = kur.toCertReqMsgArray();
    final int n = certReqMsgs.length;

    Map<Integer, CertTemplateData> certTemplateDatas = new HashMap<>(n * 10 / 6);
    Map<Integer, CertResponse> certResponses = new HashMap<>(n * 10 / 6);
    Map<Integer, ASN1Integer> certReqIds = new HashMap<>(n * 10 / 6);

    // pre-process requests
    for (int i = 0; i < n; i++) {
        if (cmpControl.isGroupEnroll() && certTemplateDatas.size() != i) {
            // last certReqMsg cannot be used to enroll certificate
            break;
        }/*from  w  ww.  jav  a 2s.  c o  m*/

        CertReqMsg reqMsg = certReqMsgs[i];
        CertificateRequestMessage req = new CertificateRequestMessage(reqMsg);
        ASN1Integer certReqId = reqMsg.getCertReq().getCertReqId();
        certReqIds.put(i, certReqId);

        if (!req.hasProofOfPossession()) {
            certResponses.put(i, buildErrorCertResponse(certReqId, PKIFailureInfo.badPOP, "no POP", null));
            continue;
        }

        if (!verifyPopo(req, tmpRequestor.isRa())) {
            LOG.warn("could not validate POP for request {}", certReqId.getValue());
            certResponses.put(i, buildErrorCertResponse(certReqId, PKIFailureInfo.badPOP, "invalid POP", null));
            continue;
        }

        CmpUtf8Pairs keyvalues = CmpUtil.extract(reqMsg.getRegInfo());
        String certprofileName = (keyvalues == null) ? null : keyvalues.getValue(CmpUtf8Pairs.KEY_CERT_PROFILE);
        if (certprofileName == null) {
            String msg = "no certificate profile";
            certResponses.put(i, buildErrorCertResponse(certReqId, PKIFailureInfo.badCertTemplate, msg));
            continue;
        }

        if (!isCertProfilePermitted(tmpRequestor, certprofileName)) {
            String msg = "certprofile " + certprofileName + " is not allowed";
            certResponses.put(i, buildErrorCertResponse(certReqId, PKIFailureInfo.notAuthorized, msg));
            continue;
        }

        CertTemplate certTemp = req.getCertTemplate();
        OptionalValidity validity = certTemp.getValidity();

        Date notBefore = null;
        Date notAfter = null;
        if (validity != null) {
            Time time = validity.getNotBefore();
            if (time != null) {
                notBefore = time.getDate();
            }
            time = validity.getNotAfter();
            if (time != null) {
                notAfter = time.getDate();
            }
        }

        CertTemplateData certTempData = new CertTemplateData(certTemp.getSubject(), certTemp.getPublicKey(),
                notBefore, notAfter, certTemp.getExtensions(), certprofileName);
        certTemplateDatas.put(i, certTempData);
    } // end for

    if (certResponses.size() == n) {
        // all error
        CertResponse[] certResps = new CertResponse[n];
        for (int i = 0; i < n; i++) {
            certResps[i] = certResponses.get(i);
        }
        return new CertRepMessage(null, certResps);
    }

    if (cmpControl.isGroupEnroll() && certTemplateDatas.size() != n) {
        // at least one certRequest cannot be used to enroll certificate
        int lastFailureIndex = certTemplateDatas.size();
        BigInteger failCertReqId = certReqIds.get(lastFailureIndex).getPositiveValue();
        CertResponse failCertResp = certResponses.get(lastFailureIndex);
        PKIStatus failStatus = PKIStatus.getInstance(new ASN1Integer(failCertResp.getStatus().getStatus()));
        PKIFailureInfo failureInfo = new PKIFailureInfo(failCertResp.getStatus().getFailInfo());

        CertResponse[] certResps = new CertResponse[n];

        for (int i = 0; i < n; i++) {
            if (i == lastFailureIndex) {
                certResps[i] = failCertResp;
                continue;
            }

            ASN1Integer certReqId = certReqIds.get(i);
            String msg = "error in certReq " + failCertReqId;
            PKIStatusInfo tmpStatus = generateRejectionStatus(failStatus, failureInfo.intValue(), msg);
            certResps[i] = new CertResponse(certReqId, tmpStatus);
        }

        return new CertRepMessage(null, certResps);
    }

    final int k = certTemplateDatas.size();
    List<CertTemplateData> certTemplateList = new ArrayList<>(k);
    List<ASN1Integer> certReqIdList = new ArrayList<>(k);
    Map<Integer, Integer> reqIndexToCertIndexMap = new HashMap<>(k * 10 / 6);

    for (int i = 0; i < n; i++) {
        if (!certTemplateDatas.containsKey(i)) {
            continue;
        }

        certTemplateList.add(certTemplateDatas.get(i));
        certReqIdList.add(certReqIds.get(i));
        reqIndexToCertIndexMap.put(i, certTemplateList.size() - 1);
    }

    List<CertResponse> generateCertResponses = generateCertificates(certTemplateList, certReqIdList,
            tmpRequestor, user, tid, keyUpdate, request, cmpControl, msgId, event);
    boolean anyCertEnrolled = false;

    CertResponse[] certResps = new CertResponse[n];
    for (int i = 0; i < n; i++) {
        if (certResponses.containsKey(i)) {
            certResps[i] = certResponses.get(i);
        } else {
            int respIndex = reqIndexToCertIndexMap.get(i);
            certResps[i] = generateCertResponses.get(respIndex);
            if (!anyCertEnrolled && certResps[i].getCertifiedKeyPair() != null) {
                anyCertEnrolled = true;
            }
        }
    }

    CMPCertificate[] caPubs = null;
    if (anyCertEnrolled && cmpControl.isSendCaCert()) {
        caPubs = new CMPCertificate[] { getCa().getCaInfo().getCertInCmpFormat() };
    }

    return new CertRepMessage(caPubs, certResps);
}

From source file:org.xipki.pki.ca.server.impl.cmp.X509CaCmpResponder.java

License:Open Source License

private PKIBody unRevokeRemoveCertificates(final PKIMessage request, final RevReqContent rr,
        final Permission permission, final CmpControl cmpControl, final String msgId) {
    RevDetails[] revContent = rr.toRevDetailsArray();

    RevRepContentBuilder repContentBuilder = new RevRepContentBuilder();
    final int n = revContent.length;
    // test the request
    for (int i = 0; i < n; i++) {
        RevDetails revDetails = revContent[i];

        CertTemplate certDetails = revDetails.getCertDetails();
        X500Name issuer = certDetails.getIssuer();
        ASN1Integer serialNumber = certDetails.getSerialNumber();

        try {//from  w ww  .  j  a  va 2s  .c o m
            X500Name caSubject = getCa().getCaInfo().getCertificate().getSubjectAsX500Name();

            if (issuer == null) {
                return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate,
                        "issuer is not present");
            }

            if (!issuer.equals(caSubject)) {
                return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate,
                        "issuer does not target at the CA");
            }

            if (serialNumber == null) {
                return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate,
                        "serialNumber is not present");
            }

            if (certDetails.getSigningAlg() != null || certDetails.getValidity() != null
                    || certDetails.getSubject() != null || certDetails.getPublicKey() != null
                    || certDetails.getIssuerUID() != null || certDetails.getSubjectUID() != null) {
                return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate,
                        "only version, issuer and serialNumber in RevDetails.certDetails are "
                                + "allowed, but more is specified");
            }

            if (certDetails.getExtensions() == null) {
                if (cmpControl.isRrAkiRequired()) {
                    return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate,
                            "issuer's AKI not present");
                }
            } else {
                Extensions exts = certDetails.getExtensions();
                ASN1ObjectIdentifier[] oids = exts.getCriticalExtensionOIDs();
                if (oids != null) {
                    for (ASN1ObjectIdentifier oid : oids) {
                        if (!Extension.authorityKeyIdentifier.equals(oid)) {
                            return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate,
                                    "unknown critical extension " + oid.getId());
                        }
                    }
                }

                Extension ext = exts.getExtension(Extension.authorityKeyIdentifier);
                if (ext == null) {
                    return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate,
                            "issuer's AKI not present");
                } else {
                    AuthorityKeyIdentifier aki = AuthorityKeyIdentifier.getInstance(ext.getParsedValue());

                    if (aki.getKeyIdentifier() == null) {
                        return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate,
                                "issuer's AKI not present");
                    }

                    boolean issuerMatched = true;

                    byte[] caSki = getCa().getCaInfo().getCertificate().getSubjectKeyIdentifier();
                    if (Arrays.equals(caSki, aki.getKeyIdentifier())) {
                        issuerMatched = false;
                    }

                    if (issuerMatched && aki.getAuthorityCertSerialNumber() != null) {
                        BigInteger caSerial = getCa().getCaInfo().getSerialNumber();
                        if (!caSerial.equals(aki.getAuthorityCertSerialNumber())) {
                            issuerMatched = false;
                        }
                    }

                    if (issuerMatched && aki.getAuthorityCertIssuer() != null) {
                        GeneralName[] names = aki.getAuthorityCertIssuer().getNames();
                        for (GeneralName name : names) {
                            if (name.getTagNo() != GeneralName.directoryName) {
                                issuerMatched = false;
                                break;
                            }

                            if (!caSubject.equals(name.getName())) {
                                issuerMatched = false;
                                break;
                            }
                        }
                    }

                    if (!issuerMatched) {
                        return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate,
                                "issuer does not target at the CA");
                    }
                }
            }
        } catch (IllegalArgumentException ex) {
            return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badRequest,
                    "the request is not invalid");
        }
    } // end for

    byte[] encodedRequest = null;
    if (getCa().getCaInfo().isSaveRequest()) {
        try {
            encodedRequest = request.getEncoded();
        } catch (IOException ex) {
            LOG.warn("could not encode request");
        }
    }

    Long reqDbId = null;

    for (int i = 0; i < n; i++) {
        RevDetails revDetails = revContent[i];

        CertTemplate certDetails = revDetails.getCertDetails();
        ASN1Integer serialNumber = certDetails.getSerialNumber();
        // serialNumber is not null due to the check in the previous for-block.

        X500Name caSubject = getCa().getCaInfo().getCertificate().getSubjectAsX500Name();
        BigInteger snBigInt = serialNumber.getPositiveValue();
        CertId certId = new CertId(new GeneralName(caSubject), serialNumber);

        PKIStatusInfo status;

        try {
            Object returnedObj = null;
            Long certDbId = null;
            X509Ca ca = getCa();
            if (Permission.UNREVOKE_CERT == permission) {
                // unrevoke
                returnedObj = ca.unrevokeCertificate(snBigInt, msgId);
                if (returnedObj != null) {
                    certDbId = ((X509CertWithDbId) returnedObj).getCertId();
                }
            } else if (Permission.REMOVE_CERT == permission) {
                // remove
                returnedObj = ca.removeCertificate(snBigInt, msgId);
            } else {
                // revoke
                Date invalidityDate = null;
                CrlReason reason = null;

                Extensions crlDetails = revDetails.getCrlEntryDetails();
                if (crlDetails != null) {
                    ASN1ObjectIdentifier extId = Extension.reasonCode;
                    ASN1Encodable extValue = crlDetails.getExtensionParsedValue(extId);
                    if (extValue != null) {
                        int reasonCode = ASN1Enumerated.getInstance(extValue).getValue().intValue();
                        reason = CrlReason.forReasonCode(reasonCode);
                    }

                    extId = Extension.invalidityDate;
                    extValue = crlDetails.getExtensionParsedValue(extId);
                    if (extValue != null) {
                        try {
                            invalidityDate = ASN1GeneralizedTime.getInstance(extValue).getDate();
                        } catch (ParseException ex) {
                            throw new OperationException(ErrorCode.INVALID_EXTENSION,
                                    "invalid extension " + extId.getId());
                        }
                    }
                } // end if (crlDetails)

                if (reason == null) {
                    reason = CrlReason.UNSPECIFIED;
                }

                returnedObj = ca.revokeCertificate(snBigInt, reason, invalidityDate, msgId);
                if (returnedObj != null) {
                    certDbId = ((X509CertWithRevocationInfo) returnedObj).getCert().getCertId();
                }
            } // end if (permission)

            if (returnedObj == null) {
                throw new OperationException(ErrorCode.UNKNOWN_CERT, "cert not exists");
            }

            if (certDbId != null && ca.getCaInfo().isSaveRequest()) {
                if (reqDbId == null) {
                    reqDbId = ca.addRequest(encodedRequest);
                }
                ca.addRequestCert(reqDbId, certDbId);
            }
            status = new PKIStatusInfo(PKIStatus.granted);
        } catch (OperationException ex) {
            ErrorCode code = ex.getErrorCode();
            LOG.warn("{} certificate, OperationException: code={}, message={}", permission.name(), code.name(),
                    ex.getErrorMessage());
            String errorMessage;
            switch (code) {
            case DATABASE_FAILURE:
            case SYSTEM_FAILURE:
                errorMessage = code.name();
                break;
            default:
                errorMessage = code.name() + ": " + ex.getErrorMessage();
                break;
            } // end switch code

            int failureInfo = getPKiFailureInfo(ex);
            status = generateRejectionStatus(failureInfo, errorMessage);
        } // end try

        repContentBuilder.add(status, certId);
    } // end for

    return new PKIBody(PKIBody.TYPE_REVOCATION_REP, repContentBuilder.build());
}