| /* |
| * |
| * Copyright 2018 gRPC authors. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| package conn |
| |
| import ( |
| "testing" |
| |
| core "google.golang.org/grpc/credentials/alts/internal" |
| ) |
| |
| // getGCMCryptoPair outputs a client/server pair on aes128gcmRekey. |
| func getRekeyCryptoPair(key []byte, counter []byte, t *testing.T) (ALTSRecordCrypto, ALTSRecordCrypto) { |
| client, err := NewAES128GCMRekey(core.ClientSide, key) |
| if err != nil { |
| t.Fatalf("NewAES128GCMRekey(ClientSide, key) = %v", err) |
| } |
| server, err := NewAES128GCMRekey(core.ServerSide, key) |
| if err != nil { |
| t.Fatalf("NewAES128GCMRekey(ServerSide, key) = %v", err) |
| } |
| // set counter if provided. |
| if counter != nil { |
| if CounterSide(counter) == core.ClientSide { |
| client.(*aes128gcmRekey).outCounter = CounterFromValue(counter, overflowLenAES128GCMRekey) |
| server.(*aes128gcmRekey).inCounter = CounterFromValue(counter, overflowLenAES128GCMRekey) |
| } else { |
| server.(*aes128gcmRekey).outCounter = CounterFromValue(counter, overflowLenAES128GCMRekey) |
| client.(*aes128gcmRekey).inCounter = CounterFromValue(counter, overflowLenAES128GCMRekey) |
| } |
| } |
| return client, server |
| } |
| |
| func testRekeyEncryptRoundtrip(client ALTSRecordCrypto, server ALTSRecordCrypto, t *testing.T) { |
| // Encrypt. |
| const plaintext = "This is plaintext." |
| var err error |
| buf := []byte(plaintext) |
| buf, err = client.Encrypt(buf[:0], buf) |
| if err != nil { |
| t.Fatal("Encrypting with client-side context: unexpected error", err, "\n", |
| "Plaintext:", []byte(plaintext)) |
| } |
| |
| // Encrypt a second message. |
| const plaintext2 = "This is a second plaintext." |
| buf2 := []byte(plaintext2) |
| buf2, err = client.Encrypt(buf2[:0], buf2) |
| if err != nil { |
| t.Fatal("Encrypting with client-side context: unexpected error", err, "\n", |
| "Plaintext:", []byte(plaintext2)) |
| } |
| |
| // Decryption fails: cannot decrypt second message before first. |
| if got, err := server.Decrypt(nil, buf2); err == nil { |
| t.Error("Decrypting client-side ciphertext with a client-side context unexpectedly succeeded; want unexpected counter error:\n", |
| " Original plaintext:", []byte(plaintext2), "\n", |
| " Ciphertext:", buf2, "\n", |
| " Decrypted plaintext:", got) |
| } |
| |
| // Decryption fails: wrong counter space. |
| if got, err := client.Decrypt(nil, buf); err == nil { |
| t.Error("Decrypting client-side ciphertext with a client-side context unexpectedly succeeded; want counter space error:\n", |
| " Original plaintext:", []byte(plaintext), "\n", |
| " Ciphertext:", buf, "\n", |
| " Decrypted plaintext:", got) |
| } |
| |
| // Decrypt first message. |
| ciphertext := append([]byte(nil), buf...) |
| buf, err = server.Decrypt(buf[:0], buf) |
| if err != nil || string(buf) != plaintext { |
| t.Fatal("Decrypting client-side ciphertext with a server-side context did not produce original content:\n", |
| " Original plaintext:", []byte(plaintext), "\n", |
| " Ciphertext:", ciphertext, "\n", |
| " Decryption error:", err, "\n", |
| " Decrypted plaintext:", buf) |
| } |
| |
| // Decryption fails: replay attack. |
| if got, err := server.Decrypt(nil, buf); err == nil { |
| t.Error("Decrypting client-side ciphertext with a client-side context unexpectedly succeeded; want unexpected counter error:\n", |
| " Original plaintext:", []byte(plaintext), "\n", |
| " Ciphertext:", buf, "\n", |
| " Decrypted plaintext:", got) |
| } |
| } |
| |
| // Test encrypt and decrypt on roundtrip messages for aes128gcmRekey. |
| func (s) TestAES128GCMRekeyEncryptRoundtrip(t *testing.T) { |
| // Test for aes128gcmRekey. |
| key := make([]byte, 44) |
| client, server := getRekeyCryptoPair(key, nil, t) |
| testRekeyEncryptRoundtrip(client, server, t) |
| } |