• 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 org.junit.Assert.assertThrows;
21 
22 import com.google.crypto.tink.InsecureSecretKeyAccess;
23 import com.google.crypto.tink.Key;
24 import com.google.crypto.tink.Parameters;
25 import com.google.crypto.tink.proto.KeyData;
26 import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
27 import com.google.crypto.tink.util.SecretBytes;
28 import com.google.errorprone.annotations.Immutable;
29 import com.google.protobuf.ByteString;
30 import java.security.GeneralSecurityException;
31 import javax.annotation.Nullable;
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 import org.junit.runners.JUnit4;
35 
36 /** Unit tests for {@link InternalConfiguration}. */
37 @RunWith(JUnit4.class)
38 public class InternalConfigurationTest {
39   // Test classes which we can populate PrimitiveRegistry instances with.
40   @Immutable
41   private static final class TestKey1 extends Key {
42     @Override
getParameters()43     public Parameters getParameters() {
44       throw new UnsupportedOperationException("Not needed in test");
45     }
46 
47     @Override
48     @Nullable
getIdRequirementOrNull()49     public Integer getIdRequirementOrNull() {
50       return null;
51     }
52 
53     @Override
equalsKey(Key other)54     public boolean equalsKey(Key other) {
55       throw new UnsupportedOperationException("Not needed in test");
56     }
57   }
58 
59   @Immutable
60   private static final class TestKey2 extends Key {
61     @Override
getParameters()62     public Parameters getParameters() {
63       throw new UnsupportedOperationException("Not needed in test");
64     }
65 
66     @Override
67     @Nullable
getIdRequirementOrNull()68     public Integer getIdRequirementOrNull() {
69       throw new UnsupportedOperationException("Not needed in test");
70     }
71 
72     @Override
equalsKey(Key other)73     public boolean equalsKey(Key other) {
74       throw new UnsupportedOperationException("Not needed in test");
75     }
76   }
77 
78   @Immutable
79   private static final class TestPrimitiveA {
80 
81     private final Key key;
82 
TestPrimitiveA()83     public TestPrimitiveA() {
84       this.key = null;
85     }
86 
TestPrimitiveA(Key key)87     public TestPrimitiveA(Key key) {
88       this.key = key;
89     }
90 
getKey()91     public Key getKey() {
92       return key;
93     }
94   }
95 
96   @Immutable
97   private static final class TestPrimitiveB {
TestPrimitiveB()98     public TestPrimitiveB() {}
99   }
100 
101   @Immutable
102   private static final class TestWrapperA
103       implements PrimitiveWrapper<TestPrimitiveA, TestPrimitiveA> {
104 
105     @Override
wrap(final PrimitiveSet<TestPrimitiveA> primitives)106     public TestPrimitiveA wrap(final PrimitiveSet<TestPrimitiveA> primitives) {
107       return new TestPrimitiveA();
108     }
109 
110     @Override
getPrimitiveClass()111     public Class<TestPrimitiveA> getPrimitiveClass() {
112       return TestPrimitiveA.class;
113     }
114 
115     @Override
getInputPrimitiveClass()116     public Class<TestPrimitiveA> getInputPrimitiveClass() {
117       return TestPrimitiveA.class;
118     }
119   }
120 
121   @Immutable
122   private static final class TestWrapperB
123       implements PrimitiveWrapper<TestPrimitiveB, TestPrimitiveB> {
124 
125     @Override
wrap(final PrimitiveSet<TestPrimitiveB> primitives)126     public TestPrimitiveB wrap(final PrimitiveSet<TestPrimitiveB> primitives) {
127       return new TestPrimitiveB();
128     }
129 
130     @Override
getPrimitiveClass()131     public Class<TestPrimitiveB> getPrimitiveClass() {
132       return TestPrimitiveB.class;
133     }
134 
135     @Override
getInputPrimitiveClass()136     public Class<TestPrimitiveB> getInputPrimitiveClass() {
137       return TestPrimitiveB.class;
138     }
139   }
140 
getPrimitiveAKey1(TestKey1 key)141   private static TestPrimitiveA getPrimitiveAKey1(TestKey1 key) {
142     return new TestPrimitiveA(key);
143   }
144 
getPrimitiveAKey2(TestKey2 key)145   private static TestPrimitiveA getPrimitiveAKey2(TestKey2 key) {
146     return new TestPrimitiveA(key);
147   }
148 
getPrimitiveBKey1(TestKey1 key)149   private static TestPrimitiveB getPrimitiveBKey1(TestKey1 key) {
150     return new TestPrimitiveB();
151   }
152 
getPrimitiveBKey2(TestKey2 key)153   private static TestPrimitiveB getPrimitiveBKey2(TestKey2 key) {
154     return new TestPrimitiveB();
155   }
156 
157   @Test
getLegacyPrimitive_throws()158   public void getLegacyPrimitive_throws() throws Exception {
159     PrimitiveRegistry registry =
160         PrimitiveRegistry.builder()
161             .registerPrimitiveConstructor(
162                 PrimitiveConstructor.create(
163                     InternalConfigurationTest::getPrimitiveAKey1,
164                     TestKey1.class,
165                     TestPrimitiveA.class))
166             .build();
167     InternalConfiguration configuration =
168         InternalConfiguration.createFromPrimitiveRegistry(registry);
169 
170     assertThrows(
171         UnsupportedOperationException.class,
172         () ->
173             configuration.getLegacyPrimitive(
174                 KeyData.newBuilder()
175                     .setValue(
176                         ByteString.copyFrom(
177                             SecretBytes.randomBytes(32).toByteArray(InsecureSecretKeyAccess.get())))
178                     .setTypeUrl("type.googleapis.com/google.crypto.tink.HmacKey")
179                     .setKeyMaterialType(KeyMaterialType.SYMMETRIC)
180                     .build(),
181                 TestPrimitiveA.class));
182   }
183 
184   @Test
getPrimitive_works()185   public void getPrimitive_works() throws Exception {
186     PrimitiveRegistry registry =
187         PrimitiveRegistry.builder()
188             .registerPrimitiveConstructor(
189                 PrimitiveConstructor.create(
190                     InternalConfigurationTest::getPrimitiveAKey1,
191                     TestKey1.class,
192                     TestPrimitiveA.class))
193             .build();
194     InternalConfiguration configuration =
195         InternalConfiguration.createFromPrimitiveRegistry(registry);
196     TestKey1 key = new TestKey1();
197 
198     TestPrimitiveA primitive = configuration.getPrimitive(key, TestPrimitiveA.class);
199 
200     assertThat(primitive.getKey()).isEqualTo(key);
201   }
202 
203   @Test
wrap_works()204   public void wrap_works() throws Exception {
205     PrimitiveRegistry registry =
206         PrimitiveRegistry.builder().registerPrimitiveWrapper(new TestWrapperA()).build();
207     InternalConfiguration configuration =
208         InternalConfiguration.createFromPrimitiveRegistry(registry);
209 
210     // Check that the type is as expected.
211     TestPrimitiveA unused = configuration.wrap(
212                 PrimitiveSet.newBuilder(TestPrimitiveA.class).build(), TestPrimitiveA.class);
213   }
214 
215   @Test
getInputPrimitiveClass_works()216   public void getInputPrimitiveClass_works() throws Exception {
217     PrimitiveRegistry registry =
218         PrimitiveRegistry.builder().registerPrimitiveWrapper(new TestWrapperA()).build();
219     InternalConfiguration configuration =
220         InternalConfiguration.createFromPrimitiveRegistry(registry);
221 
222     assertThat(configuration.getInputPrimitiveClass(TestPrimitiveA.class))
223         .isEqualTo(TestPrimitiveA.class);
224   }
225 
226   @Test
getPrimitive_dispatchWorks()227   public void getPrimitive_dispatchWorks() throws Exception {
228     PrimitiveRegistry registry =
229         PrimitiveRegistry.builder()
230             .registerPrimitiveConstructor(
231                 PrimitiveConstructor.create(
232                     InternalConfigurationTest::getPrimitiveAKey1,
233                     TestKey1.class,
234                     TestPrimitiveA.class))
235             .registerPrimitiveConstructor(
236                 PrimitiveConstructor.create(
237                     InternalConfigurationTest::getPrimitiveAKey2,
238                     TestKey2.class,
239                     TestPrimitiveA.class))
240             .registerPrimitiveConstructor(
241                 PrimitiveConstructor.create(
242                     InternalConfigurationTest::getPrimitiveBKey1,
243                     TestKey1.class,
244                     TestPrimitiveB.class))
245             .build();
246     InternalConfiguration configuration =
247         InternalConfiguration.createFromPrimitiveRegistry(registry);
248     TestKey1 key1 = new TestKey1();
249     TestKey2 key2 = new TestKey2();
250 
251     TestPrimitiveA primitiveAKey1 = configuration.getPrimitive(key1, TestPrimitiveA.class);
252     TestPrimitiveA primitiveAKey2 = configuration.getPrimitive(key2, TestPrimitiveA.class);
253 
254     assertThat(primitiveAKey1.getKey()).isEqualTo(key1);
255     assertThat(primitiveAKey2.getKey()).isEqualTo(key2);
256     // Check that the resulting primitive is of the expected type.
257     TestPrimitiveB unused = configuration.getPrimitive(key1, TestPrimitiveB.class);
258   }
259 
260   @Test
wrap_dispatchWorks()261   public void wrap_dispatchWorks() throws Exception {
262     PrimitiveRegistry registry =
263         PrimitiveRegistry.builder()
264             .registerPrimitiveWrapper(new TestWrapperA())
265             .registerPrimitiveWrapper(new TestWrapperB())
266             .build();
267     InternalConfiguration configuration =
268         InternalConfiguration.createFromPrimitiveRegistry(registry);
269 
270     // Check that the wrapped primitives are of the expected types.
271     TestPrimitiveA unusedA = configuration.wrap(
272                 PrimitiveSet.newBuilder(TestPrimitiveA.class).build(), TestPrimitiveA.class);
273     TestPrimitiveB unusedB = configuration.wrap(
274                 PrimitiveSet.newBuilder(TestPrimitiveB.class).build(), TestPrimitiveB.class);
275   }
276 
277   @Test
getInputPrimitiveClass_dispatchWorks()278   public void getInputPrimitiveClass_dispatchWorks() throws Exception {
279     PrimitiveRegistry registry =
280         PrimitiveRegistry.builder()
281             .registerPrimitiveWrapper(new TestWrapperA())
282             .registerPrimitiveWrapper(new TestWrapperB())
283             .build();
284     InternalConfiguration configuration =
285         InternalConfiguration.createFromPrimitiveRegistry(registry);
286 
287     assertThat(configuration.getInputPrimitiveClass(TestPrimitiveA.class))
288         .isEqualTo(TestPrimitiveA.class);
289     assertThat(configuration.getInputPrimitiveClass(TestPrimitiveB.class))
290         .isEqualTo(TestPrimitiveB.class);
291   }
292 
293   @Test
getPrimitive_unregisteredKeyTypeThrows()294   public void getPrimitive_unregisteredKeyTypeThrows() throws Exception {
295     PrimitiveRegistry registry =
296         PrimitiveRegistry.builder()
297             .registerPrimitiveConstructor(
298                 PrimitiveConstructor.create(
299                     InternalConfigurationTest::getPrimitiveAKey1,
300                     TestKey1.class,
301                     TestPrimitiveA.class))
302             .build();
303     InternalConfiguration configuration =
304         InternalConfiguration.createFromPrimitiveRegistry(registry);
305     TestKey2 wrongClassKey = new TestKey2();
306 
307     assertThrows(
308         GeneralSecurityException.class,
309         () -> configuration.getPrimitive(wrongClassKey, TestPrimitiveA.class));
310   }
311 
312   @Test
getPrimitive_unregisteredPrimitiveClassThrows()313   public void getPrimitive_unregisteredPrimitiveClassThrows() throws Exception {
314     PrimitiveRegistry registry =
315         PrimitiveRegistry.builder()
316             .registerPrimitiveConstructor(
317                 PrimitiveConstructor.create(
318                     InternalConfigurationTest::getPrimitiveAKey1,
319                     TestKey1.class,
320                     TestPrimitiveA.class))
321             .build();
322     InternalConfiguration configuration =
323         InternalConfiguration.createFromPrimitiveRegistry(registry);
324     TestKey1 correctClassKey = new TestKey1();
325 
326     assertThrows(
327         GeneralSecurityException.class,
328         () -> configuration.getPrimitive(correctClassKey, TestPrimitiveB.class));
329   }
330 
331   @Test
getPrimitive_wrongPrimitiveKeyClassCombinationThrows()332   public void getPrimitive_wrongPrimitiveKeyClassCombinationThrows() throws Exception {
333     PrimitiveRegistry registry =
334         PrimitiveRegistry.builder()
335             .registerPrimitiveConstructor(
336                 PrimitiveConstructor.create(
337                     InternalConfigurationTest::getPrimitiveAKey1,
338                     TestKey1.class,
339                     TestPrimitiveA.class))
340             .registerPrimitiveConstructor(
341                 PrimitiveConstructor.create(
342                     InternalConfigurationTest::getPrimitiveBKey2,
343                     TestKey2.class,
344                     TestPrimitiveB.class))
345             .build();
346     InternalConfiguration configuration =
347         InternalConfiguration.createFromPrimitiveRegistry(registry);
348 
349     assertThrows(
350         GeneralSecurityException.class,
351         () -> configuration.getPrimitive(new TestKey1(), TestPrimitiveB.class));
352     assertThrows(
353         GeneralSecurityException.class,
354         () -> configuration.getPrimitive(new TestKey2(), TestPrimitiveA.class));
355   }
356 
357   @Test
wrap_wrongInputPrimitiveClassThrows()358   public void wrap_wrongInputPrimitiveClassThrows() throws Exception {
359     PrimitiveRegistry registry =
360         PrimitiveRegistry.builder().registerPrimitiveWrapper(new TestWrapperA()).build();
361     InternalConfiguration configuration =
362         InternalConfiguration.createFromPrimitiveRegistry(registry);
363 
364     assertThrows(
365         GeneralSecurityException.class,
366         () ->
367             configuration.wrap(
368                 PrimitiveSet.newBuilder(TestPrimitiveB.class).build(), TestPrimitiveA.class));
369   }
370 
371   @Test
wrap_unregisteredWrapperClassThrows()372   public void wrap_unregisteredWrapperClassThrows() throws Exception {
373     PrimitiveRegistry registry =
374         PrimitiveRegistry.builder().registerPrimitiveWrapper(new TestWrapperA()).build();
375     InternalConfiguration configuration =
376         InternalConfiguration.createFromPrimitiveRegistry(registry);
377 
378     assertThrows(
379         GeneralSecurityException.class,
380         () ->
381             configuration.wrap(
382                 PrimitiveSet.newBuilder(TestPrimitiveA.class).build(), TestPrimitiveB.class));
383   }
384 
385   @Test
getInputPrimitiveClass_unregisteredWrapperClassThrows()386   public void getInputPrimitiveClass_unregisteredWrapperClassThrows() throws Exception {
387     PrimitiveRegistry registry =
388         PrimitiveRegistry.builder().registerPrimitiveWrapper(new TestWrapperA()).build();
389     InternalConfiguration configuration =
390         InternalConfiguration.createFromPrimitiveRegistry(registry);
391 
392     assertThrows(
393         GeneralSecurityException.class,
394         () -> configuration.getInputPrimitiveClass(TestPrimitiveB.class));
395   }
396 
397   @Test
emptyRegistry_throws()398   public void emptyRegistry_throws() {
399     PrimitiveRegistry registry = PrimitiveRegistry.builder().build();
400     InternalConfiguration configuration =
401         InternalConfiguration.createFromPrimitiveRegistry(registry);
402 
403     assertThrows(
404         GeneralSecurityException.class,
405         () -> configuration.getPrimitive(new TestKey1(), TestPrimitiveA.class));
406     assertThrows(
407         GeneralSecurityException.class,
408         () -> configuration.getInputPrimitiveClass(TestPrimitiveA.class));
409     assertThrows(
410         GeneralSecurityException.class,
411         () ->
412             configuration.wrap(
413                 PrimitiveSet.newBuilder(TestPrimitiveA.class).build(), TestPrimitiveA.class));
414   }
415 }
416