• 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.hybrid;
18 
19 import com.google.crypto.tink.Aead;
20 import com.google.crypto.tink.DeterministicAead;
21 import com.google.crypto.tink.Registry;
22 import com.google.crypto.tink.aead.AeadConfig;
23 import com.google.crypto.tink.daead.DeterministicAeadConfig;
24 import com.google.crypto.tink.hybrid.subtle.AeadOrDaead;
25 import com.google.crypto.tink.proto.AesCtrHmacAeadKey;
26 import com.google.crypto.tink.proto.AesCtrHmacAeadKeyFormat;
27 import com.google.crypto.tink.proto.AesCtrKey;
28 import com.google.crypto.tink.proto.AesGcmKey;
29 import com.google.crypto.tink.proto.AesGcmKeyFormat;
30 import com.google.crypto.tink.proto.AesSivKey;
31 import com.google.crypto.tink.proto.AesSivKeyFormat;
32 import com.google.crypto.tink.proto.HmacKey;
33 import com.google.crypto.tink.proto.KeyTemplate;
34 import com.google.crypto.tink.subtle.EciesAeadHkdfDemHelper;
35 import com.google.protobuf.ByteString;
36 import com.google.protobuf.ExtensionRegistryLite;
37 import com.google.protobuf.InvalidProtocolBufferException;
38 import java.security.GeneralSecurityException;
39 import java.util.Arrays;
40 
41 /**
42  * Helper generating {@code Aead}-instances for specified {@code KeyTemplate} and key material. It
43  * uses selected {@code KeyManager}-instances from the {@code Registry} to obtain the instances of
44  * {@code Aead}.
45  */
46 class RegistryEciesAeadHkdfDemHelper implements EciesAeadHkdfDemHelper {
47   private final String demKeyTypeUrl;
48   private final int symmetricKeySize;
49 
50   // used iff demKeyTypeUrl == AeadConfig.AES_GCM_TYPE_URL
51   private AesGcmKey aesGcmKey;
52 
53   // used iff demKeyTypeUrl == AeadConfig.AES_CTR_HMAC_AEAD_TYPE_URL
54   private AesCtrHmacAeadKey aesCtrHmacAeadKey;
55   private int aesCtrKeySize;
56 
57   // used iff demKeyTypeUrl == AeadConfig.AES_SIV_TYPE_URL
58   private AesSivKey aesSivKey;
59 
RegistryEciesAeadHkdfDemHelper(KeyTemplate demTemplate)60   RegistryEciesAeadHkdfDemHelper(KeyTemplate demTemplate) throws GeneralSecurityException {
61     demKeyTypeUrl = demTemplate.getTypeUrl();
62     if (demKeyTypeUrl.equals(AeadConfig.AES_GCM_TYPE_URL)) {
63       try {
64         AesGcmKeyFormat gcmKeyFormat =
65             AesGcmKeyFormat.parseFrom(
66                 demTemplate.getValue(), ExtensionRegistryLite.getEmptyRegistry());
67         this.aesGcmKey =
68             AesGcmKey.parseFrom(
69                 Registry.newKeyData(demTemplate).getValue(),
70                 ExtensionRegistryLite.getEmptyRegistry());
71         this.symmetricKeySize = gcmKeyFormat.getKeySize();
72       } catch (InvalidProtocolBufferException e) {
73         throw new GeneralSecurityException(
74             "invalid KeyFormat protobuf, expected AesGcmKeyFormat", e);
75       }
76     } else if (demKeyTypeUrl.equals(AeadConfig.AES_CTR_HMAC_AEAD_TYPE_URL)) {
77       try {
78         AesCtrHmacAeadKeyFormat aesCtrHmacAeadKeyFormat =
79             AesCtrHmacAeadKeyFormat.parseFrom(
80                 demTemplate.getValue(), ExtensionRegistryLite.getEmptyRegistry());
81         this.aesCtrHmacAeadKey =
82             AesCtrHmacAeadKey.parseFrom(
83                 Registry.newKeyData(demTemplate).getValue(),
84                 ExtensionRegistryLite.getEmptyRegistry());
85         this.aesCtrKeySize = aesCtrHmacAeadKeyFormat.getAesCtrKeyFormat().getKeySize();
86         int hmacKeySize = aesCtrHmacAeadKeyFormat.getHmacKeyFormat().getKeySize();
87         this.symmetricKeySize = aesCtrKeySize + hmacKeySize;
88       } catch (InvalidProtocolBufferException e) {
89         throw new GeneralSecurityException(
90             "invalid KeyFormat protobuf, expected AesCtrHmacAeadKeyFormat", e);
91       }
92     } else if (demKeyTypeUrl.equals(DeterministicAeadConfig.AES_SIV_TYPE_URL)) {
93       try {
94         AesSivKeyFormat aesSivKeyFormat =
95             AesSivKeyFormat.parseFrom(
96                 demTemplate.getValue(), ExtensionRegistryLite.getEmptyRegistry());
97         this.aesSivKey =
98             AesSivKey.parseFrom(
99                 Registry.newKeyData(demTemplate).getValue(),
100                 ExtensionRegistryLite.getEmptyRegistry());
101         this.symmetricKeySize = aesSivKeyFormat.getKeySize();
102       } catch (InvalidProtocolBufferException e) {
103         throw new GeneralSecurityException(
104             "invalid KeyFormat protobuf, expected AesCtrHmacAeadKeyFormat", e);
105       }
106     } else {
107       throw new GeneralSecurityException("unsupported AEAD DEM key type: " + demKeyTypeUrl);
108     }
109   }
110 
111   @Override
getSymmetricKeySizeInBytes()112   public int getSymmetricKeySizeInBytes() {
113     return symmetricKeySize;
114   }
115 
116   @Override
getAeadOrDaead(final byte[] symmetricKeyValue)117   public AeadOrDaead getAeadOrDaead(final byte[] symmetricKeyValue)
118       throws GeneralSecurityException {
119     if (symmetricKeyValue.length != getSymmetricKeySizeInBytes()) {
120       throw new GeneralSecurityException("Symmetric key has incorrect length");
121     }
122     if (demKeyTypeUrl.equals(AeadConfig.AES_GCM_TYPE_URL)) {
123       AesGcmKey aeadKey = AesGcmKey.newBuilder()
124           .mergeFrom(aesGcmKey)
125           .setKeyValue(ByteString.copyFrom(symmetricKeyValue, 0, symmetricKeySize))
126           .build();
127       return new AeadOrDaead(
128           Registry.getPrimitive(demKeyTypeUrl, aeadKey.toByteString(), Aead.class));
129     } else if (demKeyTypeUrl.equals(AeadConfig.AES_CTR_HMAC_AEAD_TYPE_URL)) {
130       byte[] aesCtrKeyValue = Arrays.copyOfRange(symmetricKeyValue, 0, aesCtrKeySize);
131       byte[] hmacKeyValue = Arrays.copyOfRange(symmetricKeyValue, aesCtrKeySize, symmetricKeySize);
132       AesCtrKey aesCtrKey =
133           AesCtrKey.newBuilder()
134               .mergeFrom(aesCtrHmacAeadKey.getAesCtrKey())
135               .setKeyValue(ByteString.copyFrom(aesCtrKeyValue))
136               .build();
137       HmacKey hmacKey =
138           HmacKey.newBuilder()
139               .mergeFrom(aesCtrHmacAeadKey.getHmacKey())
140               .setKeyValue(ByteString.copyFrom(hmacKeyValue))
141               .build();
142       AesCtrHmacAeadKey aeadKey =
143           AesCtrHmacAeadKey.newBuilder()
144               .setVersion(aesCtrHmacAeadKey.getVersion())
145               .setAesCtrKey(aesCtrKey)
146               .setHmacKey(hmacKey)
147               .build();
148       return new AeadOrDaead(
149           Registry.getPrimitive(demKeyTypeUrl, aeadKey.toByteString(), Aead.class));
150     } else if (demKeyTypeUrl.equals(DeterministicAeadConfig.AES_SIV_TYPE_URL)) {
151       AesSivKey daeadKey =
152           AesSivKey.newBuilder()
153               .mergeFrom(aesSivKey)
154               .setKeyValue(ByteString.copyFrom(symmetricKeyValue, 0, symmetricKeySize))
155               .build();
156       return new AeadOrDaead(
157           Registry.getPrimitive(demKeyTypeUrl, daeadKey.toByteString(), DeterministicAead.class));
158     } else {
159       throw new GeneralSecurityException("unknown DEM key type");
160     }
161   }
162 }
163