• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5356326050

23 Jun 2023 01:05PM UTC coverage: 91.728% (-0.008%) from 91.736%
5356326050

Pull #3595

github

web-flow
Merge a5b917599 into 92171c524
Pull Request #3595: Improve clang-tidy coverage

78163 of 85212 relevant lines covered (91.73%)

12690161.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.78
/src/tests/test_ffi.cpp
1
/*
2
* (C) 2015 Jack Lloyd
3
* (C) 2016 René Korthaus
4
* (C) 2018 Ribose Inc, Krzysztof Kwiatkowski
5
* (C) 2018 Ribose Inc
6
*
7
* Botan is released under the Simplified BSD License (see license.txt)
8
*/
9

10
#define BOTAN_NO_DEPRECATED_WARNINGS
11

12
#include "tests.h"
13
#include <botan/version.h>
14

15
#if defined(BOTAN_HAS_FFI)
16
   #include <botan/ffi.h>
17
   #include <botan/hex.h>
18
   #include <botan/internal/loadstor.h>
19
   #include <set>
20
#endif
21

22
namespace Botan_Tests {
23

24
namespace {
25

26
#if defined(BOTAN_HAS_FFI)
27

28
   // NOLINTNEXTLINE(*-macro-usage)
29
   #define TEST_FFI_OK(func, args) result.test_rc_ok(#func, func args)
30
   // NOLINTNEXTLINE(*-macro-usage)
31
   #define TEST_FFI_INIT(func, args) result.test_rc_init(#func, func args)
32
   // NOLINTNEXTLINE(*-macro-usage)
33
   #define TEST_FFI_FAIL(msg, func, args) result.test_rc_fail(#func, msg, func args)
34
   // NOLINTNEXTLINE(*-macro-usage)
35
   #define TEST_FFI_RC(rc, func, args) result.test_rc(#func, rc, func args)
36

37
   // NOLINTNEXTLINE(*-macro-usage)
38
   #define REQUIRE_FFI_OK(func, args)                           \
39
      if(!TEST_FFI_OK(func, args)) {                            \
40
         result.test_note("Exiting test early due to failure"); \
41
         return;                                                \
42
      }
43

44
class FFI_Test : public Test {
39✔
45
   public:
46
      std::vector<Test::Result> run() override {
39✔
47
         Test::Result result(this->name());
39✔
48

49
         botan_rng_t rng;
39✔
50
         if(botan_rng_init(&rng, "system") != 0) {
39✔
51
            result.test_failure("Failed to init RNG");
×
52
            return {result};
×
53
         }
54

55
         result.start_timer();
39✔
56
         ffi_test(result, rng);
39✔
57
         result.end_timer();
39✔
58

59
         botan_rng_destroy(rng);
39✔
60

61
         return {result};
78✔
62
      }
39✔
63

64
   private:
65
      virtual std::string name() const = 0;
66
      virtual void ffi_test(Test::Result& result, botan_rng_t rng) = 0;
67
};
68

69
void ffi_test_pubkey_export(Test::Result& result, botan_pubkey_t pub, botan_privkey_t priv, botan_rng_t rng) {
11✔
70
   // export public key
71
   size_t pubkey_len = 0;
11✔
72
   TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
11✔
73
               botan_pubkey_export,
74
               (pub, nullptr, &pubkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_DER));
75

76
   std::vector<uint8_t> pubkey(pubkey_len);
11✔
77
   TEST_FFI_OK(botan_pubkey_export, (pub, pubkey.data(), &pubkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_DER));
11✔
78

79
   pubkey_len = 0;
11✔
80
   TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
11✔
81
               botan_pubkey_export,
82
               (pub, nullptr, &pubkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_PEM));
83

84
   pubkey.resize(pubkey_len);
11✔
85
   TEST_FFI_OK(botan_pubkey_export, (pub, pubkey.data(), &pubkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_PEM));
11✔
86

87
   // reimport exported public key
88
   botan_pubkey_t pub_copy;
11✔
89
   TEST_FFI_OK(botan_pubkey_load, (&pub_copy, pubkey.data(), pubkey_len));
11✔
90
   TEST_FFI_OK(botan_pubkey_check_key, (pub_copy, rng, 0));
11✔
91
   TEST_FFI_OK(botan_pubkey_destroy, (pub_copy));
11✔
92

93
   // export private key
94
   std::vector<uint8_t> privkey;
11✔
95
   size_t privkey_len = 0;
11✔
96

97
   // call with nullptr to query the length
98
   TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
11✔
99
               botan_privkey_export,
100
               (priv, nullptr, &privkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_DER));
101

102
   privkey.resize(privkey_len);
11✔
103
   privkey_len = privkey.size();  // set buffer size
11✔
104

105
   TEST_FFI_OK(botan_privkey_export, (priv, privkey.data(), &privkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_DER));
11✔
106

107
   privkey.resize(privkey_len);
11✔
108

109
   result.test_gte("Reasonable size", privkey.size(), 32);
11✔
110

111
   // reimport exported private key
112
   botan_privkey_t copy;
11✔
113
   TEST_FFI_OK(botan_privkey_load, (&copy, rng, privkey.data(), privkey.size(), nullptr));
11✔
114
   botan_privkey_destroy(copy);
11✔
115

116
   // Now again for PEM
117
   privkey_len = 0;
11✔
118

119
   TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
11✔
120
               botan_privkey_export,
121
               (priv, nullptr, &privkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_PEM));
122

123
   privkey.resize(privkey_len);
11✔
124
   TEST_FFI_OK(botan_privkey_export, (priv, privkey.data(), &privkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_PEM));
11✔
125

126
   TEST_FFI_OK(botan_privkey_load, (&copy, rng, privkey.data(), privkey.size(), nullptr));
11✔
127
   botan_privkey_destroy(copy);
11✔
128

129
   #if defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_PKCS5_PBES2)
130
   const size_t pbkdf_iter = 1000;
11✔
131

132
   // export private key encrypted
133
   privkey_len = 0;
11✔
134
   TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
11✔
135
               botan_privkey_export_encrypted_pbkdf_iter,
136
               (priv, nullptr, &privkey_len, rng, "password", pbkdf_iter, "", "", BOTAN_PRIVKEY_EXPORT_FLAG_DER));
137

138
   privkey.resize(privkey_len);
11✔
139
   privkey_len = privkey.size();
11✔
140

141
   TEST_FFI_OK(
11✔
142
      botan_privkey_export_encrypted_pbkdf_iter,
143
      (priv, privkey.data(), &privkey_len, rng, "password", pbkdf_iter, "", "", BOTAN_PRIVKEY_EXPORT_FLAG_DER));
144

145
   // reimport encrypted private key
146
   botan_privkey_load(&copy, rng, privkey.data(), privkey.size(), "password");
11✔
147
   botan_privkey_destroy(copy);
11✔
148

149
   privkey_len = 0;
11✔
150
   TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
11✔
151
               botan_privkey_export_encrypted_pbkdf_iter,
152
               (priv, nullptr, &privkey_len, rng, "password", pbkdf_iter, "", "", BOTAN_PRIVKEY_EXPORT_FLAG_PEM));
153

154
   privkey.resize(privkey_len);
11✔
155
   TEST_FFI_OK(
11✔
156
      botan_privkey_export_encrypted_pbkdf_iter,
157
      (priv, privkey.data(), &privkey_len, rng, "password", pbkdf_iter, "", "", BOTAN_PRIVKEY_EXPORT_FLAG_PEM));
158

159
   privkey.resize(privkey_len * 2);
11✔
160
   privkey_len = privkey.size();
11✔
161
   const uint32_t pbkdf_msec = 100;
11✔
162
   size_t pbkdf_iters_out = 0;
11✔
163

164
      #if defined(BOTAN_HAS_SCRYPT)
165
   const std::string pbe_hash = "Scrypt";
11✔
166
      #else
167
   const std::string pbe_hash = "SHA-512";
168
      #endif
169

170
      #if defined(BOTAN_HAS_AEAD_GCM)
171
   const std::string pbe_cipher = "AES-256/GCM";
11✔
172
      #else
173
   const std::string pbe_cipher = "AES-256/CBC";
174
      #endif
175

176
   TEST_FFI_OK(botan_privkey_export_encrypted_pbkdf_msec,
11✔
177
               (priv,
178
                privkey.data(),
179
                &privkey_len,
180
                rng,
181
                "password",
182
                pbkdf_msec,
183
                &pbkdf_iters_out,
184
                pbe_cipher.c_str(),
185
                pbe_hash.c_str(),
186
                0));
187

188
   if(pbe_hash == "Scrypt") {
11✔
189
      result.test_eq("Scrypt iters set to zero in this API", pbkdf_iters_out, 0);
22✔
190
   } else {
191
      // PBKDF2 currently always rounds to multiple of 2000
192
      result.test_eq("Expected PBKDF2 iters", pbkdf_iters_out % 2000, 0);
×
193
   }
194

195
   privkey.resize(privkey_len);
11✔
196

197
   TEST_FFI_OK(botan_privkey_load, (&copy, rng, privkey.data(), privkey.size(), "password"));
11✔
198
   botan_privkey_destroy(copy);
11✔
199
   #endif
200

201
   // calculate fingerprint
202
   size_t strength = 0;
11✔
203
   TEST_FFI_OK(botan_pubkey_estimated_strength, (pub, &strength));
11✔
204
   result.test_gte("estimated strength", strength, 1);
11✔
205

206
   size_t fingerprint_len = 0;
11✔
207
   TEST_FFI_RC(
11✔
208
      BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_pubkey_fingerprint, (pub, "SHA-256", nullptr, &fingerprint_len));
209

210
   std::vector<uint8_t> fingerprint(fingerprint_len);
11✔
211
   TEST_FFI_OK(botan_pubkey_fingerprint, (pub, "SHA-256", fingerprint.data(), &fingerprint_len));
22✔
212
}
33✔
213

214
class FFI_Utils_Test final : public FFI_Test {
×
215
   public:
216
      std::string name() const override { return "FFI Utils"; }
1✔
217

218
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
219
         result.test_is_eq("FFI API version", botan_ffi_api_version(), uint32_t(BOTAN_HAS_FFI));
1✔
220
         result.test_is_eq("Major version", botan_version_major(), Botan::version_major());
1✔
221
         result.test_is_eq("Minor version", botan_version_minor(), Botan::version_minor());
1✔
222
         result.test_is_eq("Patch version", botan_version_patch(), Botan::version_patch());
1✔
223
         result.test_is_eq("Botan version", botan_version_string(), Botan::version_cstr());
1✔
224
         result.test_is_eq("Botan version datestamp", botan_version_datestamp(), Botan::version_datestamp());
1✔
225
         result.test_is_eq("FFI supports its own version", botan_ffi_supports_api(botan_ffi_api_version()), 0);
1✔
226

227
         result.test_is_eq("FFI supports 2.0 version", botan_ffi_supports_api(20150515), 0);
1✔
228
         result.test_is_eq("FFI supports 2.1 version", botan_ffi_supports_api(20170327), 0);
1✔
229
         result.test_is_eq("FFI supports 2.3 version", botan_ffi_supports_api(20170815), 0);
1✔
230
         result.test_is_eq("FFI supports 2.8 version", botan_ffi_supports_api(20180713), 0);
1✔
231

232
         result.test_is_eq("FFI doesn't support bogus version", botan_ffi_supports_api(20160229), -1);
1✔
233

234
         const std::vector<uint8_t> mem1 = {0xFF, 0xAA, 0xFF};
1✔
235
         const std::vector<uint8_t> mem2 = {0xFF, 0xA9, 0xFF};
1✔
236

237
         TEST_FFI_RC(0, botan_constant_time_compare, (mem1.data(), mem1.data(), mem1.size()));
1✔
238
         TEST_FFI_RC(-1, botan_constant_time_compare, (mem1.data(), mem2.data(), mem1.size()));
1✔
239

240
         std::vector<uint8_t> to_zero = {0xFF, 0xA0};
1✔
241
         TEST_FFI_OK(botan_scrub_mem, (to_zero.data(), to_zero.size()));
1✔
242
         result.confirm("scrub_memory zeros", to_zero[0] == 0 && to_zero[1] == 0);
2✔
243

244
         const std::vector<uint8_t> bin = {0xAA, 0xDE, 0x01};
1✔
245

246
         std::string outstr;
1✔
247
         std::vector<uint8_t> outbuf;
1✔
248

249
         outstr.resize(2 * bin.size());
1✔
250
         TEST_FFI_OK(botan_hex_encode, (bin.data(), bin.size(), &outstr[0], 0));
1✔
251
         result.test_eq("uppercase hex", outstr, "AADE01");
2✔
252

253
         TEST_FFI_OK(botan_hex_encode, (bin.data(), bin.size(), &outstr[0], BOTAN_FFI_HEX_LOWER_CASE));
1✔
254
         result.test_eq("lowercase hex", outstr, "aade01");
2✔
255
      }
5✔
256
};
257

258
class FFI_RNG_Test final : public FFI_Test {
×
259
   public:
260
      std::string name() const override { return "FFI RNG"; }
1✔
261

262
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
263
         // RNG test and initialization
264
         botan_rng_t rng;
1✔
265
         botan_rng_t system_rng;
1✔
266
         botan_rng_t hwrng_rng = nullptr;
1✔
267
         botan_rng_t null_rng;
1✔
268
         botan_rng_t custom_rng;
1✔
269

270
         TEST_FFI_FAIL("invalid rng type", botan_rng_init, (&rng, "invalid_type"));
2✔
271

272
         REQUIRE_FFI_OK(botan_rng_init, (&system_rng, "system"));
1✔
273
         REQUIRE_FFI_OK(botan_rng_init, (&null_rng, "null"));
1✔
274

275
         int rc = botan_rng_init(&hwrng_rng, "hwrng");
1✔
276
         result.confirm("Either success or not implemented", rc == 0 || rc == BOTAN_FFI_ERROR_NOT_IMPLEMENTED);
2✔
277

278
         std::vector<uint8_t> outbuf(512);
1✔
279

280
         rc = botan_rng_init(&rng, "user-threadsafe");
1✔
281
         result.confirm("Either success or not implemented", rc == 0 || rc == BOTAN_FFI_ERROR_NOT_IMPLEMENTED);
2✔
282

283
         if(rc != 0) {
1✔
284
            REQUIRE_FFI_OK(botan_rng_init, (&rng, "user"));
×
285
            REQUIRE_FFI_OK(botan_rng_destroy, (rng));
×
286
         }
287

288
         if(rc == 0) {
1✔
289
            TEST_FFI_OK(botan_rng_get, (rng, outbuf.data(), outbuf.size()));
1✔
290
            TEST_FFI_OK(botan_rng_reseed, (rng, 256));
1✔
291

292
            TEST_FFI_RC(BOTAN_FFI_ERROR_INVALID_OBJECT_STATE, botan_rng_reseed_from_rng, (rng, null_rng, 256));
1✔
293
            if(hwrng_rng) {
1✔
294
               TEST_FFI_OK(botan_rng_reseed_from_rng, (rng, hwrng_rng, 256));
2✔
295
            }
296
            TEST_FFI_RC(BOTAN_FFI_ERROR_INVALID_OBJECT_STATE, botan_rng_get, (null_rng, outbuf.data(), outbuf.size()));
1✔
297

298
            TEST_FFI_OK(botan_rng_destroy, (rng));
2✔
299
         }
300

301
         if(TEST_FFI_OK(botan_rng_init, (&rng, "user"))) {
1✔
302
            TEST_FFI_OK(botan_rng_get, (rng, outbuf.data(), outbuf.size()));
1✔
303
            TEST_FFI_OK(botan_rng_reseed, (rng, 256));
1✔
304

305
            TEST_FFI_OK(botan_rng_reseed_from_rng, (rng, system_rng, 256));
1✔
306

307
            uint8_t not_really_entropy[32] = {0};
1✔
308
            TEST_FFI_OK(botan_rng_add_entropy, (rng, not_really_entropy, 32));
2✔
309
         }
310

311
         uint8_t system_rng_buf[4096];
1✔
312
         TEST_FFI_OK(botan_system_rng_get, (system_rng_buf, sizeof(system_rng_buf)));
1✔
313

314
         size_t cb_counter = 0;
1✔
315

316
         auto custom_get_cb = +[](void* context, uint8_t* out, size_t out_len) -> int {
1✔
317
            Botan::set_mem(out, out_len, 0x12);
318
            BOTAN_UNUSED(out, out_len);
319
            (*(static_cast<size_t*>(context)))++;
320
            return 0;
321
         };
322

323
         auto custom_add_entropy_cb = +[](void* context, const uint8_t input[], size_t length) -> int {
1✔
324
            BOTAN_UNUSED(input, length);
325
            (*(static_cast<size_t*>(context)))++;
326
            return 0;
327
         };
328

329
         auto custom_destroy_cb = +[](void* context) -> void { (*(static_cast<size_t*>(context)))++; };
1✔
330

331
         if(TEST_FFI_OK(
2✔
332
               botan_rng_init_custom,
333
               (&custom_rng, "custom rng", &cb_counter, custom_get_cb, custom_add_entropy_cb, custom_destroy_cb))) {
334
            Botan::clear_mem(outbuf.data(), outbuf.size());
1✔
335
            TEST_FFI_OK(botan_rng_get, (custom_rng, outbuf.data(), outbuf.size()));
1✔
336
            result.test_eq("custom_get_cb called", cb_counter, 1);
1✔
337
            std::vector<uint8_t> pattern(outbuf.size(), 0x12);
1✔
338
            result.test_eq("custom_get_cb returned bytes", pattern, outbuf);
1✔
339

340
            TEST_FFI_OK(botan_rng_reseed, (custom_rng, 256));
1✔
341
            result.test_eq("custom_add_entropy_cb called", cb_counter, 2);
1✔
342

343
            TEST_FFI_OK(botan_rng_reseed_from_rng, (custom_rng, system_rng, 256));
1✔
344
            result.test_eq("custom_add_entropy_cb called", cb_counter, 3);
1✔
345

346
            uint8_t not_really_entropy[32] = {0};
1✔
347
            TEST_FFI_OK(botan_rng_add_entropy, (custom_rng, not_really_entropy, 32));
1✔
348
            result.test_eq("custom_add_entropy_cb called", cb_counter, 4);
1✔
349

350
            TEST_FFI_OK(botan_rng_destroy, (custom_rng));
1✔
351
            result.test_eq("custom_destroy_cb called", cb_counter, 5);
2✔
352
         }
1✔
353

354
         TEST_FFI_OK(botan_rng_destroy, (rng));
1✔
355
         TEST_FFI_OK(botan_rng_destroy, (null_rng));
1✔
356
         TEST_FFI_OK(botan_rng_destroy, (system_rng));
1✔
357
         TEST_FFI_OK(botan_rng_destroy, (hwrng_rng));
2✔
358
      }
1✔
359
};
360

361
class FFI_RSA_Cert_Test final : public FFI_Test {
×
362
   public:
363
      std::string name() const override { return "FFI RSA cert"; }
1✔
364

365
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
366
         botan_x509_cert_t cert;
1✔
367
         if(TEST_FFI_INIT(botan_x509_cert_load_file, (&cert, Test::data_file("x509/ocsp/randombit.pem").c_str()))) {
4✔
368
            TEST_FFI_RC(0, botan_x509_cert_hostname_match, (cert, "randombit.net"));
1✔
369
            TEST_FFI_RC(0, botan_x509_cert_hostname_match, (cert, "www.randombit.net"));
1✔
370
            TEST_FFI_RC(-1, botan_x509_cert_hostname_match, (cert, "*.randombit.net"));
1✔
371
            TEST_FFI_RC(-1, botan_x509_cert_hostname_match, (cert, "flub.randombit.net"));
1✔
372
            TEST_FFI_RC(-1, botan_x509_cert_hostname_match, (cert, "randombit.net.com"));
1✔
373

374
            botan_x509_cert_t copy;
1✔
375
            TEST_FFI_OK(botan_x509_cert_dup, (&copy, cert));
1✔
376
            TEST_FFI_RC(0, botan_x509_cert_hostname_match, (copy, "randombit.net"));
1✔
377

378
            TEST_FFI_OK(botan_x509_cert_destroy, (copy));
1✔
379
            TEST_FFI_OK(botan_x509_cert_destroy, (cert));
2✔
380
         }
381
      }
1✔
382
};
383

384
class FFI_ZFEC_Test final : public FFI_Test {
×
385
   public:
386
      std::string name() const override { return "FFI ZFEC"; }
1✔
387

388
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
389
         /* exercise a simple success case
390
          */
391

392
         // Select some arbitrary, valid encoding parameters.  There is
393
         // nothing special about them but some relationships between these
394
         // values and other inputs must hold.
395
         const size_t K = 3;
1✔
396
         const size_t N = 11;
1✔
397

398
         // The decoder needs to know the indexes of the blocks being passed
399
         // in to it.  This array must equal [0..N) for the logic in the
400
         // decoding loop below to hold.
401
         const std::vector<size_t> indexes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1✔
402

403
         // This will be the size of each encoded (or decoded) block.  This is
404
         // an arbitrary value but it must match up with the length of the
405
         // test data given in `input`.
406
         const size_t blockSize = 15;
1✔
407

408
         // K of the blocks are required so the total information represented
409
         // can be this multiple.  totalSize must be a multiple of K and it
410
         // always will be using this construction.
411
         const size_t totalSize = blockSize * K;
1✔
412

413
         // Here's the complete original input (plus a trailing NUL that we
414
         // won't pass through ZFEC).  These are arbitrary bytes.
415
         const uint8_t input[totalSize + 1] = "Does this work?AAAAAAAAAAAAAAAzzzzzzzzzzzzzzz";
1✔
416

417
         // Allocate memory for the encoding and decoding output parameters.
418
         std::vector<uint8_t> encoded_buf(N * blockSize);
1✔
419
         std::vector<uint8_t> decoded_buf(K * blockSize);
1✔
420

421
         std::vector<uint8_t*> encoded(N);
1✔
422
         for(size_t i = 0; i < N; ++i) {
12✔
423
            encoded[i] = &encoded_buf[i * blockSize];
11✔
424
         }
425
         std::vector<uint8_t*> decoded(K);
1✔
426
         for(size_t i = 0; i < K; ++i) {
4✔
427
            decoded[i] = &decoded_buf[i * blockSize];
3✔
428
         }
429

430
         // First encode the complete input string into N blocks where K are
431
         // required for reconstruction.  The N encoded blocks will end up in
432
         // `encoded`.
433
         if(!TEST_FFI_INIT(botan_zfec_encode, (K, N, input, totalSize, encoded.data()))) {
2✔
434
            return;
435
         }
436

437
         // Any K blocks can be decoded to reproduce the original input (split
438
         // across an array of K strings of blockSize bytes each).  This loop
439
         // only exercises decoding with consecutive blocks because it's
440
         // harder to pick non-consecutive blocks out for a test.
441
         for(size_t offset = 0; offset < N - K; ++offset) {
9✔
442
            result.test_note("About to decode with offset " + std::to_string(offset));
16✔
443
            // Pass in the K shares starting from `offset` (and their indexes)
444
            // so that we can try decoding a certain group of blocks here.  Any
445
            // K shares *should* work.
446
            REQUIRE_FFI_OK(botan_zfec_decode,
16✔
447
                           (K, N, indexes.data() + offset, encoded.data() + offset, blockSize, decoded.data()));
448

449
            // Check that the original input bytes have been written to the
450
            // output parameter.
451
            for(size_t k = 0, pos = 0; k < K; ++k, pos += blockSize) {
32✔
452
               TEST_FFI_RC(0, botan_constant_time_compare, (input + pos, decoded[k], blockSize));
48✔
453
            }
454
         }
455

456
         /* Exercise a couple basic failure cases, such as you encounter if
457
          * the caller supplies invalid parameters.  We don't try to
458
          * exhaustively prove invalid parameters are handled through this
459
          * interface since the implementation only passes them through to
460
          * ZFEC::{encode,decode} where the real checking is.  We just want to
461
          * see that errors can propagate.
462
          */
463
         TEST_FFI_FAIL("encode with out-of-bounds encoding parameters should have failed",
2✔
464
                       botan_zfec_encode,
465
                       (0, 0, nullptr, 0, nullptr));
466
         TEST_FFI_FAIL("decode with out-of-bounds encoding parameters should have failed",
3✔
467
                       botan_zfec_decode,
468
                       (0, 0, nullptr, nullptr, 0, nullptr));
469
      }
5✔
470
};
471

472
class FFI_CRL_Test final : public FFI_Test {
×
473
   public:
474
      std::string name() const override { return "FFI CRL"; }
1✔
475

476
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
477
         const char* crl_string =
1✔
478
            "-----BEGIN X509 CRL-----\n"
479
            "MIICoTCCAQkCAQEwDQYJKoZIhvcNAQELBQAwgZQxLTArBgNVBAMTJFVzYWJsZSBj\n"
480
            "ZXJ0IHZhbGlkYXRpb246IFRlbXBvcmFyeSBDQTE5MDcGA1UECxMwQ2VudHJlIGZv\n"
481
            "ciBSZXNlYXJjaCBvbiBDcnlwdG9ncmFwaHkgYW5kIFNlY3VyaXR5MRswGQYDVQQK\n"
482
            "ExJNYXNhcnlrIFVuaXZlcnNpdHkxCzAJBgNVBAYTAkNaGA8yMDUwMDIyNTE1MjE0\n"
483
            "MloYDzIwNTAwMjI1MTUyNDQxWjAAoDowODAfBgNVHSMEGDAWgBRKzxAvI4+rVVo/\n"
484
            "JzLigRznREyB+TAVBgNVHRQEDgIMXcr16yNys/gjeuCFMA0GCSqGSIb3DQEBCwUA\n"
485
            "A4IBgQCfxv/5REM/KUnzeVycph3dJr1Yrtxhc6pZmQ9pMzSW/nawLN3rUHm5oG44\n"
486
            "ZuQgjvzE4PnbU0/DNRu/4w3H58kgrctJHHXbbvkU3lf2ZZLh2wBl+EUh92+/COow\n"
487
            "ZyGB+jqj/XwB99hYUhrY6NLEWRz08kpgG6dnNMEU0uFqdQKWk0CQPnmgPRgDb8BW\n"
488
            "IuMBcjY7aF9XoCZFOqPYdEvUKzAo4QGCf7uJ7fNGS3LqvjaLjAHJseSr5/yR7Q9r\n"
489
            "nEdI38yKPbRj0tNHe7j+BbYg31C+X+AZZKJtlTg8GxYR3qfQio1kDgpZ3rQLzHY3\n"
490
            "ea2MLX/Kdx9cPSwh4KwlcDxQmQKoELb4EnZW1CScSBHi9HQyCBNyCkgkOBMGcJqz\n"
491
            "Ihq1dGeSf8eca9+Avk5kAQ3yjXK1TI2CDEi0msrXLr9XbgowXiOLLzR+rYkhQz+V\n"
492
            "RnIoBwjnrGoJoz636KS170SZCB9ARNs17WE4IvbJdZrTXNOGaVZCQUUpiLRj4ZSO\n"
493
            "Na/nobI=\n"
494
            "-----END X509 CRL-----";
495

496
         botan_x509_crl_t bytecrl;
1✔
497
         if(!TEST_FFI_INIT(botan_x509_crl_load, (&bytecrl, reinterpret_cast<const uint8_t*>(crl_string), 966))) {
2✔
498
            return;
×
499
         }
500

501
         botan_x509_crl_t crl;
1✔
502
         REQUIRE_FFI_OK(botan_x509_crl_load_file, (&crl, Test::data_file("x509/nist/root.crl").c_str()));
4✔
503

504
         botan_x509_cert_t cert1;
1✔
505
         REQUIRE_FFI_OK(botan_x509_cert_load_file, (&cert1, Test::data_file("x509/nist/test01/end.crt").c_str()));
4✔
506
         TEST_FFI_RC(-1, botan_x509_is_revoked, (crl, cert1));
1✔
507
         TEST_FFI_OK(botan_x509_cert_destroy, (cert1));
1✔
508

509
         botan_x509_cert_t cert2;
1✔
510
         REQUIRE_FFI_OK(botan_x509_cert_load_file, (&cert2, Test::data_file("x509/nist/test20/int.crt").c_str()));
4✔
511
         TEST_FFI_RC(0, botan_x509_is_revoked, (crl, cert2));
1✔
512
         TEST_FFI_RC(-1, botan_x509_is_revoked, (bytecrl, cert2));
1✔
513
         TEST_FFI_OK(botan_x509_cert_destroy, (cert2));
1✔
514

515
         TEST_FFI_OK(botan_x509_crl_destroy, (crl));
1✔
516
         TEST_FFI_OK(botan_x509_crl_destroy, (bytecrl));
2✔
517
      }
518
};
519

520
class FFI_Cert_Validation_Test final : public FFI_Test {
×
521
   public:
522
      std::string name() const override { return "FFI Cert Validation"; }
1✔
523

524
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
525
         botan_x509_cert_t root;
1✔
526
         int rc;
1✔
527

528
         if(!TEST_FFI_INIT(botan_x509_cert_load_file, (&root, Test::data_file("x509/nist/root.crt").c_str()))) {
4✔
529
            return;
×
530
         }
531

532
         botan_x509_cert_t end2;
1✔
533
         botan_x509_cert_t sub2;
1✔
534
         REQUIRE_FFI_OK(botan_x509_cert_load_file, (&end2, Test::data_file("x509/nist/test02/end.crt").c_str()));
4✔
535
         REQUIRE_FFI_OK(botan_x509_cert_load_file, (&sub2, Test::data_file("x509/nist/test02/int.crt").c_str()));
4✔
536

537
         TEST_FFI_RC(1, botan_x509_cert_verify, (&rc, end2, &sub2, 1, &root, 1, nullptr, 0, nullptr, 0));
1✔
538
         result.confirm("Validation failed", rc == 5002);
2✔
539
         result.test_eq("Validation status string", botan_x509_cert_validation_status(rc), "Signature error");
1✔
540

541
         TEST_FFI_RC(1, botan_x509_cert_verify, (&rc, end2, nullptr, 0, &root, 1, nullptr, 0, nullptr, 0));
1✔
542
         result.confirm("Validation failed", rc == 3000);
2✔
543
         result.test_eq(
1✔
544
            "Validation status string", botan_x509_cert_validation_status(rc), "Certificate issuer not found");
545

546
         botan_x509_cert_t end7;
1✔
547
         botan_x509_cert_t sub7;
1✔
548
         REQUIRE_FFI_OK(botan_x509_cert_load_file, (&end7, Test::data_file("x509/nist/test07/end.crt").c_str()));
4✔
549
         REQUIRE_FFI_OK(botan_x509_cert_load_file, (&sub7, Test::data_file("x509/nist/test07/int.crt").c_str()));
4✔
550

551
         botan_x509_cert_t subs[2] = {sub2, sub7};
1✔
552
         TEST_FFI_RC(1, botan_x509_cert_verify, (&rc, end7, subs, 2, &root, 1, nullptr, 0, nullptr, 0));
1✔
553
         result.confirm("Validation failed", rc == 1001);
2✔
554
         result.test_eq("Validation status string",
1✔
555
                        botan_x509_cert_validation_status(rc),
556
                        "Hash function used is considered too weak for security");
557

558
         TEST_FFI_RC(0, botan_x509_cert_verify, (&rc, end7, subs, 2, &root, 1, nullptr, 80, nullptr, 0));
1✔
559
         result.confirm("Validation passed", rc == 0);
2✔
560
         result.test_eq("Validation status string", botan_x509_cert_validation_status(rc), "Verified");
1✔
561

562
         TEST_FFI_RC(1,
1✔
563
                     botan_x509_cert_verify_with_crl,
564
                     (&rc, end7, subs, 2, nullptr, 0, nullptr, 0, "x509/farce", 0, nullptr, 0));
565
         result.confirm("Validation failed", rc == 3000);
2✔
566
         result.test_eq(
1✔
567
            "Validation status string", botan_x509_cert_validation_status(rc), "Certificate issuer not found");
568

569
         botan_x509_crl_t rootcrl;
1✔
570

571
         REQUIRE_FFI_OK(botan_x509_crl_load_file, (&rootcrl, Test::data_file("x509/nist/root.crl").c_str()));
4✔
572
         TEST_FFI_RC(
1✔
573
            0, botan_x509_cert_verify_with_crl, (&rc, end7, subs, 2, &root, 1, &rootcrl, 1, nullptr, 80, nullptr, 0));
574
         result.confirm("Validation passed", rc == 0);
2✔
575
         result.test_eq("Validation status string", botan_x509_cert_validation_status(rc), "Verified");
1✔
576

577
         botan_x509_cert_t end20;
1✔
578
         botan_x509_cert_t sub20;
1✔
579
         botan_x509_crl_t sub20crl;
1✔
580
         REQUIRE_FFI_OK(botan_x509_cert_load_file, (&end20, Test::data_file("x509/nist/test20/end.crt").c_str()));
4✔
581
         REQUIRE_FFI_OK(botan_x509_cert_load_file, (&sub20, Test::data_file("x509/nist/test20/int.crt").c_str()));
4✔
582
         REQUIRE_FFI_OK(botan_x509_crl_load_file, (&sub20crl, Test::data_file("x509/nist/test20/int.crl").c_str()));
4✔
583
         botan_x509_crl_t crls[2] = {sub20crl, rootcrl};
1✔
584
         TEST_FFI_RC(
1✔
585
            1, botan_x509_cert_verify_with_crl, (&rc, end20, &sub20, 1, &root, 1, crls, 2, nullptr, 80, nullptr, 0));
586
         result.confirm("Validation failed", rc == 5000);
2✔
587
         result.test_eq("Validation status string", botan_x509_cert_validation_status(rc), "Certificate is revoked");
1✔
588

589
         TEST_FFI_OK(botan_x509_cert_destroy, (end2));
1✔
590
         TEST_FFI_OK(botan_x509_cert_destroy, (sub2));
1✔
591
         TEST_FFI_OK(botan_x509_cert_destroy, (end7));
1✔
592
         TEST_FFI_OK(botan_x509_cert_destroy, (sub7));
1✔
593
         TEST_FFI_OK(botan_x509_cert_destroy, (end20));
1✔
594
         TEST_FFI_OK(botan_x509_cert_destroy, (sub20));
1✔
595
         TEST_FFI_OK(botan_x509_crl_destroy, (sub20crl));
1✔
596
         TEST_FFI_OK(botan_x509_cert_destroy, (root));
1✔
597
         TEST_FFI_OK(botan_x509_crl_destroy, (rootcrl));
2✔
598
      }
599
};
600

601
class FFI_ECDSA_Certificate_Test final : public FFI_Test {
×
602
   public:
603
      std::string name() const override { return "FFI ECDSA cert"; }
1✔
604

605
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
606
         botan_x509_cert_t cert;
1✔
607
         if(TEST_FFI_INIT(botan_x509_cert_load_file,
4✔
608
                          (&cert, Test::data_file("x509/ecc/CSCA.CSCA.csca-germany.1.crt").c_str()))) {
609
            size_t date_len = 0;
1✔
610
            TEST_FFI_RC(
1✔
611
               BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_get_time_starts, (cert, nullptr, &date_len));
612

613
            date_len = 8;
1✔
614
            TEST_FFI_RC(
1✔
615
               BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_get_time_starts, (cert, nullptr, &date_len));
616

617
            std::string date(date_len - 1, '0');
1✔
618
            TEST_FFI_OK(botan_x509_cert_get_time_starts, (cert, &date[0], &date_len));
1✔
619
            result.test_eq("cert valid from", date, "070719152718Z");
2✔
620

621
            date_len = 0;
1✔
622
            TEST_FFI_RC(
1✔
623
               BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_get_time_expires, (cert, nullptr, &date_len));
624

625
            date.resize(date_len - 1);
1✔
626
            TEST_FFI_OK(botan_x509_cert_get_time_expires, (cert, &date[0], &date_len));
1✔
627
            result.test_eq("cert valid until", date, "280119151800Z");
2✔
628

629
            uint64_t not_before = 0;
1✔
630
            TEST_FFI_OK(botan_x509_cert_not_before, (cert, &not_before));
1✔
631
            result.confirm("cert not before", not_before == 1184858838);
2✔
632

633
            uint64_t not_after = 0;
1✔
634
            TEST_FFI_OK(botan_x509_cert_not_after, (cert, &not_after));
1✔
635
            result.confirm("cert not after", not_after == 1831907880);
2✔
636

637
            size_t serial_len = 0;
1✔
638
            TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
1✔
639
                        botan_x509_cert_get_serial_number,
640
                        (cert, nullptr, &serial_len));
641

642
            std::vector<uint8_t> serial(serial_len);
1✔
643
            TEST_FFI_OK(botan_x509_cert_get_serial_number, (cert, serial.data(), &serial_len));
1✔
644
            result.test_eq("cert serial length", serial.size(), 1);
1✔
645
            result.test_int_eq(serial[0], 1, "cert serial");
1✔
646

647
            size_t fingerprint_len = 0;
1✔
648
            TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
1✔
649
                        botan_x509_cert_get_fingerprint,
650
                        (cert, "SHA-256", nullptr, &fingerprint_len));
651

652
            std::vector<uint8_t> fingerprint(fingerprint_len);
1✔
653
            TEST_FFI_OK(botan_x509_cert_get_fingerprint, (cert, "SHA-256", fingerprint.data(), &fingerprint_len));
1✔
654
            result.test_eq(
1✔
655
               "cert fingerprint",
656
               reinterpret_cast<const char*>(fingerprint.data()),
1✔
657
               "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");
658

659
            size_t key_id_len = 0;
1✔
660
            TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
1✔
661
                        botan_x509_cert_get_authority_key_id,
662
                        (cert, nullptr, &key_id_len));
663

664
            std::vector<uint8_t> key_id(key_id_len);
1✔
665
            TEST_FFI_OK(botan_x509_cert_get_authority_key_id, (cert, key_id.data(), &key_id_len));
1✔
666
            result.test_eq("cert authority key id",
3✔
667
                           Botan::hex_encode(key_id.data(), key_id.size(), true),
2✔
668
                           "0096452DE588F966C4CCDF161DD1F3F5341B71E7");
669

670
            key_id_len = 0;
1✔
671
            TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
1✔
672
                        botan_x509_cert_get_subject_key_id,
673
                        (cert, nullptr, &key_id_len));
674

675
            key_id.resize(key_id_len);
1✔
676
            TEST_FFI_OK(botan_x509_cert_get_subject_key_id, (cert, key_id.data(), &key_id_len));
1✔
677
            result.test_eq("cert subject key id",
3✔
678
                           Botan::hex_encode(key_id.data(), key_id.size(), true),
2✔
679
                           "0096452DE588F966C4CCDF161DD1F3F5341B71E7");
680

681
            size_t pubkey_len = 0;
1✔
682
            TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
1✔
683
                        botan_x509_cert_get_public_key_bits,
684
                        (cert, nullptr, &pubkey_len));
685

686
            std::vector<uint8_t> pubkey(pubkey_len);
1✔
687
            TEST_FFI_OK(botan_x509_cert_get_public_key_bits, (cert, pubkey.data(), &pubkey_len));
1✔
688

689
            botan_pubkey_t pub;
1✔
690
            if(TEST_FFI_OK(botan_x509_cert_get_public_key, (cert, &pub))) {
2✔
691
               TEST_FFI_OK(botan_pubkey_destroy, (pub));
2✔
692
            }
693

694
            size_t dn_len = 0;
1✔
695
            TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
1✔
696
                        botan_x509_cert_get_issuer_dn,
697
                        (cert, "Name", 0, nullptr, &dn_len));
698

699
            std::vector<uint8_t> dn(dn_len);
1✔
700
            TEST_FFI_OK(botan_x509_cert_get_issuer_dn, (cert, "Name", 0, dn.data(), &dn_len));
1✔
701
            result.test_eq("issuer dn", reinterpret_cast<const char*>(dn.data()), "csca-germany");
1✔
702

703
            dn_len = 0;
1✔
704
            TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
1✔
705
                        botan_x509_cert_get_subject_dn,
706
                        (cert, "Name", 0, nullptr, &dn_len));
707

708
            dn.resize(dn_len);
1✔
709
            TEST_FFI_OK(botan_x509_cert_get_subject_dn, (cert, "Name", 0, dn.data(), &dn_len));
1✔
710
            result.test_eq("subject dn", reinterpret_cast<const char*>(dn.data()), "csca-germany");
1✔
711

712
            size_t printable_len = 0;
1✔
713
            TEST_FFI_RC(
1✔
714
               BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_to_string, (cert, nullptr, &printable_len));
715

716
            std::string printable(printable_len - 1, '0');
1✔
717
            TEST_FFI_OK(botan_x509_cert_to_string, (cert, &printable[0], &printable_len));
1✔
718

719
            TEST_FFI_RC(0, botan_x509_cert_allowed_usage, (cert, KEY_CERT_SIGN));
1✔
720
            TEST_FFI_RC(0, botan_x509_cert_allowed_usage, (cert, CRL_SIGN));
1✔
721
            TEST_FFI_RC(1, botan_x509_cert_allowed_usage, (cert, DIGITAL_SIGNATURE));
1✔
722

723
            TEST_FFI_OK(botan_x509_cert_destroy, (cert));
2✔
724
         }
6✔
725
      }
1✔
726
};
727

728
class FFI_PKCS_Hashid_Test final : public FFI_Test {
×
729
   public:
730
      std::string name() const override { return "FFI PKCS hash id"; }
1✔
731

732
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
733
         std::vector<uint8_t> hash_id(64);
1✔
734
         size_t hash_id_len = hash_id.size();
1✔
735

736
         if(TEST_FFI_INIT(botan_pkcs_hash_id, ("SHA-256", hash_id.data(), &hash_id_len))) {
2✔
737
            result.test_eq("Expected SHA-256 PKCS hash id len", hash_id_len, 19);
1✔
738

739
            hash_id.resize(hash_id_len);
1✔
740
            result.test_eq("Expected SHA_256 PKCS hash id", hash_id, "3031300D060960864801650304020105000420");
1✔
741

742
            hash_id_len = 3;  // too short
1✔
743
            TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
2✔
744
                        botan_pkcs_hash_id,
745
                        ("SHA-256", hash_id.data(), &hash_id_len));
746
         }
747
      }
1✔
748
};
749

750
class FFI_CBC_Cipher_Test final : public FFI_Test {
×
751
   public:
752
      std::string name() const override { return "FFI CBC cipher"; }
1✔
753

754
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
755
         botan_cipher_t cipher_encrypt, cipher_decrypt;
1✔
756

757
         if(TEST_FFI_INIT(botan_cipher_init, (&cipher_encrypt, "AES-128/CBC/PKCS7", BOTAN_CIPHER_INIT_FLAG_ENCRYPT))) {
2✔
758
            size_t min_keylen = 0;
1✔
759
            size_t max_keylen = 0;
1✔
760
            TEST_FFI_OK(botan_cipher_query_keylen, (cipher_encrypt, &min_keylen, &max_keylen));
1✔
761
            result.test_int_eq(min_keylen, 16, "Min key length");
1✔
762
            result.test_int_eq(max_keylen, 16, "Max key length");
1✔
763

764
            // from https://github.com/geertj/bluepass/blob/master/tests/vectors/aes-cbc-pkcs7.txt
765
            const std::vector<uint8_t> plaintext =
1✔
766
               Botan::hex_decode("0397f4f6820b1f9386f14403be5ac16e50213bd473b4874b9bcbf5f318ee686b1d");
1✔
767
            const std::vector<uint8_t> symkey = Botan::hex_decode("898be9cc5004ed0fa6e117c9a3099d31");
1✔
768
            const std::vector<uint8_t> nonce = Botan::hex_decode("9dea7621945988f96491083849b068df");
1✔
769
            const std::vector<uint8_t> exp_ciphertext = Botan::hex_decode(
1✔
770
               "e232cd6ef50047801ee681ec30f61d53cfd6b0bca02fd03c1b234baa10ea82ac9dab8b960926433a19ce6dea08677e34");
1✔
771

772
            size_t output_written = 0;
1✔
773
            size_t input_consumed = 0;
1✔
774

775
            // Test that after clear or final the object can be reused
776
            for(size_t r = 0; r != 2; ++r) {
3✔
777
               size_t ctext_len;
2✔
778
               TEST_FFI_OK(botan_cipher_output_length, (cipher_encrypt, plaintext.size(), &ctext_len));
2✔
779
               result.test_eq("Expected size of padded message", ctext_len, plaintext.size() + 15);
2✔
780
               std::vector<uint8_t> ciphertext(ctext_len);
2✔
781

782
               TEST_FFI_OK(botan_cipher_set_key, (cipher_encrypt, symkey.data(), symkey.size()));
2✔
783
               TEST_FFI_OK(botan_cipher_start, (cipher_encrypt, nonce.data(), nonce.size()));
2✔
784
               TEST_FFI_OK(botan_cipher_update,
2✔
785
                           (cipher_encrypt,
786
                            0,
787
                            ciphertext.data(),
788
                            ciphertext.size(),
789
                            &output_written,
790
                            plaintext.data(),
791
                            plaintext.size(),
792
                            &input_consumed));
793
               TEST_FFI_OK(botan_cipher_clear, (cipher_encrypt));
2✔
794

795
               TEST_FFI_OK(botan_cipher_set_key, (cipher_encrypt, symkey.data(), symkey.size()));
2✔
796
               TEST_FFI_OK(botan_cipher_start, (cipher_encrypt, nonce.data(), nonce.size()));
2✔
797
               TEST_FFI_OK(botan_cipher_update,
2✔
798
                           (cipher_encrypt,
799
                            BOTAN_CIPHER_UPDATE_FLAG_FINAL,
800
                            ciphertext.data(),
801
                            ciphertext.size(),
802
                            &output_written,
803
                            plaintext.data(),
804
                            plaintext.size(),
805
                            &input_consumed));
806

807
               ciphertext.resize(output_written);
2✔
808
               result.test_eq("AES/CBC ciphertext", ciphertext, exp_ciphertext);
2✔
809

810
               if(TEST_FFI_OK(botan_cipher_init, (&cipher_decrypt, "AES-128/CBC", BOTAN_CIPHER_INIT_FLAG_DECRYPT))) {
4✔
811
                  size_t ptext_len;
2✔
812
                  TEST_FFI_OK(botan_cipher_output_length, (cipher_decrypt, ciphertext.size(), &ptext_len));
2✔
813
                  std::vector<uint8_t> decrypted(ptext_len);
2✔
814

815
                  TEST_FFI_OK(botan_cipher_set_key, (cipher_decrypt, symkey.data(), symkey.size()));
2✔
816
                  TEST_FFI_OK(botan_cipher_start, (cipher_decrypt, nonce.data(), nonce.size()));
2✔
817
                  TEST_FFI_OK(botan_cipher_update,
2✔
818
                              (cipher_decrypt,
819
                               BOTAN_CIPHER_UPDATE_FLAG_FINAL,
820
                               decrypted.data(),
821
                               decrypted.size(),
822
                               &output_written,
823
                               ciphertext.data(),
824
                               ciphertext.size(),
825
                               &input_consumed));
826

827
                  decrypted.resize(output_written);
2✔
828

829
                  result.test_eq("AES/CBC plaintext", decrypted, plaintext);
2✔
830

831
                  TEST_FFI_OK(botan_cipher_destroy, (cipher_decrypt));
4✔
832
               }
2✔
833
            }
2✔
834

835
            TEST_FFI_OK(botan_cipher_destroy, (cipher_encrypt));
2✔
836
         }
4✔
837
      }
1✔
838
};
839

840
class FFI_GCM_Test final : public FFI_Test {
×
841
   public:
842
      std::string name() const override { return "FFI GCM"; }
1✔
843

844
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
845
         botan_cipher_t cipher_encrypt, cipher_decrypt;
1✔
846

847
         if(TEST_FFI_INIT(botan_cipher_init, (&cipher_encrypt, "AES-128/GCM", BOTAN_CIPHER_INIT_FLAG_ENCRYPT))) {
2✔
848
            char namebuf[18];
1✔
849
            size_t name_len = 15;
1✔
850
            TEST_FFI_FAIL("output buffer too short", botan_cipher_name, (cipher_encrypt, namebuf, &name_len));
2✔
851
            result.test_eq("name len", name_len, 16);
1✔
852

853
            name_len = sizeof(namebuf);
1✔
854
            if(TEST_FFI_OK(botan_cipher_name, (cipher_encrypt, namebuf, &name_len))) {
2✔
855
               result.test_eq("name len", name_len, 16);
1✔
856
               result.test_eq("name", std::string(namebuf), "AES-128/GCM(16)");
2✔
857
            }
858

859
            size_t min_keylen = 0;
1✔
860
            size_t max_keylen = 0;
1✔
861
            size_t nonce_len = 0;
1✔
862
            size_t tag_len = 0;
1✔
863

864
            TEST_FFI_OK(botan_cipher_query_keylen, (cipher_encrypt, &min_keylen, &max_keylen));
1✔
865
            result.test_int_eq(min_keylen, 16, "Min key length");
1✔
866
            result.test_int_eq(max_keylen, 16, "Max key length");
1✔
867

868
            TEST_FFI_OK(botan_cipher_get_default_nonce_length, (cipher_encrypt, &nonce_len));
1✔
869
            result.test_int_eq(nonce_len, 12, "Expected default GCM nonce length");
1✔
870

871
            TEST_FFI_OK(botan_cipher_get_tag_length, (cipher_encrypt, &tag_len));
1✔
872
            result.test_int_eq(tag_len, 16, "Expected GCM tag length");
1✔
873

874
            TEST_FFI_RC(1, botan_cipher_valid_nonce_length, (cipher_encrypt, 12));
1✔
875
            // GCM accepts any nonce size except zero
876
            TEST_FFI_RC(0, botan_cipher_valid_nonce_length, (cipher_encrypt, 0));
1✔
877
            TEST_FFI_RC(1, botan_cipher_valid_nonce_length, (cipher_encrypt, 1));
1✔
878
            TEST_FFI_RC(1, botan_cipher_valid_nonce_length, (cipher_encrypt, 100009));
1✔
879

880
            // NIST test vector
881
            const std::vector<uint8_t> plaintext = Botan::hex_decode(
1✔
882
               "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39");
1✔
883

884
            const std::vector<uint8_t> symkey = Botan::hex_decode("FEFFE9928665731C6D6A8F9467308308");
1✔
885
            const std::vector<uint8_t> nonce = Botan::hex_decode("CAFEBABEFACEDBADDECAF888");
1✔
886
            const std::vector<uint8_t> exp_ciphertext = Botan::hex_decode(
1✔
887
               "42831EC2217774244B7221B784D0D49CE3AA212F2C02A4E035C17E2329ACA12E21D514B25466931C7D8F6A5AAC84AA051BA30B396A0AAC973D58E0915BC94FBC3221A5DB94FAE95AE7121A47");
1✔
888
            const std::vector<uint8_t> aad = Botan::hex_decode("FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2");
1✔
889

890
            std::vector<uint8_t> ciphertext(tag_len + plaintext.size());
1✔
891

892
            size_t output_written = 0;
1✔
893
            size_t input_consumed = 0;
1✔
894

895
            // Test that after clear or final the object can be reused
896
            for(size_t r = 0; r != 2; ++r) {
3✔
897
               TEST_FFI_OK(botan_cipher_set_key, (cipher_encrypt, symkey.data(), symkey.size()));
2✔
898

899
               // First use a nonce of the AAD, and ensure reset works
900
               TEST_FFI_OK(botan_cipher_start, (cipher_encrypt, aad.data(), aad.size()));
2✔
901
               TEST_FFI_OK(botan_cipher_reset, (cipher_encrypt));
2✔
902

903
               TEST_FFI_OK(botan_cipher_start, (cipher_encrypt, nonce.data(), nonce.size()));
2✔
904
               TEST_FFI_OK(botan_cipher_update,
2✔
905
                           (cipher_encrypt,
906
                            0,
907
                            ciphertext.data(),
908
                            ciphertext.size(),
909
                            &output_written,
910
                            plaintext.data(),
911
                            plaintext.size(),
912
                            &input_consumed));
913
               TEST_FFI_OK(botan_cipher_clear, (cipher_encrypt));
2✔
914

915
               TEST_FFI_OK(botan_cipher_set_key, (cipher_encrypt, symkey.data(), symkey.size()));
2✔
916
               TEST_FFI_OK(botan_cipher_set_associated_data, (cipher_encrypt, aad.data(), aad.size()));
2✔
917
               TEST_FFI_OK(botan_cipher_start, (cipher_encrypt, nonce.data(), nonce.size()));
2✔
918
               TEST_FFI_OK(botan_cipher_update,
2✔
919
                           (cipher_encrypt,
920
                            BOTAN_CIPHER_UPDATE_FLAG_FINAL,
921
                            ciphertext.data(),
922
                            ciphertext.size(),
923
                            &output_written,
924
                            plaintext.data(),
925
                            plaintext.size(),
926
                            &input_consumed));
927

928
               ciphertext.resize(output_written);
2✔
929
               result.test_eq("AES/GCM ciphertext", ciphertext, exp_ciphertext);
2✔
930

931
               if(TEST_FFI_OK(botan_cipher_init, (&cipher_decrypt, "AES-128/GCM", BOTAN_CIPHER_INIT_FLAG_DECRYPT))) {
4✔
932
                  std::vector<uint8_t> decrypted(plaintext.size());
2✔
933

934
                  TEST_FFI_OK(botan_cipher_set_key, (cipher_decrypt, symkey.data(), symkey.size()));
2✔
935
                  TEST_FFI_OK(botan_cipher_set_associated_data, (cipher_decrypt, aad.data(), aad.size()));
2✔
936
                  TEST_FFI_OK(botan_cipher_start, (cipher_decrypt, nonce.data(), nonce.size()));
2✔
937
                  TEST_FFI_OK(botan_cipher_update,
2✔
938
                              (cipher_decrypt,
939
                               BOTAN_CIPHER_UPDATE_FLAG_FINAL,
940
                               decrypted.data(),
941
                               decrypted.size(),
942
                               &output_written,
943
                               ciphertext.data(),
944
                               ciphertext.size(),
945
                               &input_consumed));
946

947
                  result.test_int_eq(input_consumed, ciphertext.size(), "All input consumed");
2✔
948
                  result.test_int_eq(output_written, decrypted.size(), "Expected output size produced");
2✔
949
                  result.test_eq("AES/GCM plaintext", decrypted, plaintext);
2✔
950

951
                  TEST_FFI_OK(botan_cipher_destroy, (cipher_decrypt));
4✔
952
               }
2✔
953
            }
954

955
            TEST_FFI_OK(botan_cipher_destroy, (cipher_encrypt));
2✔
956
         }
6✔
957
      }
1✔
958
};
959

960
class FFI_EAX_Test final : public FFI_Test {
×
961
   public:
962
      std::string name() const override { return "FFI EAX"; }
1✔
963

964
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
965
         botan_cipher_t cipher_encrypt, cipher_decrypt;
1✔
966

967
         if(TEST_FFI_INIT(botan_cipher_init, (&cipher_encrypt, "AES-128/EAX", BOTAN_CIPHER_INIT_FLAG_ENCRYPT))) {
2✔
968
            size_t min_keylen = 0;
1✔
969
            size_t max_keylen = 0;
1✔
970
            size_t mod_keylen = 0;
1✔
971
            size_t nonce_len = 0;
1✔
972
            size_t tag_len = 0;
1✔
973

974
            TEST_FFI_OK(botan_cipher_query_keylen, (cipher_encrypt, &min_keylen, &max_keylen));
1✔
975
            result.test_int_eq(min_keylen, 16, "Min key length");
1✔
976
            result.test_int_eq(max_keylen, 16, "Max key length");
1✔
977

978
            TEST_FFI_OK(botan_cipher_get_keyspec, (cipher_encrypt, &min_keylen, &max_keylen, &mod_keylen));
1✔
979
            result.test_int_eq(min_keylen, 16, "Min key length");
1✔
980
            result.test_int_eq(max_keylen, 16, "Max key length");
1✔
981
            result.test_int_eq(mod_keylen, 1, "Mod key length");
1✔
982

983
            TEST_FFI_OK(botan_cipher_get_default_nonce_length, (cipher_encrypt, &nonce_len));
1✔
984
            result.test_int_eq(nonce_len, 12, "Expected default EAX nonce length");
1✔
985

986
            TEST_FFI_OK(botan_cipher_get_tag_length, (cipher_encrypt, &tag_len));
1✔
987
            result.test_int_eq(tag_len, 16, "Expected EAX tag length");
1✔
988

989
            TEST_FFI_RC(1, botan_cipher_valid_nonce_length, (cipher_encrypt, 12));
1✔
990
            // EAX accepts any nonce size...
991
            TEST_FFI_RC(1, botan_cipher_valid_nonce_length, (cipher_encrypt, 0));
1✔
992

993
            const std::vector<uint8_t> plaintext =
1✔
994
               Botan::hex_decode("0000000000000000000000000000000011111111111111111111111111111111");
1✔
995
            const std::vector<uint8_t> symkey = Botan::hex_decode("000102030405060708090a0b0c0d0e0f");
1✔
996
            const std::vector<uint8_t> nonce = Botan::hex_decode("3c8cc2970a008f75cc5beae2847258c2");
1✔
997
            const std::vector<uint8_t> exp_ciphertext = Botan::hex_decode(
1✔
998
               "3c441f32ce07822364d7a2990e50bb13d7b02a26969e4a937e5e9073b0d9c968db90bdb3da3d00afd0fc6a83551da95e");
1✔
999

1000
            std::vector<uint8_t> ciphertext(tag_len + plaintext.size());
1✔
1001

1002
            size_t output_written = 0;
1✔
1003
            size_t input_consumed = 0;
1✔
1004

1005
            // Test that after clear or final the object can be reused
1006
            for(size_t r = 0; r != 2; ++r) {
3✔
1007
               TEST_FFI_OK(botan_cipher_set_key, (cipher_encrypt, symkey.data(), symkey.size()));
2✔
1008
               TEST_FFI_OK(botan_cipher_start, (cipher_encrypt, nonce.data(), nonce.size()));
2✔
1009
               TEST_FFI_OK(botan_cipher_update,
2✔
1010
                           (cipher_encrypt,
1011
                            0,
1012
                            ciphertext.data(),
1013
                            ciphertext.size(),
1014
                            &output_written,
1015
                            plaintext.data(),
1016
                            plaintext.size(),
1017
                            &input_consumed));
1018
               TEST_FFI_OK(botan_cipher_clear, (cipher_encrypt));
2✔
1019

1020
               TEST_FFI_OK(botan_cipher_set_key, (cipher_encrypt, symkey.data(), symkey.size()));
2✔
1021
               TEST_FFI_OK(botan_cipher_start, (cipher_encrypt, nonce.data(), nonce.size()));
2✔
1022
               TEST_FFI_OK(botan_cipher_update,
2✔
1023
                           (cipher_encrypt,
1024
                            BOTAN_CIPHER_UPDATE_FLAG_FINAL,
1025
                            ciphertext.data(),
1026
                            ciphertext.size(),
1027
                            &output_written,
1028
                            plaintext.data(),
1029
                            plaintext.size(),
1030
                            &input_consumed));
1031

1032
               ciphertext.resize(output_written);
2✔
1033
               result.test_eq("AES/EAX ciphertext", ciphertext, exp_ciphertext);
2✔
1034

1035
               if(TEST_FFI_OK(botan_cipher_init, (&cipher_decrypt, "AES-128/EAX", BOTAN_CIPHER_INIT_FLAG_DECRYPT))) {
4✔
1036
                  std::vector<uint8_t> decrypted(plaintext.size());
2✔
1037

1038
                  TEST_FFI_OK(botan_cipher_set_key, (cipher_decrypt, symkey.data(), symkey.size()));
2✔
1039
                  TEST_FFI_OK(botan_cipher_start, (cipher_decrypt, nonce.data(), nonce.size()));
2✔
1040
                  TEST_FFI_OK(botan_cipher_update,
2✔
1041
                              (cipher_decrypt,
1042
                               BOTAN_CIPHER_UPDATE_FLAG_FINAL,
1043
                               decrypted.data(),
1044
                               decrypted.size(),
1045
                               &output_written,
1046
                               ciphertext.data(),
1047
                               ciphertext.size(),
1048
                               &input_consumed));
1049

1050
                  result.test_int_eq(input_consumed, ciphertext.size(), "All input consumed");
2✔
1051
                  result.test_int_eq(output_written, decrypted.size(), "Expected output size produced");
2✔
1052
                  result.test_eq("AES/EAX plaintext", decrypted, plaintext);
2✔
1053

1054
                  TEST_FFI_OK(botan_cipher_destroy, (cipher_decrypt));
4✔
1055
               }
2✔
1056
            }
1057

1058
            TEST_FFI_OK(botan_cipher_destroy, (cipher_encrypt));
2✔
1059
         }
5✔
1060
      }
1✔
1061
};
1062

1063
class FFI_StreamCipher_Test final : public FFI_Test {
×
1064
   public:
1065
      std::string name() const override { return "FFI stream ciphers"; }
1✔
1066

1067
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
1068
         botan_cipher_t ctr;
1✔
1069

1070
         if(TEST_FFI_INIT(botan_cipher_init, (&ctr, "AES-128/CTR-BE", BOTAN_CIPHER_INIT_FLAG_ENCRYPT))) {
2✔
1071
            const std::vector<uint8_t> key = Botan::hex_decode("2B7E151628AED2A6ABF7158809CF4F3C");
1✔
1072
            const std::vector<uint8_t> nonce = Botan::hex_decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFDFF");
1✔
1073
            const std::vector<uint8_t> pt = Botan::hex_decode(
1✔
1074
               "AE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710");
1✔
1075
            const std::vector<uint8_t> exp_ct = Botan::hex_decode(
1✔
1076
               "9806F66B7970FDFF8617187BB9FFFDFF5AE4DF3EDBD5D35E5B4F09020DB03EAB1E031DDA2FBE03D1792170A0F3009CEE");
1✔
1077

1078
            std::vector<uint8_t> ct(pt.size());
1✔
1079

1080
            size_t input_consumed = 0;
1✔
1081
            size_t output_written = 0;
1✔
1082

1083
            TEST_FFI_OK(botan_cipher_set_key, (ctr, key.data(), key.size()));
1✔
1084
            TEST_FFI_OK(botan_cipher_start, (ctr, nonce.data(), nonce.size()));
1✔
1085

1086
            // Test partial updates...
1087
            TEST_FFI_OK(botan_cipher_update,
1✔
1088
                        (ctr, 0, ct.data(), ct.size(), &output_written, pt.data(), 5, &input_consumed));
1089

1090
            result.test_int_eq(output_written, 5, "Expected output written");
1✔
1091
            result.test_int_eq(input_consumed, 5, "Expected input consumed");
1✔
1092

1093
            TEST_FFI_OK(botan_cipher_update,
1✔
1094
                        (ctr, 0, &ct[5], ct.size() - 5, &output_written, &pt[5], pt.size() - 5, &input_consumed));
1095

1096
            result.test_int_eq(output_written, ct.size() - 5, "Expected output written");
1✔
1097
            result.test_int_eq(input_consumed, pt.size() - 5, "Expected input consumed");
1✔
1098
            result.test_eq("AES-128/CTR ciphertext", ct, exp_ct);
1✔
1099

1100
            TEST_FFI_OK(botan_cipher_destroy, (ctr));
2✔
1101
         }
5✔
1102
      }
1✔
1103
};
1104

1105
class FFI_HashFunction_Test final : public FFI_Test {
×
1106
   public:
1107
      std::string name() const override { return "FFI hash"; }
1✔
1108

1109
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
1110
         const char* input_str = "ABC";
1✔
1111

1112
         botan_hash_t hash;
1✔
1113
         TEST_FFI_FAIL("invalid hash name", botan_hash_init, (&hash, "SHA-255", 0));
2✔
1114
         TEST_FFI_FAIL("invalid flags", botan_hash_init, (&hash, "SHA-256", 1));
2✔
1115

1116
         if(TEST_FFI_INIT(botan_hash_init, (&hash, "SHA-256", 0))) {
1✔
1117
            char namebuf[10];
1✔
1118
            size_t name_len = 7;
1✔
1119
            TEST_FFI_FAIL("output buffer too short", botan_hash_name, (hash, namebuf, &name_len));
2✔
1120
            result.test_eq("name len", name_len, 8);
1✔
1121

1122
            name_len = sizeof(namebuf);
1✔
1123
            if(TEST_FFI_OK(botan_hash_name, (hash, namebuf, &name_len))) {
1✔
1124
               result.test_eq("name len", name_len, 8);
1✔
1125
               result.test_eq("name", std::string(namebuf), "SHA-256");
2✔
1126
            }
1127

1128
            size_t block_size;
1✔
1129
            if(TEST_FFI_OK(botan_hash_block_size, (hash, &block_size))) {
2✔
1130
               result.test_eq("hash block size", block_size, 64);
2✔
1131
            }
1132

1133
            size_t output_len;
1✔
1134
            if(TEST_FFI_OK(botan_hash_output_length, (hash, &output_len))) {
2✔
1135
               result.test_eq("hash output length", output_len, 32);
1✔
1136

1137
               std::vector<uint8_t> outbuf(output_len);
1✔
1138

1139
               // Test that after clear or final the object can be reused
1140
               for(size_t r = 0; r != 2; ++r) {
3✔
1141
                  TEST_FFI_OK(botan_hash_update, (hash, reinterpret_cast<const uint8_t*>(input_str), 1));
2✔
1142
                  TEST_FFI_OK(botan_hash_clear, (hash));
2✔
1143

1144
                  TEST_FFI_OK(botan_hash_update,
2✔
1145
                              (hash, reinterpret_cast<const uint8_t*>(input_str), std::strlen(input_str)));
1146
                  TEST_FFI_OK(botan_hash_final, (hash, outbuf.data()));
2✔
1147

1148
                  result.test_eq(
4✔
1149
                     "SHA-256 output", outbuf, "B5D4045C3F466FA91FE2CC6ABE79232A1A57CDF104F7A26E716E0A1E2789DF78");
1150
               }
1151

1152
               // Test botan_hash_copy_state
1153
               const char* msg = "message digest";
1✔
1154
               const char* expected = "F7846F55CF23E14EEBEAB5B4E1550CAD5B509E3348FBC4EFA3A1413D393CB650";
1✔
1155
               TEST_FFI_OK(botan_hash_clear, (hash));
1✔
1156
               TEST_FFI_OK(botan_hash_update, (hash, reinterpret_cast<const uint8_t*>(&msg[0]), 1));
1✔
1157
               botan_hash_t fork;
1✔
1158
               if(TEST_FFI_OK(botan_hash_copy_state, (&fork, hash))) {
2✔
1159
                  TEST_FFI_OK(botan_hash_update,
1✔
1160
                              (fork, reinterpret_cast<const uint8_t*>(&msg[1]), std::strlen(msg) - 2));
1161

1162
                  TEST_FFI_OK(botan_hash_update,
1✔
1163
                              (hash, reinterpret_cast<const uint8_t*>(&msg[1]), std::strlen(msg) - 1));
1164
                  TEST_FFI_OK(botan_hash_final, (hash, outbuf.data()));
1✔
1165
                  result.test_eq("hashing split", outbuf, expected);
1✔
1166

1167
                  TEST_FFI_OK(botan_hash_update,
1✔
1168
                              (fork, reinterpret_cast<const uint8_t*>(&msg[std::strlen(msg) - 1]), 1));
1169
                  TEST_FFI_OK(botan_hash_final, (fork, outbuf.data()));
1✔
1170
                  result.test_eq("hashing split", outbuf, expected);
1✔
1171

1172
                  TEST_FFI_OK(botan_hash_destroy, (fork));
2✔
1173
               }
1174
            }
1✔
1175

1176
            TEST_FFI_OK(botan_hash_destroy, (hash));
2✔
1177
         }
1178
      }
1✔
1179
};
1180

1181
class FFI_MAC_Test final : public FFI_Test {
×
1182
   public:
1183
      std::string name() const override { return "FFI MAC"; }
1✔
1184

1185
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
1186
         const char* input_str = "ABC";
1✔
1187

1188
         // MAC test
1189
         botan_mac_t mac;
1✔
1190
         TEST_FFI_FAIL("bad flag", botan_mac_init, (&mac, "HMAC(SHA-256)", 1));
2✔
1191
         TEST_FFI_FAIL("bad name", botan_mac_init, (&mac, "HMAC(SHA-259)", 0));
2✔
1192

1193
         if(TEST_FFI_INIT(botan_mac_init, (&mac, "HMAC(SHA-256)", 0))) {
1✔
1194
            char namebuf[16];
1✔
1195
            size_t name_len = 13;
1✔
1196
            TEST_FFI_FAIL("output buffer too short", botan_mac_name, (mac, namebuf, &name_len));
2✔
1197
            result.test_eq("name len", name_len, 14);
1✔
1198

1199
            name_len = sizeof(namebuf);
1✔
1200
            if(TEST_FFI_OK(botan_mac_name, (mac, namebuf, &name_len))) {
1✔
1201
               result.test_eq("name len", name_len, 14);
1✔
1202
               result.test_eq("name", std::string(namebuf), "HMAC(SHA-256)");
2✔
1203
            }
1204

1205
            size_t min_keylen = 0, max_keylen = 0, mod_keylen = 0;
1✔
1206
            TEST_FFI_RC(0, botan_mac_get_keyspec, (mac, nullptr, nullptr, nullptr));
1✔
1207
            TEST_FFI_RC(0, botan_mac_get_keyspec, (mac, &min_keylen, nullptr, nullptr));
1✔
1208
            TEST_FFI_RC(0, botan_mac_get_keyspec, (mac, nullptr, &max_keylen, nullptr));
1✔
1209
            TEST_FFI_RC(0, botan_mac_get_keyspec, (mac, nullptr, nullptr, &mod_keylen));
1✔
1210

1211
            result.test_eq("Expected min keylen", min_keylen, 0);
1✔
1212
            result.test_eq("Expected max keylen", max_keylen, 4096);
1✔
1213
            result.test_eq("Expected mod keylen", mod_keylen, 1);
1✔
1214

1215
            size_t output_len;
1✔
1216
            if(TEST_FFI_OK(botan_mac_output_length, (mac, &output_len))) {
2✔
1217
               result.test_eq("MAC output length", output_len, 32);
1✔
1218

1219
               const uint8_t mac_key[] = {0xAA, 0xBB, 0xCC, 0xDD};
1✔
1220
               std::vector<uint8_t> outbuf(output_len);
1✔
1221

1222
               // Test that after clear or final the object can be reused
1223
               for(size_t r = 0; r != 2; ++r) {
3✔
1224
                  TEST_FFI_OK(botan_mac_set_key, (mac, mac_key, sizeof(mac_key)));
2✔
1225
                  TEST_FFI_OK(botan_mac_update,
2✔
1226
                              (mac, reinterpret_cast<const uint8_t*>(input_str), std::strlen(input_str)));
1227
                  TEST_FFI_OK(botan_mac_clear, (mac));
2✔
1228

1229
                  TEST_FFI_OK(botan_mac_set_key, (mac, mac_key, sizeof(mac_key)));
2✔
1230
                  TEST_FFI_OK(botan_mac_update,
2✔
1231
                              (mac, reinterpret_cast<const uint8_t*>(input_str), std::strlen(input_str)));
1232
                  TEST_FFI_OK(botan_mac_final, (mac, outbuf.data()));
2✔
1233

1234
                  result.test_eq(
4✔
1235
                     "HMAC output", outbuf, "1A82EEA984BC4A7285617CC0D05F1FE1D6C96675924A81BC965EE8FF7B0697A7");
1236
               }
1237
            }
1✔
1238

1239
            TEST_FFI_OK(botan_mac_destroy, (mac));
2✔
1240
         }
1241
      }
1✔
1242
};
1243

1244
class FFI_Scrypt_Test final : public FFI_Test {
×
1245
   public:
1246
      std::string name() const override { return "FFI Scrypt"; }
1✔
1247

1248
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
1249
         std::vector<uint8_t> output(24);
1✔
1250
         const uint8_t salt[8] = {0};
1✔
1251
         const char* pass = "password";
1✔
1252

1253
         if(TEST_FFI_INIT(botan_scrypt, (output.data(), output.size(), pass, salt, sizeof(salt), 8, 1, 1))) {
1✔
1254
            result.test_eq("scrypt output", output, "4B9B888D695288E002CC4F9D90808A4D296A45CE4471AFBB");
1✔
1255

1256
            size_t N, r, p;
1✔
1257
            TEST_FFI_OK(botan_pwdhash_timed,
1✔
1258
                        ("Scrypt", 50, &r, &p, &N, output.data(), output.size(), "bunny", 5, salt, sizeof(salt)));
1259

1260
            std::vector<uint8_t> cmp(output.size());
1✔
1261

1262
            TEST_FFI_OK(botan_pwdhash, ("Scrypt", N, r, p, cmp.data(), cmp.size(), "bunny", 5, salt, sizeof(salt)));
1✔
1263
            result.test_eq("recomputed scrypt", cmp, output);
2✔
1264
         }
1✔
1265
      }
1✔
1266
};
1267

1268
class FFI_KDF_Test final : public FFI_Test {
×
1269
   public:
1270
      std::string name() const override { return "FFI KDF"; }
1✔
1271

1272
      void ffi_test(Test::Result& result, botan_rng_t rng) override {
1✔
1273
         std::vector<uint8_t> outbuf;
1✔
1274

1275
         const std::string passphrase = "ltexmfeyylmlbrsyikaw";
1✔
1276

1277
         const std::vector<uint8_t> pbkdf_salt = Botan::hex_decode("ED1F39A0A7F3889AAF7E60743B3BC1CC2C738E60");
1✔
1278
         const size_t pbkdf_out_len = 10;
1✔
1279
         const size_t pbkdf_iterations = 1000;
1✔
1280

1281
         outbuf.resize(pbkdf_out_len);
1✔
1282

1283
         if(TEST_FFI_INIT(botan_pbkdf,
1✔
1284
                          ("PBKDF2(SHA-1)",
1285
                           outbuf.data(),
1286
                           outbuf.size(),
1287
                           passphrase.c_str(),
1288
                           pbkdf_salt.data(),
1289
                           pbkdf_salt.size(),
1290
                           pbkdf_iterations))) {
1291
            result.test_eq("PBKDF output", outbuf, "027AFADD48F4BE8DCC4F");
1✔
1292

1293
            size_t iters_10ms, iters_100ms;
1✔
1294

1295
            TEST_FFI_OK(botan_pbkdf_timed,
1✔
1296
                        ("PBKDF2(SHA-1)",
1297
                         outbuf.data(),
1298
                         outbuf.size(),
1299
                         passphrase.c_str(),
1300
                         pbkdf_salt.data(),
1301
                         pbkdf_salt.size(),
1302
                         10,
1303
                         &iters_10ms));
1304
            TEST_FFI_OK(botan_pbkdf_timed,
1✔
1305
                        ("PBKDF2(SHA-1)",
1306
                         outbuf.data(),
1307
                         outbuf.size(),
1308
                         passphrase.c_str(),
1309
                         pbkdf_salt.data(),
1310
                         pbkdf_salt.size(),
1311
                         100,
1312
                         &iters_100ms));
1313

1314
            result.test_note("PBKDF timed 10 ms " + std::to_string(iters_10ms) + " iterations " + "100 ms " +
3✔
1315
                             std::to_string(iters_100ms) + " iterations");
4✔
1316
         }
1317

1318
         const std::vector<uint8_t> kdf_secret = Botan::hex_decode("92167440112E");
1✔
1319
         const std::vector<uint8_t> kdf_salt = Botan::hex_decode("45A9BEDED69163123D0348F5185F61ABFB1BF18D6AEA454F");
1✔
1320
         const size_t kdf_out_len = 18;
1✔
1321
         outbuf.resize(kdf_out_len);
1✔
1322

1323
         if(TEST_FFI_INIT(botan_kdf,
1✔
1324
                          ("KDF2(SHA-1)",
1325
                           outbuf.data(),
1326
                           outbuf.size(),
1327
                           kdf_secret.data(),
1328
                           kdf_secret.size(),
1329
                           kdf_salt.data(),
1330
                           kdf_salt.size(),
1331
                           nullptr,
1332
                           0))) {
1333
            result.test_eq("KDF output", outbuf, "3A5DC9AA1C872B4744515AC2702D6396FC2A");
2✔
1334
         }
1335

1336
         size_t out_len = 64;
1✔
1337
         std::string outstr;
1✔
1338
         outstr.resize(out_len);
1✔
1339

1340
         int rc =
1✔
1341
            botan_bcrypt_generate(reinterpret_cast<uint8_t*>(&outstr[0]), &out_len, passphrase.c_str(), rng, 4, 0);
1✔
1342

1343
         if(rc == 0) {
1✔
1344
            result.test_eq("bcrypt output size", out_len, 61);
1✔
1345

1346
            TEST_FFI_OK(botan_bcrypt_is_valid, (passphrase.c_str(), outstr.data()));
1✔
1347
            TEST_FFI_FAIL("bad password", botan_bcrypt_is_valid, ("nope", outstr.data()));
2✔
1348
         }
1349
      }
6✔
1350
};
1351

1352
class FFI_Blockcipher_Test final : public FFI_Test {
×
1353
   public:
1354
      std::string name() const override { return "FFI block ciphers"; }
1✔
1355

1356
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
1357
         botan_block_cipher_t cipher;
1✔
1358

1359
         if(TEST_FFI_INIT(botan_block_cipher_init, (&cipher, "AES-128"))) {
2✔
1360
            char namebuf[10];
1✔
1361
            size_t name_len = 7;
1✔
1362
            TEST_FFI_FAIL("output buffer too short", botan_block_cipher_name, (cipher, namebuf, &name_len));
2✔
1363
            result.test_eq("name len", name_len, 8);
1✔
1364

1365
            name_len = sizeof(namebuf);
1✔
1366
            if(TEST_FFI_OK(botan_block_cipher_name, (cipher, namebuf, &name_len))) {
2✔
1367
               result.test_eq("name len", name_len, 8);
1✔
1368
               result.test_eq("name", std::string(namebuf), "AES-128");
2✔
1369
            }
1370

1371
            const std::vector<uint8_t> zero16(16, 0);
1✔
1372
            std::vector<uint8_t> block(16, 0);
1✔
1373

1374
            TEST_FFI_OK(botan_block_cipher_clear, (cipher));
1✔
1375

1376
            TEST_FFI_RC(
1✔
1377
               BOTAN_FFI_ERROR_KEY_NOT_SET, botan_block_cipher_encrypt_blocks, (cipher, block.data(), block.data(), 1));
1378
            TEST_FFI_RC(
1✔
1379
               BOTAN_FFI_ERROR_KEY_NOT_SET, botan_block_cipher_decrypt_blocks, (cipher, block.data(), block.data(), 1));
1380

1381
            TEST_FFI_RC(BOTAN_FFI_ERROR_NULL_POINTER, botan_block_cipher_encrypt_blocks, (cipher, nullptr, nullptr, 0));
1✔
1382
            TEST_FFI_RC(BOTAN_FFI_ERROR_NULL_POINTER, botan_block_cipher_decrypt_blocks, (cipher, nullptr, nullptr, 0));
1✔
1383

1384
            TEST_FFI_RC(16, botan_block_cipher_block_size, (cipher));
1✔
1385

1386
            size_t min_keylen = 0, max_keylen = 0, mod_keylen = 0;
1✔
1387
            TEST_FFI_RC(0, botan_block_cipher_get_keyspec, (cipher, nullptr, nullptr, nullptr));
1✔
1388
            TEST_FFI_RC(0, botan_block_cipher_get_keyspec, (cipher, &min_keylen, nullptr, nullptr));
1✔
1389
            TEST_FFI_RC(0, botan_block_cipher_get_keyspec, (cipher, nullptr, &max_keylen, nullptr));
1✔
1390
            TEST_FFI_RC(0, botan_block_cipher_get_keyspec, (cipher, nullptr, nullptr, &mod_keylen));
1✔
1391

1392
            result.test_eq("Expected min keylen", min_keylen, 16);
1✔
1393
            result.test_eq("Expected max keylen", max_keylen, 16);
1✔
1394
            result.test_eq("Expected mod keylen", mod_keylen, 1);
1✔
1395

1396
            TEST_FFI_OK(botan_block_cipher_set_key, (cipher, zero16.data(), zero16.size()));
1✔
1397

1398
            TEST_FFI_OK(botan_block_cipher_encrypt_blocks, (cipher, block.data(), block.data(), 1));
1✔
1399
            result.test_eq("AES-128 encryption works", block, "66E94BD4EF8A2C3B884CFA59CA342B2E");
1✔
1400

1401
            TEST_FFI_OK(botan_block_cipher_encrypt_blocks, (cipher, block.data(), block.data(), 1));
1✔
1402
            result.test_eq("AES-128 encryption works", block, "F795BD4A52E29ED713D313FA20E98DBC");
1✔
1403

1404
            TEST_FFI_OK(botan_block_cipher_decrypt_blocks, (cipher, block.data(), block.data(), 1));
1✔
1405
            result.test_eq("AES-128 decryption works", block, "66E94BD4EF8A2C3B884CFA59CA342B2E");
1✔
1406

1407
            TEST_FFI_OK(botan_block_cipher_decrypt_blocks, (cipher, block.data(), block.data(), 1));
1✔
1408
            result.test_eq("AES-128 decryption works", block, "00000000000000000000000000000000");
1✔
1409

1410
            TEST_FFI_OK(botan_block_cipher_clear, (cipher));
1✔
1411
            botan_block_cipher_destroy(cipher);
1✔
1412
         }
2✔
1413
      }
1✔
1414
};
1415

1416
class FFI_ErrorHandling_Test final : public FFI_Test {
×
1417
   public:
1418
      std::string name() const override { return "FFI error handling"; }
1✔
1419

1420
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
1421
         // delete of null is ok/ignored
1422
         TEST_FFI_RC(0, botan_hash_destroy, (nullptr));
1✔
1423

1424
   #if !defined(BOTAN_HAS_SANITIZER_UNDEFINED)
1425
         // Confirm that botan_x_destroy checks the argument type
1426
         botan_mp_t mp;
1✔
1427
         botan_mp_init(&mp);
1✔
1428
         TEST_FFI_RC(BOTAN_FFI_ERROR_INVALID_OBJECT, botan_hash_destroy, (reinterpret_cast<botan_hash_t>(mp)));
1✔
1429
         TEST_FFI_RC(0, botan_mp_destroy, (mp));
1✔
1430
   #endif
1431

1432
         std::set<std::string> errors;
1✔
1433
         for(int i = -100; i != 50; ++i) {
151✔
1434
            const char* err = botan_error_description(i);
150✔
1435
            result.confirm("Never a null pointer", err != nullptr);
300✔
1436

1437
            if(err) {
150✔
1438
               std::string s(err);
150✔
1439

1440
               if(s != "Unknown error") {
150✔
1441
                  result.confirm("No duplicate messages", !errors.contains(s));
40✔
1442
                  errors.insert(s);
170✔
1443
               }
1444
            }
150✔
1445
         }
1446
      }
1✔
1447
};
1448

1449
class FFI_Base64_Test final : public FFI_Test {
×
1450
   public:
1451
      std::string name() const override { return "FFI base64"; }
1✔
1452

1453
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
1454
         const uint8_t bin[9] = {0x16, 0x8a, 0x1f, 0x06, 0xe9, 0xe7, 0xcb, 0xdd, 0x34};
1✔
1455
         char out_buf[1024] = {0};
1✔
1456

1457
         size_t out_len = sizeof(out_buf);
1✔
1458
         TEST_FFI_OK(botan_base64_encode, (bin, sizeof(bin), out_buf, &out_len));
1✔
1459

1460
         result.test_eq("encoded string", out_buf, "FoofBunny900");
1✔
1461

1462
         out_len -= 1;
1✔
1463
         TEST_FFI_RC(
1✔
1464
            BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_base64_encode, (bin, sizeof(bin), out_buf, &out_len));
1465

1466
         const char* base64 = "U3VjaCBiYXNlNjQgd293IQ==";
1✔
1467
         uint8_t out_bin[1024] = {0};
1✔
1468

1469
         out_len = 3;
1✔
1470
         TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
1✔
1471
                     botan_base64_decode,
1472
                     (base64, strlen(base64), out_bin, &out_len));
1473

1474
         result.test_eq("output length", out_len, 18);
1✔
1475

1476
         out_len = sizeof(out_bin);
1✔
1477
         TEST_FFI_OK(botan_base64_decode, (base64, strlen(base64), out_bin, &out_len));
1✔
1478

1479
         result.test_eq(
3✔
1480
            "decoded string", std::string(reinterpret_cast<const char*>(out_bin), out_len), "Such base64 wow!");
3✔
1481
      }
1✔
1482
};
1483

1484
class FFI_Hex_Test final : public FFI_Test {
×
1485
   public:
1486
      std::string name() const override { return "FFI hex"; }
1✔
1487

1488
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
1489
         const uint8_t bin[4] = {0xDE, 0xAD, 0xBE, 0xEF};
1✔
1490
         char hex_buf[16] = {0};
1✔
1491

1492
         TEST_FFI_OK(botan_hex_encode, (bin, sizeof(bin), hex_buf, 0));
1✔
1493

1494
         result.test_eq("encoded string", hex_buf, "DEADBEEF");
1✔
1495

1496
         const char* hex = "67657420796572206A756D626F20736872696D70";
1✔
1497
         uint8_t out_bin[1024] = {0};
1✔
1498
         size_t out_len = 5;
1✔
1499

1500
         TEST_FFI_RC(
1✔
1501
            BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_hex_decode, (hex, strlen(hex), out_bin, &out_len));
1502

1503
         out_len = sizeof(out_bin);
1✔
1504
         TEST_FFI_OK(botan_hex_decode, (hex, strlen(hex), out_bin, &out_len));
1✔
1505

1506
         result.test_eq(
3✔
1507
            "decoded string", std::string(reinterpret_cast<const char*>(out_bin), out_len), "get yer jumbo shrimp");
3✔
1508
      }
1✔
1509
};
1510

1511
class FFI_MP_Test final : public FFI_Test {
×
1512
   public:
1513
      std::string name() const override { return "FFI MP"; }
1✔
1514

1515
      void ffi_test(Test::Result& result, botan_rng_t rng) override {
1✔
1516
         char str_buf[1024] = {0};
1✔
1517
         size_t str_len = 0;
1✔
1518

1519
         botan_mp_t x;
1✔
1520
         botan_mp_init(&x);
1✔
1521
         TEST_FFI_RC(0, botan_mp_is_odd, (x));
1✔
1522
         TEST_FFI_RC(1, botan_mp_is_even, (x));
1✔
1523
         TEST_FFI_RC(0, botan_mp_is_negative, (x));
1✔
1524
         TEST_FFI_RC(1, botan_mp_is_positive, (x));
1✔
1525
         TEST_FFI_RC(1, botan_mp_is_zero, (x));
1✔
1526
         botan_mp_destroy(x);
1✔
1527

1528
         botan_mp_init(&x);
1✔
1529
         size_t bn_bytes = 0;
1✔
1530
         TEST_FFI_OK(botan_mp_num_bytes, (x, &bn_bytes));
1✔
1531
         result.test_eq("Expected size for MP 0", bn_bytes, 0);
1✔
1532

1533
         botan_mp_set_from_int(x, 5);
1✔
1534
         TEST_FFI_OK(botan_mp_num_bytes, (x, &bn_bytes));
1✔
1535
         result.test_eq("Expected size for MP 5", bn_bytes, 1);
1✔
1536

1537
         botan_mp_add_u32(x, x, 75);
1✔
1538
         TEST_FFI_OK(botan_mp_num_bytes, (x, &bn_bytes));
1✔
1539
         result.test_eq("Expected size for MP 80", bn_bytes, 1);
1✔
1540

1541
         str_len = sizeof(str_buf);
1✔
1542
         TEST_FFI_OK(botan_mp_to_str, (x, 10, str_buf, &str_len));
1✔
1543
         result.test_eq("botan_mp_add", std::string(str_buf), "80");
2✔
1544

1545
         botan_mp_sub_u32(x, x, 80);
1✔
1546
         TEST_FFI_RC(1, botan_mp_is_zero, (x));
1✔
1547
         botan_mp_add_u32(x, x, 259);
1✔
1548
         TEST_FFI_OK(botan_mp_num_bytes, (x, &bn_bytes));
1✔
1549
         result.test_eq("Expected size for MP 259", bn_bytes, 2);
1✔
1550

1551
         str_len = sizeof(str_buf);
1✔
1552
         TEST_FFI_OK(botan_mp_to_str, (x, 10, str_buf, &str_len));
1✔
1553
         result.test_eq("botan_mp_add", std::string(str_buf), "259");
2✔
1554

1555
         TEST_FFI_RC(1, botan_mp_is_odd, (x));
1✔
1556
         TEST_FFI_RC(0, botan_mp_is_even, (x));
1✔
1557
         TEST_FFI_RC(0, botan_mp_is_negative, (x));
1✔
1558
         TEST_FFI_RC(1, botan_mp_is_positive, (x));
1✔
1559
         TEST_FFI_RC(0, botan_mp_is_zero, (x));
1✔
1560

1561
         {
1✔
1562
            botan_mp_t zero;
1✔
1563
            botan_mp_init(&zero);
1✔
1564
            int cmp;
1✔
1565
            TEST_FFI_OK(botan_mp_cmp, (&cmp, x, zero));
1✔
1566
            result.confirm("bigint_mp_cmp(+, 0)", cmp == 1);
2✔
1567

1568
            TEST_FFI_OK(botan_mp_cmp, (&cmp, zero, x));
1✔
1569
            result.confirm("bigint_mp_cmp(0, +)", cmp == -1);
2✔
1570

1571
            TEST_FFI_RC(0, botan_mp_is_negative, (x));
1✔
1572
            TEST_FFI_RC(1, botan_mp_is_positive, (x));
1✔
1573
            TEST_FFI_OK(botan_mp_flip_sign, (x));
1✔
1574
            TEST_FFI_RC(1, botan_mp_is_negative, (x));
1✔
1575
            TEST_FFI_RC(0, botan_mp_is_positive, (x));
1✔
1576

1577
            // test no negative zero
1578
            TEST_FFI_RC(0, botan_mp_is_negative, (zero));
1✔
1579
            TEST_FFI_RC(1, botan_mp_is_positive, (zero));
1✔
1580
            TEST_FFI_OK(botan_mp_flip_sign, (zero));
1✔
1581
            TEST_FFI_RC(0, botan_mp_is_negative, (zero));
1✔
1582
            TEST_FFI_RC(1, botan_mp_is_positive, (zero));
1✔
1583

1584
            TEST_FFI_OK(botan_mp_cmp, (&cmp, x, zero));
1✔
1585
            result.confirm("bigint_mp_cmp(-, 0)", cmp == -1);
2✔
1586

1587
            TEST_FFI_OK(botan_mp_cmp, (&cmp, zero, x));
1✔
1588
            result.confirm("bigint_mp_cmp(0, -)", cmp == 1);
2✔
1589

1590
            TEST_FFI_OK(botan_mp_cmp, (&cmp, zero, zero));
1✔
1591
            result.confirm("bigint_mp_cmp(0, 0)", cmp == 0);
2✔
1592

1593
            TEST_FFI_OK(botan_mp_cmp, (&cmp, x, x));
1✔
1594
            result.confirm("bigint_mp_cmp(x, x)", cmp == 0);
2✔
1595

1596
            TEST_FFI_OK(botan_mp_flip_sign, (x));
1✔
1597

1598
            botan_mp_destroy(zero);
1✔
1599
         }
1600

1601
         size_t x_bits = 0;
1✔
1602
         TEST_FFI_OK(botan_mp_num_bits, (x, &x_bits));
1✔
1603
         result.test_eq("botan_mp_num_bits", x_bits, 9);
1✔
1604

1605
         TEST_FFI_OK(botan_mp_to_hex, (x, str_buf));
1✔
1606
         result.test_eq("botan_mp_to_hex", std::string(str_buf), "0x0103");
2✔
1607

1608
         uint32_t x_32;
1✔
1609
         TEST_FFI_OK(botan_mp_to_uint32, (x, &x_32));
1✔
1610
         result.test_eq("botan_mp_to_uint32", size_t(x_32), size_t(0x103));
1✔
1611

1612
         TEST_FFI_RC(1, botan_mp_get_bit, (x, 1));
1✔
1613
         TEST_FFI_RC(0, botan_mp_get_bit, (x, 87));
1✔
1614
         TEST_FFI_OK(botan_mp_set_bit, (x, 87));
1✔
1615
         TEST_FFI_RC(1, botan_mp_get_bit, (x, 87));
1✔
1616
         TEST_FFI_OK(botan_mp_to_hex, (x, str_buf));
1✔
1617
         result.test_eq("botan_mp_set_bit", std::string(str_buf), "0x8000000000000000000103");
3✔
1618

1619
         TEST_FFI_OK(botan_mp_clear_bit, (x, 87));
1✔
1620
         TEST_FFI_OK(botan_mp_to_hex, (x, str_buf));
1✔
1621
         result.test_eq("botan_mp_set_bit", std::string(str_buf), "0x0103");
2✔
1622

1623
         botan_mp_t y;
1✔
1624
         TEST_FFI_OK(botan_mp_init, (&y));
1✔
1625
         TEST_FFI_OK(botan_mp_set_from_int, (y, 0x1234567));
1✔
1626

1627
         botan_mp_t r;
1✔
1628
         botan_mp_init(&r);
1✔
1629

1630
         TEST_FFI_OK(botan_mp_add, (r, x, y));
1✔
1631
         str_len = sizeof(str_buf);
1✔
1632
         TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
1✔
1633
         result.test_eq("botan_mp_add", std::string(str_buf), "19089002");
2✔
1634

1635
         TEST_FFI_OK(botan_mp_mul, (r, x, y));
1✔
1636
         str_len = sizeof(str_buf);
1✔
1637
         TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
1✔
1638
         result.test_eq("botan_mp_mul", std::string(str_buf), "4943984437");
2✔
1639
         TEST_FFI_RC(0, botan_mp_is_negative, (r));
1✔
1640

1641
         botan_mp_t q;
1✔
1642
         botan_mp_init(&q);
1✔
1643
         TEST_FFI_OK(botan_mp_div, (q, r, y, x));
1✔
1644

1645
         str_len = sizeof(str_buf);
1✔
1646
         TEST_FFI_OK(botan_mp_to_str, (q, 10, str_buf, &str_len));
1✔
1647
         result.test_eq("botan_mp_div_q", std::string(str_buf), "73701");
2✔
1648

1649
         str_len = sizeof(str_buf);
1✔
1650
         TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
1✔
1651
         result.test_eq("botan_mp_div_r", std::string(str_buf), "184");
2✔
1652

1653
         TEST_FFI_OK(botan_mp_set_from_str, (y, "4943984437"));
1✔
1654
         TEST_FFI_OK(botan_mp_sub, (r, x, y));
1✔
1655
         str_len = sizeof(str_buf);
1✔
1656
         TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
1✔
1657
         result.test_eq("botan_mp_sub", std::string(str_buf), "-4943984178");
2✔
1658
         TEST_FFI_RC(1, botan_mp_is_negative, (r));
1✔
1659

1660
         TEST_FFI_OK(botan_mp_lshift, (r, x, 39));
1✔
1661
         str_len = sizeof(str_buf);
1✔
1662
         TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
1✔
1663
         result.test_eq("botan_mp_lshift", std::string(str_buf), "142386755796992");
2✔
1664

1665
         TEST_FFI_OK(botan_mp_rshift, (r, r, 3));
1✔
1666
         str_len = sizeof(str_buf);
1✔
1667
         TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
1✔
1668
         result.test_eq("botan_mp_rshift", std::string(str_buf), "17798344474624");
2✔
1669

1670
         TEST_FFI_OK(botan_mp_gcd, (r, x, y));
1✔
1671
         str_len = sizeof(str_buf);
1✔
1672
         TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
1✔
1673
         result.test_eq("botan_mp_gcd", std::string(str_buf), "259");
2✔
1674

1675
         botan_mp_t p;
1✔
1676
         botan_mp_init(&p);
1✔
1677
         const uint8_t M127[] = {
1✔
1678
            0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1679
         TEST_FFI_OK(botan_mp_from_bin, (p, M127, sizeof(M127)));
1✔
1680
         TEST_FFI_RC(1, botan_mp_is_prime, (p, rng, 64));
1✔
1681

1682
         size_t p_bits = 0;
1✔
1683
         TEST_FFI_OK(botan_mp_num_bits, (p, &p_bits));
1✔
1684
         result.test_eq("botan_mp_num_bits", p_bits, 127);
1✔
1685

1686
         TEST_FFI_OK(botan_mp_mod_inverse, (r, x, p));
1✔
1687
         str_len = sizeof(str_buf);
1✔
1688
         TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
1✔
1689
         result.test_eq("botan_mp_mod_inverse", std::string(str_buf), "40728777507911553541948312086427855425");
3✔
1690

1691
         TEST_FFI_OK(botan_mp_powmod, (r, x, r, p));
1✔
1692
         str_len = sizeof(str_buf);
1✔
1693
         TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
1✔
1694
         result.test_eq("botan_mp_powmod", std::string(str_buf), "40550417419160441638948180641668117560");
3✔
1695

1696
         TEST_FFI_OK(botan_mp_num_bytes, (r, &bn_bytes));
1✔
1697
         result.test_eq("botan_mp_num_bytes", bn_bytes, 16);
1✔
1698

1699
         std::vector<uint8_t> bn_buf;
1✔
1700
         bn_buf.resize(bn_bytes);
1✔
1701
         botan_mp_to_bin(r, bn_buf.data());
1✔
1702
         result.test_eq("botan_mp_to_bin", bn_buf, "1E81B9EFE0BE1902F6D03F9F5E5FB438");
1✔
1703

1704
         TEST_FFI_OK(botan_mp_set_from_mp, (y, r));
1✔
1705
         TEST_FFI_OK(botan_mp_mod_mul, (r, x, y, p));
1✔
1706
         str_len = sizeof(str_buf);
1✔
1707
         TEST_FFI_OK(botan_mp_to_str, (r, 10, str_buf, &str_len));
1✔
1708
         result.test_eq("botan_mp_mod_mul", std::string(str_buf), "123945920473931248854653259523111998693");
3✔
1709

1710
         str_len = 0;
1✔
1711
         TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_mp_to_str, (r, 10, str_buf, &str_len));
1✔
1712

1713
         size_t x_bytes;
1✔
1714
         botan_mp_rand_bits(x, rng, 512);
1✔
1715
         TEST_FFI_OK(botan_mp_num_bytes, (x, &x_bytes));
1✔
1716
         result.test_lte("botan_mp_num_bytes", x_bytes, 512 / 8);
1✔
1717

1718
         TEST_FFI_OK(botan_mp_set_from_radix_str, (x, "909A", 16));
1✔
1719
         TEST_FFI_OK(botan_mp_to_uint32, (x, &x_32));
1✔
1720
         result.test_eq("botan_mp_set_from_radix_str(16)", x_32, static_cast<size_t>(0x909A));
1✔
1721

1722
         TEST_FFI_OK(botan_mp_set_from_radix_str, (x, "9098135", 10));
1✔
1723
         TEST_FFI_OK(botan_mp_to_uint32, (x, &x_32));
1✔
1724
         result.test_eq("botan_mp_set_from_radix_str(10)", x_32, static_cast<size_t>(9098135));
1✔
1725

1726
         botan_mp_destroy(p);
1✔
1727
         botan_mp_destroy(x);
1✔
1728
         botan_mp_destroy(y);
1✔
1729
         botan_mp_destroy(r);
1✔
1730
         botan_mp_destroy(q);
1✔
1731
      }
1✔
1732
};
1733

1734
class FFI_FPE_Test final : public FFI_Test {
×
1735
   public:
1736
      std::string name() const override { return "FFI FPE"; }
1✔
1737

1738
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
1739
         const uint8_t key[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1✔
1740

1741
         botan_mp_t n;
1✔
1742
         botan_mp_init(&n);
1✔
1743
         botan_mp_set_from_str(n, "1000000000");
1✔
1744

1745
         botan_fpe_t fpe;
1✔
1746
         if(!TEST_FFI_INIT(botan_fpe_fe1_init, (&fpe, n, key, sizeof(key), 5, 0))) {
2✔
1747
            botan_mp_destroy(n);
×
1748
            return;
×
1749
         }
1750

1751
         botan_mp_t x;
1✔
1752
         botan_mp_init(&x);
1✔
1753
         botan_mp_set_from_str(x, "178051120");
1✔
1754

1755
         TEST_FFI_OK(botan_fpe_encrypt, (fpe, x, nullptr, 0));
1✔
1756

1757
         uint32_t xval = 0;
1✔
1758
         TEST_FFI_OK(botan_mp_to_uint32, (x, &xval));
1✔
1759
         result.test_eq("Expected FPE ciphertext", xval, size_t(605648666));
1✔
1760

1761
         TEST_FFI_OK(botan_fpe_encrypt, (fpe, x, nullptr, 0));
1✔
1762
         TEST_FFI_OK(botan_fpe_decrypt, (fpe, x, nullptr, 0));
1✔
1763
         TEST_FFI_OK(botan_fpe_decrypt, (fpe, x, nullptr, 0));
1✔
1764

1765
         TEST_FFI_OK(botan_mp_to_uint32, (x, &xval));
1✔
1766
         result.test_eq("FPE round trip", xval, size_t(178051120));
1✔
1767

1768
         TEST_FFI_OK(botan_fpe_destroy, (fpe));
1✔
1769
         TEST_FFI_OK(botan_mp_destroy, (x));
1✔
1770
         TEST_FFI_OK(botan_mp_destroy, (n));
2✔
1771
      }
1772
};
1773

1774
class FFI_TOTP_Test final : public FFI_Test {
×
1775
   public:
1776
      std::string name() const override { return "FFI TOTP"; }
1✔
1777

1778
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
1779
         const std::vector<uint8_t> key = Botan::hex_decode("3132333435363738393031323334353637383930");
1✔
1780
         const size_t digits = 8;
1✔
1781
         const size_t timestep = 30;
1✔
1782
         botan_totp_t totp;
1✔
1783

1784
         if(!TEST_FFI_INIT(botan_totp_init, (&totp, key.data(), key.size(), "SHA-1", digits, timestep))) {
1✔
1785
            return;
×
1786
         }
1787

1788
         uint32_t code;
1✔
1789
         TEST_FFI_OK(botan_totp_generate, (totp, &code, 59));
1✔
1790
         result.confirm("TOTP code", code == 94287082);
2✔
1791

1792
         TEST_FFI_OK(botan_totp_generate, (totp, &code, 1111111109));
1✔
1793
         result.confirm("TOTP code 2", code == 7081804);
2✔
1794

1795
         TEST_FFI_OK(botan_totp_check, (totp, 94287082, 59 + 60, 60));
1✔
1796
         TEST_FFI_RC(1, botan_totp_check, (totp, 94287082, 59 + 31, 1));
1✔
1797
         TEST_FFI_RC(1, botan_totp_check, (totp, 94287082, 59 + 61, 1));
1✔
1798

1799
         TEST_FFI_OK(botan_totp_destroy, (totp));
2✔
1800
      }
1✔
1801
};
1802

1803
class FFI_HOTP_Test final : public FFI_Test {
×
1804
   public:
1805
      std::string name() const override { return "FFI HOTP"; }
1✔
1806

1807
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
1808
         const std::vector<uint8_t> key = Botan::hex_decode("3132333435363738393031323334353637383930");
1✔
1809
         const size_t digits = 6;
1✔
1810

1811
         botan_hotp_t hotp;
1✔
1812
         uint32_t hotp_val;
1✔
1813

1814
         if(!TEST_FFI_INIT(botan_hotp_init, (&hotp, key.data(), key.size(), "SHA-1", digits))) {
1✔
1815
            return;
×
1816
         }
1817

1818
         TEST_FFI_OK(botan_hotp_generate, (hotp, &hotp_val, 0));
1✔
1819
         result.confirm("Valid value for counter 0", hotp_val == 755224);
2✔
1820
         TEST_FFI_OK(botan_hotp_generate, (hotp, &hotp_val, 1));
1✔
1821
         result.confirm("Valid value for counter 0", hotp_val == 287082);
2✔
1822
         TEST_FFI_OK(botan_hotp_generate, (hotp, &hotp_val, 2));
1✔
1823
         result.confirm("Valid value for counter 0", hotp_val == 359152);
2✔
1824
         TEST_FFI_OK(botan_hotp_generate, (hotp, &hotp_val, 0));
1✔
1825
         result.confirm("Valid value for counter 0", hotp_val == 755224);
2✔
1826

1827
         uint64_t next_ctr = 0;
1✔
1828

1829
         TEST_FFI_OK(botan_hotp_check, (hotp, &next_ctr, 755224, 0, 0));
1✔
1830
         result.confirm("HOTP resync", next_ctr == 1);
2✔
1831
         TEST_FFI_OK(botan_hotp_check, (hotp, nullptr, 359152, 2, 0));
1✔
1832
         TEST_FFI_RC(1, botan_hotp_check, (hotp, nullptr, 359152, 1, 0));
1✔
1833
         TEST_FFI_OK(botan_hotp_check, (hotp, &next_ctr, 359152, 0, 2));
1✔
1834
         result.confirm("HOTP resync", next_ctr == 3);
2✔
1835

1836
         TEST_FFI_OK(botan_hotp_destroy, (hotp));
2✔
1837
      }
1✔
1838
};
1839

1840
class FFI_Keywrap_Test final : public FFI_Test {
×
1841
   public:
1842
      std::string name() const override { return "FFI Keywrap"; }
1✔
1843

1844
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
1845
         const uint8_t key[16] = {0};
1✔
1846
         const uint8_t kek[16] = {0xFF, 0};
1✔
1847

1848
         uint8_t wrapped[16 + 8] = {0};
1✔
1849
         size_t wrapped_keylen = sizeof(wrapped);
1✔
1850

1851
         if(TEST_FFI_INIT(botan_key_wrap3394, (key, sizeof(key), kek, sizeof(kek), wrapped, &wrapped_keylen))) {
2✔
1852
            const uint8_t expected_wrapped_key[16 + 8] = {0x04, 0x13, 0x37, 0x39, 0x82, 0xCF, 0xFA, 0x31,
1✔
1853
                                                          0x81, 0xCA, 0x4F, 0x59, 0x74, 0x4D, 0xED, 0x29,
1854
                                                          0x1F, 0x3F, 0xE5, 0x24, 0x00, 0x1B, 0x93, 0x20};
1855

1856
            result.test_eq("Expected wrapped keylen size", wrapped_keylen, 16 + 8);
1✔
1857

1858
            result.test_eq(
1✔
1859
               nullptr, "Wrapped key", wrapped, wrapped_keylen, expected_wrapped_key, sizeof(expected_wrapped_key));
1860

1861
            uint8_t dec_key[16] = {0};
1✔
1862
            size_t dec_keylen = sizeof(dec_key);
1✔
1863
            TEST_FFI_OK(botan_key_unwrap3394, (wrapped, sizeof(wrapped), kek, sizeof(kek), dec_key, &dec_keylen));
1✔
1864

1865
            result.test_eq(nullptr, "Unwrapped key", dec_key, dec_keylen, key, sizeof(key));
2✔
1866
         }
1867
      }
1✔
1868
};
1869

1870
class FFI_RSA_Test final : public FFI_Test {
×
1871
   public:
1872
      std::string name() const override { return "FFI RSA"; }
1✔
1873

1874
      void ffi_test(Test::Result& result, botan_rng_t rng) override {
1✔
1875
         botan_privkey_t priv;
1✔
1876

1877
         if(TEST_FFI_INIT(botan_privkey_create_rsa, (&priv, rng, 1024))) {
2✔
1878
            TEST_FFI_OK(botan_privkey_check_key, (priv, rng, 0));
1✔
1879

1880
            botan_pubkey_t pub;
1✔
1881
            TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
1✔
1882
            TEST_FFI_OK(botan_pubkey_check_key, (pub, rng, 0));
1✔
1883

1884
            ffi_test_pubkey_export(result, pub, priv, rng);
1✔
1885

1886
            botan_mp_t p, q, d, n, e;
1✔
1887
            botan_mp_init(&p);
1✔
1888
            botan_mp_init(&q);
1✔
1889
            botan_mp_init(&d);
1✔
1890
            botan_mp_init(&n);
1✔
1891
            botan_mp_init(&e);
1✔
1892

1893
            TEST_FFI_RC(BOTAN_FFI_ERROR_BAD_PARAMETER, botan_privkey_get_field, (p, priv, "quux"));
1✔
1894
            TEST_FFI_RC(BOTAN_FFI_ERROR_BAD_PARAMETER, botan_pubkey_get_field, (p, pub, "quux"));
1✔
1895

1896
            TEST_FFI_OK(botan_privkey_rsa_get_p, (p, priv));
1✔
1897
            TEST_FFI_OK(botan_privkey_rsa_get_q, (q, priv));
1✔
1898
            TEST_FFI_OK(botan_privkey_rsa_get_d, (d, priv));
1✔
1899
            TEST_FFI_OK(botan_privkey_rsa_get_e, (e, priv));
1✔
1900
            TEST_FFI_OK(botan_privkey_rsa_get_n, (n, priv));
1✔
1901

1902
            // Confirm same (e,n) values in public key
1903
            {
1✔
1904
               botan_mp_t pub_e, pub_n;
1✔
1905
               botan_mp_init(&pub_e);
1✔
1906
               botan_mp_init(&pub_n);
1✔
1907
               TEST_FFI_OK(botan_pubkey_rsa_get_e, (pub_e, pub));
1✔
1908
               TEST_FFI_OK(botan_pubkey_rsa_get_n, (pub_n, pub));
1✔
1909

1910
               TEST_FFI_RC(1, botan_mp_equal, (pub_e, e));
1✔
1911
               TEST_FFI_RC(1, botan_mp_equal, (pub_n, n));
1✔
1912
               botan_mp_destroy(pub_e);
1✔
1913
               botan_mp_destroy(pub_n);
1✔
1914
            }
1915

1916
            TEST_FFI_RC(1, botan_mp_is_prime, (p, rng, 64));
1✔
1917
            TEST_FFI_RC(1, botan_mp_is_prime, (q, rng, 64));
1✔
1918

1919
            // Test p != q
1920
            TEST_FFI_RC(0, botan_mp_equal, (p, q));
1✔
1921

1922
            // Test p * q == n
1923
            botan_mp_t x;
1✔
1924
            botan_mp_init(&x);
1✔
1925
            TEST_FFI_OK(botan_mp_mul, (x, p, q));
1✔
1926

1927
            TEST_FFI_RC(1, botan_mp_equal, (x, n));
1✔
1928
            botan_mp_destroy(x);
1✔
1929

1930
            botan_privkey_t loaded_privkey;
1✔
1931
            // First try loading a bogus key and verify check_key fails
1932
            TEST_FFI_OK(botan_privkey_load_rsa, (&loaded_privkey, n, d, q));
1✔
1933
            TEST_FFI_RC(-1, botan_privkey_check_key, (loaded_privkey, rng, 0));
1✔
1934
            botan_privkey_destroy(loaded_privkey);
1✔
1935

1936
            TEST_FFI_OK(botan_privkey_load_rsa, (&loaded_privkey, p, q, e));
1✔
1937
            TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey, rng, 0));
1✔
1938

1939
            botan_pubkey_t loaded_pubkey;
1✔
1940
            TEST_FFI_OK(botan_pubkey_load_rsa, (&loaded_pubkey, n, e));
1✔
1941
            TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey, rng, 0));
1✔
1942

1943
            botan_mp_destroy(p);
1✔
1944
            botan_mp_destroy(q);
1✔
1945
            botan_mp_destroy(d);
1✔
1946
            botan_mp_destroy(e);
1✔
1947
            botan_mp_destroy(n);
1✔
1948

1949
            size_t pkcs1_len = 0;
1✔
1950
            TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
1✔
1951
                        botan_privkey_rsa_get_privkey,
1952
                        (loaded_privkey, nullptr, &pkcs1_len, BOTAN_PRIVKEY_EXPORT_FLAG_DER));
1953

1954
            std::vector<uint8_t> pkcs1(pkcs1_len);
1✔
1955
            TEST_FFI_OK(botan_privkey_rsa_get_privkey,
1✔
1956
                        (loaded_privkey, pkcs1.data(), &pkcs1_len, BOTAN_PRIVKEY_EXPORT_FLAG_DER));
1957

1958
            botan_privkey_t privkey_from_pkcs1;
1✔
1959
            TEST_FFI_OK(botan_privkey_load_rsa_pkcs1, (&privkey_from_pkcs1, pkcs1.data(), pkcs1_len));
1✔
1960
            TEST_FFI_OK(botan_privkey_destroy, (privkey_from_pkcs1));
1✔
1961

1962
            pkcs1_len = 0;
1✔
1963
            TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
1✔
1964
                        botan_privkey_rsa_get_privkey,
1965
                        (loaded_privkey, nullptr, &pkcs1_len, BOTAN_PRIVKEY_EXPORT_FLAG_PEM));
1966
            pkcs1.resize(pkcs1_len);
1✔
1967
            TEST_FFI_OK(botan_privkey_rsa_get_privkey,
1✔
1968
                        (loaded_privkey, pkcs1.data(), &pkcs1_len, BOTAN_PRIVKEY_EXPORT_FLAG_PEM));
1969

1970
            char namebuf[32] = {0};
1✔
1971
            size_t name_len = sizeof(namebuf);
1✔
1972
            if(TEST_FFI_OK(botan_pubkey_algo_name, (loaded_pubkey, namebuf, &name_len))) {
2✔
1973
               result.test_eq("algo name", std::string(namebuf), "RSA");
2✔
1974
            }
1975

1976
            name_len = sizeof(namebuf);
1✔
1977
            if(TEST_FFI_OK(botan_privkey_algo_name, (loaded_privkey, namebuf, &name_len))) {
2✔
1978
               result.test_eq("algo name", std::string(namebuf), "RSA");
2✔
1979
            }
1980

1981
            botan_pk_op_encrypt_t encrypt;
1✔
1982

1983
            if(TEST_FFI_INIT(botan_pk_op_encrypt_create, (&encrypt, loaded_pubkey, "OAEP(SHA-256)", 0))) {
2✔
1984
               std::vector<uint8_t> plaintext(32);
1✔
1985
               TEST_FFI_OK(botan_rng_get, (rng, plaintext.data(), plaintext.size()));
1✔
1986

1987
               size_t ctext_len;
1✔
1988
               TEST_FFI_OK(botan_pk_op_encrypt_output_length, (encrypt, plaintext.size(), &ctext_len));
1✔
1989
               std::vector<uint8_t> ciphertext(ctext_len);
1✔
1990

1991
               if(TEST_FFI_OK(botan_pk_op_encrypt,
2✔
1992
                              (encrypt, rng, ciphertext.data(), &ctext_len, plaintext.data(), plaintext.size()))) {
1993
                  ciphertext.resize(ctext_len);
1✔
1994

1995
                  botan_pk_op_decrypt_t decrypt;
1✔
1996
                  if(TEST_FFI_OK(botan_pk_op_decrypt_create, (&decrypt, priv, "OAEP(SHA-256)", 0))) {
2✔
1997
                     size_t decrypted_len;
1✔
1998
                     TEST_FFI_OK(botan_pk_op_decrypt_output_length, (decrypt, ciphertext.size(), &decrypted_len));
1✔
1999
                     std::vector<uint8_t> decrypted(decrypted_len);
1✔
2000
                     TEST_FFI_OK(botan_pk_op_decrypt,
1✔
2001
                                 (decrypt, decrypted.data(), &decrypted_len, ciphertext.data(), ciphertext.size()));
2002
                     decrypted.resize(decrypted_len);
1✔
2003

2004
                     result.test_eq("RSA plaintext", decrypted, plaintext);
2✔
2005
                  }
1✔
2006

2007
                  TEST_FFI_OK(botan_pk_op_decrypt_destroy, (decrypt));
2✔
2008
               }
2009

2010
               TEST_FFI_OK(botan_pk_op_encrypt_destroy, (encrypt));
2✔
2011
            }
2✔
2012

2013
            TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey));
1✔
2014
            TEST_FFI_OK(botan_pubkey_destroy, (pub));
1✔
2015
            TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey));
1✔
2016
            TEST_FFI_OK(botan_privkey_destroy, (priv));
2✔
2017
         }
1✔
2018
      }
1✔
2019
};
2020

2021
class FFI_DSA_Test final : public FFI_Test {
×
2022
   public:
2023
      std::string name() const override { return "FFI DSA"; }
1✔
2024

2025
      void ffi_test(Test::Result& result, botan_rng_t rng) override {
1✔
2026
         botan_privkey_t priv;
1✔
2027

2028
         if(TEST_FFI_INIT(botan_privkey_create, (&priv, "DSA", "dsa/jce/1024", rng))) {
2✔
2029
            do_dsa_test(priv, rng, result);
1✔
2030
         }
2031

2032
         if(TEST_FFI_INIT(botan_privkey_create_dsa, (&priv, rng, 1024, 160))) {
2✔
2033
            do_dsa_test(priv, rng, result);
1✔
2034
         }
2035
      }
1✔
2036

2037
   private:
2038
      static void do_dsa_test(botan_privkey_t priv, botan_rng_t rng, Test::Result& result) {
2✔
2039
         TEST_FFI_OK(botan_privkey_check_key, (priv, rng, 0));
2✔
2040

2041
         botan_pubkey_t pub;
2✔
2042
         TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
2✔
2043
         TEST_FFI_OK(botan_pubkey_check_key, (pub, rng, 0));
2✔
2044

2045
         ffi_test_pubkey_export(result, pub, priv, rng);
2✔
2046

2047
         botan_mp_t p, q, g, x, y;
2✔
2048
         botan_mp_init(&p);
2✔
2049
         botan_mp_init(&q);
2✔
2050
         botan_mp_init(&g);
2✔
2051
         botan_mp_init(&x);
2✔
2052
         botan_mp_init(&y);
2✔
2053

2054
         TEST_FFI_OK(botan_privkey_dsa_get_x, (x, priv));
2✔
2055
         TEST_FFI_OK(botan_pubkey_dsa_get_g, (g, pub));
2✔
2056
         TEST_FFI_OK(botan_pubkey_dsa_get_p, (p, pub));
2✔
2057
         TEST_FFI_OK(botan_pubkey_dsa_get_q, (q, pub));
2✔
2058
         TEST_FFI_OK(botan_pubkey_dsa_get_y, (y, pub));
2✔
2059

2060
         botan_mp_t cmp;
2✔
2061
         botan_mp_init(&cmp);
2✔
2062
         TEST_FFI_RC(BOTAN_FFI_ERROR_BAD_PARAMETER, botan_privkey_get_field, (cmp, priv, "quux"));
2✔
2063

2064
         TEST_FFI_OK(botan_privkey_get_field, (cmp, priv, "x"));
2✔
2065
         TEST_FFI_RC(1, botan_mp_equal, (cmp, x));
2✔
2066

2067
         TEST_FFI_OK(botan_privkey_get_field, (cmp, priv, "y"));
2✔
2068
         TEST_FFI_RC(1, botan_mp_equal, (cmp, y));
2✔
2069

2070
         TEST_FFI_OK(botan_privkey_get_field, (cmp, priv, "p"));
2✔
2071
         TEST_FFI_RC(1, botan_mp_equal, (cmp, p));
2✔
2072
         botan_mp_destroy(cmp);
2✔
2073

2074
         botan_privkey_t loaded_privkey;
2✔
2075
         TEST_FFI_OK(botan_privkey_load_dsa, (&loaded_privkey, p, q, g, x));
2✔
2076
         TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey, rng, 0));
2✔
2077

2078
         botan_pubkey_t loaded_pubkey;
2✔
2079
         TEST_FFI_OK(botan_pubkey_load_dsa, (&loaded_pubkey, p, q, g, y));
2✔
2080
         TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey, rng, 0));
2✔
2081

2082
         botan_mp_destroy(p);
2✔
2083
         botan_mp_destroy(q);
2✔
2084
         botan_mp_destroy(g);
2✔
2085
         botan_mp_destroy(y);
2✔
2086
         botan_mp_destroy(x);
2✔
2087

2088
         botan_pk_op_sign_t signer;
2✔
2089

2090
         std::vector<uint8_t> message(6, 6);
2✔
2091
         std::vector<uint8_t> signature;
2✔
2092

2093
         if(TEST_FFI_OK(botan_pk_op_sign_create, (&signer, loaded_privkey, "SHA-256", 0))) {
4✔
2094
            // TODO: break input into multiple calls to update
2095
            TEST_FFI_OK(botan_pk_op_sign_update, (signer, message.data(), message.size()));
2✔
2096

2097
            size_t sig_len;
2✔
2098
            TEST_FFI_OK(botan_pk_op_sign_output_length, (signer, &sig_len));
2✔
2099
            signature.resize(sig_len);
2✔
2100

2101
            size_t output_sig_len = sig_len;
2✔
2102
            TEST_FFI_OK(botan_pk_op_sign_finish, (signer, rng, signature.data(), &output_sig_len));
2✔
2103
            result.test_lte("Output length is upper bound", output_sig_len, sig_len);
2✔
2104
            signature.resize(output_sig_len);
2✔
2105

2106
            TEST_FFI_OK(botan_pk_op_sign_destroy, (signer));
4✔
2107
         }
2108

2109
         botan_pk_op_verify_t verifier = nullptr;
2✔
2110

2111
         if(!signature.empty() && TEST_FFI_OK(botan_pk_op_verify_create, (&verifier, pub, "SHA-256", 0))) {
4✔
2112
            TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
2✔
2113
            TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
2✔
2114

2115
            // TODO: randomize this
2116
            signature[0] ^= 1;
2✔
2117
            TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
2✔
2118
            TEST_FFI_RC(
2✔
2119
               BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
2120

2121
            message[0] ^= 1;
2✔
2122
            TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
2✔
2123
            TEST_FFI_RC(
2✔
2124
               BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
2125

2126
            signature[0] ^= 1;
2✔
2127
            TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
2✔
2128
            TEST_FFI_RC(
2✔
2129
               BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
2130

2131
            message[0] ^= 1;
2✔
2132
            TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
2✔
2133
            TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
2✔
2134

2135
            TEST_FFI_OK(botan_pk_op_verify_destroy, (verifier));
4✔
2136
         }
2137

2138
         TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey));
2✔
2139
         TEST_FFI_OK(botan_pubkey_destroy, (pub));
2✔
2140
         TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey));
2✔
2141
         TEST_FFI_OK(botan_privkey_destroy, (priv));
4✔
2142
      }
4✔
2143
};
2144

2145
class FFI_ECDSA_Test final : public FFI_Test {
×
2146
   public:
2147
      std::string name() const override { return "FFI ECDSA"; }
1✔
2148

2149
      void ffi_test(Test::Result& result, botan_rng_t rng) override {
1✔
2150
         static const char* kCurve = "secp384r1";
1✔
2151
         botan_privkey_t priv;
1✔
2152
         botan_pubkey_t pub;
1✔
2153

2154
         if(!TEST_FFI_INIT(botan_privkey_create_ecdsa, (&priv, rng, kCurve))) {
2✔
2155
            return;
×
2156
         }
2157

2158
         TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
1✔
2159
         ffi_test_pubkey_export(result, pub, priv, rng);
1✔
2160

2161
         // Check key load functions
2162
         botan_mp_t private_scalar, public_x, public_y;
1✔
2163
         botan_mp_init(&private_scalar);
1✔
2164
         botan_mp_init(&public_x);
1✔
2165
         botan_mp_init(&public_y);
1✔
2166

2167
         TEST_FFI_RC(BOTAN_FFI_ERROR_BAD_PARAMETER, botan_privkey_get_field, (private_scalar, priv, "quux"));
1✔
2168
         TEST_FFI_RC(BOTAN_FFI_ERROR_BAD_PARAMETER, botan_pubkey_get_field, (private_scalar, pub, "quux"));
1✔
2169

2170
         TEST_FFI_OK(botan_privkey_get_field, (private_scalar, priv, "x"));
1✔
2171
         TEST_FFI_OK(botan_pubkey_get_field, (public_x, pub, "public_x"));
1✔
2172
         TEST_FFI_OK(botan_pubkey_get_field, (public_y, pub, "public_y"));
1✔
2173

2174
         botan_privkey_t loaded_privkey;
1✔
2175
         botan_pubkey_t loaded_pubkey;
1✔
2176
         TEST_FFI_OK(botan_privkey_load_ecdsa, (&loaded_privkey, private_scalar, kCurve));
1✔
2177
         TEST_FFI_OK(botan_pubkey_load_ecdsa, (&loaded_pubkey, public_x, public_y, kCurve));
1✔
2178
         TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey, rng, 0));
1✔
2179
         TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey, rng, 0));
1✔
2180

2181
         char namebuf[32] = {0};
1✔
2182
         size_t name_len = sizeof(namebuf);
1✔
2183

2184
         TEST_FFI_OK(botan_pubkey_algo_name, (pub, &namebuf[0], &name_len));
1✔
2185
         result.test_eq(namebuf, namebuf, "ECDSA");
1✔
2186

2187
         std::vector<uint8_t> message(1280), signature;
1✔
2188
         TEST_FFI_OK(botan_rng_get, (rng, message.data(), message.size()));
1✔
2189

2190
         for(uint32_t flags = 0; flags <= 1; ++flags) {
3✔
2191
            botan_pk_op_sign_t signer;
2✔
2192
            if(TEST_FFI_INIT(botan_pk_op_sign_create, (&signer, loaded_privkey, "SHA-384", flags))) {
4✔
2193
               // TODO: break input into multiple calls to update
2194
               TEST_FFI_OK(botan_pk_op_sign_update, (signer, message.data(), message.size()));
2✔
2195

2196
               size_t sig_len;
2✔
2197
               TEST_FFI_OK(botan_pk_op_sign_output_length, (signer, &sig_len));
2✔
2198

2199
               signature.resize(sig_len);
2✔
2200

2201
               size_t output_sig_len = signature.size();
2✔
2202
               TEST_FFI_OK(botan_pk_op_sign_finish, (signer, rng, signature.data(), &output_sig_len));
2✔
2203
               signature.resize(output_sig_len);
2✔
2204

2205
               TEST_FFI_OK(botan_pk_op_sign_destroy, (signer));
4✔
2206
            }
2207

2208
            botan_pk_op_verify_t verifier = nullptr;
2✔
2209

2210
            if(!signature.empty() && TEST_FFI_OK(botan_pk_op_verify_create, (&verifier, pub, "SHA-384", flags))) {
4✔
2211
               TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
2✔
2212
               TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
2✔
2213

2214
               // TODO: randomize this
2215
               signature[0] ^= 1;
2✔
2216
               TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
2✔
2217
               TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER,
2✔
2218
                           botan_pk_op_verify_finish,
2219
                           (verifier, signature.data(), signature.size()));
2220

2221
               message[0] ^= 1;
2✔
2222
               TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
2✔
2223
               TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER,
2✔
2224
                           botan_pk_op_verify_finish,
2225
                           (verifier, signature.data(), signature.size()));
2226

2227
               signature[0] ^= 1;
2✔
2228
               TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
2✔
2229
               TEST_FFI_RC(BOTAN_FFI_INVALID_VERIFIER,
2✔
2230
                           botan_pk_op_verify_finish,
2231
                           (verifier, signature.data(), signature.size()));
2232

2233
               message[0] ^= 1;
2✔
2234
               TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
2✔
2235
               TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
2✔
2236

2237
               TEST_FFI_OK(botan_pk_op_verify_destroy, (verifier));
4✔
2238
            }
2239
         }
2240

2241
         TEST_FFI_OK(botan_mp_destroy, (private_scalar));
1✔
2242
         TEST_FFI_OK(botan_mp_destroy, (public_x));
1✔
2243
         TEST_FFI_OK(botan_mp_destroy, (public_y));
1✔
2244
         TEST_FFI_OK(botan_pubkey_destroy, (pub));
1✔
2245
         TEST_FFI_OK(botan_privkey_destroy, (priv));
1✔
2246
         TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey));
1✔
2247
         TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey));
2✔
2248
      }
2✔
2249
};
2250

2251
class FFI_SM2_Sig_Test final : public FFI_Test {
×
2252
   public:
2253
      std::string name() const override { return "FFI SM2 Sig"; }
1✔
2254

2255
      void ffi_test(Test::Result& result, botan_rng_t rng) override {
1✔
2256
         static const char* kCurve = "sm2p256v1";
1✔
2257
         const std::string sm2_ident = "SM2 Ident Field";
1✔
2258
         botan_privkey_t priv;
1✔
2259
         botan_pubkey_t pub;
1✔
2260
         botan_privkey_t loaded_privkey;
1✔
2261
         botan_pubkey_t loaded_pubkey;
1✔
2262

2263
         if(!TEST_FFI_INIT(botan_privkey_create, (&priv, "SM2_Sig", kCurve, rng))) {
2✔
2264
            return;
2265
         }
2266

2267
         TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
1✔
2268
         ffi_test_pubkey_export(result, pub, priv, rng);
1✔
2269

2270
         uint8_t za[32];
1✔
2271
         size_t sizeof_za = sizeof(za);
1✔
2272
         TEST_FFI_OK(botan_pubkey_sm2_compute_za, (za, &sizeof_za, "Ident", "SM3", pub));
1✔
2273

2274
         // Check key load functions
2275
         botan_mp_t private_scalar, public_x, public_y;
1✔
2276
         botan_mp_init(&private_scalar);
1✔
2277
         botan_mp_init(&public_x);
1✔
2278
         botan_mp_init(&public_y);
1✔
2279

2280
         TEST_FFI_OK(botan_privkey_get_field, (private_scalar, priv, "x"));
1✔
2281
         TEST_FFI_OK(botan_pubkey_get_field, (public_x, pub, "public_x"));
1✔
2282
         TEST_FFI_OK(botan_pubkey_get_field, (public_y, pub, "public_y"));
1✔
2283
         REQUIRE_FFI_OK(botan_privkey_load_sm2, (&loaded_privkey, private_scalar, kCurve));
2✔
2284
         REQUIRE_FFI_OK(botan_pubkey_load_sm2, (&loaded_pubkey, public_x, public_y, kCurve));
2✔
2285
         TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey, rng, 0));
1✔
2286
         TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey, rng, 0));
1✔
2287

2288
         char namebuf[32] = {0};
1✔
2289
         size_t name_len = sizeof(namebuf);
1✔
2290

2291
         TEST_FFI_OK(botan_pubkey_algo_name, (pub, &namebuf[0], &name_len));
1✔
2292
         result.test_eq(namebuf, namebuf, "SM2");
1✔
2293

2294
         std::vector<uint8_t> message(1280), signature;
1✔
2295
         TEST_FFI_OK(botan_rng_get, (rng, message.data(), message.size()));
1✔
2296
         botan_pk_op_sign_t signer;
1✔
2297
         if(TEST_FFI_OK(botan_pk_op_sign_create, (&signer, loaded_privkey, sm2_ident.c_str(), 0))) {
2✔
2298
            // TODO: break input into multiple calls to update
2299
            TEST_FFI_OK(botan_pk_op_sign_update, (signer, message.data(), message.size()));
1✔
2300

2301
            size_t sig_len;
1✔
2302
            TEST_FFI_OK(botan_pk_op_sign_output_length, (signer, &sig_len));
1✔
2303

2304
            signature.resize(sig_len);
1✔
2305

2306
            TEST_FFI_OK(botan_pk_op_sign_finish, (signer, rng, signature.data(), &sig_len));
1✔
2307
            signature.resize(sig_len);
1✔
2308

2309
            TEST_FFI_OK(botan_pk_op_sign_destroy, (signer));
2✔
2310
         }
2311

2312
         botan_pk_op_verify_t verifier = nullptr;
1✔
2313

2314
         if(!signature.empty() && TEST_FFI_OK(botan_pk_op_verify_create, (&verifier, pub, sm2_ident.c_str(), 0))) {
2✔
2315
            TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1✔
2316
            TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1✔
2317

2318
            // TODO: randomize this
2319
            signature[0] ^= 1;
1✔
2320
            TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1✔
2321
            TEST_FFI_RC(
1✔
2322
               BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
2323

2324
            message[0] ^= 1;
1✔
2325
            TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1✔
2326
            TEST_FFI_RC(
1✔
2327
               BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
2328

2329
            signature[0] ^= 1;
1✔
2330
            TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1✔
2331
            TEST_FFI_RC(
1✔
2332
               BOTAN_FFI_INVALID_VERIFIER, botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
2333

2334
            message[0] ^= 1;
1✔
2335
            TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1✔
2336
            TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1✔
2337

2338
            TEST_FFI_OK(botan_pk_op_verify_destroy, (verifier));
2✔
2339
         }
2340

2341
         TEST_FFI_OK(botan_mp_destroy, (private_scalar));
1✔
2342
         TEST_FFI_OK(botan_mp_destroy, (public_x));
1✔
2343
         TEST_FFI_OK(botan_mp_destroy, (public_y));
1✔
2344
         TEST_FFI_OK(botan_pubkey_destroy, (pub));
1✔
2345
         TEST_FFI_OK(botan_privkey_destroy, (priv));
1✔
2346
         TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey));
1✔
2347
         TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey));
2✔
2348
      }
2✔
2349
};
2350

2351
class FFI_SM2_Enc_Test final : public FFI_Test {
×
2352
   public:
2353
      std::string name() const override { return "FFI SM2 Enc"; }
1✔
2354

2355
      void ffi_test(Test::Result& result, botan_rng_t rng) override {
1✔
2356
         static const char* kCurve = "sm2p256v1";
1✔
2357
         botan_privkey_t priv;
1✔
2358
         botan_pubkey_t pub;
1✔
2359
         botan_privkey_t loaded_privkey;
1✔
2360
         botan_pubkey_t loaded_pubkey;
1✔
2361

2362
         if(!TEST_FFI_INIT(botan_privkey_create, (&priv, "SM2_Enc", kCurve, rng))) {
2✔
2363
            return;
×
2364
         }
2365

2366
         TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
1✔
2367
         ffi_test_pubkey_export(result, pub, priv, rng);
1✔
2368

2369
         uint8_t za[32];
1✔
2370
         size_t sizeof_za = sizeof(za);
1✔
2371
         TEST_FFI_OK(botan_pubkey_sm2_compute_za, (za, &sizeof_za, "Ident", "SM3", pub));
1✔
2372

2373
         // Check key load functions
2374
         botan_mp_t private_scalar, public_x, public_y;
1✔
2375
         botan_mp_init(&private_scalar);
1✔
2376
         botan_mp_init(&public_x);
1✔
2377
         botan_mp_init(&public_y);
1✔
2378

2379
         TEST_FFI_OK(botan_privkey_get_field, (private_scalar, priv, "x"));
1✔
2380
         TEST_FFI_OK(botan_pubkey_get_field, (public_x, pub, "public_x"));
1✔
2381
         TEST_FFI_OK(botan_pubkey_get_field, (public_y, pub, "public_y"));
1✔
2382
         REQUIRE_FFI_OK(botan_privkey_load_sm2_enc, (&loaded_privkey, private_scalar, kCurve));
2✔
2383
         REQUIRE_FFI_OK(botan_pubkey_load_sm2_enc, (&loaded_pubkey, public_x, public_y, kCurve));
2✔
2384
         TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey, rng, 0));
1✔
2385
         TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey, rng, 0));
1✔
2386

2387
         char namebuf[32] = {0};
1✔
2388
         size_t name_len = sizeof(namebuf);
1✔
2389

2390
         TEST_FFI_OK(botan_pubkey_algo_name, (pub, &namebuf[0], &name_len));
1✔
2391
         result.test_eq(namebuf, namebuf, "SM2");
1✔
2392

2393
         std::vector<uint8_t> message(32);
1✔
2394

2395
         std::vector<uint8_t> ciphertext;
1✔
2396
         TEST_FFI_OK(botan_rng_get, (rng, message.data(), message.size()));
1✔
2397

2398
         botan_pk_op_encrypt_t enc;
1✔
2399
         if(TEST_FFI_OK(botan_pk_op_encrypt_create, (&enc, loaded_pubkey, "", 0))) {
2✔
2400
            size_t ctext_len;
1✔
2401
            TEST_FFI_OK(botan_pk_op_encrypt_output_length, (enc, message.size(), &ctext_len));
1✔
2402

2403
            ciphertext.resize(ctext_len);
1✔
2404
            TEST_FFI_OK(botan_pk_op_encrypt, (enc, rng, ciphertext.data(), &ctext_len, message.data(), message.size()));
1✔
2405
            ciphertext.resize(ctext_len);
1✔
2406

2407
            botan_pk_op_decrypt_t dec;
1✔
2408
            TEST_FFI_OK(botan_pk_op_decrypt_create, (&dec, loaded_privkey, "", 0));
1✔
2409

2410
            std::vector<uint8_t> recovered(message.size());
1✔
2411
            size_t recovered_len = recovered.size();
1✔
2412

2413
            TEST_FFI_OK(botan_pk_op_decrypt,
1✔
2414
                        (dec, recovered.data(), &recovered_len, ciphertext.data(), ciphertext.size()));
2415

2416
            botan_pk_op_decrypt_destroy(dec);
1✔
2417
         }
1✔
2418
         botan_pk_op_encrypt_destroy(enc);
1✔
2419

2420
         TEST_FFI_OK(botan_mp_destroy, (private_scalar));
1✔
2421
         TEST_FFI_OK(botan_mp_destroy, (public_x));
1✔
2422
         TEST_FFI_OK(botan_mp_destroy, (public_y));
1✔
2423
         TEST_FFI_OK(botan_pubkey_destroy, (pub));
1✔
2424
         TEST_FFI_OK(botan_privkey_destroy, (priv));
1✔
2425
         TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey));
1✔
2426
         TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey));
2✔
2427
      }
2✔
2428
};
2429

2430
class FFI_ECDH_Test final : public FFI_Test {
×
2431
   public:
2432
      std::string name() const override { return "FFI ECDH"; }
1✔
2433

2434
      void ffi_test(Test::Result& result, botan_rng_t rng) override {
1✔
2435
         botan_privkey_t priv1;
1✔
2436
         if(!TEST_FFI_INIT(botan_privkey_create_ecdh, (&priv1, rng, "secp256r1"))) {
2✔
2437
            return;
×
2438
         }
2439

2440
         botan_privkey_t priv2;
1✔
2441
         REQUIRE_FFI_OK(botan_privkey_create_ecdh, (&priv2, rng, "secp256r1"));
2✔
2442

2443
         botan_pubkey_t pub1;
1✔
2444
         REQUIRE_FFI_OK(botan_privkey_export_pubkey, (&pub1, priv1));
2✔
2445

2446
         botan_pubkey_t pub2;
1✔
2447
         REQUIRE_FFI_OK(botan_privkey_export_pubkey, (&pub2, priv2));
2✔
2448

2449
         /* Reload key-pair1 in order to test functions for key loading */
2450
         botan_mp_t private_scalar, public_x, public_y;
1✔
2451
         botan_mp_init(&private_scalar);
1✔
2452
         botan_mp_init(&public_x);
1✔
2453
         botan_mp_init(&public_y);
1✔
2454

2455
         TEST_FFI_OK(botan_privkey_get_field, (private_scalar, priv1, "x"));
1✔
2456
         TEST_FFI_OK(botan_pubkey_get_field, (public_x, pub1, "public_x"));
1✔
2457
         TEST_FFI_OK(botan_pubkey_get_field, (public_y, pub1, "public_y"));
1✔
2458

2459
         botan_privkey_t loaded_privkey1;
1✔
2460
         botan_pubkey_t loaded_pubkey1;
1✔
2461
         REQUIRE_FFI_OK(botan_privkey_load_ecdh, (&loaded_privkey1, private_scalar, "secp256r1"));
2✔
2462
         REQUIRE_FFI_OK(botan_pubkey_load_ecdh, (&loaded_pubkey1, public_x, public_y, "secp256r1"));
2✔
2463
         TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey1, rng, 0));
1✔
2464
         TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey1, rng, 0));
1✔
2465

2466
         ffi_test_pubkey_export(result, loaded_pubkey1, priv1, rng);
1✔
2467
         ffi_test_pubkey_export(result, pub2, priv2, rng);
1✔
2468

2469
         botan_pk_op_ka_t ka1;
1✔
2470
         REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka1, loaded_privkey1, "KDF2(SHA-256)", 0));
2✔
2471
         botan_pk_op_ka_t ka2;
1✔
2472
         REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka2, priv2, "KDF2(SHA-256)", 0));
2✔
2473

2474
         size_t pubkey1_len = 0;
1✔
2475
         TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
1✔
2476
                     botan_pk_op_key_agreement_export_public,
2477
                     (priv1, nullptr, &pubkey1_len));
2478
         std::vector<uint8_t> pubkey1(pubkey1_len);
1✔
2479
         REQUIRE_FFI_OK(botan_pk_op_key_agreement_export_public, (priv1, pubkey1.data(), &pubkey1_len));
2✔
2480
         size_t pubkey2_len = 0;
1✔
2481
         TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
1✔
2482
                     botan_pk_op_key_agreement_export_public,
2483
                     (priv2, nullptr, &pubkey2_len));
2484
         std::vector<uint8_t> pubkey2(pubkey2_len);
1✔
2485
         REQUIRE_FFI_OK(botan_pk_op_key_agreement_export_public, (priv2, pubkey2.data(), &pubkey2_len));
2✔
2486

2487
         std::vector<uint8_t> salt(32);
1✔
2488
         TEST_FFI_OK(botan_rng_get, (rng, salt.data(), salt.size()));
1✔
2489

2490
         const size_t shared_key_len = 64;
1✔
2491

2492
         std::vector<uint8_t> key1(shared_key_len);
1✔
2493
         size_t key1_len = key1.size();
1✔
2494
         TEST_FFI_OK(botan_pk_op_key_agreement,
1✔
2495
                     (ka1, key1.data(), &key1_len, pubkey2.data(), pubkey2.size(), salt.data(), salt.size()));
2496

2497
         std::vector<uint8_t> key2(shared_key_len);
1✔
2498
         size_t key2_len = key2.size();
1✔
2499
         TEST_FFI_OK(botan_pk_op_key_agreement,
1✔
2500
                     (ka2, key2.data(), &key2_len, pubkey1.data(), pubkey1.size(), salt.data(), salt.size()));
2501

2502
         result.test_eq("shared ECDH key", key1, key2);
1✔
2503

2504
         TEST_FFI_OK(botan_mp_destroy, (private_scalar));
1✔
2505
         TEST_FFI_OK(botan_mp_destroy, (public_x));
1✔
2506
         TEST_FFI_OK(botan_mp_destroy, (public_y));
1✔
2507
         TEST_FFI_OK(botan_pk_op_key_agreement_destroy, (ka1));
1✔
2508
         TEST_FFI_OK(botan_pk_op_key_agreement_destroy, (ka2));
1✔
2509
         TEST_FFI_OK(botan_privkey_destroy, (priv1));
1✔
2510
         TEST_FFI_OK(botan_privkey_destroy, (priv2));
1✔
2511
         TEST_FFI_OK(botan_pubkey_destroy, (pub1));
1✔
2512
         TEST_FFI_OK(botan_pubkey_destroy, (pub2));
1✔
2513
         TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey1));
1✔
2514
         TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey1));
2✔
2515
      }
5✔
2516
};
2517

2518
class FFI_McEliece_Test final : public FFI_Test {
×
2519
   public:
2520
      std::string name() const override { return "FFI McEliece"; }
1✔
2521

2522
      void ffi_test(Test::Result& result, botan_rng_t rng) override {
1✔
2523
         botan_privkey_t priv;
1✔
2524
         if(TEST_FFI_INIT(botan_privkey_create_mceliece, (&priv, rng, 2048, 50))) {
2✔
2525
            botan_pubkey_t pub;
1✔
2526
            TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
1✔
2527

2528
            ffi_test_pubkey_export(result, pub, priv, rng);
1✔
2529

2530
            char namebuf[32] = {0};
1✔
2531
            size_t name_len = sizeof(namebuf);
1✔
2532
            if(TEST_FFI_OK(botan_pubkey_algo_name, (pub, namebuf, &name_len))) {
2✔
2533
               result.test_eq("algo name", std::string(namebuf), "McEliece");
2✔
2534
            }
2535

2536
            // TODO test KEM
2537

2538
            TEST_FFI_OK(botan_pubkey_destroy, (pub));
1✔
2539
            TEST_FFI_OK(botan_privkey_destroy, (priv));
2✔
2540
         }
2541
      }
1✔
2542
};
2543

2544
class FFI_Ed25519_Test final : public FFI_Test {
×
2545
   public:
2546
      std::string name() const override { return "FFI Ed25519"; }
1✔
2547

2548
      void ffi_test(Test::Result& result, botan_rng_t rng) override {
1✔
2549
         botan_pubkey_t pub;
1✔
2550
         botan_privkey_t priv;
1✔
2551

2552
         // From draft-koch-eddsa-for-openpgp-04
2553
         const std::vector<uint8_t> seed =
1✔
2554
            Botan::hex_decode("1a8b1ff05ded48e18bf50166c664ab023ea70003d78d9e41f5758a91d850f8d2");
1✔
2555
         const std::vector<uint8_t> pubkey =
1✔
2556
            Botan::hex_decode("3f098994bdd916ed4053197934e4a87c80733a1280d62f8010992e43ee3b2406");
1✔
2557
         const std::vector<uint8_t> message = Botan::hex_decode("4f70656e504750040016080006050255f95f9504ff0000000c");
1✔
2558
         const std::vector<uint8_t> exp_sig = Botan::hex_decode(
1✔
2559
            "56f90cca98e2102637bd983fdb16c131dfd27ed82bf4dde5606e0d756aed3366"
2560
            "d09c4fa11527f038e0f57f2201d82f2ea2c9033265fa6ceb489e854bae61b404");
1✔
2561

2562
         if(!TEST_FFI_INIT(botan_privkey_load_ed25519, (&priv, seed.data()))) {
2✔
2563
            return;
×
2564
         }
2565

2566
         uint8_t retr_privkey[64];
1✔
2567
         TEST_FFI_OK(botan_privkey_ed25519_get_privkey, (priv, retr_privkey));
1✔
2568

2569
         result.test_eq(nullptr, "Public key matches", retr_privkey + 32, 32, pubkey.data(), pubkey.size());
1✔
2570

2571
         TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
1✔
2572

2573
         uint8_t retr_pubkey[32];
1✔
2574
         TEST_FFI_OK(botan_pubkey_ed25519_get_pubkey, (pub, retr_pubkey));
1✔
2575
         result.test_eq(nullptr, "Public key matches", retr_pubkey, 32, pubkey.data(), pubkey.size());
1✔
2576

2577
         TEST_FFI_OK(botan_pubkey_destroy, (pub));
1✔
2578
         TEST_FFI_OK(botan_pubkey_load_ed25519, (&pub, pubkey.data()));
1✔
2579

2580
         botan_pk_op_sign_t signer;
1✔
2581
         std::vector<uint8_t> signature;
1✔
2582

2583
         if(TEST_FFI_OK(botan_pk_op_sign_create, (&signer, priv, "SHA-256", 0))) {
2✔
2584
            TEST_FFI_OK(botan_pk_op_sign_update, (signer, message.data(), message.size()));
1✔
2585

2586
            size_t sig_len;
1✔
2587
            TEST_FFI_OK(botan_pk_op_sign_output_length, (signer, &sig_len));
1✔
2588

2589
            signature.resize(sig_len);
1✔
2590

2591
            TEST_FFI_OK(botan_pk_op_sign_finish, (signer, rng, signature.data(), &sig_len));
1✔
2592
            signature.resize(sig_len);
1✔
2593

2594
            TEST_FFI_OK(botan_pk_op_sign_destroy, (signer));
2✔
2595
         }
2596

2597
         result.test_eq("Expected signature", signature, exp_sig);
1✔
2598

2599
         botan_pk_op_verify_t verifier;
1✔
2600

2601
         if(TEST_FFI_OK(botan_pk_op_verify_create, (&verifier, pub, "SHA-256", 0))) {
2✔
2602
            TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
1✔
2603
            TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
1✔
2604

2605
            TEST_FFI_OK(botan_pk_op_verify_destroy, (verifier));
2✔
2606
         }
2607

2608
         TEST_FFI_OK(botan_pubkey_destroy, (pub));
1✔
2609
         TEST_FFI_OK(botan_privkey_destroy, (priv));
2✔
2610
      }
5✔
2611
};
2612

2613
class FFI_X25519_Test final : public FFI_Test {
×
2614
   public:
2615
      std::string name() const override { return "FFI X25519"; }
1✔
2616

2617
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
2618
         // From RFC 8037
2619

2620
         const std::vector<uint8_t> a_pub_bits =
1✔
2621
            Botan::hex_decode("de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f");
1✔
2622
         const std::vector<uint8_t> b_priv_bits =
1✔
2623
            Botan::hex_decode("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a");
1✔
2624
         const std::vector<uint8_t> b_pub_bits =
1✔
2625
            Botan::hex_decode("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a");
1✔
2626
         const std::vector<uint8_t> shared_secret_bits =
1✔
2627
            Botan::hex_decode("4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742");
1✔
2628

2629
         botan_privkey_t b_priv;
1✔
2630
         if(!TEST_FFI_INIT(botan_privkey_load_x25519, (&b_priv, b_priv_bits.data()))) {
2✔
2631
            return;
2632
         }
2633

2634
         std::vector<uint8_t> privkey_read(32);
1✔
2635
         TEST_FFI_OK(botan_privkey_x25519_get_privkey, (b_priv, privkey_read.data()));
1✔
2636
         result.test_eq("X25519 private key", privkey_read, b_priv_bits);
1✔
2637

2638
         std::vector<uint8_t> pubkey_read(32);
1✔
2639

2640
         botan_pubkey_t b_pub;
1✔
2641
         TEST_FFI_OK(botan_privkey_export_pubkey, (&b_pub, b_priv));
1✔
2642
         TEST_FFI_OK(botan_pubkey_x25519_get_pubkey, (b_pub, pubkey_read.data()));
1✔
2643
         result.test_eq("X25519 public key b", pubkey_read, b_pub_bits);
1✔
2644

2645
         botan_pubkey_t a_pub;
1✔
2646
         TEST_FFI_OK(botan_pubkey_load_x25519, (&a_pub, a_pub_bits.data()));
1✔
2647
         TEST_FFI_OK(botan_pubkey_x25519_get_pubkey, (a_pub, pubkey_read.data()));
1✔
2648
         result.test_eq("X25519 public key a", pubkey_read, a_pub_bits);
1✔
2649

2650
         botan_pk_op_ka_t ka;
1✔
2651
         REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka, b_priv, "Raw", 0));
2✔
2652

2653
         std::vector<uint8_t> shared_output(32);
1✔
2654
         size_t shared_len = shared_output.size();
1✔
2655
         TEST_FFI_OK(botan_pk_op_key_agreement,
1✔
2656
                     (ka, shared_output.data(), &shared_len, a_pub_bits.data(), a_pub_bits.size(), nullptr, 0));
2657

2658
         result.test_eq("Shared secret matches expected", shared_secret_bits, shared_output);
1✔
2659

2660
         TEST_FFI_OK(botan_pubkey_destroy, (a_pub));
1✔
2661
         TEST_FFI_OK(botan_pubkey_destroy, (b_pub));
1✔
2662
         TEST_FFI_OK(botan_privkey_destroy, (b_priv));
1✔
2663
         TEST_FFI_OK(botan_pk_op_key_agreement_destroy, (ka));
2✔
2664
      }
7✔
2665
};
2666

2667
int botan_ffi_view_u8_fn(void* ctx, const uint8_t buf[], size_t len) {
9✔
2668
   if(!ctx || !buf) {
9✔
2669
      return BOTAN_FFI_ERROR_NULL_POINTER;
2670
   }
2671

2672
   std::memcpy(ctx, buf, len);
9✔
2673

2674
   return 0;
9✔
2675
}
2676

2677
class FFI_Kyber512_Test final : public FFI_Test {
×
2678
   public:
2679
      std::string name() const override { return "FFI Kyber512"; }
1✔
2680

2681
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
2682
         const std::vector<uint8_t> a_pub_bits = Botan::hex_decode(
1✔
2683
            "5fc44b99d7584f38cd28360cc5625a905b96af12930ed5b5fe2a82fc5aa7dc4b829fe37635f13f5af2a6d3081dad878785698a0aa914374c4e43b89f094a7892aa149a38b49c06a068d829a8d249e753a375d097a0f162e6c3a4dfe8c79761410c605ed3899a3fc44378e14f28879e8f148077e6bc3bb2ae56178c491611bf6aaf5f9a9cb9b5659223007940bcd6f8a23280a56015330e8577259587b12606f4c937ea13606cb3bb046066ad294261e2b22022bcc74678a5520570d88e4ceb42692631e7e3711c4b2fd5347f0328598340cb3c65c8f55ac02716831094cb6eb90f175b173d9c650329aaf513633633bb2ce6858e7447abc41b6fb06da8782572c332b09660366926bf529ed8caaa6243ccdb152b36ba6e47c714145c86f5b3b61de84ef1470d03fa0135e35194fa1fb3bc860fa500d1299aee88ce56054376c1199c553dd90a8d6f9cc763c811d0c66da6f851abf1056635a34a68aa7815868f153a3a5c77fcc8b1eb1807fbf62a6fb43b355700e78230943a2ba1e11b181345b11b4d46266e7b359f074a500c8857d79ba60f64262d662ccd9c8489a4c19df67437db193f95b9765181d9152262b1166f97be53497f001cb1be79024d6a2289bcc704e1b1d821015366a3cc8a484e6bc2e1f1b889f19323e3101aa09ad9ea62ba4005039bbfb5998055f93fbf77b14433116d5958422654dada1127213f02b78717a5a0454271d5b0c02517a6c27a3c3610101d753c09a25571775477dc13b2e404db4965b9a9350330c73a8a3642d39af8a23839ab85c6355b12f279f849813c280d54c5913e99b6946a0aaf012c8cab025396b255f002d837c761d42a4aeb38c5f456aaf79e162700c6b4048eca6f9a7367f90238d67bcf8e6a0d8a553c071522f9d2394e28483d2048be2a8f9c8c8e39991a41273c7eacaefc6a308be870b45b41176412954a1a0fd83d362a5ab288663dec5456b6286d0b2cecb01922fb3d473802ea2b86639bce02450339261cffb114e1e725e90677826a1688f686b29a78779c9822315dafc55753e98c8ed3221f2b3220805c8a28983355207da36fb72f9bc85c0a13b9d041586fd583feb12afd5a402dd33b43543f5fa4eb436c8d");
1✔
2684
         const std::vector<uint8_t> b_priv_bits = Botan::hex_decode(
1✔
2685
            "cf8c33fabbc3e6685f60779a456412e9060a792a3f67d90389815773e06dd2071e3906a1159921485b6221b73dfc723da9d45bbc99523c55b203f81856ba8d38f731c6594a0a9796f485c7cad02ee3a80a737cada2e40b580a1060a1364d365169539ce4d800eab9723153c5b266853b3a33112ccb03491e77f57aeb74c7670426c5bb02615b1907b353beda51f38a788774b1c9eb3c49f89df59ba00e196f180a37fd9acd6691b493d78f95a49906b26fa46125663a37b0b2614197473ba012956bc9348a9afc8907527bb7c2dcbd384b85630b3687096ffd9a93d603121706c06c05baca286bebea0ecdf391ba489d7ff6a7a1c7c3dd0c521c02bb3fa7c3e5b98f19509486ab33f1597346b03c7197865792896c1a553e8379c6f51729e9907d09b4fbc5b4279298f60195998225d95c2aef335c9e6a26f4988e0f19c307fc00f8aa0b21090daab0c540363f121044729322bebb97427227e8b01705826879ab4d42e30bf191068b705527a3ae9a5b3e30371c50b5b75d189903e60175f904c1488be7e872d3dc3be1bb31921027cb075f6bb051c28980c65b9959e8acf2d38671d27285d03419512008335492476e0c23ac6263425f8a65fbc1a38110b38db641f3a9872fa312d26b9c81f11de1d9378b629e9bdc7ca31496ac9511bff42a7a96b28f740a84c2904fe4056ca1989b28439222cee31c554e982d318366037070c4bb778b261e3479c605317922947e4340560732ca8fda63e2a7ac8cc67015e97d308c361e634f8cdb1e836b572367334c949011a9c52f391194baa91f08a71e847d3be202554ab1c4f871c9b26db5f4992db5b3688b1ea877925d02895d470b9659c51213b206b82de489455c6502856b841d000aab3c065ff6720f9222914b6421224d716684a7762fc98ba7f4655f4cfa82fc52472b01b1e22255fc990b20240b802034c99777b71b5c0d8a4c733b69d5f76ddfdb1128da3e194c1169a924f5d868d1dbc4ddcb30197c25005391c1fcc098010af1e9ab72bc8c3bd1c58b15583035bc2dd0898e148fb20b8c502a31489b00dd645ab24709bff5c37d1a7fee5c56d7490ae77a61b1c5951e359d2a89a946f200b1f647c0283de5d403282c693dfccca1c1b54804ab86f36e1f16550a77b75328916c770c225b142dfb750659ba6d532003f8b6d48825b122682051acda7c20f09117b3e5c93e8c1bd446672512947d964f0484a05b85af82f4401d323484d23373c0c6c8990a3fba70f8a2c13e7350ce945c8f4882b1929f10d18bb45a883c116d1ce06493a50580069743d26062da9171006405d27e2f7220a897024dca507b737a6c32ba3d925e15c9789589507a768ca075beb2fb17a17144c52810566a972dba60ad806a2ff15957a3bbd85a8f1ef34445d18cc668ca7a8ac5fc7545934221a4c92c60024069cc34d592ac30c88c3376bc133622e2b192e9b4b60a9a84e5304873e62d6f98103cc8c43f6024fb7739418cc2602b21416040220cb3ec588679c033d61a3c697c403463c17c13a63d7304044a9f024b907b440b39b7b6423723dda943447a900af0170144755d9a968f634e26f892ee19cd00a97b48d5041b4473ec8741e077126f85bbb8334b8b2cbd63429afa543a540740c1e56893f6b2f2f7c42a12bcd48c647726cca06841212656ff9b3d3e799e92c48414d653a61ca8dc2c49b7342469a868b7938db8d7844e6311134b2c30538ffa927ee3961a44e0a66438c5643aa1d13658fe8a7c2a84702a8211422831994ca1e801131ab88a25162d3cd988ebe09e6cb01ca7324256691635c536f576990664841b7c89b0dc325472271fdc2b0824a9514b5eb46a743f9734ee20648a407f5d505cc9614748f344a16950b5483e45516236d43afd1494d564c23e20b64a124593604404c879a776a5bd9399629600e86aa1a641be7a13418cda318bbc3af0c2a66c999841251a1c2868b05028f6a56a72c33d8a653c77f69af4247dc6f80d329921ce3355894605c35372ddf0c84cacb42d6ccbdf39a55b672a891749622a011747a01625764c788413f2c0fd877275c88fd5730fa9e87a3c783702223a4443525cc5b5381c976dd9cb08ac47490125ca5c70baac01ff9143bc40ceeb2a16c1529d70c07074a0013749656ff4b16d890868b26c99bf8461495793bbb1b12ca369c825cb31d68731326bf4764b416bb3338e5d6352d5a5006d7cd901489e7f851711c08e00cd4162ccfc2564d5893d52b2c7300e2d894b0eaa40a6ab254506d8c1176a33c4a1b2879604b1b80df48d31dd");
1✔
2686
         const std::vector<uint8_t> b_pub_bits = Botan::hex_decode(
1✔
2687
            "ee5c56d7490ae77a61b1c5951e359d2a89a946f200b1f647c0283de5d403282c693dfccca1c1b54804ab86f36e1f16550a77b75328916c770c225b142dfb750659ba6d532003f8b6d48825b122682051acda7c20f09117b3e5c93e8c1bd446672512947d964f0484a05b85af82f4401d323484d23373c0c6c8990a3fba70f8a2c13e7350ce945c8f4882b1929f10d18bb45a883c116d1ce06493a50580069743d26062da9171006405d27e2f7220a897024dca507b737a6c32ba3d925e15c9789589507a768ca075beb2fb17a17144c52810566a972dba60ad806a2ff15957a3bbd85a8f1ef34445d18cc668ca7a8ac5fc7545934221a4c92c60024069cc34d592ac30c88c3376bc133622e2b192e9b4b60a9a84e5304873e62d6f98103cc8c43f6024fb7739418cc2602b21416040220cb3ec588679c033d61a3c697c403463c17c13a63d7304044a9f024b907b440b39b7b6423723dda943447a900af0170144755d9a968f634e26f892ee19cd00a97b48d5041b4473ec8741e077126f85bbb8334b8b2cbd63429afa543a540740c1e56893f6b2f2f7c42a12bcd48c647726cca06841212656ff9b3d3e799e92c48414d653a61ca8dc2c49b7342469a868b7938db8d7844e6311134b2c30538ffa927ee3961a44e0a66438c5643aa1d13658fe8a7c2a84702a8211422831994ca1e801131ab88a25162d3cd988ebe09e6cb01ca7324256691635c536f576990664841b7c89b0dc325472271fdc2b0824a9514b5eb46a743f9734ee20648a407f5d505cc9614748f344a16950b5483e45516236d43afd1494d564c23e20b64a124593604404c879a776a5bd9399629600e86aa1a641be7a13418cda318bbc3af0c2a66c999841251a1c2868b05028f6a56a72c33d8a653c77f69af4247dc6f80d329921ce3355894605c35372ddf0c84cacb42d6ccbdf39a55b672a891749622a011747a01625764c788413f2c0fd877275c88fd5730fa9e87a3c783702223a4443525cc5b5381c976dd9cb08ac47490125ca5c70baac01ff9143bc40ceeb2a16c1529d70c07074a0013749656ff4b16d890868b26c99bf8461495793bbb1b12ca369c825cb31d68731326bf4764b416bb333");
1✔
2688

2689
         botan_privkey_t b_priv;
1✔
2690
         if(!TEST_FFI_INIT(botan_privkey_load_kyber, (&b_priv, b_priv_bits.data(), 1632))) {
2✔
2691
            return;
×
2692
         }
2693

2694
         std::vector<uint8_t> privkey_read(1632);
1✔
2695
         TEST_FFI_OK(botan_privkey_view_kyber_raw_key, (b_priv, privkey_read.data(), botan_ffi_view_u8_fn));
1✔
2696
         result.test_eq("kyber512 private key", privkey_read, b_priv_bits);
1✔
2697

2698
         std::vector<uint8_t> pubkey_read(800);
1✔
2699

2700
         botan_pubkey_t b_pub;
1✔
2701
         TEST_FFI_OK(botan_privkey_export_pubkey, (&b_pub, b_priv));
1✔
2702
         TEST_FFI_OK(botan_pubkey_view_kyber_raw_key, (b_pub, pubkey_read.data(), botan_ffi_view_u8_fn));
1✔
2703
         result.test_eq("kyber512 public key b", pubkey_read, b_pub_bits);
1✔
2704

2705
         botan_pubkey_t a_pub;
1✔
2706
         TEST_FFI_OK(botan_pubkey_load_kyber, (&a_pub, a_pub_bits.data(), 800));
1✔
2707
         TEST_FFI_OK(botan_pubkey_view_kyber_raw_key, (a_pub, pubkey_read.data(), botan_ffi_view_u8_fn));
1✔
2708
         result.test_eq("kyber512 public key a", pubkey_read, a_pub_bits);
1✔
2709

2710
         TEST_FFI_OK(botan_pubkey_destroy, (a_pub));
1✔
2711
         TEST_FFI_OK(botan_pubkey_destroy, (b_pub));
1✔
2712
         TEST_FFI_OK(botan_privkey_destroy, (b_priv));
2✔
2713
      }
5✔
2714
};
2715

2716
class FFI_Kyber768_Test final : public FFI_Test {
×
2717
   public:
2718
      std::string name() const override { return "FFI Kyber768"; }
1✔
2719

2720
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
2721
         const std::vector<uint8_t> a_pub_bits = Botan::hex_decode(
1✔
2722
            "38d4851e5c010da39a7470bc1c80916f78c7bd5891dcd3b1ea84b6f051b346b803c1b97c94604020b7279b27836c3049ea0b9a3758510b7559593237ade72587462206b709f365848c96559326a5fe6c6f4cf531fd1a18477267f66ba14af20163c41f1138a01995147f271ddfc2be5361b281e6029d210584b2859b7383667284f767bb32782baad10933da0138a3a0660a149531c03f9c8ffccb33e3c3a5a7984e21fab26aa72a8a6b942f265e52551a9c800e5a44805f0c0141a05554213387f105df56458496bd8f469051886da223cb9fe78e7b390bf94b0a937691af9550082b76d045cb4d29c23c67942608d078a1c80f24767a945d19f077d82c9b9b197073464abe69cf7c5626177308f384672d5263b0c4826db4470e1a70e4751e3918abe8fcbc3bc0531ae89e5512214b5cc94a16a014bcb3826c79fbf4add0825eeefbab88cb7cff37bb8d491f8de902578a1e961655565b7718782a23504fdc13c783f130e177925e305d1fbc63cc8c15c2c67f85500cca785de9f480490558ef71aaf0fb5b513914401269b309c4c59c64d2a757d8855f58465615925f1ea6812cb143fff383e1048e285118bf932944b86fbdf4b1b9e65685664a07775c46952aaada1168f54b47c7a231e7355c64637467b5a3c09cab67bb35f58640c2726283bb63530a15f66eca48a840c00ca8862e283c73bfbb413a2915b8d1159a043f12c59bfa828248249b76106faa61a127a0280c586350e7a42cb74ca49cabd606891ec7cb8e84affe4b2e14c71658332b755611bab7977fa76ce736b21ed34a17ac0ec3561ca9b282d4a2bc407697924b1cf918ba83d3a4fdc82564c95bd904bdeee91ed6ccb36baa88a05c80712901bf280aee6538ec2078c2a84ee5862fc137cd92e97968d69fc3453a1e1cb161c50c9f2473a0d09037b188a0fa01efc344c2ac8fe8592b0a58456662a95033659a158a2d90a6e50c253a87975785ce29c4570000a154d4b3b2c642205c8c7cf9ac6b1071fbb368ab950a744b88c95ba5243017831120a9048338d29847830d12a933a09abd21a46b828cb14e808cd35129c9dc6e5b931d4a126fefe07909618e2b4586e7b6b424963b7323ba505ba112bb9b834a7d1b78ad0df53d556a1c69369f09148b1dc9938df59223f087fd6833be5b2bc2651fe58911ac01467f9297dfdc22b41a0f1702718710b78cf35b1865813a896d45214d338155b6c043c532330c002d520739467a504a866637fb3451c849f8f83e6a94147f168da53acdf9d8affd968a84124a9abc09af960cd3b29f2344831bb41e67605eebf00df202857117399dd748b6514aed61bb2f6cb841d168d5f35e20054573a331cd4882a04b072c179158825bcf471266da0dcceab1a021c73254751d5a161c1a92062c220a217a69d9823314b4de996fe8d45f6db5af16c1561495a4c43090bc394c94e1b0ec738eb56267201c2ecd1c7b4993c0efc0284bdc9a091c294f95703a7178822c8a95b79b1e4591e0998d893875c1a879c08a073cc67df426bba792c18ae6c1feba879bec54812c2affa012973b700ad48e271078280864268600a7aa309eaa1098750a0f8a522eb929577b412f7855613688b72f9bc85c0a13b9d041586fd583feb12afd5a402dd33b43543f5fa4eb436c8d");
1✔
2723
         const std::vector<uint8_t> b_priv_bits = Botan::hex_decode(
1✔
2724
            "9bc4986eec853ac90896c7300f914216773baa687f57f81f94e6b5a26515c0a74c73b19dc6b9888755a1d1db6a1128b02c5144ed9ba75e874a68a14dee3a9bf770b767121fbbdb292e097444757fe2f324a875b0a07a4fbdcc8fd6137fce80c69f412be103b01f8b3bed392600f830d1b20d73ca0b386666d16c5d96db10e309041890bfd4ab7bdec27191979abe7637e76153918cc2af1545724abfd95ca496281a0cc6ca63a87819b75aa86452e5027d429cad64a9c029112a3a7b9fb993c6a6d0671f6c9e24986b83f67cf1236d94c051559616826a947eaa15074025d1ab810c80220e8a8c2c222d4e8594bf35811b444a57e9bf94fb2479d174d6b38c8c3b4730437c244b2513232ec798adec4a8e597bca83bca5948468f93c022ba65311a91e3d95c299c70c3f1a43cd0c83dd500bd2211b9b385b82f2c003b10d295765b3e367563a5f19033fc1231db9620f835c95f5a261190a5da1c24ed528316f0a1520d223e208a8c99b24d28598ade74fc88370e7f45102c5a6411891c661b356b9a32e1cc0fafaa085d7670e8bcb5e768eb255204f2445b5b73b04079881903a553c865744343a925c7899777b1c9dd5579a481512f8157061606a9a67c041d38bc179048be17dd9e19dc0a572bce595afa3b68ff21bf78a63a7560636b6bb01ec3362e2aaabc8965818b7f2417ca8f66a5a2a67f72a3931e125d638a872862a7b680a54aa1f25d90dbd567635ec6664919e29517325a5c5048cc8d1c31af5e4866e85025b9184a7b75ed7f2c9c8d88259fa2ec5b05ed3751584f88308c67ff1a72fa2453305160baf404db7d4be56f1547b20bb7dec23f02b10db584b28ca40d8b39c1c3ab9f3d7bbda0822604ca48f26694d69810aa888ae3c0983c5ba4cb74211f7a5361ccdee694f4202aebe13a75b1b2dda1b3232376be213582afc4fde3474766671fe865e2fd98384eb65b2f349f1e24269b91bd9d08c80849735a9951304afd130b5c2211314630aed4b6ac3b1252a0999ff5a3ec26a283342389d219fd243706128b389eb2334fb2a6184a4eab6735d7428df5633ce030b8f853ee47c4401fc5d06b43c9b66b7aeeb23b5f000a30a6f88f027ee3994fe8b63e51b83bc24bb733a3773a35cbe138f6d9c91a3a3898bca6776030d740ac355176547d624719656a9a44e91c63faf7699dc6c2c45575718d48828828b39043c2fda2af416837efc38d17c56d4b63c63a5ab43434647d029f7b236b288958f06910763610f8b2f027a8dcd780039ab34a6871427476ff6500240e83b87c95dcfa45ac5315ef34b343fb609eb296e915c849bb8c57f57c69b177eaa8456377403fe8c6627a3282d45308f675d67085a15f0b1b55aa2a8f21afd6c05c3c00e9eb8c32418cb41963ce427b43e7545c58325c7b9368db2333de424dbeb3430f007d18a68d73b7dc67960b28206a68a1be400a770b5cd9d45a72824ca00345ac56491c1414fe5287a2eb2ad61f3bdcd0c84c335b04a703425d79dbd02b0a0e90de5b331c3c29f6562969e04cdf7095b2a7646b3d006b0b83cb68580b5ccb71de1b4d9f131bac133d6088e10613a00599d81d4818403a4bea83905304cc45ca645a9b2c6484cf9490f1755c744d9988ed60475e6ae44355ed15c7b549366f29581ec2721fd6704e0ca3f878812805675141c0a15a7b7ac35a9e3f8b2a010bc184981c57852895b2695d56131e32326717f6b101df1bc82b3ba0222d52656d118538c4ca3416be1c76ba37a9901a36e4883be6c541f2bbb561818cd2f136b98f658250545c1fa5bcfdc04374016db1c5132447fd6d568866451c25412f72967de868eaeb9c546fb40ea88cd84a1a586ca51c74bc9c3e56e104323afb658d1ac003151bdc35879a4b6762648bff0caa682f1b3319805d2326d5a46af832aacefbaa1ea820568ea3925870e9b6577eb93898e1b0cfbd1c995cb4cd6cabb979813819749b40a9952f50e97c4365e777dcfe9084219294c205acb350e07db9c98f53444546460962e2bf5aa1cc12273d882fcc215a7397b3f9b307c56b9a0429b30f88453a2376669b28b4bc4b84b51714b6652b7a1a0b53e9ec61b55ca51cdb38243239ee5f18243e515f178768a888f475b3d9060136bb22ee355b3da02c16ad83bdbb4aaa13809cb4bcd5bb53710737d3883632f9254e3336af61621a376720572450e3937c0d930e349adbfa7642ff822b9135e18f943e0178617604d10e0c09ffb3e09783c09d12cbe93311757af9857b77d1488ed39321ca97c3745c5bc176ca81274c8321bcb2029938b32bbd01aec137032f9760849701649120050b50d8353c36b8bb7724a67e7660fc93324065d63912c35a86d8fe60683067bbd2685c552ad8c65c77c57c937676fd61595c453174bf996e9d3a9ccb837b25464115c1ba3343ac097b80735aed3225091167cd8f841ffe49c5e698ef542124253084623179394433a4b61547b9ee09c98c2736ea086bd69d1bc7ae68a6ae5ce682a215860006b4604dee45a3e212f97643acb77a79a880382e483537c5198d4483a176d25aac9c3670a3f30956f18ad441904776bcd48131c7d6465bce0c133010f3176c92ec962f5c6b84d4c3ae949619cf48172997ca3b1ccf5c8cc7a67923e1295801048a3d40ac4f2c6467c750fc71314a0c1fc22637dd52e7ea50907ea973d765a6a9bb2b11aa405b9187f72026696710e61af3e41c33da1a05eb65e6523704f078e74e32f10e00247967aee3a8c6546889ef67cd613ad7236583f2104122ac6c6a40a84dc96d81c569e76a952c0a25f396e48337a4fe029a4c91cc7406872706a55573b75f160a4facad7c85fab141c63454bf48990729096ce9965604c7cc1e60ae6868dcc41bc3df71c3e5593f0488b0c6a3063e817f9f4bacb17599c8666ff3591126b4891fb7f5d29660bab60cf5007043a4311d41ab3b29787184f3d3c9ab7cc247f635145b67e970505ba44ad0e06b11ec5cda4175295199d19d660204cbdc17947cc66442d3a2cd408a20fe98174f31ee4e5bb3fa8bcd102bedc26527e9bae836442978a6ccbe510f93ab77569ab1f09d0e6312dd0cc0bcaf095fa8a52a7212d14714a7bf852416c9b026301bd965c30a43d24d97298346a46b2c4bc814ba4059653358b03c9456c60bf0193932eaa2f24ea8e4b010a5a4425ce4540fbab90d8e55c97ac2687f15ff5299278824a08d4743e1a62e1c6619cd3278cd75a97a5b4e3a38668b26c99bf8461495793bbb1b12ca369c825cb31d68731326bf4764b416bb3339ae9c9ce46d9da0e714c0bae8712a670d0e5dcfdd1dd0d045932c79c559b2ab3c7300e2d894b0eaa40a6ab254506d8c1176a33c4a1b2879604b1b80df48d31dd");
1✔
2725
         const std::vector<uint8_t> b_pub_bits = Botan::hex_decode(
1✔
2726
            "f9490f1755c744d9988ed60475e6ae44355ed15c7b549366f29581ec2721fd6704e0ca3f878812805675141c0a15a7b7ac35a9e3f8b2a010bc184981c57852895b2695d56131e32326717f6b101df1bc82b3ba0222d52656d118538c4ca3416be1c76ba37a9901a36e4883be6c541f2bbb561818cd2f136b98f658250545c1fa5bcfdc04374016db1c5132447fd6d568866451c25412f72967de868eaeb9c546fb40ea88cd84a1a586ca51c74bc9c3e56e104323afb658d1ac003151bdc35879a4b6762648bff0caa682f1b3319805d2326d5a46af832aacefbaa1ea820568ea3925870e9b6577eb93898e1b0cfbd1c995cb4cd6cabb979813819749b40a9952f50e97c4365e777dcfe9084219294c205acb350e07db9c98f53444546460962e2bf5aa1cc12273d882fcc215a7397b3f9b307c56b9a0429b30f88453a2376669b28b4bc4b84b51714b6652b7a1a0b53e9ec61b55ca51cdb38243239ee5f18243e515f178768a888f475b3d9060136bb22ee355b3da02c16ad83bdbb4aaa13809cb4bcd5bb53710737d3883632f9254e3336af61621a376720572450e3937c0d930e349adbfa7642ff822b9135e18f943e0178617604d10e0c09ffb3e09783c09d12cbe93311757af9857b77d1488ed39321ca97c3745c5bc176ca81274c8321bcb2029938b32bbd01aec137032f9760849701649120050b50d8353c36b8bb7724a67e7660fc93324065d63912c35a86d8fe60683067bbd2685c552ad8c65c77c57c937676fd61595c453174bf996e9d3a9ccb837b25464115c1ba3343ac097b80735aed3225091167cd8f841ffe49c5e698ef542124253084623179394433a4b61547b9ee09c98c2736ea086bd69d1bc7ae68a6ae5ce682a215860006b4604dee45a3e212f97643acb77a79a880382e483537c5198d4483a176d25aac9c3670a3f30956f18ad441904776bcd48131c7d6465bce0c133010f3176c92ec962f5c6b84d4c3ae949619cf48172997ca3b1ccf5c8cc7a67923e1295801048a3d40ac4f2c6467c750fc71314a0c1fc22637dd52e7ea50907ea973d765a6a9bb2b11aa405b9187f72026696710e61af3e41c33da1a05eb65e6523704f078e74e32f10e00247967aee3a8c6546889ef67cd613ad7236583f2104122ac6c6a40a84dc96d81c569e76a952c0a25f396e48337a4fe029a4c91cc7406872706a55573b75f160a4facad7c85fab141c63454bf48990729096ce9965604c7cc1e60ae6868dcc41bc3df71c3e5593f0488b0c6a3063e817f9f4bacb17599c8666ff3591126b4891fb7f5d29660bab60cf5007043a4311d41ab3b29787184f3d3c9ab7cc247f635145b67e970505ba44ad0e06b11ec5cda4175295199d19d660204cbdc17947cc66442d3a2cd408a20fe98174f31ee4e5bb3fa8bcd102bedc26527e9bae836442978a6ccbe510f93ab77569ab1f09d0e6312dd0cc0bcaf095fa8a52a7212d14714a7bf852416c9b026301bd965c30a43d24d97298346a46b2c4bc814ba4059653358b03c9456c60bf0193932eaa2f24ea8e4b010a5a4425ce4540fbab90d8e55c97ac2687f15ff5299278824a08d4743e1a62e1c6619cd3278cd75a97a5b4e3a38668b26c99bf8461495793bbb1b12ca369c825cb31d68731326bf4764b416bb333");
1✔
2727

2728
         botan_privkey_t b_priv;
1✔
2729
         if(!TEST_FFI_INIT(botan_privkey_load_kyber, (&b_priv, b_priv_bits.data(), 2400))) {
2✔
2730
            return;
×
2731
         }
2732

2733
         std::vector<uint8_t> privkey_read(2400);
1✔
2734
         TEST_FFI_OK(botan_privkey_view_kyber_raw_key, (b_priv, privkey_read.data(), botan_ffi_view_u8_fn));
1✔
2735
         result.test_eq("kyber768 private key", privkey_read, b_priv_bits);
1✔
2736

2737
         std::vector<uint8_t> pubkey_read(1184);
1✔
2738

2739
         botan_pubkey_t b_pub;
1✔
2740
         TEST_FFI_OK(botan_privkey_export_pubkey, (&b_pub, b_priv));
1✔
2741
         TEST_FFI_OK(botan_pubkey_view_kyber_raw_key, (b_pub, pubkey_read.data(), botan_ffi_view_u8_fn));
1✔
2742
         result.test_eq("kyber768 public key b", pubkey_read, b_pub_bits);
1✔
2743

2744
         botan_pubkey_t a_pub;
1✔
2745
         TEST_FFI_OK(botan_pubkey_load_kyber, (&a_pub, a_pub_bits.data(), 1184));
1✔
2746
         TEST_FFI_OK(botan_pubkey_view_kyber_raw_key, (a_pub, pubkey_read.data(), botan_ffi_view_u8_fn));
1✔
2747
         result.test_eq("kyber768 public key a", pubkey_read, a_pub_bits);
1✔
2748

2749
         TEST_FFI_OK(botan_pubkey_destroy, (a_pub));
1✔
2750
         TEST_FFI_OK(botan_pubkey_destroy, (b_pub));
1✔
2751
         TEST_FFI_OK(botan_privkey_destroy, (b_priv));
2✔
2752
      }
5✔
2753
};
2754

2755
class FFI_Kyber1024_Test final : public FFI_Test {
×
2756
   public:
2757
      std::string name() const override { return "FFI Kyber1024"; }
1✔
2758

2759
      void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override {
1✔
2760
         const std::vector<uint8_t> a_pub_bits = Botan::hex_decode(
1✔
2761
            "9779a4d1fc45ec261f048b9c9daa38c9ec228b6505e8905226b38486802059c2c5c89601560634cb1337b1315365144842bc405a292e683cafa4514526945c4dfb68ee2acdb8b79532836696d53125a045bdbb8a3bcc8123083d1e682c5bd7820c76c448351151474f69d601d7708dbb2c979d77527494b68520a8ff66c34162ca2aec8072a2a51ff259389648e75b95c16abe14604edbfabaf400b76a7a0f07db61dce19102f43b2d1060747b02c4425485341fd5d9bffaa7016061374963b985209c6b9a7db3f94958311d027900a3d8c44f8435b093a236a0509f1928df7719ce8c4e90228f4db87cb9e882f2712180238845d31eb906c60eb63e0ff55e84b867a91b79ae74a03ac00473c8c1b3e6aedcc37f1e69b8e136019bdb01c374a122e164c32584b2fbcf5e013a45127c893326b6860378cb5525a48b522b30132b7688214b69808dd19aa4ff033e16252016fc9479222424393e51db7115e38114e6893cdcc8ae1117a4316548010ab4629fb672148d031a6c601a6a4a661d872d8ef693750a115958716ab9263eb0516357102358cde5256464805ca8f59661751ad6a475a7ec78cb7319c3bbc544e1bb1185aaaeb751ba0b3923246e33f40a4ff4780b745362a218d169474d7208a9f7577228308af20f8d2403a27477cf53cff133a247d5c2b298bf21bac6dc44649e63afcef54ad3a07a74e447b36bacca295e053368ef7c146e1c28edb31b3777c941a7c27dc559437b0ff83c2910f827ef244d7726af2b9708654bcfb139a26844c6f4b79cd9e4747065a77596b927f96cbdbc7267ac9e32ac396f6c4ce739aa0aa60fccac178edab1e04688fe71a74201a99bc64b55f8cb89e11545e5275af48626ec667520ba8a7c88c2307e793455ef8780fae16412ea59e92406f595902dc21c612b142801cf31abc0475c7bde772d51c55a2dfc651bc5ab4143022813cc4c8cc6f52c8d27e3cd7851849a8c4343f0c7ed6c6cb9f765c5047e55bc48aad5b932128287f70939db753a61c0d7db1830c256288c1c85cc9bbce58366dac528c893d61b69850bcb82758e836936e1f8163861586482cad35b4db1437fad6980b66280b1652d72f52407a8015f85c29e75b2158933a4f5887db320b583cdcbca274eac21f8702879b8bc4afb62ba056d146512921554c765464d4c96bd3c9a9720187c3339d0593bc4bba59155469ff6b8688a5fc5fa6b46d4070668bd168c5f796492760940999927628236b2412968438d2cbc2a978abc097320291b0ed7e4631ec9bbe28ac63ab6860e976ac1552afc43897d6937a092432dc481a914c3a1273c43009e8ec523cb93ced9898f90905340ba6e01bc572d03a893fa21c4342d88dc3e77b33b1fc063dcdb689d8c4ffc840ce879cfb3471385512cc7c7591383b1fac89832bb1cb3324e6d2868918844cb20ca4df812b42824192a43380430a37a7f3ac41ed064cfe055157b91b5c0108fb7a613a0112af4d64e48f8a345328a99b7bf0c91cb037215b0177ad4c263e6d78f5958c848158e4fd2117c248e0cab3cf98c1e27868838f8428ba0562df6b61e8736e2b8b266607918e0ce2ce3af67c81fa5c2a4d2bc8e871825b702b3beca397b33a518dac8b1393d494a90900c01b55925857cbf8027051d36a4f141a4d2dc440341305e033cb50a074be459c76a339a9a52c447360dea2a5699ccea683a42430aa6fc9545c75c0492641af7a4e9267bcc384e55714cf49741eba3b69d6417a555475d3c021112b8b3588c63747b5ce2ccfee91297fa419f9c4298978fff0870d8a855b48899ca9bb47d836d62d2038cc3816f3a698bb3bbff78c7a015b0ea1960634292e1d50b03e1043a98ca9b27063e668b05e2c17d692d382b181365a818518ec747720337ca1868596af42a90fab1870373d74b8f6d42ac86b18bca3ab04764680cf2060c529abe5b8ef4474dc8cc47a8033ebd884d3e0a0f1a94420d8a3c9162b7af87a2c8a394647434f4a3bc2b477813ac82cf387185b587f7f68938eccddd6934d143ba17bb4a712566d2a55aaddb3323713667401b4a20b86c23bf1076439cb6b8c115389dba4e6f0c915be7602b9703b535070e4a5c5649a5d7080515026706b2604575cbd0687f2729a92a997d21ea7200c41ed8315275f4c7b72f9bc85c0a13b9d041586fd583feb12afd5a402dd33b43543f5fa4eb436c8d");
1✔
2762
         const std::vector<uint8_t> b_priv_bits = Botan::hex_decode(
1✔
2763
            "9bc4986eec853ac90896c7300f914216773baa687f57f81f94e6b5a26515c0a74c73b19dc6b9888755a1d1db6a1128b02c5144ed9ba75e874a68a14dee3a9bf770b767121fbbdb292e097444757fe2f324a875b0a07a4fbdcc8fd6137fce80c69f412be103b01f8b3bed392600f830d1b20d73ca0b386666d16c5d96db10e309041890bfd4ab7bdec27191979abe7637e76153918cc2af1545724abfd95ca496281a0cc6ca63a87819b75aa86452e5027d429cad64a9c029112a3a7b9fb993c6a6d0671f6c9e24986b83f67cf1236d94c051559616826a947eaa15074025d1ab810c80220e8a8c2c222d4e8594bf35811b444a57e9bf94fb2479d174d6b38c8c3b4730437c244b2513232ec798adec4a8e597bca83bca5948468f93c022ba65311a91e3d95c299c70c3f1a43cd0c83dd500bd2211b9b385b82f2c003b10d295765b3e367563a5f19033fc1231db9620f835c95f5a261190a5da1c24ed528316f0a1520d223e208a8c99b24d28598ade74fc88370e7f45102c5a6411891c661b356b9a32e1cc0fafaa085d7670e8bcb5e768eb255204f2445b5b73b04079881903a553c865744343a925c7899777b1c9dd5579a481512f8157061606a9a67c041d38bc179048be17dd9e19dc0a572bce595afa3b68ff21bf78a63a7560636b6bb01ec3362e2aaabc8965818b7f2417ca8f66a5a2a67f72a3931e125d638a872862a7b680a54aa1f25d90dbd567635ec6664919e29517325a5c5048cc8d1c31af5e4866e85025b9184a7b75ed7f2c9c8d88259fa2ec5b05ed3751584f88308c67ff1a72fa2453305160baf404db7d4be56f1547b20bb7dec23f02b10db584b28ca40d8b39c1c3ab9f3d7bbda0822604ca48f26694d69810aa888ae3c0983c5ba4cb74211f7a5361ccdee694f4202aebe13a75b1b2dda1b3232376be213582afc4fde3474766671fe865e2fd98384eb65b2f349f1e24269b91bd9d08c80849735a9951304afd130b5c2211314630aed4b6ac3b1252a0999ff5a3ec26a283342389d219fd243706128b389eb2334fb2a6184a4eab6735d7428df5633ce030b8f853ee47c4401fc5d06b43c9b66b7aeeb23b5f000a30a6f88f027ee3994fe8b63e51b83bc24bb733a3773a35cbe138f6d9c91a3a3898bca6776030d740ac355176547d624719656a9a44e91c63faf7699dc6c2c45575718d48828828b39043c2fda2af416837efc38d17c56d4b63c63a5ab43434647d029f7b236b288958f06910763610f8b2f027a8dcd780039ab34a6871427476ff6500240e83b87c95dcfa45ac5315ef34b343fb609eb296e915c849bb8c57f57c69b177eaa8456377403fe8c6627a3282d45308f675d67085a15f0b1b55aa2a8f21afd6c05c3c00e9eb8c32418cb41963ce427b43e7545c58325c7b9368db2333de424dbeb3430f007d18a68d73b7dc67960b28206a68a1be400a770b5cd9d45a72824ca00345ac56491c1414fe5287a2eb2ad61f3bdcd0c84c335b04a703425d79dbd02b0a0e90de5b331c3c29f6562969e04cdf7095b2a7646b3d006b0b83cb68580b5ccb71de1b4d9f131bac133d6088e10613a00599d81d4818403a4bea83905304cc45ca645a9b2c6484ce4f7bfbe3597f0c2c50784065abc214b5518ed8c7d427205392987d807cdfa571d09932e0a1217e7c5703dfc9be7c4a0f2f33338f316b8c203c6b84285a0957c363d3722145b592f9d6277b1b7446aa2005663b9898901da3b8978eaa8aee87a209c72bfd6cd10a2bedac527f26c419b4bb9a4ca13dba14cff5671461c4cff238d213988120c3cae3b15b607269420c14a9b23a6bb887ad048e6688528137dd5c071172bcaddd5ba4fb9acfb1712ca04aa267b0686a237414b16c4ac03525a45513a393605a29f3b4c07dc5cd082c67b770e69723c6425a23f573216c4cabd6c9c39533f16643bc6151672c466dea63fb8e2180fbcb453c5670b01c0fc7043d198b6c320bf0dfc5016d00f46dc0ba75c7369fc13b65733301b3a92c0cf8dcc1f01e33291a9974d5b5debfa3be5531c69a066a6f4230ba778502654b7e76191d3ba68b1488c848d8ef11bb9ac5a5374af6ccacd02432b247a963685127728825a162c43c1cc79a7b60f571481a3a635a18f0050cbe6f4af1a5a2224044622bb3893bc837be699d5279dac78c9d49818ebc91d4ff6cb54b294e4c378d8eb584f561d21ca87b7c77b1c551f52112ba72c4b6514bb286856e89b48b0a62bad093894474b246a515f849056c9aeb572060ee11b93e236204a8ff1784ede0c3f4c0cd0cdb2a50bd4bcb1225c0dd2caa8a129fdcb01f0e1a75da465b6b8742e4946dbe3ab21ca6c4e592d398a5700375b7b770c17e117663b51313824854585ece4a1520c59a513555f548afdc6748eb9b770b7af8adc9b3c1861efc00ebde93f91fa1539c3411ec9b154c93d1f508b9714cdd0aaabcb436951aa54978b84faa8bd838c29a12657a6389fa658237326bf80e44cff183d9c9107d30c7b4df83908a8badbc1bb5328ae61e6451291710408196261bb913b285c168fe5c7456cd74970377330139beb4c8b4c00c5954254a748308bc30f3a1ccabed83628422e5515b294e80bfed024902a81518c0e6827caa13230016b72aec10d31aab9f9b072652486c3b779c845804d001b223b4065667a5e318b4e0b27c41a099168ce763ac245c1c26354cfc8214cacf01dc8c99c5fc855639cb7486a7a6b71766d62369ee6349f521591344fb8026099fc055c3a0ca2002271c9361f52acaf4675a97b3593f3447b284ad69a9711501411e14e48f080e2a0bceba07a02f79dc15c3c971c1e671a66bf7144395a94d08c46603c4369b25b38d924693492f6500745cb1d2a037e2cd814fac70d8254aea4526e061648d227350dec1ba6305299a45bde4029a9f63e4f62acb5246ba8b54208a37b98fa77e4b720f02b18969635cc16cb6e236ff78111b621cab0339c60b529a9207c94a74925aa3d177636a6d205d72b429f614d452358b98582e42c2f3a32c94202a8625a760483807bbac74c083a7a786ae7b46aff3810a5318e3f479e67e83b4c94587d345ffda17273a55e0432281c670e36b76539263636445e4d110fa1c92b2e65b1ee993b26c41c8c66b181206ff559728993503e7611fa0ca24156642d29a52cbb6aeff88fa1bb790b4344472503ae77967d11a904550a95cc47c3435f1e44b4b890cf5dc4cbd7486a6cab60d1a6622e40c67e854ed0e6a0c4c2aa92a29731e69bc6b3ca9e83893df4bdb37338055bc16bc7cd875b0691d0212109b77236b10b0c72b7a76e9ce346061028be3271c480435e2482d3d2733ed619c2d3698d29a3225a7731a62db4f214a0b11569e91895fbccb8a92d18f94d307a542ff96d2ce8c2bbaa8fab948c83365162268124cabe934b3a5e6530b7f74397a980c243bdce2989747565dd9ba65a7498aa7c3ee711c3be239e93cb45134c082a900cc951756afa42e74a65001822cab95f41798fdef89ea8a751740842e2f7a271e98dbd5158d7455fe9b9cdcd0a0f68c91e59b00979673a1deabf8d213971f994c0bb08899a91e0b896319b9fc69651e3453b14d1cc94462341548fc81c643ab0b10303c7be2c3458b226d0e45f58b21658a853b84615ac5234da9bc5699646fc53c0df907f9a3c598dab6c409b7884a7a84e1a51c2caa80779cd86b77314dabae85caa28972bb6503273a82eb96ab24af6bb0ad0c9ba07ce24216696e265206abc9e147ceef1ad2e343d17aabbc4803496366c7afb53f604c92323c70be5c1e3f601c215c888f3ab239c72aba0634a2901a71891f5d072d41b524e410c7f276ff1109878d7196b5615f1f50c13976257600a821909cb36cf8d2857a2f801cf258913f56a5153234640b9e61bbd4e7b69f83a1eb8ac6b92cb841e808b700aa784a733451048211797563cccc748c9fbb54b3b65445cba676149c7ae9a9a2ecab6599b8505bc561ad85d8c052ed9669e50e684270c86f1cb4fd6708a6746c643392c8a088477dc8bf58ba4a54a8b79e523fc19a28bd47d7e5a334d8296ec86c7f52b7e73b475a0716422953cdd8a8aed0b3a84dc8425145c240c55870240a23977215b364c5596286bc496728717c329dd4b5d0b310980bc0b3f591a2d5cb2c9eaccfa1c7d3a096fc11091a4007a0f23a59782699c3171da53bc7b914f26c95391d6445073a1bd7a44691bafab9c9aceccc7ec389255c3a0ff24c71b30b6bf80c010803383485a7b295991d759cefbae257bbdee1806818565ebd09bf814c98686bbf44a0b14d28735f79ca2261bf9a31b2ca090c7667168b26c99bf8461495793bbb1b12ca369c825cb31d68731326bf4764b416bb33357e74a31d3cd71513fb880e1e177438f29009bab0a131fec4cc24752015efe71c7300e2d894b0eaa40a6ab254506d8c1176a33c4a1b2879604b1b80df48d31dd");
1✔
2764
         const std::vector<uint8_t> b_pub_bits = Botan::hex_decode(
1✔
2765
            "93bc837be699d5279dac78c9d49818ebc91d4ff6cb54b294e4c378d8eb584f561d21ca87b7c77b1c551f52112ba72c4b6514bb286856e89b48b0a62bad093894474b246a515f849056c9aeb572060ee11b93e236204a8ff1784ede0c3f4c0cd0cdb2a50bd4bcb1225c0dd2caa8a129fdcb01f0e1a75da465b6b8742e4946dbe3ab21ca6c4e592d398a5700375b7b770c17e117663b51313824854585ece4a1520c59a513555f548afdc6748eb9b770b7af8adc9b3c1861efc00ebde93f91fa1539c3411ec9b154c93d1f508b9714cdd0aaabcb436951aa54978b84faa8bd838c29a12657a6389fa658237326bf80e44cff183d9c9107d30c7b4df83908a8badbc1bb5328ae61e6451291710408196261bb913b285c168fe5c7456cd74970377330139beb4c8b4c00c5954254a748308bc30f3a1ccabed83628422e5515b294e80bfed024902a81518c0e6827caa13230016b72aec10d31aab9f9b072652486c3b779c845804d001b223b4065667a5e318b4e0b27c41a099168ce763ac245c1c26354cfc8214cacf01dc8c99c5fc855639cb7486a7a6b71766d62369ee6349f521591344fb8026099fc055c3a0ca2002271c9361f52acaf4675a97b3593f3447b284ad69a9711501411e14e48f080e2a0bceba07a02f79dc15c3c971c1e671a66bf7144395a94d08c46603c4369b25b38d924693492f6500745cb1d2a037e2cd814fac70d8254aea4526e061648d227350dec1ba6305299a45bde4029a9f63e4f62acb5246ba8b54208a37b98fa77e4b720f02b18969635cc16cb6e236ff78111b621cab0339c60b529a9207c94a74925aa3d177636a6d205d72b429f614d452358b98582e42c2f3a32c94202a8625a760483807bbac74c083a7a786ae7b46aff3810a5318e3f479e67e83b4c94587d345ffda17273a55e0432281c670e36b76539263636445e4d110fa1c92b2e65b1ee993b26c41c8c66b181206ff559728993503e7611fa0ca24156642d29a52cbb6aeff88fa1bb790b4344472503ae77967d11a904550a95cc47c3435f1e44b4b890cf5dc4cbd7486a6cab60d1a6622e40c67e854ed0e6a0c4c2aa92a29731e69bc6b3ca9e83893df4bdb37338055bc16bc7cd875b0691d0212109b77236b10b0c72b7a76e9ce346061028be3271c480435e2482d3d2733ed619c2d3698d29a3225a7731a62db4f214a0b11569e91895fbccb8a92d18f94d307a542ff96d2ce8c2bbaa8fab948c83365162268124cabe934b3a5e6530b7f74397a980c243bdce2989747565dd9ba65a7498aa7c3ee711c3be239e93cb45134c082a900cc951756afa42e74a65001822cab95f41798fdef89ea8a751740842e2f7a271e98dbd5158d7455fe9b9cdcd0a0f68c91e59b00979673a1deabf8d213971f994c0bb08899a91e0b896319b9fc69651e3453b14d1cc94462341548fc81c643ab0b10303c7be2c3458b226d0e45f58b21658a853b84615ac5234da9bc5699646fc53c0df907f9a3c598dab6c409b7884a7a84e1a51c2caa80779cd86b77314dabae85caa28972bb6503273a82eb96ab24af6bb0ad0c9ba07ce24216696e265206abc9e147ceef1ad2e343d17aabbc4803496366c7afb53f604c92323c70be5c1e3f601c215c888f3ab239c72aba0634a2901a71891f5d072d41b524e410c7f276ff1109878d7196b5615f1f50c13976257600a821909cb36cf8d2857a2f801cf258913f56a5153234640b9e61bbd4e7b69f83a1eb8ac6b92cb841e808b700aa784a733451048211797563cccc748c9fbb54b3b65445cba676149c7ae9a9a2ecab6599b8505bc561ad85d8c052ed9669e50e684270c86f1cb4fd6708a6746c643392c8a088477dc8bf58ba4a54a8b79e523fc19a28bd47d7e5a334d8296ec86c7f52b7e73b475a0716422953cdd8a8aed0b3a84dc8425145c240c55870240a23977215b364c5596286bc496728717c329dd4b5d0b310980bc0b3f591a2d5cb2c9eaccfa1c7d3a096fc11091a4007a0f23a59782699c3171da53bc7b914f26c95391d6445073a1bd7a44691bafab9c9aceccc7ec389255c3a0ff24c71b30b6bf80c010803383485a7b295991d759cefbae257bbdee1806818565ebd09bf814c98686bbf44a0b14d28735f79ca2261bf9a31b2ca090c7667168b26c99bf8461495793bbb1b12ca369c825cb31d68731326bf4764b416bb333");
1✔
2766

2767
         botan_privkey_t b_priv;
1✔
2768
         if(!TEST_FFI_INIT(botan_privkey_load_kyber, (&b_priv, b_priv_bits.data(), 3168))) {
2✔
2769
            return;
×
2770
         }
2771

2772
         std::vector<uint8_t> privkey_read(3168);
1✔
2773
         TEST_FFI_OK(botan_privkey_view_kyber_raw_key, (b_priv, privkey_read.data(), botan_ffi_view_u8_fn));
1✔
2774
         result.test_eq("kyber1024 private key", privkey_read, b_priv_bits);
1✔
2775

2776
         std::vector<uint8_t> pubkey_read(1568);
1✔
2777

2778
         botan_pubkey_t b_pub;
1✔
2779
         TEST_FFI_OK(botan_privkey_export_pubkey, (&b_pub, b_priv));
1✔
2780
         TEST_FFI_OK(botan_pubkey_view_kyber_raw_key, (b_pub, pubkey_read.data(), botan_ffi_view_u8_fn));
1✔
2781
         result.test_eq("kyber1024 public key b", pubkey_read, b_pub_bits);
1✔
2782

2783
         botan_pubkey_t a_pub;
1✔
2784
         TEST_FFI_OK(botan_pubkey_load_kyber, (&a_pub, a_pub_bits.data(), 1568));
1✔
2785
         TEST_FFI_OK(botan_pubkey_view_kyber_raw_key, (a_pub, pubkey_read.data(), botan_ffi_view_u8_fn));
1✔
2786
         result.test_eq("kyber1024 public key a", pubkey_read, a_pub_bits);
1✔
2787

2788
         TEST_FFI_OK(botan_pubkey_destroy, (a_pub));
1✔
2789
         TEST_FFI_OK(botan_pubkey_destroy, (b_pub));
1✔
2790
         TEST_FFI_OK(botan_privkey_destroy, (b_priv));
2✔
2791
      }
5✔
2792
};
2793

2794
class FFI_ElGamal_Test final : public FFI_Test {
×
2795
   public:
2796
      std::string name() const override { return "FFI ElGamal"; }
1✔
2797

2798
      void ffi_test(Test::Result& result, botan_rng_t rng) override {
1✔
2799
         botan_privkey_t priv;
1✔
2800

2801
         if(TEST_FFI_INIT(botan_privkey_create, (&priv, "ElGamal", "modp/ietf/1024", rng))) {
2✔
2802
            do_elgamal_test(priv, rng, result);
1✔
2803
         }
2804

2805
         if(TEST_FFI_INIT(botan_privkey_create_elgamal, (&priv, rng, 1024, 160))) {
2✔
2806
            do_elgamal_test(priv, rng, result);
1✔
2807
         }
2808
      }
1✔
2809

2810
   private:
2811
      static void do_elgamal_test(botan_privkey_t priv, botan_rng_t rng, Test::Result& result) {
2✔
2812
         TEST_FFI_OK(botan_privkey_check_key, (priv, rng, 0));
2✔
2813

2814
         botan_pubkey_t pub;
2✔
2815
         TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv));
2✔
2816
         TEST_FFI_OK(botan_pubkey_check_key, (pub, rng, 0));
2✔
2817

2818
         ffi_test_pubkey_export(result, pub, priv, rng);
2✔
2819
         botan_mp_t p, g, x, y;
2✔
2820
         botan_mp_init(&p);
2✔
2821
         botan_mp_init(&g);
2✔
2822
         botan_mp_init(&x);
2✔
2823
         botan_mp_init(&y);
2✔
2824

2825
         TEST_FFI_OK(botan_pubkey_get_field, (p, pub, "p"));
2✔
2826
         TEST_FFI_OK(botan_pubkey_get_field, (g, pub, "g"));
2✔
2827
         TEST_FFI_OK(botan_pubkey_get_field, (y, pub, "y"));
2✔
2828
         TEST_FFI_OK(botan_privkey_get_field, (x, priv, "x"));
2✔
2829

2830
         size_t p_len = 0;
2✔
2831
         TEST_FFI_OK(botan_mp_num_bytes, (p, &p_len));
2✔
2832

2833
         botan_privkey_t loaded_privkey;
2✔
2834
         TEST_FFI_OK(botan_privkey_load_elgamal, (&loaded_privkey, p, g, x));
2✔
2835

2836
         botan_pubkey_t loaded_pubkey;
2✔
2837
         TEST_FFI_OK(botan_pubkey_load_elgamal, (&loaded_pubkey, p, g, y));
2✔
2838

2839
         botan_mp_destroy(p);
2✔
2840
         botan_mp_destroy(g);
2✔
2841
         botan_mp_destroy(y);
2✔
2842
         botan_mp_destroy(x);
2✔
2843

2844
         std::vector<uint8_t> plaintext(16, 0xFF);
2✔
2845
         std::vector<uint8_t> ciphertext;
2✔
2846
         std::vector<uint8_t> decryption;
2✔
2847

2848
         // Test encryption
2849
         botan_pk_op_encrypt_t op_enc;
2✔
2850
         if(TEST_FFI_OK(botan_pk_op_encrypt_create, (&op_enc, loaded_pubkey, "Raw", 0))) {
4✔
2851
            size_t ctext_len;
2✔
2852
            TEST_FFI_OK(botan_pk_op_encrypt_output_length, (op_enc, plaintext.size(), &ctext_len));
2✔
2853
            ciphertext.resize(ctext_len);
2✔
2854
            TEST_FFI_OK(botan_pk_op_encrypt,
2✔
2855
                        (op_enc, rng, ciphertext.data(), &ctext_len, plaintext.data(), plaintext.size()));
2856
            ciphertext.resize(ctext_len);
2✔
2857
            TEST_FFI_OK(botan_pk_op_encrypt_destroy, (op_enc));
4✔
2858
         }
2859

2860
         // Test decryption
2861
         botan_pk_op_decrypt_t op_dec;
2✔
2862
         if(TEST_FFI_OK(botan_pk_op_decrypt_create, (&op_dec, loaded_privkey, "Raw", 0))) {
4✔
2863
            size_t ptext_len;
2✔
2864
            TEST_FFI_OK(botan_pk_op_decrypt_output_length, (op_dec, ciphertext.size(), &ptext_len));
2✔
2865
            decryption.resize(ptext_len);
2✔
2866
            TEST_FFI_OK(botan_pk_op_decrypt,
2✔
2867
                        (op_dec, decryption.data(), &ptext_len, ciphertext.data(), ciphertext.size()));
2868
            decryption.resize(ptext_len);
2✔
2869
            TEST_FFI_OK(botan_pk_op_decrypt_destroy, (op_dec));
4✔
2870
         }
2871

2872
         result.test_eq("decryption worked", decryption, plaintext);
2✔
2873

2874
         TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey));
2✔
2875
         TEST_FFI_OK(botan_pubkey_destroy, (pub));
2✔
2876
         TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey));
2✔
2877
         TEST_FFI_OK(botan_privkey_destroy, (priv));
4✔
2878
      }
6✔
2879
};
2880

2881
class FFI_DH_Test final : public FFI_Test {
×
2882
   public:
2883
      std::string name() const override { return "FFI DH"; }
1✔
2884

2885
      void ffi_test(Test::Result& result, botan_rng_t rng) override {
1✔
2886
         botan_privkey_t priv1;
1✔
2887
         if(!TEST_FFI_INIT(botan_privkey_create_dh, (&priv1, rng, "modp/ietf/2048"))) {
2✔
2888
            return;
×
2889
         }
2890

2891
         botan_privkey_t priv2;
1✔
2892
         REQUIRE_FFI_OK(botan_privkey_create_dh, (&priv2, rng, "modp/ietf/2048"));
2✔
2893

2894
         botan_pubkey_t pub1;
1✔
2895
         REQUIRE_FFI_OK(botan_privkey_export_pubkey, (&pub1, priv1));
2✔
2896

2897
         botan_pubkey_t pub2;
1✔
2898
         REQUIRE_FFI_OK(botan_privkey_export_pubkey, (&pub2, priv2));
2✔
2899

2900
         // Reload key-pair1 in order to test functions for key loading
2901
         botan_mp_t private_x, public_g, public_p, public_y;
1✔
2902

2903
         botan_mp_init(&private_x);
1✔
2904
         botan_mp_init(&public_g);
1✔
2905
         botan_mp_init(&public_p);
1✔
2906
         botan_mp_init(&public_y);
1✔
2907

2908
         TEST_FFI_OK(botan_privkey_get_field, (private_x, priv1, "x"));
1✔
2909
         TEST_FFI_OK(botan_pubkey_get_field, (public_g, pub1, "g"));
1✔
2910
         TEST_FFI_OK(botan_pubkey_get_field, (public_p, pub1, "p"));
1✔
2911
         TEST_FFI_OK(botan_pubkey_get_field, (public_y, pub1, "y"));
1✔
2912

2913
         botan_privkey_t loaded_privkey1;
1✔
2914
         botan_pubkey_t loaded_pubkey1;
1✔
2915
         TEST_FFI_OK(botan_privkey_load_dh, (&loaded_privkey1, public_p, public_g, private_x));
1✔
2916
         TEST_FFI_OK(botan_pubkey_load_dh, (&loaded_pubkey1, public_p, public_g, public_y));
1✔
2917

2918
         TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey1, rng, 0));
1✔
2919
         TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey1, rng, 0));
1✔
2920

2921
         botan_mp_t loaded_public_g, loaded_public_p, loaded_public_y;
1✔
2922
         botan_mp_init(&loaded_public_g);
1✔
2923
         botan_mp_init(&loaded_public_p);
1✔
2924
         botan_mp_init(&loaded_public_y);
1✔
2925

2926
         TEST_FFI_OK(botan_pubkey_get_field, (loaded_public_g, loaded_pubkey1, "g"));
1✔
2927
         TEST_FFI_OK(botan_pubkey_get_field, (loaded_public_p, loaded_pubkey1, "p"));
1✔
2928
         TEST_FFI_OK(botan_pubkey_get_field, (loaded_public_y, loaded_pubkey1, "y"));
1✔
2929

2930
         int cmp;
1✔
2931

2932
         TEST_FFI_OK(botan_mp_cmp, (&cmp, loaded_public_g, public_g));
1✔
2933
         result.confirm("bigint_mp_cmp(g, g)", cmp == 0);
2✔
2934

2935
         TEST_FFI_OK(botan_mp_cmp, (&cmp, loaded_public_p, public_p));
1✔
2936
         result.confirm("bigint_mp_cmp(p, p)", cmp == 0);
2✔
2937

2938
         TEST_FFI_OK(botan_mp_cmp, (&cmp, loaded_public_y, public_y));
1✔
2939
         result.confirm("bigint_mp_cmp(y, y)", cmp == 0);
2✔
2940

2941
         botan_pk_op_ka_t ka1;
1✔
2942
         REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka1, loaded_privkey1, "Raw", 0));
2✔
2943
         botan_pk_op_ka_t ka2;
1✔
2944
         REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka2, priv2, "Raw", 0));
2✔
2945

2946
         size_t pubkey1_len = 0;
1✔
2947
         TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
1✔
2948
                     botan_pk_op_key_agreement_export_public,
2949
                     (priv1, nullptr, &pubkey1_len));
2950
         std::vector<uint8_t> pubkey1(pubkey1_len);
1✔
2951
         REQUIRE_FFI_OK(botan_pk_op_key_agreement_export_public, (priv1, pubkey1.data(), &pubkey1_len));
2✔
2952
         size_t pubkey2_len = 0;
1✔
2953
         TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
1✔
2954
                     botan_pk_op_key_agreement_export_public,
2955
                     (priv2, nullptr, &pubkey2_len));
2956
         std::vector<uint8_t> pubkey2(pubkey2_len);
1✔
2957
         REQUIRE_FFI_OK(botan_pk_op_key_agreement_export_public, (priv2, pubkey2.data(), &pubkey2_len));
2✔
2958

2959
         const size_t shared_key_len = 256;
1✔
2960

2961
         std::vector<uint8_t> key1(shared_key_len);
1✔
2962
         size_t key1_len = key1.size();
1✔
2963

2964
         TEST_FFI_OK(botan_pk_op_key_agreement,
1✔
2965
                     (ka1, key1.data(), &key1_len, pubkey2.data(), pubkey2.size(), nullptr, 0));
2966

2967
         std::vector<uint8_t> key2(shared_key_len);
1✔
2968
         size_t key2_len = key2.size();
1✔
2969

2970
         TEST_FFI_OK(botan_pk_op_key_agreement,
1✔
2971
                     (ka2, key2.data(), &key2_len, pubkey1.data(), pubkey1.size(), nullptr, 0));
2972

2973
         result.test_eq("shared DH key", key1, key2);
1✔
2974

2975
         TEST_FFI_OK(botan_mp_destroy, (private_x));
1✔
2976
         TEST_FFI_OK(botan_mp_destroy, (public_p));
1✔
2977
         TEST_FFI_OK(botan_mp_destroy, (public_g));
1✔
2978
         TEST_FFI_OK(botan_mp_destroy, (public_y));
1✔
2979

2980
         TEST_FFI_OK(botan_mp_destroy, (loaded_public_p));
1✔
2981
         TEST_FFI_OK(botan_mp_destroy, (loaded_public_g));
1✔
2982
         TEST_FFI_OK(botan_mp_destroy, (loaded_public_y));
1✔
2983

2984
         TEST_FFI_OK(botan_pk_op_key_agreement_destroy, (ka1));
1✔
2985
         TEST_FFI_OK(botan_pk_op_key_agreement_destroy, (ka2));
1✔
2986
         TEST_FFI_OK(botan_privkey_destroy, (priv1));
1✔
2987
         TEST_FFI_OK(botan_privkey_destroy, (priv2));
1✔
2988
         TEST_FFI_OK(botan_pubkey_destroy, (pub1));
1✔
2989
         TEST_FFI_OK(botan_pubkey_destroy, (pub2));
1✔
2990
         TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey1));
1✔
2991
         TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey1));
2✔
2992
      }
4✔
2993
};
2994

2995
BOTAN_REGISTER_TEST("ffi", "ffi_utils", FFI_Utils_Test);
2996
BOTAN_REGISTER_TEST("ffi", "ffi_rng", FFI_RNG_Test);
2997
BOTAN_REGISTER_TEST("ffi", "ffi_rsa_cert", FFI_RSA_Cert_Test);
2998
BOTAN_REGISTER_TEST("ffi", "ffi_zfec", FFI_ZFEC_Test);
2999
BOTAN_REGISTER_TEST("ffi", "ffi_crl", FFI_CRL_Test);
3000
BOTAN_REGISTER_TEST("ffi", "ffi_cert_validation", FFI_Cert_Validation_Test);
3001
BOTAN_REGISTER_TEST("ffi", "ffi_ecdsa_certificate", FFI_ECDSA_Certificate_Test);
3002
BOTAN_REGISTER_TEST("ffi", "ffi_pkcs_hashid", FFI_PKCS_Hashid_Test);
3003
BOTAN_REGISTER_TEST("ffi", "ffi_cbc_cipher", FFI_CBC_Cipher_Test);
3004
BOTAN_REGISTER_TEST("ffi", "ffi_gcm", FFI_GCM_Test);
3005
BOTAN_REGISTER_TEST("ffi", "ffi_eax", FFI_EAX_Test);
3006
BOTAN_REGISTER_TEST("ffi", "ffi_streamcipher", FFI_StreamCipher_Test);
3007
BOTAN_REGISTER_TEST("ffi", "ffi_hashfunction", FFI_HashFunction_Test);
3008
BOTAN_REGISTER_TEST("ffi", "ffi_mac", FFI_MAC_Test);
3009
BOTAN_REGISTER_TEST("ffi", "ffi_scrypt", FFI_Scrypt_Test);
3010
BOTAN_REGISTER_TEST("ffi", "ffi_kdf", FFI_KDF_Test);
3011
BOTAN_REGISTER_TEST("ffi", "ffi_blockcipher", FFI_Blockcipher_Test);
3012
BOTAN_REGISTER_TEST("ffi", "ffi_errorhandling", FFI_ErrorHandling_Test);
3013
BOTAN_REGISTER_TEST("ffi", "ffi_base64", FFI_Base64_Test);
3014
BOTAN_REGISTER_TEST("ffi", "ffi_hex", FFI_Hex_Test);
3015
BOTAN_REGISTER_TEST("ffi", "ffi_mp", FFI_MP_Test);
3016
BOTAN_REGISTER_TEST("ffi", "ffi_fpe", FFI_FPE_Test);
3017
BOTAN_REGISTER_TEST("ffi", "ffi_totp", FFI_TOTP_Test);
3018
BOTAN_REGISTER_TEST("ffi", "ffi_hotp", FFI_HOTP_Test);
3019
BOTAN_REGISTER_TEST("ffi", "ffi_keywrap", FFI_Keywrap_Test);
3020
BOTAN_REGISTER_TEST("ffi", "ffi_rsa", FFI_RSA_Test);
3021
BOTAN_REGISTER_TEST("ffi", "ffi_dsa", FFI_DSA_Test);
3022
BOTAN_REGISTER_TEST("ffi", "ffi_ecdsa", FFI_ECDSA_Test);
3023
BOTAN_REGISTER_TEST("ffi", "ffi_sm2_sig", FFI_SM2_Sig_Test);
3024
BOTAN_REGISTER_TEST("ffi", "ffi_sm2_enc", FFI_SM2_Enc_Test);
3025
BOTAN_REGISTER_TEST("ffi", "ffi_ecdh", FFI_ECDH_Test);
3026
BOTAN_REGISTER_TEST("ffi", "ffi_mceliece", FFI_McEliece_Test);
3027
BOTAN_REGISTER_TEST("ffi", "ffi_ed25519", FFI_Ed25519_Test);
3028
BOTAN_REGISTER_TEST("ffi", "ffi_x25519", FFI_X25519_Test);
3029
BOTAN_REGISTER_TEST("ffi", "ffi_kyber512", FFI_Kyber512_Test);
3030
BOTAN_REGISTER_TEST("ffi", "ffi_kyber768", FFI_Kyber768_Test);
3031
BOTAN_REGISTER_TEST("ffi", "ffi_kyber1024", FFI_Kyber1024_Test);
3032
BOTAN_REGISTER_TEST("ffi", "ffi_elgamal", FFI_ElGamal_Test);
3033
BOTAN_REGISTER_TEST("ffi", "ffi_dh", FFI_DH_Test);
3034

3035
#endif
3036

3037
}  // namespace
3038

3039
}  // namespace Botan_Tests
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc