use of org.bouncycastle.asn1.x509.Time in project xipki by xipki.
the class ImportCrl method addCertificate.
private void addCertificate(AtomicLong maxId, int caId, Certificate cert, String profileName, String certLogId) throws DataAccessException, ImportCrlException {
// not issued by the given issuer
if (!caSubject.equals(cert.getIssuer())) {
LOG.warn("certificate {} is not issued by the given CA, ignore it", certLogId);
return;
}
// we don't use the binary read from file, since it may contains redundant ending bytes.
byte[] encodedCert;
try {
encodedCert = cert.getEncoded();
} catch (IOException ex) {
throw new ImportCrlException("could not encode certificate {}" + certLogId, ex);
}
String b64CertHash = certhashAlgo.base64Hash(encodedCert);
if (caSpki != null) {
byte[] aki = null;
try {
aki = X509Util.extractAki(cert);
} catch (CertificateEncodingException ex) {
LogUtil.error(LOG, ex, "invalid AuthorityKeyIdentifier of certificate {}" + certLogId + ", ignore it");
return;
}
if (aki == null || !Arrays.equals(caSpki, aki)) {
LOG.warn("certificate {} is not issued by the given CA, ignore it", certLogId);
return;
}
}
// end if
LOG.info("Importing certificate {}", certLogId);
Long id = getId(caId, cert.getSerialNumber().getPositiveValue());
boolean tblCertIdExists = (id != null);
PreparedStatement ps;
String sql;
// first update the table CERT
if (tblCertIdExists) {
sql = SQL_UPDATE_CERT;
ps = psUpdateCert;
} else {
sql = SQL_INSERT_CERT;
ps = psInsertCert;
id = maxId.incrementAndGet();
}
try {
int offset = 1;
if (sql == SQL_INSERT_CERT) {
ps.setLong(offset++, id);
// ISSUER ID IID
ps.setInt(offset++, caId);
// serial number SN
ps.setString(offset++, cert.getSerialNumber().getPositiveValue().toString(16));
// whether revoked REV
ps.setInt(offset++, 0);
// revocation reason RR
ps.setNull(offset++, Types.SMALLINT);
// revocation time RT
ps.setNull(offset++, Types.BIGINT);
ps.setNull(offset++, Types.BIGINT);
}
// last update LUPDATE
ps.setLong(offset++, System.currentTimeMillis() / 1000);
TBSCertificate tbsCert = cert.getTBSCertificate();
// not before NBEFORE
ps.setLong(offset++, tbsCert.getStartDate().getDate().getTime() / 1000);
// not after NAFTER
ps.setLong(offset++, tbsCert.getEndDate().getDate().getTime() / 1000);
// profile name PN
if (StringUtil.isBlank(profileName)) {
ps.setNull(offset++, Types.VARCHAR);
} else {
ps.setString(offset++, profileName);
}
ps.setString(offset++, b64CertHash);
if (sql == SQL_UPDATE_CERT) {
ps.setLong(offset++, id);
}
ps.executeUpdate();
} catch (SQLException ex) {
throw datasource.translate(sql, ex);
}
// it is not required to add entry to table CRAW
LOG.info("Imported certificate {}", certLogId);
}
use of org.bouncycastle.asn1.x509.Time in project xipki by xipki.
the class ImportCrl method deleteEntriesNotUpdatedSince.
private void deleteEntriesNotUpdatedSince(Connection conn, Date time) throws DataAccessException {
// remove the unmodified entries
String sql = "DELETE FROM CERT WHERE LUPDATE<" + time.getTime() / 1000;
Statement stmt = datasource.createStatement(conn);
try {
stmt.executeUpdate(sql);
} catch (SQLException ex) {
throw datasource.translate(sql, ex);
} finally {
releaseResources(stmt, null);
}
}
use of org.bouncycastle.asn1.x509.Time in project xipki by xipki.
the class OcspQa method checkSingleCert.
// method checkOcsp
private List<ValidationIssue> checkSingleCert(int index, SingleResp singleResp, IssuerHash issuerHash, OcspCertStatus expectedStatus, byte[] encodedCert, Date expectedRevTime, boolean extendedRevoke, Occurrence nextupdateOccurrence, Occurrence certhashOccurrence, ASN1ObjectIdentifier certhashAlg) {
if (expectedStatus == OcspCertStatus.unknown || expectedStatus == OcspCertStatus.issuerUnknown) {
certhashOccurrence = Occurrence.forbidden;
}
List<ValidationIssue> issues = new LinkedList<>();
// issuer hash
ValidationIssue issue = new ValidationIssue("OCSP.RESPONSE." + index + ".ISSUER", "certificate issuer");
issues.add(issue);
CertificateID certId = singleResp.getCertID();
HashAlgo hashAlgo = HashAlgo.getInstance(certId.getHashAlgOID());
if (hashAlgo == null) {
issue.setFailureMessage("unknown hash algorithm " + certId.getHashAlgOID().getId());
} else {
if (!issuerHash.match(hashAlgo, certId.getIssuerNameHash(), certId.getIssuerKeyHash())) {
issue.setFailureMessage("issuer not match");
}
}
// status
issue = new ValidationIssue("OCSP.RESPONSE." + index + ".STATUS", "certificate status");
issues.add(issue);
CertificateStatus singleCertStatus = singleResp.getCertStatus();
OcspCertStatus status = null;
Long revTimeSec = null;
if (singleCertStatus == null) {
status = OcspCertStatus.good;
} else if (singleCertStatus instanceof RevokedStatus) {
RevokedStatus revStatus = (RevokedStatus) singleCertStatus;
revTimeSec = revStatus.getRevocationTime().getTime() / 1000;
if (revStatus.hasRevocationReason()) {
int reason = revStatus.getRevocationReason();
if (extendedRevoke && reason == CrlReason.CERTIFICATE_HOLD.getCode() && revTimeSec == 0) {
status = OcspCertStatus.unknown;
revTimeSec = null;
} else {
CrlReason revocationReason = CrlReason.forReasonCode(reason);
switch(revocationReason) {
case UNSPECIFIED:
status = OcspCertStatus.unspecified;
break;
case KEY_COMPROMISE:
status = OcspCertStatus.keyCompromise;
break;
case CA_COMPROMISE:
status = OcspCertStatus.cACompromise;
break;
case AFFILIATION_CHANGED:
status = OcspCertStatus.affiliationChanged;
break;
case SUPERSEDED:
status = OcspCertStatus.superseded;
break;
case CERTIFICATE_HOLD:
status = OcspCertStatus.certificateHold;
break;
case REMOVE_FROM_CRL:
status = OcspCertStatus.removeFromCRL;
break;
case PRIVILEGE_WITHDRAWN:
status = OcspCertStatus.privilegeWithdrawn;
break;
case AA_COMPROMISE:
status = OcspCertStatus.aACompromise;
break;
case CESSATION_OF_OPERATION:
status = OcspCertStatus.cessationOfOperation;
break;
default:
issue.setFailureMessage("should not reach here, unknown CRLReason " + revocationReason);
break;
}
}
// end if
} else {
status = OcspCertStatus.rev_noreason;
}
// end if (revStatus.hasRevocationReason())
} else if (singleCertStatus instanceof UnknownStatus) {
status = extendedRevoke ? OcspCertStatus.issuerUnknown : OcspCertStatus.unknown;
} else {
issue.setFailureMessage("unknown certstatus: " + singleCertStatus.getClass().getName());
}
if (!issue.isFailed() && expectedStatus != status) {
issue.setFailureMessage("is='" + status + "', but expected='" + expectedStatus + "'");
}
// revocation time
issue = new ValidationIssue("OCSP.RESPONSE." + index + ".REVTIME", "certificate time");
issues.add(issue);
if (expectedRevTime != null) {
if (revTimeSec == null) {
issue.setFailureMessage("is='null', but expected='" + formatTime(expectedRevTime) + "'");
} else if (revTimeSec != expectedRevTime.getTime() / 1000) {
issue.setFailureMessage("is='" + formatTime(new Date(revTimeSec * 1000)) + "', but expected='" + formatTime(expectedRevTime) + "'");
}
}
// nextUpdate
Date nextUpdate = singleResp.getNextUpdate();
issue = checkOccurrence("OCSP.RESPONSE." + index + ".NEXTUPDATE", nextUpdate, nextupdateOccurrence);
issues.add(issue);
Extension extension = singleResp.getExtension(ISISMTTObjectIdentifiers.id_isismtt_at_certHash);
issue = checkOccurrence("OCSP.RESPONSE." + index + ".CERTHASH", extension, certhashOccurrence);
issues.add(issue);
if (extension != null) {
ASN1Encodable extensionValue = extension.getParsedValue();
CertHash certHash = CertHash.getInstance(extensionValue);
ASN1ObjectIdentifier hashAlgOid = certHash.getHashAlgorithm().getAlgorithm();
if (certhashAlg != null) {
// certHash algorithm
issue = new ValidationIssue("OCSP.RESPONSE." + index + ".CHASH.ALG", "certhash algorithm");
issues.add(issue);
ASN1ObjectIdentifier is = certHash.getHashAlgorithm().getAlgorithm();
if (!certhashAlg.equals(is)) {
issue.setFailureMessage("is '" + is.getId() + "', but expected '" + certhashAlg.getId() + "'");
}
}
byte[] hashValue = certHash.getCertificateHash();
if (encodedCert != null) {
issue = new ValidationIssue("OCSP.RESPONSE." + index + ".CHASH.VALIDITY", "certhash validity");
issues.add(issue);
try {
MessageDigest md = MessageDigest.getInstance(hashAlgOid.getId());
byte[] expectedHashValue = md.digest(encodedCert);
if (!Arrays.equals(expectedHashValue, hashValue)) {
issue.setFailureMessage("certhash does not match the requested certificate");
}
} catch (NoSuchAlgorithmException ex) {
issue.setFailureMessage("NoSuchAlgorithm " + hashAlgOid.getId());
}
}
// end if(encodedCert != null)
}
return issues;
}
use of org.bouncycastle.asn1.x509.Time 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.bouncycastle.asn1.x509.Time 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);
}
Aggregations