Skip to content

Commit

Permalink
Adjust and extend unit tests for MAC protected messages
Browse files Browse the repository at this point in the history
  • Loading branch information
kiron-mx committed Apr 30, 2024
1 parent 53fe11a commit c56a05c
Show file tree
Hide file tree
Showing 8 changed files with 325 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* Copyright (c) 2022 Siemens AG
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package com.siemens.pki.cmpracomponent.test;

import com.siemens.pki.cmpracomponent.configuration.Configuration;
import com.siemens.pki.cmpracomponent.msggeneration.PkiMessageGenerator;
import com.siemens.pki.cmpracomponent.protection.MacProtection;
import com.siemens.pki.cmpracomponent.protection.ProtectionProvider;
import com.siemens.pki.cmpracomponent.test.framework.ConfigurationFactory;
import com.siemens.pki.cmpracomponent.test.framework.EnrollmentResult;
import com.siemens.pki.cmpracomponent.test.framework.HeaderProviderForTest;
import com.siemens.pki.cmpracomponent.util.MessageDumper;
import org.bouncycastle.asn1.cmp.CMPCertificate;
import org.bouncycastle.asn1.cmp.CertRepMessage;
import org.bouncycastle.asn1.cmp.PKIBody;
import org.bouncycastle.asn1.cmp.PKIMessage;
import org.bouncycastle.asn1.crmf.CertTemplateBuilder;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.junit.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import java.security.KeyPair;
import java.util.function.Function;

import static org.junit.Assert.assertEquals;

public class MacProtectionTestcasebase extends OnlineEnrollmentTestcaseBase {

private static final Logger LOGGER = LoggerFactory.getLogger(MacProtectionTestcasebase.class);

@Before
public void setUp() throws Exception {
final Configuration config = ConfigurationFactory.buildMixedDownstreamConfiguration();
launchCmpCaAndRa(config);
}

public static EnrollmentResult executeCrmfCertificateRequest(
final int requestMessageType,
final int expectedResponseMessageType,
final ProtectionProvider protectionProvider,
final String expectedResponseProtection,
final Function<PKIMessage, PKIMessage> cmpClient)
throws Exception {
final KeyPair keyPair = ConfigurationFactory.getKeyGenerator().generateKeyPair();
final CertTemplateBuilder ctb = new CertTemplateBuilder()
.setPublicKey(
SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded()))
.setSubject(new X500Name("CN=Subject"));

final PKIBody crBody =
PkiMessageGenerator.generateIrCrKurBody(requestMessageType, ctb.build(), null, keyPair.getPrivate());

final PKIMessage cr = PkiMessageGenerator.generateAndProtectMessage(
new HeaderProviderForTest("theCertProfileForOnlineEnrollment"), protectionProvider, crBody);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("send:\n" + MessageDumper.dumpPkiMessage(cr));
}
final PKIMessage crResponse = cmpClient.apply(cr);

if (LOGGER.isDebugEnabled()) {
// avoid unnecessary string processing, if debug isn't enabled
LOGGER.debug("got:\n" + MessageDumper.dumpPkiMessage(crResponse));
}
assertEquals(
"message type",
expectedResponseMessageType,
crResponse.getBody().getType());

if (protectionProvider instanceof MacProtection) {
assertEquals(
"protection type",
expectedResponseProtection,
crResponse.getHeader().getProtectionAlg().getAlgorithm().getId());
}

if (expectedResponseMessageType == PKIBody.TYPE_ERROR) {
return new EnrollmentResult(null, null);
}
else {
final CMPCertificate enrolledCertificate = ((CertRepMessage)
crResponse.getBody().getContent())
.getResponse()[0]
.getCertifiedKeyPair()
.getCertOrEncCert()
.getCertificate();

final PKIMessage certConf = PkiMessageGenerator.generateAndProtectMessage(
new HeaderProviderForTest(crResponse.getHeader()),
protectionProvider,
PkiMessageGenerator.generateCertConfBody(enrolledCertificate));

if (LOGGER.isDebugEnabled()) {
LOGGER.debug("send:\n" + MessageDumper.dumpPkiMessage(certConf));
}
final PKIMessage pkiConf = cmpClient.apply(certConf);

if (LOGGER.isDebugEnabled()) {
LOGGER.debug("got:\n" + MessageDumper.dumpPkiMessage(pkiConf));
}
assertEquals("message type", PKIBody.TYPE_CONFIRM, pkiConf.getBody().getType());

return new EnrollmentResult(enrolledCertificate, keyPair.getPrivate());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import com.siemens.pki.cmpracomponent.cryptoservices.AlgorithmHelper;
import com.siemens.pki.cmpracomponent.msggeneration.PkiMessageGenerator;
import com.siemens.pki.cmpracomponent.protection.MacProtection;
import com.siemens.pki.cmpracomponent.protection.ProtectionProvider;
import com.siemens.pki.cmpracomponent.test.framework.ConfigurationFactory;
import com.siemens.pki.cmpracomponent.test.framework.EnrollmentResult;
Expand Down Expand Up @@ -78,6 +79,13 @@ public static EnrollmentResult executeCrmfCertificateRequest(
expectedResponseMessageType,
crResponse.getBody().getType());

if (protectionProvider instanceof MacProtection) {
assertEquals(
"protection type",
cr.getHeader().getProtectionAlg().getAlgorithm().getId(),
crResponse.getHeader().getProtectionAlg().getAlgorithm().getId());
}

final CMPCertificate enrolledCertificate = ((CertRepMessage)
crResponse.getBody().getContent())
.getResponse()[0]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2022 Siemens AG
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package com.siemens.pki.cmpracomponent.test;

import com.siemens.pki.cmpracomponent.configuration.Configuration;
import com.siemens.pki.cmpracomponent.test.framework.ConfigurationFactory;
import org.junit.Before;

public class Pbmac1EnrollmentTestcasebase extends OnlineEnrollmentTestcaseBase {

@Before
public void setUp() throws Exception {
final Configuration config = ConfigurationFactory.buildPbmac1DownstreamConfiguration();
launchCmpCaAndRa(config);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2020 Siemens AG
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package com.siemens.pki.cmpracomponent.test;

import com.siemens.pki.cmpracomponent.protection.ProtectionProvider;
import com.siemens.pki.cmpracomponent.test.framework.ConfigurationFactory;
import org.bouncycastle.asn1.cmp.PKIBody;
import org.junit.Ignore;
import org.junit.Test;

public class TestMacProtectedIp extends MacProtectionTestcasebase {

@Ignore
public void testFailedProtectionIp() throws Exception {
executeCrmfCertificateRequest(
PKIBody.TYPE_INIT_REQ,
PKIBody.TYPE_ERROR,
ConfigurationFactory.getEeWrongPasswordbasedProtectionProvider(),
"1.2.840.10045.4.3.2", // signature based protection
getEeClient());
}

@Test
public void testPasswordbasedIp() throws Exception {
executeCrmfCertificateRequest(
PKIBody.TYPE_INIT_REQ,
PKIBody.TYPE_INIT_REP,
ConfigurationFactory.getEePasswordbasedProtectionProvider(),
"1.2.840.113533.7.66.13",
getEeClient());
}

/**
* Enrolling an End Entity to a New PKI/Using MAC-Based Protection for
* Enrollment
*
* @throws Exception in case of error
*/
@Test
public void testPbmac1Ip() throws Exception {
executeCrmfCertificateRequest(
PKIBody.TYPE_INIT_REQ,
PKIBody.TYPE_INIT_REP,
ConfigurationFactory.getEePbmac1ProtectionProvider(),
"1.2.840.113549.1.5.14",
getEeClient());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,4 @@ public void testPasswordbasedIr() throws Exception {
ConfigurationFactory.getEePasswordbasedProtectionProvider(),
getEeClient());
}

/**
* Enrolling an End Entity to a New PKI/Using MAC-Based Protection for
* Enrollment
*
* @throws Exception in case of error
*/
@Test
public void testPbmac1Ir() throws Exception {
executeCrmfCertificateRequest(
PKIBody.TYPE_INIT_REQ,
PKIBody.TYPE_INIT_REP,
ConfigurationFactory.getEePbmac1ProtectionProvider(),
getEeClient());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2020 Siemens AG
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package com.siemens.pki.cmpracomponent.test;

import com.siemens.pki.cmpracomponent.test.framework.ConfigurationFactory;
import org.bouncycastle.asn1.cmp.PKIBody;
import org.junit.Test;

public class TestPbmac1Ir extends PasswordEnrollmentTestcasebase {

/**
* Enrolling an End Entity to a New PKI/Using MAC-Based Protection for
* Enrollment
*
* @throws Exception in case of error
*/
@Test
public void testPbmac1Ir() throws Exception {
executeCrmfCertificateRequest(
PKIBody.TYPE_INIT_REQ,
PKIBody.TYPE_INIT_REP,
ConfigurationFactory.getEePbmac1ProtectionProvider(),
getEeClient());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,26 @@ public class ConfigurationFactory {
private static SharedSecret eeSharedSecretCredentials;

public static Configuration buildPasswordbasedDownstreamConfiguration() throws Exception {
final CredentialContext downstreamCredentials = new SharedSecret("PASSWORDBASEDMAC", TestUtils.PASSWORD);
final VerificationContext downstreamTrust = new PasswordValidationCredentials(TestUtils.PASSWORD);

final CredentialContext upstreamCredentials =
new TrustChainAndPrivateKey("credentials/CMP_LRA_UPSTREAM_Keystore.p12", "Password".toCharArray());
final VerificationContext upstreamTrust =
new SignatureValidationCredentials("credentials/CMP_CA_Root.pem", null);
final SignatureValidationCredentials enrollmentTrust =
new SignatureValidationCredentials("credentials/ENROLL_Root.pem", null);

return buildSimpleRaConfiguration(
downstreamCredentials,
ReprotectMode.reprotect,
downstreamTrust,
upstreamCredentials,
upstreamTrust,
enrollmentTrust);
}

public static Configuration buildPbmac1DownstreamConfiguration() throws Exception {
final CredentialContext downstreamCredentials = new SharedSecret("PBMAC1", TestUtils.PASSWORD);
final VerificationContext downstreamTrust = new PasswordValidationCredentials(TestUtils.PASSWORD);

Expand All @@ -100,6 +120,27 @@ public static Configuration buildPasswordbasedDownstreamConfiguration() throws E
enrollmentTrust);
}

public static Configuration buildMixedDownstreamConfiguration() throws Exception {
final TrustChainAndPrivateKey downstreamCredentials =
new TrustChainAndPrivateKey("credentials/CMP_LRA_DOWNSTREAM_Keystore.p12", "Password".toCharArray());
final VerificationContext downstreamTrust = new PasswordValidationCredentials(TestUtils.PASSWORD);

final CredentialContext upstreamCredentials =
new TrustChainAndPrivateKey("credentials/CMP_LRA_UPSTREAM_Keystore.p12", "Password".toCharArray());
final VerificationContext upstreamTrust =
new SignatureValidationCredentials("credentials/CMP_CA_Root.pem", null);
final SignatureValidationCredentials enrollmentTrust =
new SignatureValidationCredentials("credentials/ENROLL_Root.pem", null);

return buildSimpleRaConfiguration(
downstreamCredentials,
ReprotectMode.reprotect,
downstreamTrust,
upstreamCredentials,
upstreamTrust,
enrollmentTrust);
}

public static Configuration buildSignatureBasedDownstreamConfiguration() throws Exception {
final TrustChainAndPrivateKey downstreamCredentials =
new TrustChainAndPrivateKey("credentials/CMP_LRA_DOWNSTREAM_Keystore.p12", "Password".toCharArray());
Expand Down Expand Up @@ -710,6 +751,15 @@ public static ProtectionProvider getEePasswordbasedProtectionProvider()
return eePasswordbasedProtectionProvider;
}

public static ProtectionProvider getEeWrongPasswordbasedProtectionProvider()
throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException {
if (eePasswordbasedProtectionProvider == null) {
eePasswordbasedProtectionProvider =
ProtectionProviderFactory.createProtectionProvider(getEeWrongSharedSecretCredentials());
}
return eePasswordbasedProtectionProvider;
}

public static ProtectionProvider getEePbmac1ProtectionProvider()
throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException {
if (eePbmac1ProtectionProvider == null) {
Expand All @@ -726,6 +776,13 @@ private static SharedSecret getEeSharedSecretCredentials() {
return eeSharedSecretCredentials;
}

private static SharedSecret getEeWrongSharedSecretCredentials() {
if (eeSharedSecretCredentials == null) {
eeSharedSecretCredentials = new SharedSecret("PASSWORDBASEDMAC", TestUtils.WRONG_PASSWORD);
}
return eeSharedSecretCredentials;
}

public static TrustChainAndPrivateKey getEeSignaturebasedCredentials() throws Exception {
if (eeSignaturebasedCredentials == null) {
eeSignaturebasedCredentials = new TrustChainAndPrivateKey(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ public class TestUtils {

public static final String PASSWORD = "Password";
public static final char[] PASSWORD_AS_CHAR_ARRAY = PASSWORD.toCharArray();

public static final String WRONG_PASSWORD = "WrongPassword";
public static final char[] WRONG_PASSWORD_AS_CHAR_ARRAY = WRONG_PASSWORD.toCharArray();
static final SecureRandom RANDOM = new SecureRandom();

// utility class, never create an instance
Expand Down

0 comments on commit c56a05c

Please sign in to comment.