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 "encoding/hex" 21*e7b1675dSTing-Kang Chang "strings" 22*e7b1675dSTing-Kang Chang "testing" 23*e7b1675dSTing-Kang Chang 24*e7b1675dSTing-Kang Chang "github.com/google/tink/go/mac/subtle" 25*e7b1675dSTing-Kang Chang "github.com/google/tink/go/subtle/random" 26*e7b1675dSTing-Kang Chang) 27*e7b1675dSTing-Kang Chang 28*e7b1675dSTing-Kang Changvar key, _ = hex.DecodeString("000102030405060708090a0b0c0d0e0f") 29*e7b1675dSTing-Kang Changvar data = []byte("Hello") 30*e7b1675dSTing-Kang Changvar hmacTests = []struct { 31*e7b1675dSTing-Kang Chang hashAlg string 32*e7b1675dSTing-Kang Chang tagSize uint32 33*e7b1675dSTing-Kang Chang key []byte 34*e7b1675dSTing-Kang Chang data []byte 35*e7b1675dSTing-Kang Chang expectedMac string 36*e7b1675dSTing-Kang Chang}{ 37*e7b1675dSTing-Kang Chang { 38*e7b1675dSTing-Kang Chang hashAlg: "SHA256", 39*e7b1675dSTing-Kang Chang tagSize: 32, 40*e7b1675dSTing-Kang Chang data: data, 41*e7b1675dSTing-Kang Chang key: key, 42*e7b1675dSTing-Kang Chang expectedMac: "e0ff02553d9a619661026c7aa1ddf59b7b44eac06a9908ff9e19961d481935d4", 43*e7b1675dSTing-Kang Chang }, 44*e7b1675dSTing-Kang Chang { 45*e7b1675dSTing-Kang Chang hashAlg: "SHA512", 46*e7b1675dSTing-Kang Chang tagSize: 64, 47*e7b1675dSTing-Kang Chang data: data, 48*e7b1675dSTing-Kang Chang key: key, 49*e7b1675dSTing-Kang Chang expectedMac: "481e10d823ba64c15b94537a3de3f253c16642451ac45124dd4dde120bf1e5c15" + 50*e7b1675dSTing-Kang Chang "e55487d55ba72b43039f235226e7954cd5854b30abc4b5b53171a4177047c9b", 51*e7b1675dSTing-Kang Chang }, 52*e7b1675dSTing-Kang Chang // empty data 53*e7b1675dSTing-Kang Chang { 54*e7b1675dSTing-Kang Chang hashAlg: "SHA256", 55*e7b1675dSTing-Kang Chang tagSize: 32, 56*e7b1675dSTing-Kang Chang data: []byte{}, 57*e7b1675dSTing-Kang Chang key: key, 58*e7b1675dSTing-Kang Chang expectedMac: "07eff8b326b7798c9ccfcbdbe579489ac785a7995a04618b1a2813c26744777d", 59*e7b1675dSTing-Kang Chang }, 60*e7b1675dSTing-Kang Chang} 61*e7b1675dSTing-Kang Chang 62*e7b1675dSTing-Kang Changfunc TestHMACBasic(t *testing.T) { 63*e7b1675dSTing-Kang Chang for i, test := range hmacTests { 64*e7b1675dSTing-Kang Chang cipher, err := subtle.NewHMAC(test.hashAlg, test.key, test.tagSize) 65*e7b1675dSTing-Kang Chang if err != nil { 66*e7b1675dSTing-Kang Chang t.Errorf("cannot create new mac in test case %d: %s", i, err) 67*e7b1675dSTing-Kang Chang } 68*e7b1675dSTing-Kang Chang mac, err := cipher.ComputeMAC(test.data) 69*e7b1675dSTing-Kang Chang if err != nil { 70*e7b1675dSTing-Kang Chang t.Errorf("mac computation failed in test case %d: %s", i, err) 71*e7b1675dSTing-Kang Chang } 72*e7b1675dSTing-Kang Chang if hex.EncodeToString(mac) != test.expectedMac[:(test.tagSize*2)] { 73*e7b1675dSTing-Kang Chang t.Errorf("incorrect mac in test case %d: expect %s, got %s", 74*e7b1675dSTing-Kang Chang i, test.expectedMac[:(test.tagSize*2)], hex.EncodeToString(mac)) 75*e7b1675dSTing-Kang Chang } 76*e7b1675dSTing-Kang Chang if err := cipher.VerifyMAC(mac, test.data); err != nil { 77*e7b1675dSTing-Kang Chang t.Errorf("mac verification failed in test case %d: %s", i, err) 78*e7b1675dSTing-Kang Chang } 79*e7b1675dSTing-Kang Chang } 80*e7b1675dSTing-Kang Chang} 81*e7b1675dSTing-Kang Chang 82*e7b1675dSTing-Kang Changfunc TestNewHMACWithInvalidInput(t *testing.T) { 83*e7b1675dSTing-Kang Chang // invalid hash algorithm 84*e7b1675dSTing-Kang Chang _, err := subtle.NewHMAC("MD5", random.GetRandomBytes(16), 32) 85*e7b1675dSTing-Kang Chang if err == nil || !strings.Contains(err.Error(), "invalid hash algorithm") { 86*e7b1675dSTing-Kang Chang t.Errorf("expect an error when hash algorithm is invalid") 87*e7b1675dSTing-Kang Chang } 88*e7b1675dSTing-Kang Chang // key too short 89*e7b1675dSTing-Kang Chang _, err = subtle.NewHMAC("SHA256", random.GetRandomBytes(1), 32) 90*e7b1675dSTing-Kang Chang if err == nil || !strings.Contains(err.Error(), "key too short") { 91*e7b1675dSTing-Kang Chang t.Errorf("expect an error when key is too short") 92*e7b1675dSTing-Kang Chang } 93*e7b1675dSTing-Kang Chang // tag too short 94*e7b1675dSTing-Kang Chang _, err = subtle.NewHMAC("SHA256", random.GetRandomBytes(16), 9) 95*e7b1675dSTing-Kang Chang if err == nil || !strings.Contains(err.Error(), "tag size too small") { 96*e7b1675dSTing-Kang Chang t.Errorf("expect an error when tag size is too small") 97*e7b1675dSTing-Kang Chang } 98*e7b1675dSTing-Kang Chang // tag too big 99*e7b1675dSTing-Kang Chang _, err = subtle.NewHMAC("SHA1", random.GetRandomBytes(16), 21) 100*e7b1675dSTing-Kang Chang if err == nil || !strings.Contains(err.Error(), "tag size too big") { 101*e7b1675dSTing-Kang Chang t.Errorf("expect an error when tag size is too big") 102*e7b1675dSTing-Kang Chang } 103*e7b1675dSTing-Kang Chang _, err = subtle.NewHMAC("SHA256", random.GetRandomBytes(16), 33) 104*e7b1675dSTing-Kang Chang if err == nil || !strings.Contains(err.Error(), "tag size too big") { 105*e7b1675dSTing-Kang Chang t.Errorf("expect an error when tag size is too big") 106*e7b1675dSTing-Kang Chang } 107*e7b1675dSTing-Kang Chang _, err = subtle.NewHMAC("SHA512", random.GetRandomBytes(16), 65) 108*e7b1675dSTing-Kang Chang if err == nil || !strings.Contains(err.Error(), "tag size too big") { 109*e7b1675dSTing-Kang Chang t.Errorf("expect an error when tag size is too big") 110*e7b1675dSTing-Kang Chang } 111*e7b1675dSTing-Kang Chang} 112*e7b1675dSTing-Kang Chang 113*e7b1675dSTing-Kang Changfunc TestHMAComputeVerifyWithNilInput(t *testing.T) { 114*e7b1675dSTing-Kang Chang cipher, err := subtle.NewHMAC("SHA256", random.GetRandomBytes(16), 32) 115*e7b1675dSTing-Kang Chang if err != nil { 116*e7b1675dSTing-Kang Chang t.Errorf("unexpected error when creating new HMAC") 117*e7b1675dSTing-Kang Chang } 118*e7b1675dSTing-Kang Chang tag, err := cipher.ComputeMAC(nil) 119*e7b1675dSTing-Kang Chang if err != nil { 120*e7b1675dSTing-Kang Chang t.Errorf("cipher.ComputeMAC(nil) failed: %v", err) 121*e7b1675dSTing-Kang Chang } 122*e7b1675dSTing-Kang Chang if err := cipher.VerifyMAC(tag, nil); err != nil { 123*e7b1675dSTing-Kang Chang t.Errorf("cipher.VerifyMAC(tag, nil) failed: %v", err) 124*e7b1675dSTing-Kang Chang } 125*e7b1675dSTing-Kang Chang} 126*e7b1675dSTing-Kang Chang 127*e7b1675dSTing-Kang Changfunc TestVerifyMACWithInvalidInput(t *testing.T) { 128*e7b1675dSTing-Kang Chang cipher, err := subtle.NewHMAC("SHA256", random.GetRandomBytes(16), 32) 129*e7b1675dSTing-Kang Chang if err != nil { 130*e7b1675dSTing-Kang Chang t.Errorf("unexpected error when creating new HMAC") 131*e7b1675dSTing-Kang Chang } 132*e7b1675dSTing-Kang Chang if err := cipher.VerifyMAC(nil, []byte{1}); err == nil { 133*e7b1675dSTing-Kang Chang t.Errorf("expect an error when mac is nil") 134*e7b1675dSTing-Kang Chang } 135*e7b1675dSTing-Kang Chang if err := cipher.VerifyMAC([]byte{1}, nil); err == nil { 136*e7b1675dSTing-Kang Chang t.Errorf("expect an error when data is nil") 137*e7b1675dSTing-Kang Chang } 138*e7b1675dSTing-Kang Chang if err := cipher.VerifyMAC(nil, nil); err == nil { 139*e7b1675dSTing-Kang Chang t.Errorf("cipher.VerifyMAC(nil, nil) succeeded unexpectedly") 140*e7b1675dSTing-Kang Chang } 141*e7b1675dSTing-Kang Chang} 142*e7b1675dSTing-Kang Chang 143*e7b1675dSTing-Kang Changfunc TestHMACModification(t *testing.T) { 144*e7b1675dSTing-Kang Chang for i, test := range hmacTests { 145*e7b1675dSTing-Kang Chang cipher, err := subtle.NewHMAC(test.hashAlg, test.key, test.tagSize) 146*e7b1675dSTing-Kang Chang if err != nil { 147*e7b1675dSTing-Kang Chang t.Errorf("cannot create new mac in test case %d: %s", i, err) 148*e7b1675dSTing-Kang Chang } 149*e7b1675dSTing-Kang Chang mac, _ := cipher.ComputeMAC(test.data) 150*e7b1675dSTing-Kang Chang for i := 0; i < len(mac); i++ { 151*e7b1675dSTing-Kang Chang tmp := mac[i] 152*e7b1675dSTing-Kang Chang for j := 0; j < 8; j++ { 153*e7b1675dSTing-Kang Chang mac[i] ^= 1 << uint8(j) 154*e7b1675dSTing-Kang Chang err := cipher.VerifyMAC(mac, test.data) 155*e7b1675dSTing-Kang Chang if err == nil { 156*e7b1675dSTing-Kang Chang t.Errorf("test case %d: modified MAC should be invalid", i) 157*e7b1675dSTing-Kang Chang } 158*e7b1675dSTing-Kang Chang mac[i] = tmp 159*e7b1675dSTing-Kang Chang } 160*e7b1675dSTing-Kang Chang } 161*e7b1675dSTing-Kang Chang } 162*e7b1675dSTing-Kang Chang} 163*e7b1675dSTing-Kang Chang 164*e7b1675dSTing-Kang Changfunc TestHMACTruncation(t *testing.T) { 165*e7b1675dSTing-Kang Chang for i, test := range hmacTests { 166*e7b1675dSTing-Kang Chang cipher, err := subtle.NewHMAC(test.hashAlg, test.key, test.tagSize) 167*e7b1675dSTing-Kang Chang if err != nil { 168*e7b1675dSTing-Kang Chang t.Errorf("cannot create new mac in test case %d: %s", i, err) 169*e7b1675dSTing-Kang Chang } 170*e7b1675dSTing-Kang Chang mac, _ := cipher.ComputeMAC(test.data) 171*e7b1675dSTing-Kang Chang for i := 1; i < len(mac); i++ { 172*e7b1675dSTing-Kang Chang tmp := mac[:i] 173*e7b1675dSTing-Kang Chang err := cipher.VerifyMAC(tmp, test.data) 174*e7b1675dSTing-Kang Chang if err == nil { 175*e7b1675dSTing-Kang Chang t.Errorf("test case %d: truncated MAC should be invalid", i) 176*e7b1675dSTing-Kang Chang } 177*e7b1675dSTing-Kang Chang } 178*e7b1675dSTing-Kang Chang } 179*e7b1675dSTing-Kang Chang} 180