1 // Copyright 2017 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 //////////////////////////////////////////////////////////////////////////////// 16 17 package com.google.crypto.tink; 18 19 import com.google.crypto.tink.config.internal.TinkFipsUtil; 20 import com.google.crypto.tink.internal.KeyManagerRegistry; 21 import com.google.crypto.tink.internal.MutableParametersRegistry; 22 import com.google.crypto.tink.internal.MutablePrimitiveRegistry; 23 import com.google.crypto.tink.internal.PrimitiveSet; 24 import com.google.crypto.tink.prf.Prf; 25 import com.google.crypto.tink.proto.KeyData; 26 import com.google.protobuf.ByteString; 27 import com.google.protobuf.ExtensionRegistryLite; 28 import com.google.protobuf.InvalidProtocolBufferException; 29 import com.google.protobuf.MessageLite; 30 import java.security.GeneralSecurityException; 31 import java.util.Collections; 32 import java.util.HashSet; 33 import java.util.List; 34 import java.util.Locale; 35 import java.util.Set; 36 import java.util.concurrent.ConcurrentHashMap; 37 import java.util.concurrent.ConcurrentMap; 38 import java.util.logging.Logger; 39 import javax.annotation.Nullable; 40 41 /** 42 * A global container of key managers and catalogues. 43 * 44 * <p>Registry maps each supported key type to a corresponding {@link KeyManager} object, which 45 * "understands" the key type (i.e., the KeyManager can instantiate the primitive corresponding to 46 * given key, or can generate new keys of the supported key type). It holds also a {@link 47 * PrimitiveWrapper} for each supported primitive, so that it can wrap a set of primitives 48 * (corresponding to a keyset) into a single primitive. 49 * 50 * <p>Keeping KeyManagers for all primitives in a single Registry (rather than having a separate 51 * KeyManager per primitive) enables modular construction of compound primitives from "simple" ones, 52 * e.g., AES-CTR-HMAC AEAD encryption uses IND-CPA encryption and a MAC. 53 * 54 * <p>Registry is initialized at startup, and is later used to instantiate primitives for given keys 55 * or keysets. Note that regular users will usually not work directly with Registry, but rather via 56 * {@link TinkConfig} and {@link KeysetHandle#getPrimitive(Class)}-methods, which in the background 57 * register and query the Registry for specific KeyManagers and PrimitiveWrappers. Registry is 58 * public though, to enable configurations with custom catalogues, primitives or KeyManagers. 59 * 60 * <p>To initialize the Registry with all key managers: 61 * 62 * <pre>{@code 63 * TinkConfig.register(); 64 * }</pre> 65 * 66 * <p>Here's how to register only {@link Aead} key managers: 67 * 68 * <pre>{@code 69 * AeadConfig.register(); 70 * }</pre> 71 * 72 * <p>After the Registry has been initialized, one can use get a primitive as follows: 73 * 74 * <pre>{@code 75 * KeysetHandle keysetHandle = ...; 76 * Aead aead = keysetHandle.getPrimitive(RegistryConfiguration.get(), Aead.class); 77 * }</pre> 78 * 79 * @since 1.0.0 80 */ 81 public final class Registry { 82 private static final Logger logger = Logger.getLogger(Registry.class.getName()); 83 84 private static final ConcurrentMap<String, Catalogue<?>> catalogueMap = 85 new ConcurrentHashMap<>(); // name -> catalogue mapping 86 87 /** 88 * Resets the registry. 89 * 90 * <p>After reset the registry is empty, i.e. it contains no key managers. Thus one might need to 91 * call {@code XyzConfig.register()} to re-install the catalogues. 92 * 93 * <p>This method is intended for testing. 94 */ reset()95 static synchronized void reset() { 96 KeyManagerRegistry.resetGlobalInstanceTestOnly(); 97 MutablePrimitiveRegistry.resetGlobalInstanceTestOnly(); 98 catalogueMap.clear(); 99 } 100 101 /** 102 * Tries to add a catalogue, to enable custom configuration of key types and key managers. 103 * 104 * <p>Adding a custom catalogue should be a one-time operaton. There is an existing catalogue, 105 * throw exception if {@code catalogue} and the existing catalogue aren't instances of the same 106 * class, and do nothing if they are. 107 * 108 * @throws GeneralSecurityException if there's an existing catalogue and it is not an instance of 109 * the same class as {@code catalogue} 110 * @deprecated Catalogues are no longer supported. 111 */ 112 @Deprecated addCatalogue( String catalogueName, Catalogue<?> catalogue)113 public static synchronized void addCatalogue( 114 String catalogueName, Catalogue<?> catalogue) throws GeneralSecurityException { 115 if (catalogueName == null) { 116 throw new IllegalArgumentException("catalogueName must be non-null."); 117 } 118 if (catalogue == null) { 119 throw new IllegalArgumentException("catalogue must be non-null."); 120 } 121 if (catalogueMap.containsKey(catalogueName.toLowerCase(Locale.US))) { 122 Catalogue<?> existing = catalogueMap.get(catalogueName.toLowerCase(Locale.US)); 123 if (!catalogue.getClass().getName().equals(existing.getClass().getName())) { 124 logger.warning( 125 "Attempted overwrite of a catalogueName catalogue for name " + catalogueName); 126 throw new GeneralSecurityException( 127 "catalogue for name " + catalogueName + " has been already registered"); 128 } 129 } 130 catalogueMap.put(catalogueName.toLowerCase(Locale.US), catalogue); 131 } 132 133 /** 134 * Tries to get a catalogue associated with {@code catalogueName}. 135 * 136 * @deprecated Catalogues are no longer supported. 137 * @throws GeneralSecurityException if no catalogue is found 138 */ 139 @Deprecated getCatalogue(String catalogueName)140 public static Catalogue<?> getCatalogue(String catalogueName) 141 throws GeneralSecurityException { 142 if (catalogueName == null) { 143 throw new IllegalArgumentException("catalogueName must be non-null."); 144 } 145 Catalogue<?> catalogue = catalogueMap.get(catalogueName.toLowerCase(Locale.US)); 146 if (catalogue == null) { 147 String error = String.format("no catalogue found for %s. ", catalogueName); 148 if (catalogueName.toLowerCase(Locale.US).startsWith("tinkaead")) { 149 error += "Maybe call AeadConfig.register()."; 150 } 151 if (catalogueName.toLowerCase(Locale.US).startsWith("tinkdeterministicaead")) { 152 error += "Maybe call DeterministicAeadConfig.register()."; 153 } else if (catalogueName.toLowerCase(Locale.US).startsWith("tinkstreamingaead")) { 154 error += "Maybe call StreamingAeadConfig.register()."; 155 } else if (catalogueName.toLowerCase(Locale.US).startsWith("tinkhybriddecrypt") 156 || catalogueName.toLowerCase(Locale.US).startsWith("tinkhybridencrypt")) { 157 error += "Maybe call HybridConfig.register()."; 158 } else if (catalogueName.toLowerCase(Locale.US).startsWith("tinkmac")) { 159 error += "Maybe call MacConfig.register()."; 160 } else if (catalogueName.toLowerCase(Locale.US).startsWith("tinkpublickeysign") 161 || catalogueName.toLowerCase(Locale.US).startsWith("tinkpublickeyverify")) { 162 error += "Maybe call SignatureConfig.register()."; 163 } else if (catalogueName.toLowerCase(Locale.US).startsWith("tink")) { 164 error += "Maybe call TinkConfig.register()."; 165 } 166 throw new GeneralSecurityException(error); 167 } 168 return catalogue; 169 } 170 171 /** 172 * Tries to register {@code manager} for {@code manager.getKeyType()}. Users can generate new keys 173 * with this manager using the {@link Registry#newKey} methods. 174 * 175 * <p>If there is an existing key manager, throws an exception if {@code manager} and the existing 176 * key manager aren't instances of the same class, or the existing key manager could not create 177 * new keys. Otherwise registration succeeds. 178 * 179 * @throws GeneralSecurityException if there's an existing key manager is not an instance of the 180 * class of {@code manager}, or the registration tries to re-enable the generation of new 181 * keys. 182 */ registerKeyManager(final KeyManager<P> manager)183 public static synchronized <P> void registerKeyManager(final KeyManager<P> manager) 184 throws GeneralSecurityException { 185 registerKeyManager(manager, /* newKeyAllowed= */ true); 186 } 187 createAllowedPrimitives()188 private static Set<Class<?>> createAllowedPrimitives() { 189 HashSet<Class<?>> result = new HashSet<>(); 190 result.add(Aead.class); 191 result.add(DeterministicAead.class); 192 result.add(StreamingAead.class); 193 result.add(HybridEncrypt.class); 194 result.add(HybridDecrypt.class); 195 result.add(Mac.class); 196 result.add(Prf.class); 197 result.add(PublicKeySign.class); 198 result.add(PublicKeyVerify.class); 199 return result; 200 } 201 202 private static final Set<Class<?>> ALLOWED_PRIMITIVES = 203 Collections.unmodifiableSet(createAllowedPrimitives()); 204 205 /** 206 * Tries to register {@code manager} for {@code manager.getKeyType()}. If {@code newKeyAllowed} is 207 * true, users can generate new keys with this manager using the {@link Registry#newKey} methods. 208 * 209 * <p>If there is an existing key manager, throws an exception if {@code manager} and the existing 210 * key manager aren't instances of the same class, or if {@code newKeyAllowed} is true while the 211 * existing key manager could not create new keys. Otherwise registration succeeds. 212 * 213 * @throws GeneralSecurityException if there's an existing key manager is not an instance of the 214 * class of {@code manager}, or the registration tries to re-enable the generation of new 215 * keys. 216 */ registerKeyManager( final KeyManager<P> manager, boolean newKeyAllowed)217 public static synchronized <P> void registerKeyManager( 218 final KeyManager<P> manager, boolean newKeyAllowed) throws GeneralSecurityException { 219 if (manager == null) { 220 throw new IllegalArgumentException("key manager must be non-null."); 221 } 222 if (!ALLOWED_PRIMITIVES.contains(manager.getPrimitiveClass())) { 223 throw new GeneralSecurityException( 224 "Registration of key managers for class " 225 + manager.getPrimitiveClass() 226 + " has been disabled. Please file an issue on" 227 + " https://github.com/tink-crypto/tink-java"); 228 } 229 if (!TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_NOT_FIPS.isCompatible()) { 230 throw new GeneralSecurityException("Registering key managers is not supported in FIPS mode"); 231 } 232 KeyManagerRegistry.globalInstance().registerKeyManager(manager, newKeyAllowed); 233 } 234 235 /** 236 * Tries to register {@code manager} for the given {@code typeUrl}. Users can generate new keys 237 * with this manager using the {@link Registry#newKey} methods. 238 * 239 * <p>Does nothing if there's an existing key manager and it's an instance of the same class as 240 * {@code manager}. 241 * 242 * @throws GeneralSecurityException if there's an existing key manager and it is not an instance 243 * of the same class as {@code manager} 244 * @deprecated use {@link #registerKeyManager(KeyManager) registerKeyManager(KeyManager<P>)} 245 */ 246 @Deprecated registerKeyManager( String typeUrl, final KeyManager<P> manager)247 public static synchronized <P> void registerKeyManager( 248 String typeUrl, final KeyManager<P> manager) throws GeneralSecurityException { 249 registerKeyManager(typeUrl, manager, /* newKeyAllowed= */ true); 250 } 251 252 /** 253 * Tries to register {@code manager} for the given {@code typeUrl}. If {@code newKeyAllowed} is 254 * true, users can generate new keys with this manager using the {@link Registry#newKey} methods. 255 * 256 * <p>Does nothing if there's an existing key manager and it's an instance of the same class as 257 * {@code manager}. 258 * 259 * @throws GeneralSecurityException if there's an existing key manager and it is not an instance 260 * of the same class as {@code manager} 261 * @deprecated use {@link #registerKeyManager(KeyManager, boolean) 262 * registerKeyManager(KeyManager<P>, boolean)} 263 */ 264 @Deprecated registerKeyManager( String typeUrl, final KeyManager<P> manager, boolean newKeyAllowed)265 public static synchronized <P> void registerKeyManager( 266 String typeUrl, final KeyManager<P> manager, boolean newKeyAllowed) 267 throws GeneralSecurityException { 268 if (manager == null) { 269 throw new IllegalArgumentException("key manager must be non-null."); 270 } 271 if (!typeUrl.equals(manager.getKeyType())) { 272 throw new GeneralSecurityException("Manager does not support key type " + typeUrl + "."); 273 } 274 registerKeyManager(manager, newKeyAllowed); 275 } 276 277 /** 278 * Returns a {@link KeyManager} for the given {@code typeUrl} (if found). 279 * 280 * @deprecated KeyManagers should not be used directly. Use {@code newKeyData} or {@code 281 * getPrimitive} instead. 282 */ 283 @Deprecated getKeyManager(String typeUrl, Class<P> primitiveClass)284 public static <P> KeyManager<P> getKeyManager(String typeUrl, Class<P> primitiveClass) 285 throws GeneralSecurityException { 286 return KeyManagerRegistry.globalInstance().getKeyManager(typeUrl, primitiveClass); 287 } 288 289 /** 290 * Returns a {@link KeyManager} for the given {@code typeUrl} (if found). 291 * 292 * @deprecated KeyManagers should not be used directly. Use {@code newKeyData} or {@code 293 * getPrimitive} instead. 294 */ 295 @Deprecated getUntypedKeyManager(String typeUrl)296 public static KeyManager<?> getUntypedKeyManager(String typeUrl) 297 throws GeneralSecurityException { 298 return KeyManagerRegistry.globalInstance().getUntypedKeyManager(typeUrl); 299 } 300 301 /** 302 * Generates a new {@link KeyData} for the specified {@code template}. 303 * 304 * <p>It looks up a {@link KeyManager} identified by {@code keyTemplate.type_url}, and calls 305 * {@link KeyManager#newKeyData}. 306 * 307 * <p>This method should be used solely for key management. 308 * 309 * @return a new {@link KeyData} 310 * @deprecated Use {@code KeysetHandle.generateNew} with a Parameters object instead. To convert a 311 * proto KeyTemplate to a parameters one can use {@code 312 * TinkProtoParametersFormat.parse(t.toByteArray());} 313 */ 314 @Deprecated newKeyData( com.google.crypto.tink.proto.KeyTemplate keyTemplate)315 public static synchronized KeyData newKeyData( 316 com.google.crypto.tink.proto.KeyTemplate keyTemplate) throws GeneralSecurityException { 317 KeyManager<?> manager = 318 KeyManagerRegistry.globalInstance().getUntypedKeyManager(keyTemplate.getTypeUrl()); 319 if (KeyManagerRegistry.globalInstance().isNewKeyAllowed(keyTemplate.getTypeUrl())) { 320 return manager.newKeyData(keyTemplate.getValue()); 321 } else { 322 throw new GeneralSecurityException( 323 "newKey-operation not permitted for key type " + keyTemplate.getTypeUrl()); 324 } 325 } 326 327 /** 328 * Generates a new {@link KeyData} for the specified {@code template}. 329 * 330 * <p>It looks up a {@link KeyManager} identified by {@code keyTemplate.type_url}, and calls 331 * {@link KeyManager#newKeyData}. 332 * 333 * <p>This method should be used solely for key management. 334 * 335 * @return a new {@link KeyData} 336 * @deprecated Use {@code KeysetHandle.generateNew(keyTemplate.toParameters())} instead and use 337 * the Keyset Handle API. 338 */ 339 @Deprecated newKeyData( com.google.crypto.tink.KeyTemplate keyTemplate)340 public static synchronized KeyData newKeyData( 341 com.google.crypto.tink.KeyTemplate keyTemplate) throws GeneralSecurityException { 342 byte[] serializedKeyTemplate = TinkProtoParametersFormat.serialize(keyTemplate.toParameters()); 343 try { 344 return newKeyData( 345 com.google.crypto.tink.proto.KeyTemplate.parseFrom( 346 serializedKeyTemplate, ExtensionRegistryLite.getEmptyRegistry())); 347 } catch (InvalidProtocolBufferException e) { 348 throw new GeneralSecurityException("Failed to parse serialized parameters", e); 349 } 350 } 351 352 /** 353 * Generates a new key for the specified {@code keyTemplate}. 354 * 355 * <p>It looks up a {@link KeyManager} identified by {@code keyTemplate.type_url}, and calls 356 * {@link KeyManager#newKey} with {@code keyTemplate} as the parameter. 357 * 358 * @return a new key 359 * @deprecated Use {@code newKeyData} instead. 360 */ 361 @Deprecated newKey( com.google.crypto.tink.proto.KeyTemplate keyTemplate)362 public static synchronized MessageLite newKey( 363 com.google.crypto.tink.proto.KeyTemplate keyTemplate) throws GeneralSecurityException { 364 KeyManager<?> manager = getUntypedKeyManager(keyTemplate.getTypeUrl()); 365 if (KeyManagerRegistry.globalInstance().isNewKeyAllowed(keyTemplate.getTypeUrl())) { 366 return manager.newKey(keyTemplate.getValue()); 367 } else { 368 throw new GeneralSecurityException( 369 "newKey-operation not permitted for key type " + keyTemplate.getTypeUrl()); 370 } 371 } 372 373 /** 374 * Generates a new key for the specified {@code format}. 375 * 376 * <p>It looks up a {@link KeyManager} identified by {@code keyTemplate.type_url}, and calls 377 * {@link KeyManager#newKey} with {@code format} as the parameter. 378 * 379 * @return a new key 380 * @deprecated Use {@code newKeyData} instead. 381 */ 382 @Deprecated newKey(String typeUrl, MessageLite format)383 public static synchronized MessageLite newKey(String typeUrl, MessageLite format) 384 throws GeneralSecurityException { 385 KeyManager<?> manager = getUntypedKeyManager(typeUrl); 386 if (KeyManagerRegistry.globalInstance().isNewKeyAllowed(typeUrl)) { 387 return manager.newKey(format); 388 } else { 389 throw new GeneralSecurityException("newKey-operation not permitted for key type " + typeUrl); 390 } 391 } 392 393 /** 394 * Extracts the public key data from the private key given in {@code serializedPrivateKey}. 395 * 396 * <p>It looks up a {@link PrivateKeyManager} identified by {@code typeUrl}, and calls {@link 397 * PrivateKeyManager#getPublicKeyData} with {@code serializedPrivateKey} as the parameter. 398 * 399 * @return the public key of the corresponding private key 400 * @deprecated Instead, users should have their keys in a {@link KeysetHandle} and call {@code 401 * keysetHandle.getPublicKeysetHandle}. 402 */ 403 @Deprecated getPublicKeyData(String typeUrl, ByteString serializedPrivateKey)404 public static KeyData getPublicKeyData(String typeUrl, ByteString serializedPrivateKey) 405 throws GeneralSecurityException { 406 KeyManager<?> manager = getUntypedKeyManager(typeUrl); 407 if (!(manager instanceof PrivateKeyManager)) { 408 throw new GeneralSecurityException( 409 "manager for key type " + typeUrl + " is not a PrivateKeyManager"); 410 } 411 return ((PrivateKeyManager) manager).getPublicKeyData(serializedPrivateKey); 412 } 413 414 /** 415 * Creates a new primitive for the key given in {@code key}. 416 * 417 * <p>It looks up a {@link KeyManager} identified by {@code type_url}, and calls {@link 418 * KeyManager#getPrimitive} with {@code key} as the parameter. 419 * 420 * @return a new primitive 421 * @deprecated Use {@code getPrimitive(typeUrl, serializedKey, Primitive.class} instead. 422 */ 423 @Deprecated getPrimitive( String typeUrl, MessageLite key, Class<P> primitiveClass)424 public static <P> P getPrimitive( 425 String typeUrl, MessageLite key, Class<P> primitiveClass) throws GeneralSecurityException { 426 KeyManager<P> manager = 427 KeyManagerRegistry.globalInstance().getKeyManager(typeUrl, primitiveClass); 428 return manager.getPrimitive(key.toByteString()); 429 } 430 431 /** 432 * Creates a new primitive for the key given in {@code serializedKey}. 433 * 434 * <p>It looks up a {@link KeyManager} identified by {@code type_url}, and calls {@link 435 * KeyManager#getPrimitive} with {@code serialized} as the parameter. 436 * 437 * @return a new primitive 438 */ getPrimitive( String typeUrl, ByteString serializedKey, Class<P> primitiveClass)439 public static <P> P getPrimitive( 440 String typeUrl, ByteString serializedKey, Class<P> primitiveClass) 441 throws GeneralSecurityException { 442 KeyManager<P> manager = 443 KeyManagerRegistry.globalInstance().getKeyManager(typeUrl, primitiveClass); 444 return manager.getPrimitive(serializedKey); 445 } 446 447 /** 448 * Creates a new primitive for the key given in {@code serializedKey}. 449 * 450 * <p>It looks up a {@link KeyManager} identified by {@code type_url}, and calls {@link 451 * KeyManager#getPrimitive} with {@code serialized} as the parameter. 452 * 453 * @return a new primitive 454 */ getPrimitive(String typeUrl, byte[] serializedKey, Class<P> primitiveClass)455 public static <P> P getPrimitive(String typeUrl, byte[] serializedKey, Class<P> primitiveClass) 456 throws GeneralSecurityException { 457 return getPrimitive(typeUrl, ByteString.copyFrom(serializedKey), primitiveClass); 458 } 459 460 /** 461 * Creates a new primitive for the key given in {@code keyData}. 462 * 463 * <p>It looks up a {@link KeyManager} identified by {@code keyData.type_url}, and calls {@link 464 * KeyManager#getPrimitive} with {@code keyData.value} as the parameter. 465 * 466 * @return a new primitive 467 */ getPrimitive(KeyData keyData, Class<P> primitiveClass)468 public static <P> P getPrimitive(KeyData keyData, Class<P> primitiveClass) 469 throws GeneralSecurityException { 470 return getPrimitive(keyData.getTypeUrl(), keyData.getValue(), primitiveClass); 471 } 472 getFullPrimitive(KeyT key, Class<P> primitiveClass)473 static <KeyT extends Key, P> P getFullPrimitive(KeyT key, Class<P> primitiveClass) 474 throws GeneralSecurityException { 475 return MutablePrimitiveRegistry.globalInstance().getPrimitive(key, primitiveClass); 476 } 477 478 /** 479 * Looks up the globally registered PrimitiveWrapper for this primitive and wraps the given 480 * PrimitiveSet with it. 481 */ wrap(PrimitiveSet<B> primitiveSet, Class<P> clazz)482 public static <B, P> P wrap(PrimitiveSet<B> primitiveSet, Class<P> clazz) 483 throws GeneralSecurityException { 484 return MutablePrimitiveRegistry.globalInstance().wrap(primitiveSet, clazz); 485 } 486 wrap(PrimitiveSet<P> primitiveSet)487 public static <P> P wrap(PrimitiveSet<P> primitiveSet) 488 throws GeneralSecurityException { 489 return wrap(primitiveSet, primitiveSet.getPrimitiveClass()); 490 } 491 492 /** 493 * Returns an immutable list of key template names supported by registered key managers that are 494 * allowed to generate new keys. 495 * 496 * @since 1.6.0 497 */ keyTemplates()498 public static synchronized List<String> keyTemplates() { 499 return MutableParametersRegistry.globalInstance().getNames(); 500 } 501 502 /** 503 * Returns the input primitive required when creating a {@code wrappedPrimitive}. 504 * 505 * <p>This returns the primitive class of the objects required when we want to create a wrapped 506 * primitive of type {@code wrappedPrimitive}. Returns {@code null} if no wrapper for this 507 * primitive has been registered. 508 */ 509 @Nullable getInputPrimitive(Class<?> wrappedPrimitive)510 public static Class<?> getInputPrimitive(Class<?> wrappedPrimitive) { 511 try { 512 return MutablePrimitiveRegistry.globalInstance().getInputPrimitiveClass(wrappedPrimitive); 513 } catch (GeneralSecurityException e) { 514 return null; 515 } 516 } 517 518 /** 519 * Tries to enable the FIPS restrictions if the Registry is empty. 520 * 521 * @throws GeneralSecurityException if any key manager has already been registered. 522 */ restrictToFipsIfEmpty()523 public static synchronized void restrictToFipsIfEmpty() throws GeneralSecurityException { 524 KeyManagerRegistry.globalInstance().restrictToFipsIfEmptyAndGlobalInstance(); 525 } 526 Registry()527 private Registry() {} 528 } 529