From 3af0e2d318859b6f3a09703b30d076559b515a21 Mon Sep 17 00:00:00 2001 From: Colm O hEigeartaigh Date: Tue, 8 Sep 2026 10:43:09 +0100 Subject: [PATCH] Fix STS secret-key sizing --- ...eConversationTokenInterceptorProvider.java | 7 ++-- .../cxf/sts/operation/AbstractOperation.java | 3 +- .../provider/DefaultSubjectProvider.java | 8 +++-- .../token/provider/TokenProviderUtils.java | 36 +++++++++++++++++++ 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/SecureConversationTokenInterceptorProvider.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/SecureConversationTokenInterceptorProvider.java index fa354d35f58..0615b530841 100755 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/SecureConversationTokenInterceptorProvider.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/SecureConversationTokenInterceptorProvider.java @@ -41,6 +41,7 @@ import org.apache.wss4j.policy.model.AlgorithmSuite; import org.apache.wss4j.policy.model.SecureConversationToken; import org.apache.wss4j.policy.model.SupportingTokens; +import org.apache.xml.security.algorithms.JCEMapper; /** * @@ -104,8 +105,10 @@ static String setupClient(STSClient client, AlgorithmSuite suite = NegotiationUtils.getAlgorithmSuite(aim); if (suite != null) { client.setAlgorithmSuite(suite); - int x = suite.getAlgorithmSuiteType().getMaximumSymmetricKeyLength(); - if (x < 256) { + // The secret must have exactly the length required by the encryption algorithm of the suite + int x = JCEMapper.getKeyLengthFromURI(suite.getAlgorithmSuiteType().getEncryption()); + if (x >= suite.getAlgorithmSuiteType().getMinimumSymmetricKeyLength() + && x <= suite.getAlgorithmSuiteType().getMaximumSymmetricKeyLength()) { client.setKeySize(x); } } diff --git a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java index ef05d5fd67a..ac8c2db75bf 100644 --- a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java +++ b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java @@ -61,6 +61,7 @@ import org.apache.cxf.sts.token.delegation.TokenDelegationResponse; import org.apache.cxf.sts.token.provider.TokenProvider; import org.apache.cxf.sts.token.provider.TokenProviderParameters; +import org.apache.cxf.sts.token.provider.TokenProviderUtils; import org.apache.cxf.sts.token.provider.TokenReference; import org.apache.cxf.sts.token.realm.Relationship; import org.apache.cxf.sts.token.realm.RelationshipResolver; @@ -382,7 +383,7 @@ protected Element encryptSecret( final SecretKey symmetricKey; if (secret != null) { - symmetricKey = KeyUtils.prepareSecretKey(encryptionProperties.getEncryptionAlgorithm(), secret); + symmetricKey = TokenProviderUtils.createSecretKey(secret, keyRequirements, encryptionProperties); } else { KeyGenerator keyGen = KeyUtils.getKeyGenerator(encryptionProperties.getEncryptionAlgorithm()); symmetricKey = keyGen.generateKey(); diff --git a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java index de7ae784e31..19339ed139e 100644 --- a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java +++ b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java @@ -266,7 +266,8 @@ protected KeyInfoBean createKeyInfo(SubjectProviderParameters subjectProviderPar } Document doc = subjectProviderParameters.getDoc(); byte[] secret = subjectProviderParameters.getSecret(); - return createEncryptedKeyKeyInfo(certs[0], secret, doc, encryptionProperties, crypto); + return createEncryptedKeyKeyInfo(certs[0], secret, doc, encryptionProperties, crypto, + keyRequirements); } catch (WSSecurityException ex) { LOG.log(Level.WARNING, "", ex); throw new STSException(ex.getMessage(), ex); @@ -327,7 +328,8 @@ protected static KeyInfoBean createEncryptedKeyKeyInfo( byte[] secret, Document doc, EncryptionProperties encryptionProperties, - Crypto encryptionCrypto + Crypto encryptionCrypto, + KeyRequirements keyRequirements ) throws WSSecurityException { KeyInfoBean keyInfo = new KeyInfoBean(); @@ -339,7 +341,7 @@ protected static KeyInfoBean createEncryptedKeyKeyInfo( final SecretKey symmetricKey; if (secret != null) { - symmetricKey = KeyUtils.prepareSecretKey(encryptionProperties.getEncryptionAlgorithm(), secret); + symmetricKey = TokenProviderUtils.createSecretKey(secret, keyRequirements, encryptionProperties); } else { KeyGenerator keyGen = KeyUtils.getKeyGenerator(encryptionProperties.getEncryptionAlgorithm()); symmetricKey = keyGen.generateKey(); diff --git a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/TokenProviderUtils.java b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/TokenProviderUtils.java index 91b4f6a3162..2b8907b4ea8 100644 --- a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/TokenProviderUtils.java +++ b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/TokenProviderUtils.java @@ -44,6 +44,7 @@ import org.apache.cxf.ws.security.wss4j.WSS4JUtils; import org.apache.wss4j.common.ConfigurationConstants; import org.apache.wss4j.common.WSEncryptionPart; +import org.apache.wss4j.common.WSS4JConstants; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.util.KeyUtils; import org.apache.wss4j.dom.handler.WSHandlerConstants; @@ -58,6 +59,11 @@ public final class TokenProviderUtils { private static final Logger LOG = LogUtils.getL7dLogger(TokenProviderUtils.class); + private static final Map AES_ALGORITHMS = Map.of( + 16, WSS4JConstants.AES_128, + 24, WSS4JConstants.AES_192, + 32, WSS4JConstants.AES_256); + private TokenProviderUtils() { // complete } @@ -104,6 +110,36 @@ public static String extractAddressFromParticipantsEPR(Object participants) { return null; } + /** + * Create a SecretKey for the given issued secret. The secret was sized according to the KeySize and + * EncryptWith values of the request, so the algorithm associated with it must match that length + * rather than simply being the algorithm that the STS is configured with. + */ + public static SecretKey createSecretKey( + byte[] secret, + KeyRequirements keyRequirements, + EncryptionProperties encryptionProperties + ) throws WSSecurityException { + String encryptWith = keyRequirements.getEncryptWith(); + if (encryptWith == null + || !encryptionProperties.getAcceptedEncryptionAlgorithms().contains(encryptWith) + || KeyUtils.getKeyLength(encryptWith) != secret.length) { + encryptWith = encryptionProperties.getEncryptionAlgorithm(); + } + if (KeyUtils.getKeyLength(encryptWith) != secret.length) { + // Fall back on an algorithm that matches the length of the issued secret + encryptWith = AES_ALGORITHMS.get(secret.length); + if (encryptWith == null) { + throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE); + } + if (LOG.isLoggable(Level.FINE)) { + LOG.fine("Issued secret does not match the configured encryption algorithm, using: " + + encryptWith); + } + } + return KeyUtils.prepareSecretKey(encryptWith, secret); + } + /** * Encrypt a Token element using the given arguments. */