Search in sources :

Example 6 with PKIMessage

use of org.bouncycastle.asn1.cmp.PKIMessage in project xipki by xipki.

the class CmpCaClient method verifyProtection.

// method extractGeneralRepContent
private boolean verifyProtection(GeneralPKIMessage pkiMessage) throws CMPException, InvalidKeyException {
    ProtectedPKIMessage protectedMsg = new ProtectedPKIMessage(pkiMessage);
    if (protectedMsg.hasPasswordBasedMacProtection()) {
        LOG.warn("protection is not signature based: " + pkiMessage.getHeader().getProtectionAlg().getAlgorithm().getId());
        return false;
    }
    PKIHeader header = protectedMsg.getHeader();
    if (!header.getSender().equals(responderSubject)) {
        LOG.warn("not authorized responder '{}'", header.getSender());
        return false;
    }
    String algOid = protectedMsg.getHeader().getProtectionAlg().getAlgorithm().getId();
    if (!trustedProtectionAlgOids.contains(algOid)) {
        LOG.warn("PKI protection algorithm is untrusted '{}'", algOid);
        return false;
    }
    ContentVerifierProvider verifierProvider = getContentVerifierProvider(responderCert.getPublicKey());
    if (verifierProvider == null) {
        LOG.warn("not authorized responder '{}'", header.getSender());
        return false;
    }
    return protectedMsg.verify(verifierProvider);
}
Also used : PKIHeader(org.bouncycastle.asn1.cmp.PKIHeader) ProtectedPKIMessage(org.bouncycastle.cert.cmp.ProtectedPKIMessage) ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) DEROctetString(org.bouncycastle.asn1.DEROctetString) DERUTF8String(org.bouncycastle.asn1.DERUTF8String) ContentVerifierProvider(org.bouncycastle.operator.ContentVerifierProvider)

Example 7 with PKIMessage

use of org.bouncycastle.asn1.cmp.PKIMessage in project xipki by xipki.

the class CmpResponder method verifyProtection.

private ProtectionVerificationResult verifyProtection(String tid, GeneralPKIMessage pkiMessage, CmpControl cmpControl) throws CMPException, InvalidKeyException, OperatorCreationException {
    ProtectedPKIMessage protectedMsg = new ProtectedPKIMessage(pkiMessage);
    if (protectedMsg.hasPasswordBasedMacProtection()) {
        LOG.warn("NOT_SIGNAUTRE_BASED: {}", pkiMessage.getHeader().getProtectionAlg().getAlgorithm().getId());
        return new ProtectionVerificationResult(null, ProtectionResult.NOT_SIGNATURE_BASED);
    }
    PKIHeader header = protectedMsg.getHeader();
    AlgorithmIdentifier protectionAlg = header.getProtectionAlg();
    if (!cmpControl.getSigAlgoValidator().isAlgorithmPermitted(protectionAlg)) {
        LOG.warn("SIG_ALGO_FORBIDDEN: {}", pkiMessage.getHeader().getProtectionAlg().getAlgorithm().getId());
        return new ProtectionVerificationResult(null, ProtectionResult.SIGALGO_FORBIDDEN);
    }
    CmpRequestorInfo requestor = getRequestor(header);
    if (requestor == null) {
        LOG.warn("tid={}: not authorized requestor '{}'", tid, header.getSender());
        return new ProtectionVerificationResult(null, ProtectionResult.SENDER_NOT_AUTHORIZED);
    }
    ContentVerifierProvider verifierProvider = securityFactory.getContentVerifierProvider(requestor.getCert().getCert());
    if (verifierProvider == null) {
        LOG.warn("tid={}: not authorized requestor '{}'", tid, header.getSender());
        return new ProtectionVerificationResult(requestor, ProtectionResult.SENDER_NOT_AUTHORIZED);
    }
    boolean signatureValid = protectedMsg.verify(verifierProvider);
    return new ProtectionVerificationResult(requestor, signatureValid ? ProtectionResult.VALID : ProtectionResult.INVALID);
}
Also used : PKIHeader(org.bouncycastle.asn1.cmp.PKIHeader) ProtectedPKIMessage(org.bouncycastle.cert.cmp.ProtectedPKIMessage) ProtectionVerificationResult(org.xipki.cmp.ProtectionVerificationResult) AlgorithmIdentifier(org.bouncycastle.asn1.x509.AlgorithmIdentifier) ContentVerifierProvider(org.bouncycastle.operator.ContentVerifierProvider)

Example 8 with PKIMessage

use of org.bouncycastle.asn1.cmp.PKIMessage in project xipki by xipki.

the class CmpResponder method buildErrorPkiMessage.

// method addProtection
protected PKIMessage buildErrorPkiMessage(ASN1OctetString tid, PKIHeader requestHeader, int failureCode, String statusText) {
    GeneralName respRecipient = requestHeader.getSender();
    PKIHeaderBuilder respHeader = new PKIHeaderBuilder(requestHeader.getPvno().getValue().intValue(), getSender(), respRecipient);
    respHeader.setMessageTime(new ASN1GeneralizedTime(new Date()));
    if (tid != null) {
        respHeader.setTransactionID(tid);
    }
    ASN1OctetString senderNonce = requestHeader.getSenderNonce();
    if (senderNonce != null) {
        respHeader.setRecipNonce(senderNonce);
    }
    PKIStatusInfo status = generateRejectionStatus(failureCode, statusText);
    ErrorMsgContent error = new ErrorMsgContent(status);
    PKIBody body = new PKIBody(PKIBody.TYPE_ERROR, error);
    return new PKIMessage(respHeader.build(), body);
}
Also used : ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) ProtectedPKIMessage(org.bouncycastle.cert.cmp.ProtectedPKIMessage) PKIMessage(org.bouncycastle.asn1.cmp.PKIMessage) GeneralPKIMessage(org.bouncycastle.cert.cmp.GeneralPKIMessage) PKIBody(org.bouncycastle.asn1.cmp.PKIBody) PKIHeaderBuilder(org.bouncycastle.asn1.cmp.PKIHeaderBuilder) PKIStatusInfo(org.bouncycastle.asn1.cmp.PKIStatusInfo) ASN1GeneralizedTime(org.bouncycastle.asn1.ASN1GeneralizedTime) GeneralName(org.bouncycastle.asn1.x509.GeneralName) ErrorMsgContent(org.bouncycastle.asn1.cmp.ErrorMsgContent) Date(java.util.Date)

Example 9 with PKIMessage

use of org.bouncycastle.asn1.cmp.PKIMessage in project xipki by xipki.

the class CmpResponder method processPkiMessage.

public PKIMessage processPkiMessage(PKIMessage pkiMessage, X509Certificate tlsClientCert, AuditEvent event) {
    ParamUtil.requireNonNull("pkiMessage", pkiMessage);
    ParamUtil.requireNonNull("event", event);
    GeneralPKIMessage message = new GeneralPKIMessage(pkiMessage);
    PKIHeader reqHeader = message.getHeader();
    ASN1OctetString tid = reqHeader.getTransactionID();
    String msgId = null;
    if (event != null) {
        msgId = RandomUtil.nextHexLong();
        event.addEventData(CaAuditConstants.NAME_mid, msgId);
    }
    if (tid == null) {
        byte[] randomBytes = randomTransactionId();
        tid = new DEROctetString(randomBytes);
    }
    String tidStr = Base64.encodeToString(tid.getOctets());
    if (event != null) {
        event.addEventData(CaAuditConstants.NAME_tid, tidStr);
    }
    int reqPvno = reqHeader.getPvno().getValue().intValue();
    if (reqPvno != PVNO_CMP2000) {
        if (event != null) {
            event.setLevel(AuditLevel.INFO);
            event.setStatus(AuditStatus.FAILED);
            event.addEventData(CaAuditConstants.NAME_message, "unsupproted version " + reqPvno);
        }
        return buildErrorPkiMessage(tid, reqHeader, PKIFailureInfo.unsupportedVersion, null);
    }
    CmpControl cmpControl = getCmpControl();
    Integer failureCode = null;
    String statusText = null;
    Date messageTime = null;
    if (reqHeader.getMessageTime() != null) {
        try {
            messageTime = reqHeader.getMessageTime().getDate();
        } catch (ParseException ex) {
            LogUtil.error(LOG, ex, "tid=" + tidStr + ": could not parse messageTime");
        }
    }
    GeneralName recipient = reqHeader.getRecipient();
    boolean intentMe = (recipient == null) ? true : intendsMe(recipient);
    if (!intentMe) {
        LOG.warn("tid={}: I am not the intended recipient, but '{}'", tid, reqHeader.getRecipient());
        failureCode = PKIFailureInfo.badRequest;
        statusText = "I am not the intended recipient";
    } else if (messageTime == null) {
        if (cmpControl.isMessageTimeRequired()) {
            failureCode = PKIFailureInfo.missingTimeStamp;
            statusText = "missing time-stamp";
        }
    } else {
        long messageTimeBias = cmpControl.getMessageTimeBias();
        if (messageTimeBias < 0) {
            messageTimeBias *= -1;
        }
        long msgTimeMs = messageTime.getTime();
        long currentTimeMs = System.currentTimeMillis();
        long bias = (msgTimeMs - currentTimeMs) / 1000L;
        if (bias > messageTimeBias) {
            failureCode = PKIFailureInfo.badTime;
            statusText = "message time is in the future";
        } else if (bias * -1 > messageTimeBias) {
            failureCode = PKIFailureInfo.badTime;
            statusText = "message too old";
        }
    }
    if (failureCode != null) {
        if (event != null) {
            event.setLevel(AuditLevel.INFO);
            event.setStatus(AuditStatus.FAILED);
            event.addEventData(CaAuditConstants.NAME_message, statusText);
        }
        return buildErrorPkiMessage(tid, reqHeader, failureCode, statusText);
    }
    boolean isProtected = message.hasProtection();
    CmpRequestorInfo requestor;
    String errorStatus;
    if (isProtected) {
        try {
            ProtectionVerificationResult verificationResult = verifyProtection(tidStr, message, cmpControl);
            ProtectionResult pr = verificationResult.getProtectionResult();
            switch(pr) {
                case VALID:
                    errorStatus = null;
                    break;
                case INVALID:
                    errorStatus = "request is protected by signature but invalid";
                    break;
                case NOT_SIGNATURE_BASED:
                    errorStatus = "request is not protected by signature";
                    break;
                case SENDER_NOT_AUTHORIZED:
                    errorStatus = "request is protected by signature but the requestor is not authorized";
                    break;
                case SIGALGO_FORBIDDEN:
                    errorStatus = "request is protected by signature but the protection algorithm" + " is forbidden";
                    break;
                default:
                    throw new RuntimeException("should not reach here, unknown ProtectionResult " + pr);
            }
            // end switch
            requestor = (CmpRequestorInfo) verificationResult.getRequestor();
        } catch (Exception ex) {
            LogUtil.error(LOG, ex, "tid=" + tidStr + ": could not verify the signature");
            errorStatus = "request has invalid signature based protection";
            requestor = null;
        }
    } else if (tlsClientCert != null) {
        boolean authorized = false;
        requestor = getRequestor(reqHeader);
        if (requestor != null) {
            if (tlsClientCert.equals(requestor.getCert().getCert())) {
                authorized = true;
            }
        }
        if (authorized) {
            errorStatus = null;
        } else {
            LOG.warn("tid={}: not authorized requestor (TLS client '{}')", tid, X509Util.getRfc4519Name(tlsClientCert.getSubjectX500Principal()));
            errorStatus = "requestor (TLS client certificate) is not authorized";
        }
    } else {
        errorStatus = "request has no protection";
        requestor = null;
    }
    if (errorStatus != null) {
        if (event != null) {
            event.setLevel(AuditLevel.INFO);
            event.setStatus(AuditStatus.FAILED);
            event.addEventData(CaAuditConstants.NAME_message, errorStatus);
        }
        return buildErrorPkiMessage(tid, reqHeader, PKIFailureInfo.badMessageCheck, errorStatus);
    }
    PKIMessage resp = processPkiMessage0(pkiMessage, requestor, tid, message, msgId, event);
    if (isProtected) {
        resp = addProtection(resp, event);
    } else {
    // protected by TLS connection
    }
    return resp;
}
Also used : PKIHeader(org.bouncycastle.asn1.cmp.PKIHeader) ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) ProtectionResult(org.xipki.cmp.ProtectionResult) ProtectedPKIMessage(org.bouncycastle.cert.cmp.ProtectedPKIMessage) PKIMessage(org.bouncycastle.asn1.cmp.PKIMessage) GeneralPKIMessage(org.bouncycastle.cert.cmp.GeneralPKIMessage) ProtectionVerificationResult(org.xipki.cmp.ProtectionVerificationResult) DEROctetString(org.bouncycastle.asn1.DEROctetString) ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) DEROctetString(org.bouncycastle.asn1.DEROctetString) Date(java.util.Date) OperatorCreationException(org.bouncycastle.operator.OperatorCreationException) CMPException(org.bouncycastle.cert.cmp.CMPException) ParseException(java.text.ParseException) InvalidKeyException(java.security.InvalidKeyException) GeneralPKIMessage(org.bouncycastle.cert.cmp.GeneralPKIMessage) CmpControl(org.xipki.ca.server.mgmt.api.CmpControl) ParseException(java.text.ParseException) GeneralName(org.bouncycastle.asn1.x509.GeneralName)

Example 10 with PKIMessage

use of org.bouncycastle.asn1.cmp.PKIMessage in project xipki by xipki.

the class X509CaCmpResponderImpl method cmpUnRevokeRemoveCertificates.

// method cmpEnrollCert
private PKIBody cmpUnRevokeRemoveCertificates(PKIMessage request, PKIHeaderBuilder respHeader, CmpControl cmpControl, PKIHeader reqHeader, PKIBody reqBody, CmpRequestorInfo requestor, String msgId, AuditEvent event) {
    Integer requiredPermission = null;
    boolean allRevdetailsOfSameType = true;
    RevReqContent rr = RevReqContent.getInstance(reqBody.getContent());
    RevDetails[] revContent = rr.toRevDetailsArray();
    int len = revContent.length;
    for (int i = 0; i < len; i++) {
        RevDetails revDetails = revContent[i];
        Extensions crlDetails = revDetails.getCrlEntryDetails();
        int reasonCode = CrlReason.UNSPECIFIED.getCode();
        if (crlDetails != null) {
            ASN1ObjectIdentifier extId = Extension.reasonCode;
            ASN1Encodable extValue = crlDetails.getExtensionParsedValue(extId);
            if (extValue != null) {
                reasonCode = ASN1Enumerated.getInstance(extValue).getValue().intValue();
            }
        }
        if (reasonCode == XiSecurityConstants.CMP_CRL_REASON_REMOVE) {
            if (requiredPermission == null) {
                event.addEventType(CaAuditConstants.TYPE_CMP_rr_remove);
                requiredPermission = PermissionConstants.REMOVE_CERT;
            } else if (requiredPermission != PermissionConstants.REMOVE_CERT) {
                allRevdetailsOfSameType = false;
                break;
            }
        } else if (reasonCode == CrlReason.REMOVE_FROM_CRL.getCode()) {
            if (requiredPermission == null) {
                event.addEventType(CaAuditConstants.TYPE_CMP_rr_unrevoke);
                requiredPermission = PermissionConstants.UNREVOKE_CERT;
            } else if (requiredPermission != PermissionConstants.UNREVOKE_CERT) {
                allRevdetailsOfSameType = false;
                break;
            }
        } else {
            if (requiredPermission == null) {
                event.addEventType(CaAuditConstants.TYPE_CMP_rr_revoke);
                requiredPermission = PermissionConstants.REVOKE_CERT;
            } else if (requiredPermission != PermissionConstants.REVOKE_CERT) {
                allRevdetailsOfSameType = false;
                break;
            }
        }
    }
    if (!allRevdetailsOfSameType) {
        ErrorMsgContent emc = new ErrorMsgContent(new PKIStatusInfo(PKIStatus.rejection, new PKIFreeText("not all revDetails are of the same type"), new PKIFailureInfo(PKIFailureInfo.badRequest)));
        return new PKIBody(PKIBody.TYPE_ERROR, emc);
    } else {
        try {
            checkPermission(requestor, requiredPermission);
        } catch (InsuffientPermissionException ex) {
            event.setStatus(AuditStatus.FAILED);
            event.addEventData(CaAuditConstants.NAME_message, "NOT_PERMITTED");
            return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.notAuthorized, null);
        }
        return unRevokeRemoveCertificates(request, rr, requiredPermission, cmpControl, msgId);
    }
}
Also used : PKIBody(org.bouncycastle.asn1.cmp.PKIBody) PKIStatusInfo(org.bouncycastle.asn1.cmp.PKIStatusInfo) InsuffientPermissionException(org.xipki.ca.api.InsuffientPermissionException) Extensions(org.bouncycastle.asn1.x509.Extensions) RevReqContent(org.bouncycastle.asn1.cmp.RevReqContent) PKIFreeText(org.bouncycastle.asn1.cmp.PKIFreeText) ASN1Integer(org.bouncycastle.asn1.ASN1Integer) BigInteger(java.math.BigInteger) PKIFailureInfo(org.bouncycastle.asn1.cmp.PKIFailureInfo) ASN1Encodable(org.bouncycastle.asn1.ASN1Encodable) ErrorMsgContent(org.bouncycastle.asn1.cmp.ErrorMsgContent) RevDetails(org.bouncycastle.asn1.cmp.RevDetails) ASN1ObjectIdentifier(org.bouncycastle.asn1.ASN1ObjectIdentifier)

Aggregations

PKIMessage (org.bouncycastle.asn1.cmp.PKIMessage)31 PKIBody (org.bouncycastle.asn1.cmp.PKIBody)24 Date (java.util.Date)18 ASN1OctetString (org.bouncycastle.asn1.ASN1OctetString)16 PKIHeader (org.bouncycastle.asn1.cmp.PKIHeader)16 IOException (java.io.IOException)14 ProtectedPKIMessage (org.bouncycastle.cert.cmp.ProtectedPKIMessage)13 X509Certificate (java.security.cert.X509Certificate)12 ASN1Integer (org.bouncycastle.asn1.ASN1Integer)11 DERUTF8String (org.bouncycastle.asn1.DERUTF8String)11 GeneralPKIMessage (org.bouncycastle.cert.cmp.GeneralPKIMessage)11 DEROctetString (org.bouncycastle.asn1.DEROctetString)10 InfoTypeAndValue (org.bouncycastle.asn1.cmp.InfoTypeAndValue)9 ContentInfo (org.bouncycastle.asn1.cms.ContentInfo)9 BigInteger (java.math.BigInteger)8 ASN1ObjectIdentifier (org.bouncycastle.asn1.ASN1ObjectIdentifier)8 X500Name (org.bouncycastle.asn1.x500.X500Name)7 Extensions (org.bouncycastle.asn1.x509.Extensions)7 InvalidKeyException (java.security.InvalidKeyException)6 CertificateException (java.security.cert.CertificateException)6