From cc27a9a0f521eac73160d93df5a905fe60ecf2d9 Mon Sep 17 00:00:00 2001
From: coulbeck <coulbeck@localhost>
Date: Tue, 02 Oct 2007 01:04:43 +0000
Subject: [PATCH] More changes for issue 466. - Defines the schema for secret keys. - Keeps the crypto manager secret key cache up to date with secret keys published in ADS.

---
 opendj-sdk/opends/src/server/org/opends/server/backends/TrustStoreBackend.java |   30 ++-
 opendj-sdk/opends/src/server/org/opends/server/core/TrustStoreSyncThread.java  |  107 +++++++++++--
 opendj-sdk/opends/src/server/org/opends/server/config/ConfigConstants.java     |   73 ++++++++
 opendj-sdk/opends/resource/schema/02-config.ldif                               |   47 +++++
 opendj-sdk/opends/src/server/org/opends/server/types/CryptoManager.java        |  210 +++++++++++++++++++++++++-
 5 files changed, 423 insertions(+), 44 deletions(-)

diff --git a/opendj-sdk/opends/resource/schema/02-config.ldif b/opendj-sdk/opends/resource/schema/02-config.ldif
index 8ddfcd7..fa1b379 100644
--- a/opendj-sdk/opends/resource/schema/02-config.ldif
+++ b/opendj-sdk/opends/resource/schema/02-config.ldif
@@ -2068,6 +2068,36 @@
   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.423
+  NAME 'ds-cfg-cipher-transformation-name'
+  DESC 'The name of a cryptographic cipher transformation consisting of an
+  algorithm, a mode, and a padding specification, separated by slashes'
+  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.424
+  NAME 'ds-cfg-mac-algorithm-name'
+  DESC 'The name of a cryptographic message authentication code (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.425
+  NAME 'ds-cfg-key-length-bits'
+  DESC 'The length of a cryptographic secret key'
+  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.426
+  NAME 'ds-cfg-initialization-vector-length-bits'
+  DESC 'The length of a cryptographic cipher initialization vector'
+  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.427
+  NAME 'ds-cfg-symmetric-key'
+  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' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
   NAME 'ds-cfg-access-control-handler'
   SUP top
@@ -3511,4 +3541,19 @@
   SUP ds-cfg-extended-operation-handler
   STRUCTURAL
   X-ORIGIN 'OpenDS Directory Server' )
-
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.174
+  NAME 'ds-cfg-cipher-key'
+  SUP top
+  STRUCTURAL
+  MUST ( ds-cfg-key-id $ ds-cfg-cipher-transformation-name $
+  ds-cfg-key-length-bits $ ds-cfg-symmetric-key )
+  MAY ( ds-cfg-initialization-vector-length-bits $ ds-cfg-key-compromised-time )
+  X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.175
+  NAME 'ds-cfg-mac-key'
+  SUP top
+  STRUCTURAL
+  MUST ( ds-cfg-key-id $ ds-cfg-mac-algorithm-name $
+  ds-cfg-key-length-bits $ ds-cfg-symmetric-key )
+  MAY ds-cfg-key-compromised-time
+  X-ORIGIN 'OpenDS Directory Server' )
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/TrustStoreBackend.java b/opendj-sdk/opends/src/server/org/opends/server/backends/TrustStoreBackend.java
index db218ce..dc49bc5 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/TrustStoreBackend.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/backends/TrustStoreBackend.java
@@ -574,7 +574,7 @@
   {
     // Make sure that the DN specifies a certificate alias.
     AttributeType t =
-         DirectoryServer.getAttributeType(ATTR_CERT_ALIAS, true);
+         DirectoryServer.getAttributeType(ATTR_CRYPTO_KEY_ID, true);
     AttributeValue v = entryDN.getRDN().getAttributeValue(t);
     if (v == null)
     {
@@ -615,8 +615,8 @@
     ocMap.put(DirectoryServer.getTopObjectClass(), OC_TOP);
 
     ObjectClass objectClass =
-         DirectoryServer.getObjectClass(OC_INSTANCE_KEY, true);
-    ocMap.put(objectClass, OC_INSTANCE_KEY);
+         DirectoryServer.getObjectClass(OC_CRYPTO_INSTANCE_KEY, true);
+    ocMap.put(objectClass, OC_CRYPTO_INSTANCE_KEY);
 
     LinkedHashMap<AttributeType,List<Attribute>> opAttrs =
          new LinkedHashMap<AttributeType,List<Attribute>>(0);
@@ -632,7 +632,8 @@
     userAttrs.put(t, attrList);
 
 
-    t = DirectoryServer.getAttributeType(ATTR_ADS_CERTIFICATE, true);
+    t = DirectoryServer.getAttributeType(
+         ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE, true);
     valueSet = new LinkedHashSet<AttributeValue>(1);
     valueSet.add(new AttributeValue(t,
                           certValue));
@@ -792,7 +793,7 @@
       if ((scope != SearchScope.BASE_OBJECT) && (! (aliases.length == 0) ))
       {
         AttributeType certAliasType =
-             DirectoryServer.getAttributeType(ATTR_CERT_ALIAS, true);
+             DirectoryServer.getAttributeType(ATTR_CRYPTO_KEY_ID, true);
         for (String alias : aliases)
         {
           DN certDN = makeChildDN(this.baseDN, certAliasType,
@@ -1570,7 +1571,7 @@
 
     // Make sure that the DN specifies a certificate alias.
     AttributeType t =
-         DirectoryServer.getAttributeType(ATTR_CERT_ALIAS, true);
+         DirectoryServer.getAttributeType(ATTR_CRYPTO_KEY_ID, true);
     AttributeValue v = entryDN.getRDN().getAttributeValue(t);
     if (v == null)
     {
@@ -1612,12 +1613,14 @@
       }
       else
       {
-        List<Attribute> certAttrs = entry.getAttribute(ATTR_ADS_CERTIFICATE);
+        List<Attribute> certAttrs = entry.getAttribute(
+             ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE);
         if (certAttrs == null)
         {
           Message message =
                ERR_TRUSTSTORE_ENTRY_MISSING_CERT_ATTR.get(
-                    String.valueOf(entryDN), ATTR_ADS_CERTIFICATE);
+                    String.valueOf(entryDN),
+                    ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE);
           throw new DirectoryException(
                DirectoryServer.getServerErrorResultCode(), message);
         }
@@ -1625,7 +1628,8 @@
         {
           Message message =
                ERR_TRUSTSTORE_ENTRY_HAS_MULTIPLE_CERT_ATTRS.get(
-                    String.valueOf(entryDN), ATTR_ADS_CERTIFICATE);
+                    String.valueOf(entryDN),
+                    ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE);
           throw new DirectoryException(
                DirectoryServer.getServerErrorResultCode(), message);
         }
@@ -1635,7 +1639,8 @@
         {
           Message message =
                ERR_TRUSTSTORE_ENTRY_MISSING_CERT_VALUE.get(
-                    String.valueOf(entryDN), ATTR_ADS_CERTIFICATE);
+                    String.valueOf(entryDN),
+                    ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE);
           throw new DirectoryException(
                DirectoryServer.getServerErrorResultCode(), message);
         }
@@ -1643,7 +1648,8 @@
         {
           Message message =
                ERR_TRUSTSTORE_ENTRY_HAS_MULTIPLE_CERT_VALUES.get(
-                    String.valueOf(entryDN), ATTR_ADS_CERTIFICATE);
+                    String.valueOf(entryDN),
+                    ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE);
           throw new DirectoryException(
                DirectoryServer.getServerErrorResultCode(), message);
         }
@@ -1699,7 +1705,7 @@
   {
     // Make sure that the DN specifies a certificate alias.
     AttributeType t =
-         DirectoryServer.getAttributeType(ATTR_CERT_ALIAS, true);
+         DirectoryServer.getAttributeType(ATTR_CRYPTO_KEY_ID, true);
     AttributeValue v = entryDN.getRDN().getAttributeValue(t);
     if (v == null)
     {
diff --git a/opendj-sdk/opends/src/server/org/opends/server/config/ConfigConstants.java b/opendj-sdk/opends/src/server/org/opends/server/config/ConfigConstants.java
index 21aceb9..c002985 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/config/ConfigConstants.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/config/ConfigConstants.java
@@ -2873,9 +2873,9 @@
 
 
   /**
-   * The name of the attribute that holds a server certificate alias.
+   * The name of the attribute that holds a cryptographic cipher-key identifier.
    */
-  public static final String ATTR_CERT_ALIAS = "ds-cfg-key-id";
+  public static final String ATTR_CRYPTO_KEY_ID = "ds-cfg-key-id";
 
 
 
@@ -2883,7 +2883,7 @@
    * The name of the objectclass that will be used for a server
    * certificate entry.
    */
-  public static final String OC_INSTANCE_KEY =
+  public static final String OC_CRYPTO_INSTANCE_KEY =
        "ds-cfg-instance-key";
 
 
@@ -2898,14 +2898,75 @@
 
 
   /**
-   * The name of the attribute that is used to specify a server
-   * instance key.
+   * The name of the objectclass that will be used for a cipher key.
    */
-  public static final String ATTR_ADS_CERTIFICATE =
+  public static final String OC_CRYPTO_CIPHER_KEY = "ds-cfg-cipher-key";
+
+
+
+  /**
+   * The name of the objectclass that will be used for a mac key.
+   */
+  public static final String OC_CRYPTO_MAC_KEY = "ds-cfg-mac-key";
+
+
+
+  /**
+   * The name of the attribute that is used to hold a cryptographic
+   * public key certificate.
+   */
+  public static final String ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE =
        "ds-cfg-public-key-certificate";
 
 
   /**
+   * The name of the attribute that is used to hold the name of a
+   * cryptographic cipher transformation.
+   */
+  public static final String ATTR_CRYPTO_CIPHER_TRANSFORMATION_NAME =
+       "ds-cfg-cipher-transformation-name";
+
+
+  /**
+   * The name of the attribute that is used to hold the name of a
+   * cryptographic message authentication code (MAC) algorithm.
+   */
+  public static final String ATTR_CRYPTO_MAC_ALGORITHM_NAME =
+       "ds-cfg-mac-algorithm-name";
+
+
+  /**
+   * The name of the attribute that is used to hold the length of a
+   * cryptographic secret key.
+   */
+  public static final String ATTR_CRYPTO_KEY_LENGTH_BITS =
+       "ds-cfg-key-length-bits";
+
+
+  /**
+   * The name of the attribute that is used to hold the length of a
+   * cryptographic cipher initialization vector.
+   */
+  public static final String ATTR_CRYPTO_INIT_VECTOR_LENGTH_BITS =
+       "ds-cfg-initialization-vector-length-bits";
+
+
+  /**
+   * The name of the attribute that is used to hold a cryptographic
+   * cipher-key wrapped by a public-key.
+   */
+  public static final String ATTR_CRYPTO_SYMMETRIC_KEY = "ds-cfg-symmetric-key";
+
+
+  /**
+   * The name of the attribute that is used to hold time a cryptographic key
+   * was suspected to be compromised.
+   */
+  public static final String ATTR_CRYPTO_KEY_COMPROMISED_TIME =
+       "ds-cfg-key-compromised-time";
+
+
+  /**
    * The DN of the entry that will serve as the base for all Directory Server
    * loggers.
    */
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/TrustStoreSyncThread.java b/opendj-sdk/opends/src/server/org/opends/server/core/TrustStoreSyncThread.java
index 2b72403..d096375 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/TrustStoreSyncThread.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/TrustStoreSyncThread.java
@@ -46,7 +46,9 @@
 import static org.opends.server.util.ServerConstants.
      OID_ENTRY_CHANGE_NOTIFICATION;
 import org.opends.server.config.ConfigConstants;
-import static org.opends.server.config.ConfigConstants.OC_INSTANCE_KEY;
+import static org.opends.server.config.ConfigConstants.OC_CRYPTO_INSTANCE_KEY;
+import static org.opends.server.config.ConfigConstants.OC_CRYPTO_CIPHER_KEY;
+import static org.opends.server.config.ConfigConstants.OC_CRYPTO_MAC_KEY;
 import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.protocols.internal.InternalSearchListener;
@@ -90,6 +92,9 @@
   // The DN of the instance keys container within the admin suffix.
   private DN instanceKeysDN;
 
+  // The DN of the secret keys container within the admin suffix.
+  private DN secretKeysDN;
+
   // The DN of the trust store root.
   private DN trustStoreRootDN;
 
@@ -102,8 +107,8 @@
   // The attribute type that holds the time a key was compromised.
   AttributeType attrCompromisedTime;
 
-  // A filter on the instance key object class.
-  private SearchFilter instanceKeyFilter;
+  // A filter on object class to select key entries.
+  private SearchFilter keySearchFilter;
 
   // Indicates whether the ADS suffix backend is initialized.
   private boolean adminBackendInitialized;
@@ -117,6 +122,15 @@
   // Indicates whether the initial search has been done.
   private boolean searchDone;
 
+  // The instance key objectclass.
+  private ObjectClass ocInstanceKey;
+
+  // The cipher key objectclass.
+  private ObjectClass ocCipherKey;
+
+  // The mac key objectclass.
+  private ObjectClass ocMacKey;
+
   /**
    * Creates a new instance of this trust store synchronization thread.
    */
@@ -140,22 +154,33 @@
     {
       adminSuffixDN = DN.decode(ADSContext.getAdministrationSuffixDN());
       instanceKeysDN = adminSuffixDN.concat(DN.decode("cn=instance keys"));
+      secretKeysDN = adminSuffixDN.concat(DN.decode("cn=secret keys"));
       trustStoreRootDN = DN.decode(ConfigConstants.DN_TRUST_STORE_ROOT);
-      instanceKeyFilter =
-           SearchFilter.createFilterFromString(
-                "(objectclass=" + ConfigConstants.OC_INSTANCE_KEY + ")");
+      keySearchFilter =
+           SearchFilter.createFilterFromString("(|" +
+                "(objectclass=" + OC_CRYPTO_INSTANCE_KEY + ")" +
+                "(objectclass=" + OC_CRYPTO_CIPHER_KEY + ")" +
+                "(objectclass=" + OC_CRYPTO_MAC_KEY + ")" +
+                ")");
     }
     catch (DirectoryException e)
     {
       //
     }
 
+    ocInstanceKey = DirectoryServer.getObjectClass(
+         OC_CRYPTO_INSTANCE_KEY, true);
+    ocCipherKey = DirectoryServer.getObjectClass(
+         OC_CRYPTO_CIPHER_KEY, true);
+    ocMacKey = DirectoryServer.getObjectClass(
+         OC_CRYPTO_MAC_KEY, true);
+
     attrCert = DirectoryServer.getAttributeType(
-         ConfigConstants.ATTR_ADS_CERTIFICATE, true);
+         ConfigConstants.ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE, true);
     attrAlias = DirectoryServer.getAttributeType(
-         ConfigConstants.ATTR_CERT_ALIAS, true);
+         ConfigConstants.ATTR_CRYPTO_KEY_ID, true);
     attrCompromisedTime = DirectoryServer.getAttributeType(
-         "ds-cfg-key-compromised-time", true);
+         ConfigConstants.ATTR_CRYPTO_KEY_COMPROMISED_TIME, true);
 
     if (DirectoryServer.getBackendWithBaseDN(adminSuffixDN) != null)
     {
@@ -226,7 +251,7 @@
                                      adminSuffixDN, SearchScope.WHOLE_SUBTREE,
                                      DereferencePolicy.NEVER_DEREF_ALIASES,
                                      0, 0,
-                                     false, instanceKeyFilter, attributes,
+                                     false, keySearchFilter, attributes,
                                      this);
 
     searchOperation.run();
@@ -403,6 +428,35 @@
                                         SearchResultEntry searchEntry)
        throws DirectoryException
   {
+    if (searchEntry.hasObjectClass(ocInstanceKey))
+    {
+      handleInstanceKeySearchEntry(searchEntry);
+    }
+    else
+    {
+      try
+      {
+        if (searchEntry.hasObjectClass(ocCipherKey))
+        {
+          DirectoryServer.getCryptoManager().importCipherKeyEntry(searchEntry);
+        }
+        else if (searchEntry.hasObjectClass(ocMacKey))
+        {
+          DirectoryServer.getCryptoManager().importMacKeyEntry(searchEntry);
+        }
+      }
+      catch (CryptoManager.CryptoManagerException e)
+      {
+        throw new DirectoryException(
+             DirectoryServer.getServerErrorResultCode(), e);
+      }
+    }
+  }
+
+
+  private void handleInstanceKeySearchEntry(SearchResultEntry searchEntry)
+       throws DirectoryException
+  {
     RDN srcRDN = searchEntry.getDN().getRDN();
 
     // Only process the entry if it has the expected form of RDN.
@@ -545,13 +599,10 @@
    */
   private void addEntry(Entry srcEntry, DN dstDN)
   {
-    ObjectClass instanceKeyOC =
-         DirectoryServer.getObjectClass(OC_INSTANCE_KEY, true);
-
     LinkedHashMap<ObjectClass,String> ocMap =
          new LinkedHashMap<ObjectClass,String>(2);
     ocMap.put(DirectoryServer.getTopObjectClass(), OC_TOP);
-    ocMap.put(instanceKeyOC, OC_INSTANCE_KEY);
+    ocMap.put(ocInstanceKey, OC_CRYPTO_INSTANCE_KEY);
 
     HashMap<AttributeType, List<Attribute>> userAttrs =
          new HashMap<AttributeType, List<Attribute>>();
@@ -600,11 +651,35 @@
   public void handleAddOperation(PostResponseAddOperation addOperation,
                                  Entry entry)
   {
-    if (!addOperation.getEntryDN().isDescendantOf(instanceKeysDN))
+    if (addOperation.getEntryDN().isDescendantOf(instanceKeysDN))
     {
-      return;
+      handleInstanceKeyAddOperation(entry);
     }
+    else if (addOperation.getEntryDN().isDescendantOf(secretKeysDN))
+    {
+      try
+      {
+        if (entry.hasObjectClass(ocCipherKey))
+        {
+          DirectoryServer.getCryptoManager().importCipherKeyEntry(entry);
+        }
+        else if (entry.hasObjectClass(ocMacKey))
+        {
+          DirectoryServer.getCryptoManager().importMacKeyEntry(entry);
+        }
+      }
+      catch (CryptoManager.CryptoManagerException e)
+      {
+        Message message = Message.raw("Failed to import key entry: %s",
+                                      e.getMessage());
+        ErrorLogger.logError(message);
+      }
+    }
+  }
 
+
+  private void handleInstanceKeyAddOperation(Entry entry)
+  {
     RDN srcRDN = entry.getDN().getRDN();
 
     // Only process the entry if it has the expected form of RDN.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/types/CryptoManager.java b/opendj-sdk/opends/src/server/org/opends/server/types/CryptoManager.java
index 6c6ef58..ab90472 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/types/CryptoManager.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/types/CryptoManager.java
@@ -66,6 +66,8 @@
 import org.opends.server.util.Base64;
 import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.protocols.internal.InternalSearchOperation;
+import org.opends.server.schema.DirectoryStringSyntax;
+import org.opends.server.schema.IntegerSyntax;
 
 /**
  * This class provides the interface to the Directory Server
@@ -136,6 +138,17 @@
   // The set of SSL cipher suites enabled or null for the default set.
   private final SortedSet<String> sslCipherSuites;
 
+  // Various schema element references.
+  private final AttributeType attrKeyID;
+  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;
+
 
   /**
    * Creates a new instance of this crypto manager object from a given
@@ -155,6 +168,26 @@
   public CryptoManager(CryptoManagerCfg cfg)
          throws ConfigException, InitializationException
   {
+    // Initialize various schema references.
+    attrKeyID = DirectoryServer.getAttributeType(
+         ConfigConstants.ATTR_CRYPTO_KEY_ID);
+    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);
+
     // TODO -- Get the crypto defaults from the configuration.
 
     // Preferred digest and validation.
@@ -273,13 +306,14 @@
    */
  public byte[] getInstanceKeyCertificate()
          throws CryptoManagerException {
-   final String DN_ADS_CERTIFICATE = ConfigConstants.ATTR_CERT_ALIAS
-           + "=" + ConfigConstants.ADS_CERTIFICATE_ALIAS + ","
+   final String DN_ADS_CERTIFICATE =
+        ConfigConstants.ATTR_CRYPTO_KEY_ID
+        + "=" + ConfigConstants.ADS_CERTIFICATE_ALIAS + ","
            + ConfigConstants.DN_TRUST_STORE_ROOT; // TODO: constant
    final String FILTER_OC_INSTANCE_KEY
-           = new StringBuilder("(objectclass=")
-                              .append(ConfigConstants.OC_INSTANCE_KEY)
-                              .append(")").toString();
+        = new StringBuilder("(objectclass=")
+        .append(ConfigConstants.OC_CRYPTO_INSTANCE_KEY)
+        .append(")").toString();
    final String ATTR_INSTANCE_KEY_CERTIFICATE_BINARY
            = "ds-cfg-public-key-certificate;binary";
    final LinkedHashSet<String> requestedAttributes
@@ -307,9 +341,9 @@
          final Entry e = searchOp.getSearchEntries().getFirst();
          /* attribute ds-cfg-public-key-certificate is a MUST in the
             schema */
-         final List<Attribute> attrs
-                 = e.getAttribute(DirectoryServer.getAttributeType(
-                               ConfigConstants.ATTR_ADS_CERTIFICATE));
+         final List<Attribute> attrs =
+            e.getAttribute(DirectoryServer.getAttributeType(
+                 ConfigConstants.ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE));
          final Attribute a = attrs.get(0);
          final AttributeValue v = a.getValues().iterator().next();
          certificate = v.getValueBytes();
@@ -1509,6 +1543,164 @@
   }
 
   /**
+   * Imports a cipher key entry from an entry in ADS.
+   *
+   * @param entry  The ADS cipher key entry to be imported.
+   *               The entry will be ignored if it does not have
+   *               the ds-cfg-cipher-key objectclass, or if the
+   *               key is already present.
+   *
+   * @throws CryptoManagerException
+   *               If the entry had the correct objectclass,
+   *               was not already present but could not
+   *               be imported.
+   */
+  public void importCipherKeyEntry(Entry entry)
+       throws CryptoManagerException
+  {
+    // Ignore the entry if it does not have the appropriate
+    // objectclass.
+    if (!entry.hasObjectClass(ocCipherKey)) return;
+
+    try
+    {
+      String keyID =
+           entry.getAttributeValue(attrKeyID,
+                                   DirectoryStringSyntax.DECODER);
+      int ivLengthBits =
+           entry.getAttributeValue(attrInitVectorLength,
+                                   IntegerSyntax.DECODER);
+      int keyLengthBits =
+           entry.getAttributeValue(attrKeyLength,
+                                   IntegerSyntax.DECODER);
+      String transformation =
+           entry.getAttributeValue(attrTransformation,
+                                   DirectoryStringSyntax.DECODER);
+      String compromisedTime =
+           entry.getAttributeValue(attrCompromisedTime,
+                                   DirectoryStringSyntax.DECODER);
+
+      ArrayList<String> symmetricKeys = new ArrayList<String>();
+      entry.getAttributeValues(attrSymmetricKey,
+                             DirectoryStringSyntax.DECODER,
+                             symmetricKeys);
+
+      // Find the symmetric key value that was wrapped using
+      // our instance key.
+      SecretKey secretKey = null;
+      for (String symmetricKey : symmetricKeys)
+      {
+        secretKey = decodeSymmetricKeyAttribute(symmetricKey);
+        if (secretKey != null) break;
+      }
+
+      if (secretKey == null)
+      {
+        // TODO: i18n
+        Message message =
+             Message.raw("Key entry %s contains no " +
+                  "symmetric key value that can be decoded " +
+                  "by this server",
+                         entry.getDN());
+        throw new CryptoManagerException(message);
+      }
+
+      boolean isCompromised = compromisedTime != null;
+
+      CipherKeyEntry.importCipherKeyEntry(this, keyID,
+                                          transformation,
+                                          secretKey, keyLengthBits,
+                                          ivLengthBits,
+                                          isCompromised);
+
+    }
+    catch (DirectoryException e)
+    {
+      // TODO: i18n
+      Message message =
+           Message.raw("Error decoding cipher key entry %s: %s",
+                       entry.getDN(), e.getMessage());
+      throw new CryptoManagerException(message, e);
+    }
+  }
+
+  /**
+   * Imports a mac key entry from an entry in ADS.
+   *
+   * @param entry  The ADS mac key entry to be imported. The
+   *               entry will be ignored if it does not have the
+   *               ds-cfg-mac-key objectclass, or if the key is
+   *               already present.
+   *
+   * @throws CryptoManagerException
+   *               If the entry had the correct objectclass,
+   *               was not already present but could not
+   *               be imported.
+   */
+  public void importMacKeyEntry(Entry entry)
+       throws CryptoManagerException
+  {
+    // Ignore the entry if it does not have the appropriate
+    // objectclass.
+    if (!entry.hasObjectClass(ocMacKey)) return;
+
+    try
+    {
+      String keyID =
+           entry.getAttributeValue(attrKeyID,
+                                   DirectoryStringSyntax.DECODER);
+      int keyLengthBits =
+           entry.getAttributeValue(attrKeyLength,
+                                   IntegerSyntax.DECODER);
+      String algorithm =
+           entry.getAttributeValue(attrMacAlgorithm,
+                                   DirectoryStringSyntax.DECODER);
+      String compromisedTime =
+           entry.getAttributeValue(attrCompromisedTime,
+                                   DirectoryStringSyntax.DECODER);
+
+      ArrayList<String> symmetricKeys = new ArrayList<String>();
+      entry.getAttributeValues(attrSymmetricKey,
+                             DirectoryStringSyntax.DECODER,
+                             symmetricKeys);
+
+      // Find the symmetric key value that was wrapped using our
+      // instance key.
+      SecretKey secretKey = null;
+      for (String symmetricKey : symmetricKeys)
+      {
+        secretKey = decodeSymmetricKeyAttribute(symmetricKey);
+        if (secretKey != null) break;
+      }
+
+      if (secretKey == null)
+      {
+        // TODO: i18n
+        Message message =
+             Message.raw("Key entry %s contains no " +
+                  "symmetric key value that can be decoded " +
+                  "by this server",
+                         entry.getDN());
+        throw new CryptoManagerException(message);
+      }
+
+      boolean isCompromised = compromisedTime != null;
+
+      MacKeyEntry.importMacKeyEntry(this, keyID, algorithm,
+                                    secretKey, keyLengthBits,
+                                    isCompromised);
+
+    }
+    catch (DirectoryException e)
+    {
+      Message message =
+           Message.raw("Error decoding mac key entry %s: %s",
+                       entry.getDN(), e.getMessage());
+      throw new CryptoManagerException(message, e);
+    }
+  }
+
+  /**
    * This class implements a utility interface to the unique
    * identifier corresponding to a cryptographic key. For each key
    * stored in an entry in ADS, the key identifier is the naming
@@ -1971,7 +2163,7 @@
             CryptoManager cryptoManager,
             final KeyEntryID keyID) {
       return cryptoManager.cipherKeyEntryCache.get(keyID);
-      /* TODO: Does ADS monitorying thread keep map updated with keys
+      /* TODO: Does ADS monitoring thread keep map updated with keys
          produced at other sites? If not, fetch from ADS and update
          map (assuming a legitimate key ID, the key should exist in
          ADS because this routine is called for decryption). */

--
Gitblit v1.10.0