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 static com.google.crypto.tink.internal.TinkBugException.exceptionIsBug; 20 21 import com.google.crypto.tink.AccessesPartialKey; 22 import com.google.crypto.tink.Aead; 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.aead.internal.AesEaxProtoSerialization; 27 import com.google.crypto.tink.config.internal.TinkFipsUtil; 28 import com.google.crypto.tink.internal.KeyManagerRegistry; 29 import com.google.crypto.tink.internal.LegacyKeyManagerImpl; 30 import com.google.crypto.tink.internal.MutableKeyCreationRegistry; 31 import com.google.crypto.tink.internal.MutableParametersRegistry; 32 import com.google.crypto.tink.internal.MutablePrimitiveRegistry; 33 import com.google.crypto.tink.internal.PrimitiveConstructor; 34 import com.google.crypto.tink.proto.KeyData.KeyMaterialType; 35 import com.google.crypto.tink.subtle.AesEaxJce; 36 import com.google.crypto.tink.util.SecretBytes; 37 import java.security.GeneralSecurityException; 38 import java.util.Collections; 39 import java.util.HashMap; 40 import java.util.Map; 41 import javax.annotation.Nullable; 42 43 /** 44 * This key manager generates new {@code AesEaxKey} keys and produces new instances of {@code 45 * AesEaxJce}. 46 */ 47 public final class AesEaxKeyManager { validate(AesEaxParameters parameters)48 private static final void validate(AesEaxParameters parameters) throws GeneralSecurityException { 49 if (parameters.getKeySizeBytes() == 24) { 50 throw new GeneralSecurityException("192 bit AES GCM Parameters are not valid"); 51 } 52 } 53 54 private static final PrimitiveConstructor<AesEaxKey, Aead> AES_EAX_PRIMITIVE_CONSTRUCTOR = 55 PrimitiveConstructor.create(AesEaxJce::create, AesEaxKey.class, Aead.class); 56 getKeyType()57 static String getKeyType() { 58 return "type.googleapis.com/google.crypto.tink.AesEaxKey"; 59 } 60 61 private static final KeyManager<Aead> legacyKeyManager = 62 LegacyKeyManagerImpl.create( 63 getKeyType(), 64 Aead.class, 65 KeyMaterialType.SYMMETRIC, 66 com.google.crypto.tink.proto.AesEaxKey.parser()); 67 namedParameters()68 private static Map<String, Parameters> namedParameters() throws GeneralSecurityException { 69 Map<String, Parameters> result = new HashMap<>(); 70 result.put("AES128_EAX", PredefinedAeadParameters.AES128_EAX); 71 result.put( 72 "AES128_EAX_RAW", 73 AesEaxParameters.builder() 74 .setIvSizeBytes(16) 75 .setKeySizeBytes(16) 76 .setTagSizeBytes(16) 77 .setVariant(AesEaxParameters.Variant.NO_PREFIX) 78 .build()); 79 result.put("AES256_EAX", PredefinedAeadParameters.AES256_EAX); 80 result.put( 81 "AES256_EAX_RAW", 82 AesEaxParameters.builder() 83 .setIvSizeBytes(16) 84 .setKeySizeBytes(32) 85 .setTagSizeBytes(16) 86 .setVariant(AesEaxParameters.Variant.NO_PREFIX) 87 .build()); 88 89 return Collections.unmodifiableMap(result); 90 } 91 92 @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration. 93 private static final MutableKeyCreationRegistry.KeyCreator<AesEaxParameters> KEY_CREATOR = 94 AesEaxKeyManager::createAesEaxKey; 95 96 @AccessesPartialKey createAesEaxKey( AesEaxParameters parameters, @Nullable Integer idRequirement)97 private static com.google.crypto.tink.aead.AesEaxKey createAesEaxKey( 98 AesEaxParameters parameters, @Nullable Integer idRequirement) 99 throws GeneralSecurityException { 100 validate(parameters); 101 return com.google.crypto.tink.aead.AesEaxKey.builder() 102 .setParameters(parameters) 103 .setIdRequirement(idRequirement) 104 .setKeyBytes(SecretBytes.randomBytes(parameters.getKeySizeBytes())) 105 .build(); 106 } 107 register(boolean newKeyAllowed)108 public static void register(boolean newKeyAllowed) throws GeneralSecurityException { 109 if (!TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_NOT_FIPS.isCompatible()) { 110 throw new GeneralSecurityException("Registering AES EAX is not supported in FIPS mode"); 111 } 112 AesEaxProtoSerialization.register(); 113 MutablePrimitiveRegistry.globalInstance() 114 .registerPrimitiveConstructor(AES_EAX_PRIMITIVE_CONSTRUCTOR); 115 MutableParametersRegistry.globalInstance().putAll(namedParameters()); 116 MutableKeyCreationRegistry.globalInstance().add(KEY_CREATOR, AesEaxParameters.class); 117 KeyManagerRegistry.globalInstance().registerKeyManager(legacyKeyManager, newKeyAllowed); 118 } 119 120 /** 121 * @return a {@link KeyTemplate} that generates new instances of AES-EAX with the following 122 * parameters: 123 * <ul> 124 * <li>Key size: 16 bytes 125 * <li>IV size: 16 bytes 126 * <li>Prefix type: {@link KeyTemplate.OutputPrefixType#TINK} 127 * </ul> 128 */ aes128EaxTemplate()129 public static final KeyTemplate aes128EaxTemplate() { 130 return exceptionIsBug( 131 () -> 132 KeyTemplate.createFrom( 133 AesEaxParameters.builder() 134 .setIvSizeBytes(16) 135 .setKeySizeBytes(16) 136 .setTagSizeBytes(16) 137 .setVariant(AesEaxParameters.Variant.TINK) 138 .build())); 139 } 140 141 /** 142 * @return a {@link KeyTemplate} that generates new instances of AES-EAX with the following 143 * parameters: 144 * <ul> 145 * <li>Key size: 16 bytes 146 * <li>IV size: 16 bytes 147 * <li>Prefix type: {@link KeyTemplate.OutputPrefixType#RAW} (no prefix) 148 * </ul> 149 */ rawAes128EaxTemplate()150 public static final KeyTemplate rawAes128EaxTemplate() { 151 return exceptionIsBug( 152 () -> 153 KeyTemplate.createFrom( 154 AesEaxParameters.builder() 155 .setIvSizeBytes(16) 156 .setKeySizeBytes(16) 157 .setTagSizeBytes(16) 158 .setVariant(AesEaxParameters.Variant.NO_PREFIX) 159 .build())); 160 } 161 162 /** 163 * @return a {@link KeyTemplate} that generates new instances of AES-EAX with the following 164 * parameters: 165 * <ul> 166 * <li>Key size: 32 bytes 167 * <li>IV size: 16 bytes 168 * <li>Prefix type: {@link KeyTemplate.OutputPrefixType#TINK} 169 * </ul> 170 */ aes256EaxTemplate()171 public static final KeyTemplate aes256EaxTemplate() { 172 return exceptionIsBug( 173 () -> 174 KeyTemplate.createFrom( 175 AesEaxParameters.builder() 176 .setIvSizeBytes(16) 177 .setKeySizeBytes(32) 178 .setTagSizeBytes(16) 179 .setVariant(AesEaxParameters.Variant.TINK) 180 .build())); 181 } 182 183 /** 184 * @return a {@link KeyTemplate} that generates new instances of AES-EAX with the following 185 * parameters: 186 * <ul> 187 * <li>Key size: 32 bytes 188 * <li>IV size: 16 bytes 189 * <li>Prefix type: {@link KeyTemplate.OutputPrefixType#RAW} (no prefix) 190 * </ul> 191 */ rawAes256EaxTemplate()192 public static final KeyTemplate rawAes256EaxTemplate() { 193 return exceptionIsBug( 194 () -> 195 KeyTemplate.createFrom( 196 AesEaxParameters.builder() 197 .setIvSizeBytes(16) 198 .setKeySizeBytes(32) 199 .setTagSizeBytes(16) 200 .setVariant(AesEaxParameters.Variant.NO_PREFIX) 201 .build())); 202 } 203 AesEaxKeyManager()204 private AesEaxKeyManager() {} 205 } 206