• 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.Parameters;
25 import com.google.crypto.tink.aead.internal.LegacyFullAead;
26 import com.google.crypto.tink.config.internal.TinkFipsUtil;
27 import com.google.crypto.tink.internal.KeyManagerRegistry;
28 import com.google.crypto.tink.internal.LegacyKeyManagerImpl;
29 import com.google.crypto.tink.internal.MutableKeyCreationRegistry;
30 import com.google.crypto.tink.internal.MutablePrimitiveRegistry;
31 import com.google.crypto.tink.internal.PrimitiveConstructor;
32 import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
33 import java.security.GeneralSecurityException;
34 import javax.annotation.Nullable;
35 
36 /**
37  * This key manager generates new {@code KmsEnvelopeAeadKey} keys and produces new instances of
38  * {@code KmsEnvelopeAead}.
39  */
40 public class KmsEnvelopeAeadKeyManager {
41   private static final String TYPE_URL =
42       "type.googleapis.com/google.crypto.tink.KmsEnvelopeAeadKey";
43 
44   private static final KeyManager<Aead> legacyKeyManager =
45       LegacyKeyManagerImpl.create(
46           getKeyType(),
47           Aead.class,
48           KeyMaterialType.SYMMETRIC,
49           com.google.crypto.tink.proto.KmsEnvelopeAeadKey.parser());
50 
51   /**
52    * Creates a "new" key from a parameters.
53    *
54    * <p>While this creates a new Key object, it doesn't actually create a new key. It simply creates
55    * the key object corresponding to this parameters object. Creating a new key would require to
56    * call an API in the KMS, which this method does not do.
57    *
58    * <p>The reason this method exists is that in the past, Tink did not provide an API for the user
59    * to create a key object by themselves. Instead, users had to always create a Key from a key
60    * template (which is now a Parameters object) via {@code KeysetHandle.generateNew(template);}. To
61    * support old usages, we need to register this creator.
62    */
63   @AccessesPartialKey
newKey( LegacyKmsEnvelopeAeadParameters parameters, @Nullable Integer idRequirement)64   private static LegacyKmsEnvelopeAeadKey newKey(
65       LegacyKmsEnvelopeAeadParameters parameters, @Nullable Integer idRequirement)
66       throws GeneralSecurityException {
67     return LegacyKmsEnvelopeAeadKey.create(parameters, idRequirement);
68   }
69 
70   @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration.
71   private static final MutableKeyCreationRegistry.KeyCreator<LegacyKmsEnvelopeAeadParameters>
72       KEY_CREATOR = KmsEnvelopeAeadKeyManager::newKey;
73 
74   @AccessesPartialKey
create(LegacyKmsEnvelopeAeadKey key)75   private static Aead create(LegacyKmsEnvelopeAeadKey key) throws GeneralSecurityException {
76     String kekUri = key.getParameters().getKekUri();
77     Aead rawAead =
78         KmsEnvelopeAead.create(
79             key.getParameters().getDekParametersForNewKeys(),
80             KmsClients.get(kekUri).getAead(kekUri));
81     return LegacyFullAead.create(rawAead, key.getOutputPrefix());
82   }
83 
84   private static final PrimitiveConstructor<LegacyKmsEnvelopeAeadKey, Aead>
85       LEGACY_KMS_ENVELOPE_AEAD_PRIMITIVE_CONSTRUCTOR =
86           PrimitiveConstructor.create(
87               KmsEnvelopeAeadKeyManager::create, LegacyKmsEnvelopeAeadKey.class, Aead.class);
88 
getKeyType()89   static String getKeyType() {
90     return TYPE_URL;
91   }
92 
makeRawAesGcm(AesGcmParameters parameters)93   private static AeadParameters makeRawAesGcm(AesGcmParameters parameters)
94       throws GeneralSecurityException {
95     return AesGcmParameters.builder()
96         .setIvSizeBytes(parameters.getIvSizeBytes())
97         .setKeySizeBytes(parameters.getKeySizeBytes())
98         .setTagSizeBytes(parameters.getTagSizeBytes())
99         .setVariant(AesGcmParameters.Variant.NO_PREFIX)
100         .build();
101   }
102 
makeRawChaCha20Poly1305()103   private static AeadParameters makeRawChaCha20Poly1305() {
104     return ChaCha20Poly1305Parameters.create(ChaCha20Poly1305Parameters.Variant.NO_PREFIX);
105   }
106 
makeRawXChaCha20Poly1305()107   private static AeadParameters makeRawXChaCha20Poly1305() {
108     return XChaCha20Poly1305Parameters.create(XChaCha20Poly1305Parameters.Variant.NO_PREFIX);
109   }
110 
makeRawAesCtrHmacAead(AesCtrHmacAeadParameters parameters)111   private static AeadParameters makeRawAesCtrHmacAead(AesCtrHmacAeadParameters parameters)
112       throws GeneralSecurityException {
113     return AesCtrHmacAeadParameters.builder()
114         .setAesKeySizeBytes(parameters.getAesKeySizeBytes())
115         .setHmacKeySizeBytes(parameters.getHmacKeySizeBytes())
116         .setTagSizeBytes(parameters.getTagSizeBytes())
117         .setIvSizeBytes(parameters.getIvSizeBytes())
118         .setHashType(parameters.getHashType())
119         .setVariant(AesCtrHmacAeadParameters.Variant.NO_PREFIX)
120         .build();
121   }
122 
makeRawAesEax(AesEaxParameters parameters)123   private static AeadParameters makeRawAesEax(AesEaxParameters parameters)
124       throws GeneralSecurityException {
125     return AesEaxParameters.builder()
126         .setIvSizeBytes(parameters.getIvSizeBytes())
127         .setKeySizeBytes(parameters.getKeySizeBytes())
128         .setTagSizeBytes(parameters.getTagSizeBytes())
129         .setVariant(AesEaxParameters.Variant.NO_PREFIX)
130         .build();
131   }
132 
makeRawAesGcmSiv(AesGcmSivParameters parameters)133   private static AeadParameters makeRawAesGcmSiv(AesGcmSivParameters parameters)
134       throws GeneralSecurityException {
135     return AesGcmSivParameters.builder()
136         .setKeySizeBytes(parameters.getKeySizeBytes())
137         .setVariant(AesGcmSivParameters.Variant.NO_PREFIX)
138         .build();
139   }
140 
makeRaw(Parameters parameters)141   private static AeadParameters makeRaw(Parameters parameters) throws GeneralSecurityException {
142     if (parameters instanceof AesGcmParameters) {
143       return makeRawAesGcm((AesGcmParameters) parameters);
144     }
145     if (parameters instanceof ChaCha20Poly1305Parameters) {
146       return makeRawChaCha20Poly1305();
147     }
148     if (parameters instanceof XChaCha20Poly1305Parameters) {
149       return makeRawXChaCha20Poly1305();
150     }
151     if (parameters instanceof AesCtrHmacAeadParameters) {
152       return makeRawAesCtrHmacAead((AesCtrHmacAeadParameters) parameters);
153     }
154     if (parameters instanceof AesEaxParameters) {
155       return makeRawAesEax((AesEaxParameters) parameters);
156     }
157     if (parameters instanceof AesGcmSivParameters) {
158       return makeRawAesGcmSiv((AesGcmSivParameters) parameters);
159     }
160     throw new IllegalArgumentException("Illegal parameters" + parameters);
161   }
162 
getRequiredParsingStrategy( AeadParameters parameters)163   private static LegacyKmsEnvelopeAeadParameters.DekParsingStrategy getRequiredParsingStrategy(
164       AeadParameters parameters) {
165     if (parameters instanceof AesGcmParameters) {
166       return LegacyKmsEnvelopeAeadParameters.DekParsingStrategy.ASSUME_AES_GCM;
167     }
168     if (parameters instanceof ChaCha20Poly1305Parameters) {
169       return LegacyKmsEnvelopeAeadParameters.DekParsingStrategy.ASSUME_CHACHA20POLY1305;
170     }
171     if (parameters instanceof XChaCha20Poly1305Parameters) {
172       return LegacyKmsEnvelopeAeadParameters.DekParsingStrategy.ASSUME_XCHACHA20POLY1305;
173     }
174     if (parameters instanceof AesCtrHmacAeadParameters) {
175       return LegacyKmsEnvelopeAeadParameters.DekParsingStrategy.ASSUME_AES_CTR_HMAC;
176     }
177     if (parameters instanceof AesEaxParameters) {
178       return LegacyKmsEnvelopeAeadParameters.DekParsingStrategy.ASSUME_AES_EAX;
179     }
180     if (parameters instanceof AesGcmSivParameters) {
181       return LegacyKmsEnvelopeAeadParameters.DekParsingStrategy.ASSUME_AES_GCM_SIV;
182     }
183     throw new IllegalArgumentException("Illegal parameters" + parameters);
184   }
185 
186   /**
187    * Returns a new {@link KeyTemplate} that can generate a {@link LegacyKmsEnvelopeAeadKey} whose
188    * key encrypting key (KEK) is pointing to {@code kekUri} and DEK template is {@code dekTemplate}
189    * (or a derived version of it).
190    *
191    * <p>It requires that a {@code KmsClient} that can handle {@code kekUri} is registered. Avoid
192    * registering it more than once.
193    *
194    * <p><b>Note: </b> Unlike other templates, when you call {@link KeysetHandle#generateNew} with
195    * this template Tink does not generate new key material, but instead creates a reference to the
196    * remote KEK.
197    *
198    * <p>The second argument of the passed in template is ignoring the Variant, and assuming
199    * NO_PREFIX instead.
200    *
201    * <p>It is often not necessary to use this function. Instead of registering a {@code KmsClient},
202    * and creating an {@code Aead} using {@code
203    * KeysetHandle.generateNew(KmsEnvelopeAeadKeyManager.createKeyTemplate(keyUri,
204    * KeyTemplates.get("AES128_GCM"))).getPrimitive(RegistryConfiguration.get(), Aead.class)}, create
205    * the {@code Aead} directly using {@code
206    * KmsEnvelopeAead.create(PredefinedAeadParameters.AES256_GCM, kmsClient.getAead(keyUri))},
207    * without registering any {@code KmsClient}.
208    */
209   @AccessesPartialKey
createKeyTemplate(String kekUri, KeyTemplate dekTemplate)210   public static KeyTemplate createKeyTemplate(String kekUri, KeyTemplate dekTemplate) {
211     try {
212       Parameters parameters = dekTemplate.toParameters();
213       AeadParameters outputPrefixRawParameters = makeRaw(parameters);
214       LegacyKmsEnvelopeAeadParameters legacyKmsEnvelopeAeadParameters =
215           LegacyKmsEnvelopeAeadParameters.builder()
216               .setKekUri(kekUri)
217               .setDekParsingStrategy(getRequiredParsingStrategy(outputPrefixRawParameters))
218               .setDekParametersForNewKeys(outputPrefixRawParameters)
219               .build();
220       return KeyTemplate.createFrom(legacyKmsEnvelopeAeadParameters);
221     } catch (GeneralSecurityException e) {
222       throw new IllegalArgumentException(
223           "Cannot create LegacyKmsEnvelopeAeadParameters for template: " + dekTemplate, e);
224     }
225   }
226 
register(boolean newKeyAllowed)227   public static void register(boolean newKeyAllowed) throws GeneralSecurityException {
228     if (!TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_NOT_FIPS.isCompatible()) {
229       throw new GeneralSecurityException(
230           "Registering KMS Envelope AEAD is not supported in FIPS mode");
231     }
232     LegacyKmsEnvelopeAeadProtoSerialization.register();
233     MutableKeyCreationRegistry.globalInstance()
234         .add(KEY_CREATOR, LegacyKmsEnvelopeAeadParameters.class);
235     MutablePrimitiveRegistry.globalInstance()
236         .registerPrimitiveConstructor(LEGACY_KMS_ENVELOPE_AEAD_PRIMITIVE_CONSTRUCTOR);
237     KeyManagerRegistry.globalInstance().registerKeyManager(legacyKeyManager, newKeyAllowed);
238   }
239 
KmsEnvelopeAeadKeyManager()240   private KmsEnvelopeAeadKeyManager() {}
241 }
242