35 #if defined(HAVE_XKEY_PROVIDER) && defined (ENABLE_CRYPTOAPI)
38 #include <openssl/bio.h>
39 #include <openssl/pem.h>
40 #include <openssl/core_names.h>
41 #include <openssl/evp.h>
42 #include <openssl/pkcs12.h>
54 const char *algorithm)
67 while ((e = ERR_get_error()))
69 msg(flags,
"OpenSSL error %lu: %s\n", e, ERR_error_string(e, NULL));
77 #define _countof(x) sizeof((x))/sizeof(*(x))
81 static const uint8_t test_hash[] = {
82 0x77, 0x38, 0x65, 0x00, 0x1e, 0x96, 0x48, 0xc6, 0x57, 0x0b, 0xae,
83 0xc0, 0xb7, 0x96, 0xf9, 0x66, 0x4d, 0x5f, 0xd0, 0xb7
87 static const char *valid_str[] = {
88 "773865001e9648c6570baec0b796f9664d5fd0b7",
89 " 77 386500 1e 96 48 c6570b aec0b7 96f9664d5f d0 b7",
90 " 773865001e9648c6570baec0b796f9664d5fd0b7 ",
94 static const char *invalid_str[] = {
95 "773 865001e9648c6570baec0b796f9664d5fd0b7",
96 "77:38:65001e9648c6570baec0b796f9664d5fd0b7",
97 "7738x5001e9648c6570baec0b796f9664d5fd0b7",
105 const char *
const cert;
106 const char *
const key;
107 const char *
const cname;
114 static bool certs_loaded;
115 static HCERTSTORE user_store;
128 assert(
sizeof(certs_local) ==
sizeof(
certs));
129 memcpy(
certs, certs_local,
sizeof(certs_local));
141 return c->
cert ? c : NULL;
146 import_certs(
void **state)
154 user_store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER
155 |CERT_STORE_OPEN_EXISTING_FLAG, L
"MY");
156 assert_non_null(user_store);
160 const char *pass =
"opensesame";
161 const wchar_t *wpass = L
"opensesame";
164 EVP_PKEY *pkey = NULL;
166 BIO *buf = BIO_new_mem_buf(c->
cert, -1);
169 x509 = PEM_read_bio_X509(buf, NULL, NULL, NULL);
173 buf = BIO_new_mem_buf(c->
key, -1);
176 pkey = PEM_read_bio_PrivateKey(buf, NULL, NULL, NULL);
182 fail_msg(
"Failed to parse certificate/key data: <%s>", c->
friendly_name);
186 PKCS12 *p12 = PKCS12_create(pass, c->
friendly_name, pkey, x509, NULL, 0, 0, 0, 0, 0);
191 fail_msg(
"Failed to convert to PKCS12: <%s>", c->
friendly_name);
195 CRYPT_DATA_BLOB blob = {.cbData = 0, .pbData = NULL};
196 int len = i2d_PKCS12(p12, &blob.pbData);
199 fail_msg(
"Failed to DER encode PKCS12: <%s>", c->
friendly_name);
204 DWORD flags = PKCS12_ALLOW_OVERWRITE_KEY|PKCS12_ALWAYS_CNG_KSP;
205 HCERTSTORE tmp_store = PFXImportCertStore(&blob, wpass, flags);
207 OPENSSL_free(blob.pbData);
209 assert_non_null(tmp_store);
217 const CERT_CONTEXT *ctx = CertEnumCertificatesInStore(tmp_store, NULL);
218 assert_non_null(ctx);
219 bool added = CertAddCertificateContextToStore(user_store, ctx,
220 CERT_STORE_ADD_REPLACE_EXISTING, NULL);
223 CertFreeCertificateContext(ctx);
224 CertCloseStore(tmp_store, 0);
236 const CERT_CONTEXT *ctx = NULL;
237 while ((ctx = CertEnumCertificatesInStore(user_store, ctx)))
239 char *friendly_name = get_cert_name(ctx, &gc);
240 if (!lookup_cert(friendly_name))
246 const CERT_CONTEXT *ctx_dup = CertDuplicateCertificateContext(ctx);
249 CertDeleteCertificateFromStore(ctx_dup);
253 CertCloseStore(user_store, 0);
256 certs_loaded =
false;
262 test_find_cert_bythumb(
void **state)
265 char select_string[64];
267 const CERT_CONTEXT *ctx;
270 assert_non_null(user_store);
274 snprintf(select_string,
sizeof(select_string),
"THUMB:%s", c->
hash);
275 ctx = find_certificate_in_store(select_string, user_store);
279 assert_int_equal(c->valid, 1);
280 char *friendly_name = get_cert_name(ctx, &gc);
282 CertFreeCertificateContext(ctx);
287 assert_int_equal(c->valid, 0);
295 test_find_cert_byname(
void **state)
298 char select_string[64];
300 const CERT_CONTEXT *ctx;
303 assert_non_null(user_store);
307 snprintf(select_string,
sizeof(select_string),
"SUBJ:%s", c->
cname);
308 ctx = find_certificate_in_store(select_string, user_store);
314 assert_non_null(ctx);
316 char *friendly_name = get_cert_name(ctx, &gc);
318 assert_non_null(found);
320 assert_int_equal(found->valid, 1);
321 CertFreeCertificateContext(ctx);
328 test_find_cert_byissuer(
void **state)
331 char select_string[64];
333 const CERT_CONTEXT *ctx;
336 assert_non_null(user_store);
340 snprintf(select_string,
sizeof(select_string),
"ISSUER:%s", c->
issuer);
341 ctx = find_certificate_in_store(select_string, user_store);
347 assert_non_null(ctx);
349 char *friendly_name = get_cert_name(ctx, &gc);
351 assert_non_null(found);
353 assert_int_equal(found->valid, 1);
354 CertFreeCertificateContext(ctx);
361 setup_xkey_provider(
void **state)
366 prov[0] = OSSL_PROVIDER_load(
tls_libctx,
"default");
367 OSSL_PROVIDER_add_builtin(
tls_libctx,
"ovpn.xkey", xkey_provider_init);
368 prov[1] = OSSL_PROVIDER_load(
tls_libctx,
"ovpn.xkey");
371 EVP_set_default_properties(
tls_libctx,
"?provider!=ovpn.xkey");
376 teardown_xkey_provider(
void **state)
379 for (
size_t i = 0; i < _countof(prov); i++)
383 OSSL_PROVIDER_unload(prov[i]);
398 test_cryptoapi_sign(
void **state)
401 char select_string[64];
403 EVP_PKEY *privkey = NULL;
406 assert_true(certs_loaded);
414 snprintf(select_string,
sizeof(select_string),
"THUMB:%s", c->
hash);
415 if (Load_CryptoAPI_certificate(select_string, &x509, &privkey) != 1)
417 fail_msg(
"Load_CryptoAPI_certificate failed: <%s>", c->
friendly_name);
420 EVP_PKEY *pubkey = X509_get0_pubkey(x509);
421 assert_non_null(pubkey);
424 EVP_PKEY_free(privkey);
432 test_ssl_ctx_use_cryptoapicert(
void **state)
435 char select_string[64];
438 assert_true(certs_loaded);
447 assert_non_null(ssl_ctx);
449 snprintf(select_string,
sizeof(select_string),
"THUMB:%s", c->
hash);
452 fail_msg(
"SSL_CTX_use_CryptoAPI_certificate failed: <%s>", c->
friendly_name);
456 if (!SSL_CTX_check_private_key(ssl_ctx))
458 fail_msg(
"Certificate and private key in ssl_ctx do not match for <%s>", c->
friendly_name);
462 SSL_CTX_free(ssl_ctx);
467 test_parse_hexstring(
void **state)
469 unsigned char hash[255];
472 for (
int i = 0; i < _countof(valid_str); i++)
474 int len = parse_hexstring(valid_str[i],
hash, _countof(
hash));
475 assert_int_equal(len,
sizeof(test_hash));
476 assert_memory_equal(
hash, test_hash,
sizeof(test_hash));
480 for (
int i = 0; i < _countof(invalid_str); i++)
482 int len = parse_hexstring(invalid_str[i],
hash, _countof(
hash));
483 assert_int_equal(len, 0);
491 const struct CMUnitTest tests[] = {
492 cmocka_unit_test(test_parse_hexstring),
493 cmocka_unit_test(import_certs),
494 cmocka_unit_test(test_find_cert_bythumb),
495 cmocka_unit_test(test_find_cert_byname),
496 cmocka_unit_test(test_find_cert_byissuer),
497 cmocka_unit_test_setup_teardown(test_cryptoapi_sign, setup_xkey_provider,
498 teardown_xkey_provider),
499 cmocka_unit_test_setup_teardown(test_ssl_ctx_use_cryptoapicert, setup_xkey_provider,
500 teardown_xkey_provider),
503 int ret = cmocka_run_group_tests_name(
"cryptoapi tests", tests, NULL,
cleanup);