From e97e664f51681ddca869074fcac7aaad3a490326 Mon Sep 17 00:00:00 2001
From: baskaran <baskaran@google.com>
Date: Thu, 21 Mar 2019 15:23:54 -0700
Subject: [PATCH] updating keyset validation logic to ensure there is only one
 ENABLED key.

PiperOrigin-RevId: 239685123
GitOrigin-RevId: 31a6c5e65fab77c9376fffe35c1cab7ca07148e5
---
 go/keyset/BUILD.bazel        |  1 +
 go/keyset/validation.go      | 17 +++++++++++++++--
 go/keyset/validation_test.go | 24 ++++++++++++++++++++++++
 3 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/go/keyset/BUILD.bazel b/go/keyset/BUILD.bazel
index 109e5caff..09538434b 100644
--- a/go/keyset/BUILD.bazel
+++ b/go/keyset/BUILD.bazel
@@ -43,6 +43,7 @@ go_test(
         "//go/keyset:go_default_library",
         "//go/mac:go_default_library",
         "//go/subtle/aead:go_default_library",
+        "//go/subtle/random:go_default_library",
         "//go/testkeyset:go_default_library",
         "//go/testutil:go_default_library",
         "//proto:tink_go_proto",
diff --git a/go/keyset/validation.go b/go/keyset/validation.go
index 4c5c8cff0..df6e04e8d 100644
--- a/go/keyset/validation.go
+++ b/go/keyset/validation.go
@@ -41,18 +41,31 @@ func Validate(keyset *tinkpb.Keyset) error {
 	}
 	primaryKeyID := keyset.PrimaryKeyId
 	hasPrimaryKey := false
+	containsOnlyPub := true
+	numEnabledKeys := 0
 	for _, key := range keyset.Key {
 		if err := validateKey(key); err != nil {
 			return err
 		}
-		if key.Status == tinkpb.KeyStatusType_ENABLED && key.KeyId == primaryKeyID {
+		if key.Status != tinkpb.KeyStatusType_ENABLED {
+			continue
+		}
+		if key.KeyId == primaryKeyID {
 			if hasPrimaryKey {
 				return fmt.Errorf("keyset contains multiple primary keys")
 			}
 			hasPrimaryKey = true
 		}
+		if key.KeyData.KeyMaterialType != tinkpb.KeyData_ASYMMETRIC_PUBLIC {
+			containsOnlyPub = false
+		}
+		numEnabledKeys++
 	}
-	if !hasPrimaryKey {
+	if numEnabledKeys == 0 {
+		return fmt.Errorf("keyset must contain at least one ENABLED key")
+	}
+
+	if !hasPrimaryKey && !containsOnlyPub {
 		return fmt.Errorf("keyset does not contain a valid primary key")
 	}
 	return nil
diff --git a/go/keyset/validation_test.go b/go/keyset/validation_test.go
index a3470777c..bfa440355 100644
--- a/go/keyset/validation_test.go
+++ b/go/keyset/validation_test.go
@@ -18,6 +18,7 @@ import (
 	"testing"
 
 	"github.com/google/tink/go/keyset"
+	"github.com/google/tink/go/subtle/random"
 	"github.com/google/tink/go/testutil"
 	tinkpb "github.com/google/tink/proto/tink_go_proto"
 )
@@ -72,6 +73,29 @@ func TestValidate(t *testing.T) {
 			t.Errorf("expect an error when validate invalid key %d", i)
 		}
 	}
+	//no primary keys
+	keys = []*tinkpb.Keyset_Key{
+		testutil.NewDummyKey(1, tinkpb.KeyStatusType_DISABLED, tinkpb.OutputPrefixType_TINK),
+		testutil.NewDummyKey(1, tinkpb.KeyStatusType_DISABLED, tinkpb.OutputPrefixType_LEGACY),
+	}
+	if err = keyset.Validate(testutil.NewKeyset(1, keys)); err == nil {
+		t.Errorf("expect an error when there are no primary keys")
+	}
+	// public key only
+	keys = []*tinkpb.Keyset_Key{
+		testutil.NewKey(testutil.NewKeyData(testutil.EciesAeadHkdfPublicKeyTypeURL, random.GetRandomBytes(10), tinkpb.KeyData_ASYMMETRIC_PUBLIC), tinkpb.KeyStatusType_ENABLED, 1, tinkpb.OutputPrefixType_TINK),
+	}
+	if err = keyset.Validate(testutil.NewKeyset(1, keys)); err != nil {
+		t.Errorf("valid test failed when using public key only: %v", err)
+	}
+	// private key
+	keys = []*tinkpb.Keyset_Key{
+		testutil.NewKey(testutil.NewKeyData(testutil.EciesAeadHkdfPublicKeyTypeURL, random.GetRandomBytes(10), tinkpb.KeyData_ASYMMETRIC_PUBLIC), tinkpb.KeyStatusType_ENABLED, 1, tinkpb.OutputPrefixType_TINK),
+		testutil.NewKey(testutil.NewKeyData(testutil.EciesAeadHkdfPrivateKeyTypeURL, random.GetRandomBytes(10), tinkpb.KeyData_ASYMMETRIC_PRIVATE), tinkpb.KeyStatusType_ENABLED, 1, tinkpb.OutputPrefixType_TINK),
+	}
+	if err = keyset.Validate(testutil.NewKeyset(1, keys)); err == nil {
+		t.Errorf("expect an error when there are keydata other than public")
+	}
 }
 
 func generateInvalidKeys() []*tinkpb.Keyset_Key {
-- 
GitLab