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