xref: /aosp_15_r20/external/tink/go/hybrid/internal/hpke/x25519_kem_test.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 hpke
18
19import (
20	"bytes"
21	"errors"
22	"fmt"
23	"testing"
24
25	"github.com/google/tink/go/subtle"
26)
27
28// TODO(b/201070904): Write tests using internetDraftVector.
29func TestX25519KEMEncapsulateBoringSSLVectors(t *testing.T) {
30	i := 0
31	vecs := baseModeX25519HKDFSHA256Vectors(t)
32	for key, vec := range vecs {
33		if key.mode != baseMode ||
34			key.kemID != x25519HKDFSHA256 ||
35			key.kdfID != hkdfSHA256 ||
36			(key.aeadID != aes128GCM && key.aeadID != aes256GCM && key.aeadID != chaCha20Poly1305) {
37			continue
38		}
39
40		i++
41		t.Run(fmt.Sprintf("%d", key.id), func(t *testing.T) {
42			kem, err := newKEM(x25519HKDFSHA256)
43			if err != nil {
44				t.Fatal(err)
45			}
46			x25519KEMGeneratePrivateKey = func() ([]byte, error) {
47				return vec.senderPrivKey, nil
48			}
49
50			secret, enc, err := kem.encapsulate(vec.recipientPubKey)
51			if err != nil {
52				t.Errorf("encapsulate for vector %v: got err %q, want success", key, err)
53			}
54			if !bytes.Equal(secret, vec.sharedSecret) {
55				t.Errorf("encapsulate for vector %v: got shared secret %v, want %v", key, secret, vec.sharedSecret)
56			}
57			if !bytes.Equal(enc, vec.encapsulatedKey) {
58				t.Errorf("encapsulate for vector %v: got encapsulated key %v, want %v", key, enc, vec.encapsulatedKey)
59			}
60		})
61	}
62	x25519KEMGeneratePrivateKey = subtle.GeneratePrivateKeyX25519
63	if i < 2 {
64		t.Errorf("number of vectors tested = %d, want > %d", i, 2)
65	}
66}
67
68func TestX25519KEMEncapsulateBadRecipientPubKey(t *testing.T) {
69	_, v := internetDraftVector(t)
70	kem, err := newKEM(x25519HKDFSHA256)
71	if err != nil {
72		t.Fatal(err)
73	}
74	badRecipientPubKey := append(v.recipientPubKey, []byte("hello")...)
75	if _, _, err := kem.encapsulate(badRecipientPubKey); err == nil {
76		t.Error("encapsulate: got success, want err")
77	}
78}
79
80func TestX25519KEMEncapsulateBadSenderPrivKey(t *testing.T) {
81	_, v := internetDraftVector(t)
82	kem, err := newKEM(x25519HKDFSHA256)
83	if err != nil {
84		t.Fatal(err)
85	}
86
87	x25519KEMPublicFromPrivate = func(privKey []byte) ([]byte, error) {
88		return nil, errors.New("failed to compute public key")
89	}
90	if _, _, err := kem.encapsulate(v.recipientPubKey); err == nil {
91		t.Error("encapsulate: got success, want err")
92	}
93	x25519KEMPublicFromPrivate = subtle.PublicFromPrivateX25519
94}
95
96func TestX25519KEMDecapsulateBoringSSLVectors(t *testing.T) {
97	i := 0
98	vecs := baseModeX25519HKDFSHA256Vectors(t)
99	for key, vec := range vecs {
100		if key.mode != baseMode ||
101			key.kemID != x25519HKDFSHA256 ||
102			key.kdfID != hkdfSHA256 ||
103			(key.aeadID != aes128GCM && key.aeadID != aes256GCM && key.aeadID != chaCha20Poly1305) {
104			continue
105		}
106
107		i++
108		t.Run(fmt.Sprintf("%d", key.id), func(t *testing.T) {
109			kem, err := newKEM(x25519HKDFSHA256)
110			if err != nil {
111				t.Fatal(err)
112			}
113			secret, err := kem.decapsulate(vec.encapsulatedKey, vec.recipientPrivKey)
114			if err != nil {
115				t.Errorf("decapsulate for vector %v: got err %q, want success", key, err)
116			}
117			if !bytes.Equal(secret, vec.sharedSecret) {
118				t.Errorf("decapsulate for vector %v: got shared secret %v, want %v", key, secret, vec.sharedSecret)
119			}
120		})
121	}
122	if i < 2 {
123		t.Errorf("number of vectors tested = %d, want > %d", i, 2)
124	}
125}
126
127// TestX25519KEMDecapsulateEncapsulatedKeyPrefixesLargerSlice checks--if the
128// encapsulated key is part of a larger slice, as in HPKE Encrypt
129// https://github.com/google/tink/blob/619b6c1bb1f8573ca56de50cfc6ba23d355670db/go/hybrid/hpke/encrypt.go#L61
130// --that decapsulate does not modify the larger slice.
131func TestX25519KEMDecapsulateEncapsulatedKeyPrefixesLargerSlice(t *testing.T) {
132	_, v := internetDraftVector(t)
133	kem, err := newKEM(x25519HKDFSHA256)
134	if err != nil {
135		t.Fatal(err)
136	}
137
138	largerSlice := make([]byte, 3*len(v.encapsulatedKey))
139	suffix := largerSlice[len(v.encapsulatedKey):]
140	zeroedSlice := make([]byte, len(suffix))
141	if !bytes.Equal(suffix, zeroedSlice) {
142		t.Errorf("suffix: got %x, want %x", suffix, zeroedSlice)
143	}
144
145	copy(largerSlice, v.encapsulatedKey)
146	if !bytes.Equal(suffix, zeroedSlice) {
147		t.Errorf("suffix: got %x, want %x", suffix, zeroedSlice)
148	}
149
150	encapsulatedKey := largerSlice[:len(v.encapsulatedKey)]
151	if _, err := kem.decapsulate(encapsulatedKey, v.recipientPrivKey); err != nil {
152		t.Errorf("decapsulate: got err %q, want success", err)
153	}
154	if !bytes.Equal(suffix, zeroedSlice) {
155		t.Errorf("suffix: got %x, want %x", suffix, zeroedSlice)
156	}
157}
158
159func TestX25519KEMDecapsulateBadEncapsulatedKey(t *testing.T) {
160	_, v := internetDraftVector(t)
161	kem, err := newKEM(x25519HKDFSHA256)
162	if err != nil {
163		t.Fatal(err)
164	}
165	badEncapsulatedKey := append(v.encapsulatedKey, []byte("hello")...)
166	if _, err := kem.decapsulate(badEncapsulatedKey, v.recipientPrivKey); err == nil {
167		t.Error("decapsulate: got success, want err")
168	}
169}
170
171func TestX25519KEMDecapsulateBadRecipientPrivKey(t *testing.T) {
172	_, v := internetDraftVector(t)
173	kem, err := newKEM(x25519HKDFSHA256)
174	if err != nil {
175		t.Fatal(err)
176	}
177	badRecipientPrivKey := append(v.recipientPrivKey, []byte("hello")...)
178	if _, err := kem.decapsulate(v.encapsulatedKey, badRecipientPrivKey); err == nil {
179		t.Error("decapsulate: got success, want err")
180	}
181}
182
183func TestX25519KEMEncapsulatedKeyLength(t *testing.T) {
184	kem, err := newKEM(x25519HKDFSHA256)
185	if err != nil {
186		t.Fatal(err)
187	}
188	if kem.encapsulatedKeyLength() != 32 {
189		t.Errorf("encapsulatedKeyLength: got %d, want 32", kem.encapsulatedKeyLength())
190	}
191}
192