xref: /aosp_15_r20/external/tink/go/prf/hkdf_prf_key_manager.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1// Copyright 2020 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 prf
18
19import (
20	"errors"
21	"fmt"
22	"io"
23
24	"google.golang.org/protobuf/proto"
25	"github.com/google/tink/go/core/registry"
26	"github.com/google/tink/go/keyset"
27	"github.com/google/tink/go/prf/subtle"
28	"github.com/google/tink/go/subtle/random"
29	commonpb "github.com/google/tink/go/proto/common_go_proto"
30	hkdfpb "github.com/google/tink/go/proto/hkdf_prf_go_proto"
31	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
32)
33
34const (
35	hkdfprfKeyVersion = 0
36	hkdfprfTypeURL    = "type.googleapis.com/google.crypto.tink.HkdfPrfKey"
37)
38
39var errInvalidHKDFPRFKey = errors.New("hkdf_prf_key_manager: invalid key")
40var errInvalidHKDFPRFKeyFormat = errors.New("hkdf_prf_key_manager: invalid key format")
41
42// hkdfprfKeyManager generates new HKDF PRF keys and produces new instances of HKDF.
43type hkdfprfKeyManager struct{}
44
45// Assert that hkdfprfKeyManager implements the KeyManager interface.
46var _ registry.KeyManager = (*hkdfprfKeyManager)(nil)
47
48// Primitive constructs a HKDF instance for the given serialized HKDFKey.
49func (km *hkdfprfKeyManager) Primitive(serializedKey []byte) (interface{}, error) {
50	if len(serializedKey) == 0 {
51		return nil, errInvalidHKDFPRFKey
52	}
53	key := new(hkdfpb.HkdfPrfKey)
54	if err := proto.Unmarshal(serializedKey, key); err != nil {
55		return nil, errInvalidHKDFPRFKey
56	}
57	if err := km.validateKey(key); err != nil {
58		return nil, err
59	}
60	hash := commonpb.HashType_name[int32(key.Params.Hash)]
61	hkdf, err := subtle.NewHKDFPRF(hash, key.KeyValue, key.Params.Salt)
62	if err != nil {
63		return nil, err
64	}
65	return hkdf, nil
66}
67
68// NewKey generates a new HKDFPRFKey according to specification in the given HKDFPRFKeyFormat.
69func (km *hkdfprfKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) {
70	if len(serializedKeyFormat) == 0 {
71		return nil, errInvalidHKDFPRFKeyFormat
72	}
73	keyFormat := new(hkdfpb.HkdfPrfKeyFormat)
74	if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil {
75		return nil, errInvalidHKDFPRFKeyFormat
76	}
77	if err := km.validateKeyFormat(keyFormat); err != nil {
78		return nil, fmt.Errorf("hkdf_prf_key_manager: invalid key format: %s", err)
79	}
80	keyValue := random.GetRandomBytes(keyFormat.KeySize)
81	return &hkdfpb.HkdfPrfKey{
82		Version:  hkdfprfKeyVersion,
83		Params:   keyFormat.Params,
84		KeyValue: keyValue,
85	}, nil
86}
87
88// NewKeyData generates a new KeyData according to specification in the given
89// serialized HKDFPRFKeyFormat. This should be used solely by the key management API.
90func (km *hkdfprfKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) {
91	key, err := km.NewKey(serializedKeyFormat)
92	if err != nil {
93		return nil, err
94	}
95	serializedKey, err := proto.Marshal(key)
96	if err != nil {
97		return nil, errInvalidHKDFPRFKeyFormat
98	}
99
100	return &tinkpb.KeyData{
101		TypeUrl:         hkdfprfTypeURL,
102		Value:           serializedKey,
103		KeyMaterialType: km.KeyMaterialType(),
104	}, nil
105}
106
107// DoesSupport checks whether this KeyManager supports the given key type.
108func (km *hkdfprfKeyManager) DoesSupport(typeURL string) bool {
109	return typeURL == hkdfprfTypeURL
110}
111
112// TypeURL returns the type URL of keys managed by this KeyManager.
113func (km *hkdfprfKeyManager) TypeURL() string {
114	return hkdfprfTypeURL
115}
116
117// KeyMaterialType returns the key material type of this KeyManager.
118func (km *hkdfprfKeyManager) KeyMaterialType() tinkpb.KeyData_KeyMaterialType {
119	return tinkpb.KeyData_SYMMETRIC
120}
121
122// DeriveKey derives a new key from serializedKeyFormat and pseudorandomness.
123func (km *hkdfprfKeyManager) DeriveKey(serializedKeyFormat []byte, pseudorandomness io.Reader) (proto.Message, error) {
124	if len(serializedKeyFormat) == 0 {
125		return nil, errInvalidHKDFPRFKeyFormat
126	}
127	keyFormat := new(hkdfpb.HkdfPrfKeyFormat)
128	if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil {
129		return nil, errInvalidHKDFPRFKeyFormat
130	}
131	if err := km.validateKeyFormat(keyFormat); err != nil {
132		return nil, fmt.Errorf("hkdf_prf_key_manager: invalid key format: %s", err)
133	}
134	if err := keyset.ValidateKeyVersion(keyFormat.GetVersion(), hkdfprfKeyVersion); err != nil {
135		return nil, fmt.Errorf("hkdf_prf_key_manager: invalid key version: %s", err)
136	}
137
138	keyValue := make([]byte, keyFormat.GetKeySize())
139	if _, err := io.ReadFull(pseudorandomness, keyValue); err != nil {
140		return nil, fmt.Errorf("hkdf_prf_key_manager: not enough pseudorandomness given")
141	}
142
143	return &hkdfpb.HkdfPrfKey{
144		Version:  hkdfprfKeyVersion,
145		Params:   keyFormat.Params,
146		KeyValue: keyValue,
147	}, nil
148}
149
150// validateKey validates the given HKDFPRFKey. It only validates the version of the
151// key because other parameters will be validated in primitive construction.
152func (km *hkdfprfKeyManager) validateKey(key *hkdfpb.HkdfPrfKey) error {
153	err := keyset.ValidateKeyVersion(key.Version, hkdfprfKeyVersion)
154	if err != nil {
155		return fmt.Errorf("hkdf_prf_key_manager: invalid version: %s", err)
156	}
157	keySize := uint32(len(key.KeyValue))
158	hash := commonpb.HashType_name[int32(key.Params.Hash)]
159	return subtle.ValidateHKDFPRFParams(hash, keySize, key.Params.Salt)
160}
161
162// validateKeyFormat validates the given HKDFKeyFormat
163func (km *hkdfprfKeyManager) validateKeyFormat(format *hkdfpb.HkdfPrfKeyFormat) error {
164	if format.Params == nil {
165		return fmt.Errorf("null HKDF params")
166	}
167	hash := commonpb.HashType_name[int32(format.Params.Hash)]
168	return subtle.ValidateHKDFPRFParams(hash, format.KeySize, format.Params.Salt)
169}
170