xref: /aosp_15_r20/external/tink/go/signature/verifier_factory.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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 signature
18
19import (
20	"errors"
21	"fmt"
22
23	"github.com/google/tink/go/core/cryptofmt"
24	"github.com/google/tink/go/core/primitiveset"
25	"github.com/google/tink/go/internal/internalregistry"
26	"github.com/google/tink/go/internal/monitoringutil"
27	"github.com/google/tink/go/keyset"
28	"github.com/google/tink/go/monitoring"
29	"github.com/google/tink/go/tink"
30	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
31)
32
33// NewVerifier returns a Verifier primitive from the given keyset handle.
34func NewVerifier(handle *keyset.Handle) (tink.Verifier, error) {
35	ps, err := handle.Primitives()
36	if err != nil {
37		return nil, fmt.Errorf("verifier_factory: cannot obtain primitive set: %s", err)
38	}
39	return newWrappedVerifier(ps)
40}
41
42// verifierSet is a Verifier implementation that uses the
43// underlying primitive set for verifying.
44type wrappedVerifier struct {
45	ps     *primitiveset.PrimitiveSet
46	logger monitoring.Logger
47}
48
49// Asserts that verifierSet implements the Verifier interface.
50var _ tink.Verifier = (*wrappedVerifier)(nil)
51
52func newWrappedVerifier(ps *primitiveset.PrimitiveSet) (*wrappedVerifier, error) {
53	if _, ok := (ps.Primary.Primitive).(tink.Verifier); !ok {
54		return nil, fmt.Errorf("verifier_factory: not a Verifier primitive")
55	}
56
57	for _, primitives := range ps.Entries {
58		for _, p := range primitives {
59			if _, ok := (p.Primitive).(tink.Verifier); !ok {
60				return nil, fmt.Errorf("verifier_factory: not an Verifier primitive")
61			}
62		}
63	}
64	logger, err := createVerifierLogger(ps)
65	if err != nil {
66		return nil, err
67	}
68	return &wrappedVerifier{
69		ps:     ps,
70		logger: logger,
71	}, nil
72}
73
74func createVerifierLogger(ps *primitiveset.PrimitiveSet) (monitoring.Logger, error) {
75	// only keysets which contain annotations are monitored.
76	if len(ps.Annotations) == 0 {
77		return &monitoringutil.DoNothingLogger{}, nil
78	}
79	keysetInfo, err := monitoringutil.KeysetInfoFromPrimitiveSet(ps)
80	if err != nil {
81		return nil, err
82	}
83	return internalregistry.GetMonitoringClient().NewLogger(&monitoring.Context{
84		KeysetInfo:  keysetInfo,
85		Primitive:   "public_key_verify",
86		APIFunction: "verify",
87	})
88}
89
90var errInvalidSignature = errors.New("verifier_factory: invalid signature")
91
92// Verify checks whether the given signature is a valid signature of the given data.
93func (v *wrappedVerifier) Verify(signature, data []byte) error {
94	prefixSize := cryptofmt.NonRawPrefixSize
95	if len(signature) < prefixSize {
96		return errInvalidSignature
97	}
98
99	// try non-raw keys
100	prefix := signature[:prefixSize]
101	signatureNoPrefix := signature[prefixSize:]
102	entries, err := v.ps.EntriesForPrefix(string(prefix))
103	if err == nil {
104		for i := 0; i < len(entries); i++ {
105			var signedData []byte
106			if entries[i].PrefixType == tinkpb.OutputPrefixType_LEGACY {
107				signedData = make([]byte, 0, len(data)+1)
108				signedData = append(signedData, data...)
109				signedData = append(signedData, byte(0))
110			} else {
111				signedData = data
112			}
113
114			verifier, ok := (entries[i].Primitive).(tink.Verifier)
115			if !ok {
116				return fmt.Errorf("verifier_factory: not an Verifier primitive")
117			}
118
119			if err = verifier.Verify(signatureNoPrefix, signedData); err == nil {
120				v.logger.Log(entries[i].KeyID, len(signedData))
121				return nil
122			}
123		}
124	}
125
126	// try raw keys
127	entries, err = v.ps.RawEntries()
128	if err == nil {
129		for i := 0; i < len(entries); i++ {
130			verifier, ok := (entries[i].Primitive).(tink.Verifier)
131			if !ok {
132				return fmt.Errorf("verifier_factory: not an Verifier primitive")
133			}
134
135			if err = verifier.Verify(signature, data); err == nil {
136				v.logger.Log(entries[i].KeyID, len(data))
137				return nil
138			}
139		}
140	}
141	v.logger.LogFailure()
142	return errInvalidSignature
143}
144