22 #include <gtest/gtest.h>
33 #include "../test/file_test.h"
34 #include "../test/test_util.h"
52 class HPKETestVector {
54 explicit HPKETestVector() =
default;
55 ~HPKETestVector() =
default;
71 sender_ctx.get(), enc, &enc_len,
sizeof(enc), kem, kdf, aead,
72 public_key_r_.data(), public_key_r_.size(),
info_.data(),
info_.size(),
73 secret_key_e_.data(), secret_key_e_.size()));
75 VerifySender(sender_ctx.get());
80 secret_key_r_.size()));
81 for (
bool copy : {
false,
true}) {
91 size_t public_key_len;
97 size_t private_key_len;
105 aead, enc, enc_len,
info_.data(),
108 VerifyRecipient(recipient_ctx.get());
114 for (
const auto aead : kAllAEADs) {
123 for (
const auto kdf : kAllKDFs) {
132 for (
const Encryption &task : encryptions_) {
133 std::vector<uint8_t> encrypted(task.plaintext.size() +
135 size_t encrypted_len;
137 encrypted.size(), task.plaintext.data(),
138 task.plaintext.size(), task.aad.data(),
147 for (
const Encryption &task : encryptions_) {
148 std::vector<uint8_t> decrypted(task.ciphertext.size());
149 size_t decrypted_len;
151 decrypted.size(), task.ciphertext.data(),
152 task.ciphertext.size(), task.aad.data(),
161 for (
const Export &task : exports_) {
162 std::vector<uint8_t> exported_secret(task.export_length);
165 ctx, exported_secret.data(), exported_secret.size(),
166 task.exporter_context.data(), task.exporter_context.size()));
172 std::vector<uint8_t> aad;
178 std::vector<uint8_t> exporter_context;
179 size_t export_length;
180 std::vector<uint8_t> exported_value;
186 std::vector<uint8_t>
info_;
187 std::vector<uint8_t> public_key_e_;
188 std::vector<uint8_t> secret_key_e_;
189 std::vector<uint8_t> public_key_r_;
190 std::vector<uint8_t> secret_key_r_;
191 std::vector<Encryption> encryptions_;
192 std::vector<Export> exports_;
203 template <
typename T>
207 if (c < '0' || c >
'9') {
220 template <
typename T>
227 bool HPKETestVector::ReadFromFileTest(
FileTest *t) {
229 if (!FileTestReadInt(t, &
mode,
"mode") ||
231 !FileTestReadInt(t, &kdf_id_,
"kdf_id") ||
232 !FileTestReadInt(t, &aead_id_,
"aead_id") ||
233 !t->GetBytes(&
info_,
"info") ||
234 !t->GetBytes(&secret_key_r_,
"skRm") ||
235 !t->GetBytes(&public_key_r_,
"pkRm") ||
236 !t->GetBytes(&secret_key_e_,
"skEm") ||
237 !t->GetBytes(&public_key_e_,
"pkEm")) {
241 for (
int i = 1; t->HasAttribute(BuildAttrName(
"aad",
i));
i++) {
242 Encryption encryption;
243 if (!t->GetBytes(&encryption.aad, BuildAttrName(
"aad",
i)) ||
244 !t->GetBytes(&encryption.ciphertext, BuildAttrName(
"ct",
i)) ||
245 !t->GetBytes(&encryption.plaintext, BuildAttrName(
"pt",
i))) {
248 encryptions_.push_back(
std::move(encryption));
251 for (
int i = 1; t->HasAttribute(BuildAttrName(
"exporter_context",
i));
i++) {
253 if (!t->GetBytes(&exp.exporter_context,
254 BuildAttrName(
"exporter_context",
i)) ||
255 !FileTestReadInt(t, &exp.export_length, BuildAttrName(
"L",
i)) ||
256 !t->GetBytes(&exp.exported_value, BuildAttrName(
"exported_value",
i))) {
266 TEST(HPKETest, VerifyTestVectors) {
268 HPKETestVector test_vec;
278 const uint8_t info_a[] = {1, 1, 2, 3, 5, 8};
279 const uint8_t info_b[] = {42, 42, 42};
280 const uint8_t ad_a[] = {1, 2, 4, 8, 16};
289 size_t public_key_r_len;
291 &public_key_r_len,
sizeof(public_key_r)));
293 for (
const auto kdf : kAllKDFs) {
295 for (
const auto aead : kAllAEADs) {
306 sender_ctx.get(), enc, &enc_len,
sizeof(enc),
308 public_key_r_len, info.data(), info.size()));
313 recipient_ctx.get(),
key.get(), kdf(), aead(), enc, enc_len,
314 info.data(), info.size()));
316 const char kCleartextPayload[] =
"foobar";
320 sizeof(kCleartextPayload) +
322 size_t ciphertext_len;
324 sender_ctx.get(),
ciphertext.data(), &ciphertext_len,
326 reinterpret_cast<const uint8_t *
>(kCleartextPayload),
327 sizeof(kCleartextPayload), ad.data(), ad.size()));
330 std::vector<uint8_t> cleartext(
ciphertext.size());
331 size_t cleartext_len;
333 &cleartext_len, cleartext.size(),
335 ad.data(), ad.size()));
339 Bytes(kCleartextPayload,
sizeof(kCleartextPayload)));
348 TEST(HPKETest, X25519EncapSmallOrderPoint) {
350 static const uint8_t kSmallOrderPoint[32] = {
351 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
352 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
353 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8,
359 for (
const auto kdf : kAllKDFs) {
361 for (
const auto aead : kAllAEADs) {
368 sender_ctx.get(), enc, &enc_len,
sizeof(enc),
370 sizeof(kSmallOrderPoint),
nullptr, 0));
375 recipient_ctx.get(),
key.get(), kdf(), aead(), kSmallOrderPoint,
376 sizeof(kSmallOrderPoint),
nullptr, 0));
382 TEST(HPKETest, RecipientInvalidSeal) {
384 const char kCleartextPayload[] =
"foobar";
396 size_t ciphertext_len;
400 reinterpret_cast<const uint8_t *
>(kCleartextPayload),
401 sizeof(kCleartextPayload),
nullptr, 0));
405 TEST(HPKETest, SenderInvalidOpen) {
406 const uint8_t kMockCiphertext[100] = {0xff};
407 const size_t kMockCiphertextLen = 80;
419 sender_ctx.get(), enc, &enc_len,
sizeof(enc),
425 size_t cleartext_len;
427 sizeof(cleartext), kMockCiphertext,
428 kMockCiphertextLen,
nullptr, 0));
431 TEST(HPKETest, SetupSenderBufferTooSmall) {
440 sender_ctx.get(), enc, &enc_len,
sizeof(enc),
449 TEST(HPKETest, SetupSenderBufferTooLarge) {
460 sender_ctx.get(), enc, &enc_len,
sizeof(enc),
466 TEST(HPKETest, SetupRecipientWrongLengthEnc) {
482 TEST(HPKETest, SetupSenderWrongLengthPeerPublicValue) {
488 sender_ctx.get(), enc, &enc_len,
sizeof(enc),
498 TEST(HPKETest, InvalidRecipientKey) {
505 TEST(HPKETest, InternalParseIntSafe) {