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.aead; 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.internal.KeyTester; 24 import com.google.crypto.tink.subtle.Hex; 25 import com.google.crypto.tink.util.Bytes; 26 import com.google.crypto.tink.util.SecretBytes; 27 import java.security.GeneralSecurityException; 28 import org.junit.Test; 29 import org.junit.runner.RunWith; 30 import org.junit.runners.JUnit4; 31 32 @RunWith(JUnit4.class) 33 public final class AesGcmSivKeyTest { 34 @Test buildNoPrefixVariantAndGetProperties()35 public void buildNoPrefixVariantAndGetProperties() throws Exception { 36 AesGcmSivParameters parameters = 37 AesGcmSivParameters.builder() 38 .setKeySizeBytes(16) 39 .setVariant(AesGcmSivParameters.Variant.NO_PREFIX) 40 .build(); 41 assertThat(parameters.hasIdRequirement()).isFalse(); 42 SecretBytes keyBytes = SecretBytes.randomBytes(16); 43 AesGcmSivKey key = 44 AesGcmSivKey.builder().setParameters(parameters).setKeyBytes(keyBytes).build(); 45 assertThat(key.getParameters()).isEqualTo(parameters); 46 assertThat(key.getKeyBytes()).isEqualTo(keyBytes); 47 assertThat(key.getOutputPrefix()).isEqualTo(Bytes.copyFrom(new byte[] {})); 48 assertThat(key.getIdRequirementOrNull()).isNull(); 49 } 50 51 @Test buildTinkVariantAndGetProperties()52 public void buildTinkVariantAndGetProperties() throws Exception { 53 AesGcmSivParameters parameters = 54 AesGcmSivParameters.builder() 55 .setKeySizeBytes(16) 56 .setVariant(AesGcmSivParameters.Variant.TINK) 57 .build(); 58 assertThat(parameters.hasIdRequirement()).isTrue(); 59 SecretBytes keyBytes = SecretBytes.randomBytes(16); 60 AesGcmSivKey key = 61 AesGcmSivKey.builder() 62 .setParameters(parameters) 63 .setKeyBytes(keyBytes) 64 .setIdRequirement(0x66AABBCC) 65 .build(); 66 assertThat(key.getParameters()).isEqualTo(parameters); 67 assertThat(key.getKeyBytes()).isEqualTo(keyBytes); 68 assertThat(key.getOutputPrefix()).isEqualTo(Bytes.copyFrom(Hex.decode("0166AABBCC"))); 69 assertThat(key.getIdRequirementOrNull()).isEqualTo(0x66AABBCC); 70 } 71 72 @Test buildCrunchyVariantAndGetProperties()73 public void buildCrunchyVariantAndGetProperties() throws Exception { 74 AesGcmSivParameters parameters = 75 AesGcmSivParameters.builder() 76 .setKeySizeBytes(32) 77 .setVariant(AesGcmSivParameters.Variant.CRUNCHY) 78 .build(); 79 assertThat(parameters.hasIdRequirement()).isTrue(); 80 SecretBytes keyBytes = SecretBytes.randomBytes(32); 81 AesGcmSivKey key = 82 AesGcmSivKey.builder() 83 .setParameters(parameters) 84 .setKeyBytes(keyBytes) 85 .setIdRequirement(0x66AABBCC) 86 .build(); 87 assertThat(key.getParameters()).isEqualTo(parameters); 88 assertThat(key.getKeyBytes()).isEqualTo(keyBytes); 89 assertThat(key.getOutputPrefix()).isEqualTo(Bytes.copyFrom(Hex.decode("0066AABBCC"))); 90 assertThat(key.getIdRequirementOrNull()).isEqualTo(0x66AABBCC); 91 } 92 93 @Test emptyBuild_fails()94 public void emptyBuild_fails() throws Exception { 95 assertThrows(GeneralSecurityException.class, () -> AesGcmSivKey.builder().build()); 96 } 97 98 @Test buildWithoutParameters_fails()99 public void buildWithoutParameters_fails() throws Exception { 100 assertThrows( 101 GeneralSecurityException.class, 102 () -> AesGcmSivKey.builder().setKeyBytes(SecretBytes.randomBytes(32)).build()); 103 } 104 105 @Test buildWithoutKeyBytes_fails()106 public void buildWithoutKeyBytes_fails() throws Exception { 107 AesGcmSivParameters parameters = 108 AesGcmSivParameters.builder() 109 .setKeySizeBytes(16) 110 .setVariant(AesGcmSivParameters.Variant.NO_PREFIX) 111 .build(); 112 assertThrows( 113 GeneralSecurityException.class, 114 () -> AesGcmSivKey.builder().setParameters(parameters).build()); 115 } 116 117 @Test paramtersRequireIdButIdIsNotSetInBuild_fails()118 public void paramtersRequireIdButIdIsNotSetInBuild_fails() throws Exception { 119 AesGcmSivParameters parametersWithIdRequirement = 120 AesGcmSivParameters.builder() 121 .setKeySizeBytes(16) 122 .setVariant(AesGcmSivParameters.Variant.TINK) 123 .build(); 124 assertThat(parametersWithIdRequirement.hasIdRequirement()).isTrue(); 125 assertThrows( 126 GeneralSecurityException.class, 127 () -> 128 AesGcmSivKey.builder() 129 .setKeyBytes(SecretBytes.randomBytes(16)) 130 .setParameters(parametersWithIdRequirement) 131 .build()); 132 } 133 134 @Test buildBadKeySize_fails()135 public void buildBadKeySize_fails() throws Exception { 136 AesGcmSivParameters parameters = 137 AesGcmSivParameters.builder() 138 .setKeySizeBytes(32) 139 .setVariant(AesGcmSivParameters.Variant.NO_PREFIX) 140 .build(); 141 assertThrows( 142 GeneralSecurityException.class, 143 () -> 144 AesGcmSivKey.builder() 145 .setParameters(parameters) 146 .setKeyBytes(SecretBytes.randomBytes(16)) 147 .build()); 148 } 149 150 @Test testEqualities()151 public void testEqualities() throws Exception { 152 SecretBytes keyBytes32 = SecretBytes.randomBytes(32); 153 SecretBytes keyBytes32Copy = 154 SecretBytes.copyFrom( 155 keyBytes32.toByteArray(InsecureSecretKeyAccess.get()), InsecureSecretKeyAccess.get()); 156 SecretBytes keyBytes32Diff = SecretBytes.randomBytes(32); 157 SecretBytes keyBytes16 = SecretBytes.randomBytes(16); 158 159 AesGcmSivParameters noPrefixParametersKeySize32 = 160 AesGcmSivParameters.builder() 161 .setKeySizeBytes(32) 162 .setVariant(AesGcmSivParameters.Variant.NO_PREFIX) 163 .build(); 164 AesGcmSivParameters noPrefixParametersKeySize16 = 165 AesGcmSivParameters.builder() 166 .setKeySizeBytes(16) 167 .setVariant(AesGcmSivParameters.Variant.NO_PREFIX) 168 .build(); 169 AesGcmSivParameters tinkPrefixParametersKeySize32 = 170 AesGcmSivParameters.builder() 171 .setKeySizeBytes(32) 172 .setVariant(AesGcmSivParameters.Variant.TINK) 173 .build(); 174 AesGcmSivParameters crunchyPrefixParametersKeySize32 = 175 AesGcmSivParameters.builder() 176 .setKeySizeBytes(32) 177 .setVariant(AesGcmSivParameters.Variant.CRUNCHY) 178 .build(); 179 180 new KeyTester() 181 .addEqualityGroup( 182 "No prefix, keyBytes32", 183 AesGcmSivKey.builder() 184 .setParameters(noPrefixParametersKeySize32) 185 .setKeyBytes(keyBytes32) 186 .build(), 187 // The same key built twice must be equal. 188 AesGcmSivKey.builder() 189 .setParameters(noPrefixParametersKeySize32) 190 .setKeyBytes(keyBytes32) 191 .build(), 192 // The same key built with a copy of key bytes must be equal. 193 AesGcmSivKey.builder() 194 .setParameters(noPrefixParametersKeySize32) 195 .setKeyBytes(keyBytes32Copy) 196 .build(), 197 // Setting id requirement to null is equal to not setting it. 198 AesGcmSivKey.builder() 199 .setParameters(noPrefixParametersKeySize32) 200 .setKeyBytes(keyBytes32) 201 .setIdRequirement(null) 202 .build()) 203 // This group checks that keys with different key bytes are not equal. 204 .addEqualityGroup( 205 "No prefix, newly generated keyBytes32", 206 AesGcmSivKey.builder() 207 .setParameters(noPrefixParametersKeySize32) 208 .setKeyBytes(keyBytes32Diff) 209 .build()) 210 // This group checks that keys with different key sizes are not equal. 211 .addEqualityGroup( 212 "No prefix, keyBytes16", 213 AesGcmSivKey.builder() 214 .setParameters(noPrefixParametersKeySize16) 215 .setKeyBytes(keyBytes16) 216 .build()) 217 .addEqualityGroup( 218 "Tink with key id 1907, keyBytes32", 219 AesGcmSivKey.builder() 220 .setParameters(tinkPrefixParametersKeySize32) 221 .setKeyBytes(keyBytes32) 222 .setIdRequirement(1907) 223 .build(), 224 AesGcmSivKey.builder() 225 .setParameters(tinkPrefixParametersKeySize32) 226 .setKeyBytes(keyBytes32Copy) 227 .setIdRequirement(1907) 228 .build()) 229 // This group checks that keys with different key ids are not equal. 230 .addEqualityGroup( 231 "Tink with key id 1908, keyBytes32", 232 AesGcmSivKey.builder() 233 .setParameters(tinkPrefixParametersKeySize32) 234 .setKeyBytes(keyBytes32) 235 .setIdRequirement(1908) 236 .build()) 237 // This groups checks that keys with different output prefix types are not equal. 238 .addEqualityGroup( 239 "Crunchy with key id 1907, keyBytes32", 240 AesGcmSivKey.builder() 241 .setParameters(crunchyPrefixParametersKeySize32) 242 .setKeyBytes(keyBytes32) 243 .setIdRequirement(1907) 244 .build()) 245 .doTests(); 246 } 247 248 @Test testDifferentKeyTypesEquality_fails()249 public void testDifferentKeyTypesEquality_fails() throws Exception { 250 AesGcmSivParameters aesGcmSivParameters = 251 AesGcmSivParameters.builder() 252 .setKeySizeBytes(16) 253 .setVariant(AesGcmSivParameters.Variant.NO_PREFIX) 254 .build(); 255 256 AesGcmParameters aesGcmParameters = 257 AesGcmParameters.builder() 258 .setKeySizeBytes(16) 259 .setIvSizeBytes(16) 260 .setTagSizeBytes(16) 261 .setVariant(AesGcmParameters.Variant.NO_PREFIX) 262 .build(); 263 264 SecretBytes keyBytes = SecretBytes.randomBytes(16); 265 AesGcmKey aesGcmKey = 266 AesGcmKey.builder().setParameters(aesGcmParameters).setKeyBytes(keyBytes).build(); 267 AesGcmSivKey aesGcmSivKey = 268 AesGcmSivKey.builder().setParameters(aesGcmSivParameters).setKeyBytes(keyBytes).build(); 269 270 assertThat(aesGcmSivKey.equalsKey(aesGcmKey)).isFalse(); 271 } 272 } 273