diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7cbca55a..7820dfe5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -143,3 +143,8 @@ fix: handling of NestedEndpointContext.isIncomingRecipientValid
### 4.1.4 (Jul 23 2024)
fix: again fix protection of NESTED responses
+
+### 4.2.0 (Sep 10 2024)
+
+feat: Use same credentials for MAC based protection at Downstream
+
diff --git a/pom.xml b/pom.xml
index 1d9b2acf..2480f038 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,7 @@
com.siemens.pki
CmpRaComponent
jar
- 4.1.4
+ 4.2.0
UTF-8
.
diff --git a/src/main/java/com/siemens/pki/cmpclientcomponent/main/ClientRequestHandler.java b/src/main/java/com/siemens/pki/cmpclientcomponent/main/ClientRequestHandler.java
index f873ba5f..603f26c2 100644
--- a/src/main/java/com/siemens/pki/cmpclientcomponent/main/ClientRequestHandler.java
+++ b/src/main/java/com/siemens/pki/cmpclientcomponent/main/ClientRequestHandler.java
@@ -83,7 +83,7 @@ class ValidatorAndProtector {
public ValidatorAndProtector(NestedEndpointContext nestedEndpoint)
throws GeneralSecurityException, CmpProcessingException {
headerValidator = new MessageHeaderValidator(NESTED_INTERFACE_NAME);
- outputProtection = new MsgOutputProtector(nestedEndpoint, NESTED_INTERFACE_NAME);
+ outputProtection = new MsgOutputProtector(nestedEndpoint, NESTED_INTERFACE_NAME, null);
this.inputVerification = ConfigLogger.logOptional(
NESTED_INTERFACE_NAME,
"NestedEndpointContext.getInputVerification()",
diff --git a/src/main/java/com/siemens/pki/cmpracomponent/msggeneration/MsgOutputProtector.java b/src/main/java/com/siemens/pki/cmpracomponent/msggeneration/MsgOutputProtector.java
index 514ba40c..01fd36ba 100644
--- a/src/main/java/com/siemens/pki/cmpracomponent/msggeneration/MsgOutputProtector.java
+++ b/src/main/java/com/siemens/pki/cmpracomponent/msggeneration/MsgOutputProtector.java
@@ -24,7 +24,9 @@
import com.siemens.pki.cmpracomponent.configuration.CmpMessageInterface.ReprotectMode;
import com.siemens.pki.cmpracomponent.configuration.CredentialContext;
import com.siemens.pki.cmpracomponent.configuration.NestedEndpointContext;
+import com.siemens.pki.cmpracomponent.configuration.SharedSecretCredentialContext;
import com.siemens.pki.cmpracomponent.msgvalidation.CmpProcessingException;
+import com.siemens.pki.cmpracomponent.msgvalidation.MessageContext;
import com.siemens.pki.cmpracomponent.persistency.PersistencyContext;
import com.siemens.pki.cmpracomponent.protection.ProtectionProvider;
import com.siemens.pki.cmpracomponent.protection.ProtectionProviderFactory;
@@ -61,6 +63,8 @@ public class MsgOutputProtector {
private final ProtectionProvider protector;
private final PersistencyContext persistencyContext;
+ private final CredentialContext protectionCredentials;
+
private final boolean suppressRedundantExtraCerts;
private final GeneralName recipient;
@@ -69,15 +73,15 @@ public class MsgOutputProtector {
* ctor
* @param config specific configuration
* @param interfaceName name of interface used in logging messages
- * @param persistencyContext reference to transaction specific
- * {@link PersistencyContext}
+ * @param messageContext reference to transaction specific
+ * {@link MessageContext}
* @throws CmpProcessingException in case of inconsistent configuration
* @throws GeneralSecurityException in case of broken configuration
*/
public MsgOutputProtector(
- final CmpMessageInterface config, final String interfaceName, final PersistencyContext persistencyContext)
+ final CmpMessageInterface config, final String interfaceName, final MessageContext messageContext)
throws CmpProcessingException, GeneralSecurityException {
- this.persistencyContext = persistencyContext;
+ persistencyContext = ifNotNull(messageContext, MessageContext::getPersistencyContext);
suppressRedundantExtraCerts = ConfigLogger.log(
interfaceName,
"CmpMessageInterface.getSuppressRedundantExtraCerts()",
@@ -87,15 +91,21 @@ public MsgOutputProtector(
recipient = ifNotNull(
ConfigLogger.logOptional(interfaceName, "CmpMessageInterface.getRecipient()", config::getRecipient),
rec -> new GeneralName(new X500Name(rec)));
- final CredentialContext outputCredentials = ConfigLogger.logOptional(
- interfaceName, "CmpMessageInterface.getOutputCredentials()", config::getOutputCredentials);
- if (reprotectMode == ReprotectMode.reprotect && outputCredentials == null) {
- throw new CmpProcessingException(
- interfaceName,
- PKIFailureInfo.wrongAuthority,
- "reprotectMode is reprotect, but no output credentials are given");
+ final CredentialContext verificationCredentials =
+ ifNotNull(messageContext, MessageContext::getCredentialContext);
+ if (verificationCredentials instanceof SharedSecretCredentialContext) {
+ protectionCredentials = verificationCredentials;
+ } else {
+ protectionCredentials = ConfigLogger.logOptional(
+ interfaceName, "CmpMessageInterface.getOutputCredentials()", config::getOutputCredentials);
+ if (reprotectMode == ReprotectMode.reprotect && protectionCredentials == null) {
+ throw new CmpProcessingException(
+ interfaceName,
+ PKIFailureInfo.wrongAuthority,
+ "reprotectMode is reprotect, but no output credentials are given");
+ }
}
- protector = ProtectionProviderFactory.createProtectionProvider(outputCredentials, interfaceName);
+ protector = ProtectionProviderFactory.createProtectionProvider(protectionCredentials, interfaceName);
}
/**
@@ -105,7 +115,8 @@ public MsgOutputProtector(
* @throws CmpProcessingException in case of inconsistent configuration
* @throws GeneralSecurityException in case of broken configuration
*/
- public MsgOutputProtector(final NestedEndpointContext config, final String interfaceName)
+ public MsgOutputProtector(
+ final NestedEndpointContext config, final String interfaceName, final CredentialContext credentialContext)
throws CmpProcessingException, GeneralSecurityException {
this.persistencyContext = null;
suppressRedundantExtraCerts = false;
@@ -113,10 +124,13 @@ public MsgOutputProtector(final NestedEndpointContext config, final String inter
recipient = ifNotNull(
ConfigLogger.logOptional(interfaceName, "NestedEndpointContext.getRecipient()", config::getRecipient),
rec -> new GeneralName(new X500Name(rec)));
- protector = ProtectionProviderFactory.createProtectionProvider(
- ConfigLogger.logOptional(
- interfaceName, "NestedEndpointContext.getOutputCredentials()", config::getOutputCredentials),
- interfaceName);
+ if (credentialContext instanceof SharedSecretCredentialContext) {
+ protectionCredentials = credentialContext;
+ } else {
+ protectionCredentials = ConfigLogger.logOptional(
+ interfaceName, "NestedEndpointContext.getOutputCredentials()", config::getOutputCredentials);
+ }
+ protector = ProtectionProviderFactory.createProtectionProvider(protectionCredentials, interfaceName);
}
/**
diff --git a/src/main/java/com/siemens/pki/cmpracomponent/msgprocessing/CmpRaUpstream.java b/src/main/java/com/siemens/pki/cmpracomponent/msgprocessing/CmpRaUpstream.java
index a1bb81d0..1977f9f0 100644
--- a/src/main/java/com/siemens/pki/cmpracomponent/msgprocessing/CmpRaUpstream.java
+++ b/src/main/java/com/siemens/pki/cmpracomponent/msgprocessing/CmpRaUpstream.java
@@ -26,6 +26,7 @@
import com.siemens.pki.cmpracomponent.msgvalidation.CmpProcessingException;
import com.siemens.pki.cmpracomponent.msgvalidation.CmpValidationException;
import com.siemens.pki.cmpracomponent.msgvalidation.InputValidator;
+import com.siemens.pki.cmpracomponent.msgvalidation.MessageContext;
import com.siemens.pki.cmpracomponent.msgvalidation.MessageHeaderValidator;
import com.siemens.pki.cmpracomponent.msgvalidation.ProtectionValidator;
import com.siemens.pki.cmpracomponent.persistency.PersistencyContext;
@@ -131,8 +132,8 @@ public PKIMessage handleRequest(final PKIMessage in, final PersistencyContext pe
// never re-protect a KUR
sentMessage = in;
} else {
- final MsgOutputProtector outputProtector =
- new MsgOutputProtector(upstreamConfiguration, INTERFACE_NAME, persistencyContext);
+ final MsgOutputProtector outputProtector = new MsgOutputProtector(
+ upstreamConfiguration, INTERFACE_NAME, new MessageContext(persistencyContext, null));
sentMessage = outputProtector.protectOutgoingMessage(in, null);
}
final NestedEndpointContext nestedEndpointContext = ConfigLogger.logOptional(
@@ -141,7 +142,7 @@ public PKIMessage handleRequest(final PKIMessage in, final PersistencyContext pe
upstreamConfiguration::getNestedEndpointContext);
if (nestedEndpointContext != null) {
final MsgOutputProtector nestedProtector =
- new MsgOutputProtector(nestedEndpointContext, "NESTED CMP upstream");
+ new MsgOutputProtector(nestedEndpointContext, "NESTED CMP upstream", null);
// wrap into nested message
sentMessage = nestedProtector.protectOutgoingMessage(
new PKIMessage(
diff --git a/src/main/java/com/siemens/pki/cmpracomponent/msgprocessing/RaDownstream.java b/src/main/java/com/siemens/pki/cmpracomponent/msgprocessing/RaDownstream.java
index 765dfe21..e33cf454 100644
--- a/src/main/java/com/siemens/pki/cmpracomponent/msgprocessing/RaDownstream.java
+++ b/src/main/java/com/siemens/pki/cmpracomponent/msgprocessing/RaDownstream.java
@@ -23,6 +23,7 @@
import com.siemens.pki.cmpracomponent.configuration.CkgContext;
import com.siemens.pki.cmpracomponent.configuration.CmpMessageInterface;
import com.siemens.pki.cmpracomponent.configuration.Configuration;
+import com.siemens.pki.cmpracomponent.configuration.CredentialContext;
import com.siemens.pki.cmpracomponent.configuration.InventoryInterface;
import com.siemens.pki.cmpracomponent.configuration.NestedEndpointContext;
import com.siemens.pki.cmpracomponent.configuration.SignatureCredentialContext;
@@ -41,6 +42,7 @@
import com.siemens.pki.cmpracomponent.msgvalidation.CmpProcessingException;
import com.siemens.pki.cmpracomponent.msgvalidation.CmpValidationException;
import com.siemens.pki.cmpracomponent.msgvalidation.InputValidator;
+import com.siemens.pki.cmpracomponent.msgvalidation.MessageContext;
import com.siemens.pki.cmpracomponent.msgvalidation.MessageHeaderValidator;
import com.siemens.pki.cmpracomponent.msgvalidation.ProtectionValidator;
import com.siemens.pki.cmpracomponent.persistency.PersistencyContext;
@@ -377,6 +379,7 @@ private PKIMessage handleCrmfCertificateRequest(
*/
PKIMessage handleInputMessage(final PKIMessage in) {
PersistencyContext persistencyContext = null;
+ MessageContext messageContext = null;
int responseBodyType = PKIBody.TYPE_ERROR;
int retryAfterTime = 0;
try {
@@ -412,9 +415,9 @@ PKIMessage handleInputMessage(final PKIMessage in) {
config::isRaVerifiedAcceptable,
supportedMessageTypes,
persistencyContext);
- inputValidator.validate(in);
+ messageContext = inputValidator.validate(in);
- PKIMessage responseFromUpstream = handleValidatedRequest(in, persistencyContext);
+ PKIMessage responseFromUpstream = handleValidatedRequest(in, messageContext);
// apply downstream protection and nesting
List issuingChain = null;
responseBodyType = responseFromUpstream.getBody().getType();
@@ -443,7 +446,7 @@ PKIMessage handleInputMessage(final PKIMessage in) {
ifNotNull(persistencyContext, PersistencyContext::getCertProfile),
responseBodyType);
PKIMessage protectedResponse = new MsgOutputProtector(
- downstreamConfiguration, INTERFACE_NAME, persistencyContext)
+ downstreamConfiguration, INTERFACE_NAME, messageContext)
.protectOutgoingMessage(
new PKIMessage(
responseFromUpstream.getHeader(),
@@ -460,7 +463,8 @@ PKIMessage handleInputMessage(final PKIMessage in) {
// no nesting required
return protectedResponse;
}
- return new MsgOutputProtector(nestedEndpointContext, NESTED_INTERFACE_NAME)
+ return new MsgOutputProtector(
+ nestedEndpointContext, NESTED_INTERFACE_NAME, messageContext.getCredentialContext())
.createOutgoingMessage(
PkiMessageGenerator.buildForwardingHeaderProvider(protectedResponse),
new PKIBody(PKIBody.TYPE_NESTED, new PKIMessages(protectedResponse)));
@@ -472,7 +476,7 @@ PKIMessage handleInputMessage(final PKIMessage in) {
config::getDownstreamConfiguration,
ifNotNull(persistencyContext, PersistencyContext::getCertProfile),
errorBody.getType());
- return new MsgOutputProtector(downstreamConfiguration, INTERFACE_NAME, persistencyContext)
+ return new MsgOutputProtector(downstreamConfiguration, INTERFACE_NAME, messageContext)
.generateAndProtectResponseTo(in, errorBody);
} catch (final RuntimeException ex) {
final PKIBody errorBody = new CmpProcessingException(INTERFACE_NAME, ex).asErrorBody();
@@ -482,7 +486,7 @@ PKIMessage handleInputMessage(final PKIMessage in) {
config::getDownstreamConfiguration,
ifNotNull(persistencyContext, PersistencyContext::getCertProfile),
errorBody.getType());
- return new MsgOutputProtector(downstreamConfiguration, INTERFACE_NAME, persistencyContext)
+ return new MsgOutputProtector(downstreamConfiguration, INTERFACE_NAME, messageContext)
.generateAndProtectResponseTo(in, errorBody);
} finally {
if (persistencyContext != null) {
@@ -529,7 +533,7 @@ private PKIMessage handleNestedRequest(final PKIMessage in, final PersistencyCon
NESTED_INTERFACE_NAME,
"NestedEndpointContext.getInputVerification()",
nestedEndpointContext::getInputVerification));
- nestedProtectionValidator.validate(in);
+ CredentialContext credentialContext = nestedProtectionValidator.validate(in);
PKIHeader inHeader = in.getHeader();
boolean isIncomingRecipientValid = ConfigLogger.log(
NESTED_INTERFACE_NAME,
@@ -555,7 +559,8 @@ private PKIMessage handleNestedRequest(final PKIMessage in, final PersistencyCon
final PKIMessage[] responses =
Arrays.stream(embeddedMessages).map(this::handleInputMessage).toArray(PKIMessage[]::new);
// batched responses needs to be wrapped in a new NESTED response
- MsgOutputProtector nestedOutputProtector = new MsgOutputProtector(nestedEndpointContext, INTERFACE_NAME);
+ MsgOutputProtector nestedOutputProtector =
+ new MsgOutputProtector(nestedEndpointContext, INTERFACE_NAME, credentialContext);
return nestedOutputProtector.generateAndProtectResponseTo(
in, new PKIBody(PKIBody.TYPE_NESTED, new PKIMessages(responses)));
}
@@ -651,12 +656,12 @@ private PKIMessage handleRevocationRequest(PKIMessage incomingRequest, Persisten
return incomingRequest;
}
- private PKIMessage handleValidatedRequest(
- final PKIMessage incomingRequest, final PersistencyContext persistencyContext)
+ private PKIMessage handleValidatedRequest(final PKIMessage incomingRequest, final MessageContext messageContext)
throws BaseCmpException, IOException {
// request pre processing
// by default there is no pre processing
PKIMessage preprocessedRequest = incomingRequest;
+ final PersistencyContext persistencyContext = messageContext.getPersistencyContext();
switch (incomingRequest.getBody().getType()) {
case PKIBody.TYPE_INIT_REQ:
case PKIBody.TYPE_CERT_REQ:
@@ -682,8 +687,8 @@ private PKIMessage handleValidatedRequest(
case PKIBody.TYPE_GEN_MSG:
// try to handle locally
persistencyContext.setRequestType(incomingRequest.getBody().getType());
- final PKIMessage genmResponse = new ServiceImplementation(config)
- .handleValidatedInputMessage(incomingRequest, persistencyContext);
+ final PKIMessage genmResponse =
+ new ServiceImplementation(config).handleValidatedInputMessage(incomingRequest, messageContext);
if (genmResponse != null) {
return genmResponse;
}
diff --git a/src/main/java/com/siemens/pki/cmpracomponent/msgprocessing/ServiceImplementation.java b/src/main/java/com/siemens/pki/cmpracomponent/msgprocessing/ServiceImplementation.java
index d3eae4e8..bb2b7328 100644
--- a/src/main/java/com/siemens/pki/cmpracomponent/msgprocessing/ServiceImplementation.java
+++ b/src/main/java/com/siemens/pki/cmpracomponent/msgprocessing/ServiceImplementation.java
@@ -30,6 +30,7 @@
import com.siemens.pki.cmpracomponent.msggeneration.MsgOutputProtector;
import com.siemens.pki.cmpracomponent.msgvalidation.BaseCmpException;
import com.siemens.pki.cmpracomponent.msgvalidation.CmpProcessingException;
+import com.siemens.pki.cmpracomponent.msgvalidation.MessageContext;
import com.siemens.pki.cmpracomponent.persistency.PersistencyContext;
import com.siemens.pki.cmpracomponent.util.ConfigLogger;
import java.io.IOException;
@@ -229,7 +230,7 @@ private PKIBody handleGetRootCaCertificateUpdate(
new GenRepContent(new InfoTypeAndValue(CMPObjectIdentifiers.id_it_rootCaKeyUpdate)));
}
- protected PKIMessage handleValidatedInputMessage(final PKIMessage msg, final PersistencyContext persistencyContext)
+ protected PKIMessage handleValidatedInputMessage(final PKIMessage msg, final MessageContext messageContext)
throws BaseCmpException {
try {
final InfoTypeAndValue itav = ((GenMsgContent) msg.getBody().getContent()).toInfoTypeAndValueArray()[0];
@@ -238,7 +239,8 @@ protected PKIMessage handleValidatedInputMessage(final PKIMessage msg, final Per
final SupportMessageHandlerInterface messageHandler = ConfigLogger.logOptional(
INTERFACE_NAME,
"com.siemens.pki.cmpracomponent.configuration.Configuration.getSupportMessageHandler(String, String)",
- () -> config.getSupportMessageHandler(persistencyContext.getCertProfile(), infoType.getId()));
+ () -> config.getSupportMessageHandler(
+ messageContext.getPersistencyContext().getCertProfile(), infoType.getId()));
if (messageHandler == null) {
return null;
}
@@ -264,10 +266,10 @@ protected PKIMessage handleValidatedInputMessage(final PKIMessage msg, final Per
INTERFACE_NAME,
"Configuration.getDownstreamConfiguration",
config::getDownstreamConfiguration,
- ifNotNull(persistencyContext, PersistencyContext::getCertProfile),
+ ifNotNull(messageContext.getPersistencyContext(), PersistencyContext::getCertProfile),
body.getType()),
INTERFACE_NAME,
- persistencyContext);
+ messageContext);
return protector.generateAndProtectResponseTo(msg, body);
} catch (final BaseCmpException ex) {
throw ex;
diff --git a/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/InputValidator.java b/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/InputValidator.java
index 4fe32afb..305d6d4f 100644
--- a/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/InputValidator.java
+++ b/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/InputValidator.java
@@ -18,6 +18,7 @@
package com.siemens.pki.cmpracomponent.msgvalidation;
import com.siemens.pki.cmpracomponent.configuration.CmpMessageInterface;
+import com.siemens.pki.cmpracomponent.configuration.CredentialContext;
import com.siemens.pki.cmpracomponent.persistency.PersistencyContext;
import com.siemens.pki.cmpracomponent.util.ConfigLogger;
import com.siemens.pki.cmpracomponent.util.MessageDumper;
@@ -30,7 +31,7 @@
/**
* validator for an incoming message
*/
-public class InputValidator implements ValidatorIF {
+public class InputValidator implements ValidatorIF {
private final Collection supportedMessageTypes;
private final String interfaceName;
@@ -68,11 +69,11 @@ public InputValidator(
* message types
*
* @param in message to validate
- * @return nothing
+ * @return a message context
* @throws CmpProcessingException if validation failed
*/
@Override
- public Void validate(final PKIMessage in) throws BaseCmpException {
+ public MessageContext validate(final PKIMessage in) throws BaseCmpException {
if (!supportedMessageTypes.contains(in.getBody().getType())) {
throw new CmpValidationException(
interfaceName,
@@ -97,8 +98,8 @@ public Void validate(final PKIMessage in) throws BaseCmpException {
interfaceName,
"CmpMessageInterface.getInputVerification()",
cmpInterface::getInputVerification));
- protectionValidator.validate(in);
- return null;
+ CredentialContext protectionCredentials = protectionValidator.validate(in);
+ return new MessageContext(persistencyContext, protectionCredentials);
} catch (final BaseCmpException ce) {
throw ce;
} catch (final Exception e) {
diff --git a/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/MacValidator.java b/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/MacValidator.java
index d321aba8..e5b1bf23 100644
--- a/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/MacValidator.java
+++ b/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/MacValidator.java
@@ -17,6 +17,7 @@
*/
package com.siemens.pki.cmpracomponent.msgvalidation;
+import com.siemens.pki.cmpracomponent.configuration.CredentialContext;
import com.siemens.pki.cmpracomponent.configuration.VerificationContext;
import com.siemens.pki.cmpracomponent.util.ConfigLogger;
import com.siemens.pki.cmpracomponent.util.NullUtil;
@@ -27,7 +28,7 @@
/**
* base class for all MAC based validators
*/
-public abstract class MacValidator implements ValidatorIF {
+public abstract class MacValidator implements ValidatorIF {
protected final VerificationContext config;
private final String interfaceName;
diff --git a/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/MessageContext.java b/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/MessageContext.java
new file mode 100644
index 00000000..c0680aba
--- /dev/null
+++ b/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/MessageContext.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2024 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.msgvalidation;
+
+import com.siemens.pki.cmpracomponent.configuration.CredentialContext;
+import com.siemens.pki.cmpracomponent.persistency.PersistencyContext;
+
+/**
+ * Container class to store @link{PersistencyContext} and @link{CredentialContext} of a PKI message
+ */
+public class MessageContext {
+
+ final PersistencyContext persistencyContext;
+ final CredentialContext credentialContext;
+
+ /**
+ * Class constructor
+ * @param persistency a persistency context
+ * @param credentials a credential context
+ */
+ public MessageContext(PersistencyContext persistency, CredentialContext credentials) {
+ persistencyContext = persistency;
+ credentialContext = credentials;
+ }
+
+ /**
+ * provide a persistency context
+ * @return a persistency context
+ */
+ public PersistencyContext getPersistencyContext() {
+ return persistencyContext;
+ }
+
+ /**
+ * provide a credential context configuration usable for message protection
+ * @return a credential context
+ */
+ public CredentialContext getCredentialContext() {
+ return credentialContext;
+ }
+}
diff --git a/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/PBMAC1ProtectionValidator.java b/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/PBMAC1ProtectionValidator.java
index 0b451401..0a83ec51 100644
--- a/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/PBMAC1ProtectionValidator.java
+++ b/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/PBMAC1ProtectionValidator.java
@@ -17,10 +17,12 @@
*/
package com.siemens.pki.cmpracomponent.msgvalidation;
+import com.siemens.pki.cmpracomponent.configuration.CredentialContext;
import com.siemens.pki.cmpracomponent.configuration.VerificationContext;
import com.siemens.pki.cmpracomponent.cryptoservices.AlgorithmHelper;
import com.siemens.pki.cmpracomponent.cryptoservices.WrappedMac;
import com.siemens.pki.cmpracomponent.cryptoservices.WrappedMacFactory;
+import com.siemens.pki.cmpracomponent.protection.OutputSharedSecretCredentials;
import java.util.Arrays;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
@@ -50,7 +52,7 @@ public PBMAC1ProtectionValidator(final String interfaceName, final VerificationC
}
@Override
- public Void validate(final PKIMessage message) throws BaseCmpException {
+ public CredentialContext validate(final PKIMessage message) throws BaseCmpException {
try {
final PKIHeader header = message.getHeader();
final byte[] passwordAsBytes = getSharedSecret(header);
@@ -81,12 +83,16 @@ public Void validate(final PKIMessage message) throws BaseCmpException {
throw new CmpValidationException(
getInterfaceName(), PKIFailureInfo.badMessageCheck, "PBMAC1 protection check failed");
}
+ return new OutputSharedSecretCredentials(
+ params,
+ pbmac1Params.getMessageAuthScheme().getAlgorithm().getId(),
+ header.getSenderKID().getOctets(),
+ passwordAsBytes);
} catch (final BaseCmpException cex) {
throw cex;
} catch (final Exception ex) {
throw new CmpProcessingException(
getInterfaceName(), PKIFailureInfo.badMessageCheck, ex.getLocalizedMessage());
}
- return null;
}
}
diff --git a/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/PasswordBasedMacValidator.java b/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/PasswordBasedMacValidator.java
index 5e4f6260..e5ebd892 100644
--- a/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/PasswordBasedMacValidator.java
+++ b/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/PasswordBasedMacValidator.java
@@ -17,8 +17,10 @@
*/
package com.siemens.pki.cmpracomponent.msgvalidation;
+import com.siemens.pki.cmpracomponent.configuration.CredentialContext;
import com.siemens.pki.cmpracomponent.configuration.VerificationContext;
import com.siemens.pki.cmpracomponent.cryptoservices.AlgorithmHelper;
+import com.siemens.pki.cmpracomponent.protection.OutputSharedSecretCredentials;
import java.security.MessageDigest;
import java.util.Arrays;
import javax.crypto.Mac;
@@ -48,7 +50,7 @@ public PasswordBasedMacValidator(final String interfaceName, final VerificationC
}
@Override
- public Void validate(final PKIMessage message) throws BaseCmpException {
+ public CredentialContext validate(final PKIMessage message) throws BaseCmpException {
try {
final PKIHeader header = message.getHeader();
// Construct the base key according to rfc4210, section 5.1.3.1
@@ -79,12 +81,13 @@ public Void validate(final PKIMessage message) throws BaseCmpException {
throw new CmpValidationException(
getInterfaceName(), PKIFailureInfo.badMessageCheck, "PasswordBasedMac protection check failed");
}
+ return new OutputSharedSecretCredentials(
+ pbmParameter, header.getSenderKID().getOctets(), passwordAsBytes);
} catch (final BaseCmpException cex) {
throw cex;
} catch (final Exception ex) {
throw new CmpProcessingException(
getInterfaceName(), PKIFailureInfo.badMessageCheck, ex.getLocalizedMessage());
}
- return null;
}
}
diff --git a/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/ProtectionValidator.java b/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/ProtectionValidator.java
index 4c92e8b7..351dc728 100644
--- a/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/ProtectionValidator.java
+++ b/src/main/java/com/siemens/pki/cmpracomponent/msgvalidation/ProtectionValidator.java
@@ -17,6 +17,7 @@
*/
package com.siemens.pki.cmpracomponent.msgvalidation;
+import com.siemens.pki.cmpracomponent.configuration.CredentialContext;
import com.siemens.pki.cmpracomponent.configuration.VerificationContext;
import com.siemens.pki.cmpracomponent.util.MessageDumper;
import org.bouncycastle.asn1.ASN1BitString;
@@ -33,7 +34,7 @@
* This class validates the signature or password based protection of all
* incoming messages and generates proper error responses on failed validation.
*/
-public class ProtectionValidator implements ValidatorIF {
+public class ProtectionValidator implements ValidatorIF {
private static final Logger LOGGER = LoggerFactory.getLogger(ProtectionValidator.class);
@@ -59,11 +60,12 @@ public ProtectionValidator(final String interfaceName, final VerificationContext
* validation
*/
@Override
- public Void validate(final PKIMessage message) throws BaseCmpException {
+ public CredentialContext validate(final PKIMessage message) throws BaseCmpException {
if (config == null) {
// protection validation is not needed
return null;
}
+ final CredentialContext credentialContext;
final ASN1BitString protection = message.getProtection();
final AlgorithmIdentifier protectionAlg = message.getHeader().getProtectionAlg();
if (protection == null || protectionAlg == null) {
@@ -83,12 +85,13 @@ public Void validate(final PKIMessage message) throws BaseCmpException {
}
}
if (CMPObjectIdentifiers.passwordBasedMac.equals(protectionAlg.getAlgorithm())) {
- new PasswordBasedMacValidator(interfaceName, config).validate(message);
+ credentialContext = new PasswordBasedMacValidator(interfaceName, config).validate(message);
} else if (PKCSObjectIdentifiers.id_PBMAC1.equals(protectionAlg.getAlgorithm())) {
- new PBMAC1ProtectionValidator(interfaceName, config).validate(message);
+ credentialContext = new PBMAC1ProtectionValidator(interfaceName, config).validate(message);
} else {
new SignatureProtectionValidator(interfaceName, config).validate(message);
+ credentialContext = null;
}
- return null;
+ return credentialContext;
}
}
diff --git a/src/main/java/com/siemens/pki/cmpracomponent/protection/OutputSharedSecretCredentials.java b/src/main/java/com/siemens/pki/cmpracomponent/protection/OutputSharedSecretCredentials.java
new file mode 100644
index 00000000..5f9ef89f
--- /dev/null
+++ b/src/main/java/com/siemens/pki/cmpracomponent/protection/OutputSharedSecretCredentials.java
@@ -0,0 +1,101 @@
+package com.siemens.pki.cmpracomponent.protection;
+
+import com.siemens.pki.cmpracomponent.configuration.SharedSecretCredentialContext;
+import org.bouncycastle.asn1.cmp.CMPObjectIdentifiers;
+import org.bouncycastle.asn1.cmp.PBMParameter;
+import org.bouncycastle.asn1.pkcs.PBKDF2Params;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+
+/**
+ * an instance implementing {@link com.siemens.pki.cmpracomponent.configuration.SharedSecretCredentialContext}
+ * provides all attributes needed for shared secret based CMP protection of outgoing messages
+ */
+public class OutputSharedSecretCredentials implements SharedSecretCredentialContext {
+
+ final int iterationCount;
+ final int keyLength;
+ final String macAlgorithm;
+ final String passwordBasedMacAlgorithm;
+ final String prf;
+ final byte[] salt;
+ final byte[] senderKID;
+ final byte[] sharedSecret;
+
+ /**
+ * Constructor for password-based MAC protection
+ * @param pbmParameter PBM parameter
+ * @param senderKID sender key identifier
+ * @param sharedSecret shared secret
+ */
+ public OutputSharedSecretCredentials(
+ final PBMParameter pbmParameter, final byte[] senderKID, final byte[] sharedSecret) {
+ this.iterationCount = pbmParameter.getIterationCount().getValue().intValue();
+ this.macAlgorithm = pbmParameter.getMac().getAlgorithm().getId();
+ this.passwordBasedMacAlgorithm = CMPObjectIdentifiers.passwordBasedMac.getId();
+ this.prf = pbmParameter.getOwf().getAlgorithm().getId();
+ this.salt = pbmParameter.getSalt().getOctets();
+ this.senderKID = senderKID;
+ this.sharedSecret = sharedSecret;
+
+ this.keyLength = 0;
+ }
+
+ /**
+ * Constructor for PMAC1 protection
+ * @param pbkdf2Params parameters for PBKDF2 key derivation function
+ * @param macAlgorithm MAC algorithm
+ * @param senderKID sender key identifer
+ * @param sharedSecret shared secret
+ */
+ public OutputSharedSecretCredentials(
+ PBKDF2Params pbkdf2Params, String macAlgorithm, byte[] senderKID, byte[] sharedSecret) {
+ this.iterationCount = pbkdf2Params.getIterationCount().intValue();
+ this.macAlgorithm = macAlgorithm;
+ this.keyLength = pbkdf2Params.getKeyLength().intValue();
+ this.passwordBasedMacAlgorithm = PKCSObjectIdentifiers.id_PBMAC1.getId();
+ this.prf = pbkdf2Params.getPrf().getAlgorithm().getId();
+ this.salt = pbkdf2Params.getSalt();
+ this.senderKID = senderKID;
+ this.sharedSecret = sharedSecret;
+ }
+
+ @Override
+ public int getIterationCount() {
+ return iterationCount;
+ }
+
+ @Override
+ public int getkeyLength() {
+ return keyLength;
+ }
+
+ @Override
+ public String getMacAlgorithm() {
+ return macAlgorithm;
+ }
+
+ @Override
+ public String getPasswordBasedMacAlgorithm() {
+ return passwordBasedMacAlgorithm;
+ }
+
+ @Override
+ public String getPrf() {
+ return prf;
+ }
+
+ @Override
+ public byte[] getSalt() {
+ return salt;
+ }
+
+ @Override
+ public byte[] getSenderKID() {
+ return senderKID;
+ }
+
+ @Override
+ public byte[] getSharedSecret() {
+ return sharedSecret;
+ }
+}
diff --git a/src/test/java/com/siemens/pki/cmpracomponent/test/MacProtectionTestcaseBase.java b/src/test/java/com/siemens/pki/cmpracomponent/test/MacProtectionTestcaseBase.java
new file mode 100644
index 00000000..83b6bdee
--- /dev/null
+++ b/src/test/java/com/siemens/pki/cmpracomponent/test/MacProtectionTestcaseBase.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2024 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 static org.junit.Assert.assertEquals;
+
+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 java.security.KeyPair;
+import java.util.function.Function;
+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;
+
+public class MacProtectionTestcaseBase extends OnlineEnrollmentTestcaseBase {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(MacProtectionTestcaseBase.class);
+
+ @Before
+ public void setUp() throws Exception {
+ ConfigurationFactory.resetConfiguration();
+ Configuration config = ConfigurationFactory.buildMixedDownstreamConfiguration();
+ launchCmpCaAndRa(config);
+ }
+
+ public static EnrollmentResult executeCrmfCertificateRequest(
+ final int requestMessageType,
+ final int expectedResponseMessageType,
+ final ProtectionProvider protectionProvider,
+ final String expectedResponseProtection,
+ final Function 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());
+ }
+ }
+}
diff --git a/src/test/java/com/siemens/pki/cmpracomponent/test/OnlineEnrollmentTestcaseBase.java b/src/test/java/com/siemens/pki/cmpracomponent/test/OnlineEnrollmentTestcaseBase.java
index 74c02552..98fdd967 100644
--- a/src/test/java/com/siemens/pki/cmpracomponent/test/OnlineEnrollmentTestcaseBase.java
+++ b/src/test/java/com/siemens/pki/cmpracomponent/test/OnlineEnrollmentTestcaseBase.java
@@ -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;
@@ -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]
diff --git a/src/test/java/com/siemens/pki/cmpracomponent/test/PasswordEnrollmentTestcasebase.java b/src/test/java/com/siemens/pki/cmpracomponent/test/PasswordEnrollmentTestcasebase.java
index eead61a5..e1254106 100644
--- a/src/test/java/com/siemens/pki/cmpracomponent/test/PasswordEnrollmentTestcasebase.java
+++ b/src/test/java/com/siemens/pki/cmpracomponent/test/PasswordEnrollmentTestcasebase.java
@@ -25,6 +25,7 @@ public class PasswordEnrollmentTestcasebase extends OnlineEnrollmentTestcaseBase
@Before
public void setUp() throws Exception {
+ ConfigurationFactory.resetConfiguration();
final Configuration config = ConfigurationFactory.buildPasswordbasedDownstreamConfiguration();
launchCmpCaAndRa(config);
}
diff --git a/src/test/java/com/siemens/pki/cmpracomponent/test/Pbmac1EnrollmentTestcasebase.java b/src/test/java/com/siemens/pki/cmpracomponent/test/Pbmac1EnrollmentTestcasebase.java
new file mode 100644
index 00000000..f07a3647
--- /dev/null
+++ b/src/test/java/com/siemens/pki/cmpracomponent/test/Pbmac1EnrollmentTestcasebase.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2024 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);
+ }
+}
diff --git a/src/test/java/com/siemens/pki/cmpracomponent/test/TestMacProtectedIp.java b/src/test/java/com/siemens/pki/cmpracomponent/test/TestMacProtectedIp.java
new file mode 100644
index 00000000..96b4048f
--- /dev/null
+++ b/src/test/java/com/siemens/pki/cmpracomponent/test/TestMacProtectedIp.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 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 TestMacProtectedIp extends MacProtectionTestcaseBase {
+
+ @Test
+ 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());
+ }
+}
diff --git a/src/test/java/com/siemens/pki/cmpracomponent/test/TestPasswordbasedIr.java b/src/test/java/com/siemens/pki/cmpracomponent/test/TestPasswordbasedIr.java
index b05e81d5..4b7f59a9 100644
--- a/src/test/java/com/siemens/pki/cmpracomponent/test/TestPasswordbasedIr.java
+++ b/src/test/java/com/siemens/pki/cmpracomponent/test/TestPasswordbasedIr.java
@@ -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());
- }
}
diff --git a/src/test/java/com/siemens/pki/cmpracomponent/test/TestPbmac1Ir.java b/src/test/java/com/siemens/pki/cmpracomponent/test/TestPbmac1Ir.java
new file mode 100644
index 00000000..7ad248f0
--- /dev/null
+++ b/src/test/java/com/siemens/pki/cmpracomponent/test/TestPbmac1Ir.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2024 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());
+ }
+}
diff --git a/src/test/java/com/siemens/pki/cmpracomponent/test/framework/ConfigurationFactory.java b/src/test/java/com/siemens/pki/cmpracomponent/test/framework/ConfigurationFactory.java
index 2b476cc9..469680e6 100644
--- a/src/test/java/com/siemens/pki/cmpracomponent/test/framework/ConfigurationFactory.java
+++ b/src/test/java/com/siemens/pki/cmpracomponent/test/framework/ConfigurationFactory.java
@@ -82,6 +82,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);
@@ -101,6 +121,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());
@@ -746,6 +787,15 @@ public static ProtectionProvider getEePasswordbasedProtectionProvider()
return eePasswordbasedProtectionProvider;
}
+ public static ProtectionProvider getEeWrongPasswordbasedProtectionProvider()
+ throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException {
+ if (eePasswordbasedProtectionProvider == null) {
+ eePasswordbasedProtectionProvider = ProtectionProviderFactory.createProtectionProvider(
+ getEeWrongSharedSecretCredentials(), INTERFACE_NAME);
+ }
+ return eePasswordbasedProtectionProvider;
+ }
+
public static ProtectionProvider getEePbmac1ProtectionProvider()
throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException {
if (eePbmac1ProtectionProvider == null) {
@@ -762,6 +812,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(
@@ -796,5 +853,14 @@ public static KeyPairGenerator getKeyGenerator() {
return keyGenerator;
}
+ public static void resetConfiguration() {
+ eeSignaturebasedProtectionProvider = null;
+ eePbmac1ProtectionProvider = null;
+ keyGenerator = null;
+ eePasswordbasedProtectionProvider = null;
+ eeSignaturebasedCredentials = null;
+ eeSharedSecretCredentials = null;
+ }
+
private ConfigurationFactory() {}
}
diff --git a/src/test/java/com/siemens/pki/cmpracomponent/test/framework/TestUtils.java b/src/test/java/com/siemens/pki/cmpracomponent/test/framework/TestUtils.java
index 69e57667..6d62e72a 100644
--- a/src/test/java/com/siemens/pki/cmpracomponent/test/framework/TestUtils.java
+++ b/src/test/java/com/siemens/pki/cmpracomponent/test/framework/TestUtils.java
@@ -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