1 // Copyright 2017 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.prf; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static org.junit.Assert.assertThrows; 21 import static org.junit.Assert.assertTrue; 22 23 import com.google.crypto.tink.InsecureSecretKeyAccess; 24 import com.google.crypto.tink.KeyTemplate; 25 import com.google.crypto.tink.KeyTemplates; 26 import com.google.crypto.tink.KeysetHandle; 27 import com.google.crypto.tink.Parameters; 28 import com.google.crypto.tink.RegistryConfiguration; 29 import com.google.crypto.tink.TinkProtoKeysetFormat; 30 import com.google.crypto.tink.internal.KeyManagerRegistry; 31 import com.google.crypto.tink.subtle.Hex; 32 import com.google.crypto.tink.subtle.PrfAesCmac; 33 import com.google.crypto.tink.util.SecretBytes; 34 import java.security.GeneralSecurityException; 35 import java.util.Set; 36 import java.util.TreeSet; 37 import org.junit.Before; 38 import org.junit.Test; 39 import org.junit.experimental.theories.DataPoints; 40 import org.junit.experimental.theories.FromDataPoints; 41 import org.junit.experimental.theories.Theories; 42 import org.junit.experimental.theories.Theory; 43 import org.junit.runner.RunWith; 44 45 /** Test for AesCmacPrfKeyManager. */ 46 @RunWith(Theories.class) 47 public class AesCmacPrfKeyManagerTest { 48 49 @Before register()50 public void register() throws Exception { 51 PrfConfig.register(); 52 } 53 54 @Test testAes256CmacTemplate()55 public void testAes256CmacTemplate() throws Exception { 56 KeyTemplate template = AesCmacPrfKeyManager.aes256CmacTemplate(); 57 assertThat(template.toParameters()).isEqualTo(AesCmacPrfParameters.create(32)); 58 } 59 60 @Test testKeyTemplateAndManagerCompatibility()61 public void testKeyTemplateAndManagerCompatibility() throws Exception { 62 Parameters p = AesCmacPrfKeyManager.aes256CmacTemplate().toParameters(); 63 assertThat(KeysetHandle.generateNew(p).getAt(0).getKey().getParameters()).isEqualTo(p); 64 } 65 66 @DataPoints("templateNames") 67 public static final String[] KEY_TEMPLATES = 68 new String[] { 69 "AES256_CMAC_PRF", "AES_CMAC_PRF", 70 }; 71 72 @Theory testTemplates(@romDataPoints"templateNames") String templateName)73 public void testTemplates(@FromDataPoints("templateNames") String templateName) throws Exception { 74 KeysetHandle h = KeysetHandle.generateNew(KeyTemplates.get(templateName)); 75 assertThat(h.size()).isEqualTo(1); 76 assertThat(h.getAt(0).getKey().getParameters()) 77 .isEqualTo(KeyTemplates.get(templateName).toParameters()); 78 } 79 80 @Test testKeyManagerRegistered()81 public void testKeyManagerRegistered() throws Exception { 82 assertThat( 83 KeyManagerRegistry.globalInstance() 84 .getKeyManager("type.googleapis.com/google.crypto.tink.AesCmacPrfKey", Prf.class)) 85 .isNotNull(); 86 } 87 88 @Test createKey_works()89 public void createKey_works() throws Exception { 90 AesCmacPrfParameters params = AesCmacPrfParameters.create(32); 91 KeysetHandle handle = KeysetHandle.generateNew(params); 92 assertThat(handle.size()).isEqualTo(1); 93 AesCmacPrfKey key = (AesCmacPrfKey) handle.getAt(0).getKey(); 94 assertThat(key.getParameters()).isEqualTo(params); 95 } 96 97 @Test createKey_differentKeyValues_alwaysDifferent()98 public void createKey_differentKeyValues_alwaysDifferent() throws Exception { 99 AesCmacPrfParameters params = AesCmacPrfParameters.create(32); 100 101 int numKeys = 100; 102 Set<String> keys = new TreeSet<>(); 103 for (int i = 0; i < numKeys; i++) { 104 KeysetHandle handle = KeysetHandle.generateNew(params); 105 assertThat(handle.size()).isEqualTo(1); 106 AesCmacPrfKey key = (AesCmacPrfKey) handle.getAt(0).getKey(); 107 keys.add(Hex.encode(key.getKeyBytes().toByteArray(InsecureSecretKeyAccess.get()))); 108 } 109 assertThat(keys).hasSize(numKeys); 110 } 111 112 @Test createPrimitiveAndUseIt_works()113 public void createPrimitiveAndUseIt_works() throws Exception { 114 AesCmacPrfParameters params = AesCmacPrfParameters.create(32); 115 KeysetHandle handle = KeysetHandle.generateNew(params); 116 assertThat(handle.size()).isEqualTo(1); 117 PrfSet prfSet = handle.getPrimitive(RegistryConfiguration.get(), PrfSet.class); 118 Prf directPrf = PrfAesCmac.create((AesCmacPrfKey) handle.getAt(0).getKey()); 119 assertThat(prfSet.computePrimary(new byte[0], 16)) 120 .isEqualTo(directPrf.compute(new byte[0], 16)); 121 } 122 123 @Test serializeAndDeserializeKeysets()124 public void serializeAndDeserializeKeysets() throws Exception { 125 AesCmacPrfParameters params = AesCmacPrfParameters.create(32); 126 KeysetHandle handle = KeysetHandle.generateNew(params); 127 128 byte[] serializedKeyset = 129 TinkProtoKeysetFormat.serializeKeyset(handle, InsecureSecretKeyAccess.get()); 130 KeysetHandle parsed = 131 TinkProtoKeysetFormat.parseKeyset(serializedKeyset, InsecureSecretKeyAccess.get()); 132 assertTrue(parsed.equalsKeyset(handle)); 133 } 134 135 @Test createKeyWith16Bytes_throws()136 public void createKeyWith16Bytes_throws() throws Exception { 137 AesCmacPrfParameters params = AesCmacPrfParameters.create(16); 138 assertThrows(GeneralSecurityException.class, () -> KeysetHandle.generateNew(params)); 139 } 140 141 @Test createPrimitiveWith16Bytes_throws()142 public void createPrimitiveWith16Bytes_throws() throws Exception { 143 AesCmacPrfParameters params = AesCmacPrfParameters.create(16); 144 AesCmacPrfKey key = AesCmacPrfKey.create(params, SecretBytes.randomBytes(16)); 145 KeysetHandle handle = 146 KeysetHandle.newBuilder() 147 .addEntry(KeysetHandle.importKey(key).withFixedId(1).makePrimary()) 148 .build(); 149 assertThrows( 150 GeneralSecurityException.class, 151 () -> handle.getPrimitive(RegistryConfiguration.get(), PrfSet.class)); 152 } 153 154 @Test serializeDeserializeKeysetsWith16Bytes_works()155 public void serializeDeserializeKeysetsWith16Bytes_works() throws Exception { 156 AesCmacPrfParameters params = AesCmacPrfParameters.create(16); 157 AesCmacPrfKey key = AesCmacPrfKey.create(params, SecretBytes.randomBytes(16)); 158 KeysetHandle handle = 159 KeysetHandle.newBuilder() 160 .addEntry(KeysetHandle.importKey(key).withFixedId(1).makePrimary()) 161 .build(); 162 byte[] serializedKeyset = 163 TinkProtoKeysetFormat.serializeKeyset(handle, InsecureSecretKeyAccess.get()); 164 KeysetHandle parsed = 165 TinkProtoKeysetFormat.parseKeyset(serializedKeyset, InsecureSecretKeyAccess.get()); 166 assertTrue(parsed.equalsKeyset(handle)); 167 } 168 } 169