• 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.daead;
18 
19 import static com.google.crypto.tink.internal.TinkBugException.exceptionIsBug;
20 
21 import com.google.crypto.tink.AccessesPartialKey;
22 import com.google.crypto.tink.DeterministicAead;
23 import com.google.crypto.tink.KeyManager;
24 import com.google.crypto.tink.KeyTemplate;
25 import com.google.crypto.tink.Parameters;
26 import com.google.crypto.tink.SecretKeyAccess;
27 import com.google.crypto.tink.config.internal.TinkFipsUtil;
28 import com.google.crypto.tink.daead.internal.AesSivProtoSerialization;
29 import com.google.crypto.tink.internal.KeyManagerRegistry;
30 import com.google.crypto.tink.internal.LegacyKeyManagerImpl;
31 import com.google.crypto.tink.internal.MutableKeyCreationRegistry;
32 import com.google.crypto.tink.internal.MutableKeyDerivationRegistry;
33 import com.google.crypto.tink.internal.MutableParametersRegistry;
34 import com.google.crypto.tink.internal.MutablePrimitiveRegistry;
35 import com.google.crypto.tink.internal.PrimitiveConstructor;
36 import com.google.crypto.tink.internal.Util;
37 import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
38 import com.google.crypto.tink.subtle.AesSiv;
39 import com.google.crypto.tink.util.SecretBytes;
40 import java.io.InputStream;
41 import java.security.GeneralSecurityException;
42 import java.security.InvalidAlgorithmParameterException;
43 import java.util.Collections;
44 import java.util.HashMap;
45 import java.util.Map;
46 import javax.annotation.Nullable;
47 
48 /**
49  * This key manager generates new {@code AesSivKey} keys and produces new instances of {@code
50  * AesSiv}.
51  */
52 public final class AesSivKeyManager {
createDeterministicAead(AesSivKey key)53   private static DeterministicAead createDeterministicAead(AesSivKey key)
54       throws GeneralSecurityException {
55     validateParameters(key.getParameters());
56     return AesSiv.create(key);
57   }
58 
59   private static final PrimitiveConstructor<AesSivKey, DeterministicAead>
60       AES_SIV_PRIMITIVE_CONSTRUCTOR =
61           PrimitiveConstructor.create(
62               AesSivKeyManager::createDeterministicAead, AesSivKey.class, DeterministicAead.class);
63 
64   private static final int KEY_SIZE_IN_BYTES = 64;
65 
getKeyType()66   static String getKeyType() {
67     return "type.googleapis.com/google.crypto.tink.AesSivKey";
68   }
69 
70   private static final KeyManager<DeterministicAead> legacyKeyManager =
71       LegacyKeyManagerImpl.create(
72           getKeyType(),
73           DeterministicAead.class,
74           KeyMaterialType.SYMMETRIC,
75           com.google.crypto.tink.proto.AesSivKey.parser());
76 
validateParameters(AesSivParameters parameters)77   private static void validateParameters(AesSivParameters parameters)
78       throws GeneralSecurityException {
79     if (parameters.getKeySizeBytes() != KEY_SIZE_IN_BYTES) {
80       throw new InvalidAlgorithmParameterException(
81           "invalid key size: "
82               + parameters.getKeySizeBytes()
83               + ". Valid keys must have "
84               + KEY_SIZE_IN_BYTES
85               + " bytes.");
86     }
87   }
88 
89   @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration.
90   private static final MutableKeyDerivationRegistry.InsecureKeyCreator<AesSivParameters>
91       KEY_DERIVER = AesSivKeyManager::createAesSivKeyFromRandomness;
92 
93   @AccessesPartialKey
createAesSivKeyFromRandomness( AesSivParameters parameters, InputStream stream, @Nullable Integer idRequirement, SecretKeyAccess access)94   static AesSivKey createAesSivKeyFromRandomness(
95       AesSivParameters parameters,
96       InputStream stream,
97       @Nullable Integer idRequirement,
98       SecretKeyAccess access)
99       throws GeneralSecurityException {
100     validateParameters(parameters);
101     return AesSivKey.builder()
102         .setParameters(parameters)
103         .setIdRequirement(idRequirement)
104         .setKeyBytes(Util.readIntoSecretBytes(stream, parameters.getKeySizeBytes(), access))
105         .build();
106   }
107 
108   @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration.
109   private static final MutableKeyCreationRegistry.KeyCreator<AesSivParameters> KEY_CREATOR =
110       AesSivKeyManager::newKey;
111 
112   @AccessesPartialKey
newKey(AesSivParameters parameters, @Nullable Integer idRequirement)113   static AesSivKey newKey(AesSivParameters parameters, @Nullable Integer idRequirement)
114       throws GeneralSecurityException {
115     validateParameters(parameters);
116     return AesSivKey.builder()
117         .setParameters(parameters)
118         .setIdRequirement(idRequirement)
119         .setKeyBytes(SecretBytes.randomBytes(parameters.getKeySizeBytes()))
120         .build();
121   }
122 
namedParameters()123   private static Map<String, Parameters> namedParameters() throws GeneralSecurityException {
124     Map<String, Parameters> result = new HashMap<>();
125     result.put("AES256_SIV", PredefinedDeterministicAeadParameters.AES256_SIV);
126     result.put(
127         "AES256_SIV_RAW",
128         AesSivParameters.builder()
129             .setKeySizeBytes(64)
130             .setVariant(AesSivParameters.Variant.NO_PREFIX)
131             .build());
132     return Collections.unmodifiableMap(result);
133   }
134 
register(boolean newKeyAllowed)135   public static void register(boolean newKeyAllowed) throws GeneralSecurityException {
136     if (!TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_NOT_FIPS.isCompatible()) {
137       throw new GeneralSecurityException("Registering AES SIV is not supported in FIPS mode");
138     }
139     AesSivProtoSerialization.register();
140     MutablePrimitiveRegistry.globalInstance()
141         .registerPrimitiveConstructor(AES_SIV_PRIMITIVE_CONSTRUCTOR);
142     MutableParametersRegistry.globalInstance().putAll(namedParameters());
143     MutableKeyDerivationRegistry.globalInstance().add(KEY_DERIVER, AesSivParameters.class);
144     MutableKeyCreationRegistry.globalInstance().add(KEY_CREATOR, AesSivParameters.class);
145     KeyManagerRegistry.globalInstance().registerKeyManager(legacyKeyManager, newKeyAllowed);
146   }
147 
148   /**
149    * @return a {@code KeyTemplate} that generates new instances of AES-SIV-CMAC keys.
150    */
aes256SivTemplate()151   public static final KeyTemplate aes256SivTemplate() {
152     return exceptionIsBug(
153         () ->
154             KeyTemplate.createFrom(
155                 AesSivParameters.builder()
156                     .setKeySizeBytes(KEY_SIZE_IN_BYTES)
157                     .setVariant(AesSivParameters.Variant.TINK)
158                     .build()));
159   }
160 
161   /**
162    * @return A {@code KeyTemplate} that generates new instances of AES-SIV-CMAC keys. Keys generated
163    *     from this template create ciphertexts compatible with other libraries.
164    */
rawAes256SivTemplate()165   public static final KeyTemplate rawAes256SivTemplate() {
166     return exceptionIsBug(
167         () ->
168             KeyTemplate.createFrom(
169                 AesSivParameters.builder()
170                     .setKeySizeBytes(KEY_SIZE_IN_BYTES)
171                     .setVariant(AesSivParameters.Variant.NO_PREFIX)
172                     .build()));
173   }
174 
AesSivKeyManager()175   private AesSivKeyManager() {}
176 }
177