mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Fabio Pistolesi
25.54.2016 b93c8bf6f5bb9560e9ba219eb6be1ea9bb12f3be
OPENDJ-3027 Delete all references to old keys when importing new ones via replication

Cipher and MAC keys are cached in memory, when a new key arrives with the same parameters as an existing key,
it should replace it, but the existing is still referenced in the internal cache, leading to non-determinism when looking for a key.
At the present time only one key should exist for a given algorithm/key length pair.
2 files modified
51 ■■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerImpl.java 14 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/test/java/org/opends/server/crypto/CryptoManagerTestCase.java 37 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerImpl.java
@@ -1640,7 +1640,12 @@
      }
      getCipher(keyEntry, Cipher.DECRYPT_MODE, iv);
      // Cache new entry.
      // Cache new entry, make sure it is the only one using the given transformation / key length.
      CipherKeyEntry oldKeyEntry = getKeyEntry(cryptoManager, transformation, secretKeyLengthBits);
      if (oldKeyEntry != null)
      {
        cryptoManager.cipherKeyEntryCache.remove(oldKeyEntry.getKeyID());
      }
      cryptoManager.cipherKeyEntryCache.put(keyEntry.getKeyID(), keyEntry);
      return keyEntry;
@@ -2097,7 +2102,12 @@
      // Validate new entry.
      getMacEngine(keyEntry);
      // Cache new entry.
      // Cache new entry, make sure it is the only one using the given transformation / key length.
      MacKeyEntry oldKeyEntry = getKeyEntry(cryptoManager, algorithm, secretKeyLengthBits);
      if (oldKeyEntry != null)
      {
        cryptoManager.macKeyEntryCache.remove(oldKeyEntry.getKeyID());
      }
      cryptoManager.macKeyEntryCache.put(keyEntry.getKeyID(),
              keyEntry);
opendj-server-legacy/src/test/java/org/opends/server/crypto/CryptoManagerTestCase.java
@@ -24,6 +24,7 @@
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import javax.crypto.Mac;
@@ -33,6 +34,7 @@
import org.opends.admin.ads.ADSContext;
import org.opends.server.TestCaseUtils;
import org.opends.server.core.DirectoryServer;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.protocols.internal.SearchRequest;
import org.opends.server.protocols.ldap.LDAPAttribute;
@@ -41,19 +43,24 @@
import org.opends.server.types.CryptoManager;
import org.opends.server.types.CryptoManagerException;
import org.forgerock.opendj.ldap.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
import org.opends.server.util.EmbeddedUtils;
import org.opends.server.util.StaticUtils;
import org.opends.server.util.TimeThread;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.assertj.core.api.Assertions.*;
import static org.forgerock.opendj.ldap.ModificationType.*;
import static org.opends.server.config.ConfigConstants.*;
import static org.opends.server.protocols.internal.InternalClientConnection.*;
import static org.opends.server.protocols.internal.Requests.*;
import static org.opends.server.types.Attributes.create;
import static org.testng.Assert.*;
/**
@@ -74,6 +81,36 @@
    TestCaseUtils.restartServer();
  }
  @Test(expectedExceptions = CryptoManagerException.class)
  public void testImportKeysReplacesExistingKeys()
      throws Exception {
    final CryptoManagerImpl cm = DirectoryServer.getCryptoManager();
    final int keyLength = 56;
    final String cipher = "DES/CFB/NoPadding";
    byte[] cipherText = cm.encrypt(cipher, keyLength, new byte[56]);
    Entry oldKey = getKeyForCipher(cipher, keyLength);
    // Force import by changing the keyID
    Modification mod = new Modification(REPLACE, create("ds-cfg-key-id", UUID.randomUUID().toString()));
    oldKey.applyModification(mod);
    cm.importCipherKeyEntry(oldKey);
    try
    {
      cm.decrypt(cipherText);
      Assert.fail("Was expecting a CryptoManager exception, the key should be invalid.");
    }
    finally
    {
    }
  }
  private Entry getKeyForCipher(String cipher, int keyLength) throws DirectoryException
  {
    SearchRequest request = newSearchRequest("cn=secret keys, cn=admin data", SearchScope.WHOLE_SUBTREE,
        "&(ds-cfg-cipher-transformation-name=" + cipher + ")(ds-cfg-key-length-bits=" + keyLength + ")");
    InternalClientConnection conn = getRootConnection();
    InternalSearchOperation search = conn.processSearch(request);
    return search.getSearchEntries().get(0);
  }
  @Test
  public void testGetInstanceKeyCertificate()