1//go:build go1.9 2// +build go1.9 3 4package s3crypto 5 6import ( 7 "bytes" 8 "encoding/hex" 9 "encoding/json" 10 "fmt" 11 "io" 12 "io/ioutil" 13 "strings" 14 "testing" 15) 16 17// AES GCM 18func TestAES_GCM_NIST_gcmEncryptExtIV256_PTLen_128_Test_0(t *testing.T) { 19 iv, _ := hex.DecodeString("0d18e06c7c725ac9e362e1ce") 20 key, _ := hex.DecodeString("31bdadd96698c204aa9ce1448ea94ae1fb4a9a0b3c9d773b51bb1822666b8f22") 21 plaintext, _ := hex.DecodeString("2db5168e932556f8089a0622981d017d") 22 expected, _ := hex.DecodeString("fa4362189661d163fcd6a56d8bf0405a") 23 tag, _ := hex.DecodeString("d636ac1bbedd5cc3ee727dc2ab4a9489") 24 aesgcmTest(t, iv, key, plaintext, expected, tag) 25} 26 27func TestAES_GCM_NIST_gcmEncryptExtIV256_PTLen_104_Test_3(t *testing.T) { 28 iv, _ := hex.DecodeString("4742357c335913153ff0eb0f") 29 key, _ := hex.DecodeString("e5a0eb92cc2b064e1bc80891faf1fab5e9a17a9c3a984e25416720e30e6c2b21") 30 plaintext, _ := hex.DecodeString("8499893e16b0ba8b007d54665a") 31 expected, _ := hex.DecodeString("eb8e6175f1fe38eb1acf95fd51") 32 tag, _ := hex.DecodeString("88a8b74bb74fda553e91020a23deed45") 33 aesgcmTest(t, iv, key, plaintext, expected, tag) 34} 35 36func TestAES_GCM_NIST_gcmEncryptExtIV256_PTLen_256_Test_6(t *testing.T) { 37 iv, _ := hex.DecodeString("a291484c3de8bec6b47f525f") 38 key, _ := hex.DecodeString("37f39137416bafde6f75022a7a527cc593b6000a83ff51ec04871a0ff5360e4e") 39 plaintext, _ := hex.DecodeString("fafd94cede8b5a0730394bec68a8e77dba288d6ccaa8e1563a81d6e7ccc7fc97") 40 expected, _ := hex.DecodeString("44dc868006b21d49284016565ffb3979cc4271d967628bf7cdaf86db888e92e5") 41 tag, _ := hex.DecodeString("01a2b578aa2f41ec6379a44a31cc019c") 42 aesgcmTest(t, iv, key, plaintext, expected, tag) 43} 44 45func TestAES_GCM_NIST_gcmEncryptExtIV256_PTLen_408_Test_8(t *testing.T) { 46 iv, _ := hex.DecodeString("92f258071d79af3e63672285") 47 key, _ := hex.DecodeString("595f259c55abe00ae07535ca5d9b09d6efb9f7e9abb64605c337acbd6b14fc7e") 48 plaintext, _ := hex.DecodeString("a6fee33eb110a2d769bbc52b0f36969c287874f665681477a25fc4c48015c541fbe2394133ba490a34ee2dd67b898177849a91") 49 expected, _ := hex.DecodeString("bbca4a9e09ae9690c0f6f8d405e53dccd666aa9c5fa13c8758bc30abe1ddd1bcce0d36a1eaaaaffef20cd3c5970b9673f8a65c") 50 tag, _ := hex.DecodeString("26ccecb9976fd6ac9c2c0f372c52c821") 51 aesgcmTest(t, iv, key, plaintext, expected, tag) 52} 53 54type KAT struct { 55 IV string `json:"iv"` 56 Key string `json:"key"` 57 Plaintext string `json:"pt"` 58 AAD string `json:"aad"` 59 CipherText string `json:"ct"` 60 Tag string `json:"tag"` 61} 62 63func TestAES_GCM_KATS(t *testing.T) { 64 fileContents, err := ioutil.ReadFile("testdata/aes_gcm.json") 65 if err != nil { 66 t.Fatalf("failed to read KAT file: %v", err) 67 } 68 69 var kats []KAT 70 err = json.Unmarshal(fileContents, &kats) 71 if err != nil { 72 t.Fatalf("failed to unmarshal KAT json file: %v", err) 73 } 74 75 for i, kat := range kats { 76 t.Run(fmt.Sprintf("Case%d", i), func(t *testing.T) { 77 if len(kat.AAD) > 0 { 78 t.Skip("Skipping... SDK implementation does not expose additional authenticated data") 79 } 80 iv, err := hex.DecodeString(kat.IV) 81 if err != nil { 82 t.Fatalf("failed to decode iv: %v", err) 83 } 84 key, err := hex.DecodeString(kat.Key) 85 if err != nil { 86 t.Fatalf("failed to decode key: %v", err) 87 } 88 plaintext, err := hex.DecodeString(kat.Plaintext) 89 if err != nil { 90 t.Fatalf("failed to decode plaintext: %v", err) 91 } 92 ciphertext, err := hex.DecodeString(kat.CipherText) 93 if err != nil { 94 t.Fatalf("failed to decode ciphertext: %v", err) 95 } 96 tag, err := hex.DecodeString(kat.Tag) 97 if err != nil { 98 t.Fatalf("failed to decode tag: %v", err) 99 } 100 aesgcmTest(t, iv, key, plaintext, ciphertext, tag) 101 }) 102 } 103} 104 105func TestGCMEncryptReader_SourceError(t *testing.T) { 106 gcm := &gcmEncryptReader{ 107 encrypter: &mockCipherAEAD{}, 108 src: &mockSourceReader{err: fmt.Errorf("test read error")}, 109 } 110 111 b := make([]byte, 10) 112 n, err := gcm.Read(b) 113 if err == nil { 114 t.Fatalf("expected error, but got nil") 115 } else if err != nil && !strings.Contains(err.Error(), "test read error") { 116 t.Fatalf("expected source read error, but got %v", err) 117 } 118 119 if n != 0 { 120 t.Errorf("expected number of read bytes to be zero, but got %v", n) 121 } 122} 123 124func TestGCMDecryptReader_SourceError(t *testing.T) { 125 gcm := &gcmDecryptReader{ 126 decrypter: &mockCipherAEAD{}, 127 src: &mockSourceReader{err: fmt.Errorf("test read error")}, 128 } 129 130 b := make([]byte, 10) 131 n, err := gcm.Read(b) 132 if err == nil { 133 t.Fatalf("expected error, but got nil") 134 } else if err != nil && !strings.Contains(err.Error(), "test read error") { 135 t.Fatalf("expected source read error, but got %v", err) 136 } 137 138 if n != 0 { 139 t.Errorf("expected number of read bytes to be zero, but got %v", n) 140 } 141} 142 143func TestGCMDecryptReader_DecrypterOpenError(t *testing.T) { 144 gcm := &gcmDecryptReader{ 145 decrypter: &mockCipherAEAD{openError: fmt.Errorf("test open error")}, 146 src: &mockSourceReader{err: io.EOF}, 147 } 148 149 b := make([]byte, 10) 150 n, err := gcm.Read(b) 151 if err == nil { 152 t.Fatalf("expected error, but got nil") 153 } else if err != nil && !strings.Contains(err.Error(), "test open error") { 154 t.Fatalf("expected source read error, but got %v", err) 155 } 156 157 if n != 0 { 158 t.Errorf("expected number of read bytes to be zero, but got %v", n) 159 } 160} 161 162func aesgcmTest(t *testing.T, iv, key, plaintext, expected, tag []byte) { 163 t.Helper() 164 const gcmTagSize = 16 165 cd := CipherData{ 166 Key: key, 167 IV: iv, 168 } 169 gcm, err := newAESGCM(cd) 170 if err != nil { 171 t.Errorf("expected no error, but received %v", err) 172 } 173 174 cipherdata := gcm.Encrypt(bytes.NewReader(plaintext)) 175 176 ciphertext, err := ioutil.ReadAll(cipherdata) 177 if err != nil { 178 t.Errorf("expected no error, but received %v", err) 179 } 180 181 // splitting tag and ciphertext 182 etag := ciphertext[len(ciphertext)-gcmTagSize:] 183 if !bytes.Equal(etag, tag) { 184 t.Errorf("expected tags to be equivalent") 185 } 186 if !bytes.Equal(ciphertext[:len(ciphertext)-gcmTagSize], expected) { 187 t.Errorf("expected ciphertext to be equivalent") 188 } 189 190 data := gcm.Decrypt(bytes.NewReader(ciphertext)) 191 text, err := ioutil.ReadAll(data) 192 if err != nil { 193 t.Errorf("expected no error, but received %v", err) 194 } 195 if !bytes.Equal(plaintext, text) { 196 t.Errorf("expected ciphertext to be equivalent") 197 } 198} 199 200type mockSourceReader struct { 201 n int 202 err error 203} 204 205func (b mockSourceReader) Read(p []byte) (n int, err error) { 206 return b.n, b.err 207} 208 209type mockCipherAEAD struct { 210 seal []byte 211 openError error 212} 213 214func (m mockCipherAEAD) NonceSize() int { 215 panic("implement me") 216} 217 218func (m mockCipherAEAD) Overhead() int { 219 panic("implement me") 220} 221 222func (m mockCipherAEAD) Seal(dst, nonce, plaintext, additionalData []byte) []byte { 223 return m.seal 224} 225 226func (m mockCipherAEAD) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { 227 return []byte("mocked decrypt"), m.openError 228} 229