From 1a2cdfb5cf5f89348e8fee7ceeaa699d4aa54cea Mon Sep 17 00:00:00 2001
From: Fabio Pistolesi <fabio.pistolesi@forgerock.com>
Date: Thu, 21 Apr 2016 15:17:15 +0000
Subject: [PATCH] OPENDJ-2616 Support protection of pluggable backend data at rest

---
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryIDSet.java |   66 +++++++++++++++++++++++++++++++++
 1 files changed, 66 insertions(+), 0 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryIDSet.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryIDSet.java
index 62f7ff1..3066154 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryIDSet.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryIDSet.java
@@ -19,6 +19,7 @@
 import static org.forgerock.util.Reject.*;
 import static org.opends.server.util.StaticUtils.*;
 
+import java.security.GeneralSecurityException;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
@@ -31,6 +32,8 @@
 import org.forgerock.util.Reject;
 
 import com.forgerock.opendj.util.Iterators;
+import org.opends.server.types.CryptoManagerException;
+import org.opends.server.crypto.CryptoSuite;
 
 /**
  * Represents a set of Entry IDs. It can represent a set where the IDs are not defined, for example when the index entry
@@ -535,6 +538,69 @@
     }
   }
 
+  /**
+   * Decorate a V1 or V2 codec with encryption. When writing EntryIDSets to disk,
+   * prepend two bytes, {0, 1} to mark them as encrypted.
+   * The first is tag zero (unused in other encodings), followed by a byte
+   * indicating version 1 of encryption.
+   */
+  static class EntryIDSetCodecV3 implements EntryIDSetCodec
+  {
+    private static final byte CODEC_V3_TAG = 0x00;
+    private static final byte CODEC_V3_VERSION = 0x01;
+    private final EntryIDSetCodec delegate;
+    private final CryptoSuite cryptoSuite;
+    EntryIDSetCodecV3(EntryIDSetCodec delegate, CryptoSuite cryptoSuite)
+    {
+      this.delegate = delegate;
+      this.cryptoSuite = cryptoSuite;
+    }
+
+    @Override
+    public ByteString encode(EntryIDSet idSet)
+    {
+      ByteString encodedValue = delegate.encode(idSet);
+      ByteStringBuilder builder = new ByteStringBuilder(encodedValue.length());
+      builder.appendByte(CODEC_V3_TAG);
+      builder.appendByte(CODEC_V3_VERSION);
+      try
+      {
+        builder.appendBytes(cryptoSuite.encrypt(encodedValue.toByteArray()));
+        return builder.toByteString();
+      }
+      catch (GeneralSecurityException | CryptoManagerException e)
+      {
+        // Only if the underlying crypto provider has serious problems.
+        throw new IllegalStateException();
+      }
+    }
+
+    @Override
+    public EntryIDSet decode(ByteSequence key, ByteString value)
+    {
+      checkNotNull(value, "value must not be null");
+      if (value.byteAt(0) == CODEC_V3_TAG)
+      {
+        try
+        {
+          return delegate.decode(key,
+              ByteString.wrap(cryptoSuite.decrypt(value.subSequence(2, value.length()).toByteArray())));
+        }
+        catch (GeneralSecurityException | CryptoManagerException e)
+        {
+          // Only if data is completely corrupted.
+          throw new IllegalStateException();
+        }
+      }
+      return delegate.decode(key, value);
+    }
+  }
+
+  static EntryIDSetCodec newEntryIDSetCodecV3(EntryIDSetCodec codec, CryptoSuite cs)
+  {
+    return new EntryIDSetCodecV3(codec, cs);
+  }
+
   static EntryIDSet newUndefinedSet()
   {
     return newUndefinedSetWithKey(NO_KEY);

--
Gitblit v1.10.0