Move the global instance of the KeyManagerRegistry into the KeyManagerRegistry itself.
This has the advantage that we can add methods to the KeyManagerRegistry which can then be accessed internally for the global registry, but we don't need to expose them. I want to do this for registering FIPS compatible key managers.
PiperOrigin-RevId: 585023673
Change-Id: Ifbeed5cbd1c9063054aca7cb35d17398f214e452
diff --git a/src/main/java/com/google/crypto/tink/Registry.java b/src/main/java/com/google/crypto/tink/Registry.java
index 577f28f..89b2374 100644
--- a/src/main/java/com/google/crypto/tink/Registry.java
+++ b/src/main/java/com/google/crypto/tink/Registry.java
@@ -36,7 +36,6 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Logger;
import javax.annotation.Nullable;
@@ -83,9 +82,6 @@
public final class Registry {
private static final Logger logger = Logger.getLogger(Registry.class.getName());
- private static final AtomicReference<KeyManagerRegistry> keyManagerRegistry =
- new AtomicReference<>(new KeyManagerRegistry());
-
private static final ConcurrentMap<String, Catalogue<?>> catalogueMap =
new ConcurrentHashMap<>(); // name -> catalogue mapping
@@ -98,7 +94,7 @@
* <p>This method is intended for testing.
*/
static synchronized void reset() {
- keyManagerRegistry.set(new KeyManagerRegistry());
+ KeyManagerRegistry.resetGlobalInstanceTestOnly();
MutablePrimitiveRegistry.resetGlobalInstanceTestOnly();
catalogueMap.clear();
}
@@ -231,13 +227,10 @@
+ " has been disabled. Please file an issue on"
+ " https://github.com/tink-crypto/tink-java");
}
- KeyManagerRegistry newKeyManagerRegistry = new KeyManagerRegistry(keyManagerRegistry.get());
- newKeyManagerRegistry.registerKeyManager(manager, newKeyAllowed);
-
if (!TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_NOT_FIPS.isCompatible()) {
throw new GeneralSecurityException("Registering key managers is not supported in FIPS mode");
}
- keyManagerRegistry.set(newKeyManagerRegistry);
+ KeyManagerRegistry.globalInstance().registerKeyManager(manager, newKeyAllowed);
}
/**
@@ -264,9 +257,7 @@
if (manager == null) {
throw new IllegalArgumentException("key manager must be non-null.");
}
- KeyManagerRegistry newKeyManagerRegistry = new KeyManagerRegistry(keyManagerRegistry.get());
- newKeyManagerRegistry.registerKeyManager(manager, newKeyAllowed);
- keyManagerRegistry.set(newKeyManagerRegistry);
+ KeyManagerRegistry.globalInstance().registerKeyManager(manager, newKeyAllowed);
}
/**
@@ -336,11 +327,8 @@
if (privateKeyTypeManager == null || publicKeyTypeManager == null) {
throw new IllegalArgumentException("given key managers must be non-null.");
}
- KeyManagerRegistry newKeyManagerRegistry = new KeyManagerRegistry(keyManagerRegistry.get());
- newKeyManagerRegistry.registerAsymmetricKeyManagers(
- privateKeyTypeManager, publicKeyTypeManager, newKeyAllowed);
-
- keyManagerRegistry.set(newKeyManagerRegistry);
+ KeyManagerRegistry.globalInstance()
+ .registerAsymmetricKeyManagers(privateKeyTypeManager, publicKeyTypeManager, newKeyAllowed);
}
/**
@@ -369,7 +357,7 @@
@Deprecated
public static <P> KeyManager<P> getKeyManager(String typeUrl, Class<P> primitiveClass)
throws GeneralSecurityException {
- return keyManagerRegistry.get().getKeyManager(typeUrl, primitiveClass);
+ return KeyManagerRegistry.globalInstance().getKeyManager(typeUrl, primitiveClass);
}
/**
@@ -381,7 +369,7 @@
@Deprecated
public static KeyManager<?> getUntypedKeyManager(String typeUrl)
throws GeneralSecurityException {
- return keyManagerRegistry.get().getUntypedKeyManager(typeUrl);
+ return KeyManagerRegistry.globalInstance().getUntypedKeyManager(typeUrl);
}
/**
@@ -396,8 +384,9 @@
*/
public static synchronized KeyData newKeyData(
com.google.crypto.tink.proto.KeyTemplate keyTemplate) throws GeneralSecurityException {
- KeyManager<?> manager = keyManagerRegistry.get().getUntypedKeyManager(keyTemplate.getTypeUrl());
- if (keyManagerRegistry.get().isNewKeyAllowed(keyTemplate.getTypeUrl())) {
+ KeyManager<?> manager =
+ KeyManagerRegistry.globalInstance().getUntypedKeyManager(keyTemplate.getTypeUrl());
+ if (KeyManagerRegistry.globalInstance().isNewKeyAllowed(keyTemplate.getTypeUrl())) {
return manager.newKeyData(keyTemplate.getValue());
} else {
throw new GeneralSecurityException(
@@ -440,7 +429,7 @@
public static synchronized MessageLite newKey(
com.google.crypto.tink.proto.KeyTemplate keyTemplate) throws GeneralSecurityException {
KeyManager<?> manager = getUntypedKeyManager(keyTemplate.getTypeUrl());
- if (keyManagerRegistry.get().isNewKeyAllowed(keyTemplate.getTypeUrl())) {
+ if (KeyManagerRegistry.globalInstance().isNewKeyAllowed(keyTemplate.getTypeUrl())) {
return manager.newKey(keyTemplate.getValue());
} else {
throw new GeneralSecurityException(
@@ -461,7 +450,7 @@
public static synchronized MessageLite newKey(String typeUrl, MessageLite format)
throws GeneralSecurityException {
KeyManager<?> manager = getUntypedKeyManager(typeUrl);
- if (keyManagerRegistry.get().isNewKeyAllowed(typeUrl)) {
+ if (KeyManagerRegistry.globalInstance().isNewKeyAllowed(typeUrl)) {
return manager.newKey(format);
} else {
throw new GeneralSecurityException("newKey-operation not permitted for key type " + typeUrl);
@@ -498,7 +487,8 @@
@Deprecated
public static <P> P getPrimitive(
String typeUrl, MessageLite key, Class<P> primitiveClass) throws GeneralSecurityException {
- KeyManager<P> manager = keyManagerRegistry.get().getKeyManager(typeUrl, primitiveClass);
+ KeyManager<P> manager =
+ KeyManagerRegistry.globalInstance().getKeyManager(typeUrl, primitiveClass);
return manager.getPrimitive(key.toByteString());
}
@@ -513,7 +503,8 @@
public static <P> P getPrimitive(
String typeUrl, ByteString serializedKey, Class<P> primitiveClass)
throws GeneralSecurityException {
- KeyManager<P> manager = keyManagerRegistry.get().getKeyManager(typeUrl, primitiveClass);
+ KeyManager<P> manager =
+ KeyManagerRegistry.globalInstance().getKeyManager(typeUrl, primitiveClass);
return manager.getPrimitive(serializedKey);
}
@@ -594,15 +585,7 @@
* @throws GeneralSecurityException if any key manager has already been registered.
*/
public static synchronized void restrictToFipsIfEmpty() throws GeneralSecurityException {
- // If we are already using FIPS mode, do nothing.
- if (TinkFipsUtil.useOnlyFips()) {
- return;
- }
- if (keyManagerRegistry.get().isEmpty()) {
- TinkFipsUtil.setFipsRestricted();
- return;
- }
- throw new GeneralSecurityException("Could not enable FIPS mode as Registry is not empty.");
+ KeyManagerRegistry.globalInstance().restrictToFipsIfEmptyAndGlobalInstance();
}
private Registry() {}
diff --git a/src/main/java/com/google/crypto/tink/internal/BUILD.bazel b/src/main/java/com/google/crypto/tink/internal/BUILD.bazel
index e368ef0..9879655 100644
--- a/src/main/java/com/google/crypto/tink/internal/BUILD.bazel
+++ b/src/main/java/com/google/crypto/tink/internal/BUILD.bazel
@@ -876,7 +876,6 @@
":private_key_type_manager-android",
"//src/main/java/com/google/crypto/tink:key_manager-android",
"//src/main/java/com/google/crypto/tink/config/internal:tink_fips_util-android",
- "@maven//:com_google_code_findbugs_jsr305",
"@maven//:com_google_protobuf_protobuf_javalite",
],
)
@@ -917,7 +916,6 @@
":private_key_type_manager",
"//src/main/java/com/google/crypto/tink:key_manager",
"//src/main/java/com/google/crypto/tink/config/internal:tink_fips_util",
- "@maven//:com_google_code_findbugs_jsr305",
"@maven//:com_google_protobuf_protobuf_java",
],
)
diff --git a/src/main/java/com/google/crypto/tink/internal/KeyManagerRegistry.java b/src/main/java/com/google/crypto/tink/internal/KeyManagerRegistry.java
index fa38105..edfa2e9 100644
--- a/src/main/java/com/google/crypto/tink/internal/KeyManagerRegistry.java
+++ b/src/main/java/com/google/crypto/tink/internal/KeyManagerRegistry.java
@@ -41,9 +41,22 @@
private static final Logger logger = Logger.getLogger(KeyManagerRegistry.class.getName());
// A map from the TypeUrl to the KeyManagerContainer.
- private final ConcurrentMap<String, KeyManagerContainer> keyManagerMap;
+ private ConcurrentMap<String, KeyManagerContainer> keyManagerMap;
// typeUrl -> newKeyAllowed mapping
- private final ConcurrentMap<String, Boolean> newKeyAllowedMap;
+ private ConcurrentMap<String, Boolean> newKeyAllowedMap;
+
+ private static final KeyManagerRegistry GLOBAL_INSTANCE = new KeyManagerRegistry();
+
+ /** Returns the global instance. */
+ public static KeyManagerRegistry globalInstance() {
+ return GLOBAL_INSTANCE;
+ }
+
+ /** Resets the global instance. Should only be used in tests. Not thread safe. */
+ public static void resetGlobalInstanceTestOnly() {
+ GLOBAL_INSTANCE.keyManagerMap = new ConcurrentHashMap<>();
+ GLOBAL_INSTANCE.newKeyAllowedMap = new ConcurrentHashMap<>();
+ }
public KeyManagerRegistry(KeyManagerRegistry original) {
keyManagerMap = new ConcurrentHashMap<>(original.keyManagerMap);
@@ -344,4 +357,27 @@
public boolean isEmpty() {
return keyManagerMap.isEmpty();
}
+
+ /**
+ * Restricts Tink to FIPS if this is the global instance.
+ *
+ * <p>We make this a member method (instead of a static one which gets the global instance)
+ * because the call to "useOnlyFips" needs to happen under the same mutex lock which protects the
+ * registerKeyManager methods.
+ */
+ public synchronized void restrictToFipsIfEmptyAndGlobalInstance()
+ throws GeneralSecurityException {
+ if (this != globalInstance()) {
+ throw new GeneralSecurityException("Only the global instance can be restricted to FIPS.");
+ }
+ // If we are already using FIPS mode, do nothing.
+ if (TinkFipsUtil.useOnlyFips()) {
+ return;
+ }
+
+ if (!isEmpty()) {
+ throw new GeneralSecurityException("Could not enable FIPS mode as Registry is not empty.");
+ }
+ TinkFipsUtil.setFipsRestricted();
+ }
}