3
* (C) 2016 René Korthaus
5
* Botan is released under the Simplified BSD License (see license.txt)
9
#include <botan/version.h>
11
#if defined(BOTAN_HAS_FFI)
12
#include <botan/hex.h>
13
#include <botan/ffi.h>
14
#include <botan/loadstor.h>
17
namespace Botan_Tests {
21
#if defined(BOTAN_HAS_FFI)
23
#define TEST_FFI_OK(func, args) result.test_rc_ok(#func, func args)
24
#define TEST_FFI_FAIL(msg, func, args) result.test_rc_fail(#func, msg, func args)
25
#define TEST_FFI_RC(rc, func, args) result.test_rc(#func, rc, func args)
27
#define REQUIRE_FFI_OK(func, args) \
28
if(!TEST_FFI_OK(func, args)) { \
29
result.test_note("Exiting test early due to failure"); \
33
class FFI_Unit_Tests final : public Test
36
std::vector<Test::Result> run() override
38
Test::Result result("FFI");
40
result.test_is_eq("FFI API version", botan_ffi_api_version(), uint32_t(BOTAN_HAS_FFI));
41
result.test_is_eq("Major version", botan_version_major(), Botan::version_major());
42
result.test_is_eq("Minor version", botan_version_minor(), Botan::version_minor());
43
result.test_is_eq("Patch version", botan_version_patch(), Botan::version_patch());
44
result.test_is_eq("Botan version", botan_version_string(), Botan::version_cstr());
45
result.test_is_eq("Botan version datestamp", botan_version_datestamp(), Botan::version_datestamp());
46
result.test_is_eq("FFI supports its own version", botan_ffi_supports_api(botan_ffi_api_version()), 0);
48
const std::vector<uint8_t> mem1 = { 0xFF, 0xAA, 0xFF };
49
const std::vector<uint8_t> mem2 = mem1;
50
const std::vector<uint8_t> mem3 = { 0xFF, 0xA9, 0xFF };
52
TEST_FFI_RC(0, botan_same_mem, (mem1.data(), mem2.data(), mem1.size()));
53
TEST_FFI_RC(-1, botan_same_mem, (mem1.data(), mem3.data(), mem1.size()));
55
std::vector<uint8_t> to_zero = { 0xFF, 0xA0 };
56
TEST_FFI_OK(botan_scrub_mem, (to_zero.data(), to_zero.size()));
57
result.confirm("scrub_memory zeros", to_zero[0] == 0 && to_zero[1] == 0);
59
const std::vector<uint8_t> bin = { 0xAA, 0xDE, 0x01 };
60
const char* input_str = "ABC";
63
std::vector<uint8_t> outbuf;
66
outstr.resize(2 * bin.size());
67
TEST_FFI_OK(botan_hex_encode, (bin.data(), bin.size(), &outstr[0], 0));
68
result.test_eq("uppercase hex", outstr, "AADE01");
70
TEST_FFI_OK(botan_hex_encode, (bin.data(), bin.size(), &outstr[0], BOTAN_FFI_HEX_LOWER_CASE));
71
result.test_eq("lowercase hex", outstr, "aade01");
73
// RNG test and initialization
76
TEST_FFI_FAIL("invalid rng type", botan_rng_init, (&rng, "invalid_type"));
80
if(TEST_FFI_OK(botan_rng_init, (&rng, "system")))
82
TEST_FFI_OK(botan_rng_get, (rng, outbuf.data(), outbuf.size()));
83
TEST_FFI_OK(botan_rng_reseed, (rng, 256));
84
TEST_FFI_OK(botan_rng_destroy, (rng));
87
if(TEST_FFI_OK(botan_rng_init, (&rng, "user")))
89
TEST_FFI_OK(botan_rng_get, (rng, outbuf.data(), outbuf.size()));
90
TEST_FFI_OK(botan_rng_reseed, (rng, 256));
91
// used for the rest of this function and destroyed at the end
95
result.test_note("Existing early due to missing FFI RNG");
101
TEST_FFI_FAIL("invalid hash name", botan_hash_init, (&hash, "SHA-255", 0));
102
TEST_FFI_FAIL("invalid flags", botan_hash_init, (&hash, "SHA-256", 1));
104
if(TEST_FFI_OK(botan_hash_init, (&hash, "SHA-256", 0)))
107
TEST_FFI_FAIL("output buffer too short", botan_hash_name, (hash, namebuf, 5));
109
if(TEST_FFI_OK(botan_hash_name, (hash, namebuf, sizeof(namebuf))))
111
result.test_eq("hash name", std::string(namebuf), "SHA-256");
115
if (TEST_FFI_OK(botan_hash_block_size, (hash, &block_size)))
117
result.test_eq("hash block size", block_size, 64);
121
if(TEST_FFI_OK(botan_hash_output_length, (hash, &output_len)))
123
result.test_eq("hash output length", output_len, 32);
125
outbuf.resize(output_len);
127
// Test that after clear or final the object can be reused
128
for(size_t r = 0; r != 2; ++r)
130
TEST_FFI_OK(botan_hash_update, (hash, reinterpret_cast<const uint8_t*>(input_str), 1));
131
TEST_FFI_OK(botan_hash_clear, (hash));
133
TEST_FFI_OK(botan_hash_update, (hash, reinterpret_cast<const uint8_t*>(input_str), std::strlen(input_str)));
134
TEST_FFI_OK(botan_hash_final, (hash, outbuf.data()));
136
result.test_eq("SHA-256 output", outbuf, "B5D4045C3F466FA91FE2CC6ABE79232A1A57CDF104F7A26E716E0A1E2789DF78");
139
// Test botan_hash_copy_state
140
const char *msg = "message digest";
141
const char *expected = "F7846F55CF23E14EEBEAB5B4E1550CAD5B509E3348FBC4EFA3A1413D393CB650";
142
TEST_FFI_OK(botan_hash_clear, (hash));
143
TEST_FFI_OK(botan_hash_update, (hash, reinterpret_cast<const uint8_t*>(&msg[0]), 1));
145
if (TEST_FFI_OK(botan_hash_copy_state, (&fork, hash)))
147
TEST_FFI_OK(botan_hash_update, (fork, reinterpret_cast<const uint8_t*>(&msg[1]), std::strlen(msg) - 2));
149
TEST_FFI_OK(botan_hash_update, (hash, reinterpret_cast<const uint8_t*>(&msg[1]), std::strlen(msg) - 1));
150
TEST_FFI_OK(botan_hash_final, (hash, outbuf.data()));
151
result.test_eq("hashing split", outbuf, expected);
153
TEST_FFI_OK(botan_hash_update, (fork, reinterpret_cast<const uint8_t*>(&msg[std::strlen(msg)-1]), 1));
154
TEST_FFI_OK(botan_hash_final, (fork, outbuf.data()));
155
result.test_eq("hashing split", outbuf, expected);
157
TEST_FFI_OK(botan_hash_destroy, (fork));
161
TEST_FFI_OK(botan_hash_destroy, (hash));
166
TEST_FFI_FAIL("bad flag", botan_mac_init, (&mac, "HMAC(SHA-256)", 1));
167
TEST_FFI_FAIL("bad name", botan_mac_init, (&mac, "HMAC(SHA-259)", 0));
169
if(TEST_FFI_OK(botan_mac_init, (&mac, "HMAC(SHA-256)", 0)))
172
TEST_FFI_FAIL("output buffer too short", botan_mac_name, (mac, namebuf, 5));
174
if(TEST_FFI_OK(botan_mac_name, (mac, namebuf, 20)))
176
result.test_eq("mac name", std::string(namebuf), "HMAC(SHA-256)");
181
if(TEST_FFI_OK(botan_mac_output_length, (mac, &output_len)))
183
result.test_eq("MAC output length", output_len, 32);
185
const uint8_t mac_key[] = { 0xAA, 0xBB, 0xCC, 0xDD };
186
outbuf.resize(output_len);
188
// Test that after clear or final the object can be reused
189
for(size_t r = 0; r != 2; ++r)
191
TEST_FFI_OK(botan_mac_set_key, (mac, mac_key, sizeof(mac_key)));
192
TEST_FFI_OK(botan_mac_update, (mac, reinterpret_cast<const uint8_t*>(input_str), std::strlen(input_str)));
193
TEST_FFI_OK(botan_mac_clear, (mac));
195
TEST_FFI_OK(botan_mac_set_key, (mac, mac_key, sizeof(mac_key)));
196
TEST_FFI_OK(botan_mac_update, (mac, reinterpret_cast<const uint8_t*>(input_str), std::strlen(input_str)));
197
TEST_FFI_OK(botan_mac_final, (mac, outbuf.data()));
199
result.test_eq("HMAC output", outbuf, "1A82EEA984BC4A7285617CC0D05F1FE1D6C96675924A81BC965EE8FF7B0697A7");
203
TEST_FFI_OK(botan_mac_destroy, (mac));
207
const std::vector<uint8_t> pbkdf_salt = Botan::hex_decode("ED1F39A0A7F3889AAF7E60743B3BC1CC2C738E60");
208
const std::string passphrase = "ltexmfeyylmlbrsyikaw";
209
const size_t pbkdf_out_len = 10;
210
const size_t pbkdf_iterations = 1000;
212
outbuf.resize(pbkdf_out_len);
214
if(TEST_FFI_OK(botan_pbkdf, ("PBKDF2(SHA-1)",
215
outbuf.data(), outbuf.size(),
217
pbkdf_salt.data(), pbkdf_salt.size(),
220
result.test_eq("PBKDF output", outbuf, "027AFADD48F4BE8DCC4F");
223
size_t iters_10ms, iters_100ms;
225
TEST_FFI_OK(botan_pbkdf_timed, ("PBKDF2(SHA-1)", outbuf.data(), outbuf.size(),
227
pbkdf_salt.data(), pbkdf_salt.size(),
229
TEST_FFI_OK(botan_pbkdf_timed, ("PBKDF2(SHA-1)", outbuf.data(), outbuf.size(),
231
pbkdf_salt.data(), pbkdf_salt.size(),
234
result.test_note("PBKDF timed 10 ms " + std::to_string(iters_10ms) + " iterations " +
235
"100 ms " + std::to_string(iters_100ms) + " iterations");
237
#if defined(BOTAN_HAS_KDF2)
238
const std::vector<uint8_t> kdf_secret = Botan::hex_decode("92167440112E");
239
const std::vector<uint8_t> kdf_salt = Botan::hex_decode("45A9BEDED69163123D0348F5185F61ABFB1BF18D6AEA454F");
240
const size_t kdf_out_len = 18;
241
outbuf.resize(kdf_out_len);
243
if(TEST_FFI_OK(botan_kdf, ("KDF2(SHA-1)", outbuf.data(), outbuf.size(),
251
result.test_eq("KDF output", outbuf, "3A5DC9AA1C872B4744515AC2702D6396FC2A");
256
outstr.resize(out_len);
258
int rc = botan_bcrypt_generate(reinterpret_cast<uint8_t*>(&outstr[0]),
259
&out_len, passphrase.c_str(), rng, 4, 0);
263
result.test_eq("bcrypt output size", out_len, 61);
265
TEST_FFI_OK(botan_bcrypt_is_valid, (passphrase.c_str(), outstr.data()));
266
TEST_FFI_FAIL("bad password", botan_bcrypt_is_valid, ("nope", outstr.data()));
269
#if defined(BOTAN_HAS_ECDSA)
271
botan_x509_cert_t cert;
272
if(TEST_FFI_OK(botan_x509_cert_load_file, (&cert, Test::data_file("x509/ecc/CSCA.CSCA.csca-germany.1.crt").c_str())))
275
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_get_time_starts, (cert, nullptr, &date_len));
277
std::string date(date_len - 1, '0');
278
TEST_FFI_OK(botan_x509_cert_get_time_starts, (cert, &date[0], &date_len));
279
result.test_eq("cert valid from", date, "070719152718Z");
282
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_get_time_expires, (cert, nullptr, &date_len));
284
date.resize(date_len - 1);
285
TEST_FFI_OK(botan_x509_cert_get_time_expires, (cert, &date[0], &date_len));
286
result.test_eq("cert valid until", date, "280119151800Z");
288
size_t serial_len = 0;
289
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_get_serial_number, (cert, nullptr, &serial_len));
291
std::vector<uint8_t> serial(serial_len);
292
TEST_FFI_OK(botan_x509_cert_get_serial_number, (cert, serial.data(), &serial_len));
293
result.test_eq("cert serial length", serial.size(), 1);
294
result.test_int_eq(serial[0], 1, "cert serial");
296
size_t fingerprint_len = 0;
297
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_get_fingerprint,
298
(cert, "SHA-256", nullptr, &fingerprint_len));
300
std::vector<uint8_t> fingerprint(fingerprint_len);
301
TEST_FFI_OK(botan_x509_cert_get_fingerprint, (cert, "SHA-256", fingerprint.data(), &fingerprint_len));
302
result.test_eq("cert fingerprint", reinterpret_cast<const char*>(fingerprint.data()),
303
"3B:6C:99:1C:D6:5A:51:FC:EB:17:E3:AA:F6:3C:1A:DA:14:1F:82:41:30:6F:64:EE:FF:63:F3:1F:D6:07:14:9F");
305
size_t key_id_len = 0;
306
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_get_authority_key_id,
307
(cert, nullptr, &key_id_len));
309
std::vector<uint8_t> key_id(key_id_len);
310
TEST_FFI_OK(botan_x509_cert_get_authority_key_id, (cert, key_id.data(), &key_id_len));
311
result.test_eq("cert authority key id", Botan::hex_encode(key_id.data(), key_id.size(), true),
312
"0096452DE588F966C4CCDF161DD1F3F5341B71E7");
315
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_get_subject_key_id,
316
(cert, nullptr, &key_id_len));
318
key_id.resize(key_id_len);
319
TEST_FFI_OK(botan_x509_cert_get_subject_key_id, (cert, key_id.data(), &key_id_len));
320
result.test_eq("cert subject key id", Botan::hex_encode(key_id.data(), key_id.size(), true),
321
"0096452DE588F966C4CCDF161DD1F3F5341B71E7");
323
size_t pubkey_len = 0;
324
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_get_public_key_bits,
325
(cert, nullptr, &pubkey_len));
327
std::vector<uint8_t> pubkey(pubkey_len);
328
TEST_FFI_OK(botan_x509_cert_get_public_key_bits, (cert, pubkey.data(), &pubkey_len));
331
if(TEST_FFI_OK(botan_x509_cert_get_public_key, (cert, &pub)))
333
TEST_FFI_OK(botan_pubkey_destroy, (pub));
337
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_get_issuer_dn,
338
(cert, "Name", 0, nullptr, &dn_len));
340
std::vector<uint8_t> dn(dn_len);
341
TEST_FFI_OK(botan_x509_cert_get_issuer_dn, (cert, "Name", 0, dn.data(), &dn_len));
342
result.test_eq("issuer dn", reinterpret_cast<const char*>(dn.data()), "csca-germany");
345
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_get_subject_dn,
346
(cert, "Name", 0, nullptr, &dn_len));
349
TEST_FFI_OK(botan_x509_cert_get_subject_dn, (cert, "Name", 0, dn.data(), &dn_len));
350
result.test_eq("subject dn", reinterpret_cast<const char*>(dn.data()), "csca-germany");
352
size_t printable_len = 0;
353
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_to_string,
354
(cert, nullptr, &printable_len));
356
std::string printable(printable_len - 1, '0');
357
TEST_FFI_OK(botan_x509_cert_to_string, (cert, &printable[0], &printable_len));
359
TEST_FFI_RC(0, botan_x509_cert_allowed_usage, (cert, KEY_CERT_SIGN));
360
TEST_FFI_RC(0, botan_x509_cert_allowed_usage, (cert, CRL_SIGN));
361
TEST_FFI_RC(1, botan_x509_cert_allowed_usage, (cert, DIGITAL_SIGNATURE));
363
TEST_FFI_OK(botan_x509_cert_destroy, (cert));
367
std::vector<Test::Result> results;
368
results.push_back(ffi_test_errors());
369
results.push_back(ffi_test_base64());
370
results.push_back(ffi_test_mp(rng));
371
results.push_back(ffi_test_block_ciphers());
372
results.push_back(ffi_test_ciphers_cbc());
373
results.push_back(ffi_test_ciphers_aead_gcm());
374
results.push_back(ffi_test_ciphers_aead_eax());
375
results.push_back(ffi_test_stream_ciphers());
376
results.push_back(ffi_test_pkcs_hash_id());
378
#if defined(BOTAN_HAS_RFC3394_KEYWRAP)
379
results.push_back(ffi_test_keywrap());
382
#if defined(BOTAN_HAS_RSA)
383
results.push_back(ffi_test_rsa(rng));
386
#if defined(BOTAN_HAS_DSA)
387
results.push_back(ffi_test_dsa(rng));
390
#if defined(BOTAN_HAS_ECDSA)
391
results.push_back(ffi_test_ecdsa(rng));
394
#if defined(BOTAN_HAS_ECDH)
395
results.push_back(ffi_test_ecdh(rng));
398
#if defined(BOTAN_HAS_SM2)
399
results.push_back(ffi_test_sm2(rng));
400
results.push_back(ffi_test_sm2_enc(rng));
403
#if defined(BOTAN_HAS_MCELIECE)
404
results.push_back(ffi_test_mceliece(rng));
407
#if defined(BOTAN_HAS_ELGAMAL)
408
results.push_back(ffi_test_elgamal(rng));
411
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
412
results.push_back(ffi_test_dh(rng));
415
#if defined(BOTAN_HAS_ED25519)
416
results.push_back(ffi_test_ed25519(rng));
419
TEST_FFI_OK(botan_rng_destroy, (rng));
421
results.push_back(result);
426
Test::Result ffi_test_pkcs_hash_id()
428
Test::Result result("FFI PKCS hash id");
430
#if defined(BOTAN_HAS_HASH_ID)
431
std::vector<uint8_t> hash_id(64);
434
hash_id_len = 3; // too short
435
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
436
botan_pkcs_hash_id, ("SHA-256", hash_id.data(), &hash_id_len));
438
result.test_eq("Expected SHA-256 PKCS hash id len", hash_id_len, 19);
440
TEST_FFI_OK(botan_pkcs_hash_id, ("SHA-256", hash_id.data(), &hash_id_len));
442
result.test_eq("Expected SHA-256 PKCS hash id len", hash_id_len, 19);
444
hash_id.resize(hash_id_len);
445
result.test_eq("Expected SHA_256 PKCS hash id",
446
hash_id, "3031300D060960864801650304020105000420");
452
Test::Result ffi_test_ciphers_cbc()
454
Test::Result result("FFI CBC cipher");
456
botan_cipher_t cipher_encrypt, cipher_decrypt;
458
if(TEST_FFI_OK(botan_cipher_init, (&cipher_encrypt, "AES-128/CBC/PKCS7", BOTAN_CIPHER_INIT_FLAG_ENCRYPT)))
460
size_t min_keylen = 0;
461
size_t max_keylen = 0;
462
TEST_FFI_OK(botan_cipher_query_keylen, (cipher_encrypt, &min_keylen, &max_keylen));
463
result.test_int_eq(min_keylen, 16, "Min key length");
464
result.test_int_eq(max_keylen, 16, "Max key length");
466
// from https://github.com/geertj/bluepass/blob/master/tests/vectors/aes-cbc-pkcs7.txt
467
const std::vector<uint8_t> plaintext =
468
Botan::hex_decode("0397f4f6820b1f9386f14403be5ac16e50213bd473b4874b9bcbf5f318ee686b1d");
469
const std::vector<uint8_t> symkey = Botan::hex_decode("898be9cc5004ed0fa6e117c9a3099d31");
470
const std::vector<uint8_t> nonce = Botan::hex_decode("9dea7621945988f96491083849b068df");
471
const std::vector<uint8_t> exp_ciphertext =
472
Botan::hex_decode("e232cd6ef50047801ee681ec30f61d53cfd6b0bca02fd03c1b234baa10ea82ac9dab8b960926433a19ce6dea08677e34");
474
std::vector<uint8_t> ciphertext(16 + plaintext.size()); // TODO: no way to know this size from API
476
size_t output_written = 0;
477
size_t input_consumed = 0;
479
// Test that after clear or final the object can be reused
480
for(size_t r = 0; r != 2; ++r)
482
TEST_FFI_OK(botan_cipher_set_key, (cipher_encrypt, symkey.data(), symkey.size()));
483
TEST_FFI_OK(botan_cipher_start, (cipher_encrypt, nonce.data(), nonce.size()));
484
TEST_FFI_OK(botan_cipher_update, (cipher_encrypt, 0, ciphertext.data(), ciphertext.size(), &output_written,
485
plaintext.data(), plaintext.size(), &input_consumed));
486
TEST_FFI_OK(botan_cipher_clear, (cipher_encrypt));
488
TEST_FFI_OK(botan_cipher_set_key, (cipher_encrypt, symkey.data(), symkey.size()));
489
TEST_FFI_OK(botan_cipher_start, (cipher_encrypt, nonce.data(), nonce.size()));
490
TEST_FFI_OK(botan_cipher_update, (cipher_encrypt, BOTAN_CIPHER_UPDATE_FLAG_FINAL,
491
ciphertext.data(), ciphertext.size(), &output_written,
492
plaintext.data(), plaintext.size(), &input_consumed));
494
ciphertext.resize(output_written);
495
result.test_eq("AES/CBC ciphertext", ciphertext, exp_ciphertext);
497
if(TEST_FFI_OK(botan_cipher_init, (&cipher_decrypt, "AES-128/CBC", BOTAN_CIPHER_INIT_FLAG_DECRYPT)))
499
std::vector<uint8_t> decrypted(plaintext.size());
501
TEST_FFI_OK(botan_cipher_set_key, (cipher_decrypt, symkey.data(), symkey.size()));
502
TEST_FFI_OK(botan_cipher_start, (cipher_decrypt, nonce.data(), nonce.size()));
503
TEST_FFI_OK(botan_cipher_update, (cipher_decrypt, BOTAN_CIPHER_UPDATE_FLAG_FINAL,
504
decrypted.data(), decrypted.size(), &output_written,
505
ciphertext.data(), ciphertext.size(), &input_consumed));
507
result.test_eq("AES/CBC plaintext", decrypted, plaintext);
509
TEST_FFI_OK(botan_cipher_destroy, (cipher_decrypt));
513
TEST_FFI_OK(botan_cipher_destroy, (cipher_encrypt));
519
Test::Result ffi_test_ciphers_aead_gcm()
521
Test::Result result("FFI GCM");
523
#if defined(BOTAN_HAS_AEAD_GCM)
525
botan_cipher_t cipher_encrypt, cipher_decrypt;
527
if(TEST_FFI_OK(botan_cipher_init, (&cipher_encrypt, "AES-128/GCM", BOTAN_CIPHER_INIT_FLAG_ENCRYPT)))
529
size_t min_keylen = 0;
530
size_t max_keylen = 0;
531
size_t nonce_len = 0;
534
TEST_FFI_OK(botan_cipher_query_keylen, (cipher_encrypt, &min_keylen, &max_keylen));
535
result.test_int_eq(min_keylen, 16, "Min key length");
536
result.test_int_eq(max_keylen, 16, "Max key length");
538
TEST_FFI_OK(botan_cipher_get_default_nonce_length, (cipher_encrypt, &nonce_len));
539
result.test_int_eq(nonce_len, 12, "Expected default GCM nonce length");
541
TEST_FFI_OK(botan_cipher_get_tag_length, (cipher_encrypt, &tag_len));
542
result.test_int_eq(tag_len, 16, "Expected GCM tag length");
544
TEST_FFI_RC(1, botan_cipher_valid_nonce_length, (cipher_encrypt, 12));
545
// GCM accepts any nonce size...
546
TEST_FFI_RC(1, botan_cipher_valid_nonce_length, (cipher_encrypt, 0));
549
const std::vector<uint8_t> plaintext =
550
Botan::hex_decode("D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39");
552
const std::vector<uint8_t> symkey = Botan::hex_decode("FEFFE9928665731C6D6A8F9467308308");
553
const std::vector<uint8_t> nonce = Botan::hex_decode("CAFEBABEFACEDBADDECAF888");
554
const std::vector<uint8_t> exp_ciphertext = Botan::hex_decode(
555
"42831EC2217774244B7221B784D0D49CE3AA212F2C02A4E035C17E2329ACA12E21D514B25466931C7D8F6A5AAC84AA051BA30B396A0AAC973D58E0915BC94FBC3221A5DB94FAE95AE7121A47");
556
const std::vector<uint8_t> aad = Botan::hex_decode("FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2");
558
std::vector<uint8_t> ciphertext(tag_len + plaintext.size());
560
size_t output_written = 0;
561
size_t input_consumed = 0;
563
// Test that after clear or final the object can be reused
564
for(size_t r = 0; r != 2; ++r)
566
TEST_FFI_OK(botan_cipher_set_key, (cipher_encrypt, symkey.data(), symkey.size()));
567
TEST_FFI_OK(botan_cipher_start, (cipher_encrypt, nonce.data(), nonce.size()));
568
TEST_FFI_OK(botan_cipher_update, (cipher_encrypt, 0,
569
ciphertext.data(), ciphertext.size(), &output_written,
570
plaintext.data(), plaintext.size(), &input_consumed));
571
TEST_FFI_OK(botan_cipher_clear, (cipher_encrypt));
573
TEST_FFI_OK(botan_cipher_set_key, (cipher_encrypt, symkey.data(), symkey.size()));
574
TEST_FFI_OK(botan_cipher_set_associated_data, (cipher_encrypt, aad.data(), aad.size()));
575
TEST_FFI_OK(botan_cipher_start, (cipher_encrypt, nonce.data(), nonce.size()));
576
TEST_FFI_OK(botan_cipher_update, (cipher_encrypt, BOTAN_CIPHER_UPDATE_FLAG_FINAL,
577
ciphertext.data(), ciphertext.size(), &output_written,
578
plaintext.data(), plaintext.size(), &input_consumed));
580
ciphertext.resize(output_written);
581
result.test_eq("AES/GCM ciphertext", ciphertext, exp_ciphertext);
583
if(TEST_FFI_OK(botan_cipher_init, (&cipher_decrypt, "AES-128/GCM", BOTAN_CIPHER_INIT_FLAG_DECRYPT)))
585
std::vector<uint8_t> decrypted(plaintext.size());
587
TEST_FFI_OK(botan_cipher_set_key, (cipher_decrypt, symkey.data(), symkey.size()));
588
TEST_FFI_OK(botan_cipher_set_associated_data, (cipher_decrypt, aad.data(), aad.size()));
589
TEST_FFI_OK(botan_cipher_start, (cipher_decrypt, nonce.data(), nonce.size()));
590
TEST_FFI_OK(botan_cipher_update, (cipher_decrypt, BOTAN_CIPHER_UPDATE_FLAG_FINAL,
591
decrypted.data(), decrypted.size(), &output_written,
592
ciphertext.data(), ciphertext.size(), &input_consumed));
594
result.test_int_eq(input_consumed, ciphertext.size(), "All input consumed");
595
result.test_int_eq(output_written, decrypted.size(), "Expected output size produced");
596
result.test_eq("AES/GCM plaintext", decrypted, plaintext);
598
TEST_FFI_OK(botan_cipher_destroy, (cipher_decrypt));
602
TEST_FFI_OK(botan_cipher_destroy, (cipher_encrypt));
609
Test::Result ffi_test_ciphers_aead_eax()
611
Test::Result result("FFI EAX");
613
#if defined(BOTAN_HAS_AEAD_EAX)
615
botan_cipher_t cipher_encrypt, cipher_decrypt;
617
if(TEST_FFI_OK(botan_cipher_init, (&cipher_encrypt, "AES-128/EAX", BOTAN_CIPHER_INIT_FLAG_ENCRYPT)))
619
size_t min_keylen = 0;
620
size_t max_keylen = 0;
621
size_t nonce_len = 0;
624
TEST_FFI_OK(botan_cipher_query_keylen, (cipher_encrypt, &min_keylen, &max_keylen));
625
result.test_int_eq(min_keylen, 16, "Min key length");
626
result.test_int_eq(max_keylen, 16, "Max key length");
628
TEST_FFI_OK(botan_cipher_get_default_nonce_length, (cipher_encrypt, &nonce_len));
629
result.test_int_eq(nonce_len, 12, "Expected default EAX nonce length");
631
TEST_FFI_OK(botan_cipher_get_tag_length, (cipher_encrypt, &tag_len));
632
result.test_int_eq(tag_len, 16, "Expected EAX tag length");
634
TEST_FFI_RC(1, botan_cipher_valid_nonce_length, (cipher_encrypt, 12));
635
// EAX accepts any nonce size...
636
TEST_FFI_RC(1, botan_cipher_valid_nonce_length, (cipher_encrypt, 0));
638
const std::vector<uint8_t> plaintext =
639
Botan::hex_decode("0000000000000000000000000000000011111111111111111111111111111111");
640
const std::vector<uint8_t> symkey = Botan::hex_decode("000102030405060708090a0b0c0d0e0f");
641
const std::vector<uint8_t> nonce = Botan::hex_decode("3c8cc2970a008f75cc5beae2847258c2");
642
const std::vector<uint8_t> exp_ciphertext =
643
Botan::hex_decode("3c441f32ce07822364d7a2990e50bb13d7b02a26969e4a937e5e9073b0d9c968db90bdb3da3d00afd0fc6a83551da95e");
645
std::vector<uint8_t> ciphertext(tag_len + plaintext.size());
647
size_t output_written = 0;
648
size_t input_consumed = 0;
650
// Test that after clear or final the object can be reused
651
for(size_t r = 0; r != 2; ++r)
653
TEST_FFI_OK(botan_cipher_set_key, (cipher_encrypt, symkey.data(), symkey.size()));
654
TEST_FFI_OK(botan_cipher_start, (cipher_encrypt, nonce.data(), nonce.size()));
655
TEST_FFI_OK(botan_cipher_update, (cipher_encrypt, 0,
656
ciphertext.data(), ciphertext.size(), &output_written,
657
plaintext.data(), plaintext.size(), &input_consumed));
658
TEST_FFI_OK(botan_cipher_clear, (cipher_encrypt));
660
TEST_FFI_OK(botan_cipher_set_key, (cipher_encrypt, symkey.data(), symkey.size()));
661
TEST_FFI_OK(botan_cipher_start, (cipher_encrypt, nonce.data(), nonce.size()));
662
TEST_FFI_OK(botan_cipher_update, (cipher_encrypt, BOTAN_CIPHER_UPDATE_FLAG_FINAL,
663
ciphertext.data(), ciphertext.size(), &output_written,
664
plaintext.data(), plaintext.size(), &input_consumed));
666
ciphertext.resize(output_written);
667
result.test_eq("AES/EAX ciphertext", ciphertext, exp_ciphertext);
669
if(TEST_FFI_OK(botan_cipher_init, (&cipher_decrypt, "AES-128/EAX", BOTAN_CIPHER_INIT_FLAG_DECRYPT)))
671
std::vector<uint8_t> decrypted(plaintext.size());
673
TEST_FFI_OK(botan_cipher_set_key, (cipher_decrypt, symkey.data(), symkey.size()));
674
TEST_FFI_OK(botan_cipher_start, (cipher_decrypt, nonce.data(), nonce.size()));
675
TEST_FFI_OK(botan_cipher_update, (cipher_decrypt, BOTAN_CIPHER_UPDATE_FLAG_FINAL,
676
decrypted.data(), decrypted.size(), &output_written,
677
ciphertext.data(), ciphertext.size(), &input_consumed));
679
result.test_int_eq(input_consumed, ciphertext.size(), "All input consumed");
680
result.test_int_eq(output_written, decrypted.size(), "Expected output size produced");
681
result.test_eq("AES/EAX plaintext", decrypted, plaintext);
683
TEST_FFI_OK(botan_cipher_destroy, (cipher_decrypt));
687
TEST_FFI_OK(botan_cipher_destroy, (cipher_encrypt));
694
Test::Result ffi_test_stream_ciphers()
696
Test::Result result("FFI stream ciphers");
698
#if defined(BOTAN_HAS_CTR_BE)
700
const std::vector<uint8_t> key = Botan::hex_decode("2B7E151628AED2A6ABF7158809CF4F3C");
701
const std::vector<uint8_t> nonce = Botan::hex_decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFDFF");
702
const std::vector<uint8_t> pt = Botan::hex_decode(
703
"AE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710");
704
const std::vector<uint8_t> exp_ct = Botan::hex_decode(
705
"9806F66B7970FDFF8617187BB9FFFDFF5AE4DF3EDBD5D35E5B4F09020DB03EAB1E031DDA2FBE03D1792170A0F3009CEE");
709
std::vector<uint8_t> ct(pt.size());
711
if(TEST_FFI_OK(botan_cipher_init, (&ctr, "AES-128/CTR-BE", BOTAN_CIPHER_INIT_FLAG_ENCRYPT)))
713
size_t input_consumed = 0;
714
size_t output_written = 0;
716
TEST_FFI_OK(botan_cipher_set_key, (ctr, key.data(), key.size()));
717
TEST_FFI_OK(botan_cipher_start, (ctr, nonce.data(), nonce.size()));
719
// Test partial updates...
720
TEST_FFI_OK(botan_cipher_update, (ctr, 0,
721
ct.data(), ct.size(), &output_written,
722
pt.data(), 5, &input_consumed));
724
result.test_int_eq(output_written, 5, "Expected output written");
725
result.test_int_eq(input_consumed, 5, "Expected input consumed");
727
TEST_FFI_OK(botan_cipher_update, (ctr, 0,
728
&ct[5], ct.size() - 5, &output_written,
729
&pt[5], pt.size() - 5, &input_consumed));
731
result.test_int_eq(output_written, ct.size() - 5, "Expected output written");
732
result.test_int_eq(input_consumed, pt.size() - 5, "Expected input consumed");
733
result.test_eq("AES-128/CTR ciphertext", ct, exp_ct);
735
TEST_FFI_OK(botan_cipher_destroy, (ctr));
743
Test::Result ffi_test_block_ciphers()
745
Test::Result result("FFI block ciphers");
747
botan_block_cipher_t cipher;
749
if(TEST_FFI_OK(botan_block_cipher_init, (&cipher, "AES-128")))
751
const std::vector<uint8_t> zero16(16, 0);
752
std::vector<uint8_t> block(16, 0);
754
TEST_FFI_OK(botan_block_cipher_clear, (cipher));
756
TEST_FFI_RC(16, botan_block_cipher_block_size, (cipher));
758
TEST_FFI_OK(botan_block_cipher_set_key, (cipher, zero16.data(), zero16.size()));
760
TEST_FFI_OK(botan_block_cipher_encrypt_blocks, (cipher, block.data(), block.data(), 1));
761
result.test_eq("AES-128 encryption works", block, "66E94BD4EF8A2C3B884CFA59CA342B2E");
763
TEST_FFI_OK(botan_block_cipher_encrypt_blocks, (cipher, block.data(), block.data(), 1));
764
result.test_eq("AES-128 encryption works", block, "F795BD4A52E29ED713D313FA20E98DBC");
766
TEST_FFI_OK(botan_block_cipher_decrypt_blocks, (cipher, block.data(), block.data(), 1));
767
result.test_eq("AES-128 decryption works", block, "66E94BD4EF8A2C3B884CFA59CA342B2E");
769
TEST_FFI_OK(botan_block_cipher_decrypt_blocks, (cipher, block.data(), block.data(), 1));
770
result.test_eq("AES-128 decryption works", block, "00000000000000000000000000000000");
772
TEST_FFI_OK(botan_block_cipher_clear, (cipher));
773
botan_block_cipher_destroy(cipher);
779
Test::Result ffi_test_errors()
781
// Test some error handling situations
782
Test::Result result("FFI error handling");
784
// delete of null is ok/ignored
785
TEST_FFI_RC(0, botan_hash_destroy, (nullptr));
787
// Confirm that botan_x_destroy checks the argument type
790
TEST_FFI_RC(BOTAN_FFI_ERROR_INVALID_OBJECT, botan_hash_destroy, (reinterpret_cast<botan_hash_t>(mp)));
791
TEST_FFI_RC(0, botan_mp_destroy, (mp));
796
Test::Result ffi_test_base64()
798
Test::Result result("FFI base64");
800
const uint8_t bin[9] = { 0x16, 0x8a, 0x1f, 0x06, 0xe9, 0xe7, 0xcb, 0xdd, 0x34 };
801
char out_buf[1024] = { 0 };
803
size_t out_len = sizeof(out_buf);
804
TEST_FFI_OK(botan_base64_encode, (bin, sizeof(bin), out_buf, &out_len));
806
result.test_eq("encoded string", out_buf, "FoofBunny900");
809
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
811
(bin, sizeof(bin), out_buf, &out_len));
813
const char* base64 = "U3VjaCBiYXNlNjQgd293IQ==";
814
uint8_t out_bin[1024] = { 0 };
815
out_len = sizeof(out_bin);
816
TEST_FFI_OK(botan_base64_decode, (base64, strlen(base64), out_bin, &out_len));
818
result.test_eq("decoded string",
819
std::string(reinterpret_cast<const char*>(out_bin), out_len),
825
Test::Result ffi_test_mp(botan_rng_t rng)
827
Test::Result result("FFI MP");
831
TEST_FFI_RC(0, botan_mp_is_odd, (x));
832
TEST_FFI_RC(1, botan_mp_is_even, (x));
833
TEST_FFI_RC(0, botan_mp_is_negative, (x));
834
TEST_FFI_RC(1, botan_mp_is_positive, (x));
835
TEST_FFI_RC(1, botan_mp_is_zero, (x));
840
TEST_FFI_OK(botan_mp_num_bytes, (x, &bn_bytes));
841
result.test_eq("Expected size for MP 0", bn_bytes, 0);
843
botan_mp_set_from_int(x, 5);
844
TEST_FFI_OK(botan_mp_num_bytes, (x, &bn_bytes));
845
result.test_eq("Expected size for MP 5", bn_bytes, 1);
847
botan_mp_set_from_int(x, 259);
848
TEST_FFI_OK(botan_mp_num_bytes, (x, &bn_bytes));
849
result.test_eq("Expected size for MP 259", bn_bytes, 2);
851
TEST_FFI_RC(1, botan_mp_is_odd, (x));
852
TEST_FFI_RC(0, botan_mp_is_even, (x));
853
TEST_FFI_RC(0, botan_mp_is_negative, (x));
854
TEST_FFI_RC(1, botan_mp_is_positive, (x));
855
TEST_FFI_RC(0, botan_mp_is_zero, (x));
860
botan_mp_init(&zero);
862
TEST_FFI_OK(botan_mp_cmp, (&cmp, x, zero));
863
result.confirm("bigint_mp_cmp(+, 0)", cmp == 1);
865
TEST_FFI_OK(botan_mp_cmp, (&cmp, zero, x));
866
result.confirm("bigint_mp_cmp(0, +)", cmp == -1);
868
TEST_FFI_RC(0, botan_mp_is_negative, (x));
869
TEST_FFI_RC(1, botan_mp_is_positive, (x));
870
TEST_FFI_OK(botan_mp_flip_sign, (x));
871
TEST_FFI_RC(1, botan_mp_is_negative, (x));
872
TEST_FFI_RC(0, botan_mp_is_positive, (x));
874
// test no negative zero
875
TEST_FFI_RC(0, botan_mp_is_negative, (zero));
876
TEST_FFI_RC(1, botan_mp_is_positive, (zero));
877
TEST_FFI_OK(botan_mp_flip_sign, (zero));
878
TEST_FFI_RC(0, botan_mp_is_negative, (zero));
879
TEST_FFI_RC(1, botan_mp_is_positive, (zero));
881
TEST_FFI_OK(botan_mp_cmp, (&cmp, x, zero));
882
result.confirm("bigint_mp_cmp(-, 0)", cmp == -1);
884
TEST_FFI_OK(botan_mp_cmp, (&cmp, zero, x));
885
result.confirm("bigint_mp_cmp(0, -)", cmp == 1);
887
TEST_FFI_OK(botan_mp_cmp, (&cmp, zero, zero));
888
result.confirm("bigint_mp_cmp(0, 0)", cmp == 0);
890
TEST_FFI_OK(botan_mp_cmp, (&cmp, x, x));
891
result.confirm("bigint_mp_cmp(x, x)", cmp == 0);
893
TEST_FFI_OK(botan_mp_flip_sign, (x));
895
botan_mp_destroy(zero);
899
TEST_FFI_OK(botan_mp_num_bits, (x, &x_bits));
900
result.test_eq("botan_mp_num_bits", x_bits, 9);
902
char str_buf[1024] = { 0 };
905
TEST_FFI_OK(botan_mp_to_hex, (x, str_buf));
906
result.test_eq("botan_mp_to_hex", std::string(str_buf), "0103");
909
TEST_FFI_OK(botan_mp_to_uint32, (x, &x_32));
910
result.test_eq("botan_mp_to_uint32", size_t(x_32), size_t(0x103));
912
TEST_FFI_RC(1, botan_mp_get_bit, (x, 1));
913
TEST_FFI_RC(0, botan_mp_get_bit, (x, 87));
914
TEST_FFI_OK(botan_mp_set_bit, (x, 87));
915
TEST_FFI_RC(1, botan_mp_get_bit, (x, 87));
916
TEST_FFI_OK(botan_mp_to_hex, (x, str_buf));
917
result.test_eq("botan_mp_set_bit", std::string(str_buf), "8000000000000000000103");
919
TEST_FFI_OK(botan_mp_clear_bit, (x, 87));
920
TEST_FFI_OK(botan_mp_to_hex, (x, str_buf));
921
result.test_eq("botan_mp_set_bit", std::string(str_buf), "0103");
924
TEST_FFI_OK(botan_mp_init, (&y));
925
TEST_FFI_OK(botan_mp_set_from_int, (y, 0x1234567));
930
TEST_FFI_OK(botan_mp_add, (r, x, y));
931
str_len = sizeof(str_buf);
932
TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
933
result.test_eq("botan_mp_add", std::string(str_buf), "19089002");
935
TEST_FFI_OK(botan_mp_mul, (r, x, y));
936
str_len = sizeof(str_buf);
937
TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
938
result.test_eq("botan_mp_mul", std::string(str_buf), "4943984437");
939
TEST_FFI_RC(0, botan_mp_is_negative, (r));
943
TEST_FFI_OK(botan_mp_div, (q, r, y, x));
945
str_len = sizeof(str_buf);
946
TEST_FFI_OK(botan_mp_to_str, (q, 10, str_buf, &str_len));
947
result.test_eq("botan_mp_div_q", std::string(str_buf), "073701");
949
str_len = sizeof(str_buf);
950
TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
951
result.test_eq("botan_mp_div_r", std::string(str_buf), "184");
953
TEST_FFI_OK(botan_mp_set_from_str, (y, "4943984437"));
954
TEST_FFI_OK(botan_mp_sub, (r, x, y));
955
str_len = sizeof(str_buf);
956
TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
957
result.test_eq("botan_mp_sub", std::string(str_buf), "4943984178");
958
TEST_FFI_RC(1, botan_mp_is_negative, (r));
960
TEST_FFI_OK(botan_mp_lshift, (r, x, 39));
961
str_len = sizeof(str_buf);
962
TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
963
result.test_eq("botan_mp_lshift", std::string(str_buf), "142386755796992");
965
TEST_FFI_OK(botan_mp_rshift, (r, r, 3));
966
str_len = sizeof(str_buf);
967
TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
968
result.test_eq("botan_mp_rshift", std::string(str_buf), "17798344474624");
970
TEST_FFI_OK(botan_mp_gcd, (r, x, y));
971
str_len = sizeof(str_buf);
972
TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
973
result.test_eq("botan_mp_gcd", std::string(str_buf), "259");
977
const uint8_t M127[] = { 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
978
TEST_FFI_OK(botan_mp_from_bin, (p, M127, sizeof(M127)));
979
TEST_FFI_RC(1, botan_mp_is_prime, (p, rng, 64));
982
TEST_FFI_OK(botan_mp_num_bits, (p, &p_bits));
983
result.test_eq("botan_mp_num_bits", p_bits, 127);
985
TEST_FFI_OK(botan_mp_mod_inverse, (r, x, p));
986
str_len = sizeof(str_buf);
987
TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
988
result.test_eq("botan_mp_mod_inverse", std::string(str_buf), "40728777507911553541948312086427855425");
990
TEST_FFI_OK(botan_mp_powmod, (r, x, r, p));
991
str_len = sizeof(str_buf);
992
TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
993
result.test_eq("botan_mp_powmod", std::string(str_buf), "40550417419160441638948180641668117560");
995
TEST_FFI_OK(botan_mp_num_bytes, (r, &bn_bytes));
996
result.test_eq("botan_mp_num_bytes", bn_bytes, 16);
998
std::vector<uint8_t> bn_buf;
999
bn_buf.resize(bn_bytes);
1000
botan_mp_to_bin(r, bn_buf.data());
1001
result.test_eq("botan_mp_to_bin", bn_buf, "1E81B9EFE0BE1902F6D03F9F5E5FB438");
1003
TEST_FFI_OK(botan_mp_set_from_mp, (y, r));
1004
TEST_FFI_OK(botan_mp_mod_mul, (r, x, y, p));
1005
str_len = sizeof(str_buf);
1006
TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
1007
result.test_eq("botan_mp_mod_mul", std::string(str_buf), "123945920473931248854653259523111998693");
1010
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_mp_to_str, (r, 10, str_buf, &str_len));
1013
botan_mp_rand_bits(x, rng, 512);
1014
TEST_FFI_OK(botan_mp_num_bytes, (x, &x_bytes));
1015
result.test_lte("botan_mp_num_bytes", x_bytes, 512 / 8);
1017
TEST_FFI_OK(botan_mp_set_from_radix_str, (x, "909A", 16));
1018
TEST_FFI_OK(botan_mp_to_uint32, (x, &x_32));
1019
result.test_eq("botan_mp_set_from_radix_str(16)", x_32, static_cast<size_t>(0x909A));
1021
TEST_FFI_OK(botan_mp_set_from_radix_str, (x, "9098135", 10));
1022
TEST_FFI_OK(botan_mp_to_uint32, (x, &x_32));
1023
result.test_eq("botan_mp_set_from_radix_str(10)", x_32, static_cast<size_t>(9098135));
1025
botan_mp_destroy(p);
1026
botan_mp_destroy(x);
1027
botan_mp_destroy(y);
1028
botan_mp_destroy(r);
1029
botan_mp_destroy(q);
1034
void ffi_test_pubkey_export(Test::Result& result, botan_pubkey_t pub, botan_privkey_t priv, botan_rng_t rng)
1036
const size_t pbkdf_iter = 1000;
1038
// export public key
1039
size_t pubkey_len = 0;
1040
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_pubkey_export, (pub, nullptr, &pubkey_len,
1041
BOTAN_PRIVKEY_EXPORT_FLAG_DER));
1043
std::vector<uint8_t> pubkey(pubkey_len);
1044
TEST_FFI_OK(botan_pubkey_export, (pub, pubkey.data(), &pubkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_DER));
1047
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_pubkey_export,
1048
(pub, nullptr, &pubkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_PEM));
1050
pubkey.resize(pubkey_len);
1051
TEST_FFI_OK(botan_pubkey_export, (pub, pubkey.data(), &pubkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_PEM));
1053
// reimport exported public key
1054
botan_pubkey_t pub_copy;
1055
TEST_FFI_OK(botan_pubkey_load, (&pub_copy, pubkey.data(), pubkey_len));
1056
TEST_FFI_OK(botan_pubkey_check_key, (pub_copy, rng, 0));
1057
TEST_FFI_OK(botan_pubkey_destroy, (pub_copy));
1059
// export private key
1060
std::vector<uint8_t> privkey;
1061
size_t privkey_len = 0;
1063
// call with nullptr to query the length
1064
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_privkey_export,
1065
(priv, nullptr, &privkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_DER));
1067
privkey.resize(privkey_len);
1068
privkey_len = privkey.size(); // set buffer size
1070
TEST_FFI_OK(botan_privkey_export, (priv, privkey.data(), &privkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_DER));
1072
privkey.resize(privkey_len);
1074
result.test_gte("Reasonable size", privkey.size(), 32);
1076
// reimport exported private key
1077
botan_privkey_t copy;
1078
TEST_FFI_OK(botan_privkey_load, (©, rng, privkey.data(), privkey.size(), nullptr));
1079
botan_privkey_destroy(copy);
1081
// Now again for PEM
1084
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_privkey_export,
1085
(priv, nullptr, &privkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_PEM));
1087
privkey.resize(privkey_len);
1088
TEST_FFI_OK(botan_privkey_export, (priv, privkey.data(), &privkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_PEM));
1090
TEST_FFI_OK(botan_privkey_load, (©, rng, privkey.data(), privkey.size(), nullptr));
1091
botan_privkey_destroy(copy);
1093
// export private key encrypted
1095
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_privkey_export_encrypted_pbkdf_iter, (priv, nullptr,
1096
&privkey_len, rng, "password", pbkdf_iter, "", "", BOTAN_PRIVKEY_EXPORT_FLAG_DER));
1098
privkey.resize(privkey_len);
1099
privkey_len = privkey.size();
1101
TEST_FFI_OK(botan_privkey_export_encrypted_pbkdf_iter, (priv, privkey.data(), &privkey_len, rng, "password", pbkdf_iter,
1102
"", "", BOTAN_PRIVKEY_EXPORT_FLAG_DER));
1104
// reimport encrypted private key
1105
botan_privkey_load(©, rng, privkey.data(), privkey.size(), "password");
1106
botan_privkey_destroy(copy);
1109
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_privkey_export_encrypted_pbkdf_iter, (priv, nullptr,
1110
&privkey_len, rng, "password", pbkdf_iter, "", "", BOTAN_PRIVKEY_EXPORT_FLAG_PEM));
1112
privkey.resize(privkey_len);
1113
TEST_FFI_OK(botan_privkey_export_encrypted_pbkdf_iter, (priv, privkey.data(), &privkey_len, rng, "password", pbkdf_iter,
1114
"", "", BOTAN_PRIVKEY_EXPORT_FLAG_PEM));
1116
privkey.resize(privkey_len * 2);
1117
privkey_len = privkey.size();
1118
const uint32_t pbkdf_msec = 100;
1119
size_t pbkdf_iters_out = 0;
1121
TEST_FFI_OK(botan_privkey_export_encrypted_pbkdf_msec,
1122
(priv, privkey.data(), &privkey_len, rng, "password",
1123
pbkdf_msec, &pbkdf_iters_out, "AES-256/GCM", "SHA-512", 0));
1124
// PBKDF2 currently always rounds to multiple of 10,000
1125
result.test_gte("Reasonable KDF iters", pbkdf_iters_out, 1000);
1126
privkey.resize(privkey_len);
1128
TEST_FFI_OK(botan_privkey_load, (©, rng, privkey.data(), privkey.size(), "password"));
1129
botan_privkey_destroy(copy);
1131
// calculate fingerprint
1132
size_t strength = 0;
1133
TEST_FFI_OK(botan_pubkey_estimated_strength, (pub, &strength));
1134
result.test_gte("estimated strength", strength, 1);
1136
size_t fingerprint_len = 0;
1137
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_pubkey_fingerprint,
1138
(pub, "SHA-512", nullptr, &fingerprint_len));
1140
std::vector<uint8_t> fingerprint(fingerprint_len);
1141
TEST_FFI_OK(botan_pubkey_fingerprint, (pub, "SHA-512", fingerprint.data(), &fingerprint_len));
1144
Test::Result ffi_test_keywrap()
1146
Test::Result result("FFI keywrap");
1148
const uint8_t key[16] = { 0 };
1149
const uint8_t kek[16] = { 0xFF, 0 };
1151
const uint8_t expected_wrapped_key[16+8] = {
1152
0x04, 0x13, 0x37, 0x39, 0x82, 0xCF, 0xFA, 0x31, 0x81, 0xCA, 0x4F, 0x59,
1153
0x74, 0x4D, 0xED, 0x29, 0x1F, 0x3F, 0xE5, 0x24, 0x00, 0x1B, 0x93, 0x20
1156
uint8_t wrapped[16 + 8] = { 0 };
1157
size_t wrapped_keylen = sizeof(wrapped);
1158
TEST_FFI_OK(botan_key_wrap3394, (key, sizeof(key),
1160
wrapped, &wrapped_keylen));
1162
result.test_eq("Expected wrapped keylen size", wrapped_keylen, 16 + 8);
1164
result.test_eq(nullptr, "Wrapped key", wrapped, wrapped_keylen,
1165
expected_wrapped_key, sizeof(expected_wrapped_key));
1167
uint8_t dec_key[16] = { 0 };
1168
size_t dec_keylen = sizeof(dec_key);
1169
TEST_FFI_OK(botan_key_unwrap3394, (wrapped, sizeof(wrapped),
1171
dec_key, &dec_keylen));
1173
result.test_eq(nullptr, "Unwrapped key", dec_key, dec_keylen, key, sizeof(key));
1177
Test::Result ffi_test_rsa(botan_rng_t rng)
1179
Test::Result result("FFI RSA");
1181
botan_privkey_t priv;
1183
if(TEST_FFI_OK(botan_privkey_create_rsa, (&priv, rng, 1024)))
1185
TEST_FFI_OK(botan_privkey_check_key, (priv, rng, 0));
1188
TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
1189
TEST_FFI_OK(botan_pubkey_check_key, (pub, rng, 0));
1191
ffi_test_pubkey_export(result, pub, priv, rng);
1193
botan_mp_t p, q, d, n, e;
1200
TEST_FFI_OK(botan_privkey_rsa_get_p, (p, priv));
1201
TEST_FFI_OK(botan_privkey_rsa_get_q, (q, priv));
1202
TEST_FFI_OK(botan_privkey_rsa_get_d, (d, priv));
1203
TEST_FFI_OK(botan_privkey_rsa_get_e, (e, priv));
1204
TEST_FFI_OK(botan_privkey_rsa_get_n, (n, priv));
1206
// Confirm same (e,n) values in public key
1208
botan_mp_t pub_e, pub_n;
1209
botan_mp_init(&pub_e);
1210
botan_mp_init(&pub_n);
1211
TEST_FFI_OK(botan_pubkey_rsa_get_e, (pub_e, pub));
1212
TEST_FFI_OK(botan_pubkey_rsa_get_n, (pub_n, pub));
1214
TEST_FFI_RC(1, botan_mp_equal, (pub_e, e));
1215
TEST_FFI_RC(1, botan_mp_equal, (pub_n, n));
1216
botan_mp_destroy(pub_e);
1217
botan_mp_destroy(pub_n);
1220
TEST_FFI_RC(1, botan_mp_is_prime, (p, rng, 64));
1221
TEST_FFI_RC(1, botan_mp_is_prime, (q, rng, 64));
1224
TEST_FFI_RC(0, botan_mp_equal, (p, q));
1229
TEST_FFI_OK(botan_mp_mul, (x, p, q));
1231
TEST_FFI_RC(1, botan_mp_equal, (x, n));
1232
botan_mp_destroy(x);
1234
botan_privkey_t loaded_privkey;
1235
// First try loading a bogus key and verify check_key fails
1236
TEST_FFI_OK(botan_privkey_load_rsa, (&loaded_privkey, n, d, q));
1237
TEST_FFI_RC(-1, botan_privkey_check_key, (loaded_privkey, rng, 0));
1238
botan_privkey_destroy(loaded_privkey);
1240
TEST_FFI_OK(botan_privkey_load_rsa, (&loaded_privkey, p, q, e));
1241
TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey, rng, 0));
1243
botan_pubkey_t loaded_pubkey;
1244
TEST_FFI_OK(botan_pubkey_load_rsa, (&loaded_pubkey, n, e));
1245
TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey, rng, 0));
1247
botan_mp_destroy(p);
1248
botan_mp_destroy(q);
1249
botan_mp_destroy(d);
1250
botan_mp_destroy(e);
1251
botan_mp_destroy(n);
1253
char namebuf[32] = { 0 };
1254
size_t name_len = sizeof(namebuf);
1255
if(TEST_FFI_OK(botan_pubkey_algo_name, (loaded_pubkey, namebuf, &name_len)))
1257
result.test_eq("algo name", std::string(namebuf), "RSA");
1260
botan_pk_op_encrypt_t encrypt;
1262
if(TEST_FFI_OK(botan_pk_op_encrypt_create, (&encrypt, loaded_pubkey, "OAEP(SHA-256)", 0)))
1264
std::vector<uint8_t> plaintext(32);
1265
TEST_FFI_OK(botan_rng_get, (rng, plaintext.data(), plaintext.size()));
1267
std::vector<uint8_t> ciphertext(256); // TODO: no way to know this size from API
1268
size_t ctext_len = ciphertext.size();
1270
if(TEST_FFI_OK(botan_pk_op_encrypt, (encrypt, rng,
1271
ciphertext.data(), &ctext_len,
1272
plaintext.data(), plaintext.size())))
1274
ciphertext.resize(ctext_len);
1276
botan_pk_op_decrypt_t decrypt;
1277
if(TEST_FFI_OK(botan_pk_op_decrypt_create, (&decrypt, priv, "OAEP(SHA-256)", 0)))
1279
std::vector<uint8_t> decrypted(256); // TODO as with above
1280
size_t decrypted_len = decrypted.size();
1281
TEST_FFI_OK(botan_pk_op_decrypt, (decrypt, decrypted.data(), &decrypted_len,
1282
ciphertext.data(), ciphertext.size()));
1283
decrypted.resize(decrypted_len);
1285
result.test_eq("RSA plaintext", decrypted, plaintext);
1288
TEST_FFI_OK(botan_pk_op_decrypt_destroy, (decrypt));
1291
TEST_FFI_OK(botan_pk_op_encrypt_destroy, (encrypt));
1294
TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey));
1295
TEST_FFI_OK(botan_pubkey_destroy, (pub));
1296
TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey));
1297
TEST_FFI_OK(botan_privkey_destroy, (priv));
1303
Test::Result ffi_test_dsa(botan_rng_t rng)
1305
Test::Result result("FFI DSA");
1307
botan_privkey_t priv;
1309
if(TEST_FFI_OK(botan_privkey_create, (&priv, "DSA", "dsa/jce/1024", rng)))
1311
TEST_FFI_OK(botan_privkey_check_key, (priv, rng, 0));
1314
TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
1315
TEST_FFI_OK(botan_pubkey_check_key, (pub, rng, 0));
1317
ffi_test_pubkey_export(result, pub, priv, rng);
1319
botan_mp_t p, q, g, x, y;
1326
TEST_FFI_OK(botan_privkey_dsa_get_x, (x, priv));
1327
TEST_FFI_OK(botan_pubkey_dsa_get_g, (g, pub));
1328
TEST_FFI_OK(botan_pubkey_dsa_get_p, (p, pub));
1329
TEST_FFI_OK(botan_pubkey_dsa_get_q, (q, pub));
1330
TEST_FFI_OK(botan_pubkey_dsa_get_y, (y, pub));
1333
botan_mp_init(&cmp);
1334
TEST_FFI_OK(botan_privkey_get_field, (cmp, priv, "x"));
1335
TEST_FFI_RC(1, botan_mp_equal, (cmp, x));
1336
TEST_FFI_OK(botan_privkey_get_field, (cmp, priv, "y"));
1337
TEST_FFI_RC(1, botan_mp_equal, (cmp, y));
1338
TEST_FFI_OK(botan_privkey_get_field, (cmp, priv, "p"));
1339
TEST_FFI_RC(1, botan_mp_equal, (cmp, p));
1340
botan_mp_destroy(cmp);
1342
botan_privkey_t loaded_privkey;
1343
TEST_FFI_OK(botan_privkey_load_dsa, (&loaded_privkey, p, q, g, x));
1344
TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey, rng, 0));
1346
botan_pubkey_t loaded_pubkey;
1347
TEST_FFI_OK(botan_pubkey_load_dsa, (&loaded_pubkey, p, q, g, y));
1348
TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey, rng, 0));
1350
botan_mp_destroy(p);
1351
botan_mp_destroy(q);
1352
botan_mp_destroy(g);
1353
botan_mp_destroy(y);
1354
botan_mp_destroy(x);
1356
botan_pk_op_sign_t signer;
1358
std::vector<uint8_t> message(6, 6);
1359
std::vector<uint8_t> signature(20 * 2);
1361
if(TEST_FFI_OK(botan_pk_op_sign_create, (&signer, loaded_privkey, "EMSA1(SHA-256)", 0)))
1363
// TODO: break input into multiple calls to update
1364
TEST_FFI_OK(botan_pk_op_sign_update, (signer, message.data(), message.size()));
1366
signature.resize(20 * 2); // TODO: no way to derive this from API
1367
size_t sig_len = signature.size();
1368
TEST_FFI_OK(botan_pk_op_sign_finish, (signer, rng, signature.data(), &sig_len));
1369
signature.resize(sig_len);
1371
TEST_FFI_OK(botan_pk_op_sign_destroy, (signer));
1374
botan_pk_op_verify_t verifier;
1376
if(TEST_FFI_OK(botan_pk_op_verify_create, (&verifier, pub, "EMSA1(SHA-256)", 0)))
1378
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1379
TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1381
// TODO: randomize this
1383
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1384
TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1387
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1388
TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1391
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1392
TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1395
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1396
TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1398
TEST_FFI_OK(botan_pk_op_verify_destroy, (verifier));
1401
TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey));
1402
TEST_FFI_OK(botan_pubkey_destroy, (pub));
1403
TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey));
1404
TEST_FFI_OK(botan_privkey_destroy, (priv));
1409
Test::Result ffi_test_ecdsa(botan_rng_t rng)
1411
Test::Result result("FFI ECDSA");
1412
static const char* kCurve = "secp384r1";
1413
botan_privkey_t priv;
1415
botan_privkey_t loaded_privkey;
1416
botan_pubkey_t loaded_pubkey;
1418
REQUIRE_FFI_OK(botan_privkey_create_ecdsa, (&priv, rng, kCurve));
1419
TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
1420
ffi_test_pubkey_export(result, pub, priv, rng);
1422
// Check key load functions
1423
botan_mp_t private_scalar, public_x, public_y;
1424
botan_mp_init(&private_scalar);
1425
botan_mp_init(&public_x);
1426
botan_mp_init(&public_y);
1428
TEST_FFI_OK(botan_privkey_get_field, (private_scalar, priv, "x"));
1429
TEST_FFI_OK(botan_pubkey_get_field, (public_x, pub, "public_x"));
1430
TEST_FFI_OK(botan_pubkey_get_field, (public_y, pub, "public_y"));
1431
TEST_FFI_OK(botan_privkey_load_ecdsa, (&loaded_privkey, private_scalar, kCurve));
1432
TEST_FFI_OK(botan_pubkey_load_ecdsa, (&loaded_pubkey, public_x, public_y, kCurve));
1433
TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey, rng, 0));
1434
TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey, rng, 0));
1436
char namebuf[32] = { 0 };
1437
size_t name_len = sizeof(namebuf);
1439
TEST_FFI_OK(botan_pubkey_algo_name, (pub, &namebuf[0], &name_len));
1440
result.test_eq(namebuf, namebuf, "ECDSA");
1442
std::vector<uint8_t> message(1280), signature;
1443
TEST_FFI_OK(botan_rng_get, (rng, message.data(), message.size()));
1444
botan_pk_op_sign_t signer;
1445
if(TEST_FFI_OK(botan_pk_op_sign_create, (&signer, loaded_privkey, "EMSA1(SHA-384)", 0)))
1447
// TODO: break input into multiple calls to update
1448
TEST_FFI_OK(botan_pk_op_sign_update, (signer, message.data(), message.size()));
1450
signature.resize(96); // TODO: no way to derive this from API
1451
size_t sig_len = signature.size();
1452
TEST_FFI_OK(botan_pk_op_sign_finish, (signer, rng, signature.data(), &sig_len));
1453
signature.resize(sig_len);
1455
TEST_FFI_OK(botan_pk_op_sign_destroy, (signer));
1458
botan_pk_op_verify_t verifier;
1460
if(TEST_FFI_OK(botan_pk_op_verify_create, (&verifier, pub, "EMSA1(SHA-384)", 0)))
1462
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1463
TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1465
// TODO: randomize this
1467
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1468
TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1471
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1472
TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1475
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1476
TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1479
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1480
TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1482
TEST_FFI_OK(botan_pk_op_verify_destroy, (verifier));
1485
TEST_FFI_OK(botan_mp_destroy, (private_scalar));
1486
TEST_FFI_OK(botan_mp_destroy, (public_x));
1487
TEST_FFI_OK(botan_mp_destroy, (public_y));
1488
TEST_FFI_OK(botan_pubkey_destroy, (pub));
1489
TEST_FFI_OK(botan_privkey_destroy, (priv));
1490
TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey));
1491
TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey));
1496
Test::Result ffi_test_sm2(botan_rng_t rng)
1498
Test::Result result("FFI SM2 Sig");
1499
static const char* kCurve = "sm2p256v1";
1500
const std::string sm2_ident = "SM2 Ident Field";
1501
botan_privkey_t priv;
1503
botan_privkey_t loaded_privkey;
1504
botan_pubkey_t loaded_pubkey;
1506
REQUIRE_FFI_OK(botan_privkey_create, (&priv, "SM2_Sig", kCurve, rng));
1507
TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
1508
ffi_test_pubkey_export(result, pub, priv, rng);
1511
size_t sizeof_za = sizeof(za);
1512
TEST_FFI_OK(botan_pubkey_sm2_compute_za, (za, &sizeof_za, "Ident", "SM3", pub));
1514
// Check key load functions
1515
botan_mp_t private_scalar, public_x, public_y;
1516
botan_mp_init(&private_scalar);
1517
botan_mp_init(&public_x);
1518
botan_mp_init(&public_y);
1520
TEST_FFI_OK(botan_privkey_get_field, (private_scalar, priv, "x"));
1521
TEST_FFI_OK(botan_pubkey_get_field, (public_x, pub, "public_x"));
1522
TEST_FFI_OK(botan_pubkey_get_field, (public_y, pub, "public_y"));
1523
TEST_FFI_OK(botan_privkey_load_sm2, (&loaded_privkey, private_scalar, kCurve));
1524
TEST_FFI_OK(botan_pubkey_load_sm2, (&loaded_pubkey, public_x, public_y, kCurve));
1525
TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey, rng, 0));
1526
TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey, rng, 0));
1528
char namebuf[32] = { 0 };
1529
size_t name_len = sizeof(namebuf);
1531
TEST_FFI_OK(botan_pubkey_algo_name, (pub, &namebuf[0], &name_len));
1532
result.test_eq(namebuf, namebuf, "SM2_Sig");
1534
std::vector<uint8_t> message(1280), signature;
1535
TEST_FFI_OK(botan_rng_get, (rng, message.data(), message.size()));
1536
botan_pk_op_sign_t signer;
1537
if(TEST_FFI_OK(botan_pk_op_sign_create, (&signer, loaded_privkey, sm2_ident.c_str(), 0)))
1539
// TODO: break input into multiple calls to update
1540
TEST_FFI_OK(botan_pk_op_sign_update, (signer, message.data(), message.size()));
1542
signature.resize(96); // TODO: no way to derive this from API
1543
size_t sig_len = signature.size();
1544
TEST_FFI_OK(botan_pk_op_sign_finish, (signer, rng, signature.data(), &sig_len));
1545
signature.resize(sig_len);
1547
TEST_FFI_OK(botan_pk_op_sign_destroy, (signer));
1550
botan_pk_op_verify_t verifier = nullptr;
1552
if(signature.size() > 0 && TEST_FFI_OK(botan_pk_op_verify_create, (&verifier, pub, sm2_ident.c_str(), 0)))
1554
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1555
TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1557
// TODO: randomize this
1559
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1560
TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1563
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1564
TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1567
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1568
TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1571
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1572
TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1574
TEST_FFI_OK(botan_pk_op_verify_destroy, (verifier));
1577
TEST_FFI_OK(botan_mp_destroy, (private_scalar));
1578
TEST_FFI_OK(botan_mp_destroy, (public_x));
1579
TEST_FFI_OK(botan_mp_destroy, (public_y));
1580
TEST_FFI_OK(botan_pubkey_destroy, (pub));
1581
TEST_FFI_OK(botan_privkey_destroy, (priv));
1582
TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey));
1583
TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey));
1588
Test::Result ffi_test_sm2_enc(botan_rng_t rng)
1590
Test::Result result("FFI SM2 Enc");
1591
static const char* kCurve = "sm2p256v1";
1592
botan_privkey_t priv;
1594
botan_privkey_t loaded_privkey;
1595
botan_pubkey_t loaded_pubkey;
1597
REQUIRE_FFI_OK(botan_privkey_create, (&priv, "SM2_Enc", kCurve, rng));
1598
TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
1599
ffi_test_pubkey_export(result, pub, priv, rng);
1602
size_t sizeof_za = sizeof(za);
1603
TEST_FFI_OK(botan_pubkey_sm2_compute_za, (za, &sizeof_za, "Ident", "SM3", pub));
1605
// Check key load functions
1606
botan_mp_t private_scalar, public_x, public_y;
1607
botan_mp_init(&private_scalar);
1608
botan_mp_init(&public_x);
1609
botan_mp_init(&public_y);
1611
TEST_FFI_OK(botan_privkey_get_field, (private_scalar, priv, "x"));
1612
TEST_FFI_OK(botan_pubkey_get_field, (public_x, pub, "public_x"));
1613
TEST_FFI_OK(botan_pubkey_get_field, (public_y, pub, "public_y"));
1614
TEST_FFI_OK(botan_privkey_load_sm2_enc, (&loaded_privkey, private_scalar, kCurve));
1615
TEST_FFI_OK(botan_pubkey_load_sm2_enc, (&loaded_pubkey, public_x, public_y, kCurve));
1616
TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey, rng, 0));
1617
TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey, rng, 0));
1619
char namebuf[32] = { 0 };
1620
size_t name_len = sizeof(namebuf);
1622
TEST_FFI_OK(botan_pubkey_algo_name, (pub, &namebuf[0], &name_len));
1623
result.test_eq(namebuf, namebuf, "SM2_Enc");
1625
std::vector<uint8_t> message(32);
1627
std::vector<uint8_t> ciphertext(4096);
1628
TEST_FFI_OK(botan_rng_get, (rng, message.data(), message.size()));
1630
botan_pk_op_encrypt_t enc;
1631
if(TEST_FFI_OK(botan_pk_op_encrypt_create, (&enc, loaded_pubkey, "", 0)))
1633
size_t ctext_len = ciphertext.size();
1634
TEST_FFI_OK(botan_pk_op_encrypt, (enc, rng, ciphertext.data(), &ctext_len,
1635
message.data(), message.size()));
1636
ciphertext.resize(ctext_len);
1638
botan_pk_op_decrypt_t dec;
1639
TEST_FFI_OK(botan_pk_op_decrypt_create, (&dec, loaded_privkey, "", 0));
1641
std::vector<uint8_t> recovered(message.size());
1642
size_t recovered_len = recovered.size();
1644
TEST_FFI_OK(botan_pk_op_decrypt,
1645
(dec, recovered.data(), &recovered_len,
1646
ciphertext.data(), ciphertext.size()));
1648
botan_pk_op_decrypt_destroy(dec);
1650
botan_pk_op_encrypt_destroy(enc);
1652
TEST_FFI_OK(botan_mp_destroy, (private_scalar));
1653
TEST_FFI_OK(botan_mp_destroy, (public_x));
1654
TEST_FFI_OK(botan_mp_destroy, (public_y));
1655
TEST_FFI_OK(botan_pubkey_destroy, (pub));
1656
TEST_FFI_OK(botan_privkey_destroy, (priv));
1657
TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey));
1658
TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey));
1663
Test::Result ffi_test_ecdh(botan_rng_t rng)
1665
Test::Result result("FFI ECDH");
1667
botan_mp_t private_scalar, public_x, public_y;
1668
botan_privkey_t loaded_privkey1;
1669
botan_pubkey_t loaded_pubkey1;
1670
botan_mp_init(&private_scalar);
1671
botan_mp_init(&public_x);
1672
botan_mp_init(&public_y);
1674
botan_privkey_t priv1;
1675
REQUIRE_FFI_OK(botan_privkey_create_ecdh, (&priv1, rng, "secp256r1"));
1677
botan_privkey_t priv2;
1678
REQUIRE_FFI_OK(botan_privkey_create_ecdh, (&priv2, rng, "secp256r1"));
1680
botan_pubkey_t pub1;
1681
REQUIRE_FFI_OK(botan_privkey_export_pubkey, (&pub1, priv1));
1683
botan_pubkey_t pub2;
1684
REQUIRE_FFI_OK(botan_privkey_export_pubkey, (&pub2, priv2));
1686
/* Reload key-pair1 in order to test functions for key loading */
1687
TEST_FFI_OK(botan_privkey_get_field, (private_scalar, priv1, "x"));
1688
TEST_FFI_OK(botan_pubkey_get_field, (public_x, pub1, "public_x"));
1689
TEST_FFI_OK(botan_pubkey_get_field, (public_y, pub1, "public_y"));
1690
REQUIRE_FFI_OK(botan_privkey_load_ecdh, (&loaded_privkey1, private_scalar, "secp256r1"));
1691
REQUIRE_FFI_OK(botan_pubkey_load_ecdh, (&loaded_pubkey1, public_x, public_y, "secp256r1"));
1692
TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey1, rng, 0));
1693
TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey1, rng, 0));
1695
ffi_test_pubkey_export(result, loaded_pubkey1, priv1, rng);
1696
ffi_test_pubkey_export(result, pub2, priv2, rng);
1698
botan_pk_op_ka_t ka1;
1699
REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka1, loaded_privkey1, "KDF2(SHA-256)", 0));
1700
botan_pk_op_ka_t ka2;
1701
REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka2, priv2, "KDF2(SHA-256)", 0));
1703
size_t pubkey1_len = 0;
1704
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_pk_op_key_agreement_export_public, (priv1, nullptr, &pubkey1_len));
1705
std::vector<uint8_t> pubkey1(pubkey1_len);
1706
REQUIRE_FFI_OK(botan_pk_op_key_agreement_export_public, (priv1, pubkey1.data(), &pubkey1_len));
1707
size_t pubkey2_len = 0;
1708
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_pk_op_key_agreement_export_public, (priv2, nullptr, &pubkey2_len));
1709
std::vector<uint8_t> pubkey2(pubkey2_len);
1710
REQUIRE_FFI_OK(botan_pk_op_key_agreement_export_public, (priv2, pubkey2.data(), &pubkey2_len));
1712
std::vector<uint8_t> salt(32);
1713
TEST_FFI_OK(botan_rng_get, (rng, salt.data(), salt.size()));
1715
const size_t shared_key_len = 64;
1717
std::vector<uint8_t> key1(shared_key_len);
1718
size_t key1_len = key1.size();
1719
TEST_FFI_OK(botan_pk_op_key_agreement, (ka1, key1.data(), &key1_len,
1720
pubkey2.data(), pubkey2.size(),
1721
salt.data(), salt.size()));
1723
std::vector<uint8_t> key2(shared_key_len);
1724
size_t key2_len = key2.size();
1725
TEST_FFI_OK(botan_pk_op_key_agreement, (ka2, key2.data(), &key2_len,
1726
pubkey1.data(), pubkey1.size(),
1727
salt.data(), salt.size()));
1729
result.test_eq("shared ECDH key", key1, key2);
1731
TEST_FFI_OK(botan_mp_destroy, (private_scalar));
1732
TEST_FFI_OK(botan_mp_destroy, (public_x));
1733
TEST_FFI_OK(botan_mp_destroy, (public_y));
1734
TEST_FFI_OK(botan_pk_op_key_agreement_destroy, (ka1));
1735
TEST_FFI_OK(botan_pk_op_key_agreement_destroy, (ka2));
1736
TEST_FFI_OK(botan_privkey_destroy, (priv1));
1737
TEST_FFI_OK(botan_privkey_destroy, (priv2));
1738
TEST_FFI_OK(botan_pubkey_destroy, (pub1));
1739
TEST_FFI_OK(botan_pubkey_destroy, (pub2));
1740
TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey1));
1741
TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey1));
1745
Test::Result ffi_test_mceliece(botan_rng_t rng)
1747
Test::Result result("FFI McEliece");
1749
botan_privkey_t priv;
1750
#if defined(BOTAN_HAS_MCELIECE)
1751
if(TEST_FFI_OK(botan_privkey_create_mceliece, (&priv, rng, 2048, 50)))
1754
TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
1756
ffi_test_pubkey_export(result, pub, priv, rng);
1758
char namebuf[32] = { 0 };
1759
size_t name_len = sizeof(namebuf);
1760
if(TEST_FFI_OK(botan_pubkey_algo_name, (pub, namebuf, &name_len)))
1762
result.test_eq("algo name", std::string(namebuf), "McEliece");
1767
#if defined(BOTAN_HAS_MCEIES)
1768
const uint8_t ad[8] = { 0xAD, 0xAD, 0xAD, 0xAD, 0xBE, 0xEE, 0xEE, 0xFF };
1769
const size_t ad_len = sizeof(ad);
1771
const Botan::secure_vector<uint8_t> plaintext = Test::rng().random_vec(Test::rng().next_byte());
1772
size_t plaintext_len = plaintext.size();
1773
size_t ciphertext_len = 0;
1775
// first calculate ciphertext length
1776
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_mceies_encrypt, (pub, rng, "AES-256/OCB", plaintext.data(),
1777
plaintext.size(), ad, ad_len, nullptr, &ciphertext_len));
1778
std::vector<uint8_t> ciphertext(ciphertext_len);
1781
if(TEST_FFI_OK(botan_mceies_encrypt, (pub, rng, "AES-256/OCB", plaintext.data(), plaintext.size(), ad, ad_len,
1782
ciphertext.data(), &ciphertext_len)))
1784
std::vector<uint8_t> decrypted(plaintext.size());
1785
size_t decrypted_len = plaintext_len;
1787
TEST_FFI_OK(botan_mceies_decrypt, (priv, "AES-256/OCB", ciphertext.data(), ciphertext.size(), ad, ad_len,
1788
decrypted.data(), &decrypted_len));
1790
result.test_eq("MCIES plaintext", decrypted, plaintext);
1794
TEST_FFI_OK(botan_pubkey_destroy, (pub));
1795
TEST_FFI_OK(botan_privkey_destroy, (priv));
1798
// Not included, test that calling the FFI function work (and returns an error)
1799
TEST_FFI_RC(BOTAN_FFI_ERROR_NOT_IMPLEMENTED, botan_privkey_create_mceliece, (&priv, rng, 2048, 50));
1805
Test::Result ffi_test_ed25519(botan_rng_t rng)
1807
Test::Result result("FFI Ed25519");
1810
botan_privkey_t priv;
1812
// From draft-koch-eddsa-for-openpgp-04
1813
const std::vector<uint8_t> seed = Botan::hex_decode(
1814
"1a8b1ff05ded48e18bf50166c664ab023ea70003d78d9e41f5758a91d850f8d2");
1815
const std::vector<uint8_t> pubkey = Botan::hex_decode(
1816
"3f098994bdd916ed4053197934e4a87c80733a1280d62f8010992e43ee3b2406");
1817
const std::vector<uint8_t> message = Botan::hex_decode(
1818
"4f70656e504750040016080006050255f95f9504ff0000000c");
1819
const std::vector<uint8_t> exp_sig = Botan::hex_decode(
1820
"56f90cca98e2102637bd983fdb16c131dfd27ed82bf4dde5606e0d756aed3366"
1821
"d09c4fa11527f038e0f57f2201d82f2ea2c9033265fa6ceb489e854bae61b404");
1823
TEST_FFI_OK(botan_privkey_load_ed25519, (&priv, seed.data()));
1825
uint8_t retr_privkey[64];
1826
TEST_FFI_OK(botan_privkey_ed25519_get_privkey, (priv, retr_privkey));
1828
result.test_eq(nullptr, "Public key matches", retr_privkey + 32, 32,
1829
pubkey.data(), pubkey.size());
1831
TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
1833
uint8_t retr_pubkey[32];
1834
TEST_FFI_OK(botan_pubkey_ed25519_get_pubkey, (pub, retr_pubkey));
1835
result.test_eq(nullptr, "Public key matches", retr_pubkey, 32,
1836
pubkey.data(), pubkey.size());
1838
TEST_FFI_OK(botan_pubkey_destroy, (pub));
1839
TEST_FFI_OK(botan_pubkey_load_ed25519, (&pub, pubkey.data()));
1841
botan_pk_op_sign_t signer;
1842
std::vector<uint8_t> signature;
1844
if(TEST_FFI_OK(botan_pk_op_sign_create, (&signer, priv, "SHA-256", 0)))
1846
TEST_FFI_OK(botan_pk_op_sign_update, (signer, message.data(), message.size()));
1848
signature.resize(128);
1849
size_t sig_len = signature.size();
1850
TEST_FFI_OK(botan_pk_op_sign_finish, (signer, rng, signature.data(), &sig_len));
1851
signature.resize(sig_len);
1853
TEST_FFI_OK(botan_pk_op_sign_destroy, (signer));
1856
result.test_eq("Expected signature", signature, exp_sig);
1858
botan_pk_op_verify_t verifier;
1860
if(TEST_FFI_OK(botan_pk_op_verify_create, (&verifier, pub, "SHA-256", 0)))
1862
TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1863
TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1865
TEST_FFI_OK(botan_pk_op_verify_destroy, (verifier));
1868
TEST_FFI_OK(botan_pubkey_destroy, (pub));
1869
TEST_FFI_OK(botan_privkey_destroy, (priv));
1874
Test::Result ffi_test_elgamal(botan_rng_t rng)
1876
Test::Result result("FFI ELGAMAL");
1878
botan_privkey_t priv;
1880
if(TEST_FFI_OK(botan_privkey_create, (&priv, "ElGamal", nullptr, rng)))
1882
TEST_FFI_OK(botan_privkey_check_key, (priv, rng, 0));
1885
TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
1886
TEST_FFI_OK(botan_pubkey_check_key, (pub, rng, 0));
1888
ffi_test_pubkey_export(result, pub, priv, rng);
1889
botan_mp_t p, g, x, y;
1895
TEST_FFI_OK(botan_pubkey_get_field, (p, pub, "p"));
1896
TEST_FFI_OK(botan_pubkey_get_field, (g, pub, "g"));
1897
TEST_FFI_OK(botan_pubkey_get_field, (y, pub, "y"));
1898
TEST_FFI_OK(botan_privkey_get_field, (x, priv, "x"));
1901
TEST_FFI_OK(botan_mp_num_bytes, (p, &p_len));
1903
botan_privkey_t loaded_privkey;
1904
TEST_FFI_OK(botan_privkey_load_elgamal, (&loaded_privkey, p, g, x));
1905
TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey, rng, 0));
1907
botan_pubkey_t loaded_pubkey;
1908
TEST_FFI_OK(botan_pubkey_load_elgamal, (&loaded_pubkey, p, g, y));
1909
TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey, rng, 0));
1911
botan_mp_destroy(p);
1912
botan_mp_destroy(g);
1913
botan_mp_destroy(y);
1914
botan_mp_destroy(x);
1917
std::vector<uint8_t> plaintext(16, 0xFF);
1918
std::vector<uint8_t> ciphertext(p_len*2, 0);
1919
std::vector<uint8_t> decryption(16, 0);
1922
botan_pk_op_encrypt_t op_enc;
1923
size_t ct_len = ciphertext.size();
1924
REQUIRE_FFI_OK(botan_pk_op_encrypt_create, (&op_enc, loaded_pubkey, "Raw", 0));
1925
TEST_FFI_OK(botan_pk_op_encrypt, (op_enc, rng, ciphertext.data(), &ct_len, plaintext.data(), plaintext.size()));
1926
TEST_FFI_OK(botan_pk_op_encrypt_destroy, (op_enc));
1929
botan_pk_op_decrypt_t op_dec;
1930
size_t pt_len = decryption.size();
1931
REQUIRE_FFI_OK(botan_pk_op_decrypt_create, (&op_dec, loaded_privkey, "Raw", 0));
1932
TEST_FFI_OK(botan_pk_op_decrypt, (op_dec, decryption.data(), &pt_len, ciphertext.data(), ct_len));
1933
TEST_FFI_OK(botan_pk_op_decrypt_destroy, (op_dec));
1935
TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey));
1936
TEST_FFI_OK(botan_pubkey_destroy, (pub));
1937
TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey));
1938
TEST_FFI_OK(botan_privkey_destroy, (priv));
1945
Test::Result ffi_test_dh(botan_rng_t rng)
1947
Test::Result result("FFI DH");
1949
botan_mp_t private_x, public_g, public_p, public_y;
1951
botan_privkey_t loaded_privkey1;
1952
botan_pubkey_t loaded_pubkey1;
1954
botan_mp_init(&private_x);
1956
botan_mp_init(&public_g);
1957
botan_mp_init(&public_p);
1958
botan_mp_init(&public_y);
1960
botan_privkey_t priv1;
1961
REQUIRE_FFI_OK(botan_privkey_create_dh, (&priv1, rng, "modp/ietf/2048"));
1963
botan_privkey_t priv2;
1964
REQUIRE_FFI_OK(botan_privkey_create_dh, (&priv2, rng, "modp/ietf/2048"));
1966
botan_pubkey_t pub1;
1967
REQUIRE_FFI_OK(botan_privkey_export_pubkey, (&pub1, priv1));
1969
botan_pubkey_t pub2;
1970
REQUIRE_FFI_OK(botan_privkey_export_pubkey, (&pub2, priv2));
1972
// Reload key-pair1 in order to test functions for key loading
1973
TEST_FFI_OK(botan_privkey_get_field, (private_x, priv1, "x"));
1974
TEST_FFI_OK(botan_pubkey_get_field, (public_g, pub1, "g"));
1975
TEST_FFI_OK(botan_pubkey_get_field, (public_p, pub1, "p"));
1976
TEST_FFI_OK(botan_pubkey_get_field, (public_y, pub1, "y"));
1978
TEST_FFI_OK(botan_privkey_load_dh, (&loaded_privkey1, public_p, public_g, private_x));
1980
TEST_FFI_OK(botan_pubkey_load_dh, (&loaded_pubkey1, public_p, public_g, public_y));
1982
TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey1, rng, 0));
1983
TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey1, rng, 0));
1985
botan_mp_t loaded_public_g, loaded_public_p, loaded_public_y;
1986
botan_mp_init(&loaded_public_g);
1987
botan_mp_init(&loaded_public_p);
1988
botan_mp_init(&loaded_public_y);
1990
TEST_FFI_OK(botan_pubkey_get_field, (loaded_public_g, loaded_pubkey1, "g"));
1991
TEST_FFI_OK(botan_pubkey_get_field, (loaded_public_p, loaded_pubkey1, "p"));
1992
TEST_FFI_OK(botan_pubkey_get_field, (loaded_public_y, loaded_pubkey1, "y"));
1996
TEST_FFI_OK(botan_mp_cmp, (&cmp, loaded_public_g, public_g));
1997
result.confirm("bigint_mp_cmp(g, g)", cmp == 0);
1999
TEST_FFI_OK(botan_mp_cmp, (&cmp, loaded_public_p, public_p));
2000
result.confirm("bigint_mp_cmp(p, p)", cmp == 0);
2002
TEST_FFI_OK(botan_mp_cmp, (&cmp, loaded_public_y, public_y));
2003
result.confirm("bigint_mp_cmp(y, y)", cmp == 0);
2005
botan_pk_op_ka_t ka1;
2006
REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka1, loaded_privkey1, "Raw", 0));
2007
botan_pk_op_ka_t ka2;
2008
REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka2, priv2, "Raw", 0));
2010
size_t pubkey1_len = 0;
2011
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_pk_op_key_agreement_export_public, (priv1, nullptr, &pubkey1_len));
2012
std::vector<uint8_t> pubkey1(pubkey1_len);
2013
REQUIRE_FFI_OK(botan_pk_op_key_agreement_export_public, (priv1, pubkey1.data(), &pubkey1_len));
2014
size_t pubkey2_len = 0;
2015
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_pk_op_key_agreement_export_public, (priv2, nullptr, &pubkey2_len));
2016
std::vector<uint8_t> pubkey2(pubkey2_len);
2017
REQUIRE_FFI_OK(botan_pk_op_key_agreement_export_public, (priv2, pubkey2.data(), &pubkey2_len));
2019
std::vector<uint8_t> salt(32);
2021
TEST_FFI_OK(botan_rng_get, (rng, salt.data(), salt.size()));
2023
const size_t shared_key_len = 256;
2025
std::vector<uint8_t> key1(shared_key_len);
2026
size_t key1_len = key1.size();
2028
TEST_FFI_OK(botan_pk_op_key_agreement, (ka1, key1.data(), &key1_len,
2029
pubkey2.data(), pubkey2.size(),
2030
salt.data(), salt.size()));
2032
std::vector<uint8_t> key2(shared_key_len);
2033
size_t key2_len = key2.size();
2035
TEST_FFI_OK(botan_pk_op_key_agreement, (ka2, key2.data(), &key2_len,
2036
pubkey1.data(), pubkey1.size(),
2037
salt.data(), salt.size()));
2039
result.test_eq("shared DH key", key1, key2);
2041
TEST_FFI_OK(botan_mp_destroy, (private_x));
2042
TEST_FFI_OK(botan_mp_destroy, (public_p));
2043
TEST_FFI_OK(botan_mp_destroy, (public_g));
2044
TEST_FFI_OK(botan_mp_destroy, (public_y));
2046
TEST_FFI_OK(botan_mp_destroy, (loaded_public_p));
2047
TEST_FFI_OK(botan_mp_destroy, (loaded_public_g));
2048
TEST_FFI_OK(botan_mp_destroy, (loaded_public_y));
2050
TEST_FFI_OK(botan_pk_op_key_agreement_destroy, (ka1));
2051
TEST_FFI_OK(botan_pk_op_key_agreement_destroy, (ka2));
2052
TEST_FFI_OK(botan_privkey_destroy, (priv1));
2053
TEST_FFI_OK(botan_privkey_destroy, (priv2));
2054
TEST_FFI_OK(botan_pubkey_destroy, (pub1));
2055
TEST_FFI_OK(botan_pubkey_destroy, (pub2));
2056
TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey1));
2057
TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey1));
2065
BOTAN_REGISTER_TEST("ffi", FFI_Unit_Tests);