1// Copyright 2020 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 17package streamingaead_test 18 19import ( 20 "bytes" 21 "fmt" 22 "testing" 23 24 "google.golang.org/protobuf/proto" 25 "github.com/google/tink/go/core/registry" 26 "github.com/google/tink/go/streamingaead/subtle" 27 "github.com/google/tink/go/testutil" 28 ctrhmacpb "github.com/google/tink/go/proto/aes_ctr_hmac_streaming_go_proto" 29 commonpb "github.com/google/tink/go/proto/common_go_proto" 30 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 31) 32 33var aesCTRHMACKeySizes = []uint32{16, 32} 34 35func TestAESCTRHMACGetPrimitiveBasic(t *testing.T) { 36 keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) 37 if err != nil { 38 t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) 39 } 40 for _, keySize := range aesCTRHMACKeySizes { 41 key := testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, keySize, commonpb.HashType_SHA256, keySize, commonpb.HashType_SHA256, 16, 4096) 42 serializedKey, err := proto.Marshal(key) 43 if err != nil { 44 t.Errorf("failed to marshal key: %s", err) 45 } 46 p, err := keyManager.Primitive(serializedKey) 47 if err != nil { 48 t.Errorf("unexpected error: %s", err) 49 } 50 if err := validateAESCTRHMACPrimitive(p, key); err != nil { 51 t.Errorf("%s", err) 52 } 53 } 54} 55 56func TestAESCTRHMACGetPrimitiveWithInvalidInput(t *testing.T) { 57 keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) 58 if err != nil { 59 t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) 60 } 61 62 testKeys := genInvalidAESCTRHMACKeys() 63 for i := 0; i < len(testKeys); i++ { 64 serializedKey, err := proto.Marshal(testKeys[i]) 65 if err != nil { 66 t.Errorf("failed to marshal key: %s", err) 67 } 68 if _, err := keyManager.Primitive(serializedKey); err == nil { 69 t.Errorf("expect an error in test case %d", i) 70 } 71 } 72 73 if _, err := keyManager.Primitive(nil); err == nil { 74 t.Errorf("expect an error when input is nil") 75 } 76 if _, err := keyManager.Primitive([]byte{}); err == nil { 77 t.Errorf("expect an error when input is empty") 78 } 79} 80 81func TestAESCTRHMACNewKeyMultipleTimes(t *testing.T) { 82 keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) 83 if err != nil { 84 t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) 85 } 86 format := testutil.NewAESCTRHMACKeyFormat(32, commonpb.HashType_SHA256, 32, commonpb.HashType_SHA256, 16, 4096) 87 serializedFormat, err := proto.Marshal(format) 88 if err != nil { 89 t.Errorf("failed to marshal key: %s", err) 90 } 91 keys := make(map[string]struct{}) 92 n := 26 93 for i := 0; i < n; i++ { 94 key, _ := keyManager.NewKey(serializedFormat) 95 serializedKey, err := proto.Marshal(key) 96 if err != nil { 97 t.Errorf("failed to marshal key: %s", err) 98 } 99 keys[string(serializedKey)] = struct{}{} 100 101 keyData, _ := keyManager.NewKeyData(serializedFormat) 102 serializedKey = keyData.Value 103 keys[string(serializedKey)] = struct{}{} 104 } 105 if len(keys) != n*2 { 106 t.Errorf("key is repeated") 107 } 108} 109 110func TestAESCTRHMACNewKeyBasic(t *testing.T) { 111 keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) 112 if err != nil { 113 t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) 114 } 115 for _, keySize := range aesCTRHMACKeySizes { 116 format := testutil.NewAESCTRHMACKeyFormat(keySize, commonpb.HashType_SHA256, keySize, commonpb.HashType_SHA256, 16, 4096) 117 serializedFormat, err := proto.Marshal(format) 118 if err != nil { 119 t.Errorf("failed to marshal key: %s", err) 120 } 121 m, err := keyManager.NewKey(serializedFormat) 122 if err != nil { 123 t.Errorf("unexpected error: %s", err) 124 } 125 key := m.(*ctrhmacpb.AesCtrHmacStreamingKey) 126 if err := validateAESCTRHMACKey(key, format); err != nil { 127 t.Errorf("%s", err) 128 } 129 } 130} 131 132func TestAESCTRHMACNewKeyWithInvalidInput(t *testing.T) { 133 keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) 134 if err != nil { 135 t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) 136 } 137 // bad format 138 badFormats := genInvalidAESCTRHMACKeyFormats() 139 for i := 0; i < len(badFormats); i++ { 140 serializedFormat, err := proto.Marshal(badFormats[i]) 141 if err != nil { 142 t.Errorf("failed to marshal key: %s", err) 143 } 144 if _, err := keyManager.NewKey(serializedFormat); err == nil { 145 t.Errorf("expect an error in test case %d", i) 146 } 147 } 148 // nil 149 if _, err := keyManager.NewKey(nil); err == nil { 150 t.Errorf("expect an error when input is nil") 151 } 152 // empty array 153 if _, err := keyManager.NewKey([]byte{}); err == nil { 154 t.Errorf("expect an error when input is empty") 155 } 156} 157 158func TestAESCTRHMACNewKeyDataBasic(t *testing.T) { 159 keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) 160 if err != nil { 161 t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) 162 } 163 for _, keySize := range aesCTRHMACKeySizes { 164 format := testutil.NewAESCTRHMACKeyFormat(keySize, commonpb.HashType_SHA256, keySize, commonpb.HashType_SHA256, 16, 4096) 165 serializedFormat, err := proto.Marshal(format) 166 if err != nil { 167 t.Errorf("failed to marshal key: %s", err) 168 } 169 keyData, err := keyManager.NewKeyData(serializedFormat) 170 if err != nil { 171 t.Errorf("unexpected error: %s", err) 172 } 173 if keyData.TypeUrl != testutil.AESCTRHMACTypeURL { 174 t.Errorf("incorrect type url") 175 } 176 if keyData.KeyMaterialType != tinkpb.KeyData_SYMMETRIC { 177 t.Errorf("incorrect key material type") 178 } 179 key := new(ctrhmacpb.AesCtrHmacStreamingKey) 180 if err := proto.Unmarshal(keyData.Value, key); err != nil { 181 t.Errorf("incorrect key value") 182 } 183 if err := validateAESCTRHMACKey(key, format); err != nil { 184 t.Errorf("%s", err) 185 } 186 } 187} 188 189func TestAESCTRHMACNewKeyDataWithInvalidInput(t *testing.T) { 190 km, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) 191 if err != nil { 192 t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) 193 } 194 badFormats := genInvalidAESCTRHMACKeyFormats() 195 for i := 0; i < len(badFormats); i++ { 196 serializedFormat, err := proto.Marshal(badFormats[i]) 197 if err != nil { 198 t.Errorf("failed to marshal key: %s", err) 199 } 200 if _, err := km.NewKeyData(serializedFormat); err == nil { 201 t.Errorf("expect an error in test case %d", i) 202 } 203 } 204 // nil input 205 if _, err := km.NewKeyData(nil); err == nil { 206 t.Errorf("expect an error when input is nil") 207 } 208 // empty input 209 if _, err := km.NewKeyData([]byte{}); err == nil { 210 t.Errorf("expect an error when input is empty") 211 } 212} 213 214func TestAESCTRHMACDoesSupport(t *testing.T) { 215 keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) 216 if err != nil { 217 t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) 218 } 219 if !keyManager.DoesSupport(testutil.AESCTRHMACTypeURL) { 220 t.Errorf("AESCTRHMACKeyManager must support %s", testutil.AESCTRHMACTypeURL) 221 } 222 if keyManager.DoesSupport("some bad type") { 223 t.Errorf("AESCTRHMACKeyManager must support only %s", testutil.AESCTRHMACTypeURL) 224 } 225} 226 227func TestAESCTRHMACTypeURL(t *testing.T) { 228 keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) 229 if err != nil { 230 t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) 231 } 232 if keyManager.TypeURL() != testutil.AESCTRHMACTypeURL { 233 t.Errorf("incorrect key type") 234 } 235} 236 237func genInvalidAESCTRHMACKeys() []proto.Message { 238 return []proto.Message{ 239 // not a AESCTRHMACKey 240 testutil.NewAESCTRHMACKeyFormat(32, commonpb.HashType_SHA256, 32, commonpb.HashType_SHA256, 16, 4096), 241 242 // bad key size 243 testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 17, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 16, 4096), 244 testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA256, 17, commonpb.HashType_SHA256, 16, 4096), 245 testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 33, commonpb.HashType_SHA256, 33, commonpb.HashType_SHA256, 16, 4096), 246 247 // bad version 248 testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion+1, 16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 16, 4096), 249 250 // bad ciphertext_segment_size 251 testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 16, 2147483648), 252 253 // bad hmac params hash type 254 testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA224, 16, 4096), 255 testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA384, 16, 4096), 256 257 // bad hkdf hash type 258 testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA224, 16, commonpb.HashType_SHA256, 16, 4096), 259 testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA384, 16, commonpb.HashType_SHA256, 16, 4096), 260 } 261} 262 263func genInvalidAESCTRHMACKeyFormats() []proto.Message { 264 return []proto.Message{ 265 // not AESCTRHMACKeyFormat 266 testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 16, 4096), 267 268 // invalid key size 269 testutil.NewAESCTRHMACKeyFormat(17, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 16, 4096), 270 testutil.NewAESCTRHMACKeyFormat(16, commonpb.HashType_SHA256, 17, commonpb.HashType_SHA256, 16, 4096), 271 testutil.NewAESCTRHMACKeyFormat(33, commonpb.HashType_SHA256, 33, commonpb.HashType_SHA256, 16, 4096), 272 } 273} 274 275func validateAESCTRHMACKey(key *ctrhmacpb.AesCtrHmacStreamingKey, format *ctrhmacpb.AesCtrHmacStreamingKeyFormat) error { 276 if uint32(len(key.KeyValue)) != format.KeySize { 277 return fmt.Errorf("incorrect key size") 278 } 279 if key.Version != testutil.AESCTRHMACKeyVersion { 280 return fmt.Errorf("incorrect key version") 281 } 282 if key.Params.CiphertextSegmentSize != format.Params.CiphertextSegmentSize { 283 return fmt.Errorf("incorrect ciphertext segment size") 284 } 285 if key.Params.DerivedKeySize != format.Params.DerivedKeySize { 286 return fmt.Errorf("incorrect derived key size") 287 } 288 if key.Params.HkdfHashType != format.Params.HkdfHashType { 289 return fmt.Errorf("incorrect HKDF hash type") 290 } 291 // try to encrypt and decrypt 292 p, err := subtle.NewAESCTRHMAC( 293 key.KeyValue, 294 key.Params.HkdfHashType.String(), 295 int(key.Params.DerivedKeySize), 296 key.Params.HmacParams.Hash.String(), 297 int(key.Params.HmacParams.TagSize), 298 int(key.Params.CiphertextSegmentSize), 299 0, 300 ) 301 if err != nil { 302 return fmt.Errorf("invalid key") 303 } 304 return validateAESCTRHMACPrimitive(p, key) 305} 306 307func validateAESCTRHMACPrimitive(p interface{}, key *ctrhmacpb.AesCtrHmacStreamingKey) error { 308 cipher := p.(*subtle.AESCTRHMAC) 309 if !bytes.Equal(cipher.MainKey, key.KeyValue) { 310 return fmt.Errorf("main key and primitive don't match") 311 } 312 return encryptDecrypt(cipher, cipher, 32, 32) 313} 314