• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.internal;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static java.nio.charset.StandardCharsets.UTF_8;
21 import static org.junit.Assert.assertThrows;
22 
23 import com.google.crypto.tink.Aead;
24 import com.google.crypto.tink.InsecureSecretKeyAccess;
25 import com.google.crypto.tink.KeysetHandle;
26 import com.google.crypto.tink.Mac;
27 import com.google.crypto.tink.Registry;
28 import com.google.crypto.tink.aead.AesEaxKey;
29 import com.google.crypto.tink.aead.AesEaxParameters;
30 import com.google.crypto.tink.aead.AesEaxParameters.Variant;
31 import com.google.crypto.tink.mac.ChunkedMac;
32 import com.google.crypto.tink.mac.ChunkedMacComputation;
33 import com.google.crypto.tink.mac.HmacKey;
34 import com.google.crypto.tink.mac.HmacParameters;
35 import com.google.crypto.tink.mac.HmacParameters.HashType;
36 import com.google.crypto.tink.mac.MacConfig;
37 import com.google.crypto.tink.mac.internal.LegacyFullMac;
38 import com.google.crypto.tink.proto.HmacParams;
39 import com.google.crypto.tink.proto.KeyData;
40 import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
41 import com.google.crypto.tink.proto.KeyStatusType;
42 import com.google.crypto.tink.proto.Keyset;
43 import com.google.crypto.tink.proto.OutputPrefixType;
44 import com.google.crypto.tink.util.SecretBytes;
45 import com.google.protobuf.ByteString;
46 import java.nio.ByteBuffer;
47 import java.security.GeneralSecurityException;
48 import org.junit.Before;
49 import org.junit.Test;
50 import org.junit.runner.RunWith;
51 import org.junit.runners.JUnit4;
52 
53 /** Unit tests for {@link RegistryConfiguration}. */
54 @RunWith(JUnit4.class)
55 public class RegistryConfigurationTest {
56   private static final int HMAC_KEY_SIZE = 20;
57   private static final int HMAC_TAG_SIZE = 10;
58 
59   private static HmacKey rawKey;
60   private static KeyData rawKeyData;
61   private static Keyset.Key rawKeysetKey;
62   private static LegacyProtoKey legacyProtoRawKey;
63 
64   @Before
setUp()65   public void setUp() throws GeneralSecurityException {
66     MacConfig.register();
67     createTestKeys();
68   }
69 
createTestKeys()70   private static void createTestKeys() {
71     try {
72       rawKey =
73           HmacKey.builder()
74               .setParameters(
75                   HmacParameters.builder()
76                       .setKeySizeBytes(HMAC_KEY_SIZE)
77                       .setTagSizeBytes(HMAC_TAG_SIZE)
78                       .setVariant(HmacParameters.Variant.NO_PREFIX)
79                       .setHashType(HashType.SHA256)
80                       .build())
81               .setKeyBytes(SecretBytes.randomBytes(HMAC_KEY_SIZE))
82               .setIdRequirement(null)
83               .build();
84 
85       // Create the proto key artefacts.
86       KeysetHandle keysetHandle =
87           KeysetHandle.newBuilder()
88               .addEntry(KeysetHandle.importKey(rawKey).withRandomId().makePrimary())
89               .build();
90       rawKeyData =
91           KeyData.newBuilder()
92               .setValue(
93                   com.google.crypto.tink.proto.HmacKey.newBuilder()
94                       .setParams(
95                           HmacParams.newBuilder()
96                               .setHash(com.google.crypto.tink.proto.HashType.SHA256)
97                               .setTagSize(HMAC_TAG_SIZE)
98                               .build())
99                       .setKeyValue(
100                           ByteString.copyFrom(
101                               rawKey.getKeyBytes().toByteArray(InsecureSecretKeyAccess.get())))
102                       .build()
103                       .toByteString())
104               .setTypeUrl("type.googleapis.com/google.crypto.tink.HmacKey")
105               .setKeyMaterialType(KeyMaterialType.SYMMETRIC)
106               .build();
107       rawKeysetKey =
108           Keyset.Key.newBuilder()
109               .setKeyData(rawKeyData)
110               .setStatus(KeyStatusType.ENABLED)
111               .setKeyId(keysetHandle.getPrimary().getId())
112               .setOutputPrefixType(OutputPrefixType.RAW)
113               .build();
114       legacyProtoRawKey =
115           new LegacyProtoKey(
116               MutableSerializationRegistry.globalInstance()
117                   .serializeKey(rawKey, ProtoKeySerialization.class, InsecureSecretKeyAccess.get()),
118               InsecureSecretKeyAccess.get());
119     } catch (GeneralSecurityException e) {
120       throw new IllegalStateException(e);
121     }
122   }
123 
124   @Test
getLegacyPrimitive_matchesRegistry()125   public void getLegacyPrimitive_matchesRegistry() throws Exception {
126     byte[] plaintext = "plaintext".getBytes(UTF_8);
127 
128     Mac configurationMac =
129         RegistryConfiguration.get().getLegacyPrimitive(rawKeyData, Mac.class);
130     Mac registryMac = Registry.getPrimitive(rawKeyData, Mac.class);
131 
132     assertThat(configurationMac.computeMac(plaintext)).isEqualTo(registryMac.computeMac(plaintext));
133   }
134 
135   @Test
getPrimitive_matchesRegistry()136   public void getPrimitive_matchesRegistry() throws Exception {
137     byte[] plaintext = "plaintext".getBytes(UTF_8);
138 
139     ChunkedMac configurationMac =
140         RegistryConfiguration.get().getPrimitive(rawKey, ChunkedMac.class);
141     ChunkedMacComputation configurationComputation = configurationMac.createComputation();
142     ChunkedMac registryMac =
143         MutablePrimitiveRegistry.globalInstance().getPrimitive(rawKey, ChunkedMac.class);
144     ChunkedMacComputation registryComputation = registryMac.createComputation();
145 
146     configurationComputation.update(ByteBuffer.wrap(plaintext));
147     registryComputation.update(ByteBuffer.wrap(plaintext));
148 
149     assertThat(configurationComputation.computeMac()).isEqualTo(registryComputation.computeMac());
150   }
151 
152   @Test
wrap_matchesRegistry()153   public void wrap_matchesRegistry() throws Exception {
154     byte[] plaintext = "plaintext".getBytes(UTF_8);
155 
156     Mac registryMac = Registry.getPrimitive(rawKeyData, Mac.class);
157     // The following relies on the fact that internally LegacyFullMac uses RegistryConfiguration.
158     Mac wrappedConfigurationMac =
159         RegistryConfiguration.get()
160             .wrap(
161                 PrimitiveSet.newBuilder(Mac.class)
162                     .addPrimaryFullPrimitive(
163                         LegacyFullMac.create(legacyProtoRawKey), legacyProtoRawKey, rawKeysetKey)
164                     .build(),
165                 Mac.class);
166 
167     assertThat(wrappedConfigurationMac.computeMac(plaintext))
168         .isEqualTo(registryMac.computeMac(plaintext));
169   }
170 
171   @Test
getInputPrimitiveClass_matchesRegistry()172   public void getInputPrimitiveClass_matchesRegistry() throws Exception {
173     assertThat(RegistryConfiguration.get().getInputPrimitiveClass(ChunkedMac.class))
174         .isEqualTo(Registry.getInputPrimitive(ChunkedMac.class));
175   }
176 
177   @Test
getInputPrimitiveClass_returnsNullOnUnregisteredPrimitive()178   public void getInputPrimitiveClass_returnsNullOnUnregisteredPrimitive() throws Exception {
179     assertThat(RegistryConfiguration.get().getInputPrimitiveClass(Aead.class))
180         .isNull();
181   }
182 
183   @Test
requestingUnregisteredPrimitives_throws()184   public void requestingUnregisteredPrimitives_throws() throws GeneralSecurityException {
185     AesEaxKey aesEaxKey =
186         AesEaxKey.builder()
187             .setKeyBytes(SecretBytes.randomBytes(32))
188             .setIdRequirement(1234)
189             .setParameters(
190                 AesEaxParameters.builder()
191                     .setIvSizeBytes(16)
192                     .setTagSizeBytes(16)
193                     .setKeySizeBytes(32)
194                     .setVariant(Variant.TINK)
195                     .build())
196             .build();
197 
198     assertThrows(
199         GeneralSecurityException.class,
200         () -> RegistryConfiguration.get().getPrimitive(aesEaxKey, Aead.class));
201     assertThrows(
202         GeneralSecurityException.class,
203         () ->
204             RegistryConfiguration.get()
205                 .wrap(PrimitiveSet.newBuilder(Aead.class).build(), Aead.class));
206   }
207 }
208