• 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.mac;
18 
19 import static java.nio.charset.StandardCharsets.UTF_8;
20 
21 import com.google.crypto.tink.Key;
22 import com.google.crypto.tink.KeysetHandle;
23 import com.google.crypto.tink.Mac;
24 import com.google.crypto.tink.RegistryConfiguration;
25 import com.google.crypto.tink.mac.AesCmacParameters.Variant;
26 import com.google.crypto.tink.mac.HmacParameters.HashType;
27 import com.google.crypto.tink.mac.internal.AesCmacProtoSerialization;
28 import com.google.crypto.tink.mac.internal.HmacProtoSerialization;
29 import com.google.crypto.tink.util.SecretBytes;
30 import java.nio.ByteBuffer;
31 import java.security.GeneralSecurityException;
32 import org.junit.BeforeClass;
33 import org.junit.experimental.theories.DataPoints;
34 import org.junit.experimental.theories.FromDataPoints;
35 import org.junit.experimental.theories.Theories;
36 import org.junit.experimental.theories.Theory;
37 import org.junit.runner.RunWith;
38 
39 /**
40  * These tests ensure interoperability between the new ChunkedMac implementations and the old Mac
41  * implementations.
42  */
43 @RunWith(Theories.class)
44 public class ChunkedMacTest {
45   private static final int HMAC_KEY_SIZE = 20;
46   private static final int HMAC_TAG_SIZE = 10;
47   private static final int AES_CMAC_KEY_SIZE = 32;
48   private static final int AES_CMAC_TAG_SIZE = 10;
49 
50   @DataPoints("keys")
51   public static Key[] keys;
52 
53   @BeforeClass
setUp()54   public static void setUp() throws Exception {
55     MacConfig.register();
56     AesCmacProtoSerialization.register();
57     HmacProtoSerialization.register();
58     ChunkedMacWrapper.register();
59     createTestKeys();
60   }
61 
createTestKeys()62   private static void createTestKeys() {
63     HmacParameters noPrefixHmacParameters =
64         createDefaultHmacParameters(HmacParameters.Variant.NO_PREFIX);
65     HmacParameters legacyHmacParameters =
66         createDefaultHmacParameters(HmacParameters.Variant.LEGACY);
67     HmacParameters crunchyHmacParameters =
68         createDefaultHmacParameters(HmacParameters.Variant.CRUNCHY);
69     HmacParameters tinkHmacParameters =
70         createDefaultHmacParameters(HmacParameters.Variant.TINK);
71     AesCmacParameters noPrefixAesCmacParameters =
72         createDefaultAesCmacParameters(AesCmacParameters.Variant.NO_PREFIX);
73     AesCmacParameters legacyAesCmacParameters =
74         createDefaultAesCmacParameters(AesCmacParameters.Variant.LEGACY);
75     AesCmacParameters crunchyAesCmacParameters =
76         createDefaultAesCmacParameters(AesCmacParameters.Variant.CRUNCHY);
77     AesCmacParameters tinkAesCmacParameters =
78         createDefaultAesCmacParameters(AesCmacParameters.Variant.TINK);
79 
80     try {
81       keys =
82           new Key[] {
83             HmacKey.builder()
84                 .setParameters(noPrefixHmacParameters)
85                 .setKeyBytes(SecretBytes.randomBytes(HMAC_KEY_SIZE))
86                 .setIdRequirement(null)
87                 .build(),
88             AesCmacKey.builder()
89                 .setParameters(noPrefixAesCmacParameters)
90                 .setAesKeyBytes(SecretBytes.randomBytes(AES_CMAC_KEY_SIZE))
91                 .setIdRequirement(null)
92                 .build(),
93             HmacKey.builder()
94                 .setParameters(tinkHmacParameters)
95                 .setKeyBytes(SecretBytes.randomBytes(HMAC_KEY_SIZE))
96                 .setIdRequirement(4)
97                 .build(),
98             AesCmacKey.builder()
99                 .setParameters(tinkAesCmacParameters)
100                 .setAesKeyBytes(SecretBytes.randomBytes(AES_CMAC_KEY_SIZE))
101                 .setIdRequirement(5)
102                 .build(),
103             HmacKey.builder()
104                 .setParameters(crunchyHmacParameters)
105                 .setKeyBytes(SecretBytes.randomBytes(HMAC_KEY_SIZE))
106                 .setIdRequirement(6)
107                 .build(),
108             AesCmacKey.builder()
109                 .setParameters(crunchyAesCmacParameters)
110                 .setAesKeyBytes(SecretBytes.randomBytes(AES_CMAC_KEY_SIZE))
111                 .setIdRequirement(7)
112                 .build(),
113             HmacKey.builder()
114                 .setParameters(legacyHmacParameters)
115                 .setKeyBytes(SecretBytes.randomBytes(HMAC_KEY_SIZE))
116                 .setIdRequirement(8)
117                 .build(),
118             AesCmacKey.builder()
119                 .setParameters(legacyAesCmacParameters)
120                 .setAesKeyBytes(SecretBytes.randomBytes(AES_CMAC_KEY_SIZE))
121                 .setIdRequirement(9)
122                 .build(),
123           };
124     } catch (GeneralSecurityException e) {
125       throw new IllegalStateException(e);
126     }
127   }
128 
createDefaultAesCmacParameters(Variant variant)129   private static AesCmacParameters createDefaultAesCmacParameters(Variant variant) {
130     try {
131       return AesCmacParameters.builder()
132           .setKeySizeBytes(AES_CMAC_KEY_SIZE)
133           .setTagSizeBytes(AES_CMAC_TAG_SIZE)
134           .setVariant(variant)
135           .build();
136     } catch (GeneralSecurityException e) {
137       throw new IllegalStateException(e);
138     }
139   }
140 
createDefaultHmacParameters(HmacParameters.Variant variant)141   private static HmacParameters createDefaultHmacParameters(HmacParameters.Variant variant) {
142     try {
143       return HmacParameters.builder()
144           .setKeySizeBytes(HMAC_KEY_SIZE)
145           .setTagSizeBytes(HMAC_TAG_SIZE)
146           .setVariant(variant)
147           .setHashType(HashType.SHA256)
148           .build();
149     } catch (GeneralSecurityException e) {
150       throw new IllegalArgumentException("Incorrect parameters creation arguments", e);
151     }
152   }
153 
154   @Theory
computeWithMacVerifyWithChunkedMac_works(@romDataPoints"keys") Key key)155   public void computeWithMacVerifyWithChunkedMac_works(@FromDataPoints("keys") Key key)
156       throws GeneralSecurityException {
157     byte[] plaintext = "plaintext".getBytes(UTF_8);
158     KeysetHandle.Builder.Entry entry = KeysetHandle.importKey(key);
159     if (key.getIdRequirementOrNull() == null) {
160       entry.withFixedId(1234);
161     }
162     KeysetHandle keysetHandle = KeysetHandle.newBuilder().addEntry(entry.makePrimary()).build();
163 
164     Mac mac = keysetHandle.getPrimitive(RegistryConfiguration.get(), Mac.class);
165     byte[] tag = mac.computeMac(plaintext);
166     ChunkedMac chunkedMac =
167         keysetHandle.getPrimitive(RegistryConfiguration.get(), ChunkedMac.class);
168     ChunkedMacVerification chunkedMacVerification = chunkedMac.createVerification(tag);
169     chunkedMacVerification.update(ByteBuffer.wrap(plaintext));
170 
171     chunkedMacVerification.verifyMac();
172   }
173 
174   @Theory
computeWithChunkedMacVerifyWithMac_works(@romDataPoints"keys") Key key)175   public void computeWithChunkedMacVerifyWithMac_works(@FromDataPoints("keys") Key key)
176       throws GeneralSecurityException {
177     byte[] plaintext = "plaintext".getBytes(UTF_8);
178     KeysetHandle.Builder.Entry entry = KeysetHandle.importKey(key);
179     if (key.getIdRequirementOrNull() == null) {
180       entry.withFixedId(1234);
181     }
182     KeysetHandle keysetHandle = KeysetHandle.newBuilder().addEntry(entry.makePrimary()).build();
183 
184     ChunkedMac chunkedMac =
185         keysetHandle.getPrimitive(RegistryConfiguration.get(), ChunkedMac.class);
186     ChunkedMacComputation chunkedMacComputation = chunkedMac.createComputation();
187     chunkedMacComputation.update(ByteBuffer.wrap(plaintext));
188     byte[] tag = chunkedMacComputation.computeMac();
189     Mac mac = keysetHandle.getPrimitive(RegistryConfiguration.get(), Mac.class);
190 
191     mac.verifyMac(tag, plaintext);
192   }
193 }
194