xref: /aosp_15_r20/external/tink/go/hybrid/internal/hpke/hpke.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang// Copyright 2021 Google LLC
2*e7b1675dSTing-Kang Chang//
3*e7b1675dSTing-Kang Chang// Licensed under the Apache License, Version 2.0 (the "License");
4*e7b1675dSTing-Kang Chang// you may not use this file except in compliance with the License.
5*e7b1675dSTing-Kang Chang// You may obtain a copy of the License at
6*e7b1675dSTing-Kang Chang//
7*e7b1675dSTing-Kang Chang//      http://www.apache.org/licenses/LICENSE-2.0
8*e7b1675dSTing-Kang Chang//
9*e7b1675dSTing-Kang Chang// Unless required by applicable law or agreed to in writing, software
10*e7b1675dSTing-Kang Chang// distributed under the License is distributed on an "AS IS" BASIS,
11*e7b1675dSTing-Kang Chang// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e7b1675dSTing-Kang Chang// See the License for the specific language governing permissions and
13*e7b1675dSTing-Kang Chang// limitations under the License.
14*e7b1675dSTing-Kang Chang//
15*e7b1675dSTing-Kang Chang////////////////////////////////////////////////////////////////////////////////
16*e7b1675dSTing-Kang Chang
17*e7b1675dSTing-Kang Chang// Package hpke provides implementations of Hybrid Public Key Encryption.
18*e7b1675dSTing-Kang Changpackage hpke
19*e7b1675dSTing-Kang Chang
20*e7b1675dSTing-Kang Changimport (
21*e7b1675dSTing-Kang Chang	"encoding/binary"
22*e7b1675dSTing-Kang Chang	"fmt"
23*e7b1675dSTing-Kang Chang)
24*e7b1675dSTing-Kang Chang
25*e7b1675dSTing-Kang Changconst (
26*e7b1675dSTing-Kang Chang	// All identifier values are specified in
27*e7b1675dSTing-Kang Chang	// https://www.rfc-editor.org/rfc/rfc9180.html.
28*e7b1675dSTing-Kang Chang	// Mode identifiers.
29*e7b1675dSTing-Kang Chang	baseMode uint8 = 0x00
30*e7b1675dSTing-Kang Chang
31*e7b1675dSTing-Kang Chang	// KEM algorithm identifiers.
32*e7b1675dSTing-Kang Chang	x25519HKDFSHA256 uint16 = 0x0020
33*e7b1675dSTing-Kang Chang
34*e7b1675dSTing-Kang Chang	// KDF algorithm identifiers.
35*e7b1675dSTing-Kang Chang	hkdfSHA256 uint16 = 0x0001
36*e7b1675dSTing-Kang Chang
37*e7b1675dSTing-Kang Chang	// AEAD algorithm identifiers.
38*e7b1675dSTing-Kang Chang	aes128GCM        uint16 = 0x0001
39*e7b1675dSTing-Kang Chang	aes256GCM        uint16 = 0x0002
40*e7b1675dSTing-Kang Chang	chaCha20Poly1305 uint16 = 0x0003
41*e7b1675dSTing-Kang Chang
42*e7b1675dSTing-Kang Chang	sha256 = "SHA256"
43*e7b1675dSTing-Kang Chang	hpkeV1 = "HPKE-v1"
44*e7b1675dSTing-Kang Chang)
45*e7b1675dSTing-Kang Chang
46*e7b1675dSTing-Kang Changvar (
47*e7b1675dSTing-Kang Chang	emptySalt           = []byte{}
48*e7b1675dSTing-Kang Chang	emptyIKM            = []byte{}
49*e7b1675dSTing-Kang Chang	emptyAssociatedData = []byte{}
50*e7b1675dSTing-Kang Chang)
51*e7b1675dSTing-Kang Chang
52*e7b1675dSTing-Kang Chang// kemSuiteID generates the KEM suite ID from kemID according to
53*e7b1675dSTing-Kang Chang// https://www.rfc-editor.org/rfc/rfc9180.html#section-4.1-5.
54*e7b1675dSTing-Kang Changfunc kemSuiteID(kemID uint16) []byte {
55*e7b1675dSTing-Kang Chang	return binary.BigEndian.AppendUint16([]byte("KEM"), kemID)
56*e7b1675dSTing-Kang Chang}
57*e7b1675dSTing-Kang Chang
58*e7b1675dSTing-Kang Chang// hpkeSuiteID generates the HPKE suite ID according to
59*e7b1675dSTing-Kang Chang// https://www.rfc-editor.org/rfc/rfc9180.html#section-5.1-8.
60*e7b1675dSTing-Kang Changfunc hpkeSuiteID(kemID, kdfID, aeadID uint16) []byte {
61*e7b1675dSTing-Kang Chang	// Allocate memory for the return value with the exact amount of bytes needed.
62*e7b1675dSTing-Kang Chang	res := make([]byte, 0, 4+2+2+2)
63*e7b1675dSTing-Kang Chang	res = append(res, "HPKE"...)
64*e7b1675dSTing-Kang Chang	res = binary.BigEndian.AppendUint16(res, kemID)
65*e7b1675dSTing-Kang Chang	res = binary.BigEndian.AppendUint16(res, kdfID)
66*e7b1675dSTing-Kang Chang	res = binary.BigEndian.AppendUint16(res, aeadID)
67*e7b1675dSTing-Kang Chang	return res
68*e7b1675dSTing-Kang Chang}
69*e7b1675dSTing-Kang Chang
70*e7b1675dSTing-Kang Chang// keyScheduleContext creates the key_schedule_context defined at
71*e7b1675dSTing-Kang Chang// https://www.rfc-editor.org/rfc/rfc9180.html#section-5.1-10.
72*e7b1675dSTing-Kang Changfunc keyScheduleContext(mode uint8, pskIDHash, infoHash []byte) []byte {
73*e7b1675dSTing-Kang Chang	// Allocate memory for the return value with the exact amount of bytes needed.
74*e7b1675dSTing-Kang Chang	res := make([]byte, 0, 1+len(pskIDHash)+len(infoHash))
75*e7b1675dSTing-Kang Chang	res = append(res, mode)
76*e7b1675dSTing-Kang Chang	res = append(res, pskIDHash...)
77*e7b1675dSTing-Kang Chang	res = append(res, infoHash...)
78*e7b1675dSTing-Kang Chang	return res
79*e7b1675dSTing-Kang Chang}
80*e7b1675dSTing-Kang Chang
81*e7b1675dSTing-Kang Chang// labelIKM returns a labeled IKM according to LabeledExtract() defined at
82*e7b1675dSTing-Kang Chang// https://www.rfc-editor.org/rfc/rfc9180.html#section-4.
83*e7b1675dSTing-Kang Changfunc labelIKM(label string, ikm, suiteID []byte) []byte {
84*e7b1675dSTing-Kang Chang	// Allocate memory for the return value with the exact amount of bytes needed.
85*e7b1675dSTing-Kang Chang	res := make([]byte, 0, len(hpkeV1)+len(suiteID)+len(label)+len(ikm))
86*e7b1675dSTing-Kang Chang	res = append(res, hpkeV1...)
87*e7b1675dSTing-Kang Chang	res = append(res, suiteID...)
88*e7b1675dSTing-Kang Chang	res = append(res, label...)
89*e7b1675dSTing-Kang Chang	res = append(res, ikm...)
90*e7b1675dSTing-Kang Chang	return res
91*e7b1675dSTing-Kang Chang}
92*e7b1675dSTing-Kang Chang
93*e7b1675dSTing-Kang Chang// labelInfo returns a labeled info according to LabeledExpand() defined at
94*e7b1675dSTing-Kang Chang// https://www.rfc-editor.org/rfc/rfc9180.html#section-4.
95*e7b1675dSTing-Kang Changfunc labelInfo(label string, info, suiteID []byte, length int) ([]byte, error) {
96*e7b1675dSTing-Kang Chang	length16 := uint16(length)
97*e7b1675dSTing-Kang Chang	if int(length16) != length {
98*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("length %d must be a valid uint16 value", length)
99*e7b1675dSTing-Kang Chang	}
100*e7b1675dSTing-Kang Chang
101*e7b1675dSTing-Kang Chang	// Allocate memory for the return value with the exact amount of bytes needed.
102*e7b1675dSTing-Kang Chang	res := make([]byte, 0, 2+len(hpkeV1)+len(suiteID)+len(label)+len(info))
103*e7b1675dSTing-Kang Chang	res = binary.BigEndian.AppendUint16(res, length16)
104*e7b1675dSTing-Kang Chang	res = append(res, hpkeV1...)
105*e7b1675dSTing-Kang Chang	res = append(res, suiteID...)
106*e7b1675dSTing-Kang Chang	res = append(res, label...)
107*e7b1675dSTing-Kang Chang	res = append(res, info...)
108*e7b1675dSTing-Kang Chang	return res, nil
109*e7b1675dSTing-Kang Chang}
110