xref: /aosp_15_r20/external/tink/go/prf/subtle/hmac_test.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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	"fmt"
23	"strings"
24	"testing"
25
26	"github.com/google/tink/go/prf/subtle"
27	"github.com/google/tink/go/testutil"
28)
29
30type rfc4868test struct {
31	key  string
32	data string
33	prf  map[string]string
34}
35
36func TestVectorsRFC4868(t *testing.T) {
37	// Test vectors from RFC 4868.
38	testvectors := []*rfc4868test{
39		{
40			key:  "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
41			data: "4869205468657265",
42			prf: map[string]string{
43				"SHA256": "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
44				"SHA512": "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854",
45			},
46		},
47		{
48			key:  "4a656665",
49			data: "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
50			prf: map[string]string{
51				"SHA256": "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
52				"SHA512": "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737",
53			},
54		},
55		{
56			key:  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
57			data: "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
58			prf: map[string]string{
59				"SHA256": "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
60				"SHA512": "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb",
61			},
62		},
63		{
64			key:  "0102030405060708090a0b0c0d0e0f10111213141516171819",
65			data: "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
66			prf: map[string]string{
67				"SHA256": "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
68				"SHA512": "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd",
69			},
70		},
71		{
72			key:  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
73			data: "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374",
74			prf: map[string]string{
75				"SHA256": "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
76				"SHA512": "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598",
77			},
78		},
79		{
80			key:  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
81			data: "5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f20626520686173686564206265666f7265206265696e6720757365642062792074686520484d414320616c676f726974686d2e",
82			prf: map[string]string{
83				"SHA256": "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2",
84				"SHA512": "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58",
85			},
86		},
87	}
88	for _, v := range testvectors {
89		key, err := hex.DecodeString(v.key)
90		if err != nil {
91			t.Errorf("Could not decode key: %v", err)
92		}
93		data, err := hex.DecodeString(v.data)
94		if err != nil {
95			t.Errorf("Could not decode data: %v", err)
96		}
97		for hash, e := range v.prf {
98			h, err := subtle.NewHMACPRF(hash, key)
99			if err != nil {
100				t.Errorf("Could not create HMAC PRF object: %v", err)
101			}
102			output, err := h.ComputePRF(data, uint32(len(e)/2))
103			if err != nil {
104				t.Errorf("Error computing HMAC: %v", err)
105			}
106			if hex.EncodeToString(output) != e {
107				t.Errorf("Computation and test vector differ. Computation: %q, Test Vector %q", hex.EncodeToString(output), e)
108			}
109		}
110	}
111}
112
113func TestHMACPRFWycheproofCases(t *testing.T) {
114	testutil.SkipTestIfTestSrcDirIsNotSet(t)
115	for _, hash := range []string{"SHA1", "SHA256", "SHA512"} {
116		filename := fmt.Sprintf("hmac_%s_test.json", strings.ToLower(hash))
117		suite := new(macSuite)
118		if err := testutil.PopulateSuite(suite, filename); err != nil {
119			t.Fatalf("Failed populating suite: %s", err)
120		}
121		for _, group := range suite.TestGroups {
122			groupName := fmt.Sprintf("%s-%s-%s(%d)", suite.Algorithm, group.Type, hash, group.KeySize)
123			if group.TagSize%8 != 0 {
124				t.Errorf("For %s, requested tag size is not a multiple of 8, but %d", groupName, group.TagSize)
125			}
126
127			for _, test := range group.Tests {
128				caseName := fmt.Sprintf("%s:Case-%d", groupName, test.CaseID)
129				t.Run(caseName, func(t *testing.T) {
130
131					h, err := subtle.NewHMACPRF(hash, test.Key)
132					switch test.Result {
133					case "valid":
134						if err != nil {
135							t.Fatalf("NewHMACPRF() failed: %v", err)
136						}
137						res, err := h.ComputePRF(test.Message, group.TagSize/8)
138						if err != nil {
139							t.Fatalf("ComputePRF() failed: %v", err)
140						}
141						if !bytes.Equal(res, test.Tag) {
142							t.Errorf("ComputePRF() result and expected result do not match:\nComputed: %q\nExpected: %q", hex.EncodeToString(res), hex.EncodeToString(test.Tag))
143						}
144
145					case "invalid":
146						if err != nil {
147							return
148						}
149						res, err := h.ComputePRF(test.Message, group.TagSize/8)
150						if err != nil {
151							return
152						}
153						if bytes.Equal(res, test.Tag) {
154							t.Errorf("ComputePRF() result and invalid expected result match:\nComputed: %q\nExpected: %q", hex.EncodeToString(res), hex.EncodeToString(test.Tag))
155						}
156
157					default:
158						t.Fatalf("Unsupported test result: %q", test.Result)
159					}
160				})
161			}
162		}
163	}
164}
165
166func TestHMACPRFHash(t *testing.T) {
167	if _, err := subtle.NewHMACPRF("SHA256", []byte{
168		0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
169		0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}); err != nil {
170		t.Errorf("Expected NewHMACPRF to work with SHA256: %v", err)
171	}
172	if _, err := subtle.NewHMACPRF("SHA512", []byte{
173		0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
174		0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}); err != nil {
175		t.Errorf("Expected NewHMACPRF to work with SHA512: %v", err)
176	}
177	if _, err := subtle.NewHMACPRF("SHA1", []byte{
178		0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
179		0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}); err != nil {
180		t.Errorf("Expected NewHMACPRF to work with SHA1: %v", err)
181	}
182	if _, err := subtle.NewHMACPRF("md5", []byte{
183		0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
184		0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}); err == nil {
185		t.Errorf("Expected NewHMACPRF to fail with md5")
186	}
187}
188
189func TestHMACPRFOutputLength(t *testing.T) {
190	for hash, length := range map[string]int{"SHA1": 20, "SHA256": 32, "SHA512": 64} {
191		prf, err := subtle.NewHMACPRF(hash, []byte{
192			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
193			0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
194			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
195			0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10})
196		if err != nil {
197			t.Errorf("Expected NewHMACPRF to work on 32 byte key with hash %s", hash)
198		}
199		for i := 0; i <= length; i++ {
200			output, err := prf.ComputePRF([]byte{0x01, 0x02}, uint32(i))
201			if err != nil {
202				t.Errorf("Expected to be able to compute HMAC %s PRF with %d output length", hash, i)
203			}
204			if len(output) != i {
205				t.Errorf("Expected HMAC %s PRF to compute %d bytes, got %d", hash, i, len(output))
206			}
207		}
208		for i := length + 1; i < 100; i++ {
209			_, err := prf.ComputePRF([]byte{0x01, 0x02}, uint32(i))
210			if err == nil {
211				t.Errorf("Expected to not be able to compute HMAC %s PRF with %d output length", hash, i)
212			}
213		}
214	}
215}
216
217func TestValidateHMACPRFParams(t *testing.T) {
218	if err := subtle.ValidateHMACPRFParams("SHA256", 32); err != nil {
219		t.Errorf("Unexpected error for valid HMAC PRF params: %v", err)
220	}
221	if err := subtle.ValidateHMACPRFParams("SHA256", 4); err == nil {
222		t.Errorf("Short key size not detected for HMAC PRF params")
223	}
224	if err := subtle.ValidateHMACPRFParams("md5", 32); err == nil {
225		t.Errorf("Weak hash function not detected for HMAC PRF params")
226	}
227}
228