• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 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;
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.internal.KeyParser;
24 import com.google.crypto.tink.internal.KeySerializer;
25 import com.google.crypto.tink.internal.MutablePrimitiveRegistry;
26 import com.google.crypto.tink.internal.MutableSerializationRegistry;
27 import com.google.crypto.tink.internal.PrimitiveConstructor;
28 import com.google.crypto.tink.internal.PrimitiveSet;
29 import com.google.crypto.tink.internal.PrimitiveSet.Entry;
30 import com.google.crypto.tink.internal.PrimitiveWrapper;
31 import com.google.crypto.tink.internal.ProtoKeySerialization;
32 import com.google.crypto.tink.mac.AesCmacKey;
33 import com.google.crypto.tink.mac.AesCmacParameters;
34 import com.google.crypto.tink.mac.AesCmacParameters.Variant;
35 import com.google.crypto.tink.mac.MacConfig;
36 import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
37 import com.google.crypto.tink.proto.OutputPrefixType;
38 import com.google.crypto.tink.util.Bytes;
39 import com.google.crypto.tink.util.SecretBytes;
40 import com.google.protobuf.ByteString;
41 import java.security.GeneralSecurityException;
42 import java.util.List;
43 import javax.annotation.Nullable;
44 import org.junit.Test;
45 import org.junit.runner.RunWith;
46 import org.junit.runners.JUnit4;
47 
48 /**
49  * Tests how {@link KeysetHandle} handles the situation when there is a {@link
50  * PrimitiveSet#fullPrimitive} registered.
51  */
52 @RunWith(JUnit4.class)
53 public class KeysetHandleFullPrimitiveTest {
54 
55   private static final PrimitiveConstructor<TestKey, SingleTestPrimitive>
56       TEST_PRIMITIVE_CONSTRUCTOR =
57           PrimitiveConstructor.create(
58               KeysetHandleFullPrimitiveTest::createTestPrimitive,
59               TestKey.class,
60               SingleTestPrimitive.class);
61   public static final KeySerializer<TestKey, ProtoKeySerialization> TEST_KEY_SERIALIZER =
62       KeySerializer.create(
63           KeysetHandleFullPrimitiveTest::serializeTestKey,
64           TestKey.class,
65           ProtoKeySerialization.class);
66   public static final KeyParser<ProtoKeySerialization> TEST_KEY_PARSER =
67       KeyParser.create(
68           KeysetHandleFullPrimitiveTest::parseTestKey,
69           Bytes.copyFrom("testKeyForFullPrimitiveUrl".getBytes(UTF_8)),
70           ProtoKeySerialization.class);
71 
72   private static class SingleTestPrimitive {}
73 
74   /**
75    * In combination with {@link KeysetHandleFullPrimitiveTest#TestWrapper}, this test primitive lets
76    * us check some assumptions about the {@link PrimitiveSet} which was created by the {@link
77    * KeysetHandle}.
78    */
79   private static class WrappedTestPrimitive {
80 
81     private final PrimitiveSet<SingleTestPrimitive> primitiveSet;
82 
WrappedTestPrimitive(PrimitiveSet<SingleTestPrimitive> primitiveSet)83     WrappedTestPrimitive(PrimitiveSet<SingleTestPrimitive> primitiveSet) {
84       this.primitiveSet = primitiveSet;
85     }
86 
getPrimitiveSet()87     PrimitiveSet<SingleTestPrimitive> getPrimitiveSet() {
88       return primitiveSet;
89     }
90   }
91 
92   private static class TestWrapper
93       implements PrimitiveWrapper<SingleTestPrimitive, WrappedTestPrimitive> {
94 
95     private static final TestWrapper WRAPPER = new TestWrapper();
96 
97     @Override
wrap(PrimitiveSet<SingleTestPrimitive> primitiveSet)98     public WrappedTestPrimitive wrap(PrimitiveSet<SingleTestPrimitive> primitiveSet)
99         throws GeneralSecurityException {
100       return new WrappedTestPrimitive(primitiveSet);
101     }
102 
103     @Override
getPrimitiveClass()104     public Class<WrappedTestPrimitive> getPrimitiveClass() {
105       return WrappedTestPrimitive.class;
106     }
107 
108     @Override
getInputPrimitiveClass()109     public Class<SingleTestPrimitive> getInputPrimitiveClass() {
110       return SingleTestPrimitive.class;
111     }
112 
register()113     public static void register() throws GeneralSecurityException {
114       MutablePrimitiveRegistry.globalInstance().registerPrimitiveWrapper(WRAPPER);
115     }
116   }
117 
118   private static final class TestKey extends Key {
119 
120     private final int id;
121 
TestKey(int id)122     TestKey(int id) {
123       this.id = id;
124     }
125 
126     @Override
getParameters()127     public Parameters getParameters() {
128       throw new UnsupportedOperationException("Not needed in test");
129     }
130 
131     @Override
getIdRequirementOrNull()132     public Integer getIdRequirementOrNull() {
133       return id;
134     }
135 
136     @Override
equalsKey(Key other)137     public boolean equalsKey(Key other) {
138       throw new UnsupportedOperationException("Not needed in test");
139     }
140 
getId()141     public int getId() {
142       return id;
143     }
144   }
145 
serializeTestKey( TestKey key, @Nullable SecretKeyAccess access)146   private static ProtoKeySerialization serializeTestKey(
147       TestKey key, @Nullable SecretKeyAccess access) throws GeneralSecurityException {
148     return ProtoKeySerialization.create(
149         "testKeyForFullPrimitiveUrl",
150         ByteString.EMPTY,
151         KeyMaterialType.ASYMMETRIC_PUBLIC,
152         OutputPrefixType.TINK,
153         key.getId());
154   }
155 
parseTestKey( ProtoKeySerialization serialization, @Nullable SecretKeyAccess access)156   private static TestKey parseTestKey(
157       ProtoKeySerialization serialization, @Nullable SecretKeyAccess access) {
158     return new TestKey(serialization.getIdRequirementOrNull());
159   }
160 
createTestPrimitive(TestKey key)161   private static SingleTestPrimitive createTestPrimitive(TestKey key)
162       throws GeneralSecurityException {
163     return new SingleTestPrimitive();
164   }
165 
166   /**
167    * In combination with {@link KeysetHandleFullPrimitiveTest#MacTestWrapper}, this test primitive
168    * lets us check some assumptions about the {@link PrimitiveSet} which was created by the {@link
169    * KeysetHandle}.
170    */
171   private static class WrappedMacTestPrimitive {
172 
173     private final PrimitiveSet<Mac> primitiveSet;
174 
WrappedMacTestPrimitive(PrimitiveSet<Mac> primitiveSet)175     WrappedMacTestPrimitive(PrimitiveSet<Mac> primitiveSet) {
176       this.primitiveSet = primitiveSet;
177     }
178 
getPrimitiveSet()179     PrimitiveSet<Mac> getPrimitiveSet() {
180       return primitiveSet;
181     }
182   }
183 
184   private static class MacTestWrapper implements PrimitiveWrapper<Mac, WrappedMacTestPrimitive> {
185 
186     private static final MacTestWrapper WRAPPER = new MacTestWrapper();
187 
188     @Override
wrap(PrimitiveSet<Mac> primitiveSet)189     public WrappedMacTestPrimitive wrap(PrimitiveSet<Mac> primitiveSet)
190         throws GeneralSecurityException {
191       return new WrappedMacTestPrimitive(primitiveSet);
192     }
193 
194     @Override
getPrimitiveClass()195     public Class<WrappedMacTestPrimitive> getPrimitiveClass() {
196       return WrappedMacTestPrimitive.class;
197     }
198 
199     @Override
getInputPrimitiveClass()200     public Class<Mac> getInputPrimitiveClass() {
201       return Mac.class;
202     }
203 
register()204     public static void register() throws GeneralSecurityException {
205       MutablePrimitiveRegistry.globalInstance().registerPrimitiveWrapper(WRAPPER);
206     }
207   }
208 
209   @Test
getPrimitive_fullPrimitiveWithoutPrimitive_worksCorrectly()210   public void getPrimitive_fullPrimitiveWithoutPrimitive_worksCorrectly() throws Exception {
211     Registry.reset();
212     MutableSerializationRegistry.globalInstance().registerKeySerializer(TEST_KEY_SERIALIZER);
213     MutableSerializationRegistry.globalInstance().registerKeyParser(TEST_KEY_PARSER);
214     MutablePrimitiveRegistry.globalInstance()
215         .registerPrimitiveConstructor(TEST_PRIMITIVE_CONSTRUCTOR);
216     TestWrapper.register();
217     KeysetHandle keysetHandle =
218         KeysetHandle.newBuilder()
219             .addEntry(
220                 KeysetHandle.importKey(new TestKey(1234))
221                     .setStatus(KeyStatus.ENABLED)
222                     .withFixedId(1234)
223                     .makePrimary())
224             .addEntry(
225                 KeysetHandle.importKey(new TestKey(1235))
226                     .setStatus(KeyStatus.ENABLED)
227                     .withFixedId(1235))
228             .addEntry(
229                 KeysetHandle.importKey(new TestKey(1236))
230                     .setStatus(KeyStatus.ENABLED)
231                     .withFixedId(1236))
232             .addEntry(
233                 KeysetHandle.importKey(new TestKey(1237))
234                     .setStatus(KeyStatus.ENABLED)
235                     .withFixedId(1237))
236             .build();
237 
238     WrappedTestPrimitive primitive =
239         keysetHandle.getPrimitive(RegistryConfiguration.get(), WrappedTestPrimitive.class);
240 
241     for (List<Entry<SingleTestPrimitive>> list : primitive.getPrimitiveSet().getAll()) {
242       for (PrimitiveSet.Entry<SingleTestPrimitive> entry : list) {
243         assertThat(entry.getFullPrimitive()).isNotNull();
244       }
245     }
246   }
247 
248   @Test
getPrimitive_noFullPrimitiveNoPrimitive_throws()249   public void getPrimitive_noFullPrimitiveNoPrimitive_throws() throws Exception {
250     Registry.reset();
251     MutableSerializationRegistry.globalInstance().registerKeySerializer(TEST_KEY_SERIALIZER);
252     MutableSerializationRegistry.globalInstance().registerKeyParser(TEST_KEY_PARSER);
253     KeysetHandle keysetHandle =
254         KeysetHandle.newBuilder()
255             .addEntry(
256                 KeysetHandle.importKey(new TestKey(1234))
257                     .setStatus(KeyStatus.ENABLED)
258                     .withFixedId(1234)
259                     .makePrimary())
260             .addEntry(
261                 KeysetHandle.importKey(new TestKey(1235))
262                     .setStatus(KeyStatus.ENABLED)
263                     .withFixedId(1235))
264             .addEntry(
265                 KeysetHandle.importKey(new TestKey(1236))
266                     .setStatus(KeyStatus.ENABLED)
267                     .withFixedId(1236))
268             .addEntry(
269                 KeysetHandle.importKey(new TestKey(1237))
270                     .setStatus(KeyStatus.ENABLED)
271                     .withFixedId(1237))
272             .build();
273 
274     assertThrows(
275         GeneralSecurityException.class,
276         () -> keysetHandle.getPrimitive(RegistryConfiguration.get(), WrappedTestPrimitive.class));
277   }
278 
279   @Test
getPrimitive_fullPrimitiveWithPrimitive_worksCorrectly()280   public void getPrimitive_fullPrimitiveWithPrimitive_worksCorrectly() throws Exception {
281     Registry.reset();
282     MacTestWrapper.register();
283     MacConfig.register();
284     AesCmacParameters parameters =
285         AesCmacParameters.builder()
286             .setKeySizeBytes(32)
287             .setTagSizeBytes(10)
288             .setVariant(Variant.TINK)
289             .build();
290     KeysetHandle keysetHandle =
291         KeysetHandle.newBuilder()
292             .addEntry(
293                 KeysetHandle.importKey(
294                         AesCmacKey.builder()
295                             .setParameters(parameters)
296                             .setAesKeyBytes(SecretBytes.randomBytes(32))
297                             .setIdRequirement(1234)
298                             .build())
299                     .setStatus(KeyStatus.ENABLED)
300                     .withFixedId(1234)
301                     .makePrimary())
302             .addEntry(
303                 KeysetHandle.importKey(
304                         AesCmacKey.builder()
305                             .setParameters(parameters)
306                             .setAesKeyBytes(SecretBytes.randomBytes(32))
307                             .setIdRequirement(1235)
308                             .build())
309                     .setStatus(KeyStatus.ENABLED)
310                     .withFixedId(1235))
311             .addEntry(
312                 KeysetHandle.importKey(
313                         AesCmacKey.builder()
314                             .setParameters(parameters)
315                             .setAesKeyBytes(SecretBytes.randomBytes(32))
316                             .setIdRequirement(1236)
317                             .build())
318                     .setStatus(KeyStatus.ENABLED)
319                     .withFixedId(1236))
320             .addEntry(
321                 KeysetHandle.importKey(
322                         AesCmacKey.builder()
323                             .setParameters(parameters)
324                             .setAesKeyBytes(SecretBytes.randomBytes(32))
325                             .setIdRequirement(1237)
326                             .build())
327                     .setStatus(KeyStatus.ENABLED)
328                     .withFixedId(1237))
329             .build();
330 
331     WrappedMacTestPrimitive primitive =
332         keysetHandle.getPrimitive(RegistryConfiguration.get(), WrappedMacTestPrimitive.class);
333 
334     for (List<Entry<Mac>> list : primitive.getPrimitiveSet().getAll()) {
335       for (PrimitiveSet.Entry<Mac> entry : list) {
336         assertThat(entry.getFullPrimitive()).isNotNull();
337       }
338     }
339   }
340 }
341