xref: /aosp_15_r20/external/tink/go/hybrid/internal/hpke/decrypt.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1// Copyright 2022 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 hpke
18
19import (
20	"errors"
21	"fmt"
22
23	"github.com/google/tink/go/tink"
24	pb "github.com/google/tink/go/proto/hpke_go_proto"
25)
26
27// Decrypt for HPKE implements interface HybridDecrypt.
28type Decrypt struct {
29	recipientPrivKey   *pb.HpkePrivateKey
30	kem                kem
31	kdf                kdf
32	aead               aead
33	encapsulatedKeyLen int
34}
35
36var _ tink.HybridDecrypt = (*Decrypt)(nil)
37
38// NewDecrypt constructs a Decrypt using HpkePrivateKey.
39func NewDecrypt(recipientPrivKey *pb.HpkePrivateKey) (*Decrypt, error) {
40	if recipientPrivKey.GetPrivateKey() == nil || len(recipientPrivKey.GetPrivateKey()) == 0 {
41		return nil, errors.New("HpkePrivateKey.PrivateKey bytes are missing")
42	}
43	kem, kdf, aead, err := newPrimitivesFromProto(recipientPrivKey.GetPublicKey().GetParams())
44	if err != nil {
45		return nil, err
46	}
47	return &Decrypt{recipientPrivKey, kem, kdf, aead, kem.encapsulatedKeyLength()}, nil
48}
49
50// Decrypt decrypts ciphertext, verifying the integrity of contextInfo.
51func (d *Decrypt) Decrypt(ciphertext, contextInfo []byte) ([]byte, error) {
52	if len(ciphertext) < d.encapsulatedKeyLen {
53		return nil, fmt.Errorf("ciphertext (size %d) is too short", len(ciphertext))
54	}
55
56	encapsulatedKey := ciphertext[:d.encapsulatedKeyLen]
57	aeadCiphertext := ciphertext[d.encapsulatedKeyLen:]
58
59	ctx, err := newRecipientContext(encapsulatedKey, d.recipientPrivKey, d.kem, d.kdf, d.aead, contextInfo)
60	if err != nil {
61		return nil, fmt.Errorf("newRecipientContext: %v", err)
62	}
63
64	return ctx.open(aeadCiphertext, emptyAssociatedData)
65}
66