xref: /aosp_15_r20/external/tink/go/hybrid/ecies_aead_hkdf_dem_helper.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1// Copyright 2021 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 hybrid
18
19import (
20	"errors"
21	"fmt"
22	"strings"
23
24	"google.golang.org/protobuf/proto"
25	"github.com/google/tink/go/core/registry"
26	"github.com/google/tink/go/hybrid/subtle"
27	"github.com/google/tink/go/tink"
28	ctrhmacpb "github.com/google/tink/go/proto/aes_ctr_hmac_aead_go_proto"
29	gcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto"
30	sivpb "github.com/google/tink/go/proto/aes_siv_go_proto"
31	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
32)
33
34const (
35	aesGCMTypeURL         = "type.googleapis.com/google.crypto.tink.AesGcmKey"
36	aesCTRHMACAEADTypeURL = "type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey"
37	aesSIVTypeURL         = "type.googleapis.com/google.crypto.tink.AesSivKey"
38)
39
40// eciesAEADHKDFDEMHelper generates AEAD or DeterministicAEAD primitives for the specified KeyTemplate and key material.
41// in order to implement the EciesAEADHKDFDEMHelper interface.
42type eciesAEADHKDFDEMHelper struct {
43	demKeyURL        string
44	keyData          []byte
45	symmetricKeySize uint32
46	aesCTRSize       uint32
47}
48
49var _ subtle.EciesAEADHKDFDEMHelper = (*eciesAEADHKDFDEMHelper)(nil)
50
51// newRegisterECIESAEADHKDFDemHelper initializes and returns a RegisterECIESAEADHKDFDemHelper
52func newRegisterECIESAEADHKDFDemHelper(k *tinkpb.KeyTemplate) (*eciesAEADHKDFDEMHelper, error) {
53	var len uint32
54	var aesCTRSize uint32
55	var keyFormat []byte
56
57	if strings.Compare(k.TypeUrl, aesGCMTypeURL) == 0 {
58		gcmKeyFormat := new(gcmpb.AesGcmKeyFormat)
59		var err error
60		if err = proto.Unmarshal(k.Value, gcmKeyFormat); err != nil {
61			return nil, err
62		}
63		len = gcmKeyFormat.KeySize
64		keyFormat, err = proto.Marshal(gcmKeyFormat)
65		if err != nil {
66			return nil, fmt.Errorf("failed to serialize key format, error :%v", err)
67		}
68	} else if strings.Compare(k.TypeUrl, aesCTRHMACAEADTypeURL) == 0 {
69		aeadKeyFormat := new(ctrhmacpb.AesCtrHmacAeadKeyFormat)
70		var err error
71		if err = proto.Unmarshal(k.Value, aeadKeyFormat); err != nil {
72			return nil, err
73		}
74		if aeadKeyFormat.AesCtrKeyFormat == nil || aeadKeyFormat.HmacKeyFormat == nil {
75			return nil, fmt.Errorf("failed to deserialize key format")
76		}
77		aesCTRSize = aeadKeyFormat.AesCtrKeyFormat.KeySize
78		len = aesCTRSize + aeadKeyFormat.HmacKeyFormat.KeySize
79		keyFormat, err = proto.Marshal(aeadKeyFormat)
80		if err != nil {
81			return nil, fmt.Errorf("failed to serialize key format, error :%v", err)
82		}
83	} else if strings.Compare(k.TypeUrl, aesSIVTypeURL) == 0 {
84		daeadKeyFormat := new(sivpb.AesSivKeyFormat)
85		var err error
86		if err = proto.Unmarshal(k.Value, daeadKeyFormat); err != nil {
87			return nil, err
88		}
89		len = daeadKeyFormat.KeySize
90		keyFormat, err = proto.Marshal(daeadKeyFormat)
91		if err != nil {
92			return nil, fmt.Errorf("failed to serialize key format, error :%v", err)
93		}
94	} else {
95		return nil, fmt.Errorf("unsupported AEAD DEM key type: %s", k.TypeUrl)
96	}
97	km, err := registry.GetKeyManager(k.TypeUrl)
98	if err != nil {
99		return nil, fmt.Errorf("failed to fetch KeyManager, error: %v", err)
100	}
101
102	key, err := km.NewKey(keyFormat)
103	if err != nil {
104		return nil, fmt.Errorf("failed to fetch key, error: %v", err)
105	}
106	sk, err := proto.Marshal(key)
107	if err != nil {
108		return nil, fmt.Errorf("failed to serialize key, error: %v", err)
109	}
110
111	return &eciesAEADHKDFDEMHelper{
112		demKeyURL:        k.TypeUrl,
113		keyData:          sk,
114		symmetricKeySize: len,
115		aesCTRSize:       aesCTRSize,
116	}, nil
117}
118
119// GetSymmetricKeySize returns the symmetric key size
120func (r *eciesAEADHKDFDEMHelper) GetSymmetricKeySize() uint32 {
121	return r.symmetricKeySize
122
123}
124
125// GetAEADOrDAEAD returns the AEAD or deterministic AEAD primitive from the DEM
126func (r *eciesAEADHKDFDEMHelper) GetAEADOrDAEAD(symmetricKeyValue []byte) (interface{}, error) {
127	var sk []byte
128	if uint32(len(symmetricKeyValue)) != r.GetSymmetricKeySize() {
129		return nil, errors.New("symmetric key has incorrect length")
130	}
131	if strings.Compare(r.demKeyURL, aesGCMTypeURL) == 0 {
132		gcmKey := new(gcmpb.AesGcmKey)
133		var err error
134		if err := proto.Unmarshal(r.keyData, gcmKey); err != nil {
135			return nil, err
136		}
137		gcmKey.KeyValue = symmetricKeyValue
138		sk, err = proto.Marshal(gcmKey)
139		if err != nil {
140			return nil, fmt.Errorf("failed to serialize key, error: %v", err)
141		}
142
143	} else if strings.Compare(r.demKeyURL, aesCTRHMACAEADTypeURL) == 0 {
144		aesCTR := new(ctrhmacpb.AesCtrHmacAeadKey)
145		var err error
146		if err := proto.Unmarshal(r.keyData, aesCTR); err != nil {
147			return nil, err
148		}
149		aesCTR.AesCtrKey.KeyValue = symmetricKeyValue[:r.aesCTRSize]
150		aesCTR.HmacKey.KeyValue = symmetricKeyValue[r.aesCTRSize:]
151		sk, err = proto.Marshal(aesCTR)
152		if err != nil {
153			return nil, fmt.Errorf("failed to serialize key, error: %v", err)
154		}
155
156	} else if strings.Compare(r.demKeyURL, aesSIVTypeURL) == 0 {
157		sivKey := new(sivpb.AesSivKey)
158		var err error
159		if err := proto.Unmarshal(r.keyData, sivKey); err != nil {
160			return nil, err
161		}
162		sivKey.KeyValue = symmetricKeyValue
163		sk, err = proto.Marshal(sivKey)
164		if err != nil {
165			return nil, fmt.Errorf("failed to serialize key, error: %v", err)
166		}
167
168	} else {
169		return nil, fmt.Errorf("unsupported AEAD DEM key type: %s", r.demKeyURL)
170	}
171
172	p, err := registry.Primitive(r.demKeyURL, sk)
173	if err != nil {
174		return nil, err
175	}
176	switch p.(type) {
177	case tink.AEAD, tink.DeterministicAEAD:
178		return p, nil
179	default:
180		return nil, fmt.Errorf("Unexpected primitive type returned by the registry for the DEM: %T", p)
181	}
182}
183