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