[java-opensaml] 02/02: OSJ-339: Add config prop for global ECDH KDF.

Brent Putman putmanb at georgetown.edu
Tue Jul 27 03:14:19 UTC 2021


This is an automated email from the git hooks/post-receive script.

putmanb pushed a commit to branch main
in repository java-opensaml.

View the commit online:
http://git.shibboleth.net/view/?p=java-opensaml.git;a=commit;h=c482720f1145dcc81817003f8136e05891a0eb3e

commit c482720f1145dcc81817003f8136e05891a0eb3e
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Tue Jul 20 19:24:38 2021 -0400

    OSJ-339: Add config prop for global ECDH KDF.
---
 .../DefaultSecurityConfigurationBootstrap.java     |  68 +++++++++---
 .../DefaultSecurityConfigurationBootstrapTest.java | 120 +++++++++++++++++++++
 2 files changed, 173 insertions(+), 15 deletions(-)

diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/config/impl/DefaultSecurityConfigurationBootstrap.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/config/impl/DefaultSecurityConfigurationBootstrap.java
index d21a30df8..d78841ede 100644
--- a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/config/impl/DefaultSecurityConfigurationBootstrap.java
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/config/impl/DefaultSecurityConfigurationBootstrap.java
@@ -22,14 +22,17 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Properties;
 import java.util.Set;
 
 import javax.annotation.Nonnull;
 
+import org.opensaml.core.config.ConfigurationService;
 import org.opensaml.security.crypto.JCAConstants;
 import org.opensaml.xmlsec.agreement.impl.DigestMethod;
 import org.opensaml.xmlsec.agreement.impl.KANonce;
 import org.opensaml.xmlsec.derivation.impl.ConcatKDF;
+import org.opensaml.xmlsec.derivation.impl.PBKDF2;
 import org.opensaml.xmlsec.encryption.support.ChainingEncryptedKeyResolver;
 import org.opensaml.xmlsec.encryption.support.EncryptedKeyResolver;
 import org.opensaml.xmlsec.encryption.support.EncryptionConstants;
@@ -68,6 +71,15 @@ import net.shibboleth.utilities.java.support.component.ComponentInitializationEx
  */
 public class DefaultSecurityConfigurationBootstrap {
     
+    /** Config property name for ECDH default Key Derivation Function (KDF). */
+    public static final String CONFIG_PROPERTY_ECDH_DEFAULT_KDF = "opensaml.config.ecdh.defaultKDF";
+    
+    /** Config property value for default KDF: ConcatKDF. */
+    public static final String CONCATKDF = "ConcatKDF";
+    
+    /** Config property value for default KDF: PBKDF2. */
+    public static final String PBKDF2 = "PBKDF2";
+    
     /** Logger. */
     private static final Logger LOG = LoggerFactory.getLogger(DefaultSecurityConfigurationBootstrap.class);
     
@@ -113,19 +125,49 @@ public class DefaultSecurityConfigurationBootstrap {
                 null
                 ));
         
+        config.setKeyAgreementConfigurations(buildKeyAgreementConfigurations());
+        
+        config.setDataKeyInfoGeneratorManager(buildDataEncryptionKeyInfoGeneratorManager());
+        config.setKeyTransportKeyInfoGeneratorManager(buildKeyTransportEncryptionKeyInfoGeneratorManager());
+        
+        return config;
+    }
+    
+    /**
+     * Build key agreement configurations.
+     * 
+     * @return key agreement configurations.
+     */
+    @Nonnull protected static Map<String, KeyAgreementEncryptionConfiguration> buildKeyAgreementConfigurations() {
+        
+        final Map<String, KeyAgreementEncryptionConfiguration> kaConfigs = new HashMap<>();
         try {
-            final Map<String, KeyAgreementEncryptionConfiguration> kaConfigs = new HashMap<>();
+            
+            final Properties props = ConfigurationService.getConfigurationProperties(); 
             
             final KeyAgreementEncryptionConfiguration ecConfig = new KeyAgreementEncryptionConfiguration();
             ecConfig.setAlgorithm(EncryptionConstants.ALGO_ID_KEYAGREEMENT_ECDH_ES);
-            final ConcatKDF ecConcatKDF = new ConcatKDF();
-            // Need to set these 3 to something to confirm to NIST spec requirements. Actual deployments
-            // can and should override in a custom config with specific parameter values, if needed.
-            ecConcatKDF.setAlgorithmID("00");
-            ecConcatKDF.setPartyUInfo("00");
-            ecConcatKDF.setPartyVInfo("00");
-            ecConcatKDF.initialize();
-            ecConfig.setParameters(Set.of(ecConcatKDF));
+            
+            final String ecKDF = 
+                    props != null ? props.getProperty(CONFIG_PROPERTY_ECDH_DEFAULT_KDF, CONCATKDF) : CONCATKDF;
+                    
+            if (CONCATKDF.equals(ecKDF)) {
+                final ConcatKDF ecConcatKDF = new ConcatKDF();
+                // Need to set these 3 to something to confirm to NIST spec requirements. Actual deployments
+                // can and should override in a custom config with specific parameter values, if needed.
+                ecConcatKDF.setAlgorithmID("00");
+                ecConcatKDF.setPartyUInfo("00");
+                ecConcatKDF.setPartyVInfo("00");
+                ecConcatKDF.initialize();
+                ecConfig.setParameters(Set.of(ecConcatKDF));
+            } else if (PBKDF2.equals(ecKDF)) {
+                final PBKDF2 ecPBKDF2 = new PBKDF2();
+                ecPBKDF2.initialize();
+                ecConfig.setParameters(Set.of(ecPBKDF2));
+            } else {
+                LOG.warn("Saw unknown value for ECDH KDF '{}', omitting global ECDH KDF configuration", ecKDF);
+                ecConfig.setParameters(Collections.emptySet());
+            }
             kaConfigs.put(JCAConstants.KEY_ALGO_EC, ecConfig);
             
             // For DH we default the Legacy KDF variant as that is mandatory for DH support.
@@ -134,21 +176,17 @@ public class DefaultSecurityConfigurationBootstrap {
             final DigestMethod digestMethod = new DigestMethod();
             digestMethod.setAlgorithm(EncryptionConstants.ALGO_ID_DIGEST_SHA256);
             digestMethod.initialize();
-            KANonce nonce = new KANonce();
+            final KANonce nonce = new KANonce();
             // This will use an auto-generated nonce value each time
             nonce.initialize();
             dhConfig.setParameters(Set.of(digestMethod, nonce));
             kaConfigs.put(JCAConstants.KEY_ALGO_DH, dhConfig);
             
-            config.setKeyAgreementConfigurations(kaConfigs);
         } catch (final ComponentInitializationException e) {
             LOG.error("Initialization failure on global key agreement encryption configuration, will be unusable", e);
         }
         
-        config.setDataKeyInfoGeneratorManager(buildDataEncryptionKeyInfoGeneratorManager());
-        config.setKeyTransportKeyInfoGeneratorManager(buildKeyTransportEncryptionKeyInfoGeneratorManager());
-        
-        return config;
+        return kaConfigs;
     }
     
     /**
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/config/impl/DefaultSecurityConfigurationBootstrapTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/config/impl/DefaultSecurityConfigurationBootstrapTest.java
new file mode 100644
index 000000000..e31190c38
--- /dev/null
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/config/impl/DefaultSecurityConfigurationBootstrapTest.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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.
+ */
+
+package org.opensaml.xmlsec.config.impl;
+
+import java.util.Map;
+import java.util.Properties;
+
+import org.opensaml.core.config.provider.ThreadLocalConfigurationPropertiesHolder;
+import org.opensaml.security.crypto.JCAConstants;
+import org.opensaml.xmlsec.derivation.KeyDerivation;
+import org.opensaml.xmlsec.derivation.impl.ConcatKDF;
+import org.opensaml.xmlsec.derivation.impl.PBKDF2;
+import org.opensaml.xmlsec.encryption.support.KeyAgreementEncryptionConfiguration;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ *
+ */
+public class DefaultSecurityConfigurationBootstrapTest {
+    
+    @Test
+    public void testECDHDefaultKDF() {
+        Map<String, KeyAgreementEncryptionConfiguration> kaConfigs = DefaultSecurityConfigurationBootstrap.buildKeyAgreementConfigurations();
+        Assert.assertTrue(kaConfigs.containsKey(JCAConstants.KEY_ALGO_EC));
+        
+        KeyAgreementEncryptionConfiguration config = kaConfigs.get(JCAConstants.KEY_ALGO_EC);
+        KeyDerivation keyDerivation = config.getParameters().stream()
+                .filter(KeyDerivation.class::isInstance)
+                .map(KeyDerivation.class::cast)
+                .findFirst().orElse(null);
+        Assert.assertNotNull(keyDerivation);
+        Assert.assertTrue(ConcatKDF.class.isInstance(keyDerivation));
+    }
+
+    @Test
+    public void testECDHConcatKDF() {
+        try {
+            Properties props = new Properties();
+            props.setProperty("opensaml.config.ecdh.defaultKDF", "ConcatKDF");
+            ThreadLocalConfigurationPropertiesHolder.setProperties(props);
+            
+            Map<String, KeyAgreementEncryptionConfiguration> kaConfigs = DefaultSecurityConfigurationBootstrap.buildKeyAgreementConfigurations();
+            Assert.assertTrue(kaConfigs.containsKey(JCAConstants.KEY_ALGO_EC));
+        
+            KeyAgreementEncryptionConfiguration config = kaConfigs.get(JCAConstants.KEY_ALGO_EC);
+            KeyDerivation keyDerivation = config.getParameters().stream()
+                    .filter(KeyDerivation.class::isInstance)
+                    .map(KeyDerivation.class::cast)
+                    .findFirst().orElse(null);
+            Assert.assertNotNull(keyDerivation);
+            Assert.assertTrue(ConcatKDF.class.isInstance(keyDerivation));
+        } finally {
+            ThreadLocalConfigurationPropertiesHolder.clear();
+        }
+        
+    }
+    
+    @Test
+    public void testECDHPBKDF2() {
+        try {
+            Properties props = new Properties();
+            props.setProperty("opensaml.config.ecdh.defaultKDF", "PBKDF2");
+            ThreadLocalConfigurationPropertiesHolder.setProperties(props);
+            
+            Map<String, KeyAgreementEncryptionConfiguration> kaConfigs = DefaultSecurityConfigurationBootstrap.buildKeyAgreementConfigurations();
+            Assert.assertTrue(kaConfigs.containsKey(JCAConstants.KEY_ALGO_EC));
+        
+            KeyAgreementEncryptionConfiguration config = kaConfigs.get(JCAConstants.KEY_ALGO_EC);
+            KeyDerivation keyDerivation = config.getParameters().stream()
+                    .filter(KeyDerivation.class::isInstance)
+                    .map(KeyDerivation.class::cast)
+                    .findFirst().orElse(null);
+            Assert.assertNotNull(keyDerivation);
+            Assert.assertTrue(PBKDF2.class.isInstance(keyDerivation));
+        } finally {
+            ThreadLocalConfigurationPropertiesHolder.clear();
+        }
+        
+    }
+    
+    @Test
+    public void testECDHBadKDF() {
+        try {
+            Properties props = new Properties();
+            props.setProperty("opensaml.config.ecdh.defaultKDF", "BADBADBAD");
+            ThreadLocalConfigurationPropertiesHolder.setProperties(props);
+            
+            Map<String, KeyAgreementEncryptionConfiguration> kaConfigs = DefaultSecurityConfigurationBootstrap.buildKeyAgreementConfigurations();
+            Assert.assertTrue(kaConfigs.containsKey(JCAConstants.KEY_ALGO_EC));
+        
+            KeyAgreementEncryptionConfiguration config = kaConfigs.get(JCAConstants.KEY_ALGO_EC);
+            KeyDerivation keyDerivation = config.getParameters().stream()
+                    .filter(KeyDerivation.class::isInstance)
+                    .map(KeyDerivation.class::cast)
+                    .findFirst().orElse(null);
+            Assert.assertNull(keyDerivation);
+
+        } finally {
+            ThreadLocalConfigurationPropertiesHolder.clear();
+        }
+        
+    }
+
+}

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list