blob: 92b368bc22e6ea63f5258e7f23faa775e743cbb5 [file] [log] [blame]
// 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 subtle_test
import (
"bytes"
"encoding/hex"
"encoding/json"
"fmt"
"os"
"path/filepath"
"testing"
"github.com/google/tink/go/kwp/subtle"
"github.com/google/tink/go/subtle/random"
"github.com/google/tink/go/testutil"
)
func TestWrapUnwrap(t *testing.T) {
kek := random.GetRandomBytes(16)
cipher, err := subtle.NewKWP(kek)
if err != nil {
t.Fatalf("failed to make kwp, error: %v", err)
}
for i := uint32(16); i < 128; i++ {
t.Run(fmt.Sprintf("MessageSize%d", i), func(t *testing.T) {
toWrap := random.GetRandomBytes(i)
wrapped, err := cipher.Wrap(toWrap)
if err != nil {
t.Fatalf("failed to wrap, error: %v", err)
}
unwrapped, err := cipher.Unwrap(wrapped)
if err != nil {
t.Fatalf("failed to unwrap, error: %v", err)
}
if !bytes.Equal(toWrap, unwrapped) {
t.Error("unwrapped doesn't match original key")
}
})
}
}
func TestKeySizes(t *testing.T) {
for i := 0; i < 255; i++ {
expectSuccess := i == 16 || i == 32
t.Run(fmt.Sprintf("KeySize%d", i), func(t *testing.T) {
_, err := subtle.NewKWP(make([]byte, i))
if expectSuccess && err != nil {
t.Errorf("failed to create KWP: %v", err)
}
if !expectSuccess && err == nil {
t.Error("created KWP with invalid key size")
}
})
}
}
func TestInvalidWrappingSizes(t *testing.T) {
kek := random.GetRandomBytes(16)
cipher, err := subtle.NewKWP(kek)
if err != nil {
t.Fatalf("failed to make kwp, error: %v", err)
}
for i := 0; i < 16; i++ {
t.Run(fmt.Sprintf("KeySize%d", i), func(t *testing.T) {
if _, err := cipher.Wrap(make([]byte, i)); err == nil {
t.Error("wrapped a short key")
}
})
}
}
type KwpCase struct {
testutil.WycheproofCase
Key string `json:"key"`
Message string `json:"msg"`
Ciphertext string `json:"ct"`
}
type KwpGroup struct {
testutil.WycheproofGroup
KeySize int `json:"keySize"`
Tests []*KwpCase `json:"tests"`
}
type KwpSuite struct {
testutil.WycheproofSuite
Groups []*KwpGroup `json:"testGroups"`
}
func TestWycheproofCases(t *testing.T) {
srcDir, ok := os.LookupEnv("TEST_SRCDIR")
if !ok {
t.Skip("TEST_SRCDIR not set")
}
f, err := os.Open(filepath.Join(srcDir, "wycheproof/testvectors/kwp_test.json"))
if err != nil {
t.Fatalf("cannot open file %s", err)
}
parser := json.NewDecoder(f)
suite := new(KwpSuite)
if err := parser.Decode(suite); err != nil {
t.Fatalf("cannot decode test data: %s", err)
}
for _, group := range suite.Groups {
if group.KeySize == 192 {
continue
}
for _, test := range group.Tests {
caseName := fmt.Sprintf("%s-%s(%d):Case-%d",
suite.Algorithm, group.Type, group.KeySize, test.CaseID)
t.Run(caseName, func(t *testing.T) { runWycheproofCase(t, test) })
}
}
}
func runWycheproofCase(t *testing.T, testCase *KwpCase) {
kek, err := hex.DecodeString(testCase.Key)
if err != nil {
t.Fatalf("hex.DecodeString(testCase.Key) => %v", err)
}
msg, err := hex.DecodeString(testCase.Message)
if err != nil {
t.Fatalf("hex.DecodeString(testCase.Message) => %v", err)
}
ct, err := hex.DecodeString(testCase.Ciphertext)
if err != nil {
t.Fatalf("hex.DecodeString(testCase.Ciphertext) => %v", err)
}
cipher, err := subtle.NewKWP(kek)
if err != nil {
switch testCase.Result {
case "valid":
t.Fatalf("cannot create kwp, error: %v", err)
case "invalid", "acceptable":
return
}
}
wrapped, err := cipher.Wrap(msg)
switch testCase.Result {
case "valid":
if err != nil {
t.Errorf("cannot wrap, error: %v", err)
} else if !bytes.Equal(ct, wrapped) {
t.Error("wrapped key mismatches test vector")
}
case "invalid":
if err == nil && bytes.Equal(ct, wrapped) {
t.Error("no error and wrapped key matches test vector for invalid case")
}
case "acceptable":
if err == nil && !bytes.Equal(ct, wrapped) {
t.Error("no error and wrapped key mismatches test vector for acceptable case")
}
}
unwrapped, err := cipher.Unwrap(ct)
switch testCase.Result {
case "valid":
if err != nil {
t.Errorf("cannot unwrap, error: %v", err)
} else if !bytes.Equal(msg, unwrapped) {
t.Error("unwrapped key mismatches test vector")
}
case "invalid":
if err == nil {
t.Error("no error unwrapping invalid case")
}
case "acceptable":
if err == nil && !bytes.Equal(msg, unwrapped) {
t.Error("no error and unwrapped key mismatches plaintext")
}
}
}