blob: 590dfbe0d1f129649688d597b36f7c613677c42a [file] [log] [blame]
/*
*
* 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)
}