xref: /aosp_15_r20/external/tink/go/aead/aes_gcm_key_manager.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 aead
18
19import (
20	"fmt"
21	"io"
22
23	"google.golang.org/protobuf/proto"
24	"github.com/google/tink/go/aead/subtle"
25	"github.com/google/tink/go/core/registry"
26	"github.com/google/tink/go/keyset"
27	"github.com/google/tink/go/subtle/random"
28	gcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto"
29	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
30)
31
32const (
33	aesGCMKeyVersion = 0
34	aesGCMTypeURL    = "type.googleapis.com/google.crypto.tink.AesGcmKey"
35)
36
37// common errors
38var errInvalidAESGCMKey = fmt.Errorf("aes_gcm_key_manager: invalid key")
39var errInvalidAESGCMKeyFormat = fmt.Errorf("aes_gcm_key_manager: invalid key format")
40
41// aesGCMKeyManager is an implementation of KeyManager interface.
42// It generates new AESGCMKey keys and produces new instances of AESGCM subtle.
43type aesGCMKeyManager struct{}
44
45// Assert that aesGCMKeyManager implements the KeyManager interface.
46var _ registry.KeyManager = (*aesGCMKeyManager)(nil)
47
48// Primitive creates an AESGCM subtle for the given serialized AESGCMKey proto.
49func (km *aesGCMKeyManager) Primitive(serializedKey []byte) (interface{}, error) {
50	if len(serializedKey) == 0 {
51		return nil, errInvalidAESGCMKey
52	}
53	key := new(gcmpb.AesGcmKey)
54	if err := proto.Unmarshal(serializedKey, key); err != nil {
55		return nil, errInvalidAESGCMKey
56	}
57	if err := km.validateKey(key); err != nil {
58		return nil, err
59	}
60	ret, err := subtle.NewAESGCM(key.KeyValue)
61	if err != nil {
62		return nil, fmt.Errorf("aes_gcm_key_manager: cannot create new primitive: %s", err)
63	}
64	return ret, nil
65}
66
67// NewKey creates a new key according to specification the given serialized AESGCMKeyFormat.
68func (km *aesGCMKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) {
69	if len(serializedKeyFormat) == 0 {
70		return nil, errInvalidAESGCMKeyFormat
71	}
72	keyFormat := new(gcmpb.AesGcmKeyFormat)
73	if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil {
74		return nil, errInvalidAESGCMKeyFormat
75	}
76	if err := km.validateKeyFormat(keyFormat); err != nil {
77		return nil, fmt.Errorf("aes_gcm_key_manager: invalid key format: %s", err)
78	}
79	keyValue := random.GetRandomBytes(keyFormat.KeySize)
80	return &gcmpb.AesGcmKey{
81		Version:  aesGCMKeyVersion,
82		KeyValue: keyValue,
83	}, nil
84}
85
86// NewKeyData creates a new KeyData according to specification in the given serialized
87// AESGCMKeyFormat.
88// It should be used solely by the key management API.
89func (km *aesGCMKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) {
90	key, err := km.NewKey(serializedKeyFormat)
91	if err != nil {
92		return nil, err
93	}
94	serializedKey, err := proto.Marshal(key)
95	if err != nil {
96		return nil, err
97	}
98	return &tinkpb.KeyData{
99		TypeUrl:         aesGCMTypeURL,
100		Value:           serializedKey,
101		KeyMaterialType: km.KeyMaterialType(),
102	}, nil
103}
104
105// DoesSupport indicates if this key manager supports the given key type.
106func (km *aesGCMKeyManager) DoesSupport(typeURL string) bool {
107	return typeURL == aesGCMTypeURL
108}
109
110// TypeURL returns the key type of keys managed by this key manager.
111func (km *aesGCMKeyManager) TypeURL() string {
112	return aesGCMTypeURL
113}
114
115// KeyMaterialType returns the key material type of the key manager.
116func (km *aesGCMKeyManager) KeyMaterialType() tinkpb.KeyData_KeyMaterialType {
117	return tinkpb.KeyData_SYMMETRIC
118}
119
120// DeriveKey derives a new key from serializedKeyFormat and pseudorandomness.
121func (km *aesGCMKeyManager) DeriveKey(serializedKeyFormat []byte, pseudorandomness io.Reader) (proto.Message, error) {
122	if len(serializedKeyFormat) == 0 {
123		return nil, errInvalidAESGCMKeyFormat
124	}
125	keyFormat := new(gcmpb.AesGcmKeyFormat)
126	if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil {
127		return nil, errInvalidAESGCMKeyFormat
128	}
129	if err := km.validateKeyFormat(keyFormat); err != nil {
130		return nil, fmt.Errorf("aes_gcm_key_manager: invalid key format: %s", err)
131	}
132	if err := keyset.ValidateKeyVersion(keyFormat.GetVersion(), aesGCMKeyVersion); err != nil {
133		return nil, fmt.Errorf("aes_gcm_key_manager: invalid key version: %s", err)
134	}
135
136	keyValue := make([]byte, keyFormat.GetKeySize())
137	if _, err := io.ReadFull(pseudorandomness, keyValue); err != nil {
138		return nil, fmt.Errorf("aes_gcm_key_manager: not enough pseudorandomness given")
139	}
140
141	return &gcmpb.AesGcmKey{
142		Version:  aesGCMKeyVersion,
143		KeyValue: keyValue,
144	}, nil
145}
146
147// validateKey validates the given AESGCMKey.
148func (km *aesGCMKeyManager) validateKey(key *gcmpb.AesGcmKey) error {
149	if err := keyset.ValidateKeyVersion(key.Version, aesGCMKeyVersion); err != nil {
150		return fmt.Errorf("aes_gcm_key_manager: %s", err)
151	}
152	keySize := uint32(len(key.KeyValue))
153	if err := subtle.ValidateAESKeySize(keySize); err != nil {
154		return fmt.Errorf("aes_gcm_key_manager: %s", err)
155	}
156	return nil
157}
158
159// validateKeyFormat validates the given AESGCMKeyFormat.
160func (km *aesGCMKeyManager) validateKeyFormat(format *gcmpb.AesGcmKeyFormat) error {
161	if err := subtle.ValidateAESKeySize(format.KeySize); err != nil {
162		return fmt.Errorf("aes_gcm_key_manager: %s", err)
163	}
164	return nil
165}
166