xref: /aosp_15_r20/external/tink/go/hybrid/subtle/ecies_aead_hkdf_hybrid_decrypt.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 subtle
18
19import (
20	"errors"
21
22	"github.com/google/tink/go/tink"
23)
24
25// ECIESAEADHKDFHybridDecrypt is an instance of ECIES decryption with HKDF-KEM (key encapsulation mechanism)
26// and AEAD-DEM (data encapsulation mechanism).
27type ECIESAEADHKDFHybridDecrypt struct {
28	privateKey   *ECPrivateKey
29	hkdfSalt     []byte
30	hkdfHMACAlgo string
31	pointFormat  string
32	demHelper    EciesAEADHKDFDEMHelper
33}
34
35// NewECIESAEADHKDFHybridDecrypt returns ECIES decryption construct with HKDF-KEM (key encapsulation mechanism)
36// and AEAD-DEM (data encapsulation mechanism).
37func NewECIESAEADHKDFHybridDecrypt(pvt *ECPrivateKey, hkdfSalt []byte, hkdfHMACAlgo string, ptFormat string, demHelper EciesAEADHKDFDEMHelper) (*ECIESAEADHKDFHybridDecrypt, error) {
38	return &ECIESAEADHKDFHybridDecrypt{
39		privateKey:   pvt,
40		hkdfSalt:     hkdfSalt,
41		hkdfHMACAlgo: hkdfHMACAlgo,
42		pointFormat:  ptFormat,
43		demHelper:    demHelper,
44	}, nil
45}
46
47// Decrypt is used to decrypt using ECIES with a HKDF-KEM and AEAD-DEM mechanisms.
48func (e *ECIESAEADHKDFHybridDecrypt) Decrypt(ciphertext, contextInfo []byte) ([]byte, error) {
49	curve := e.privateKey.PublicKey.Curve
50	headerSize, err := encodingSizeInBytes(curve, e.pointFormat)
51	if err != nil {
52		return nil, err
53	}
54	if len(ciphertext) < headerSize {
55		return nil, errors.New("ciphertext too short")
56	}
57	var kemBytes = make([]byte, headerSize)
58	var ct = make([]byte, len(ciphertext)-headerSize)
59	copy(kemBytes, ciphertext[:headerSize])
60	copy(ct, ciphertext[headerSize:])
61	rKem := &ECIESHKDFRecipientKem{
62		recipientPrivateKey: e.privateKey,
63	}
64	symmetricKey, err := rKem.decapsulate(kemBytes, e.hkdfHMACAlgo, e.hkdfSalt, contextInfo, e.demHelper.GetSymmetricKeySize(), e.pointFormat)
65	if err != nil {
66		return nil, err
67	}
68	prim, err := e.demHelper.GetAEADOrDAEAD(symmetricKey)
69	if err != nil {
70		return nil, err
71	}
72	switch a := prim.(type) {
73	case tink.AEAD:
74		return a.Decrypt(ct, []byte{})
75	case tink.DeterministicAEAD:
76		return a.DecryptDeterministically(ct, []byte{})
77	default:
78		return nil, errors.New("Internal error: unexpected primitive type")
79	}
80}
81