From c00c2e9dc41f704704508e146dd56704b0c7ff50 Mon Sep 17 00:00:00 2001
From: david_page <david_page@localhost>
Date: Wed, 03 Oct 2007 19:29:29 +0000
Subject: [PATCH] Issue 466 (partial) add some secret key tests - disabled pending ADS export

---
 opends/tests/unit-tests-testng/src/server/org/opends/server/types/CryptoManagerTestCase.java |  110 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 104 insertions(+), 6 deletions(-)

diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/types/CryptoManagerTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/types/CryptoManagerTestCase.java
index 108ae12..3363648 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/types/CryptoManagerTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/types/CryptoManagerTestCase.java
@@ -31,10 +31,17 @@
 import static org.testng.Assert.assertTrue;
 
 import org.opends.server.TestCaseUtils;
+import org.opends.server.schema.DirectoryStringSyntax;
+import org.opends.server.schema.BinarySyntax;
+import org.opends.server.protocols.internal.InternalClientConnection;
+import org.opends.server.protocols.internal.InternalSearchOperation;
+import org.opends.server.config.ConfigConstants;
 import org.opends.server.util.StaticUtils;
+import org.opends.server.util.TimeThread;
 
 import org.opends.server.core.DirectoryServer;
 import org.opends.admin.ads.util.ConnectionUtils;
+import org.opends.admin.ads.ADSContext;
 import org.opends.messages.Message;
 
 import java.io.File;
@@ -45,6 +52,7 @@
 import java.util.List;
 import java.util.LinkedList;
 import java.util.Arrays;
+import java.util.LinkedHashSet;
 import java.lang.reflect.Method;
 import java.security.MessageDigest;
 
@@ -79,7 +87,8 @@
    */
   @AfterClass()
   public void CleanUp() throws Exception {
-
+    DirectoryServer.restart(this.getClass().getName(),
+            Message.raw("CryptoManager: clean-up internal key caches."));
   }
 
 
@@ -189,7 +198,7 @@
     // default (preferred) AES/CBC/PKCS5Padding 128bit key.
     paramList.add(new CipherParameters(null, null, null, 128, 128));
     // custom
-//    paramList.add(new CipherParameters("Blowfish", "CFB", "NoPadding", 192, 64));
+// TODO:  paramList.add(new CipherParameters("Blowfish", "CFB", "NoPadding", 192, 64));
     paramList.add(new CipherParameters("Blowfish", "CFB", "NoPadding", 128, 64));
     paramList.add(new CipherParameters("RC4", null, null, 104, 0));
     paramList.add(new CipherParameters("DES", "CFB", "NoPadding", 56, 56));
@@ -316,7 +325,6 @@
   @Test(enabled=false)
   public void testKeyPersistence()
         throws Exception {
-
     final CryptoManager cm = DirectoryServer.getCryptoManager();
     final String secretMessage = "zyxwvutsrqponmlkjihgfedcba";
 
@@ -334,7 +342,97 @@
     assertEquals((new String(plainText)), secretMessage);
   }
 
-  // TODO: mark a key compromised; ensure 1) subsequent encryption
-  // requests use a new key; 2) ciphertext produced using the compromised
-  // key can still be decrypted.
+
+  /**
+   Mark a key compromised; ensure 1) subsequent encryption requests use a new
+   key; 2) ciphertext produced using the compromised key can still be decrypted.
+
+   @throws Exception In case something exceptional happens.
+   */
+  @Test(enabled=false)
+  public void testCompromisedKey() throws Exception {
+    final CryptoManager cm = DirectoryServer.getCryptoManager();
+    final String secretMessage = "zyxwvutsrqponmlkjihgfedcba";
+    final String cipherTransformationName = "AES/CBC/PKCS5Padding";
+    final int cipherKeyLength = 128;
+
+    // Initial encryption ensures a cipher key entry is in ADS.
+    final byte[] cipherText = cm.encrypt(cipherTransformationName,
+            cipherKeyLength, secretMessage.getBytes());
+
+    // Retrieve all uncompromised cipher key entries corresponding to the
+    // specified transformation and key length. Mark each entry compromised.
+    final String baseDNStr // TODO: is this DN a constant?
+            = "cn=secret keys," + ADSContext.getAdministrationSuffixDN();
+    final DN baseDN = DN.decode(baseDNStr);
+    final String FILTER_OC_INSTANCE_KEY
+            = new StringBuilder("(objectclass=")
+            .append(ConfigConstants.OC_CRYPTO_CIPHER_KEY)
+            .append(")").toString();
+    final String FILTER_NOT_COMPROMISED = new StringBuilder("(!(")
+            .append(ConfigConstants.ATTR_CRYPTO_KEY_COMPROMISED_TIME)
+            .append("=*))").toString();
+    final String FILTER_CIPHER_TRANSFORMATION_NAME = new StringBuilder("(")
+            .append(ConfigConstants.ATTR_CRYPTO_CIPHER_TRANSFORMATION_NAME)
+            .append("=").append(cipherTransformationName)
+            .append(")").toString();
+    final String FILTER_CIPHER_KEY_LENGTH = new StringBuilder("(")
+            .append(ConfigConstants.ATTR_CRYPTO_KEY_LENGTH_BITS)
+            .append("=").append(String.valueOf(cipherKeyLength))
+            .append(")").toString();
+    final String searchFilter = new StringBuilder("(&")
+            .append(FILTER_OC_INSTANCE_KEY)
+            .append(FILTER_NOT_COMPROMISED)
+            .append(FILTER_CIPHER_TRANSFORMATION_NAME)
+            .append(FILTER_CIPHER_KEY_LENGTH)
+            .append(")").toString();
+    final LinkedHashSet<String> requestedAttributes
+            = new LinkedHashSet<String>();
+    requestedAttributes.add("dn");
+    final InternalClientConnection icc
+            = InternalClientConnection.getRootConnection();
+    InternalSearchOperation searchOp = icc.processSearch(
+            baseDN,
+            SearchScope.SINGLE_LEVEL,
+            DereferencePolicy.NEVER_DEREF_ALIASES,
+            /* size limit */ 0, /* time limit */ 0,
+            /* types only */ false,
+            SearchFilter.createFilterFromString(searchFilter),
+            requestedAttributes);
+
+    assertTrue(0 < searchOp.getSearchEntries().size());
+    String compromisedTime = TimeThread.getGeneralizedTime();
+    for (Entry e : searchOp.getSearchEntries()) {
+      TestCaseUtils.applyModifications(
+        "dn: " + e.getDN().toNormalizedString(),
+        "changetype: modify",
+        "replace: " + ConfigConstants.ATTR_CRYPTO_KEY_COMPROMISED_TIME,
+        ConfigConstants.ATTR_CRYPTO_KEY_COMPROMISED_TIME + ": "
+                + compromisedTime);
+    }
+
+    // Use the transformation and key length again. A new cipher key
+    // should be produced.
+    final byte[] cipherText2 = cm.encrypt(cipherTransformationName,
+            cipherKeyLength, secretMessage.getBytes());
+
+    // test for identical keys
+    try {
+      Method m = Arrays.class.getMethod("copyOfRange", (new byte[16]).getClass(),
+              Integer.TYPE, Integer.TYPE);
+      final byte[] keyID = (byte[])m.invoke(null, cipherText, 0, 16);
+      final byte[] keyID2 = (byte[])m.invoke(null, cipherText2, 0, 16);
+      assertTrue(! Arrays.equals(keyID, keyID2));
+    }
+    catch (NoSuchMethodException ex) {
+      // skip this test - requires at least Java 6
+    }
+
+    // confirm ciphertext produced using compromised key can still
+    // be decrypted.
+    final byte[] plainText = cm.decrypt(cipherText);
+    assertEquals((new String(plainText)), secretMessage);
+
+  }
+
 }

--
Gitblit v1.10.0