From ef50c789d61e47789f342837a3479fccef23c64b Mon Sep 17 00:00:00 2001
From: coulbeck <coulbeck@localhost>
Date: Wed, 10 Oct 2007 20:29:24 +0000
Subject: [PATCH] Add configuration properties for the crypto manager's preferred digest algorithm, its preferred cipher and mac algorithms and the associated key lengths.

---
 opends/resource/schema/02-config.ldif                                            |   36 ++++
 opends/src/admin/defn/org/opends/server/admin/std/CryptoManagerConfiguration.xml |  162 ++++++++++++++++++++
 opends/src/server/org/opends/server/types/CryptoManager.java                     |  228 ++++++++++++++++++++++++++--
 3 files changed, 407 insertions(+), 19 deletions(-)

diff --git a/opends/resource/schema/02-config.ldif b/opends/resource/schema/02-config.ldif
index fa1b379..e83ca56 100644
--- a/opends/resource/schema/02-config.ldif
+++ b/opends/resource/schema/02-config.ldif
@@ -2098,6 +2098,36 @@
   DESC 'A cryptographic secret-key wrapped by a public-key'
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
   X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.428
+  NAME 'ds-cfg-digest-algorithm'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.429
+  NAME 'ds-cfg-mac-algorithm'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.430
+  NAME 'ds-cfg-mac-key-length'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.431
+  NAME 'ds-cfg-cipher-transformation'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.432
+  NAME 'ds-cfg-cipher-key-length'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.433
+  NAME 'ds-cfg-key-wrapping-transformation'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
   NAME 'ds-cfg-access-control-handler'
   SUP top
@@ -3455,6 +3485,12 @@
   SUP top
   STRUCTURAL
   MAY ( cn $
+        ds-cfg-digest-algorithm $
+        ds-cfg-mac-algorithm $
+        ds-cfg-mac-key-length $
+        ds-cfg-cipher-transformation $
+        ds-cfg-cipher-key-length $
+        ds-cfg-key-wrapping-transformation $
         ds-cfg-ssl-protocol $
         ds-cfg-ssl-cipher-suite $
         ds-cfg-ssl-cert-nickname $
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/CryptoManagerConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/CryptoManagerConfiguration.xml
index e997077..64b3c46 100644
--- a/opends/src/admin/defn/org/opends/server/admin/std/CryptoManagerConfiguration.xml
+++ b/opends/src/admin/defn/org/opends/server/admin/std/CryptoManagerConfiguration.xml
@@ -44,6 +44,168 @@
       <ldap:superior>top</ldap:superior>
     </ldap:object-class>
   </adm:profile>
+  <adm:property name="digest-algorithm" multi-valued="false" advanced="false">
+    <adm:synopsis>
+      The preferred message digest algorithm for the Directory Server.
+    </adm:synopsis>
+    <adm:requires-admin-action>
+      <adm:none>
+        <adm:synopsis>
+          Changes to this property will take effect immediately but will
+          only affect cryptographic operations performed after the
+          change.
+        </adm:synopsis>
+      </adm:none>
+    </adm:requires-admin-action>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>SHA-1</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:string />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-digest-algorithm</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="mac-algorithm" multi-valued="false" advanced="false">
+    <adm:synopsis>
+      The preferred MAC algorithm for the Directory Server.
+    </adm:synopsis>
+    <adm:requires-admin-action>
+      <adm:none>
+        <adm:synopsis>
+          Changes to this property will take effect immediately but will
+          only affect cryptographic operations performed after the
+          change.
+        </adm:synopsis>
+      </adm:none>
+    </adm:requires-admin-action>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>HmacSHA1</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:string />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-mac-algorithm</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="mac-key-length" multi-valued="false" advanced="false">
+    <adm:synopsis>
+      The preferred key length in bits for the preferred MAC algorithm.
+    </adm:synopsis>
+    <adm:requires-admin-action>
+      <adm:none>
+        <adm:synopsis>
+          Changes to this property will take effect immediately but will
+          only affect cryptographic operations performed after the
+          change.
+        </adm:synopsis>
+      </adm:none>
+    </adm:requires-admin-action>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>128</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:integer />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-mac-key-length</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="cipher-transformation" multi-valued="false" advanced="false">
+    <adm:synopsis>
+      The preferred cipher for the Directory Server.
+    </adm:synopsis>
+    <adm:requires-admin-action>
+      <adm:none>
+        <adm:synopsis>
+          Changes to this property will take effect immediately but will
+          only affect cryptographic operations performed after the
+          change.
+        </adm:synopsis>
+      </adm:none>
+    </adm:requires-admin-action>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>AES/CBC/PKCS5Padding</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:string />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-cipher-transformation</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="cipher-key-length" multi-valued="false" advanced="false">
+    <adm:synopsis>
+      The preferred key length in bits for the preferred cipher.
+    </adm:synopsis>
+    <adm:requires-admin-action>
+      <adm:none>
+        <adm:synopsis>
+          Changes to this property will take effect immediately but will
+          only affect cryptographic operations performed after the
+          change.
+        </adm:synopsis>
+      </adm:none>
+    </adm:requires-admin-action>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>128</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:integer />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-cipher-key-length</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="key-wrapping-transformation" multi-valued="false" advanced="false">
+    <adm:synopsis>
+      The preferred key wrapping transformation for the Directory Server.
+    </adm:synopsis>
+    <adm:requires-admin-action>
+      <adm:none>
+        <adm:synopsis>
+          Changes to this property will take effect immediately but will
+          only affect cryptographic operations performed after the
+          change.
+        </adm:synopsis>
+      </adm:none>
+    </adm:requires-admin-action>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:string />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-key-wrapping-transformation</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
   <adm:property name="ssl-protocol" multi-valued="true">
     <adm:synopsis>
       Specifies the names of the SSL protocols that will be allowed for
diff --git a/opends/src/server/org/opends/server/types/CryptoManager.java b/opends/src/server/org/opends/server/types/CryptoManager.java
index 2278b96..0b18896 100644
--- a/opends/src/server/org/opends/server/types/CryptoManager.java
+++ b/opends/src/server/org/opends/server/types/CryptoManager.java
@@ -53,6 +53,7 @@
 
 import org.opends.admin.ads.ADSContext;
 import org.opends.server.admin.std.server.CryptoManagerCfg;
+import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.api.Backend;
 import org.opends.server.backends.TrustStoreBackend;
 import org.opends.server.config.ConfigException;
@@ -108,6 +109,7 @@
      mayExtend=false,
      mayInvoke=true)
 public class CryptoManager
+     implements ConfigurationChangeListener<CryptoManagerCfg>
 {
   /**
    * The tracer object for the debug logger.
@@ -153,30 +155,30 @@
           = new Random(secureRandom.nextLong());
 
   // The preferred message digest algorithm for the Directory Server.
-  private final String preferredDigestAlgorithm;
+  private String preferredDigestAlgorithm;
 
   // The map from encryption key ID to MacKeyEntry (cache).
   private final Map<KeyEntryID, MacKeyEntry> macKeyEntryCache
           = new ConcurrentHashMap<KeyEntryID, MacKeyEntry>();
 
   // The preferred MAC algorithm for the Directory Server.
-  private final String preferredMACAlgorithm;
+  private String preferredMACAlgorithm;
 
   // The preferred key length for the preferred MAC algorithm.
-  private final int preferredMACAlgorithmKeyLengthBits;
+  private int preferredMACAlgorithmKeyLengthBits;
 
   // The map from encryption key ID to CipherKeyEntry (cache).
   private final Map<KeyEntryID, CipherKeyEntry> cipherKeyEntryCache
        = new ConcurrentHashMap<KeyEntryID, CipherKeyEntry>();
 
   // The preferred cipher for the Directory Server.
-  private final String preferredCipherTransformation;
+  private String preferredCipherTransformation;
 
   // The preferred key length for the preferred cipher.
-  private final int preferredCipherTransformationKeyLengthBits;
+  private int preferredCipherTransformationKeyLengthBits;
 
   // The preferred key wrapping transformation
-  private final String preferredKeyWrappingTransformation;
+  private String preferredKeyWrappingTransformation;
 
   // The name of the local certificate to use for SSL.
   private final String sslCertNickname;
@@ -257,10 +259,8 @@
       schemaInitDone = true;
     }
 
-    // TODO -- Get the crypto defaults from the configuration.
-
     // Preferred digest and validation.
-    preferredDigestAlgorithm = "SHA-1";
+    preferredDigestAlgorithm = cfg.getDigestAlgorithm();
     try{
       MessageDigest.getInstance(preferredDigestAlgorithm);
     }
@@ -274,8 +274,9 @@
     }
 
     // Preferred MAC engine and validation.
-    preferredMACAlgorithm = "HmacSHA1";
-    preferredMACAlgorithmKeyLengthBits = 128;
+    preferredMACAlgorithm = cfg.getMacAlgorithm();
+    preferredMACAlgorithmKeyLengthBits =
+         cfg.getMacKeyLength();
     try {
       MacKeyEntry.generateKeyEntry(null,
               preferredMACAlgorithm,
@@ -291,8 +292,10 @@
     }
 
     // Preferred encryption cipher and validation.
-    preferredCipherTransformation = "AES/CBC/PKCS5Padding";
-    preferredCipherTransformationKeyLengthBits = 128;
+    preferredCipherTransformation =
+         cfg.getCipherTransformation();
+    preferredCipherTransformationKeyLengthBits =
+         cfg.getCipherKeyLength();
     try {
       CipherKeyEntry.generateKeyEntry(null,
               preferredCipherTransformation,
@@ -315,7 +318,7 @@
     // TODO: Trying OAEPWITHSHA-512ANDMGF1PADDING throws an exception
     // "Key too small...".
     preferredKeyWrappingTransformation
-            = "RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING";
+            = cfg.getKeyWrappingTransformation();
     try {
       final String certificateBase64 =
       "MIIB2jCCAUMCBEb7wpYwDQYJKoZIhvcNAQEEBQAwNDEbMBkGA1UEChMST3B" +
@@ -349,6 +352,9 @@
     sslEncryption   = cfg.isSSLEncryption();
     sslProtocols    = cfg.getSSLProtocol();
     sslCipherSuites = cfg.getSSLCipherSuite();
+
+    // Register as a configuration change listener.
+    cfg.addChangeListener(this);
   }
 
 
@@ -676,8 +682,8 @@
 
 
   /**
-   * Encodes a ds-cfg-symmetric-key attribute value using the supplied
-   * arguments.
+   * Encodes a ds-cfg-symmetric-key attribute value with the preferred
+   * key wrapping transformation and using the supplied arguments.
    *
    * The syntax of the ds-cfg-symmetric-key attribute:
    * <pre>
@@ -713,9 +719,45 @@
           final byte[] wrappingKeyCertificateData,
           final SecretKey secretKey)
           throws CryptoManagerException {
+    return encodeSymmetricKeyAttribute(
+         preferredKeyWrappingTransformation,
+         wrappingKeyID,
+         wrappingKeyCertificateData,
+         secretKey);
+  }
+
+
+  /**
+   * Encodes a ds-cfg-symmetric-key attribute value with a specified
+   * key wrapping transformation and using the supplied arguments.
+   *
+   * @param wrappingTransformationName The name of the key wrapping
+   * transformation.
+   *
+   * @param wrappingKeyID The key identifier of the wrapping key. This
+   * parameter is the first field in the encoded value and identifies
+   * the instance that will be able to unwrap the secret key.
+   *
+   * @param wrappingKeyCertificateData The public key certificate used
+   * to derive the wrapping key.
+   *
+   * @param secretKey The secret key value to be wrapped for the
+   * encoded value.
+   *
+   * @return The encoded representation of the ds-cfg-symmetric-key
+   * attribute with the secret key wrapped with the supplied public
+   * key.
+   *
+   * @throws CryptoManagerException  If there is a problem wrapping
+   * the secret key.
+   */
+  private String encodeSymmetricKeyAttribute(
+          final String wrappingTransformationName,
+          final String wrappingKeyID,
+          final byte[] wrappingKeyCertificateData,
+          final SecretKey secretKey)
+          throws CryptoManagerException {
     // Wrap secret key.
-    final String wrappingTransformationName
-            = preferredKeyWrappingTransformation;
     String wrappedKeyElement;
     try {
       final CertificateFactory cf
@@ -877,7 +919,8 @@
     final byte[] wrappingKeyCert =
             certMap.get(requestedInstanceKeyID);
     return encodeSymmetricKeyAttribute(
-            requestedInstanceKeyID, wrappingKeyCert, secretKey);
+         preferredKeyWrappingTransformation,
+         requestedInstanceKeyID, wrappingKeyCert, secretKey);
   }
 
 
@@ -3284,5 +3327,152 @@
       super(message, cause);
     }
   }
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationChangeAcceptable(
+       CryptoManagerCfg cfg,
+       List<Message> unacceptableReasons)
+  {
+    // Acceptable until we find an error.
+    boolean acceptable = true;
+
+    // Preferred digest validation.
+    String preferredDigestAlgorithm =
+         cfg.getDigestAlgorithm();
+    if (!preferredDigestAlgorithm.equals(
+         this.preferredDigestAlgorithm))
+    {
+      try{
+        MessageDigest.getInstance(preferredDigestAlgorithm);
+      }
+      catch (Exception ex) {
+        if (debugEnabled()) {
+          TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+        }
+        unacceptableReasons.add(
+             ERR_CRYPTOMGR_CANNOT_GET_PREFERRED_DIGEST.get(
+                  getExceptionMessage(ex)));
+        acceptable = false;
+      }
+    }
+
+    // Preferred MAC algorithm validation.
+    String preferredMACAlgorithm = cfg.getMacAlgorithm();
+    Integer preferredMACAlgorithmKeyLengthBits =
+         cfg.getMacKeyLength();
+    if (!preferredMACAlgorithm.equals(this.preferredMACAlgorithm) ||
+         preferredMACAlgorithmKeyLengthBits !=
+              this.preferredMACAlgorithmKeyLengthBits)
+    {
+      try {
+        MacKeyEntry.generateKeyEntry(
+             null,
+             preferredMACAlgorithm,
+             preferredMACAlgorithmKeyLengthBits);
+      }
+      catch (Exception ex) {
+        if (debugEnabled()) {
+          TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+        }
+        unacceptableReasons.add(
+             ERR_CRYPTOMGR_CANNOT_GET_PREFERRED_MAC_ENGINE.get(
+                  getExceptionMessage(ex)));
+        acceptable = false;
+      }
+    }
+
+    // Preferred encryption cipher validation.
+    String preferredCipherTransformation =
+         cfg.getCipherTransformation();
+    Integer preferredCipherTransformationKeyLengthBits =
+         cfg.getCipherKeyLength();
+    if (!preferredCipherTransformation.equals(
+         this.preferredCipherTransformation) ||
+         preferredCipherTransformationKeyLengthBits !=
+              this.preferredCipherTransformationKeyLengthBits)
+    {
+      try {
+        CipherKeyEntry.generateKeyEntry(
+             null,
+             preferredCipherTransformation,
+             preferredCipherTransformationKeyLengthBits);
+      }
+      catch (Exception ex) {
+        if (debugEnabled()) {
+          TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+        }
+        unacceptableReasons.add(
+             ERR_CRYPTOMGR_CANNOT_GET_PREFERRED_ENCRYPTION_CIPHER.get(
+                  getExceptionMessage(ex)));
+        acceptable = false;
+      }
+    }
+
+    // Preferred secret key wrapping cipher and validation. Depends
+    // on MAC cipher for secret key. Note that the TrustStoreBackend
+    // not available at this point, hence a "dummy" certificate must
+    // be used to validate the choice of secret key wrapping cipher.
+    String preferredKeyWrappingTransformation
+            = cfg.getKeyWrappingTransformation();
+    if (!preferredKeyWrappingTransformation.equals(
+         this.preferredKeyWrappingTransformation))
+    {
+      try {
+        final byte[] certificate =
+             getInstanceKeyCertificateFromLocalTruststore();
+        final String keyID = getInstanceKeyID(certificate);
+        final SecretKey macKey =
+             MacKeyEntry.generateKeyEntry(
+                  null,
+                  preferredMACAlgorithm,
+                  preferredMACAlgorithmKeyLengthBits).
+                  getSecretKey();
+        encodeSymmetricKeyAttribute(
+             preferredKeyWrappingTransformation, keyID,
+             certificate, macKey);
+      }
+      catch (Exception ex) {
+        if (debugEnabled()) {
+          TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+        }
+        unacceptableReasons.add(
+          ERR_CRYPTOMGR_CANNOT_GET_PREFERRED_KEY_WRAPPING_CIPHER.get(
+                  getExceptionMessage(ex)));
+        acceptable = false;
+      }
+    }
+
+    return acceptable;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationChange(
+       CryptoManagerCfg cfg)
+  {
+    ResultCode resultCode = ResultCode.SUCCESS;
+    boolean adminActionRequired = false;
+    List<Message> messages = new ArrayList<Message>();
+
+    preferredDigestAlgorithm =
+         cfg.getDigestAlgorithm();
+    preferredMACAlgorithm =
+         cfg.getMacAlgorithm();
+    preferredMACAlgorithmKeyLengthBits =
+         cfg.getMacKeyLength();
+    preferredCipherTransformation =
+         cfg.getCipherTransformation();
+    preferredCipherTransformationKeyLengthBits =
+         cfg.getCipherKeyLength();
+    preferredKeyWrappingTransformation =
+         cfg.getKeyWrappingTransformation();
+
+    return new ConfigChangeResult(resultCode,
+                                  adminActionRequired, messages);
+  }
 }
 

--
Gitblit v1.10.0