• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2019 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 primitiveset_test
18
19import (
20	"fmt"
21	"testing"
22
23	"github.com/google/go-cmp/cmp"
24	"github.com/google/tink/go/core/primitiveset"
25	"github.com/google/tink/go/testutil"
26	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
27)
28
29func makeTestKey(keyID int, status tinkpb.KeyStatusType, outputPrefixType tinkpb.OutputPrefixType, typeURL string) *tinkpb.Keyset_Key {
30	k := testutil.NewDummyKey(keyID, status, outputPrefixType)
31	k.GetKeyData().TypeUrl = typeURL
32	return k
33}
34
35func TestPrimitvesetNew(t *testing.T) {
36	ps := primitiveset.New()
37	if ps.Primary != nil || ps.Entries == nil || ps.EntriesInKeysetOrder == nil {
38		t.Errorf("expect primary to be nil and primitives is initialized")
39	}
40}
41
42func TestPrimitivesetAddAndEntriesInKeysetOrder(t *testing.T) {
43	keys := []*tinkpb.Keyset_Key{
44		makeTestKey(1234543, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.1"),
45		makeTestKey(7213743, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_LEGACY, "type.url.2"),
46		makeTestKey(5294722, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_RAW, "type.url.3"),
47	}
48	macs := make([]testutil.DummyMAC, len(keys))
49	for i := 0; i < len(macs); i++ {
50		macs[i] = testutil.DummyMAC{Name: fmt.Sprintf("%d", i)}
51	}
52	ps := primitiveset.New()
53	got := []*primitiveset.Entry{}
54	for i := 0; i < len(macs); i++ {
55		e, err := ps.Add(&macs[i], keys[i])
56		if err != nil {
57			t.Fatalf("ps.Add(%q) err = %v, want nil", macs[i].Name, err)
58		}
59		got = append(got, e)
60	}
61	want := []*primitiveset.Entry{
62		{
63			KeyID:      1234543,
64			Status:     tinkpb.KeyStatusType_ENABLED,
65			Primitive:  &testutil.DummyMAC{Name: "0"},
66			PrefixType: tinkpb.OutputPrefixType_TINK,
67			TypeURL:    "type.url.1",
68			Prefix:     string([]byte{1, 0, 18, 214, 111}),
69		},
70		{
71			KeyID:      7213743,
72			Status:     tinkpb.KeyStatusType_ENABLED,
73			Primitive:  &testutil.DummyMAC{Name: "1"},
74			PrefixType: tinkpb.OutputPrefixType_LEGACY,
75			TypeURL:    "type.url.2",
76			Prefix:     string([]byte{0, 0, 110, 18, 175}),
77		},
78		{
79			KeyID:      5294722,
80			Status:     tinkpb.KeyStatusType_ENABLED,
81			Primitive:  &testutil.DummyMAC{Name: "2"},
82			PrefixType: tinkpb.OutputPrefixType_RAW,
83			TypeURL:    "type.url.3",
84			Prefix:     "",
85		},
86	}
87	if !cmp.Equal(got, want) {
88		t.Errorf("got = %v, want = %v", got, want)
89	}
90	if !cmp.Equal(ps.EntriesInKeysetOrder, want) {
91		t.Errorf("EntriesInKeysetOrder = %v, want = %v", ps.EntriesInKeysetOrder, want)
92	}
93}
94
95func TestPrimitivesetRawEntries(t *testing.T) {
96	keys := []*tinkpb.Keyset_Key{
97		makeTestKey(1234543, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.1"),
98		makeTestKey(7213743, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_LEGACY, "type.url.2"),
99		makeTestKey(9473277, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_RAW, "type.url.3"),
100		makeTestKey(5294722, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_RAW, "type.url.4"),
101	}
102	macs := make([]testutil.DummyMAC, len(keys))
103	for i := 0; i < len(macs); i++ {
104		macs[i] = testutil.DummyMAC{Name: fmt.Sprintf("Mac#%d", i)}
105	}
106	ps := primitiveset.New()
107	for i := 0; i < len(macs); i++ {
108		if _, err := ps.Add(macs[i], keys[i]); err != nil {
109			t.Fatalf("ps.Add(%q) err = %v, want nil", macs[i].Name, err)
110		}
111	}
112	got, err := ps.RawEntries()
113	if err != nil {
114		t.Errorf("RawEntries() err = %v, want nil", err)
115	}
116	want := []*primitiveset.Entry{
117		{
118			KeyID:      keys[2].GetKeyId(),
119			Status:     keys[2].GetStatus(),
120			PrefixType: keys[2].GetOutputPrefixType(),
121			TypeURL:    keys[2].GetKeyData().GetTypeUrl(),
122			Primitive:  macs[2],
123		},
124		{
125			KeyID:      keys[3].GetKeyId(),
126			Status:     keys[3].GetStatus(),
127			PrefixType: keys[3].GetOutputPrefixType(),
128			TypeURL:    keys[3].GetKeyData().GetTypeUrl(),
129			Primitive:  macs[3],
130		},
131	}
132	if !cmp.Equal(got, want) {
133		t.Errorf("Raw primitives got = %v, want = %v", got, want)
134	}
135}
136
137func TestPrimitivesetPrefixedEntries(t *testing.T) {
138	type testCase struct {
139		tag        string
140		prefix     string
141		keys       []*tinkpb.Keyset_Key
142		primitives []interface{}
143		want       []*primitiveset.Entry
144	}
145	for _, tc := range []testCase{
146		{
147			tag:    "legacy Prefix",
148			prefix: string([]byte{0, 0, 18, 214, 111}), // LEGACY_PREFIX + 1234543,
149			keys: []*tinkpb.Keyset_Key{
150				makeTestKey(1234543, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_LEGACY, "type.url.1"),
151				makeTestKey(7213743, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.2"),
152			},
153			primitives: []interface{}{
154				&testutil.DummyMAC{Name: "1"},
155				&testutil.DummyMAC{Name: "2"},
156			},
157			want: []*primitiveset.Entry{
158				{
159					KeyID:      1234543,
160					Status:     tinkpb.KeyStatusType_ENABLED,
161					Primitive:  &testutil.DummyMAC{Name: "1"},
162					PrefixType: tinkpb.OutputPrefixType_LEGACY,
163					TypeURL:    "type.url.1",
164					Prefix:     string([]byte{0, 0, 18, 214, 111}),
165				},
166			},
167		},
168		{
169			tag:    "raw prefix",
170			prefix: "",
171			keys: []*tinkpb.Keyset_Key{
172				makeTestKey(1234543, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_RAW, "type.url.1"),
173				makeTestKey(7213743, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.2"),
174			},
175			primitives: []interface{}{
176				&testutil.DummyMAC{Name: "1"},
177				&testutil.DummyMAC{Name: "2"},
178			},
179			want: []*primitiveset.Entry{
180				{
181					KeyID:      1234543,
182					Status:     tinkpb.KeyStatusType_ENABLED,
183					Primitive:  &testutil.DummyMAC{Name: "1"},
184					PrefixType: tinkpb.OutputPrefixType_RAW,
185					TypeURL:    "type.url.1",
186					Prefix:     "",
187				},
188			},
189		},
190		{
191			tag:    "tink prefix  multiple entries",
192			prefix: string([]byte{1, 0, 18, 214, 111}), // TINK_PREFIX + 1234543
193			keys: []*tinkpb.Keyset_Key{
194				makeTestKey(1234543, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.1"),
195				makeTestKey(1234543, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.2"),
196				makeTestKey(1234543, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_RAW, "type.url.3"),
197				makeTestKey(7213743, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.4"),
198			},
199			primitives: []interface{}{
200				&testutil.DummyMAC{Name: "1"},
201				&testutil.DummyMAC{Name: "2"},
202				&testutil.DummyMAC{Name: "3"},
203				&testutil.DummyMAC{Name: "4"},
204			},
205			want: []*primitiveset.Entry{
206				{
207					KeyID:      1234543,
208					Status:     tinkpb.KeyStatusType_ENABLED,
209					Primitive:  &testutil.DummyMAC{Name: "1"},
210					PrefixType: tinkpb.OutputPrefixType_TINK,
211					TypeURL:    "type.url.1",
212					Prefix:     string([]byte{1, 0, 18, 214, 111}),
213				},
214				{
215					KeyID:      1234543,
216					Status:     tinkpb.KeyStatusType_ENABLED,
217					Primitive:  &testutil.DummyMAC{Name: "2"},
218					PrefixType: tinkpb.OutputPrefixType_TINK,
219					TypeURL:    "type.url.2",
220					Prefix:     string([]byte{1, 0, 18, 214, 111}),
221				},
222			},
223		},
224	} {
225		ps := primitiveset.New()
226		for i := 0; i < len(tc.keys); i++ {
227			if _, err := ps.Add(tc.primitives[i], tc.keys[i]); err != nil {
228				t.Fatalf("ps.Add(%q) err = %v, want nil", tc.primitives[i], err)
229			}
230		}
231		got, err := ps.EntriesForPrefix(tc.prefix)
232		if err != nil {
233			t.Errorf("EntriesForPrefix() err =  %v, want nil", err)
234		}
235		if !cmp.Equal(got, tc.want) {
236			t.Errorf("got = %v, want = %v", got, tc.want)
237		}
238	}
239}
240
241func TestAddWithInvalidInput(t *testing.T) {
242	ps := primitiveset.New()
243	type testCase struct {
244		tag       string
245		primitive interface{}
246		key       *tinkpb.Keyset_Key
247	}
248	for _, tc := range []testCase{
249		{
250			tag:       "nil primitive",
251			primitive: nil,
252			key:       makeTestKey(0, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.1"),
253		},
254		{
255			tag:       "nil key",
256			primitive: &testutil.DummyMAC{},
257			key:       nil,
258		},
259		{
260			tag:       "unknown prefix type",
261			primitive: &testutil.DummyMAC{},
262			key:       makeTestKey(0, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_UNKNOWN_PREFIX, "type.url.1"),
263		},
264		{
265			tag:       "disabled key",
266			primitive: &testutil.DummyMAC{},
267			key:       makeTestKey(0, tinkpb.KeyStatusType_DISABLED, tinkpb.OutputPrefixType_TINK, "type.url.1"),
268		},
269		{
270			tag:       "nil keyData",
271			primitive: &testutil.DummyMAC{},
272			key: &tinkpb.Keyset_Key{
273				KeyData:          nil,
274				Status:           tinkpb.KeyStatusType_ENABLED,
275				OutputPrefixType: tinkpb.OutputPrefixType_TINK,
276				KeyId:            0,
277			},
278		},
279	} {
280		if _, err := ps.Add(tc.primitive, tc.key); err == nil {
281			t.Errorf("Add() err = nil, want error")
282		}
283	}
284}
285