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