xref: /aosp_15_r20/external/tink/go/prf/prf_set.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang// Copyright 2020 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 Chang// Package prf contains utilities to calculate pseudo random function families.
18*e7b1675dSTing-Kang Changpackage prf
19*e7b1675dSTing-Kang Chang
20*e7b1675dSTing-Kang Changimport (
21*e7b1675dSTing-Kang Chang	"fmt"
22*e7b1675dSTing-Kang Chang
23*e7b1675dSTing-Kang Chang	"github.com/google/tink/go/core/registry"
24*e7b1675dSTing-Kang Chang	"github.com/google/tink/go/internal/internalregistry"
25*e7b1675dSTing-Kang Chang	"github.com/google/tink/go/monitoring"
26*e7b1675dSTing-Kang Chang)
27*e7b1675dSTing-Kang Chang
28*e7b1675dSTing-Kang Chang// The PRF interface is an abstraction for an element of a pseudo random
29*e7b1675dSTing-Kang Chang// function family, selected by a key. It has the following property:
30*e7b1675dSTing-Kang Chang//   - It is deterministic. PRF.compute(input, length) will always return the
31*e7b1675dSTing-Kang Chang//     same output if the same key is used. PRF.compute(input, length1) will be
32*e7b1675dSTing-Kang Chang//     a prefix of PRF.compute(input, length2) if length1 < length2 and the same
33*e7b1675dSTing-Kang Chang//     key is used.
34*e7b1675dSTing-Kang Chang//   - It is indistinguishable from a random function:
35*e7b1675dSTing-Kang Chang//     Given the evaluation of n different inputs, an attacker cannot
36*e7b1675dSTing-Kang Chang//     distinguish between the PRF and random bytes on an input different from
37*e7b1675dSTing-Kang Chang//     the n that are known.
38*e7b1675dSTing-Kang Chang//
39*e7b1675dSTing-Kang Chang// Use cases for PRF are deterministic redaction of PII, keyed hash functions,
40*e7b1675dSTing-Kang Chang// creating sub IDs that do not allow joining with the original dataset without
41*e7b1675dSTing-Kang Chang// knowing the key.
42*e7b1675dSTing-Kang Chang// While PRFs can be used in order to prove authenticity of a message, using the
43*e7b1675dSTing-Kang Chang// MAC interface is recommended for that use case, as it has support for
44*e7b1675dSTing-Kang Chang// verification, avoiding the security problems that often happen during
45*e7b1675dSTing-Kang Chang// verification, and having automatic support for key rotation. It also allows
46*e7b1675dSTing-Kang Chang// for non-deterministic MAC algorithms.
47*e7b1675dSTing-Kang Changtype PRF interface {
48*e7b1675dSTing-Kang Chang	// Computes the PRF selected by the underlying key on input and
49*e7b1675dSTing-Kang Chang	// returns the first outputLength bytes.
50*e7b1675dSTing-Kang Chang	// When choosing this parameter keep the birthday paradox in mind.
51*e7b1675dSTing-Kang Chang	// If you have 2^n different inputs that your system has to handle
52*e7b1675dSTing-Kang Chang	// set the output length (in bytes) to at least
53*e7b1675dSTing-Kang Chang	// ceil(n/4 + 4)
54*e7b1675dSTing-Kang Chang	// This corresponds to 2*n + 32 bits, meaning a collision will occur with
55*e7b1675dSTing-Kang Chang	// a probability less than 1:2^32. When in doubt, request a security review.
56*e7b1675dSTing-Kang Chang	// Returns a non ok status if the algorithm fails or if the output of
57*e7b1675dSTing-Kang Chang	// algorithm is less than outputLength.
58*e7b1675dSTing-Kang Chang	ComputePRF(input []byte, outputLength uint32) ([]byte, error)
59*e7b1675dSTing-Kang Chang}
60*e7b1675dSTing-Kang Chang
61*e7b1675dSTing-Kang Changtype monitoredPRF struct {
62*e7b1675dSTing-Kang Chang	prf    PRF
63*e7b1675dSTing-Kang Chang	keyID  uint32
64*e7b1675dSTing-Kang Chang	logger monitoring.Logger
65*e7b1675dSTing-Kang Chang}
66*e7b1675dSTing-Kang Chang
67*e7b1675dSTing-Kang Changvar _ PRF = (*monitoredPRF)(nil)
68*e7b1675dSTing-Kang Chang
69*e7b1675dSTing-Kang Changfunc (w *monitoredPRF) ComputePRF(input []byte, outputLength uint32) ([]byte, error) {
70*e7b1675dSTing-Kang Chang	p, err := w.prf.ComputePRF(input, outputLength)
71*e7b1675dSTing-Kang Chang	if err != nil {
72*e7b1675dSTing-Kang Chang		w.logger.LogFailure()
73*e7b1675dSTing-Kang Chang		return nil, err
74*e7b1675dSTing-Kang Chang	}
75*e7b1675dSTing-Kang Chang	w.logger.Log(w.keyID, len(input))
76*e7b1675dSTing-Kang Chang	return p, nil
77*e7b1675dSTing-Kang Chang}
78*e7b1675dSTing-Kang Chang
79*e7b1675dSTing-Kang Chang// Set is a set of PRFs. A Tink Keyset can be converted into a set of PRFs using this primitive. Every
80*e7b1675dSTing-Kang Chang// key in the keyset corresponds to a PRF in the prf.Set.
81*e7b1675dSTing-Kang Chang// Every PRF in the set is given an ID, which is the same ID as the key id in
82*e7b1675dSTing-Kang Chang// the Keyset.
83*e7b1675dSTing-Kang Changtype Set struct {
84*e7b1675dSTing-Kang Chang	// PrimaryID is the key ID marked as primary in the corresponding Keyset.
85*e7b1675dSTing-Kang Chang	PrimaryID uint32
86*e7b1675dSTing-Kang Chang	// PRFs maps key IDs to their corresponding PRF.
87*e7b1675dSTing-Kang Chang	PRFs map[uint32]PRF
88*e7b1675dSTing-Kang Chang}
89*e7b1675dSTing-Kang Chang
90*e7b1675dSTing-Kang Chang// ComputePrimaryPRF is equivalent to set.PRFs[set.PrimaryID].ComputePRF(input, outputLength).
91*e7b1675dSTing-Kang Changfunc (s Set) ComputePrimaryPRF(input []byte, outputLength uint32) ([]byte, error) {
92*e7b1675dSTing-Kang Chang	prf, ok := s.PRFs[s.PrimaryID]
93*e7b1675dSTing-Kang Chang	if !ok {
94*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("Could not find primary ID %d in prf.Set", s.PrimaryID)
95*e7b1675dSTing-Kang Chang	}
96*e7b1675dSTing-Kang Chang	return prf.ComputePRF(input, outputLength)
97*e7b1675dSTing-Kang Chang}
98*e7b1675dSTing-Kang Chang
99*e7b1675dSTing-Kang Changfunc init() {
100*e7b1675dSTing-Kang Chang	if err := registry.RegisterKeyManager(new(hmacprfKeyManager)); err != nil {
101*e7b1675dSTing-Kang Chang		panic(fmt.Sprintf("prf.init() failed: %v", err))
102*e7b1675dSTing-Kang Chang	}
103*e7b1675dSTing-Kang Chang	if err := internalregistry.AllowKeyDerivation(hmacprfTypeURL); err != nil {
104*e7b1675dSTing-Kang Chang		panic(fmt.Sprintf("prf.init() failed: %v", err))
105*e7b1675dSTing-Kang Chang	}
106*e7b1675dSTing-Kang Chang	if err := registry.RegisterKeyManager(new(hkdfprfKeyManager)); err != nil {
107*e7b1675dSTing-Kang Chang		panic(fmt.Sprintf("prf.init() failed: %v", err))
108*e7b1675dSTing-Kang Chang	}
109*e7b1675dSTing-Kang Chang	if err := internalregistry.AllowKeyDerivation(hkdfprfTypeURL); err != nil {
110*e7b1675dSTing-Kang Chang		panic(fmt.Sprintf("prf.init() failed: %v", err))
111*e7b1675dSTing-Kang Chang	}
112*e7b1675dSTing-Kang Chang	if err := registry.RegisterKeyManager(new(aescmacprfKeyManager)); err != nil {
113*e7b1675dSTing-Kang Chang		panic(fmt.Sprintf("prf.init() failed: %v", err))
114*e7b1675dSTing-Kang Chang	}
115*e7b1675dSTing-Kang Chang}
116