1*e7b1675dSTing-Kang Chang// Copyright 2018 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 keyset 18*e7b1675dSTing-Kang Chang 19*e7b1675dSTing-Kang Changimport ( 20*e7b1675dSTing-Kang Chang "fmt" 21*e7b1675dSTing-Kang Chang 22*e7b1675dSTing-Kang Chang tinkpb "github.com/google/tink/go/proto/tink_go_proto" 23*e7b1675dSTing-Kang Chang) 24*e7b1675dSTing-Kang Chang 25*e7b1675dSTing-Kang Chang// ValidateKeyVersion checks whether the given version is valid. The version is valid 26*e7b1675dSTing-Kang Chang// only if it is the range [0..maxExpected] 27*e7b1675dSTing-Kang Changfunc ValidateKeyVersion(version, maxExpected uint32) error { 28*e7b1675dSTing-Kang Chang if version > maxExpected { 29*e7b1675dSTing-Kang Chang return fmt.Errorf("key has version %v; only keys with version in range [0..%v] are supported", 30*e7b1675dSTing-Kang Chang version, maxExpected) 31*e7b1675dSTing-Kang Chang } 32*e7b1675dSTing-Kang Chang return nil 33*e7b1675dSTing-Kang Chang} 34*e7b1675dSTing-Kang Chang 35*e7b1675dSTing-Kang Chang// Validate validates the given key set. 36*e7b1675dSTing-Kang Chang// Returns nil if it is valid; an error otherwise. 37*e7b1675dSTing-Kang Changfunc Validate(keyset *tinkpb.Keyset) error { 38*e7b1675dSTing-Kang Chang if keyset == nil { 39*e7b1675dSTing-Kang Chang return fmt.Errorf("Validate() called with nil") 40*e7b1675dSTing-Kang Chang } 41*e7b1675dSTing-Kang Chang if len(keyset.Key) == 0 { 42*e7b1675dSTing-Kang Chang return fmt.Errorf("empty keyset") 43*e7b1675dSTing-Kang Chang } 44*e7b1675dSTing-Kang Chang primaryKeyID := keyset.PrimaryKeyId 45*e7b1675dSTing-Kang Chang hasPrimaryKey := false 46*e7b1675dSTing-Kang Chang numEnabledKeys := 0 47*e7b1675dSTing-Kang Chang for _, key := range keyset.Key { 48*e7b1675dSTing-Kang Chang if err := validateKey(key); err != nil { 49*e7b1675dSTing-Kang Chang return err 50*e7b1675dSTing-Kang Chang } 51*e7b1675dSTing-Kang Chang if key.Status != tinkpb.KeyStatusType_ENABLED { 52*e7b1675dSTing-Kang Chang continue 53*e7b1675dSTing-Kang Chang } 54*e7b1675dSTing-Kang Chang if key.KeyId == primaryKeyID { 55*e7b1675dSTing-Kang Chang if hasPrimaryKey { 56*e7b1675dSTing-Kang Chang return fmt.Errorf("keyset contains multiple primary keys") 57*e7b1675dSTing-Kang Chang } 58*e7b1675dSTing-Kang Chang hasPrimaryKey = true 59*e7b1675dSTing-Kang Chang } 60*e7b1675dSTing-Kang Chang numEnabledKeys++ 61*e7b1675dSTing-Kang Chang } 62*e7b1675dSTing-Kang Chang if numEnabledKeys == 0 { 63*e7b1675dSTing-Kang Chang return fmt.Errorf("keyset must contain at least one ENABLED key") 64*e7b1675dSTing-Kang Chang } 65*e7b1675dSTing-Kang Chang 66*e7b1675dSTing-Kang Chang if !hasPrimaryKey { 67*e7b1675dSTing-Kang Chang return fmt.Errorf("keyset does not contain a valid primary key") 68*e7b1675dSTing-Kang Chang } 69*e7b1675dSTing-Kang Chang return nil 70*e7b1675dSTing-Kang Chang} 71*e7b1675dSTing-Kang Chang 72*e7b1675dSTing-Kang Chang/* 73*e7b1675dSTing-Kang ChangvalidateKey validates the given key. 74*e7b1675dSTing-Kang ChangReturns nil if it is valid; an error otherwise. 75*e7b1675dSTing-Kang Chang*/ 76*e7b1675dSTing-Kang Changfunc validateKey(key *tinkpb.Keyset_Key) error { 77*e7b1675dSTing-Kang Chang if key == nil { 78*e7b1675dSTing-Kang Chang return fmt.Errorf("ValidateKey() called with nil") 79*e7b1675dSTing-Kang Chang } 80*e7b1675dSTing-Kang Chang if key.KeyData == nil { 81*e7b1675dSTing-Kang Chang return fmt.Errorf("key %d has no key data", key.KeyId) 82*e7b1675dSTing-Kang Chang } 83*e7b1675dSTing-Kang Chang if key.OutputPrefixType != tinkpb.OutputPrefixType_TINK && 84*e7b1675dSTing-Kang Chang key.OutputPrefixType != tinkpb.OutputPrefixType_LEGACY && 85*e7b1675dSTing-Kang Chang key.OutputPrefixType != tinkpb.OutputPrefixType_RAW && 86*e7b1675dSTing-Kang Chang key.OutputPrefixType != tinkpb.OutputPrefixType_CRUNCHY { 87*e7b1675dSTing-Kang Chang return fmt.Errorf("key %d has unknown prefix", key.KeyId) 88*e7b1675dSTing-Kang Chang } 89*e7b1675dSTing-Kang Chang if key.Status != tinkpb.KeyStatusType_ENABLED && 90*e7b1675dSTing-Kang Chang key.Status != tinkpb.KeyStatusType_DISABLED && 91*e7b1675dSTing-Kang Chang key.Status != tinkpb.KeyStatusType_DESTROYED { 92*e7b1675dSTing-Kang Chang return fmt.Errorf("key %d has unknown status", key.KeyId) 93*e7b1675dSTing-Kang Chang } 94*e7b1675dSTing-Kang Chang return nil 95*e7b1675dSTing-Kang Chang} 96