1*e7b1675dSTing-Kang Chang// Copyright 2020 Google LLC 2*e7b1675dSTing-Kang Chang// 3*e7b1675dSTing-Kang Chang// Licensed under the Apache License, Version 2.0 (the "License"); 4*e7b1675dSTing-Kang Chang// you may not use this file except in compliance with the License. 5*e7b1675dSTing-Kang Chang// You may obtain a copy of the License at 6*e7b1675dSTing-Kang Chang// 7*e7b1675dSTing-Kang Chang// http://www.apache.org/licenses/LICENSE-2.0 8*e7b1675dSTing-Kang Chang// 9*e7b1675dSTing-Kang Chang// Unless required by applicable law or agreed to in writing, software 10*e7b1675dSTing-Kang Chang// distributed under the License is distributed on an "AS IS" BASIS, 11*e7b1675dSTing-Kang Chang// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*e7b1675dSTing-Kang Chang// See the License for the specific language governing permissions and 13*e7b1675dSTing-Kang Chang// limitations under the License. 14*e7b1675dSTing-Kang Chang// 15*e7b1675dSTing-Kang Chang//////////////////////////////////////////////////////////////////////////////// 16*e7b1675dSTing-Kang Chang 17*e7b1675dSTing-Kang Changpackage subtle_test 18*e7b1675dSTing-Kang Chang 19*e7b1675dSTing-Kang Changimport ( 20*e7b1675dSTing-Kang Chang "bytes" 21*e7b1675dSTing-Kang Chang "encoding/hex" 22*e7b1675dSTing-Kang Chang "encoding/json" 23*e7b1675dSTing-Kang Chang "fmt" 24*e7b1675dSTing-Kang Chang "os" 25*e7b1675dSTing-Kang Chang "path/filepath" 26*e7b1675dSTing-Kang Chang "testing" 27*e7b1675dSTing-Kang Chang 28*e7b1675dSTing-Kang Chang "github.com/google/tink/go/kwp/subtle" 29*e7b1675dSTing-Kang Chang "github.com/google/tink/go/subtle/random" 30*e7b1675dSTing-Kang Chang "github.com/google/tink/go/testutil" 31*e7b1675dSTing-Kang Chang) 32*e7b1675dSTing-Kang Chang 33*e7b1675dSTing-Kang Changfunc TestWrapUnwrap(t *testing.T) { 34*e7b1675dSTing-Kang Chang kek := random.GetRandomBytes(16) 35*e7b1675dSTing-Kang Chang cipher, err := subtle.NewKWP(kek) 36*e7b1675dSTing-Kang Chang if err != nil { 37*e7b1675dSTing-Kang Chang t.Fatalf("failed to make kwp, error: %v", err) 38*e7b1675dSTing-Kang Chang } 39*e7b1675dSTing-Kang Chang 40*e7b1675dSTing-Kang Chang for i := uint32(16); i < 128; i++ { 41*e7b1675dSTing-Kang Chang t.Run(fmt.Sprintf("MessageSize%d", i), func(t *testing.T) { 42*e7b1675dSTing-Kang Chang toWrap := random.GetRandomBytes(i) 43*e7b1675dSTing-Kang Chang 44*e7b1675dSTing-Kang Chang wrapped, err := cipher.Wrap(toWrap) 45*e7b1675dSTing-Kang Chang if err != nil { 46*e7b1675dSTing-Kang Chang t.Fatalf("failed to wrap, error: %v", err) 47*e7b1675dSTing-Kang Chang } 48*e7b1675dSTing-Kang Chang 49*e7b1675dSTing-Kang Chang unwrapped, err := cipher.Unwrap(wrapped) 50*e7b1675dSTing-Kang Chang if err != nil { 51*e7b1675dSTing-Kang Chang t.Fatalf("failed to unwrap, error: %v", err) 52*e7b1675dSTing-Kang Chang } 53*e7b1675dSTing-Kang Chang 54*e7b1675dSTing-Kang Chang if !bytes.Equal(toWrap, unwrapped) { 55*e7b1675dSTing-Kang Chang t.Error("unwrapped doesn't match original key") 56*e7b1675dSTing-Kang Chang } 57*e7b1675dSTing-Kang Chang }) 58*e7b1675dSTing-Kang Chang } 59*e7b1675dSTing-Kang Chang} 60*e7b1675dSTing-Kang Chang 61*e7b1675dSTing-Kang Changfunc TestKeySizes(t *testing.T) { 62*e7b1675dSTing-Kang Chang for i := 0; i < 255; i++ { 63*e7b1675dSTing-Kang Chang expectSuccess := i == 16 || i == 32 64*e7b1675dSTing-Kang Chang t.Run(fmt.Sprintf("KeySize%d", i), func(t *testing.T) { 65*e7b1675dSTing-Kang Chang _, err := subtle.NewKWP(make([]byte, i)) 66*e7b1675dSTing-Kang Chang 67*e7b1675dSTing-Kang Chang if expectSuccess && err != nil { 68*e7b1675dSTing-Kang Chang t.Errorf("failed to create KWP: %v", err) 69*e7b1675dSTing-Kang Chang } 70*e7b1675dSTing-Kang Chang 71*e7b1675dSTing-Kang Chang if !expectSuccess && err == nil { 72*e7b1675dSTing-Kang Chang t.Error("created KWP with invalid key size") 73*e7b1675dSTing-Kang Chang } 74*e7b1675dSTing-Kang Chang }) 75*e7b1675dSTing-Kang Chang 76*e7b1675dSTing-Kang Chang } 77*e7b1675dSTing-Kang Chang} 78*e7b1675dSTing-Kang Chang 79*e7b1675dSTing-Kang Changfunc TestInvalidWrappingSizes(t *testing.T) { 80*e7b1675dSTing-Kang Chang kek := random.GetRandomBytes(16) 81*e7b1675dSTing-Kang Chang cipher, err := subtle.NewKWP(kek) 82*e7b1675dSTing-Kang Chang if err != nil { 83*e7b1675dSTing-Kang Chang t.Fatalf("failed to make kwp, error: %v", err) 84*e7b1675dSTing-Kang Chang } 85*e7b1675dSTing-Kang Chang 86*e7b1675dSTing-Kang Chang for i := 0; i < 16; i++ { 87*e7b1675dSTing-Kang Chang t.Run(fmt.Sprintf("KeySize%d", i), func(t *testing.T) { 88*e7b1675dSTing-Kang Chang if _, err := cipher.Wrap(make([]byte, i)); err == nil { 89*e7b1675dSTing-Kang Chang t.Error("wrapped a short key") 90*e7b1675dSTing-Kang Chang } 91*e7b1675dSTing-Kang Chang }) 92*e7b1675dSTing-Kang Chang } 93*e7b1675dSTing-Kang Chang} 94*e7b1675dSTing-Kang Chang 95*e7b1675dSTing-Kang Changtype KwpCase struct { 96*e7b1675dSTing-Kang Chang testutil.WycheproofCase 97*e7b1675dSTing-Kang Chang Key string `json:"key"` 98*e7b1675dSTing-Kang Chang Message string `json:"msg"` 99*e7b1675dSTing-Kang Chang Ciphertext string `json:"ct"` 100*e7b1675dSTing-Kang Chang} 101*e7b1675dSTing-Kang Chang 102*e7b1675dSTing-Kang Changtype KwpGroup struct { 103*e7b1675dSTing-Kang Chang testutil.WycheproofGroup 104*e7b1675dSTing-Kang Chang KeySize int `json:"keySize"` 105*e7b1675dSTing-Kang Chang Tests []*KwpCase `json:"tests"` 106*e7b1675dSTing-Kang Chang} 107*e7b1675dSTing-Kang Chang 108*e7b1675dSTing-Kang Changtype KwpSuite struct { 109*e7b1675dSTing-Kang Chang testutil.WycheproofSuite 110*e7b1675dSTing-Kang Chang Groups []*KwpGroup `json:"testGroups"` 111*e7b1675dSTing-Kang Chang} 112*e7b1675dSTing-Kang Chang 113*e7b1675dSTing-Kang Changfunc TestWycheproofCases(t *testing.T) { 114*e7b1675dSTing-Kang Chang srcDir, ok := os.LookupEnv("TEST_SRCDIR") 115*e7b1675dSTing-Kang Chang if !ok { 116*e7b1675dSTing-Kang Chang t.Skip("TEST_SRCDIR not set") 117*e7b1675dSTing-Kang Chang } 118*e7b1675dSTing-Kang Chang f, err := os.Open(filepath.Join(srcDir, "wycheproof/testvectors/kwp_test.json")) 119*e7b1675dSTing-Kang Chang if err != nil { 120*e7b1675dSTing-Kang Chang t.Fatalf("cannot open file %s", err) 121*e7b1675dSTing-Kang Chang } 122*e7b1675dSTing-Kang Chang parser := json.NewDecoder(f) 123*e7b1675dSTing-Kang Chang suite := new(KwpSuite) 124*e7b1675dSTing-Kang Chang if err := parser.Decode(suite); err != nil { 125*e7b1675dSTing-Kang Chang t.Fatalf("cannot decode test data: %s", err) 126*e7b1675dSTing-Kang Chang } 127*e7b1675dSTing-Kang Chang 128*e7b1675dSTing-Kang Chang for _, group := range suite.Groups { 129*e7b1675dSTing-Kang Chang if group.KeySize == 192 { 130*e7b1675dSTing-Kang Chang continue 131*e7b1675dSTing-Kang Chang } 132*e7b1675dSTing-Kang Chang 133*e7b1675dSTing-Kang Chang for _, test := range group.Tests { 134*e7b1675dSTing-Kang Chang caseName := fmt.Sprintf("%s-%s(%d):Case-%d", 135*e7b1675dSTing-Kang Chang suite.Algorithm, group.Type, group.KeySize, test.CaseID) 136*e7b1675dSTing-Kang Chang t.Run(caseName, func(t *testing.T) { runWycheproofCase(t, test) }) 137*e7b1675dSTing-Kang Chang } 138*e7b1675dSTing-Kang Chang } 139*e7b1675dSTing-Kang Chang} 140*e7b1675dSTing-Kang Chang 141*e7b1675dSTing-Kang Changfunc runWycheproofCase(t *testing.T, testCase *KwpCase) { 142*e7b1675dSTing-Kang Chang kek, err := hex.DecodeString(testCase.Key) 143*e7b1675dSTing-Kang Chang if err != nil { 144*e7b1675dSTing-Kang Chang t.Fatalf("hex.DecodeString(testCase.Key) => %v", err) 145*e7b1675dSTing-Kang Chang } 146*e7b1675dSTing-Kang Chang 147*e7b1675dSTing-Kang Chang msg, err := hex.DecodeString(testCase.Message) 148*e7b1675dSTing-Kang Chang if err != nil { 149*e7b1675dSTing-Kang Chang t.Fatalf("hex.DecodeString(testCase.Message) => %v", err) 150*e7b1675dSTing-Kang Chang } 151*e7b1675dSTing-Kang Chang 152*e7b1675dSTing-Kang Chang ct, err := hex.DecodeString(testCase.Ciphertext) 153*e7b1675dSTing-Kang Chang if err != nil { 154*e7b1675dSTing-Kang Chang t.Fatalf("hex.DecodeString(testCase.Ciphertext) => %v", err) 155*e7b1675dSTing-Kang Chang } 156*e7b1675dSTing-Kang Chang 157*e7b1675dSTing-Kang Chang cipher, err := subtle.NewKWP(kek) 158*e7b1675dSTing-Kang Chang if err != nil { 159*e7b1675dSTing-Kang Chang switch testCase.Result { 160*e7b1675dSTing-Kang Chang case "valid": 161*e7b1675dSTing-Kang Chang t.Fatalf("cannot create kwp, error: %v", err) 162*e7b1675dSTing-Kang Chang case "invalid", "acceptable": 163*e7b1675dSTing-Kang Chang return 164*e7b1675dSTing-Kang Chang } 165*e7b1675dSTing-Kang Chang } 166*e7b1675dSTing-Kang Chang 167*e7b1675dSTing-Kang Chang wrapped, err := cipher.Wrap(msg) 168*e7b1675dSTing-Kang Chang switch testCase.Result { 169*e7b1675dSTing-Kang Chang case "valid": 170*e7b1675dSTing-Kang Chang if err != nil { 171*e7b1675dSTing-Kang Chang t.Errorf("cannot wrap, error: %v", err) 172*e7b1675dSTing-Kang Chang } else if !bytes.Equal(ct, wrapped) { 173*e7b1675dSTing-Kang Chang t.Error("wrapped key mismatches test vector") 174*e7b1675dSTing-Kang Chang } 175*e7b1675dSTing-Kang Chang case "invalid": 176*e7b1675dSTing-Kang Chang if err == nil && bytes.Equal(ct, wrapped) { 177*e7b1675dSTing-Kang Chang t.Error("no error and wrapped key matches test vector for invalid case") 178*e7b1675dSTing-Kang Chang } 179*e7b1675dSTing-Kang Chang case "acceptable": 180*e7b1675dSTing-Kang Chang if err == nil && !bytes.Equal(ct, wrapped) { 181*e7b1675dSTing-Kang Chang t.Error("no error and wrapped key mismatches test vector for acceptable case") 182*e7b1675dSTing-Kang Chang } 183*e7b1675dSTing-Kang Chang } 184*e7b1675dSTing-Kang Chang 185*e7b1675dSTing-Kang Chang unwrapped, err := cipher.Unwrap(ct) 186*e7b1675dSTing-Kang Chang switch testCase.Result { 187*e7b1675dSTing-Kang Chang case "valid": 188*e7b1675dSTing-Kang Chang if err != nil { 189*e7b1675dSTing-Kang Chang t.Errorf("cannot unwrap, error: %v", err) 190*e7b1675dSTing-Kang Chang } else if !bytes.Equal(msg, unwrapped) { 191*e7b1675dSTing-Kang Chang t.Error("unwrapped key mismatches test vector") 192*e7b1675dSTing-Kang Chang } 193*e7b1675dSTing-Kang Chang case "invalid": 194*e7b1675dSTing-Kang Chang if err == nil { 195*e7b1675dSTing-Kang Chang t.Error("no error unwrapping invalid case") 196*e7b1675dSTing-Kang Chang } 197*e7b1675dSTing-Kang Chang case "acceptable": 198*e7b1675dSTing-Kang Chang if err == nil && !bytes.Equal(msg, unwrapped) { 199*e7b1675dSTing-Kang Chang t.Error("no error and unwrapped key mismatches plaintext") 200*e7b1675dSTing-Kang Chang } 201*e7b1675dSTing-Kang Chang } 202*e7b1675dSTing-Kang Chang} 203