Example usage for org.bouncycastle.asn1.cmp PKIMessage getProtection

List of usage examples for org.bouncycastle.asn1.cmp PKIMessage getProtection

Introduction

In this page you can find the example usage for org.bouncycastle.asn1.cmp PKIMessage getProtection.

Prototype

public DERBitString getProtection() 

Source Link

Usage

From source file:org.ejbca.core.protocol.cmp.authentication.EndEntityCertificateAuthenticationModule.java

License:Open Source License

@Override
/*/*from ww w .j av a 2 s  .  c om*/
 * Verifies the signature of 'msg'. msg should be signed and the signer's certificate should be  
 * attached in msg in the extraCert field.  
 * 
 * When successful, the authentication string is set.
 */
public boolean verifyOrExtract(final PKIMessage msg, final String username) {

    //Check that msg is signed
    if (msg.getProtection() == null) {
        this.errorMessage = "PKI Message is not athenticated properly. No PKI protection is found.";
        return false;
    }

    // Read the extraCert and store it in a local variable
    extraCert = getExtraCert(msg);
    if (extraCert == null) {
        this.errorMessage = "Error while reading the certificate in the extraCert field";
        return false;
    }

    boolean vendormode = impl.isVendorCertificateMode(msg.getBody().getType(), this.confAlias);
    boolean omitVerifications = cmpConfiguration.getOmitVerificationsInEEC(confAlias);
    boolean ramode = cmpConfiguration.getRAMode(confAlias);
    if (log.isDebugEnabled()) {
        log.debug("CMP is operating in RA mode: " + this.cmpConfiguration.getRAMode(this.confAlias));
        log.debug("CMP is operating in Vendor mode: " + vendormode);
        log.debug("CMP message already been authenticated: " + authenticated);
        log.debug("Omitting som verifications: " + omitVerifications);
    }

    //----------------------------------------------------------------------------------------
    // Perform the different checks depending on the configuration and previous authentication
    //----------------------------------------------------------------------------------------

    // Not allowed combinations.
    if (ramode && vendormode) {
        this.errorMessage = "Vendor mode and RA mode cannot be combined";
        return false;
    }
    if (omitVerifications && (!ramode || !authenticated)) {
        this.errorMessage = "Omitting some verifications can only be accepted in RA mode and when the "
                + "CMP request has already been authenticated, for example, through the use of NestedMessageContent";
        return false;
    }

    // Accepted combinations
    if (omitVerifications && ramode && authenticated) {
        // Do nothing here
        if (log.isDebugEnabled()) {
            log.debug(
                    "Skipping some verification of the extraCert certificate in RA mode and an already authenticated CMP message, tex. through NestedMessageContent");
        }
    } else if (ramode) {

        // Get the CA to use for the authentication
        CAInfo cainfo = getCAInfoByName(authenticationparameter);
        if (cainfo == null)
            return false;

        // Check that extraCert is in the Database
        CertificateInfo certinfo = certSession.getCertificateInfo(CertTools.getFingerprintAsString(extraCert));
        if (certinfo == null) {
            this.errorMessage = "The certificate attached to the PKIMessage in the extraCert field could not be found in the database.";
            return false;
        }

        // More extraCert verifications
        if (!isExtraCertIssuedByCA(cainfo) || !isExtraCertValid() || !isExtraCertActive(certinfo)) {
            return false;
        }

        // Check that extraCert belong to an admin with sufficient access rights
        if (!isAuthorizedAdmin(certinfo, msg, cainfo.getCAId())) {
            this.errorMessage = "'" + CertTools.getSubjectDN(extraCert)
                    + "' is not an authorized administrator.";
            return false;
        }

    } else if (!ramode) { // client mode

        String extraCertUsername = null;
        if (vendormode) {

            // Check that extraCert is issued  by a configured VendorCA
            if (!impl.isExtraCertIssuedByVendorCA(admin, this.confAlias, extraCert)) {
                this.errorMessage = "The certificate in extraCert field is not issued by any of the configured Vendor CAs: "
                        + cmpConfiguration.getVendorCA(confAlias);
                return false;
            }

            // Extract the username from extraCert to use for  further authentication
            String subjectDN = CertTools.getSubjectDN(extraCert);
            extraCertUsername = CertTools.getPartFromDN(subjectDN,
                    this.cmpConfiguration.getExtractUsernameComponent(this.confAlias));
            if (log.isDebugEnabled()) {
                log.debug("Username (" + extraCertUsername + ") was extracted from the '"
                        + this.cmpConfiguration.getExtractUsernameComponent(this.confAlias)
                        + "' part of the subjectDN of the certificate in the 'extraCerts' field.");
            }

        } else {

            // Get the CA to use for the authentication
            CAInfo cainfo = getCAInfoByIssuer(CertTools.getIssuerDN(extraCert));

            // Check that extraCert is in the Database
            CertificateInfo certinfo = certSession
                    .getCertificateInfo(CertTools.getFingerprintAsString(extraCert));
            if (certinfo == null) {
                this.errorMessage = "The certificate attached to the PKIMessage in the extraCert field could not be found in the database.";
                return false;
            }

            // More extraCert verifications
            if (!isExtraCertIssuedByCA(cainfo) || !isExtraCertValid() || !isExtraCertActive(certinfo)) {
                return false;
            }

            // Extract the username from extraCert to use for  further authentication
            extraCertUsername = certinfo.getUsername();
        }

        // Check if this certificate belongs to the user
        if ((username != null) && (extraCertUsername != null)) {
            if (!StringUtils.equals(username, extraCertUsername)) {
                this.errorMessage = "The End Entity certificate attached to the PKIMessage in the extraCert field does not belong to user '"
                        + username + "'";
                if (log.isDebugEnabled()) {
                    // Use a different debug message, as not to reveal too much information
                    log.debug(this.errorMessage + ", but to user '" + extraCertUsername + "'");
                }
                return false;
            }

            //set the password of the request to this user's password so it can later be used when issuing the certificate
            if (log.isDebugEnabled()) {
                log.debug(
                        "The End Entity certificate attached to the PKIMessage in the extraCert field belongs to user '"
                                + username + "'.");
                log.debug("Extracting and setting password for user '" + username + "'.");
            }
            try {
                EndEntityInformation user = eeAccessSession.findUser(admin, username);
                password = user.getPassword();
                if (password == null) {
                    password = genRandomPwd();
                    user.setPassword(password);
                    eeManagementSession.changeUser(admin, user, false);
                }
            } catch (AuthorizationDeniedException e) {
                if (log.isDebugEnabled()) {
                    log.debug(e.getLocalizedMessage());
                }
                this.errorMessage = e.getLocalizedMessage();
                return false;
            } catch (CADoesntExistsException e) {
                if (log.isDebugEnabled()) {
                    log.debug(e.getLocalizedMessage());
                }
                this.errorMessage = e.getLocalizedMessage();
                return false;
            } catch (UserDoesntFullfillEndEntityProfile e) {
                if (log.isDebugEnabled()) {
                    log.debug(e.getLocalizedMessage());
                }
                this.errorMessage = e.getLocalizedMessage();
                return false;
            } catch (WaitingForApprovalException e) {
                if (log.isDebugEnabled()) {
                    log.debug(e.getLocalizedMessage());
                }
                this.errorMessage = e.getLocalizedMessage();
                return false;
            } catch (EjbcaException e) {
                if (log.isDebugEnabled()) {
                    log.debug(e.getLocalizedMessage());
                }
                this.errorMessage = e.getLocalizedMessage();
                return false;
            }
        }
    }

    //-------------------------------------------------------------
    //Begin the signature verification process.
    //Verify the signature of msg using the public key of extraCert
    //-------------------------------------------------------------
    try {
        final Signature sig = Signature.getInstance(msg.getHeader().getProtectionAlg().getAlgorithm().getId(),
                "BC");
        sig.initVerify(extraCert.getPublicKey());
        sig.update(CmpMessageHelper.getProtectedBytes(msg));
        if (sig.verify(msg.getProtection().getBytes())) {
            if (password == null) {
                // If not set earlier
                password = genRandomPwd();
            }
        } else {
            this.errorMessage = "Failed to verify the signature in the PKIMessage";
            return false;
        }
    } catch (InvalidKeyException e) {
        if (log.isDebugEnabled()) {
            log.debug(e.getLocalizedMessage());
        }
        this.errorMessage = e.getLocalizedMessage();
        return false;
    } catch (NoSuchAlgorithmException e) {
        if (log.isDebugEnabled()) {
            log.debug(e.getLocalizedMessage());
        }
        this.errorMessage = e.getLocalizedMessage();
        return false;
    } catch (NoSuchProviderException e) {
        if (log.isDebugEnabled()) {
            log.debug(e.getLocalizedMessage());
        }
        this.errorMessage = e.getLocalizedMessage();
        return false;
    } catch (SignatureException e) {
        if (log.isDebugEnabled()) {
            log.debug(e.getLocalizedMessage());
        }
        this.errorMessage = e.getLocalizedMessage();
        return false;
    }

    return this.password != null;
}

From source file:org.ejbca.core.protocol.cmp.authentication.HMACAuthenticationModule.java

License:Open Source License

@Override
/*/*ww  w  .ja  v a 2s .  c o  m*/
 * Verifies that 'msg' is sent by a trusted source. 
 * 
 * In RA mode:
 *      - A globally configured shared secret for all CAs will be used to authenticate the message.
 *      - If the globally shared secret fails, the password set in the CA will be used to authenticate the message.
 *  In client mode, the clear-text password set in the pre-registered end entity in the database will be used to 
 *  authenticate the message. 
 * 
 * When successful, the authentication string will be set to the password that was successfully used in authenticating the message.
 */
public boolean verifyOrExtract(final PKIMessage msg, final String username) {

    if (msg == null) {
        this.errorMessage = "No PKIMessage was found";
        return false;
    }

    if ((msg.getProtection() == null) || (msg.getHeader().getProtectionAlg() == null)) {
        this.errorMessage = "PKI Message is not athenticated properly. No HMAC protection was found.";
        return false;
    }

    try {
        verifyer = new CmpPbeVerifyer(msg);
    } catch (Exception e) {
        this.errorMessage = "Could not create CmpPbeVerifyer. " + e.getMessage();
        return false;
    }

    if (verifyer == null) {
        this.errorMessage = "Could not create CmpPbeVerifyer Object";
        return false;
    }

    if (this.cmpConfiguration.getRAMode(this.confAlias)) { //RA mode
        if (LOG.isDebugEnabled()) {
            LOG.debug("Verifying HMAC in RA mode");
        }

        // Check that the value of KeyId from the request is allowed 
        // Note that this restriction only applies to HMAC and not EndEntityCertificate because in the later, the use of profiles can be restricted through 
        // Administrator privileges. Other authentication modules are not used in RA mode
        if (StringUtils.equals(cmpConfiguration.getRAEEProfile(confAlias), "KeyId")
                || StringUtils.equals(cmpConfiguration.getRACertProfile(confAlias), "KeyId")) {
            final String keyId = CmpMessageHelper.getStringFromOctets(msg.getHeader().getSenderKID());
            if (StringUtils.equals(keyId, "EMPTY") || StringUtils.equals(keyId, "ENDUSER")) {
                errorMessage = "Unaccepted KeyId '" + keyId + "' in CMP request";
                LOG.info(errorMessage);
                return false;
            }
        }

        // If we use a globally configured shared secret for all CAs we check it right away
        String authSecret = globalSharedSecret;

        if (globalSharedSecret != null) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Verifying message using Global Shared secret");
            }
            try {
                if (verifyer.verify(authSecret)) {
                    this.password = authSecret;
                } else {
                    String errmsg = INTRES.getLocalizedMessage("cmp.errorauthmessage", "Global auth secret");
                    LOG.info(errmsg); // info because this is something we should expect and we handle it
                    if (verifyer.getErrMsg() != null) {
                        errmsg = verifyer.getErrMsg();
                        LOG.info(errmsg);
                    }
                }
            } catch (InvalidKeyException e) {
                this.errorMessage = e.getLocalizedMessage();
                if (LOG.isDebugEnabled()) {
                    LOG.debug(this.errorMessage, e);
                }
                return false;
            } catch (NoSuchAlgorithmException e) {
                this.errorMessage = e.getLocalizedMessage();
                if (LOG.isDebugEnabled()) {
                    LOG.debug(this.errorMessage, e);
                }
                return false;
            } catch (NoSuchProviderException e) {
                this.errorMessage = e.getLocalizedMessage();
                if (LOG.isDebugEnabled()) {
                    LOG.debug(this.errorMessage, e);
                }
                return false;
            }
        }

        // If password is null, then we failed verification using global shared secret
        if (this.password == null) {

            if (cainfo instanceof X509CAInfo) {
                authSecret = ((X509CAInfo) cainfo).getCmpRaAuthSecret();

                if (StringUtils.isNotEmpty(authSecret)) {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("Verify message using 'CMP RA Authentication Secret' from CA '"
                                + cainfo.getName() + "'.");
                    }
                    try {
                        if (verifyer.verify(authSecret)) {
                            this.password = authSecret;
                        } else {
                            // info because this is something we should expect and we handle it
                            LOG.info(INTRES.getLocalizedMessage("cmp.errorauthmessage",
                                    "Auth secret for CA=" + cainfo.getName()));
                            if (verifyer.getErrMsg() != null) {
                                LOG.info(verifyer.getErrMsg());
                            }
                        }
                    } catch (InvalidKeyException e) {
                        this.errorMessage = INTRES.getLocalizedMessage("cmp.errorgeneral");
                        LOG.error(this.errorMessage, e);
                        return false;
                    } catch (NoSuchAlgorithmException e) {
                        this.errorMessage = INTRES.getLocalizedMessage("cmp.errorgeneral");
                        LOG.error(this.errorMessage, e);
                        return false;
                    } catch (NoSuchProviderException e) {
                        this.errorMessage = INTRES.getLocalizedMessage("cmp.errorgeneral");
                        LOG.error(this.errorMessage, e);
                        return false;
                    }
                } else {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("CMP password is null from CA '" + cainfo.getName() + "'.");
                    }
                }
            }
        }

        // If password is still null, then we have failed verification with CA authentication secret too.
        if (password == null) {
            this.errorMessage = "Failed to verify message using both Global Shared Secret and CMP RA Authentication Secret";
            return false;
        }

    } else { //client mode
        if (LOG.isDebugEnabled()) {
            LOG.debug("Verifying HMAC in Client mode");
        }
        //If client mode, we try to get the pre-registered endentity from the DB, and if there is a 
        //clear text password we check HMAC using this password.
        EndEntityInformation userdata = null;
        String subjectDN = null;

        try {
            if (username != null) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Searching for an end entity with username='" + username + "'.");
                }
                userdata = this.eeAccessSession.findUser(admin, username);
            } else {
                // No username given, so we try to find from subject/issuerDN from the certificate request
                final CertTemplate certTemp = getCertTemplate(msg);
                subjectDN = certTemp.getSubject().toString();

                String issuerDN = null;
                final X500Name issuer = certTemp.getIssuer();
                if ((issuer != null) && (subjectDN != null)) {
                    issuerDN = issuer.toString();
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("Searching for an end entity with SubjectDN='" + subjectDN + "' and isserDN='"
                                + issuerDN + "'");
                    }

                    List<EndEntityInformation> userdataList = eeAccessSession
                            .findUserBySubjectAndIssuerDN(this.admin, subjectDN, issuerDN);
                    userdata = userdataList.get(0);
                    if (userdataList.size() > 1) {
                        LOG.warn("Multiple end entities with subject DN " + subjectDN + " and issuer DN"
                                + issuerDN + " were found. This may lead to unexpected behavior.");
                    }
                } else if (subjectDN != null) {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("Searching for an end entity with SubjectDN='" + subjectDN + "'.");
                    }
                    List<EndEntityInformation> userdataList = this.eeAccessSession.findUserBySubjectDN(admin,
                            subjectDN);
                    if (userdataList.size() > 0) {
                        userdata = userdataList.get(0);
                    }
                    if (userdataList.size() > 1) {
                        LOG.warn("Multiple end entities with subject DN " + subjectDN
                                + " were found. This may lead to unexpected behavior.");
                    }
                }
            }
        } catch (AuthorizationDeniedException e) {
            LOG.info("No EndEntity with subjectDN '" + subjectDN + "' could be found. "
                    + e.getLocalizedMessage());
        }

        if (userdata != null) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Comparing HMAC password authentication for user '" + userdata.getUsername() + "'.");
            }

            final String eepassword = userdata.getPassword();
            if (StringUtils.isNotEmpty(eepassword)) {
                try {
                    if (verifyer.verify(eepassword)) {
                        this.password = eepassword;
                    } else {
                        String errmsg = INTRES.getLocalizedMessage("cmp.errorauthmessage",
                                userdata.getUsername());
                        LOG.info(errmsg); // info because this is something we should expect and we handle it
                        if (verifyer.getErrMsg() != null) {
                            errmsg = verifyer.getErrMsg();
                            LOG.info(errmsg);
                        }
                        this.errorMessage = errmsg;
                        return false;
                    }
                } catch (InvalidKeyException e) {
                    this.errorMessage = INTRES.getLocalizedMessage("cmp.errorgeneral");
                    LOG.error(this.errorMessage, e);
                    return false;
                } catch (NoSuchAlgorithmException e) {
                    this.errorMessage = INTRES.getLocalizedMessage("cmp.errorgeneral");
                    LOG.error(this.errorMessage, e);
                    return false;
                } catch (NoSuchProviderException e) {
                    this.errorMessage = INTRES.getLocalizedMessage("cmp.errorgeneral");
                    LOG.error(this.errorMessage, e);
                    return false;
                }
            } else {
                this.errorMessage = "No clear text password for user '" + userdata.getUsername()
                        + "', not possible to check authentication.";
                return false;
            }
        } else {
            LOG.info(INTRES.getLocalizedMessage("ra.errorentitynotexist",
                    StringUtils.isNotEmpty(username) ? username : subjectDN));
            this.errorMessage = INTRES.getLocalizedMessage("ra.wrongusernameorpassword");
            return false;
        }
    }

    return this.password != null;
}

From source file:org.ejbca.core.protocol.cmp.AuthenticationModulesTest.java

License:Open Source License

@Test
public void test05EECrmfReq() throws NoSuchAlgorithmException, EjbcaException, IOException, Exception {
    this.cmpConfiguration.setAuthenticationModule(ALIAS, CmpConfiguration.AUTHMODULE_ENDENTITY_CERTIFICATE);
    this.cmpConfiguration.setAuthenticationParameters(ALIAS, "TestCA");
    this.cmpConfiguration.setRAMode(ALIAS, true);
    this.globalConfigurationSession.saveConfiguration(ADMIN, this.cmpConfiguration);

    final X500Name testUserDN = new X500Name("CN=cmptestuser5,C=SE");
    final String testUsername = "cmptestuser5";
    String fingerprint = null;/*from w  w w.  j av  a 2 s.c  o  m*/
    String fingerprint2 = null;
    AuthenticationToken admToken = null;
    Certificate admCert = null;
    try {
        KeyPair keys = KeyTools.genKeys("512", AlgorithmConstants.KEYALGORITHM_RSA);

        AlgorithmIdentifier pAlg = new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption);
        PKIMessage msg = genCertReq(issuerDN, testUserDN, keys, this.cacert, this.nonce, this.transid, false,
                null, null, null, null, pAlg, new DEROctetString(this.nonce));
        assertNotNull("Generating CrmfRequest failed.", msg);

        KeyPair admkeys = KeyTools.genKeys("512", "RSA");
        admToken = createAdminToken(admkeys, testUsername, testUserDN.toString(), this.caid,
                SecConst.EMPTY_ENDENTITYPROFILE, CertificateProfileConstants.CERTPROFILE_FIXED_ENDUSER);
        admCert = getCertFromCredentials(admToken);
        fingerprint = CertTools.getFingerprintAsString(admCert);

        CMPCertificate[] extraCert = getCMPCert(admCert);
        msg = CmpMessageHelper.buildCertBasedPKIProtection(msg, extraCert, admkeys.getPrivate(),
                pAlg.getAlgorithm().getId(), "BC");
        assertNotNull(msg);
        //******************************************''''''
        final Signature sig = Signature.getInstance(msg.getHeader().getProtectionAlg().getAlgorithm().getId(),
                "BC");
        sig.initVerify(admCert.getPublicKey());
        sig.update(CmpMessageHelper.getProtectedBytes(msg));
        boolean verified = sig.verify(msg.getProtection().getBytes());
        assertTrue("Signing the message failed.", verified);
        //***************************************************

        final ByteArrayOutputStream bao = new ByteArrayOutputStream();
        final DEROutputStream out = new DEROutputStream(bao);
        out.writeObject(msg);
        final byte[] ba = bao.toByteArray();
        // Send request and receive response
        final byte[] resp = sendCmpHttp(ba, 200, ALIAS);
        checkCmpResponseGeneral(resp, issuerDN, testUserDN, this.cacert,
                msg.getHeader().getSenderNonce().getOctets(), msg.getHeader().getTransactionID().getOctets(),
                true, null, PKCSObjectIdentifiers.sha1WithRSAEncryption.getId());
        CertReqMessages ir = (CertReqMessages) msg.getBody().getContent();
        Certificate cert2 = checkCmpCertRepMessage(testUserDN, this.cacert, resp,
                ir.toCertReqMsgArray()[0].getCertReq().getCertReqId().getValue().intValue());
        assertNotNull("CrmfRequest did not return a certificate", cert2);
        fingerprint2 = CertTools.getFingerprintAsString(cert2);
    } finally {
        removeAuthenticationToken(admToken, admCert, testUsername); // also removes testUsername
        this.internalCertStoreSession.removeCertificate(fingerprint);
        this.internalCertStoreSession.removeCertificate(fingerprint2);
    }
}

From source file:org.ejbca.core.protocol.cmp.AuthenticationModulesTest.java

License:Open Source License

@Test
public void test08EECrmfReqMultipleAuthModules()
        throws NoSuchAlgorithmException, EjbcaException, IOException, Exception {
    String modules = CmpConfiguration.AUTHMODULE_HMAC + ";" + CmpConfiguration.AUTHMODULE_ENDENTITY_CERTIFICATE;
    String parameters = "foo123" + ";" + "TestCA";
    this.cmpConfiguration.setAuthenticationModule(ALIAS, modules);
    this.cmpConfiguration.setAuthenticationParameters(ALIAS, parameters);
    this.cmpConfiguration.setRAMode(ALIAS, true);
    this.globalConfigurationSession.saveConfiguration(ADMIN, this.cmpConfiguration);

    KeyPair keys = KeyTools.genKeys("512", AlgorithmConstants.KEYALGORITHM_RSA);

    AlgorithmIdentifier pAlg = new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption);
    PKIMessage msg = genCertReq(issuerDN, USER_DN, keys, this.cacert, this.nonce, this.transid, false, null,
            null, null, null, pAlg, null);
    assertNotNull("Generating CrmfRequest failed.", msg);

    String adminName = "cmpTestAdmin";
    KeyPair admkeys = KeyTools.genKeys("1024", "RSA");
    AuthenticationToken adminToken = createAdminToken(admkeys, adminName, "CN=" + adminName + ",C=SE",
            this.caid, SecConst.EMPTY_ENDENTITYPROFILE, CertificateProfileConstants.CERTPROFILE_FIXED_ENDUSER);
    Certificate admCert = getCertFromCredentials(adminToken);
    CMPCertificate[] extraCert = getCMPCert(admCert);
    msg = CmpMessageHelper.buildCertBasedPKIProtection(msg, extraCert, admkeys.getPrivate(),
            pAlg.getAlgorithm().getId(), "BC");
    assertNotNull(msg);/*from  www  .  j ava  2s  .c  o  m*/

    //********************************************
    final Signature sig = Signature.getInstance(msg.getHeader().getProtectionAlg().getAlgorithm().getId(),
            "BC");
    sig.initVerify(admCert.getPublicKey());
    sig.update(CmpMessageHelper.getProtectedBytes(msg));
    boolean verified = sig.verify(msg.getProtection().getBytes());
    assertTrue("Signing the message failed.", verified);
    //********************************************

    final ByteArrayOutputStream bao = new ByteArrayOutputStream();
    final DEROutputStream out = new DEROutputStream(bao);
    out.writeObject(msg);
    final byte[] ba = bao.toByteArray();
    // Send request and receive response
    final byte[] resp = sendCmpHttp(ba, 200, ALIAS);
    checkCmpResponseGeneral(resp, issuerDN, USER_DN, this.cacert, msg.getHeader().getSenderNonce().getOctets(),
            msg.getHeader().getTransactionID().getOctets(), true, null,
            PKCSObjectIdentifiers.sha1WithRSAEncryption.getId());
    CertReqMessages ir = (CertReqMessages) msg.getBody().getContent();
    Certificate cert2 = checkCmpCertRepMessage(USER_DN, this.cacert, resp,
            ir.toCertReqMsgArray()[0].getCertReq().getCertReqId().getValue().intValue());
    assertNotNull("CrmfRequest did not return a certificate", cert2);

    removeAuthenticationToken(adminToken, admCert, adminName);
}

From source file:org.ejbca.core.protocol.cmp.AuthenticationModulesTest.java

License:Open Source License

@Test
public void test12EECrmfNotCheckAdmin()
        throws NoSuchAlgorithmException, EjbcaException, IOException, Exception {
    this.cmpConfiguration.setAuthenticationModule(ALIAS, CmpConfiguration.AUTHMODULE_ENDENTITY_CERTIFICATE);
    this.cmpConfiguration.setAuthenticationParameters(ALIAS, "TestCA");
    this.cmpConfiguration.setOmitVerificationsInECC(ALIAS, true);
    this.cmpConfiguration.setRAMode(ALIAS, true);
    this.globalConfigurationSession.saveConfiguration(ADMIN, this.cmpConfiguration);

    KeyPair keys = KeyTools.genKeys("512", AlgorithmConstants.KEYALGORITHM_RSA);

    AlgorithmIdentifier pAlg = new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption);
    PKIMessage msg = genCertReq(issuerDN, USER_DN, keys, this.cacert, this.nonce, this.transid, false, null,
            null, null, null, pAlg, new DEROctetString(this.nonce));
    assertNotNull("Generating CrmfRequest failed.", msg);

    String adminName = "cmpTestAdmin";
    KeyPair admkeys = KeyTools.genKeys("1024", "RSA");
    AuthenticationToken adminToken = createAdminToken(admkeys, adminName, "CN=" + adminName + ",C=SE",
            this.caid, SecConst.EMPTY_ENDENTITYPROFILE, CertificateProfileConstants.CERTPROFILE_FIXED_ENDUSER);
    Certificate admCert = getCertFromCredentials(adminToken);
    CMPCertificate[] extraCert = getCMPCert(admCert);
    msg = CmpMessageHelper.buildCertBasedPKIProtection(msg, extraCert, admkeys.getPrivate(),
            pAlg.getAlgorithm().getId(), "BC");
    assertNotNull(msg);//from   w  w w .j a v  a  2  s  .  c o  m

    //********************************************
    final Signature sig = Signature.getInstance(msg.getHeader().getProtectionAlg().getAlgorithm().getId(),
            "BC");
    sig.initVerify(admCert.getPublicKey());
    sig.update(CmpMessageHelper.getProtectedBytes(msg));
    boolean verified = sig.verify(msg.getProtection().getBytes());
    assertTrue("Signing the message failed.", verified);
    //********************************************

    final ByteArrayOutputStream bao = new ByteArrayOutputStream();
    final DEROutputStream out = new DEROutputStream(bao);
    out.writeObject(msg);
    final byte[] ba = bao.toByteArray();
    // Send request and receive response
    final byte[] resp = sendCmpHttp(ba, 200, ALIAS);
    checkCmpResponseGeneral(resp, issuerDN, USER_DN, this.cacert, msg.getHeader().getSenderNonce().getOctets(),
            msg.getHeader().getTransactionID().getOctets(), false, null,
            PKCSObjectIdentifiers.sha1WithRSAEncryption.getId());
    ASN1InputStream inputStream = new ASN1InputStream(new ByteArrayInputStream(resp));
    try {
        PKIMessage respObject = PKIMessage.getInstance(inputStream.readObject());
        assertNotNull(respObject);

        PKIBody body = respObject.getBody();
        assertEquals(23, body.getType());
        ErrorMsgContent err = (ErrorMsgContent) body.getContent();
        String errMsg = err.getPKIStatusInfo().getStatusString().getStringAt(0).getString();
        String expectedErrmsg = "Omitting some verifications can only be accepted in RA mode and when the CMP request has already been authenticated, for example, through the use of NestedMessageContent";
        assertEquals(expectedErrmsg, errMsg);
    } finally {
        inputStream.close();
    }
    removeAuthenticationToken(adminToken, admCert, adminName);

}

From source file:org.ejbca.core.protocol.cmp.AuthenticationModulesTest.java

License:Open Source License

/** Test CMP initial request against EJBCA CMP in client mode (operationmode=normal) using End Entity certificate signature authentication, 
 * i.e. the request is signed by a certificate of the same end entity making the request, and this signature is used for authenticating the end entity.
 * Test:/*w  ww .j  av  a2 s  .c o  m*/
 * - Request signed by a fake certificate, i.e. one that is not in the database (FAIL)
 * - Request signed by a certificate that beloongs to another user (FAIL)
 * - Request signed by a proper certificate but where user status is not NEW (FAIL)
 * - Request signed by a proper, but revoked certificate (FAIL)
 * - A working request signed by a proper, unrevoked certificate and user status is NEW (SUCCESS)
 * 
 * @throws Exception on some errors
 */
@Test
public void test18CrmfReqClientModeEESignature() throws Exception {
    this.cmpConfiguration.setAuthenticationModule(ALIAS, CmpConfiguration.AUTHMODULE_ENDENTITY_CERTIFICATE);
    this.cmpConfiguration.setAuthenticationParameters(ALIAS, "-");
    this.cmpConfiguration.setRAMode(ALIAS, false);
    this.globalConfigurationSession.saveConfiguration(ADMIN, this.cmpConfiguration);

    final X500Name testUserDN = new X500Name("CN=cmptestuser16,C=SE");
    final String testUsername = "cmptestuser16";
    final String otherUserDN = "CN=cmptestotheruser16,C=SE";
    final String otherUsername = "cmptestotheruser16";
    String fingerprint = null;
    String fingerprint2 = null;
    String fingerprint3 = null;
    try {
        KeyPair keys = KeyTools.genKeys("512", AlgorithmConstants.KEYALGORITHM_RSA);
        KeyPair fakeKeys = KeyTools.genKeys("512", AlgorithmConstants.KEYALGORITHM_RSA);
        createUser(testUsername, testUserDN.toString(), "foo123", true, this.caid,
                SecConst.EMPTY_ENDENTITYPROFILE, CertificateProfileConstants.CERTPROFILE_FIXED_ENDUSER);
        // A real certificate that can be used to sign the message
        Certificate cert = this.signSession.createCertificate(ADMIN, testUsername, "foo123",
                new PublicKeyWrapper(keys.getPublic()));
        fingerprint = CertTools.getFingerprintAsString(cert);
        // A fake certificate that should not be valid
        Certificate fakeCert = CertTools.genSelfCert(testUserDN.toString(), 30, null, fakeKeys.getPrivate(),
                fakeKeys.getPublic(), AlgorithmConstants.SIGALG_SHA1_WITH_RSA, false);

        // Step 1 sign with fake certificate, should not be valid as end entity authentication
        {
            AlgorithmIdentifier pAlg = new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption);
            PKIMessage msg = genCertReq(issuerDN, testUserDN, keys, this.cacert, this.nonce, this.transid,
                    false, null, null, null, null, pAlg, null);
            assertNotNull("Generating CrmfRequest failed.", msg);
            CMPCertificate[] extraCert = getCMPCert(fakeCert);
            msg = CmpMessageHelper.buildCertBasedPKIProtection(msg, extraCert, fakeKeys.getPrivate(),
                    pAlg.getAlgorithm().getId(), "BC");
            assertNotNull(msg);
            //******************************************''''''
            final Signature sig = Signature
                    .getInstance(msg.getHeader().getProtectionAlg().getAlgorithm().getId(), "BC");
            sig.initVerify(fakeCert.getPublicKey());
            sig.update(CmpMessageHelper.getProtectedBytes(msg));
            boolean verified = sig.verify(msg.getProtection().getBytes());
            assertTrue("Signing the message failed.", verified);
            //***************************************************

            final ByteArrayOutputStream bao = new ByteArrayOutputStream();
            final DEROutputStream out = new DEROutputStream(bao);
            out.writeObject(msg);
            final byte[] ba = bao.toByteArray();
            // Send request and receive response
            final byte[] resp = sendCmpHttp(ba, 200, ALIAS);
            // This should have failed
            checkCmpResponseGeneral(resp, issuerDN, testUserDN, this.cacert,
                    msg.getHeader().getSenderNonce().getOctets(),
                    msg.getHeader().getTransactionID().getOctets(), false, null,
                    PKCSObjectIdentifiers.sha1WithRSAEncryption.getId());
            ASN1InputStream inputStream = new ASN1InputStream(new ByteArrayInputStream(resp));
            PKIMessage respObject = PKIMessage.getInstance(inputStream.readObject());
            try {
                assertNotNull(respObject);
                PKIBody body = respObject.getBody();
                assertEquals(23, body.getType());
                ErrorMsgContent err = (ErrorMsgContent) body.getContent();
                String errMsg = err.getPKIStatusInfo().getStatusString().getStringAt(0).getString();
                String expectedErrMsg = "The certificate attached to the PKIMessage in the extraCert field could not be found in the database.";
                assertEquals(expectedErrMsg, errMsg);
            } finally {
                inputStream.close();
            }
        }
        // Step 2, sign the request with a certificate that does not belong to the user
        {
            KeyPair otherKeys = KeyTools.genKeys("512", AlgorithmConstants.KEYALGORITHM_RSA);
            createUser(otherUsername, otherUserDN, "foo123", true, this.caid, SecConst.EMPTY_ENDENTITYPROFILE,
                    CertificateProfileConstants.CERTPROFILE_FIXED_ENDUSER);
            // A real certificate that can be used to sign the message
            Certificate othercert = this.signSession.createCertificate(ADMIN, otherUsername, "foo123",
                    new PublicKeyWrapper(otherKeys.getPublic()));
            fingerprint2 = CertTools.getFingerprintAsString(cert);
            AlgorithmIdentifier pAlg = new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption);
            PKIMessage msg = genCertReq(issuerDN, testUserDN, keys, this.cacert, this.nonce, this.transid,
                    false, null, null, null, null, pAlg, null);
            assertNotNull("Generating CrmfRequest failed.", msg);
            CMPCertificate[] extraCert = getCMPCert(othercert);
            msg = CmpMessageHelper.buildCertBasedPKIProtection(msg, extraCert, otherKeys.getPrivate(),
                    pAlg.getAlgorithm().getId(), "BC");
            assertNotNull(msg);
            //******************************************''''''
            final Signature sig = Signature
                    .getInstance(msg.getHeader().getProtectionAlg().getAlgorithm().getId(), "BC");
            sig.initVerify(othercert.getPublicKey());
            sig.update(CmpMessageHelper.getProtectedBytes(msg));
            boolean verified = sig.verify(msg.getProtection().getBytes());
            assertTrue("Signing the message failed.", verified);
            //***************************************************

            final ByteArrayOutputStream bao = new ByteArrayOutputStream();
            final DEROutputStream out = new DEROutputStream(bao);
            out.writeObject(msg);
            final byte[] ba = bao.toByteArray();
            // Send request and receive response
            final byte[] resp = sendCmpHttp(ba, 200, ALIAS);
            // This should have failed
            checkCmpResponseGeneral(resp, issuerDN, testUserDN, this.cacert,
                    msg.getHeader().getSenderNonce().getOctets(),
                    msg.getHeader().getTransactionID().getOctets(), false, null,
                    PKCSObjectIdentifiers.sha1WithRSAEncryption.getId());
            ASN1InputStream inputStream = new ASN1InputStream(new ByteArrayInputStream(resp));
            try {
                PKIMessage respObject = PKIMessage.getInstance(inputStream.readObject());
                assertNotNull(respObject);
                PKIBody body = respObject.getBody();
                assertEquals(23, body.getType());
                ErrorMsgContent err = (ErrorMsgContent) body.getContent();
                String errMsg = err.getPKIStatusInfo().getStatusString().getStringAt(0).getString();
                String expectedErrMsg = "The End Entity certificate attached to the PKIMessage in the extraCert field does not belong to user '"
                        + testUsername + "'";
                assertEquals(expectedErrMsg, errMsg);
            } finally {
                inputStream.close();
            }
        }

        // Step 3 sign with the real certificate, but user status is not NEW
        AlgorithmIdentifier pAlg = new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption);
        PKIMessage msg = genCertReq(issuerDN, testUserDN, keys, this.cacert, this.nonce, this.transid, false,
                null, null, null, null, pAlg, null);
        assertNotNull("Generating CrmfRequest failed.", msg);
        CMPCertificate[] extraCert = getCMPCert(cert);
        msg = CmpMessageHelper.buildCertBasedPKIProtection(msg, extraCert, keys.getPrivate(),
                pAlg.getAlgorithm().getId(), "BC");
        assertNotNull(msg);
        //******************************************''''''
        final Signature sig = Signature.getInstance(msg.getHeader().getProtectionAlg().getAlgorithm().getId(),
                "BC");
        sig.initVerify(cert.getPublicKey());
        sig.update(CmpMessageHelper.getProtectedBytes(msg));
        boolean verified = sig.verify(msg.getProtection().getBytes());
        assertTrue("Signing the message failed.", verified);
        //***************************************************

        final ByteArrayOutputStream bao = new ByteArrayOutputStream();
        final DEROutputStream out = new DEROutputStream(bao);
        out.writeObject(msg);
        final byte[] ba = bao.toByteArray();
        // Send request and receive response
        final byte[] resp = sendCmpHttp(ba, 200, ALIAS);
        checkCmpResponseGeneral(resp, issuerDN, testUserDN, this.cacert,
                msg.getHeader().getSenderNonce().getOctets(), msg.getHeader().getTransactionID().getOctets(),
                false, null, PKCSObjectIdentifiers.sha1WithRSAEncryption.getId());
        // This should have failed
        ASN1InputStream inputStream = new ASN1InputStream(new ByteArrayInputStream(resp));
        try {
            PKIMessage respObject = PKIMessage.getInstance(inputStream.readObject());
            assertNotNull(respObject);
            PKIBody body = respObject.getBody();
            assertEquals(23, body.getType());
            ErrorMsgContent err = (ErrorMsgContent) body.getContent();
            String errMsg = err.getPKIStatusInfo().getStatusString().getStringAt(0).getString();
            String expectedErrMsg = "Got request with status GENERATED (40), NEW, FAILED or INPROCESS required: cmptestuser16.";
            assertEquals(expectedErrMsg, errMsg);

            // Step 4 now set status to NEW, and a clear text password, then it should finally work
            createUser(testUsername, testUserDN.toString(), "randompasswordhere", true, this.caid,
                    SecConst.EMPTY_ENDENTITYPROFILE, CertificateProfileConstants.CERTPROFILE_FIXED_ENDUSER);
            // Send request and receive response
            final byte[] resp2 = sendCmpHttp(ba, 200, ALIAS);
            CertReqMessages ir = (CertReqMessages) msg.getBody().getContent();
            Certificate cert2 = checkCmpCertRepMessage(testUserDN, this.cacert, resp2,
                    ir.toCertReqMsgArray()[0].getCertReq().getCertReqId().getValue().intValue());
            assertNotNull("CrmfRequest did not return a certificate", cert2);
            fingerprint3 = CertTools.getFingerprintAsString(cert2);

            // Step 5, revoke the certificate and try again
            {
                this.certificateStoreSession.setRevokeStatus(ADMIN, cert,
                        RevokedCertInfo.REVOCATION_REASON_CESSATIONOFOPERATION, null);
                final byte[] resp3 = sendCmpHttp(ba, 200, ALIAS);
                // This should have failed
                checkCmpResponseGeneral(resp, issuerDN, testUserDN, this.cacert,
                        msg.getHeader().getSenderNonce().getOctets(),
                        msg.getHeader().getTransactionID().getOctets(), false, null,
                        PKCSObjectIdentifiers.sha1WithRSAEncryption.getId());
                ASN1InputStream inputStream3 = new ASN1InputStream(new ByteArrayInputStream(resp3));
                try {
                    PKIMessage respObject3 = PKIMessage.getInstance(inputStream3.readObject());
                    assertNotNull(respObject);
                    PKIBody body3 = respObject3.getBody();
                    assertEquals(23, body3.getType());
                    err = (ErrorMsgContent) body3.getContent();
                    String errMsg3 = err.getPKIStatusInfo().getStatusString().getStringAt(0).getString();
                    String expectedErrMsg3 = "The certificate attached to the PKIMessage in the extraCert field is not active.";
                    assertEquals(expectedErrMsg3, errMsg3);
                } finally {
                    inputStream3.close();
                }
            }
        } finally {
            inputStream.close();
        }

    } finally {
        try {
            this.endEntityManagementSession.revokeAndDeleteUser(ADMIN, testUsername, ReasonFlags.unused);
        } catch (Exception e) {// do nothing
        }

        try {
            this.endEntityManagementSession.revokeAndDeleteUser(ADMIN, otherUsername, ReasonFlags.unused);
        } catch (Exception e) {// do nothing
        }

        this.internalCertStoreSession.removeCertificate(fingerprint);
        this.internalCertStoreSession.removeCertificate(fingerprint2);
        this.internalCertStoreSession.removeCertificate(fingerprint3);
    }
}

From source file:org.ejbca.core.protocol.cmp.AuthenticationModulesTest.java

License:Open Source License

/**
 * Tests that EndEntityAuthentication module can be successfully used in client mode when the end entity's password is not stored in clear text.
 * /*from  w w  w  . j av a 2  s .  co  m*/
 * @throws Exception
 */
@Test
public void test21CrmfRequestClientModeEECNotClearPassword() throws Exception {
    this.cmpConfiguration.setAuthenticationModule(ALIAS, CmpConfiguration.AUTHMODULE_ENDENTITY_CERTIFICATE);
    this.cmpConfiguration.setAuthenticationParameters(ALIAS, "-");
    this.cmpConfiguration.setRAMode(ALIAS, false);
    this.globalConfigurationSession.saveConfiguration(ADMIN, this.cmpConfiguration);

    final X500Name testUserDN = new X500Name("CN=cmptestuser21,C=SE");
    final String testUsername = "cmptestuser21";
    String fingerprint = null;
    String fingerprint2 = null;
    try {
        KeyPair keys = KeyTools.genKeys("512", AlgorithmConstants.KEYALGORITHM_RSA);
        AlgorithmIdentifier pAlg = new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption);

        createUser(testUsername, testUserDN.toString(), "foo123", false, this.caid,
                SecConst.EMPTY_ENDENTITYPROFILE, CertificateProfileConstants.CERTPROFILE_FIXED_ENDUSER);
        Certificate cert = this.signSession.createCertificate(ADMIN, testUsername, "foo123",
                new PublicKeyWrapper(keys.getPublic()));
        fingerprint = CertTools.getFingerprintAsString(cert);

        //Edit the status of the user to NEW
        createUser(testUsername, testUserDN.toString(), "foo123", false, this.caid,
                SecConst.EMPTY_ENDENTITYPROFILE, CertificateProfileConstants.CERTPROFILE_FIXED_ENDUSER);
        PKIMessage msg = genCertReq(issuerDN, testUserDN, keys, this.cacert, this.nonce, this.transid, false,
                null, null, null, null, pAlg, null);
        assertNotNull("Generating CrmfRequest failed.", msg);
        CMPCertificate[] extraCert = getCMPCert(cert);
        msg = CmpMessageHelper.buildCertBasedPKIProtection(msg, extraCert, keys.getPrivate(),
                pAlg.getAlgorithm().getId(), "BC");
        assertNotNull(msg);
        //******************************************''''''
        final Signature sig = Signature.getInstance(msg.getHeader().getProtectionAlg().getAlgorithm().getId(),
                "BC");
        sig.initVerify(cert.getPublicKey());
        sig.update(CmpMessageHelper.getProtectedBytes(msg));
        boolean verified = sig.verify(msg.getProtection().getBytes());
        assertTrue("Signing the message failed.", verified);
        //***************************************************

        final ByteArrayOutputStream bao = new ByteArrayOutputStream();
        final DEROutputStream out = new DEROutputStream(bao);
        out.writeObject(msg);
        final byte[] ba = bao.toByteArray();

        // Send request and receive response
        final byte[] resp = sendCmpHttp(ba, 200, ALIAS);
        CertReqMessages ir = (CertReqMessages) msg.getBody().getContent();
        Certificate cert2 = checkCmpCertRepMessage(testUserDN, this.cacert, resp,
                ir.toCertReqMsgArray()[0].getCertReq().getCertReqId().getValue().intValue());
        assertNotNull("CrmfRequest did not return a certificate", cert2);
        fingerprint2 = CertTools.getFingerprintAsString(cert2);
    } finally {
        try {
            this.endEntityManagementSession.revokeAndDeleteUser(ADMIN, testUsername, ReasonFlags.unused);
        } catch (Exception e) {// do nothing
        }

        this.internalCertStoreSession.removeCertificate(fingerprint);
        this.internalCertStoreSession.removeCertificate(fingerprint2);
    }
}

From source file:org.ejbca.core.protocol.cmp.CmpMessageHelper.java

License:Open Source License

/** verifies signature protection on CMP PKI messages
 *  //from ww w. j ava  2 s . c om
 * @param pKIMessage the CMP message to verify signature on, if protected by signature protection
 * @param pubKey the public key used to verify the signature
 * @return true if verification is ok or false if verification fails
 * @throws NoSuchAlgorithmException message is signed by an unknown algorithm
 * @throws NoSuchProviderException the BouncyCastle (BC) provider is not installed
 * @throws InvalidKeyException pubKey is not valid for signature verification
 * @throws SignatureException if the passed-in signature is improperly encoded or of the wrong type, if this signature algorithm is unable to process the input data provided, etc.
 */
public static boolean verifyCertBasedPKIProtection(PKIMessage pKIMessage, PublicKey pubKey)
        throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException {
    AlgorithmIdentifier sigAlg = pKIMessage.getHeader().getProtectionAlg();
    if (LOG.isDebugEnabled()) {
        LOG.debug("Verifying signature with algorithm: " + sigAlg.getAlgorithm().getId());
    }
    Signature sig = Signature.getInstance(sigAlg.getAlgorithm().getId(), "BC");
    sig.initVerify(pubKey);
    sig.update(CmpMessageHelper.getProtectedBytes(pKIMessage));
    boolean result = sig.verify(pKIMessage.getProtection().getBytes());
    if (LOG.isDebugEnabled()) {
        LOG.debug("Verification result: " + result);
    }
    return result;
}

From source file:org.ejbca.core.protocol.cmp.CmpPbeVerifyer.java

License:Open Source License

public CmpPbeVerifyer(final PKIMessage msg) {
    final PKIHeader head = msg.getHeader();
    protectedBytes = CmpMessageHelper.getProtectedBytes(msg);
    protection = msg.getProtection();
    pAlg = head.getProtectionAlg();/*from ww w  .ja v a2 s .co m*/
    final ASN1ObjectIdentifier algId = pAlg.getAlgorithm();
    if (!StringUtils.equals(algId.getId(), CMPObjectIdentifiers.passwordBasedMac.getId())) {
        final String errMsg = "Protection algorithm id expected '"
                + CMPObjectIdentifiers.passwordBasedMac.getId() + "' (passwordBasedMac) but was '"
                + algId.getId() + "'.";
        throw new IllegalArgumentException(errMsg);
    }
    final PBMParameter pp = PBMParameter.getInstance(pAlg.getParameters());
    iterationCount = pp.getIterationCount().getPositiveValue().intValue();
    final AlgorithmIdentifier owfAlg = pp.getOwf();
    // Normal OWF alg is 1.3.14.3.2.26 - SHA1
    owfOid = owfAlg.getAlgorithm().getId();
    final AlgorithmIdentifier macAlg = pp.getMac();
    // Normal mac alg is 1.3.6.1.5.5.8.1.2 - HMAC/SHA1
    macOid = macAlg.getAlgorithm().getId();
    if (LOG.isDebugEnabled()) {
        LOG.debug("Protection type is: " + algId.getId());
        LOG.debug("Iteration count is: " + iterationCount);
        LOG.debug("Owf type is: " + owfOid);
        LOG.debug("Mac type is: " + macOid);
    }
    salt = pp.getSalt().getOctets();
    //log.info("Salt: "+new String(salt));
}

From source file:org.ejbca.core.protocol.cmp.CmpTestCase.java

License:Open Source License

protected static void checkCmpResponseGeneral(byte[] retMsg, String issuerDN, X500Name userDN,
        Certificate cacert, byte[] senderNonce, byte[] transId, boolean signed, String pbeSecret,
        String expectedSignAlg)/*ww w .ja  v  a 2  s  .c o  m*/
        throws IOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException {
    assertNotNull("No response from server.", retMsg);
    assertTrue("Response was of 0 length.", retMsg.length > 0);
    boolean pbe = (pbeSecret != null);
    //
    // Parse response message
    //
    ASN1InputStream asn1InputStream = new ASN1InputStream(new ByteArrayInputStream(retMsg));
    PKIMessage respObject = null;
    try {
        respObject = PKIMessage.getInstance(asn1InputStream.readObject());
    } finally {
        asn1InputStream.close();
    }
    assertNotNull(respObject);

    // The signer, i.e. the CA, check it's the right CA
    PKIHeader header = respObject.getHeader();

    // Check that the message is signed with the correct digest alg
    if (StringUtils.isEmpty(expectedSignAlg)) {
        expectedSignAlg = PKCSObjectIdentifiers.sha1WithRSAEncryption.getId();
    }
    // if cacert is ECDSA we should expect an ECDSA signature alg
    //if (AlgorithmTools.getSignatureAlgorithm(cacert).contains("ECDSA")) {
    //    expectedSignAlg = X9ObjectIdentifiers.ecdsa_with_SHA1.getId();
    //} else if(AlgorithmTools.getSignatureAlgorithm(cacert).contains("ECGOST3410")) {
    //    expectedSignAlg = CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001.getId();
    //} else if(AlgorithmTools.getSignatureAlgorithm(cacert).contains("DSTU4145")) {
    //    expectedSignAlg = (new ASN1ObjectIdentifier(CesecoreConfiguration.getOidDstu4145())).getId();
    //}
    if (signed) {
        AlgorithmIdentifier algId = header.getProtectionAlg();
        assertNotNull(
                "Protection algorithm was null when expecting a signed response, this was propably an unprotected error message: "
                        + header.getFreeText(),
                algId);
        assertEquals(expectedSignAlg, algId.getAlgorithm().getId());
    }
    if (pbe) {
        AlgorithmIdentifier algId = header.getProtectionAlg();
        assertNotNull(
                "Protection algorithm was null when expecting a pbe protected response, this was propably an unprotected error message: "
                        + header.getFreeText(),
                algId);
        assertEquals("Protection algorithm id: " + algId.getAlgorithm().getId(),
                CMPObjectIdentifiers.passwordBasedMac.getId(), algId.getAlgorithm().getId()); // 1.2.840.113549.1.1.5 - SHA-1 with RSA Encryption
    }

    // Check that the signer is the expected CA    
    assertEquals(header.getSender().getTagNo(), 4);

    X500Name expissuer = new X500Name(issuerDN);
    X500Name actissuer = new X500Name(header.getSender().getName().toString());
    assertEquals(expissuer, actissuer);
    if (signed) {
        // Verify the signature
        byte[] protBytes = CmpMessageHelper.getProtectedBytes(respObject);
        DERBitString bs = respObject.getProtection();
        Signature sig;
        try {
            sig = Signature.getInstance(expectedSignAlg, "BC");
            sig.initVerify(cacert);
            sig.update(protBytes);
            boolean ret = sig.verify(bs.getBytes());
            assertTrue(ret);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            assertTrue(false);
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
            assertTrue(false);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            assertTrue(false);
        } catch (SignatureException e) {
            e.printStackTrace();
            assertTrue(false);
        }
    }
    if (pbe) {
        ASN1OctetString os = header.getSenderKID();
        assertNotNull(os);
        String keyId = CmpMessageHelper.getStringFromOctets(os);
        log.debug("Found a sender keyId: " + keyId);
        // Verify the PasswordBased protection of the message
        byte[] protectedBytes = CmpMessageHelper.getProtectedBytes(respObject);
        DERBitString protection = respObject.getProtection();
        AlgorithmIdentifier pAlg = header.getProtectionAlg();
        log.debug("Protection type is: " + pAlg.getAlgorithm().getId());
        PBMParameter pp = PBMParameter.getInstance(pAlg.getParameters());
        int iterationCount = pp.getIterationCount().getPositiveValue().intValue();
        log.debug("Iteration count is: " + iterationCount);
        AlgorithmIdentifier owfAlg = pp.getOwf();
        // Normal OWF alg is 1.3.14.3.2.26 - SHA1
        log.debug("Owf type is: " + owfAlg.getAlgorithm().getId());
        AlgorithmIdentifier macAlg = pp.getMac();
        // Normal mac alg is 1.3.6.1.5.5.8.1.2 - HMAC/SHA1
        log.debug("Mac type is: " + macAlg.getAlgorithm().getId());
        byte[] salt = pp.getSalt().getOctets();
        // log.info("Salt is: "+new String(salt));
        byte[] raSecret = pbeSecret != null ? pbeSecret.getBytes() : new byte[0];
        byte[] basekey = new byte[raSecret.length + salt.length];
        System.arraycopy(raSecret, 0, basekey, 0, raSecret.length);
        for (int i = 0; i < salt.length; i++) {
            basekey[raSecret.length + i] = salt[i];
        }
        // Construct the base key according to rfc4210, section 5.1.3.1
        MessageDigest dig = MessageDigest.getInstance(owfAlg.getAlgorithm().getId(),
                BouncyCastleProvider.PROVIDER_NAME);
        for (int i = 0; i < iterationCount; i++) {
            basekey = dig.digest(basekey);
            dig.reset();
        }
        // HMAC/SHA1 os normal 1.3.6.1.5.5.8.1.2 or 1.2.840.113549.2.7
        String macOid = macAlg.getAlgorithm().getId();
        Mac mac = Mac.getInstance(macOid, BouncyCastleProvider.PROVIDER_NAME);
        SecretKey key = new SecretKeySpec(basekey, macOid);
        mac.init(key);
        mac.reset();
        mac.update(protectedBytes, 0, protectedBytes.length);
        byte[] out = mac.doFinal();
        // My out should now be the same as the protection bits
        byte[] pb = protection.getBytes();
        boolean ret = Arrays.equals(out, pb);
        assertTrue(ret);
    }

    // --SenderNonce
    // SenderNonce is something the server came up with, but it should be 16
    // chars
    byte[] nonce = header.getSenderNonce().getOctets();
    assertEquals(nonce.length, 16);

    // --Recipient Nonce
    // recipient nonce should be the same as we sent away as sender nonce
    nonce = header.getRecipNonce().getOctets();
    assertEquals(new String(nonce), new String(senderNonce));

    // --Transaction ID
    // transid should be the same as the one we sent
    nonce = header.getTransactionID().getOctets();
    assertEquals(new String(nonce), new String(transId));

}