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