Search in sources :

Example 1 with PkiStatus

use of org.xipki.scep.transaction.PkiStatus in project xipki by xipki.

the class DecodedPkiMessage method decode.

@SuppressWarnings("unchecked")
public static DecodedPkiMessage decode(CMSSignedData pkiMessage, EnvelopedDataDecryptor recipient, CollectionStore<X509CertificateHolder> certStore) throws MessageDecodingException {
    ScepUtil.requireNonNull("pkiMessage", pkiMessage);
    ScepUtil.requireNonNull("recipient", recipient);
    SignerInformationStore signerStore = pkiMessage.getSignerInfos();
    Collection<SignerInformation> signerInfos = signerStore.getSigners();
    if (signerInfos.size() != 1) {
        throw new MessageDecodingException("number of signerInfos is not 1, but " + signerInfos.size());
    }
    SignerInformation signerInfo = signerInfos.iterator().next();
    SignerId sid = signerInfo.getSID();
    Collection<?> signedDataCerts = null;
    if (certStore != null) {
        signedDataCerts = certStore.getMatches(sid);
    }
    if (signedDataCerts == null || signedDataCerts.isEmpty()) {
        signedDataCerts = pkiMessage.getCertificates().getMatches(signerInfo.getSID());
    }
    if (signedDataCerts == null || signedDataCerts.size() != 1) {
        throw new MessageDecodingException("could not find embedded certificate to verify the signature");
    }
    AttributeTable signedAttrs = signerInfo.getSignedAttributes();
    if (signedAttrs == null) {
        throw new MessageDecodingException("missing SCEP attributes");
    }
    Date signingTime = null;
    // signingTime
    ASN1Encodable attrValue = ScepUtil.getFirstAttrValue(signedAttrs, CMSAttributes.signingTime);
    if (attrValue != null) {
        signingTime = Time.getInstance(attrValue).getDate();
    }
    // transactionId
    String str = getPrintableStringAttrValue(signedAttrs, ScepObjectIdentifiers.ID_TRANSACTION_ID);
    if (str == null || str.isEmpty()) {
        throw new MessageDecodingException("missing required SCEP attribute transactionId");
    }
    TransactionId transactionId = new TransactionId(str);
    // messageType
    Integer intValue = getIntegerPrintStringAttrValue(signedAttrs, ScepObjectIdentifiers.ID_MESSAGE_TYPE);
    if (intValue == null) {
        throw new MessageDecodingException("tid " + transactionId.getId() + ": missing required SCEP attribute messageType");
    }
    MessageType messageType;
    try {
        messageType = MessageType.forValue(intValue);
    } catch (IllegalArgumentException ex) {
        throw new MessageDecodingException("tid " + transactionId.getId() + ": invalid messageType '" + intValue + "'");
    }
    // senderNonce
    Nonce senderNonce = getNonceAttrValue(signedAttrs, ScepObjectIdentifiers.ID_SENDER_NONCE);
    if (senderNonce == null) {
        throw new MessageDecodingException("tid " + transactionId.getId() + ": missing required SCEP attribute senderNonce");
    }
    DecodedPkiMessage ret = new DecodedPkiMessage(transactionId, messageType, senderNonce);
    if (signingTime != null) {
        ret.setSigningTime(signingTime);
    }
    Nonce recipientNonce = null;
    try {
        recipientNonce = getNonceAttrValue(signedAttrs, ScepObjectIdentifiers.ID_RECIPIENT_NONCE);
    } catch (MessageDecodingException ex) {
        ret.setFailureMessage("could not parse recipientNonce: " + ex.getMessage());
    }
    if (recipientNonce != null) {
        ret.setRecipientNonce(recipientNonce);
    }
    PkiStatus pkiStatus = null;
    FailInfo failInfo = null;
    if (MessageType.CertRep == messageType) {
        // pkiStatus
        try {
            intValue = getIntegerPrintStringAttrValue(signedAttrs, ScepObjectIdentifiers.ID_PKI_STATUS);
        } catch (MessageDecodingException ex) {
            ret.setFailureMessage("could not parse pkiStatus: " + ex.getMessage());
            return ret;
        }
        if (intValue == null) {
            ret.setFailureMessage("missing required SCEP attribute pkiStatus");
            return ret;
        }
        try {
            pkiStatus = PkiStatus.forValue(intValue);
        } catch (IllegalArgumentException ex) {
            ret.setFailureMessage("invalid pkiStatus '" + intValue + "'");
            return ret;
        }
        ret.setPkiStatus(pkiStatus);
        // failureInfo
        if (pkiStatus == PkiStatus.FAILURE) {
            try {
                intValue = getIntegerPrintStringAttrValue(signedAttrs, ScepObjectIdentifiers.ID_FAILINFO);
            } catch (MessageDecodingException ex) {
                ret.setFailureMessage("could not parse failInfo: " + ex.getMessage());
                return ret;
            }
            if (intValue == null) {
                ret.setFailureMessage("missing required SCEP attribute failInfo");
                return ret;
            }
            try {
                failInfo = FailInfo.forValue(intValue);
            } catch (IllegalArgumentException ex) {
                ret.setFailureMessage("invalid failInfo '" + intValue + "'");
                return ret;
            }
            ret.setFailInfo(failInfo);
        }
    // end if(pkiStatus == PkiStatus.FAILURE)
    }
    // end if (MessageType.CertRep == messageType)
    // other signedAttributes
    Attribute[] attrs = signedAttrs.toASN1Structure().getAttributes();
    for (Attribute attr : attrs) {
        ASN1ObjectIdentifier type = attr.getAttrType();
        if (!SCEP_ATTR_TYPES.contains(type)) {
            ret.addSignendAttribute(type, attr.getAttrValues().getObjectAt(0));
        }
    }
    // unsignedAttributes
    AttributeTable unsignedAttrs = signerInfo.getUnsignedAttributes();
    attrs = (unsignedAttrs == null) ? null : unsignedAttrs.toASN1Structure().getAttributes();
    if (attrs != null) {
        for (Attribute attr : attrs) {
            ASN1ObjectIdentifier type = attr.getAttrType();
            ret.addUnsignendAttribute(type, attr.getAttrValues().getObjectAt(0));
        }
    }
    ASN1ObjectIdentifier digestAlgOid = signerInfo.getDigestAlgorithmID().getAlgorithm();
    ret.setDigestAlgorithm(digestAlgOid);
    String sigAlgOid = signerInfo.getEncryptionAlgOID();
    if (!PKCSObjectIdentifiers.rsaEncryption.getId().equals(sigAlgOid)) {
        ASN1ObjectIdentifier tmpDigestAlgOid;
        try {
            tmpDigestAlgOid = ScepUtil.extractDigesetAlgorithmIdentifier(signerInfo.getEncryptionAlgOID(), signerInfo.getEncryptionAlgParams());
        } catch (Exception ex) {
            final String msg = "could not extract digest algorithm from signerInfo.signatureAlgorithm: " + ex.getMessage();
            LOG.error(msg);
            LOG.debug(msg, ex);
            ret.setFailureMessage(msg);
            return ret;
        }
        if (!digestAlgOid.equals(tmpDigestAlgOid)) {
            ret.setFailureMessage("digestAlgorithm and encryptionAlgorithm do not use the same digestAlgorithm");
            return ret;
        }
    // end if
    }
    // end if
    X509CertificateHolder tmpSignerCert = (X509CertificateHolder) signedDataCerts.iterator().next();
    X509Certificate signerCert;
    try {
        signerCert = ScepUtil.toX509Cert(tmpSignerCert.toASN1Structure());
    } catch (CertificateException ex) {
        final String msg = "could not construct X509Certificate: " + ex.getMessage();
        LOG.error(msg);
        LOG.debug(msg, ex);
        ret.setFailureMessage(msg);
        return ret;
    }
    ret.setSignatureCert(signerCert);
    // validate the signature
    SignerInformationVerifier verifier;
    try {
        verifier = new JcaSimpleSignerInfoVerifierBuilder().build(tmpSignerCert);
    } catch (OperatorCreationException | CertificateException ex) {
        final String msg = "could not build signature verifier: " + ex.getMessage();
        LOG.error(msg);
        LOG.debug(msg, ex);
        ret.setFailureMessage(msg);
        return ret;
    }
    boolean signatureValid;
    try {
        signatureValid = signerInfo.verify(verifier);
    } catch (CMSException ex) {
        final String msg = "could not verify the signature: " + ex.getMessage();
        LOG.error(msg);
        LOG.debug(msg, ex);
        ret.setFailureMessage(msg);
        return ret;
    }
    ret.setSignatureValid(signatureValid);
    if (!signatureValid) {
        return ret;
    }
    if (MessageType.CertRep == messageType && (pkiStatus == PkiStatus.FAILURE | pkiStatus == PkiStatus.PENDING)) {
        return ret;
    }
    // MessageData
    CMSTypedData signedContent = pkiMessage.getSignedContent();
    ASN1ObjectIdentifier signedContentType = signedContent.getContentType();
    if (!CMSObjectIdentifiers.envelopedData.equals(signedContentType)) {
        // fall back: some SCEP client, such as JSCEP use id-data
        if (!CMSObjectIdentifiers.data.equals(signedContentType)) {
            ret.setFailureMessage("either id-envelopedData or id-data is excepted, but not '" + signedContentType.getId());
            return ret;
        }
    }
    CMSEnvelopedData envData;
    try {
        envData = new CMSEnvelopedData((byte[]) signedContent.getContent());
    } catch (CMSException ex) {
        final String msg = "could not create the CMSEnvelopedData: " + ex.getMessage();
        LOG.error(msg);
        LOG.debug(msg, ex);
        ret.setFailureMessage(msg);
        return ret;
    }
    ret.setContentEncryptionAlgorithm(envData.getContentEncryptionAlgorithm().getAlgorithm());
    byte[] encodedMessageData;
    try {
        encodedMessageData = recipient.decrypt(envData);
    } catch (MessageDecodingException ex) {
        final String msg = "could not create the CMSEnvelopedData: " + ex.getMessage();
        LOG.error(msg);
        LOG.debug(msg, ex);
        ret.setFailureMessage(msg);
        ret.setDecryptionSuccessful(false);
        return ret;
    }
    ret.setDecryptionSuccessful(true);
    try {
        if (MessageType.PKCSReq == messageType || MessageType.RenewalReq == messageType || MessageType.UpdateReq == messageType) {
            CertificationRequest messageData = CertificationRequest.getInstance(encodedMessageData);
            ret.setMessageData(messageData);
        } else if (MessageType.CertPoll == messageType) {
            IssuerAndSubject messageData = IssuerAndSubject.getInstance(encodedMessageData);
            ret.setMessageData(messageData);
        } else if (MessageType.GetCert == messageType || MessageType.GetCRL == messageType) {
            IssuerAndSerialNumber messageData = IssuerAndSerialNumber.getInstance(encodedMessageData);
            ret.setMessageData(messageData);
            ret.setMessageData(messageData);
        } else if (MessageType.CertRep == messageType) {
            ContentInfo ci = ContentInfo.getInstance(encodedMessageData);
            ret.setMessageData(ci);
        } else {
            throw new RuntimeException("should not reach here, unknown messageType " + messageType);
        }
    } catch (Exception ex) {
        final String msg = "could not parse the messageData: " + ex.getMessage();
        LOG.error(msg);
        LOG.debug(msg, ex);
        ret.setFailureMessage(msg);
        return ret;
    }
    return ret;
}
Also used : IssuerAndSerialNumber(org.bouncycastle.asn1.cms.IssuerAndSerialNumber) Attribute(org.bouncycastle.asn1.cms.Attribute) AttributeTable(org.bouncycastle.asn1.cms.AttributeTable) SignerInformation(org.bouncycastle.cms.SignerInformation) CertificateException(java.security.cert.CertificateException) ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) DERPrintableString(org.bouncycastle.asn1.DERPrintableString) SignerInformationStore(org.bouncycastle.cms.SignerInformationStore) ContentInfo(org.bouncycastle.asn1.cms.ContentInfo) ASN1Encodable(org.bouncycastle.asn1.ASN1Encodable) FailInfo(org.xipki.scep.transaction.FailInfo) SignerInformationVerifier(org.bouncycastle.cms.SignerInformationVerifier) OperatorCreationException(org.bouncycastle.operator.OperatorCreationException) MessageType(org.xipki.scep.transaction.MessageType) PkiStatus(org.xipki.scep.transaction.PkiStatus) CMSEnvelopedData(org.bouncycastle.cms.CMSEnvelopedData) CMSTypedData(org.bouncycastle.cms.CMSTypedData) JcaSimpleSignerInfoVerifierBuilder(org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder) Date(java.util.Date) CMSException(org.bouncycastle.cms.CMSException) OperatorCreationException(org.bouncycastle.operator.OperatorCreationException) MessageDecodingException(org.xipki.scep.exception.MessageDecodingException) CertificateException(java.security.cert.CertificateException) X509Certificate(java.security.cert.X509Certificate) TransactionId(org.xipki.scep.transaction.TransactionId) Nonce(org.xipki.scep.transaction.Nonce) MessageDecodingException(org.xipki.scep.exception.MessageDecodingException) SignerId(org.bouncycastle.cms.SignerId) X509CertificateHolder(org.bouncycastle.cert.X509CertificateHolder) ASN1ObjectIdentifier(org.bouncycastle.asn1.ASN1ObjectIdentifier) CertificationRequest(org.bouncycastle.asn1.pkcs.CertificationRequest) CMSException(org.bouncycastle.cms.CMSException)

Example 2 with PkiStatus

use of org.xipki.scep.transaction.PkiStatus in project xipki by xipki.

the class AbstractCaTest method test.

@Test
public void test() throws Exception {
    CaIdentifier caId = new CaIdentifier("http://localhost:" + port + "/scep/pkiclient.exe", null);
    CaCertValidator caCertValidator = new PreprovisionedCaCertValidator(ScepUtil.toX509Cert(scepServer.getCaCert()));
    ScepClient client = new ScepClient(caId, caCertValidator);
    client.setUseInsecureAlgorithms(useInsecureAlgorithms());
    client.refresh();
    CaCaps expCaCaps = getExpectedCaCaps();
    // CACaps
    CaCaps caCaps = client.getCaCaps();
    Assert.assertEquals("CACaps", expCaCaps, caCaps);
    // CA certificate
    Certificate expCaCert = scepServer.getCaCert();
    X509Certificate caCert = client.getAuthorityCertStore().getCaCert();
    if (!equals(expCaCert, caCert)) {
        Assert.fail("Configured and received CA certificate not the same");
    }
    boolean withRa = isWithRa();
    // RA
    if (withRa) {
        Certificate expRaCert = scepServer.getRaCert();
        X509Certificate raSigCert = client.getAuthorityCertStore().getSignatureCert();
        X509Certificate raEncCert = client.getAuthorityCertStore().getEncryptionCert();
        Assert.assertEquals("RA certificate", raSigCert, raEncCert);
        if (!equals(expRaCert, raSigCert)) {
            Assert.fail("Configured and received RA certificate not the same");
        }
    }
    // getNextCA
    if (isWithNextCa()) {
        AuthorityCertStore nextCa = client.scepNextCaCert();
        Certificate expNextCaCert = scepServer.getNextCaCert();
        X509Certificate nextCaCert = nextCa.getCaCert();
        if (!equals(expNextCaCert, nextCaCert)) {
            Assert.fail("Configured and received next CA certificate not the same");
        }
        if (withRa) {
            Certificate expNextRaCert = scepServer.getNextRaCert();
            X509Certificate nextRaSigCert = nextCa.getSignatureCert();
            X509Certificate nextRaEncCert = nextCa.getEncryptionCert();
            Assert.assertEquals("Next RA certificate", nextRaSigCert, nextRaEncCert);
            if (!equals(expNextRaCert, nextRaSigCert)) {
                Assert.fail("Configured and received next RA certificate not the same");
            }
        }
    }
    // enroll
    CertificationRequest csr;
    X509Certificate selfSignedCert;
    X509Certificate enroledCert;
    X500Name issuerName = X500Name.getInstance(caCert.getSubjectX500Principal().getEncoded());
    PrivateKey privKey;
    {
        KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
        kpGen.initialize(2048);
        KeyPair keypair = kpGen.generateKeyPair();
        privKey = keypair.getPrivate();
        SubjectPublicKeyInfo subjectPublicKeyInfo = ScepUtil.createSubjectPublicKeyInfo(keypair.getPublic());
        X500Name subject = new X500Name("CN=EE1, OU=emulator, O=xipki.org, C=DE");
        // first try without secret
        PKCS10CertificationRequest p10Req = ScepUtil.generateRequest(privKey, subjectPublicKeyInfo, subject, null, null);
        csr = p10Req.toASN1Structure();
        selfSignedCert = ScepUtil.generateSelfsignedCert(p10Req.toASN1Structure(), privKey);
        EnrolmentResponse enrolResp = client.scepPkcsReq(p10Req.toASN1Structure(), privKey, selfSignedCert);
        PkiStatus status = enrolResp.getPkcsRep().getPkiStatus();
        Assert.assertEquals("PkiStatus without secret", PkiStatus.FAILURE, status);
        // then try invalid secret
        p10Req = ScepUtil.generateRequest(privKey, subjectPublicKeyInfo, subject, "invalid-" + secret, null);
        csr = p10Req.toASN1Structure();
        selfSignedCert = ScepUtil.generateSelfsignedCert(p10Req.toASN1Structure(), privKey);
        enrolResp = client.scepPkcsReq(p10Req.toASN1Structure(), privKey, selfSignedCert);
        status = enrolResp.getPkcsRep().getPkiStatus();
        Assert.assertEquals("PkiStatus with invalid secret", PkiStatus.FAILURE, status);
        // try with valid secret
        p10Req = ScepUtil.generateRequest(privKey, subjectPublicKeyInfo, subject, secret, null);
        csr = p10Req.toASN1Structure();
        selfSignedCert = ScepUtil.generateSelfsignedCert(p10Req.toASN1Structure(), privKey);
        enrolResp = client.scepPkcsReq(p10Req.toASN1Structure(), privKey, selfSignedCert);
        List<X509Certificate> certs = enrolResp.getCertificates();
        Assert.assertTrue("number of received certificates", certs.size() > 0);
        X509Certificate cert = certs.get(0);
        Assert.assertNotNull("enroled certificate", cert);
        enroledCert = cert;
        // try :: self-signed certificate's subject different from the one of CSR
        p10Req = ScepUtil.generateRequest(privKey, subjectPublicKeyInfo, subject, secret, null);
        csr = p10Req.toASN1Structure();
        selfSignedCert = ScepUtil.generateSelfsignedCert(new X500Name("CN=dummy"), csr.getCertificationRequestInfo().getSubjectPublicKeyInfo(), privKey);
        enrolResp = client.scepPkcsReq(p10Req.toASN1Structure(), privKey, selfSignedCert);
        status = enrolResp.getPkcsRep().getPkiStatus();
        Assert.assertEquals("PkiStatus with invalid secret", PkiStatus.FAILURE, status);
    }
    // certPoll
    EnrolmentResponse enrolResp = client.scepCertPoll(privKey, selfSignedCert, csr, issuerName);
    List<X509Certificate> certs = enrolResp.getCertificates();
    Assert.assertTrue("number of received certificates", certs.size() > 0);
    X509Certificate cert = certs.get(0);
    Assert.assertNotNull("enrolled certificate", cert);
    // getCert
    certs = client.scepGetCert(privKey, selfSignedCert, issuerName, enroledCert.getSerialNumber());
    Assert.assertTrue("number of received certificates", certs.size() > 0);
    cert = certs.get(0);
    Assert.assertNotNull("received certificate", cert);
    // getCRL
    X509CRL crl = client.scepGetCrl(privKey, enroledCert, issuerName, enroledCert.getSerialNumber());
    Assert.assertNotNull("received CRL", crl);
    // getNextCA
    AuthorityCertStore nextCa = client.scepNextCaCert();
    Assert.assertNotNull("nextCa", nextCa);
}
Also used : PKCS10CertificationRequest(org.bouncycastle.pkcs.PKCS10CertificationRequest) PkiStatus(org.xipki.scep.transaction.PkiStatus) KeyPair(java.security.KeyPair) PrivateKey(java.security.PrivateKey) X509CRL(java.security.cert.X509CRL) CaIdentifier(org.xipki.scep.client.CaIdentifier) ScepClient(org.xipki.scep.client.ScepClient) X500Name(org.bouncycastle.asn1.x500.X500Name) KeyPairGenerator(java.security.KeyPairGenerator) SubjectPublicKeyInfo(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo) X509Certificate(java.security.cert.X509Certificate) CaCertValidator(org.xipki.scep.client.CaCertValidator) PreprovisionedCaCertValidator(org.xipki.scep.client.PreprovisionedCaCertValidator) CaCaps(org.xipki.scep.message.CaCaps) PreprovisionedCaCertValidator(org.xipki.scep.client.PreprovisionedCaCertValidator) EnrolmentResponse(org.xipki.scep.client.EnrolmentResponse) AuthorityCertStore(org.xipki.scep.message.AuthorityCertStore) List(java.util.List) PKCS10CertificationRequest(org.bouncycastle.pkcs.PKCS10CertificationRequest) CertificationRequest(org.bouncycastle.asn1.pkcs.CertificationRequest) X509Certificate(java.security.cert.X509Certificate) Certificate(org.bouncycastle.asn1.x509.Certificate) Test(org.junit.Test)

Aggregations

X509Certificate (java.security.cert.X509Certificate)2 CertificationRequest (org.bouncycastle.asn1.pkcs.CertificationRequest)2 PkiStatus (org.xipki.scep.transaction.PkiStatus)2 KeyPair (java.security.KeyPair)1 KeyPairGenerator (java.security.KeyPairGenerator)1 PrivateKey (java.security.PrivateKey)1 CertificateException (java.security.cert.CertificateException)1 X509CRL (java.security.cert.X509CRL)1 Date (java.util.Date)1 List (java.util.List)1 ASN1Encodable (org.bouncycastle.asn1.ASN1Encodable)1 ASN1ObjectIdentifier (org.bouncycastle.asn1.ASN1ObjectIdentifier)1 ASN1OctetString (org.bouncycastle.asn1.ASN1OctetString)1 DERPrintableString (org.bouncycastle.asn1.DERPrintableString)1 Attribute (org.bouncycastle.asn1.cms.Attribute)1 AttributeTable (org.bouncycastle.asn1.cms.AttributeTable)1 ContentInfo (org.bouncycastle.asn1.cms.ContentInfo)1 IssuerAndSerialNumber (org.bouncycastle.asn1.cms.IssuerAndSerialNumber)1 X500Name (org.bouncycastle.asn1.x500.X500Name)1 Certificate (org.bouncycastle.asn1.x509.Certificate)1