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