From 3e91e1fde03d111d772976960bdda1ecf7cba447 Mon Sep 17 00:00:00 2001
From: coulbeck <coulbeck@localhost>
Date: Thu, 04 Oct 2007 14:50:19 +0000
Subject: [PATCH] More changes for issue 466. Publish newly generated keys in the ADS branch.

---
 opends/src/server/org/opends/server/types/CryptoManager.java |  350 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 315 insertions(+), 35 deletions(-)

diff --git a/opends/src/server/org/opends/server/types/CryptoManager.java b/opends/src/server/org/opends/server/types/CryptoManager.java
index 1329671..553b627 100644
--- a/opends/src/server/org/opends/server/types/CryptoManager.java
+++ b/opends/src/server/org/opends/server/types/CryptoManager.java
@@ -64,6 +64,7 @@
 import org.opends.server.util.SelectableCertificateKeyManager;
 import org.opends.server.util.StaticUtils;
 import org.opends.server.util.Base64;
+import static org.opends.server.util.ServerConstants.OC_TOP;
 import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.schema.DirectoryStringSyntax;
@@ -94,16 +95,25 @@
   private static final DebugTracer TRACER = getTracer();
 
   // Various schema element references.
-  private final AttributeType attrKeyID;
-  private final AttributeType attrPublicKeyCertificate;
-  private final AttributeType attrTransformation;
-  private final AttributeType attrMacAlgorithm;
-  private final AttributeType attrSymmetricKey;
-  private final AttributeType attrInitVectorLength;
-  private final AttributeType attrKeyLength;
-  private final AttributeType attrCompromisedTime;
-  private final ObjectClass   ocCipherKey;
-  private final ObjectClass   ocMacKey;
+  private static AttributeType attrKeyID;
+  private static AttributeType attrPublicKeyCertificate;
+  private static AttributeType attrTransformation;
+  private static AttributeType attrMacAlgorithm;
+  private static AttributeType attrSymmetricKey;
+  private static AttributeType attrInitVectorLength;
+  private static AttributeType attrKeyLength;
+  private static AttributeType attrCompromisedTime;
+  private static ObjectClass   ocCipherKey;
+  private static ObjectClass   ocMacKey;
+
+  // The DN of the administration suffix.
+  private static DN adminSuffixDN;
+
+  // The DN of the ADS secret keys container.
+  private static DN secretKeysDN;
+
+  // Indicates whether the schema references have been initialized.
+  private static boolean schemaInitDone = false;
 
   // The secure random number generator used for key generation,
   // initialization vector PRNG seed...
@@ -152,7 +162,6 @@
   // The set of SSL cipher suites enabled or null for the default set.
   private final SortedSet<String> sslCipherSuites;
 
-
   /**
    * Creates a new instance of this crypto manager object from a given
    * configuration.
@@ -171,27 +180,44 @@
   public CryptoManager(CryptoManagerCfg cfg)
          throws ConfigException, InitializationException
   {
-    // Initialize various schema references.
-    attrKeyID = DirectoryServer.getAttributeType(
-         ConfigConstants.ATTR_CRYPTO_KEY_ID);
-    attrPublicKeyCertificate = DirectoryServer.getAttributeType(
-                 ConfigConstants.ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE);
-    attrTransformation = DirectoryServer.getAttributeType(
-         ConfigConstants.ATTR_CRYPTO_CIPHER_TRANSFORMATION_NAME);
-    attrMacAlgorithm = DirectoryServer.getAttributeType(
-         ConfigConstants.ATTR_CRYPTO_MAC_ALGORITHM_NAME);
-    attrSymmetricKey = DirectoryServer.getAttributeType(
-         ConfigConstants.ATTR_CRYPTO_SYMMETRIC_KEY);
-    attrInitVectorLength = DirectoryServer.getAttributeType(
-         ConfigConstants.ATTR_CRYPTO_INIT_VECTOR_LENGTH_BITS);
-    attrKeyLength = DirectoryServer.getAttributeType(
-         ConfigConstants.ATTR_CRYPTO_KEY_LENGTH_BITS);
-    attrCompromisedTime = DirectoryServer.getAttributeType(
-         ConfigConstants.ATTR_CRYPTO_KEY_COMPROMISED_TIME);
-    ocCipherKey = DirectoryServer.getObjectClass(
-         ConfigConstants.OC_CRYPTO_CIPHER_KEY);
-    ocMacKey = DirectoryServer.getObjectClass(
-         ConfigConstants.OC_CRYPTO_MAC_KEY);
+    if (!schemaInitDone)
+    {
+      // Initialize various schema references.
+      attrKeyID = DirectoryServer.getAttributeType(
+           ConfigConstants.ATTR_CRYPTO_KEY_ID);
+      attrPublicKeyCertificate = DirectoryServer.getAttributeType(
+           ConfigConstants.ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE);
+      attrTransformation = DirectoryServer.getAttributeType(
+           ConfigConstants.ATTR_CRYPTO_CIPHER_TRANSFORMATION_NAME);
+      attrMacAlgorithm = DirectoryServer.getAttributeType(
+           ConfigConstants.ATTR_CRYPTO_MAC_ALGORITHM_NAME);
+      attrSymmetricKey = DirectoryServer.getAttributeType(
+           ConfigConstants.ATTR_CRYPTO_SYMMETRIC_KEY);
+      attrInitVectorLength = DirectoryServer.getAttributeType(
+           ConfigConstants.ATTR_CRYPTO_INIT_VECTOR_LENGTH_BITS);
+      attrKeyLength = DirectoryServer.getAttributeType(
+           ConfigConstants.ATTR_CRYPTO_KEY_LENGTH_BITS);
+      attrCompromisedTime = DirectoryServer.getAttributeType(
+           ConfigConstants.ATTR_CRYPTO_KEY_COMPROMISED_TIME);
+      ocCipherKey = DirectoryServer.getObjectClass(
+           ConfigConstants.OC_CRYPTO_CIPHER_KEY);
+      ocMacKey = DirectoryServer.getObjectClass(
+           ConfigConstants.OC_CRYPTO_MAC_KEY);
+
+      try
+      {
+        adminSuffixDN = DN.decode(
+             ADSContext.getAdministrationSuffixDN());
+        secretKeysDN = adminSuffixDN.concat(
+             DN.decode("cn=secret keys"));
+      }
+      catch (DirectoryException e)
+      {
+        throw new InitializationException(e.getMessageObject());
+      }
+
+      schemaInitDone = true;
+    }
 
     // TODO -- Get the crypto defaults from the configuration.
 
@@ -2090,8 +2116,9 @@
               (null == iv) ? 0 : iv.length * Byte.SIZE);
 
       if (null != map) {
+        publishKeyEntry(cryptoManager, keyEntry);
         map.put(keyEntry.getKeyID(), keyEntry);
-        // TODO: publish key in ADS. (mark key "blocked" in map
+        // TODO: (mark key "blocked" in map
         // until registered? OTOH, Key should be in local map prior to
         // publication, since data could arrive from a remote OpenDS
         // instance encrypted with the key any time after publication.
@@ -2104,6 +2131,139 @@
 
 
     /**
+     * Publish a new cipher key by adding an entry into ADS.
+     * @param  cryptoManager The CryptoManager instance for which the
+     *                       key was generated.
+     * @param  keyEntry      The cipher key to be published.
+     * @throws CryptoManagerException
+     *                       If the key entry could not be added to
+     *                       ADS.
+     */
+    private static void publishKeyEntry(CryptoManager cryptoManager,
+                                        CipherKeyEntry keyEntry)
+         throws CryptoManagerException
+    {
+      // Construct the key entry DN.
+      AttributeValue distinguishedValue =
+           new AttributeValue(attrKeyID,
+                              keyEntry.getKeyID().getStringValue());
+      DN entryDN = secretKeysDN.concat(
+           RDN.create(attrKeyID, distinguishedValue));
+
+      // Set the entry object classes.
+      LinkedHashMap<ObjectClass,String> ocMap =
+          new LinkedHashMap<ObjectClass,String>(2);
+      ocMap.put(DirectoryServer.getTopObjectClass(), OC_TOP);
+      ocMap.put(ocCipherKey, ConfigConstants.OC_CRYPTO_CIPHER_KEY);
+
+      // Create the operational and user attributes.
+      LinkedHashMap<AttributeType,List<Attribute>> opAttrs =
+           new LinkedHashMap<AttributeType,List<Attribute>>(0);
+      LinkedHashMap<AttributeType,List<Attribute>> userAttrs =
+           new LinkedHashMap<AttributeType,List<Attribute>>();
+
+      // Add the key ID attribute.
+      LinkedHashSet<AttributeValue> valueSet =
+           new LinkedHashSet<AttributeValue>(1);
+      valueSet.add(distinguishedValue);
+
+      ArrayList<Attribute> attrList = new ArrayList<Attribute>(1);
+      attrList.add(new Attribute(attrKeyID,
+                                 attrKeyID.getNameOrOID(),
+                                 valueSet));
+      userAttrs.put(attrKeyID, attrList);
+
+      // Add the transformation name attribute.
+      valueSet = new LinkedHashSet<AttributeValue>(1);
+      valueSet.add(new AttributeValue(attrTransformation,
+                                      keyEntry.getType()));
+
+      attrList = new ArrayList<Attribute>(1);
+      attrList.add(
+           new Attribute(attrTransformation,
+                         attrTransformation.getNameOrOID(),
+                         valueSet));
+      userAttrs.put(attrTransformation, attrList);
+
+
+      // Add the init vector length attribute.
+      valueSet = new LinkedHashSet<AttributeValue>(1);
+      valueSet.add(new AttributeValue(
+           attrInitVectorLength,
+           String.valueOf(keyEntry.getIVLengthBits())));
+
+      attrList = new ArrayList<Attribute>(1);
+      attrList.add(
+           new Attribute(attrInitVectorLength,
+                         attrInitVectorLength.getNameOrOID(),
+                         valueSet));
+      userAttrs.put(attrInitVectorLength, attrList);
+
+
+      // Add the key length attribute.
+      valueSet = new LinkedHashSet<AttributeValue>(1);
+      valueSet.add(new AttributeValue(
+           attrKeyLength,
+           String.valueOf(keyEntry.getKeyLengthBits())));
+
+      attrList = new ArrayList<Attribute>(1);
+      attrList.add(
+           new Attribute(attrKeyLength,
+                         attrKeyLength.getNameOrOID(),
+                         valueSet));
+      userAttrs.put(attrKeyLength, attrList);
+
+
+      // Get the trusted certificates.
+      Map<String, byte[]> trustedCerts =
+           cryptoManager.getTrustedCertificates();
+
+      // Need to add our own instance certificate.
+      byte[] instanceKeyCertificate =
+           cryptoManager.getInstanceKeyCertificate();
+      trustedCerts.put(getInstanceKeyID(instanceKeyCertificate),
+                       instanceKeyCertificate);
+
+      // Add the symmetric key attribute.
+      LinkedHashSet<AttributeValue> symmetricKeyValues =
+           new LinkedHashSet<AttributeValue>(trustedCerts.size());
+
+      for (Map.Entry<String, byte[]> mapEntry :
+           trustedCerts.entrySet())
+      {
+        String symmetricKey =
+             cryptoManager.encodeSymmetricKeyAttribute(
+                  mapEntry.getKey(),
+                  mapEntry.getValue(),
+                  keyEntry.getSecretKey());
+
+        symmetricKeyValues.add(
+             new AttributeValue(attrSymmetricKey, symmetricKey));
+
+        attrList = new ArrayList<Attribute>(1);
+        attrList.add(new Attribute(attrSymmetricKey,
+                                   attrSymmetricKey.getNameOrOID(),
+                                   symmetricKeyValues));
+        userAttrs.put(attrSymmetricKey, attrList);
+      }
+
+      // Create the entry.
+      Entry entry = new Entry(entryDN, ocMap, userAttrs, opAttrs);
+
+      InternalClientConnection connection =
+           InternalClientConnection.getRootConnection();
+      AddOperation addOperation = connection.processAdd(entry);
+      if (addOperation.getResultCode() != ResultCode.SUCCESS)
+      {
+        // TODO i18n
+        Message message = Message.raw(
+             "Unable to add generated cipher key entry %s: %s",
+             entry.getDN(), addOperation.getErrorMessage());
+        throw new CryptoManagerException(message);
+      }
+    }
+
+    /**
      * Initializes a secret key entry from the supplied parameters,
      * validates it, and registers it in the supplied map. The
      * anticipated use of this method is to import a key entry from
@@ -2164,7 +2324,7 @@
       // Validate new entry.
       byte[] iv = null;
       if (0 < ivLengthBits) {
-        iv = new byte[ivLengthBits * Byte.SIZE];
+        iv = new byte[ivLengthBits / Byte.SIZE];
         pseudoRandom.nextBytes(iv);
       }
       getCipher(keyEntry, Cipher.DECRYPT_MODE, iv);
@@ -2430,8 +2590,9 @@
       getMacEngine(keyEntry);
 
       if (null != map) {
+        publishKeyEntry(cryptoManager, keyEntry);
         map.put(keyEntry.getKeyID(), keyEntry);
-        // TODO: publish key in ADS. (mark key "blocked" in map
+        // TODO: (mark key "blocked" in map
         // until registered? OTOH, Key should be in local map prior to
         // publication, since data could arrive from a remote OpenDS
         // instance encrypted with the key any time after publication.
@@ -2444,6 +2605,125 @@
 
 
     /**
+     * Publish a new mac key by adding an entry into ADS.
+     * @param  cryptoManager The CryptoManager instance for which the
+     *                       key was generated.
+     * @param  keyEntry      The mac key to be published.
+     * @throws CryptoManagerException
+     *                       If the key entry could not be added to
+     *                       ADS.
+     */
+    private static void publishKeyEntry(CryptoManager cryptoManager,
+                                        MacKeyEntry keyEntry)
+         throws CryptoManagerException
+    {
+      // Construct the key entry DN.
+      AttributeValue distinguishedValue =
+           new AttributeValue(attrKeyID,
+                              keyEntry.getKeyID().getStringValue());
+      DN entryDN = secretKeysDN.concat(
+           RDN.create(attrKeyID, distinguishedValue));
+
+      // Set the entry object classes.
+      LinkedHashMap<ObjectClass,String> ocMap =
+          new LinkedHashMap<ObjectClass,String>(2);
+      ocMap.put(DirectoryServer.getTopObjectClass(), OC_TOP);
+      ocMap.put(ocMacKey, ConfigConstants.OC_CRYPTO_MAC_KEY);
+
+      // Create the operational and user attributes.
+      LinkedHashMap<AttributeType,List<Attribute>> opAttrs =
+           new LinkedHashMap<AttributeType,List<Attribute>>(0);
+      LinkedHashMap<AttributeType,List<Attribute>> userAttrs =
+           new LinkedHashMap<AttributeType,List<Attribute>>();
+
+      // Add the key ID attribute.
+      LinkedHashSet<AttributeValue> valueSet =
+           new LinkedHashSet<AttributeValue>(1);
+      valueSet.add(distinguishedValue);
+
+      ArrayList<Attribute> attrList = new ArrayList<Attribute>(1);
+      attrList.add(new Attribute(attrKeyID,
+                                 attrKeyID.getNameOrOID(),
+                                 valueSet));
+      userAttrs.put(attrKeyID, attrList);
+
+      // Add the mac algorithm name attribute.
+      valueSet = new LinkedHashSet<AttributeValue>(1);
+      valueSet.add(new AttributeValue(attrMacAlgorithm,
+                                      keyEntry.getType()));
+
+      attrList = new ArrayList<Attribute>(1);
+      attrList.add(
+           new Attribute(attrMacAlgorithm,
+                         attrMacAlgorithm.getNameOrOID(),
+                         valueSet));
+      userAttrs.put(attrMacAlgorithm, attrList);
+
+
+      // Add the key length attribute.
+      valueSet = new LinkedHashSet<AttributeValue>(1);
+      valueSet.add(new AttributeValue(
+           attrKeyLength,
+           String.valueOf(keyEntry.getKeyLengthBits())));
+
+      attrList = new ArrayList<Attribute>(1);
+      attrList.add(
+           new Attribute(attrKeyLength,
+                         attrKeyLength.getNameOrOID(),
+                         valueSet));
+      userAttrs.put(attrKeyLength, attrList);
+
+
+      // Get the trusted certificates.
+      Map<String, byte[]> trustedCerts =
+           cryptoManager.getTrustedCertificates();
+
+      // Need to add our own instance certificate.
+      byte[] instanceKeyCertificate =
+           cryptoManager.getInstanceKeyCertificate();
+      trustedCerts.put(getInstanceKeyID(instanceKeyCertificate),
+                       instanceKeyCertificate);
+
+      // Add the symmetric key attribute.
+      LinkedHashSet<AttributeValue> symmetricKeyValues =
+           new LinkedHashSet<AttributeValue>(trustedCerts.size());
+
+      for (Map.Entry<String, byte[]> mapEntry :
+           trustedCerts.entrySet())
+      {
+        String symmetricKey =
+             cryptoManager.encodeSymmetricKeyAttribute(
+                  mapEntry.getKey(),
+                  mapEntry.getValue(),
+                  keyEntry.getSecretKey());
+
+        symmetricKeyValues.add(
+             new AttributeValue(attrSymmetricKey, symmetricKey));
+
+        attrList = new ArrayList<Attribute>(1);
+        attrList.add(new Attribute(attrSymmetricKey,
+                                   attrSymmetricKey.getNameOrOID(),
+                                   symmetricKeyValues));
+        userAttrs.put(attrSymmetricKey, attrList);
+      }
+
+      // Create the entry.
+      Entry entry = new Entry(entryDN, ocMap, userAttrs, opAttrs);
+
+      InternalClientConnection connection =
+           InternalClientConnection.getRootConnection();
+      AddOperation addOperation = connection.processAdd(entry);
+      if (addOperation.getResultCode() != ResultCode.SUCCESS)
+      {
+        // TODO i18n
+        Message message = Message.raw(
+             "Unable to add generated mac key entry %s: %s",
+             entry.getDN(), addOperation.getErrorMessage());
+        throw new CryptoManagerException(message);
+      }
+    }
+
+    /**
      * Initializes a secret key entry from the supplied parameters,
      * validates it, and registers it in the supplied map. The
      * anticipated use of this method is to import a key entry from

--
Gitblit v1.10.0