use of org.xipki.scep.message.DecodedPkiMessage in project xipki by xipki.
the class ScepResponder method servicePkiOperation0.
private PkiMessage servicePkiOperation0(DecodedPkiMessage req, AuditEvent event) throws MessageDecodingException, CaException {
TransactionId tid = req.getTransactionId();
PkiMessage rep = new PkiMessage(tid, MessageType.CertRep, Nonce.randomNonce());
rep.setPkiStatus(PkiStatus.SUCCESS);
rep.setRecipientNonce(req.getSenderNonce());
if (req.getFailureMessage() != null) {
return buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badRequest);
}
Boolean bo = req.isSignatureValid();
if (bo != null && !bo.booleanValue()) {
return buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badMessageCheck);
}
bo = req.isDecryptionSuccessful();
if (bo != null && !bo.booleanValue()) {
return buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badRequest);
}
Date signingTime = req.getSigningTime();
if (maxSigningTimeBiasInMs > 0) {
boolean isTimeBad = false;
if (signingTime == null) {
isTimeBad = true;
} else {
long now = System.currentTimeMillis();
long diff = now - signingTime.getTime();
if (diff < 0) {
diff = -1 * diff;
}
isTimeBad = diff > maxSigningTimeBiasInMs;
}
if (isTimeBad) {
return buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badTime);
}
}
// check the digest algorithm
String oid = req.getDigestAlgorithm().getId();
ScepHashAlgo hashAlgo = ScepHashAlgo.forNameOrOid(oid);
if (hashAlgo == null) {
LOG.warn("tid={}: unknown digest algorithm {}", tid, oid);
return buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badAlg);
}
// end if
boolean supported = false;
if (hashAlgo == ScepHashAlgo.SHA1) {
if (caCaps.containsCapability(CaCapability.SHA1)) {
supported = true;
}
} else if (hashAlgo == ScepHashAlgo.SHA256) {
if (caCaps.containsCapability(CaCapability.SHA256)) {
supported = true;
}
} else if (hashAlgo == ScepHashAlgo.SHA512) {
if (caCaps.containsCapability(CaCapability.SHA512)) {
supported = true;
}
} else if (hashAlgo == ScepHashAlgo.MD5) {
if (control.isUseInsecureAlg()) {
supported = true;
}
}
if (!supported) {
LOG.warn("tid={}: unsupported digest algorithm {}", tid, oid);
return buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badAlg);
}
// end if
// check the content encryption algorithm
ASN1ObjectIdentifier encOid = req.getContentEncryptionAlgorithm();
if (CMSAlgorithm.DES_EDE3_CBC.equals(encOid)) {
if (!caCaps.containsCapability(CaCapability.DES3)) {
LOG.warn("tid={}: encryption with DES3 algorithm is not permitted", tid, encOid);
return buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badAlg);
}
} else if (AES_ENC_ALGS.contains(encOid)) {
if (!caCaps.containsCapability(CaCapability.AES)) {
LOG.warn("tid={}: encryption with AES algorithm {} is not permitted", tid, encOid);
return buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badAlg);
}
} else if (CMSAlgorithm.DES_CBC.equals(encOid)) {
if (!control.isUseInsecureAlg()) {
LOG.warn("tid={}: encryption with DES algorithm {} is not permitted", tid, encOid);
return buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badAlg);
}
} else {
LOG.warn("tid={}: encryption with algorithm {} is not permitted", tid, encOid);
return buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badAlg);
}
if (rep.getPkiStatus() == PkiStatus.FAILURE) {
return rep;
}
MessageType messageType = req.getMessageType();
switch(messageType) {
case PKCSReq:
boolean selfSigned = req.getSignatureCert().getIssuerX500Principal().equals(req.getSignatureCert().getIssuerX500Principal());
CertificationRequest csr = CertificationRequest.getInstance(req.getMessageData());
if (selfSigned) {
X500Name name = X500Name.getInstance(req.getSignatureCert().getSubjectX500Principal().getEncoded());
if (!name.equals(csr.getCertificationRequestInfo().getSubject())) {
LOG.warn("tid={}: self-signed cert.subject != CSR.subject", tid);
return buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badRequest);
}
}
String challengePwd = getChallengePassword(csr.getCertificationRequestInfo());
if (challengePwd == null || !control.getSecret().equals(challengePwd)) {
LOG.warn("challengePassword is not trusted");
return buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badRequest);
}
Certificate cert;
try {
cert = caEmulator.generateCert(csr);
} catch (Exception ex) {
throw new CaException("system failure: " + ex.getMessage(), ex);
}
if (cert != null && control.isPendingCert()) {
rep.setPkiStatus(PkiStatus.PENDING);
} else if (cert != null) {
ContentInfo messageData = createSignedData(cert);
rep.setMessageData(messageData);
} else {
buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badCertId);
}
break;
case CertPoll:
IssuerAndSubject is = IssuerAndSubject.getInstance(req.getMessageData());
cert = caEmulator.pollCert(is.getIssuer(), is.getSubject());
if (cert != null) {
rep.setMessageData(createSignedData(cert));
} else {
buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badCertId);
}
break;
case GetCert:
IssuerAndSerialNumber isn = IssuerAndSerialNumber.getInstance(req.getMessageData());
cert = caEmulator.getCert(isn.getName(), isn.getSerialNumber().getValue());
if (cert != null) {
rep.setMessageData(createSignedData(cert));
} else {
buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badCertId);
}
break;
case RenewalReq:
if (!caCaps.containsCapability(CaCapability.Renewal)) {
buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badRequest);
} else {
csr = CertificationRequest.getInstance(req.getMessageData());
try {
cert = caEmulator.generateCert(csr);
} catch (Exception ex) {
throw new CaException("system failure: " + ex.getMessage(), ex);
}
if (cert != null) {
rep.setMessageData(createSignedData(cert));
} else {
rep.setPkiStatus(PkiStatus.FAILURE);
rep.setFailInfo(FailInfo.badCertId);
}
}
break;
case UpdateReq:
if (!caCaps.containsCapability(CaCapability.Update)) {
buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badRequest);
} else {
csr = CertificationRequest.getInstance(req.getMessageData());
try {
cert = caEmulator.generateCert(csr);
} catch (Exception ex) {
throw new CaException("system failure: " + ex.getMessage(), ex);
}
if (cert != null) {
rep.setMessageData(createSignedData(cert));
} else {
buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badCertId);
}
}
break;
case GetCRL:
isn = IssuerAndSerialNumber.getInstance(req.getMessageData());
CertificateList crl;
try {
crl = caEmulator.getCrl(isn.getName(), isn.getSerialNumber().getValue());
} catch (Exception ex) {
throw new CaException("system failure: " + ex.getMessage(), ex);
}
if (crl != null) {
rep.setMessageData(createSignedData(crl));
} else {
buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badCertId);
}
break;
default:
buildPkiMessage(rep, PkiStatus.FAILURE, FailInfo.badRequest);
}
return rep;
}
use of org.xipki.scep.message.DecodedPkiMessage in project xipki by xipki.
the class Client method decode.
private DecodedPkiMessage decode(CMSSignedData pkiMessage, PrivateKey recipientKey, X509Certificate recipientCert) throws ScepClientException {
DecodedPkiMessage resp;
try {
resp = DecodedPkiMessage.decode(pkiMessage, recipientKey, recipientCert, responseSignerCerts);
} catch (MessageDecodingException ex) {
throw new ScepClientException(ex);
}
if (resp.getFailureMessage() != null) {
throw new ScepClientException("Error: " + resp.getFailureMessage());
}
Boolean bo = resp.isSignatureValid();
if (bo != null && !bo.booleanValue()) {
throw new ScepClientException("Signature is invalid");
}
bo = resp.isDecryptionSuccessful();
if (bo != null && !bo.booleanValue()) {
throw new ScepClientException("Decryption failed");
}
Date signingTime = resp.getSigningTime();
long maxSigningTimeBias = getMaxSigningTimeBiasInMs();
if (maxSigningTimeBias > 0) {
if (signingTime == null) {
throw new ScepClientException("CMS signingTime attribute is not present");
}
long now = System.currentTimeMillis();
long diff = now - signingTime.getTime();
if (diff < 0) {
diff = -1 * diff;
}
if (diff > maxSigningTimeBias) {
throw new ScepClientException("CMS signingTime is out of permitted period");
}
}
if (!resp.getSignatureCert().equals(authorityCertStore.getSignatureCert())) {
throw new ScepClientException("the signature certificate must not be trusted");
}
return resp;
}
use of org.xipki.scep.message.DecodedPkiMessage in project xipki by xipki.
the class ScepImpl method servicePkiOperation.
public ContentInfo servicePkiOperation(CMSSignedData requestContent, String certProfileName, String msgId, AuditEvent event) throws MessageDecodingException, OperationException {
CaStatus status = getStatus();
if (CaStatus.ACTIVE != status) {
LOG.warn("SCEP {} is not active", caIdent);
throw new OperationException(ErrorCode.SYSTEM_UNAVAILABLE);
}
DecodedPkiMessage req = DecodedPkiMessage.decode(requestContent, envelopedDataDecryptor, null);
PkiMessage rep = servicePkiOperation0(requestContent, req, certProfileName, msgId, event);
audit(event, CaAuditConstants.NAME_SCEP_pkiStatus, rep.getPkiStatus().toString());
if (rep.getPkiStatus() == PkiStatus.FAILURE) {
event.setStatus(AuditStatus.FAILED);
}
if (rep.getFailInfo() != null) {
audit(event, CaAuditConstants.NAME_SCEP_failInfo, rep.getFailInfo().toString());
}
return encodeResponse(rep, req);
}
use of org.xipki.scep.message.DecodedPkiMessage in project xipki by xipki.
the class ScepImpl method servicePkiOperation0.
// method servicePkiOperation
private PkiMessage servicePkiOperation0(CMSSignedData requestContent, DecodedPkiMessage req, String certProfileName, String msgId, AuditEvent event) throws MessageDecodingException, OperationException {
ParamUtil.requireNonNull("requestContent", requestContent);
ParamUtil.requireNonNull("req", req);
String tid = req.getTransactionId().getId();
// verify and decrypt the request
audit(event, CaAuditConstants.NAME_tid, tid);
if (req.getFailureMessage() != null) {
audit(event, CaAuditConstants.NAME_SCEP_failureMessage, req.getFailureMessage());
}
Boolean bo = req.isSignatureValid();
if (bo != null && !bo.booleanValue()) {
audit(event, CaAuditConstants.NAME_SCEP_signature, "invalid");
}
bo = req.isDecryptionSuccessful();
if (bo != null && !bo.booleanValue()) {
audit(event, CaAuditConstants.NAME_SCEP_decryption, "failed");
}
PkiMessage rep = new PkiMessage(req.getTransactionId(), MessageType.CertRep, Nonce.randomNonce());
rep.setRecipientNonce(req.getSenderNonce());
if (req.getFailureMessage() != null) {
rep.setPkiStatus(PkiStatus.FAILURE);
rep.setFailInfo(FailInfo.badRequest);
return rep;
}
bo = req.isSignatureValid();
if (bo != null && !bo.booleanValue()) {
rep.setPkiStatus(PkiStatus.FAILURE);
rep.setFailInfo(FailInfo.badMessageCheck);
return rep;
}
bo = req.isDecryptionSuccessful();
if (bo != null && !bo.booleanValue()) {
rep.setPkiStatus(PkiStatus.FAILURE);
rep.setFailInfo(FailInfo.badRequest);
return rep;
}
Date signingTime = req.getSigningTime();
if (maxSigningTimeBiasInMs > 0) {
boolean isTimeBad = false;
if (signingTime == null) {
isTimeBad = true;
} else {
long now = System.currentTimeMillis();
long diff = now - signingTime.getTime();
if (diff < 0) {
diff = -1 * diff;
}
isTimeBad = diff > maxSigningTimeBiasInMs;
}
if (isTimeBad) {
rep.setPkiStatus(PkiStatus.FAILURE);
rep.setFailInfo(FailInfo.badTime);
return rep;
}
}
// end if
// check the digest algorithm
String oid = req.getDigestAlgorithm().getId();
ScepHashAlgo hashAlgo = ScepHashAlgo.forNameOrOid(oid);
if (hashAlgo == null) {
LOG.warn("tid={}: unknown digest algorithm {}", tid, oid);
rep.setPkiStatus(PkiStatus.FAILURE);
rep.setFailInfo(FailInfo.badAlg);
return rep;
}
boolean supported = false;
if (hashAlgo == ScepHashAlgo.SHA1) {
if (caCaps.containsCapability(CaCapability.SHA1)) {
supported = true;
}
} else if (hashAlgo == ScepHashAlgo.SHA256) {
if (caCaps.containsCapability(CaCapability.SHA256)) {
supported = true;
}
} else if (hashAlgo == ScepHashAlgo.SHA512) {
if (caCaps.containsCapability(CaCapability.SHA512)) {
supported = true;
}
}
if (!supported) {
LOG.warn("tid={}: unsupported digest algorithm {}", tid, oid);
rep.setPkiStatus(PkiStatus.FAILURE);
rep.setFailInfo(FailInfo.badAlg);
return rep;
}
// check the content encryption algorithm
ASN1ObjectIdentifier encOid = req.getContentEncryptionAlgorithm();
if (CMSAlgorithm.DES_EDE3_CBC.equals(encOid)) {
if (!caCaps.containsCapability(CaCapability.DES3)) {
LOG.warn("tid={}: encryption with DES3 algorithm is not permitted", tid, encOid);
rep.setPkiStatus(PkiStatus.FAILURE);
rep.setFailInfo(FailInfo.badAlg);
return rep;
}
} else if (AES_ENC_ALGOS.contains(encOid)) {
if (!caCaps.containsCapability(CaCapability.AES)) {
LOG.warn("tid={}: encryption with AES algorithm {} is not permitted", tid, encOid);
rep.setPkiStatus(PkiStatus.FAILURE);
rep.setFailInfo(FailInfo.badAlg);
return rep;
}
} else {
LOG.warn("tid={}: encryption with algorithm {} is not permitted", tid, encOid);
rep.setPkiStatus(PkiStatus.FAILURE);
rep.setFailInfo(FailInfo.badAlg);
return rep;
}
X509Ca ca;
try {
ca = caManager.getX509Ca(caIdent);
} catch (CaMgmtException ex) {
LogUtil.error(LOG, ex, tid + "=" + tid + ",could not get X509CA");
throw new OperationException(ErrorCode.SYSTEM_FAILURE, ex);
}
X500Name caX500Name = ca.getCaInfo().getCert().getSubjectAsX500Name();
try {
SignedData signedData;
MessageType mt = req.getMessageType();
audit(event, CaAuditConstants.NAME_SCEP_messageType, mt.toString());
switch(mt) {
case PKCSReq:
case RenewalReq:
case UpdateReq:
CertificationRequest csr = CertificationRequest.getInstance(req.getMessageData());
X500Name reqSubject = csr.getCertificationRequestInfo().getSubject();
if (LOG.isInfoEnabled()) {
LOG.info("tid={}, subject={}", tid, X509Util.getRfc4519Name(reqSubject));
}
try {
ca.checkCsr(csr);
} catch (OperationException ex) {
LogUtil.warn(LOG, ex, "tid=" + tid + " POPO verification failed");
throw FailInfoException.BAD_MESSAGE_CHECK;
}
CertificationRequestInfo csrReqInfo = csr.getCertificationRequestInfo();
X509Certificate reqSignatureCert = req.getSignatureCert();
X500Principal reqSigCertSubject = reqSignatureCert.getSubjectX500Principal();
boolean selfSigned = reqSigCertSubject.equals(reqSignatureCert.getIssuerX500Principal());
if (selfSigned) {
X500Name tmp = X500Name.getInstance(reqSigCertSubject.getEncoded());
if (!tmp.equals(csrReqInfo.getSubject())) {
LOG.warn("tid={}, self-signed identityCert.subject != csr.subject");
throw FailInfoException.BAD_REQUEST;
}
}
if (X509Util.getCommonName(csrReqInfo.getSubject()) == null) {
throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE, "tid=" + tid + ": no CommonName in requested subject");
}
NameId userIdent = null;
String challengePwd = CaUtil.getChallengePassword(csrReqInfo);
if (challengePwd != null) {
String[] strs = challengePwd.split(":");
if (strs == null || strs.length != 2) {
LOG.warn("tid={}: challengePassword does not have the format <user>:<password>", tid);
throw FailInfoException.BAD_REQUEST;
}
String user = strs[0];
String password = strs[1];
userIdent = ca.authenticateUser(user, password.getBytes());
if (userIdent == null) {
LOG.warn("tid={}: could not authenticate user {}", tid, user);
throw FailInfoException.BAD_REQUEST;
}
}
if (selfSigned) {
if (MessageType.PKCSReq != mt) {
LOG.warn("tid={}: self-signed certificate is not permitted for" + " messageType {}", tid, mt);
throw FailInfoException.BAD_REQUEST;
}
if (userIdent == null) {
LOG.warn("tid={}: could not extract user & password from challengePassword" + ", which are required for self-signed signature certificate", tid);
throw FailInfoException.BAD_REQUEST;
}
} else {
// certificate is known by the CA
if (userIdent == null) {
// up to draft-nourse-scep-23 the client sends all messages to enroll
// certificate via MessageType PKCSReq
KnowCertResult knowCertRes = ca.knowsCertificate(reqSignatureCert);
if (!knowCertRes.isKnown()) {
LOG.warn("tid={}: signature certificate is not trusted by the CA", tid);
throw FailInfoException.BAD_REQUEST;
}
Integer userId = knowCertRes.getUserId();
if (userId == null) {
LOG.warn("tid={}: could not extract user from the signature cert", tid);
throw FailInfoException.BAD_REQUEST;
}
userIdent = ca.getUserIdent(userId);
}
// end if
}
// end if
ByUserRequestorInfo requestor = ca.getByUserRequestor(userIdent);
checkUserPermission(requestor, certProfileName);
byte[] tidBytes = getTransactionIdBytes(tid);
Extensions extensions = CaUtil.getExtensions(csrReqInfo);
CertTemplateData certTemplateData = new CertTemplateData(csrReqInfo.getSubject(), csrReqInfo.getSubjectPublicKeyInfo(), (Date) null, (Date) null, extensions, certProfileName);
X509CertificateInfo cert = ca.generateCertificate(certTemplateData, requestor, RequestType.SCEP, tidBytes, msgId);
/* Don't save SCEP message, since it contains password in plaintext
if (ca.getCaInfo().isSaveRequest() && cert.getCert().getCertId() != null) {
byte[] encodedRequest;
try {
encodedRequest = requestContent.getEncoded();
} catch (IOException ex) {
LOG.warn("could not encode request");
encodedRequest = null;
}
if (encodedRequest != null) {
long reqId = ca.addRequest(encodedRequest);
ca.addRequestCert(reqId, cert.getCert().getCertId());
}
}*/
signedData = buildSignedData(cert.getCert().getCert());
break;
case CertPoll:
IssuerAndSubject is = IssuerAndSubject.getInstance(req.getMessageData());
audit(event, CaAuditConstants.NAME_issuer, X509Util.getRfc4519Name(is.getIssuer()));
audit(event, CaAuditConstants.NAME_subject, X509Util.getRfc4519Name(is.getSubject()));
ensureIssuedByThisCa(caX500Name, is.getIssuer());
signedData = pollCert(ca, is.getSubject(), req.getTransactionId());
break;
case GetCert:
IssuerAndSerialNumber isn = IssuerAndSerialNumber.getInstance(req.getMessageData());
BigInteger serial = isn.getSerialNumber().getPositiveValue();
audit(event, CaAuditConstants.NAME_issuer, X509Util.getRfc4519Name(isn.getName()));
audit(event, CaAuditConstants.NAME_serial, LogUtil.formatCsn(serial));
ensureIssuedByThisCa(caX500Name, isn.getName());
signedData = getCert(ca, isn.getSerialNumber().getPositiveValue());
break;
case GetCRL:
isn = IssuerAndSerialNumber.getInstance(req.getMessageData());
serial = isn.getSerialNumber().getPositiveValue();
audit(event, CaAuditConstants.NAME_issuer, X509Util.getRfc4519Name(isn.getName()));
audit(event, CaAuditConstants.NAME_serial, LogUtil.formatCsn(serial));
ensureIssuedByThisCa(caX500Name, isn.getName());
signedData = getCrl(ca, serial);
break;
default:
LOG.error("unknown SCEP messageType '{}'", req.getMessageType());
throw FailInfoException.BAD_REQUEST;
}
// end switch<
ContentInfo ci = new ContentInfo(CMSObjectIdentifiers.signedData, signedData);
rep.setMessageData(ci);
rep.setPkiStatus(PkiStatus.SUCCESS);
} catch (FailInfoException ex) {
LogUtil.error(LOG, ex);
rep.setPkiStatus(PkiStatus.FAILURE);
rep.setFailInfo(ex.getFailInfo());
}
return rep;
}
use of org.xipki.scep.message.DecodedPkiMessage in project xipki by xipki.
the class Client method scepGetCert.
public List<X509Certificate> scepGetCert(PrivateKey identityKey, X509Certificate identityCert, X500Name issuer, BigInteger serialNumber) throws ScepClientException {
ScepUtil.requireNonNull("identityKey", identityKey);
ScepUtil.requireNonNull("identityCert", identityCert);
ScepUtil.requireNonNull("issuer", issuer);
ScepUtil.requireNonNull("serialNumber", serialNumber);
initIfNotInited();
PkiMessage request = new PkiMessage(TransactionId.randomTransactionId(), MessageType.GetCert);
IssuerAndSerialNumber isn = new IssuerAndSerialNumber(issuer, serialNumber);
request.setMessageData(isn);
ContentInfo envRequest = encryptThenSign(request, identityKey, identityCert);
ScepHttpResponse httpResp = httpSend(Operation.PKIOperation, envRequest);
CMSSignedData cmsSignedData = parsePkiMessage(httpResp.getContentBytes());
DecodedPkiMessage response = decode(cmsSignedData, identityKey, identityCert);
if (response.getPkiStatus() != PkiStatus.SUCCESS) {
throw new ScepClientException("server returned " + response.getPkiStatus());
}
ContentInfo messageData = ContentInfo.getInstance(response.getMessageData());
try {
return ScepUtil.getCertsFromSignedData(SignedData.getInstance(messageData.getContent()));
} catch (CertificateException ex) {
throw new ScepClientException(ex.getMessage(), ex);
}
}
Aggregations