1 // Copyright 2023 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.aead; 18 19 import static com.google.crypto.tink.internal.Util.toBytesFromPrintableAscii; 20 21 import com.google.crypto.tink.SecretKeyAccess; 22 import com.google.crypto.tink.internal.KeyParser; 23 import com.google.crypto.tink.internal.KeySerializer; 24 import com.google.crypto.tink.internal.MutableSerializationRegistry; 25 import com.google.crypto.tink.internal.ParametersParser; 26 import com.google.crypto.tink.internal.ParametersSerializer; 27 import com.google.crypto.tink.internal.ProtoKeySerialization; 28 import com.google.crypto.tink.internal.ProtoParametersSerialization; 29 import com.google.crypto.tink.proto.KeyData.KeyMaterialType; 30 import com.google.crypto.tink.proto.KeyTemplate; 31 import com.google.crypto.tink.proto.KmsAeadKeyFormat; 32 import com.google.crypto.tink.proto.OutputPrefixType; 33 import com.google.crypto.tink.util.Bytes; 34 import com.google.protobuf.ExtensionRegistryLite; 35 import com.google.protobuf.InvalidProtocolBufferException; 36 import java.security.GeneralSecurityException; 37 import javax.annotation.Nullable; 38 39 /** Serializers and Parsers for LegacyKmsAeadProtoKey and LegacyKmsAeadProtoParameters */ 40 final class LegacyKmsAeadProtoSerialization { 41 private static final String TYPE_URL = "type.googleapis.com/google.crypto.tink.KmsAeadKey"; 42 private static final Bytes TYPE_URL_BYTES = toBytesFromPrintableAscii(TYPE_URL); 43 44 private static final ParametersSerializer<LegacyKmsAeadParameters, ProtoParametersSerialization> 45 PARAMETERS_SERIALIZER = 46 ParametersSerializer.create( 47 LegacyKmsAeadProtoSerialization::serializeParameters, 48 LegacyKmsAeadParameters.class, 49 ProtoParametersSerialization.class); 50 51 private static final ParametersParser<ProtoParametersSerialization> PARAMETERS_PARSER = 52 ParametersParser.create( 53 LegacyKmsAeadProtoSerialization::parseParameters, 54 TYPE_URL_BYTES, 55 ProtoParametersSerialization.class); 56 57 private static final KeySerializer<LegacyKmsAeadKey, ProtoKeySerialization> KEY_SERIALIZER = 58 KeySerializer.create( 59 LegacyKmsAeadProtoSerialization::serializeKey, 60 LegacyKmsAeadKey.class, 61 ProtoKeySerialization.class); 62 63 private static final KeyParser<ProtoKeySerialization> KEY_PARSER = 64 KeyParser.create( 65 LegacyKmsAeadProtoSerialization::parseKey, TYPE_URL_BYTES, ProtoKeySerialization.class); 66 toProtoOutputPrefixType(LegacyKmsAeadParameters.Variant variant)67 private static OutputPrefixType toProtoOutputPrefixType(LegacyKmsAeadParameters.Variant variant) 68 throws GeneralSecurityException { 69 if (LegacyKmsAeadParameters.Variant.TINK.equals(variant)) { 70 return OutputPrefixType.TINK; 71 } 72 if (LegacyKmsAeadParameters.Variant.NO_PREFIX.equals(variant)) { 73 return OutputPrefixType.RAW; 74 } 75 throw new GeneralSecurityException("Unable to serialize variant: " + variant); 76 } 77 toVariant(OutputPrefixType outputPrefixType)78 private static LegacyKmsAeadParameters.Variant toVariant(OutputPrefixType outputPrefixType) 79 throws GeneralSecurityException { 80 switch (outputPrefixType) { 81 case TINK: 82 return LegacyKmsAeadParameters.Variant.TINK; 83 case RAW: 84 return LegacyKmsAeadParameters.Variant.NO_PREFIX; 85 default: 86 throw new GeneralSecurityException( 87 "Unable to parse OutputPrefixType: " + outputPrefixType.getNumber()); 88 } 89 } 90 serializeParameters( LegacyKmsAeadParameters parameters)91 private static ProtoParametersSerialization serializeParameters( 92 LegacyKmsAeadParameters parameters) throws GeneralSecurityException { 93 return ProtoParametersSerialization.create( 94 KeyTemplate.newBuilder() 95 .setTypeUrl(TYPE_URL) 96 .setValue( 97 KmsAeadKeyFormat.newBuilder().setKeyUri(parameters.keyUri()).build().toByteString()) 98 .setOutputPrefixType(toProtoOutputPrefixType(parameters.variant())) 99 .build()); 100 } 101 parseParameters(ProtoParametersSerialization serialization)102 private static LegacyKmsAeadParameters parseParameters(ProtoParametersSerialization serialization) 103 throws GeneralSecurityException { 104 if (!serialization.getKeyTemplate().getTypeUrl().equals(TYPE_URL)) { 105 throw new IllegalArgumentException( 106 "Wrong type URL in call to LegacyKmsAeadProtoSerialization.parseParameters: " 107 + serialization.getKeyTemplate().getTypeUrl()); 108 } 109 KmsAeadKeyFormat format; 110 try { 111 format = 112 KmsAeadKeyFormat.parseFrom( 113 serialization.getKeyTemplate().getValue(), ExtensionRegistryLite.getEmptyRegistry()); 114 } catch (InvalidProtocolBufferException e) { 115 throw new GeneralSecurityException("Parsing KmsAeadKeyFormat failed: ", e); 116 } 117 return LegacyKmsAeadParameters.create( 118 format.getKeyUri(), toVariant(serialization.getKeyTemplate().getOutputPrefixType())); 119 } 120 serializeKey( LegacyKmsAeadKey key, @Nullable SecretKeyAccess access)121 private static ProtoKeySerialization serializeKey( 122 LegacyKmsAeadKey key, @Nullable SecretKeyAccess access) throws GeneralSecurityException { 123 return ProtoKeySerialization.create( 124 TYPE_URL, 125 com.google.crypto.tink.proto.KmsAeadKey.newBuilder() 126 .setParams( 127 KmsAeadKeyFormat.newBuilder().setKeyUri(key.getParameters().keyUri()).build()) 128 .build() 129 .toByteString(), 130 KeyMaterialType.REMOTE, 131 toProtoOutputPrefixType(key.getParameters().variant()), 132 key.getIdRequirementOrNull()); 133 } 134 parseKey( ProtoKeySerialization serialization, @Nullable SecretKeyAccess access)135 private static LegacyKmsAeadKey parseKey( 136 ProtoKeySerialization serialization, @Nullable SecretKeyAccess access) 137 throws GeneralSecurityException { 138 if (!serialization.getTypeUrl().equals(TYPE_URL)) { 139 throw new IllegalArgumentException( 140 "Wrong type URL in call to LegacyKmsAeadProtoSerialization.parseKey"); 141 } 142 try { 143 com.google.crypto.tink.proto.KmsAeadKey protoKey = 144 com.google.crypto.tink.proto.KmsAeadKey.parseFrom( 145 serialization.getValue(), ExtensionRegistryLite.getEmptyRegistry()); 146 if (protoKey.getVersion() != 0) { 147 throw new GeneralSecurityException( 148 "KmsAeadKey are only accepted with version 0, got " + protoKey); 149 } 150 LegacyKmsAeadParameters parameters = 151 LegacyKmsAeadParameters.create( 152 protoKey.getParams().getKeyUri(), toVariant(serialization.getOutputPrefixType())); 153 return LegacyKmsAeadKey.create(parameters, serialization.getIdRequirementOrNull()); 154 } catch (InvalidProtocolBufferException e) { 155 throw new GeneralSecurityException("Parsing KmsAeadKey failed: ", e); 156 } 157 } 158 register()159 public static void register() throws GeneralSecurityException { 160 register(MutableSerializationRegistry.globalInstance()); 161 } 162 register(MutableSerializationRegistry registry)163 public static void register(MutableSerializationRegistry registry) 164 throws GeneralSecurityException { 165 registry.registerParametersSerializer(PARAMETERS_SERIALIZER); 166 registry.registerParametersParser(PARAMETERS_PARSER); 167 registry.registerKeySerializer(KEY_SERIALIZER); 168 registry.registerKeyParser(KEY_PARSER); 169 } 170 LegacyKmsAeadProtoSerialization()171 private LegacyKmsAeadProtoSerialization() {} 172 } 173