use of org.openecard.bouncycastle.asn1.ASN1OctetString 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);
}
use of org.openecard.bouncycastle.asn1.ASN1OctetString 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;
}
use of org.openecard.bouncycastle.asn1.ASN1OctetString in project xipki by xipki.
the class X509CaCmpResponderImpl method processP10cr.
// method processCertReqMessages
/**
* handle the PKI body with the choice {@code p10cr}<br/>
* Since it is not possible to add attribute to the PKCS#10 request (CSR), the certificate
* profile must be specified in the attribute regInfo-utf8Pairs (1.3.6.1.5.5.7.5.2.1) within
* PKIHeader.generalInfo
*/
private PKIBody processP10cr(PKIMessage request, CmpRequestorInfo requestor, ASN1OctetString tid, PKIHeader reqHeader, CertificationRequest p10cr, CmpControl cmpControl, String msgId, AuditEvent event) {
// verify the POP first
CertResponse certResp;
ASN1Integer certReqId = new ASN1Integer(-1);
boolean certGenerated = false;
X509Ca ca = getCa();
if (!securityFactory.verifyPopo(p10cr, getCmpControl().getPopoAlgoValidator())) {
LOG.warn("could not validate POP for the pkcs#10 requst");
certResp = buildErrorCertResponse(certReqId, PKIFailureInfo.badPOP, "invalid POP");
} else {
CertificationRequestInfo certTemp = p10cr.getCertificationRequestInfo();
Extensions extensions = CaUtil.getExtensions(certTemp);
X500Name subject = certTemp.getSubject();
SubjectPublicKeyInfo publicKeyInfo = certTemp.getSubjectPublicKeyInfo();
CmpUtf8Pairs keyvalues = CmpUtil.extract(reqHeader.getGeneralInfo());
String certprofileName = null;
Date notBefore = null;
Date notAfter = null;
if (keyvalues != null) {
certprofileName = keyvalues.value(CmpUtf8Pairs.KEY_CERTPROFILE);
String str = keyvalues.value(CmpUtf8Pairs.KEY_NOTBEFORE);
if (str != null) {
notBefore = DateUtil.parseUtcTimeyyyyMMddhhmmss(str);
}
str = keyvalues.value(CmpUtf8Pairs.KEY_NOTAFTER);
if (str != null) {
notAfter = DateUtil.parseUtcTimeyyyyMMddhhmmss(str);
}
}
if (certprofileName == null) {
certResp = buildErrorCertResponse(certReqId, PKIFailureInfo.badCertTemplate, "badCertTemplate", null);
} else {
certprofileName = certprofileName.toLowerCase();
if (!requestor.isCertProfilePermitted(certprofileName)) {
String msg = "certprofile " + certprofileName + " is not allowed";
certResp = buildErrorCertResponse(certReqId, PKIFailureInfo.notAuthorized, msg);
} else {
CertTemplateData certTemplateData = new CertTemplateData(subject, publicKeyInfo, notBefore, notAfter, extensions, certprofileName);
certResp = generateCertificates(Arrays.asList(certTemplateData), Arrays.asList(certReqId), requestor, tid, false, request, cmpControl, msgId, event).get(0);
certGenerated = true;
}
}
}
CMPCertificate[] caPubs = null;
if (certGenerated && cmpControl.isSendCaCert()) {
caPubs = new CMPCertificate[] { ca.getCaInfo().getCertInCmpFormat() };
}
CertRepMessage repMessage = new CertRepMessage(caPubs, new CertResponse[] { certResp });
return new PKIBody(PKIBody.TYPE_CERT_REP, repMessage);
}
use of org.openecard.bouncycastle.asn1.ASN1OctetString in project xipki by xipki.
the class X509CaCmpResponderImpl method processCertReqMessages.
private CertRepMessage processCertReqMessages(PKIMessage request, CmpRequestorInfo requestor, ASN1OctetString tid, PKIHeader reqHeader, CertReqMessages kur, boolean keyUpdate, CmpControl cmpControl, String msgId, 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;
}
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.value(CmpUtf8Pairs.KEY_CERTPROFILE);
if (certprofileName == null) {
String msg = "no certificate profile";
certResponses.put(i, buildErrorCertResponse(certReqId, PKIFailureInfo.badCertTemplate, msg));
continue;
}
certprofileName = certprofileName.toLowerCase();
if (!tmpRequestor.isCertProfilePermitted(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);
}
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, 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);
}
use of org.openecard.bouncycastle.asn1.ASN1OctetString in project xipki by xipki.
the class X509CaCmpResponderImpl method cmpGeneralMsg.
// method cmpRevokeOrUnrevokeOrRemoveCertificates
private PKIBody cmpGeneralMsg(PKIHeaderBuilder respHeader, CmpControl cmpControl, PKIHeader reqHeader, PKIBody reqBody, CmpRequestorInfo requestor, ASN1OctetString tid, String msgId, AuditEvent event) throws InsuffientPermissionException {
GenMsgContent genMsgBody = GenMsgContent.getInstance(reqBody.getContent());
InfoTypeAndValue[] itvs = genMsgBody.toInfoTypeAndValueArray();
InfoTypeAndValue itv = null;
if (itvs != null && itvs.length > 0) {
for (InfoTypeAndValue entry : itvs) {
String itvType = entry.getInfoType().getId();
if (KNOWN_GENMSG_IDS.contains(itvType)) {
itv = entry;
break;
}
}
}
if (itv == null) {
String statusMessage = "PKIBody type " + PKIBody.TYPE_GEN_MSG + " is only supported with the sub-types " + KNOWN_GENMSG_IDS.toString();
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badRequest, statusMessage);
}
InfoTypeAndValue itvResp = null;
ASN1ObjectIdentifier infoType = itv.getInfoType();
int failureInfo;
try {
X509Ca ca = getCa();
if (CMPObjectIdentifiers.it_currentCRL.equals(infoType)) {
event.addEventType(CaAuditConstants.TYPE_CMP_genm_currentCrl);
checkPermission(requestor, PermissionConstants.GET_CRL);
CertificateList crl = ca.getBcCurrentCrl();
if (itv.getInfoValue() == null) {
// as defined in RFC 4210
crl = ca.getBcCurrentCrl();
} else {
// xipki extension
ASN1Integer crlNumber = ASN1Integer.getInstance(itv.getInfoValue());
crl = ca.getBcCrl(crlNumber.getPositiveValue());
}
if (crl == null) {
String statusMessage = "no CRL is available";
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.systemFailure, statusMessage);
}
itvResp = new InfoTypeAndValue(infoType, crl);
} else if (ObjectIdentifiers.id_xipki_cmp_cmpGenmsg.equals(infoType)) {
ASN1Encodable asn1 = itv.getInfoValue();
ASN1Integer asn1Code = null;
ASN1Encodable reqValue = null;
try {
ASN1Sequence seq = ASN1Sequence.getInstance(asn1);
asn1Code = ASN1Integer.getInstance(seq.getObjectAt(0));
if (seq.size() > 1) {
reqValue = seq.getObjectAt(1);
}
} catch (IllegalArgumentException ex) {
String statusMessage = "invalid value of the InfoTypeAndValue for " + ObjectIdentifiers.id_xipki_cmp_cmpGenmsg.getId();
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badRequest, statusMessage);
}
ASN1Encodable respValue;
int action = asn1Code.getPositiveValue().intValue();
switch(action) {
case XiSecurityConstants.CMP_ACTION_GEN_CRL:
event.addEventType(CaAuditConstants.TYPE_CMP_genm_genCrl);
checkPermission(requestor, PermissionConstants.GEN_CRL);
X509CRL tmpCrl = ca.generateCrlOnDemand(msgId);
if (tmpCrl == null) {
String statusMessage = "CRL generation is not activated";
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.systemFailure, statusMessage);
} else {
respValue = CertificateList.getInstance(tmpCrl.getEncoded());
}
break;
case XiSecurityConstants.CMP_ACTION_GET_CRL_WITH_SN:
event.addEventType(CaAuditConstants.TYPE_CMP_genm_crlForNumber);
checkPermission(requestor, PermissionConstants.GET_CRL);
ASN1Integer crlNumber = ASN1Integer.getInstance(reqValue);
respValue = ca.getBcCrl(crlNumber.getPositiveValue());
if (respValue == null) {
String statusMessage = "no CRL is available";
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.systemFailure, statusMessage);
}
break;
case XiSecurityConstants.CMP_ACTION_GET_CAINFO:
event.addEventType(CaAuditConstants.TYPE_CMP_genm_cainfo);
Set<Integer> acceptVersions = new HashSet<>();
if (reqValue != null) {
ASN1Sequence seq = DERSequence.getInstance(reqValue);
int size = seq.size();
for (int i = 0; i < size; i++) {
ASN1Integer ai = ASN1Integer.getInstance(seq.getObjectAt(i));
acceptVersions.add(ai.getPositiveValue().intValue());
}
}
if (CollectionUtil.isEmpty(acceptVersions)) {
acceptVersions.add(1);
}
String systemInfo = getSystemInfo(requestor, acceptVersions);
respValue = new DERUTF8String(systemInfo);
break;
default:
String statusMessage = "unsupported XiPKI action code '" + action + "'";
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badRequest, statusMessage);
}
// end switch (action)
ASN1EncodableVector vec = new ASN1EncodableVector();
vec.add(asn1Code);
if (respValue != null) {
vec.add(respValue);
}
itvResp = new InfoTypeAndValue(infoType, new DERSequence(vec));
} else if (ObjectIdentifiers.id_xipki_cmp_cacerts.equals(infoType)) {
event.addEventType(CaAuditConstants.TYPE_CMP_genm_cacerts);
CMPCertificate caCert = ca.getCaInfo().getCertInCmpFormat();
itvResp = new InfoTypeAndValue(infoType, new DERSequence(caCert));
}
GenRepContent genRepContent = new GenRepContent(itvResp);
return new PKIBody(PKIBody.TYPE_GEN_REP, genRepContent);
} catch (OperationException ex) {
failureInfo = getPKiFailureInfo(ex);
ErrorCode code = ex.getErrorCode();
String errorMessage;
switch(code) {
case DATABASE_FAILURE:
case SYSTEM_FAILURE:
errorMessage = code.name();
break;
default:
errorMessage = code.name() + ": " + ex.getErrorMessage();
break;
}
return buildErrorMsgPkiBody(PKIStatus.rejection, failureInfo, errorMessage);
} catch (CRLException ex) {
String statusMessage = "CRLException: " + ex.getMessage();
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.systemFailure, statusMessage);
}
}
Aggregations