Search in sources :

Example 1 with GeneralPKIMessage

use of org.bouncycastle.cert.cmp.GeneralPKIMessage in project xipki by xipki.

the class CmpCaClient method transmit.

private PKIMessage transmit(ProtectedPKIMessage request) throws Exception {
    byte[] encodedResponse = send(request.toASN1Structure().getEncoded());
    GeneralPKIMessage response = new GeneralPKIMessage(encodedResponse);
    PKIHeader reqHeader = request.getHeader();
    PKIHeader respHeader = response.getHeader();
    ASN1OctetString tid = reqHeader.getTransactionID();
    if (!tid.equals(respHeader.getTransactionID())) {
        throw new Exception("response.transactionId != request.transactionId");
    }
    ASN1OctetString senderNonce = reqHeader.getSenderNonce();
    if (!senderNonce.equals(respHeader.getRecipNonce())) {
        throw new Exception("response.recipientNonce != request.senderNonce");
    }
    GeneralName rec = respHeader.getRecipient();
    if (!requestorSubject.equals(rec)) {
        throw new Exception("unknown CMP requestor " + rec.toString());
    }
    if (!response.hasProtection()) {
        PKIBody respBody = response.getBody();
        int bodyType = respBody.getType();
        if (bodyType != PKIBody.TYPE_ERROR) {
            throw new Exception("response is not signed");
        }
    }
    if (verifyProtection(response)) {
        return response.toASN1Structure();
    }
    throw new Exception("invalid signature in PKI protection");
}
Also used : PKIHeader(org.bouncycastle.asn1.cmp.PKIHeader) ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) PKIBody(org.bouncycastle.asn1.cmp.PKIBody) GeneralName(org.bouncycastle.asn1.x509.GeneralName) OperatorCreationException(org.bouncycastle.operator.OperatorCreationException) CMPException(org.bouncycastle.cert.cmp.CMPException) InvalidKeyException(java.security.InvalidKeyException) IOException(java.io.IOException) GeneralPKIMessage(org.bouncycastle.cert.cmp.GeneralPKIMessage)

Example 2 with GeneralPKIMessage

use of org.bouncycastle.cert.cmp.GeneralPKIMessage 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 3 with GeneralPKIMessage

use of org.bouncycastle.cert.cmp.GeneralPKIMessage in project xipki by xipki.

the class CmpRequestor method signAndSend.

protected PkiResponse signAndSend(PKIMessage request, RequestResponseDebug debug) throws CmpRequestorException {
    ParamUtil.requireNonNull("request", request);
    PKIMessage tmpRequest = (signRequest) ? sign(request) : request;
    byte[] encodedRequest;
    try {
        encodedRequest = tmpRequest.getEncoded();
    } catch (IOException ex) {
        LOG.error("could not encode the PKI request {}", tmpRequest);
        throw new CmpRequestorException(ex.getMessage(), ex);
    }
    RequestResponsePair reqResp = null;
    if (debug != null) {
        reqResp = new RequestResponsePair();
        debug.add(reqResp);
        if (debug.saveRequest()) {
            reqResp.setRequest(encodedRequest);
        }
    }
    byte[] encodedResponse;
    try {
        encodedResponse = send(encodedRequest);
    } catch (IOException ex) {
        LOG.error("could not send the PKI request {} to server", tmpRequest);
        throw new CmpRequestorException("TRANSPORT_ERROR", ex);
    }
    if (reqResp != null && debug.saveResponse()) {
        reqResp.setResponse(encodedResponse);
    }
    GeneralPKIMessage response;
    try {
        response = new GeneralPKIMessage(encodedResponse);
    } catch (IOException ex) {
        LOG.error("could not decode the received PKI message: {}", Hex.encode(encodedResponse));
        throw new CmpRequestorException(ex.getMessage(), ex);
    }
    PKIHeader reqHeader = request.getHeader();
    PKIHeader respHeader = response.getHeader();
    ASN1OctetString tid = reqHeader.getTransactionID();
    ASN1OctetString respTid = respHeader.getTransactionID();
    if (!tid.equals(respTid)) {
        LOG.warn("Response contains different tid ({}) than requested {}", respTid, tid);
        throw new CmpRequestorException("Response contains differnt tid than the request");
    }
    ASN1OctetString senderNonce = reqHeader.getSenderNonce();
    ASN1OctetString respRecipientNonce = respHeader.getRecipNonce();
    if (!senderNonce.equals(respRecipientNonce)) {
        LOG.warn("tid {}: response.recipientNonce ({}) != request.senderNonce ({})", tid, respRecipientNonce, senderNonce);
        throw new CmpRequestorException("Response contains differnt tid than the request");
    }
    GeneralName rec = respHeader.getRecipient();
    if (!sender.equals(rec)) {
        LOG.warn("tid={}: unknown CMP requestor '{}'", tid, rec);
    }
    PkiResponse ret = new PkiResponse(response);
    if (response.hasProtection()) {
        try {
            ProtectionVerificationResult verifyProtection = verifyProtection(Hex.encode(tid.getOctets()), response);
            ret.setProtectionVerificationResult(verifyProtection);
        } catch (InvalidKeyException | OperatorCreationException | CMPException ex) {
            throw new CmpRequestorException(ex.getMessage(), ex);
        }
    } else if (signRequest) {
        PKIBody respBody = response.getBody();
        int bodyType = respBody.getType();
        if (bodyType != PKIBody.TYPE_ERROR) {
            throw new CmpRequestorException("response is not signed");
        }
    }
    return ret;
}
Also used : ProtectedPKIMessage(org.bouncycastle.cert.cmp.ProtectedPKIMessage) PKIMessage(org.bouncycastle.asn1.cmp.PKIMessage) GeneralPKIMessage(org.bouncycastle.cert.cmp.GeneralPKIMessage) RequestResponsePair(org.xipki.common.RequestResponsePair) PKIHeader(org.bouncycastle.asn1.cmp.PKIHeader) ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) PkiResponse(org.xipki.cmp.PkiResponse) PKIBody(org.bouncycastle.asn1.cmp.PKIBody) ProtectionVerificationResult(org.xipki.cmp.ProtectionVerificationResult) IOException(java.io.IOException) InvalidKeyException(java.security.InvalidKeyException) GeneralPKIMessage(org.bouncycastle.cert.cmp.GeneralPKIMessage) CMPException(org.bouncycastle.cert.cmp.CMPException) GeneralName(org.bouncycastle.asn1.x509.GeneralName) OperatorCreationException(org.bouncycastle.operator.OperatorCreationException)

Example 4 with GeneralPKIMessage

use of org.bouncycastle.cert.cmp.GeneralPKIMessage in project xipki by xipki.

the class X509CaCmpResponderImpl method processPkiMessage0.

@Override
protected PKIMessage processPkiMessage0(PKIMessage request, RequestorInfo requestor, ASN1OctetString tid, GeneralPKIMessage message, String msgId, AuditEvent event) {
    if (!(requestor instanceof CmpRequestorInfo)) {
        throw new IllegalArgumentException("unknown requestor type " + requestor.getClass().getName());
    }
    CmpRequestorInfo tmpRequestor = (CmpRequestorInfo) requestor;
    event.addEventData(CaAuditConstants.NAME_requestor, tmpRequestor.getIdent().getName());
    PKIHeader reqHeader = message.getHeader();
    PKIHeaderBuilder respHeader = new PKIHeaderBuilder(reqHeader.getPvno().getValue().intValue(), getSender(), reqHeader.getSender());
    respHeader.setTransactionID(tid);
    ASN1OctetString senderNonce = reqHeader.getSenderNonce();
    if (senderNonce != null) {
        respHeader.setRecipNonce(senderNonce);
    }
    PKIBody respBody;
    PKIBody reqBody = message.getBody();
    final int type = reqBody.getType();
    CmpControl cmpControl = getCmpControl();
    try {
        switch(type) {
            case PKIBody.TYPE_CERT_REQ:
            case PKIBody.TYPE_KEY_UPDATE_REQ:
            case PKIBody.TYPE_P10_CERT_REQ:
            case PKIBody.TYPE_CROSS_CERT_REQ:
                String eventType = null;
                if (PKIBody.TYPE_CERT_REQ == type) {
                    eventType = CaAuditConstants.TYPE_CMP_cr;
                } else if (PKIBody.TYPE_KEY_UPDATE_REQ == type) {
                    eventType = CaAuditConstants.TYPE_CMP_kur;
                } else if (PKIBody.TYPE_P10_CERT_REQ == type) {
                    eventType = CaAuditConstants.TYPE_CMP_p10Cr;
                } else if (PKIBody.TYPE_CROSS_CERT_REQ == type) {
                    eventType = CaAuditConstants.TYPE_CMP_ccr;
                }
                if (eventType != null) {
                    event.addEventType(eventType);
                }
                respBody = cmpEnrollCert(request, respHeader, cmpControl, reqHeader, reqBody, tmpRequestor, tid, msgId, event);
                break;
            case PKIBody.TYPE_CERT_CONFIRM:
                event.addEventType(CaAuditConstants.TYPE_CMP_certConf);
                CertConfirmContent certConf = (CertConfirmContent) reqBody.getContent();
                respBody = confirmCertificates(tid, certConf, msgId);
                break;
            case PKIBody.TYPE_REVOCATION_REQ:
                respBody = cmpUnRevokeRemoveCertificates(request, respHeader, cmpControl, reqHeader, reqBody, tmpRequestor, msgId, event);
                break;
            case PKIBody.TYPE_CONFIRM:
                event.addEventType(CaAuditConstants.TYPE_CMP_pkiConf);
                respBody = new PKIBody(PKIBody.TYPE_CONFIRM, DERNull.INSTANCE);
                break;
            case PKIBody.TYPE_GEN_MSG:
                respBody = cmpGeneralMsg(respHeader, cmpControl, reqHeader, reqBody, tmpRequestor, tid, msgId, event);
                break;
            case PKIBody.TYPE_ERROR:
                event.addEventType(CaAuditConstants.TYPE_CMP_error);
                revokePendingCertificates(tid, msgId);
                respBody = new PKIBody(PKIBody.TYPE_CONFIRM, DERNull.INSTANCE);
                break;
            default:
                event.addEventType("PKIBody." + type);
                respBody = buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badRequest, "unsupported type " + type);
                break;
        }
    // end switch (type)
    } catch (InsuffientPermissionException ex) {
        ErrorMsgContent emc = new ErrorMsgContent(new PKIStatusInfo(PKIStatus.rejection, new PKIFreeText(ex.getMessage()), new PKIFailureInfo(PKIFailureInfo.notAuthorized)));
        respBody = new PKIBody(PKIBody.TYPE_ERROR, emc);
    }
    if (respBody.getType() == PKIBody.TYPE_ERROR) {
        ErrorMsgContent errorMsgContent = (ErrorMsgContent) respBody.getContent();
        AuditStatus auditStatus = AuditStatus.FAILED;
        org.xipki.cmp.PkiStatusInfo pkiStatus = new org.xipki.cmp.PkiStatusInfo(errorMsgContent.getPKIStatusInfo());
        if (pkiStatus.pkiFailureInfo() == PKIFailureInfo.systemFailure) {
            auditStatus = AuditStatus.FAILED;
        }
        event.setStatus(auditStatus);
        String statusString = pkiStatus.statusMessage();
        if (statusString != null) {
            event.addEventData(CaAuditConstants.NAME_message, statusString);
        }
    } else if (event.getStatus() == null) {
        event.setStatus(AuditStatus.SUCCESSFUL);
    }
    return new PKIMessage(respHeader.build(), respBody);
}
Also used : PKIHeader(org.bouncycastle.asn1.cmp.PKIHeader) ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) 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) InsuffientPermissionException(org.xipki.ca.api.InsuffientPermissionException) ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) DERUTF8String(org.bouncycastle.asn1.DERUTF8String) PKIFreeText(org.bouncycastle.asn1.cmp.PKIFreeText) PKIFailureInfo(org.bouncycastle.asn1.cmp.PKIFailureInfo) CertConfirmContent(org.bouncycastle.asn1.cmp.CertConfirmContent) AuditStatus(org.xipki.audit.AuditStatus) CmpControl(org.xipki.ca.server.mgmt.api.CmpControl) ErrorMsgContent(org.bouncycastle.asn1.cmp.ErrorMsgContent)

Aggregations

ASN1OctetString (org.bouncycastle.asn1.ASN1OctetString)4 PKIHeader (org.bouncycastle.asn1.cmp.PKIHeader)4 GeneralPKIMessage (org.bouncycastle.cert.cmp.GeneralPKIMessage)4 InvalidKeyException (java.security.InvalidKeyException)3 PKIBody (org.bouncycastle.asn1.cmp.PKIBody)3 PKIMessage (org.bouncycastle.asn1.cmp.PKIMessage)3 GeneralName (org.bouncycastle.asn1.x509.GeneralName)3 CMPException (org.bouncycastle.cert.cmp.CMPException)3 OperatorCreationException (org.bouncycastle.operator.OperatorCreationException)3 IOException (java.io.IOException)2 ProtectedPKIMessage (org.bouncycastle.cert.cmp.ProtectedPKIMessage)2 CmpControl (org.xipki.ca.server.mgmt.api.CmpControl)2 ProtectionVerificationResult (org.xipki.cmp.ProtectionVerificationResult)2 ParseException (java.text.ParseException)1 Date (java.util.Date)1 DEROctetString (org.bouncycastle.asn1.DEROctetString)1 DERUTF8String (org.bouncycastle.asn1.DERUTF8String)1 CertConfirmContent (org.bouncycastle.asn1.cmp.CertConfirmContent)1 ErrorMsgContent (org.bouncycastle.asn1.cmp.ErrorMsgContent)1 PKIFailureInfo (org.bouncycastle.asn1.cmp.PKIFailureInfo)1