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