• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 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.Util.toBytesFromPrintableAscii;
20 
21 import com.google.crypto.tink.AccessesPartialKey;
22 import com.google.crypto.tink.Parameters;
23 import com.google.crypto.tink.SecretKeyAccess;
24 import com.google.crypto.tink.TinkProtoParametersFormat;
25 import com.google.crypto.tink.internal.KeyParser;
26 import com.google.crypto.tink.internal.KeySerializer;
27 import com.google.crypto.tink.internal.MutableSerializationRegistry;
28 import com.google.crypto.tink.internal.ParametersParser;
29 import com.google.crypto.tink.internal.ParametersSerializer;
30 import com.google.crypto.tink.internal.ProtoKeySerialization;
31 import com.google.crypto.tink.internal.ProtoParametersSerialization;
32 import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
33 import com.google.crypto.tink.proto.KeyTemplate;
34 import com.google.crypto.tink.proto.KmsEnvelopeAeadKey;
35 import com.google.crypto.tink.proto.KmsEnvelopeAeadKeyFormat;
36 import com.google.crypto.tink.proto.OutputPrefixType;
37 import com.google.crypto.tink.util.Bytes;
38 import com.google.protobuf.ExtensionRegistryLite;
39 import com.google.protobuf.InvalidProtocolBufferException;
40 import java.security.GeneralSecurityException;
41 import javax.annotation.Nullable;
42 
43 /**
44  * Serializers and Parsers for LegacyKmsEnvelopeAeadProtoKey and
45  * LegacyKmsEnvelopeAeadProtoParameters
46  */
47 public final class LegacyKmsEnvelopeAeadProtoSerialization {
48   private static final String TYPE_URL =
49       "type.googleapis.com/google.crypto.tink.KmsEnvelopeAeadKey";
50   private static final Bytes TYPE_URL_BYTES = toBytesFromPrintableAscii(TYPE_URL);
51 
52   private static final ParametersSerializer<
53           LegacyKmsEnvelopeAeadParameters, ProtoParametersSerialization>
54       PARAMETERS_SERIALIZER =
55           ParametersSerializer.create(
56               LegacyKmsEnvelopeAeadProtoSerialization::serializeParameters,
57               LegacyKmsEnvelopeAeadParameters.class,
58               ProtoParametersSerialization.class);
59 
60   private static final ParametersParser<ProtoParametersSerialization> PARAMETERS_PARSER =
61       ParametersParser.create(
62           LegacyKmsEnvelopeAeadProtoSerialization::parseParameters,
63           TYPE_URL_BYTES,
64           ProtoParametersSerialization.class);
65 
66   private static final KeySerializer<LegacyKmsEnvelopeAeadKey, ProtoKeySerialization>
67       KEY_SERIALIZER =
68           KeySerializer.create(
69               LegacyKmsEnvelopeAeadProtoSerialization::serializeKey,
70               LegacyKmsEnvelopeAeadKey.class,
71               ProtoKeySerialization.class);
72 
73   private static final KeyParser<ProtoKeySerialization> KEY_PARSER =
74       KeyParser.create(
75           LegacyKmsEnvelopeAeadProtoSerialization::parseKey,
76           TYPE_URL_BYTES,
77           ProtoKeySerialization.class);
78 
toProtoOutputPrefixType( LegacyKmsEnvelopeAeadParameters.Variant variant)79   private static OutputPrefixType toProtoOutputPrefixType(
80       LegacyKmsEnvelopeAeadParameters.Variant variant) throws GeneralSecurityException {
81     if (LegacyKmsEnvelopeAeadParameters.Variant.TINK.equals(variant)) {
82       return OutputPrefixType.TINK;
83     }
84     if (LegacyKmsEnvelopeAeadParameters.Variant.NO_PREFIX.equals(variant)) {
85       return OutputPrefixType.RAW;
86     }
87     throw new GeneralSecurityException("Unable to serialize variant: " + variant);
88   }
89 
toVariant( OutputPrefixType outputPrefixType)90   private static LegacyKmsEnvelopeAeadParameters.Variant toVariant(
91       OutputPrefixType outputPrefixType) throws GeneralSecurityException {
92     switch (outputPrefixType) {
93       case TINK:
94         return LegacyKmsEnvelopeAeadParameters.Variant.TINK;
95       case RAW:
96         return LegacyKmsEnvelopeAeadParameters.Variant.NO_PREFIX;
97       default:
98         throw new GeneralSecurityException(
99             "Unable to parse OutputPrefixType: " + outputPrefixType.getNumber());
100     }
101   }
102 
103   @AccessesPartialKey
serializeParameters( LegacyKmsEnvelopeAeadParameters parameters)104   private static ProtoParametersSerialization serializeParameters(
105       LegacyKmsEnvelopeAeadParameters parameters) throws GeneralSecurityException {
106     return ProtoParametersSerialization.create(
107         KeyTemplate.newBuilder()
108             .setTypeUrl(TYPE_URL)
109             .setValue(serializeParametersToKmsEnvelopeAeadKeyFormat(parameters).toByteString())
110             .setOutputPrefixType(toProtoOutputPrefixType(parameters.getVariant()))
111             .build());
112   }
113 
114   @AccessesPartialKey
serializeParametersToKmsEnvelopeAeadKeyFormat( LegacyKmsEnvelopeAeadParameters parameters)115   private static KmsEnvelopeAeadKeyFormat serializeParametersToKmsEnvelopeAeadKeyFormat(
116       LegacyKmsEnvelopeAeadParameters parameters) throws GeneralSecurityException {
117     byte[] serializedDekParameters =
118         TinkProtoParametersFormat.serialize(parameters.getDekParametersForNewKeys());
119     try {
120       KeyTemplate dekKeyTemplate =
121           KeyTemplate.parseFrom(serializedDekParameters, ExtensionRegistryLite.getEmptyRegistry());
122       return KmsEnvelopeAeadKeyFormat.newBuilder()
123           .setKekUri(parameters.getKekUri())
124           .setDekTemplate(dekKeyTemplate)
125           .build();
126     } catch (InvalidProtocolBufferException e) {
127       throw new GeneralSecurityException("Parsing KmsEnvelopeAeadKeyFormat failed: ", e);
128     }
129   }
130 
131   @AccessesPartialKey
serializeKey( LegacyKmsEnvelopeAeadKey key, @Nullable SecretKeyAccess access)132   private static ProtoKeySerialization serializeKey(
133       LegacyKmsEnvelopeAeadKey key, @Nullable SecretKeyAccess access)
134       throws GeneralSecurityException {
135     return ProtoKeySerialization.create(
136         TYPE_URL,
137         KmsEnvelopeAeadKey.newBuilder()
138             .setParams(serializeParametersToKmsEnvelopeAeadKeyFormat(key.getParameters()))
139             .build()
140             .toByteString(),
141         KeyMaterialType.REMOTE,
142         toProtoOutputPrefixType(key.getParameters().getVariant()),
143         key.getIdRequirementOrNull());
144   }
145 
146   @AccessesPartialKey
parseParameters( ProtoParametersSerialization serialization)147   private static LegacyKmsEnvelopeAeadParameters parseParameters(
148       ProtoParametersSerialization serialization) throws GeneralSecurityException {
149     if (!serialization.getKeyTemplate().getTypeUrl().equals(TYPE_URL)) {
150       throw new IllegalArgumentException(
151           "Wrong type URL in call to LegacyKmsEnvelopeAeadProtoSerialization.parseParameters: "
152               + serialization.getKeyTemplate().getTypeUrl());
153     }
154     KmsEnvelopeAeadKeyFormat format;
155     try {
156       format =
157           KmsEnvelopeAeadKeyFormat.parseFrom(
158               serialization.getKeyTemplate().getValue(), ExtensionRegistryLite.getEmptyRegistry());
159     } catch (InvalidProtocolBufferException e) {
160       throw new GeneralSecurityException("Parsing KmsEnvelopeAeadKeyFormat failed: ", e);
161     }
162     return parseParameters(format, serialization.getKeyTemplate().getOutputPrefixType());
163   }
164 
165   @AccessesPartialKey
parseParameters( KmsEnvelopeAeadKeyFormat format, OutputPrefixType outputPrefixType)166   private static LegacyKmsEnvelopeAeadParameters parseParameters(
167       KmsEnvelopeAeadKeyFormat format, OutputPrefixType outputPrefixType)
168       throws GeneralSecurityException {
169     Parameters aeadParameters =
170         TinkProtoParametersFormat.parse(
171             KeyTemplate.newBuilder()
172                 .setTypeUrl(format.getDekTemplate().getTypeUrl())
173                 .setValue(format.getDekTemplate().getValue())
174                 .setOutputPrefixType(OutputPrefixType.RAW)
175                 .build()
176                 .toByteArray());
177 
178     @Nullable LegacyKmsEnvelopeAeadParameters.DekParsingStrategy strategy;
179 
180     if (aeadParameters instanceof AesGcmParameters) {
181       strategy = LegacyKmsEnvelopeAeadParameters.DekParsingStrategy.ASSUME_AES_GCM;
182     } else if (aeadParameters instanceof ChaCha20Poly1305Parameters) {
183       strategy = LegacyKmsEnvelopeAeadParameters.DekParsingStrategy.ASSUME_CHACHA20POLY1305;
184     } else if (aeadParameters instanceof XChaCha20Poly1305Parameters) {
185       strategy = LegacyKmsEnvelopeAeadParameters.DekParsingStrategy.ASSUME_XCHACHA20POLY1305;
186     } else if (aeadParameters instanceof AesCtrHmacAeadParameters) {
187       strategy = LegacyKmsEnvelopeAeadParameters.DekParsingStrategy.ASSUME_AES_CTR_HMAC;
188     } else if (aeadParameters instanceof AesEaxParameters) {
189       strategy = LegacyKmsEnvelopeAeadParameters.DekParsingStrategy.ASSUME_AES_EAX;
190     } else if (aeadParameters instanceof AesGcmSivParameters) {
191       strategy = LegacyKmsEnvelopeAeadParameters.DekParsingStrategy.ASSUME_AES_GCM_SIV;
192     } else {
193       throw new GeneralSecurityException(
194           "Unsupported DEK parameters when parsing " + aeadParameters);
195     }
196     return LegacyKmsEnvelopeAeadParameters.builder()
197         .setVariant(toVariant(outputPrefixType))
198         .setKekUri(format.getKekUri())
199         .setDekParametersForNewKeys((AeadParameters) aeadParameters)
200         .setDekParsingStrategy(strategy)
201         .build();
202   }
203 
204   @AccessesPartialKey
parseKey( ProtoKeySerialization serialization, @Nullable SecretKeyAccess access)205   private static LegacyKmsEnvelopeAeadKey parseKey(
206       ProtoKeySerialization serialization, @Nullable SecretKeyAccess access)
207       throws GeneralSecurityException {
208     if (!serialization.getTypeUrl().equals(TYPE_URL)) {
209       throw new IllegalArgumentException(
210           "Wrong type URL in call to LegacyKmsEnvelopeAeadProtoSerialization.parseKey");
211     }
212     try {
213       KmsEnvelopeAeadKey protoKey =
214           KmsEnvelopeAeadKey.parseFrom(
215               serialization.getValue(), ExtensionRegistryLite.getEmptyRegistry());
216       if (protoKey.getVersion() != 0) {
217         throw new GeneralSecurityException(
218             "KmsEnvelopeAeadKeys are only accepted with version 0, got " + protoKey);
219       }
220 
221       LegacyKmsEnvelopeAeadParameters parameters =
222           parseParameters(protoKey.getParams(), serialization.getOutputPrefixType());
223       return LegacyKmsEnvelopeAeadKey.create(parameters, serialization.getIdRequirementOrNull());
224     } catch (InvalidProtocolBufferException e) {
225       throw new GeneralSecurityException("Parsing KmsEnvelopeAeadKey failed: ", e);
226     }
227   }
228 
register()229   public static void register() throws GeneralSecurityException {
230     register(MutableSerializationRegistry.globalInstance());
231   }
232 
register(MutableSerializationRegistry registry)233   public static void register(MutableSerializationRegistry registry)
234       throws GeneralSecurityException {
235     registry.registerParametersSerializer(PARAMETERS_SERIALIZER);
236     registry.registerParametersParser(PARAMETERS_PARSER);
237     registry.registerKeySerializer(KEY_SERIALIZER);
238     registry.registerKeyParser(KEY_PARSER);
239   }
240 
LegacyKmsEnvelopeAeadProtoSerialization()241   private LegacyKmsEnvelopeAeadProtoSerialization() {}
242 }
243