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 "encoding/hex" 21 "encoding/json" 22 "os" 23 "path/filepath" 24 "testing" 25 26 "github.com/google/tink/go/mac/subtle" 27 "github.com/google/tink/go/subtle/random" 28) 29 30var ( 31 // Test vectors from RFC 4493. 32 keyRFC4493, _ = hex.DecodeString("2b7e151628aed2a6abf7158809cf4f3c") 33 dataRFC4493, _ = hex.DecodeString("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710") 34 expected = map[int]string{ 35 0: "bb1d6929e95937287fa37d129b756746", 36 16: "070a16b46b4d4144f79bdd9dd04a287c", 37 40: "dfa66747de9ae63030ca32611497c827", 38 64: "51f0bebf7e3b9d92fc49741779363cfe", 39 } 40) 41 42type testdata struct { 43 Algorithm string 44 GeneratorVersion string 45 NumberOfTests uint32 46 TestGroups []*testgroup 47} 48 49type testgroup struct { 50 KeySize uint32 51 TagSize uint32 52 Type string 53 Tests []*testcase 54} 55 56type testcase struct { 57 Comment string 58 Key string 59 Msg string 60 Result string 61 Tag string 62 TcID uint32 63} 64 65func TestVectorsWycheproof(t *testing.T) { 66 srcDir, ok := os.LookupEnv("TEST_SRCDIR") 67 if !ok { 68 t.Skip("TEST_SRCDIR not set") 69 } 70 f, err := os.Open(filepath.Join(srcDir, "wycheproof/testvectors/aes_cmac_test.json")) 71 if err != nil { 72 t.Fatalf("cannot open file: %s", err) 73 } 74 parser := json.NewDecoder(f) 75 data := new(testdata) 76 if err := parser.Decode(data); err != nil { 77 t.Fatalf("cannot decode test data: %s", err) 78 } 79 80 for _, g := range data.TestGroups { 81 for _, tc := range g.Tests { 82 key, err := hex.DecodeString(tc.Key) 83 if err != nil || uint32(len(key))*8 != g.KeySize { 84 t.Errorf("Could not decode key for test case %d (%s): %v", tc.TcID, tc.Comment, err) 85 continue 86 } 87 msg, err := hex.DecodeString(tc.Msg) 88 if err != nil { 89 t.Errorf("Could not decode message for test case %d (%s): %v", tc.TcID, tc.Comment, err) 90 continue 91 } 92 tag, err := hex.DecodeString(tc.Tag) 93 if err != nil { 94 t.Errorf("Could not decode expected tag for test case %d (%s): %v", tc.TcID, tc.Comment, err) 95 continue 96 } 97 if g.TagSize%8 != 0 { 98 t.Errorf("Requested tag size for test case %d (%s) is not a multiple of 8, but %d", tc.TcID, tc.Comment, g.TagSize) 99 continue 100 } 101 aes, err := subtle.NewAESCMAC(key, g.TagSize/8) 102 valid := tc.Result == "valid" 103 if valid && err != nil { 104 t.Errorf("Could not create subtle.CMAC for test case %d (%s): %v", tc.TcID, tc.Comment, err) 105 continue 106 } 107 if !valid && err != nil { 108 continue 109 } 110 res, err := aes.ComputeMAC(msg) 111 if valid && err != nil { 112 t.Errorf("Could not compute AES-CMAC for test case %d (%s): %v", tc.TcID, tc.Comment, err) 113 continue 114 } 115 if valid && hex.EncodeToString(res) != tc.Tag { 116 t.Errorf("Compute AES-CMAC and expected for test case %d (%s) do not match:\nComputed: %q\nExpected: %q", tc.TcID, tc.Comment, hex.EncodeToString(res), tc.Tag) 117 } 118 if !valid && hex.EncodeToString(res) == tc.Tag && err == nil { 119 t.Errorf("Compute AES-CMAC and invalid expected for test case %d (%s) match:\nComputed: %q\nExpected: %q", tc.TcID, tc.Comment, hex.EncodeToString(res), tc.Tag) 120 } 121 err = aes.VerifyMAC(tag, msg) 122 if valid && err != nil { 123 t.Errorf("Could not verify MAC for test case %d (%s): %v", tc.TcID, tc.Comment, err) 124 } 125 if !valid && err == nil { 126 t.Errorf("Verified invalid MAC for test case %d (%s)", tc.TcID, tc.Comment) 127 } 128 } 129 } 130} 131 132func TestCMACBasic(t *testing.T) { 133 a, err := subtle.NewAESCMAC(keyRFC4493, 16) 134 if err != nil { 135 t.Errorf("Could not create subtle.CMAC object: %v", err) 136 } 137 for l, e := range expected { 138 output, err := a.ComputeMAC(dataRFC4493[:l]) 139 if err != nil { 140 t.Errorf("Error computing AES-CMAC: %v", err) 141 } 142 if hex.EncodeToString(output) != e { 143 t.Errorf("Computation and test vector differ. Computation: %q, Test Vector %q", hex.EncodeToString(output), e) 144 } 145 exp, err := hex.DecodeString(e) 146 if err != nil { 147 t.Errorf("Could not decode expected string %q: %v", e, err) 148 } 149 err = a.VerifyMAC(exp, dataRFC4493[:l]) 150 if err != nil { 151 t.Errorf("Verification of test vector failed. Test Vector %q, Verification %v", e, err) 152 } 153 } 154} 155 156func TestNewCMACWithInvalidInput(t *testing.T) { 157 // key too short 158 _, err := subtle.NewAESCMAC(random.GetRandomBytes(1), 16) 159 if err == nil { 160 t.Errorf("expect an error when key is too short") 161 } 162 // tag too short 163 _, err = subtle.NewAESCMAC(random.GetRandomBytes(16), 9) 164 if err == nil { 165 t.Errorf("expect an error when tag size is too small") 166 } 167 // tag too big 168 _, err = subtle.NewAESCMAC(random.GetRandomBytes(16), 17) 169 if err == nil { 170 t.Errorf("expect an error when tag size is too big") 171 } 172} 173 174func TestCMACComputeVerifyWithNilInput(t *testing.T) { 175 cipher, err := subtle.NewAESCMAC(random.GetRandomBytes(16), 16) 176 if err != nil { 177 t.Errorf("unexpected error when creating new CMAC") 178 } 179 tag, err := cipher.ComputeMAC(nil) 180 if err != nil { 181 t.Errorf("cipher.ComputeMAC(nil) failed: %v", err) 182 } 183 if err := cipher.VerifyMAC(tag, nil); err != nil { 184 t.Errorf("cipher.VerifyMAC(tag, nil) failed: %v", err) 185 } 186} 187 188func TestCMACVerifyMACWithInvalidInput(t *testing.T) { 189 cipher, err := subtle.NewAESCMAC(random.GetRandomBytes(16), 16) 190 if err != nil { 191 t.Errorf("unexpected error when creating new CMAC") 192 } 193 if err := cipher.VerifyMAC(nil, []byte{1}); err == nil { 194 t.Errorf("expect an error when mac is nil") 195 } 196 if err := cipher.VerifyMAC([]byte{1}, nil); err == nil { 197 t.Errorf("expect an error when data is nil") 198 } 199 if err := cipher.VerifyMAC(nil, nil); err == nil { 200 t.Errorf("cipher.VerifyMAC(nil, nil) succeeded unexpectedly") 201 } 202} 203 204func TestCMACModification(t *testing.T) { 205 a, err := subtle.NewAESCMAC(keyRFC4493, 16) 206 if err != nil { 207 t.Errorf("Could not create subtle.CMAC object: %v", err) 208 } 209 for l, e := range expected { 210 exp, err := hex.DecodeString(e) 211 if err != nil { 212 t.Errorf("Could not decode expected string %q: %v", e, err) 213 } 214 for i := 0; i < len(exp); i++ { 215 for j := 0; j < 8; j++ { 216 notExpected := make([]byte, 16) 217 copy(notExpected, exp) 218 notExpected[i] ^= 1 << uint8(j) 219 err = a.VerifyMAC(notExpected, dataRFC4493[:l]) 220 if err == nil { 221 t.Errorf("Verification of modified test vector did not fail. Test Vector %q, Modified: %q", e, hex.EncodeToString(notExpected)) 222 } 223 } 224 } 225 } 226} 227 228func TestCMACTruncation(t *testing.T) { 229 a, err := subtle.NewAESCMAC(keyRFC4493, 16) 230 if err != nil { 231 t.Errorf("Could not create subtle.CMAC object: %v", err) 232 } 233 for l, e := range expected { 234 exp, err := hex.DecodeString(e) 235 if err != nil { 236 t.Errorf("Could not decode expected string %q: %v", e, err) 237 } 238 for i := 1; i < len(exp); i++ { 239 notExpected := exp[:i] 240 err = a.VerifyMAC(notExpected, dataRFC4493[:l]) 241 if err == nil { 242 t.Errorf("Verification of truncated test vector did not fail. Test Vector %q, Modified: %q", e, hex.EncodeToString(notExpected)) 243 } 244 } 245 } 246} 247 248func TestCMACSmallerTagSize(t *testing.T) { 249 for i := 10; i <= 16; i++ { 250 a, err := subtle.NewAESCMAC(keyRFC4493, uint32(i)) 251 if err != nil { 252 t.Errorf("Could not create subtle.CMAC object: %v", err) 253 } 254 for l, e := range expected { 255 exp, err := hex.DecodeString(e) 256 if err != nil { 257 t.Errorf("Could not decode expected string %q: %v", e, err) 258 } 259 err = a.VerifyMAC(exp[:i], dataRFC4493[:l]) 260 if err != nil { 261 t.Errorf("Verification of smaller tag test vector did fail. Test Vector %q, Verification: %v", hex.EncodeToString(exp[:i]), err) 262 } 263 } 264 } 265} 266