33#ifdef HAVE_XKEY_PROVIDER
37#include <openssl/bio.h>
38#include <openssl/pem.h>
39#include <openssl/core_names.h>
40#include <openssl/evp.h>
45#ifdef ENABLE_MANAGEMENT
46static int mgmt_callback_called;
50#define _countof(x) sizeof((x)) / sizeof(*(x))
56static const char pubkey1[] =
"-----BEGIN PUBLIC KEY-----\n"
57 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7GWP6RLCGlvmVioIqYI6\n"
58 "LUR4owA7sJ/nJxBAk+/xzD6gqgSigBsTqeb+gdZwkKjY1N4w2DUA0r5i8Eja/BWN\n"
59 "xMZtC5nxK4MACtMqIwvlzfk130NhFXKtlZj2cyFBXqDdRyeg1ZrUQagcHVcgcReP\n"
60 "9yiePgfO7NUOQk8edEeOR53SFCgnLBQQ9dGWtZN0hO/5BN6NSm/fd6vq0VjTRP5a\n"
61 "BAH/BnqX9/3jV0jh8N9AE59mI1rjVVQ9VDnuAPkS8dLfdC661/CNxt0YWByTIgt1\n"
62 "+qjW4LUvLbnU/rlPhuJ1SBZg+z/JtDBCKfs7syu5WYFqRvNFg7/91Rr/NwxvW/1h\n"
64 "-----END PUBLIC KEY-----\n";
66static const char pubkey2[] =
"-----BEGIN PUBLIC KEY-----\n"
67 "MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEO85iXW+HgnUkwlj1DohNVw0GsnGIh1gZ\n"
68 "u95ff1JiUaJIkYNIkZA+hwIPFVH5aJcSCv3SPIeDS2VUAESNKHZJBQ==\n"
69 "-----END PUBLIC KEY-----\n";
71static const char pubkey3[] =
"-----BEGIN PUBLIC KEY-----\n"
72 "MCowBQYDK2VwAyEA+q5xjF5hGyyqYZidJdz/0saEQabL3N4wIZJBxNGbgJE=\n"
73 "-----END PUBLIC KEY-----";
75static const char *pubkeys[] = { pubkey1, pubkey2, pubkey3 };
77static const char *prov_name =
"ovpn.xkey";
79static const char *test_msg =
"Lorem ipsum dolor sit amet, consectetur "
80 "adipisici elit, sed eiusmod tempor incidunt "
81 "ut labore et dolore magna aliqua.";
83static const char *test_msg_b64 =
84 "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2ljaS"
85 "BlbGl0LCBzZWQgZWl1c21vZCB0ZW1wb3IgaW5jaWR1bnQgdXQgbGFib3JlIGV0IGRv"
86 "bG9yZSBtYWduYSBhbGlxdWEu";
89static const uint8_t test_digest[] = { 0x77, 0x38, 0x65, 0x00, 0x1e, 0x96, 0x48, 0xc6,
90 0x57, 0x0b, 0xae, 0xc0, 0xb7, 0x96, 0xf9, 0x66,
91 0x4d, 0x5f, 0xd0, 0xb7, 0xdb, 0xf3, 0x3a, 0xbf,
92 0x02, 0xcc, 0x78, 0x61, 0x83, 0x20, 0x20, 0xee };
94static const char *test_digest_b64 =
"dzhlAB6WSMZXC67At5b5Zk1f0Lfb8zq/Asx4YYMgIO4=";
101static const uint8_t good_sig[] = { 0xd8, 0xa7, 0xd9, 0x81, 0xd8, 0xaa, 0xd8, 0xad,
102 0x20, 0xd9, 0x8a, 0xd8, 0xa7, 0x20, 0xd8, 0xb3,
103 0xd9, 0x85, 0xd8, 0xb3, 0xd9, 0x85, 0x0 };
105static const char *good_sig_b64 =
"2KfZgdiq2K0g2YrYpyDYs9mF2LPZhQA=";
108load_pubkey(
const char *pem)
110 BIO *in = BIO_new_mem_buf(pem, -1);
113 EVP_PKEY *pkey = PEM_read_bio_PUBKEY(in, NULL, NULL, NULL);
114 assert_non_null(pkey);
124 prov[0] = OSSL_PROVIDER_load(NULL,
"default");
125 OSSL_PROVIDER_add_builtin(NULL, prov_name, xkey_provider_init);
126 prov[1] = OSSL_PROVIDER_load(NULL, prov_name);
129 EVP_set_default_properties(NULL,
"?provider!=ovpn.xkey");
131#ifdef ENABLE_MANAGEMENT
139 for (
size_t i = 0; i < _countof(prov); i++)
143 OSSL_PROVIDER_unload(prov[i]);
161#ifdef ENABLE_MANAGEMENT
162 mgmt_callback_called = 1;
164 const char *expected_tbs = test_digest_b64;
165 if (strstr(algorithm,
"data=message"))
167 expected_tbs = test_msg_b64;
170 if (!strstr(algorithm,
"ED25519"))
172 assert_non_null(strstr(algorithm,
"hashalg=SHA256"));
175 assert_string_equal(b64_data, expected_tbs);
178 if (!strstr(algorithm,
"ECDSA") && !strstr(algorithm,
"ED25519"))
180 assert_non_null(strstr(algorithm,
"RSA_PKCS1_PSS_PADDING,hashalg=SHA256,saltlen=digest"));
186 out = strdup(good_sig_b64);
187 assert_non_null(out);
194xkey_provider_test_fetch(
void **state)
196 assert_true(OSSL_PROVIDER_available(NULL, prov_name));
198 const char *algs[] = {
"RSA",
"ECDSA" };
200 for (
size_t i = 0; i < _countof(algs); i++)
202 EVP_SIGNATURE *sig = EVP_SIGNATURE_fetch(NULL, algs[i],
"provider=ovpn.xkey");
203 assert_non_null(sig);
204 assert_string_equal(OSSL_PROVIDER_get0_name(EVP_SIGNATURE_get0_provider(sig)), prov_name);
206 EVP_SIGNATURE_free(sig);
209 const char *names[] = {
"RSA",
"EC" };
211 for (
size_t i = 0; i < _countof(names); i++)
213 EVP_KEYMGMT *km = EVP_KEYMGMT_fetch(NULL, names[i],
"provider=ovpn.xkey");
215 assert_string_equal(OSSL_PROVIDER_get0_name(EVP_KEYMGMT_get0_provider(km)), prov_name);
217 EVP_KEYMGMT_free(km);
223digest_sign(EVP_PKEY *pkey)
228 OSSL_PARAM params[6] = { OSSL_PARAM_END };
230 const char *mdname =
"SHA256";
231 const char *padmode =
"pss";
232 const char *saltlen =
"digest";
234 if (EVP_PKEY_get_id(pkey) == EVP_PKEY_RSA)
237 OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, (
char *)mdname, 0);
239 OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, (
char *)padmode, 0);
241 OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, (
char *)saltlen, 0);
244 OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, (
char *)saltlen, 0);
245 params[4] = OSSL_PARAM_construct_end();
247 else if (EVP_PKEY_get_id(pkey) == EVP_PKEY_ED25519)
250 params[0] = OSSL_PARAM_construct_end();
254 EVP_PKEY_CTX *pctx = NULL;
255 EVP_MD_CTX *mctx = EVP_MD_CTX_new();
257 if (!mctx || EVP_DigestSignInit_ex(mctx, &pctx, mdname, NULL, NULL, pkey, params) <= 0)
259 fail_msg(
"Failed to initialize EVP_DigestSignInit_ex()");
264 assert_int_equal(EVP_DigestSign(mctx, sig, &siglen, (uint8_t *)test_msg, strlen(test_msg)), 1);
265 assert_true(siglen > 0);
267 if ((sig = test_calloc(1, siglen)) == NULL)
269 fail_msg(
"Out of memory");
271 assert_int_equal(EVP_DigestSign(mctx, sig, &siglen, (uint8_t *)test_msg, strlen(test_msg)), 1);
276 EVP_MD_CTX_free(mctx);
281#ifdef ENABLE_MANAGEMENT
287xkey_provider_test_mgmt_sign_cb(
void **state)
290 for (
size_t i = 0; i < _countof(pubkeys); i++)
292 pubkey = load_pubkey(pubkeys[i]);
293 assert_non_null(pubkey);
294 EVP_PKEY *privkey = xkey_load_management_key(NULL, pubkey);
295 assert_non_null(privkey);
301 mgmt_callback_called = 0;
302 uint8_t *sig = digest_sign(privkey);
303 assert_non_null(sig);
306 assert_int_equal(mgmt_callback_called, 1);
307 assert_memory_equal(sig, good_sig,
sizeof(good_sig));
316 EVP_PKEY_free(pubkey);
317 EVP_PKEY_free(privkey);
323static int xkey_free_called;
324static int xkey_sign_called;
326xkey_free(
void *handle)
328 xkey_free_called = 1;
330 assert_string_equal(handle,
"xkey_handle");
334xkey_sign(
void *handle,
unsigned char *sig,
size_t *siglen,
const unsigned char *tbs,
size_t tbslen,
343 xkey_sign_called = 1;
345 if (!strcmp(s.op,
"DigestSign"))
347 assert_memory_equal(tbs, test_msg, strlen(test_msg));
351 assert_memory_equal(tbs, test_digest,
sizeof(test_digest));
355 if (!strcmp(s.keytype,
"ED25519"))
357 assert_string_equal(s.mdname,
"none");
361 assert_int_equal(OBJ_sn2nid(s.mdname), NID_sha256);
363 if (!strcmp(s.keytype,
"RSA"))
365 assert_string_equal(s.padmode,
"pss");
367 else if (strcmp(s.keytype,
"EC") && strcmp(s.keytype,
"ED25519"))
369 fail_msg(
"Unknown keytype: %s", s.keytype);
373 memcpy(sig, good_sig,
min_size(
sizeof(good_sig), *siglen));
382xkey_provider_test_generic_sign_cb(
void **state)
384 const char *dummy =
"xkey_handle";
386 for (
size_t i = 0; i < _countof(pubkeys); i++)
388 EVP_PKEY *pubkey = load_pubkey(pubkeys[i]);
389 assert_non_null(pubkey);
392 xkey_load_generic_key(NULL, (
void *)dummy, pubkey, xkey_sign, xkey_free);
393 assert_non_null(privkey);
395 xkey_sign_called = 0;
396 xkey_free_called = 0;
397 uint8_t *sig = digest_sign(privkey);
398 assert_non_null(sig);
401 assert_int_equal(xkey_sign_called, 1);
402 assert_memory_equal(sig, good_sig,
sizeof(good_sig));
405 EVP_PKEY_free(pubkey);
406 EVP_PKEY_free(privkey);
409 assert_int_equal(xkey_free_called, 1);
418 const struct CMUnitTest tests[] = {
419 cmocka_unit_test(xkey_provider_test_fetch),
420#ifdef ENABLE_MANAGEMENT
421 cmocka_unit_test(xkey_provider_test_mgmt_sign_cb),
423 cmocka_unit_test(xkey_provider_test_generic_sign_cb),
426 int ret = cmocka_run_group_tests_name(
"xkey provider tests", tests, NULL, NULL);
static size_t min_size(size_t x, size_t y)
char * management_query_pk_sig(struct management *man, const char *b64_data, const char *algorithm)
#define MF_EXTERNAL_KEY_PSSPAD
#define MF_EXTERNAL_KEY_DIGEST
struct man_settings settings
static void openvpn_unit_test_setup(void)
Sets up the environment for unit tests like making both stderr and stdout non-buffered to avoid messa...