• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 Google Inc.
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.aead;
18 
19 import com.google.crypto.tink.AccessesPartialKey;
20 import com.google.crypto.tink.Aead;
21 import com.google.crypto.tink.KeyManager;
22 import com.google.crypto.tink.KeyTemplate;
23 import com.google.crypto.tink.KmsClients;
24 import com.google.crypto.tink.aead.internal.LegacyFullAead;
25 import com.google.crypto.tink.config.internal.TinkFipsUtil;
26 import com.google.crypto.tink.internal.KeyManagerRegistry;
27 import com.google.crypto.tink.internal.LegacyKeyManagerImpl;
28 import com.google.crypto.tink.internal.MutableKeyCreationRegistry;
29 import com.google.crypto.tink.internal.MutablePrimitiveRegistry;
30 import com.google.crypto.tink.internal.PrimitiveConstructor;
31 import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
32 import com.google.crypto.tink.proto.KmsAeadKey;
33 import java.security.GeneralSecurityException;
34 import javax.annotation.Nullable;
35 
36 /**
37  * This key manager produces new instances of {@code Aead} that forwards encrypt/decrypt requests to
38  * a key residing in a remote KMS.
39  */
40 public final class KmsAeadKeyManager {
create(LegacyKmsAeadKey key)41   private static Aead create(LegacyKmsAeadKey key) throws GeneralSecurityException {
42 
43     Aead rawAead =
44         KmsClients.get(key.getParameters().keyUri()).getAead(key.getParameters().keyUri());
45     return LegacyFullAead.create(rawAead, key.getOutputPrefix());
46   }
47 
48   private static final PrimitiveConstructor<LegacyKmsAeadKey, Aead>
49       LEGACY_KMS_AEAD_PRIMITIVE_CONSTRUCTOR =
50           PrimitiveConstructor.create(
51               KmsAeadKeyManager::create, LegacyKmsAeadKey.class, Aead.class);
52 
53   private static final KeyManager<Aead> legacyKeyManager =
54       LegacyKeyManagerImpl.create(
55           getKeyType(), Aead.class, KeyMaterialType.REMOTE, KmsAeadKey.parser());
56 
57   /**
58    * Creates a "new" key from a parameters object.
59    *
60    * <p>While this creates a new Key object, it doesn't actually create a new key. It simply creates
61    * the key object corresponding to this parameters object. Creating a new key would require to
62    * call an API in the KMS, which this method does not do.
63    *
64    * <p>The reason this method exists is that in the past, Tink did not provide an API for the user
65    * to create a key object by themselves. Instead, users had to always create a Key from a key
66    * template (which is now a Parameters object) via {@code KeysetHandle.generateNew(template);}. To
67    * support old usages, we need to register this creator.
68    */
69   @AccessesPartialKey
newKey( LegacyKmsAeadParameters parameters, @Nullable Integer idRequirement)70   private static LegacyKmsAeadKey newKey(
71       LegacyKmsAeadParameters parameters, @Nullable Integer idRequirement)
72       throws GeneralSecurityException {
73     return LegacyKmsAeadKey.create(parameters, idRequirement);
74   }
75 
76   @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration.
77   private static final MutableKeyCreationRegistry.KeyCreator<LegacyKmsAeadParameters> KEY_CREATOR =
78       KmsAeadKeyManager::newKey;
79 
getKeyType()80   static String getKeyType() {
81     return "type.googleapis.com/google.crypto.tink.KmsAeadKey";
82   }
83 
register(boolean newKeyAllowed)84   public static void register(boolean newKeyAllowed) throws GeneralSecurityException {
85     if (!TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_NOT_FIPS.isCompatible()) {
86       throw new GeneralSecurityException("Registering KMS AEAD is not supported in FIPS mode");
87     }
88     LegacyKmsAeadProtoSerialization.register();
89     MutablePrimitiveRegistry.globalInstance()
90         .registerPrimitiveConstructor(LEGACY_KMS_AEAD_PRIMITIVE_CONSTRUCTOR);
91     MutableKeyCreationRegistry.globalInstance().add(KEY_CREATOR, LegacyKmsAeadParameters.class);
92     KeyManagerRegistry.globalInstance().registerKeyManager(legacyKeyManager, newKeyAllowed);
93   }
94 
95   /**
96    * Returns a new {@link KeyTemplate} that can generate a {@link
97    * com.google.crypto.tink.proto.KmsAeadKey} whose key is pointing to {@code keyUri}. Keys
98    * generated by this key template use the RAW output prefix to make them compatible with the
99    * remote KMS' encrypt/decrypt operations.
100    *
101    * <p>It requires that a {@code KmsClient} that can handle {@code keyUri} is registered. Avoid
102    * registering it more than once.
103    *
104    * <p><b>Note: </b> Unlike other templates, when you call {@link KeysetHandle#generateNew} with
105    * this template, Tink does not generate new key material, but only creates a reference to the
106    * remote key.
107    *
108    * <p>It is often not necessary to use this function. Instead of registering a {@code KmsClient},
109    * and creating an {@code Aead} using {@code
110    * KeysetHandle.generateNew(KmsAeadKeyManager.createKeyTemplate(keyUri)).getPrimitive(RegistryConfiguration.get(),
111    * Aead.class)}, you can create the {@code Aead} directly using {@code kmsClient.getAead(kekUri)},
112    * without registering any {@code KmsClient}.
113    */
createKeyTemplate(String keyUri)114   public static KeyTemplate createKeyTemplate(String keyUri) {
115     try {
116       return KeyTemplate.createFrom(LegacyKmsAeadParameters.create(keyUri));
117     } catch (GeneralSecurityException e) {
118       // This should never happen: LegacyKmsAeadParameters shouldn't throw.
119       throw new IllegalArgumentException(e);
120     }
121   }
122 
KmsAeadKeyManager()123   private KmsAeadKeyManager() {}
124 }
125