You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2024/04/05 13:16:52 UTC
(cxf) 01/01: Put a max default configurable limit on the Jose P2C parameter
This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch coheigea/jose-p2c
in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 75d3ee09dc7109f463d4e0ee31d29932eabd9d6b
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Fri Apr 5 14:16:09 2024 +0100
Put a max default configurable limit on the Jose P2C parameter
---
.../cxf/rs/security/jose/common/JoseConstants.java | 5 ++++
.../apache/cxf/rs/security/jose/jwe/JweUtils.java | 5 +++-
.../jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java | 15 ++++++++++
.../security/jose/jwe/JwePbeHmacAesWrapTest.java | 34 ++++++++++++++++++++++
4 files changed, 58 insertions(+), 1 deletion(-)
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java
index 48d5cbc8b0..092581d3fd 100644
--- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java
@@ -192,6 +192,11 @@ public final class JoseConstants extends RSSecurityConstants {
*/
public static final String RSSEC_ENCRYPTION_PBES2_COUNT = "rs.security.encryption.pbes2.count";
+ /**
+ * The max value for the "p2c" (PBES2 count) Header Parameter used for decryption. The default is 1_000_000.
+ */
+ public static final String RSSEC_DECRYPTION_MAX_PBES2_COUNT = "rs.security.decryption.max.pbes2.count";
+
//
// JWT specific configuration
//
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java
index cefad52f5a..67d6cb6af3 100644
--- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java
@@ -568,7 +568,10 @@ public final class JweUtils {
if (password == null) {
throw new JweException(JweException.Error.KEY_DECRYPTION_FAILURE);
}
- keyDecryptionProvider = new PbesHmacAesWrapKeyDecryptionAlgorithm(new String(password));
+ int pbes2Count = MessageUtils.getContextualInteger(m,
+ JoseConstants.RSSEC_DECRYPTION_MAX_PBES2_COUNT, 1_000_000);
+
+ keyDecryptionProvider = new PbesHmacAesWrapKeyDecryptionAlgorithm(new String(password), pbes2Count);
} else {
PrivateKey privateKey = KeyManagementUtils.loadPrivateKey(m, props, KeyOperation.DECRYPT);
if (keyAlgo == null) {
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java
index 505049bba7..fcf00beeb8 100644
--- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java
@@ -26,10 +26,15 @@ import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm;
public class PbesHmacAesWrapKeyDecryptionAlgorithm implements KeyDecryptionProvider {
private final byte[] password;
private final KeyAlgorithm algo;
+ private final int maxPbesCount;
public PbesHmacAesWrapKeyDecryptionAlgorithm(String password) {
this(password, KeyAlgorithm.PBES2_HS256_A128KW, false);
}
+ public PbesHmacAesWrapKeyDecryptionAlgorithm(String password, int maxPbesCount) {
+ this(PbesHmacAesWrapKeyEncryptionAlgorithm.stringToBytes(password), KeyAlgorithm.PBES2_HS256_A128KW,
+ false, maxPbesCount);
+ }
public PbesHmacAesWrapKeyDecryptionAlgorithm(String password, KeyAlgorithm algo, boolean hashLargePasswords) {
this(PbesHmacAesWrapKeyEncryptionAlgorithm.stringToBytes(password), algo, hashLargePasswords);
}
@@ -43,15 +48,25 @@ public class PbesHmacAesWrapKeyDecryptionAlgorithm implements KeyDecryptionProvi
this(password, KeyAlgorithm.PBES2_HS256_A128KW, false);
}
public PbesHmacAesWrapKeyDecryptionAlgorithm(byte[] password, KeyAlgorithm algo, boolean hashLargePasswords) {
+ this(password, algo, hashLargePasswords, 1_000_000);
+ }
+
+ public PbesHmacAesWrapKeyDecryptionAlgorithm(byte[] password, KeyAlgorithm algo, boolean hashLargePasswords,
+ int maxPbesCount) {
this.password =
PbesHmacAesWrapKeyEncryptionAlgorithm.validatePassword(password, algo.getJwaName(), hashLargePasswords);
this.algo = algo;
+ this.maxPbesCount = maxPbesCount;
}
+
@Override
public byte[] getDecryptedContentEncryptionKey(JweDecryptionInput jweDecryptionInput) {
JweHeaders jweHeaders = jweDecryptionInput.getJweHeaders();
byte[] saltInput = getDecodedBytes(jweHeaders.getHeader("p2s"));
int pbesCount = jweHeaders.getIntegerHeader("p2c");
+ if (pbesCount > maxPbesCount) {
+ throw new JoseException("Too many PBES2 iterations");
+ }
String keyAlgoJwt = jweHeaders.getKeyEncryptionAlgorithm().getJwaName();
int keySize = PbesHmacAesWrapKeyEncryptionAlgorithm.getKeySize(keyAlgoJwt);
byte[] derivedKey = PbesHmacAesWrapKeyEncryptionAlgorithm
diff --git a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwe/JwePbeHmacAesWrapTest.java b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwe/JwePbeHmacAesWrapTest.java
index 1ad835001e..aa37cce9f6 100644
--- a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwe/JwePbeHmacAesWrapTest.java
+++ b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwe/JwePbeHmacAesWrapTest.java
@@ -20,12 +20,14 @@ package org.apache.cxf.rs.security.jose.jwe;
import java.nio.charset.StandardCharsets;
+import org.apache.cxf.rs.security.jose.common.JoseException;
import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm;
import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
public class JwePbeHmacAesWrapTest {
@@ -64,4 +66,36 @@ public class JwePbeHmacAesWrapTest {
assertEquals(specPlainText, decryptedText);
}
+
+ @Test
+ public void testDecryptWithInvalidLargeP2CValue() throws Exception {
+ final String specPlainText = "Live long and prosper.";
+ JweHeaders headers = new JweHeaders();
+ headers.setKeyEncryptionAlgorithm(KeyAlgorithm.PBES2_HS256_A128KW);
+ headers.setContentEncryptionAlgorithm(ContentAlgorithm.A128GCM);
+ final String password = "Thus from my lips, by yours, my sin is purged.";
+ KeyEncryptionProvider keyEncryption =
+ new PbesHmacAesWrapKeyEncryptionAlgorithm(password, 1_500_000, KeyAlgorithm.PBES2_HS256_A128KW, false);
+ JweEncryptionProvider encryption = new JweEncryption(keyEncryption,
+ new AesGcmContentEncryptionAlgorithm(ContentAlgorithm.A128GCM));
+ String jweContent = encryption.encrypt(specPlainText.getBytes(StandardCharsets.UTF_8), null);
+
+ // 1. It should fail by default
+ PbesHmacAesWrapKeyDecryptionAlgorithm keyDecryption = new PbesHmacAesWrapKeyDecryptionAlgorithm(password);
+ JweDecryptionProvider decryption = new JweDecryption(keyDecryption,
+ new AesGcmContentDecryptionAlgorithm(ContentAlgorithm.A128GCM));
+ try {
+ decryption.decrypt(jweContent).getContentText();
+ fail("Failure expected on a too large p2c value");
+ } catch (JoseException ex) {
+ // expected
+ }
+
+ // 2. Now we allow 1.5M iterations and it passes
+ keyDecryption = new PbesHmacAesWrapKeyDecryptionAlgorithm(password, 1_500_000);
+ decryption = new JweDecryption(keyDecryption,
+ new AesGcmContentDecryptionAlgorithm(ContentAlgorithm.A128GCM));
+ String decryptedText = decryption.decrypt(jweContent).getContentText();
+ assertEquals(specPlainText, decryptedText);
+ }
}