Skip to content

Add Windows/MSVC port - #464

Open
ColtonWilley wants to merge 1 commit into
masterfrom
windows-msvc-port-v2
Open

Add Windows/MSVC port#464
ColtonWilley wants to merge 1 commit into
masterfrom
windows-msvc-port-v2

Conversation

@ColtonWilley

Copy link
Copy Markdown
Contributor

Adds a Visual Studio solution under IDE/WINVS and the source changes needed to build wolfProvider with MSVC, FIPS and non-FIPS. Four configurations, x64.

user_settings.h is hand-written and committed rather than generated. options.h can't be reused here: it's an autotools output that bakes in results that are wrong under MSVC. wolfSSL and wolfProvider have to be built against the same one.

include/wolfprovider/version.h is now tracked. It was gitignored, so a fresh clone couldn't build on Windows at all.

Built and tested FIPS and non-FIPS, in the VS IDE.

Builds libwolfprov.dll on Windows with Visual Studio 2022 (v143, x64) against a
user_settings.h-configured wolfSSL and OpenSSL 3.x, for both non-FIPS and FIPS.

Build files live under IDE/WINVS/, laid out like the rest of the wolfSSL family
(wolfssh/ide/winvs): solution, property sheet and user_settings.h at the top,
projects one directory down. Four configurations:

  DLL Release|x64, DLL Debug|x64        the shipped provider
  Static Release|x64, Static Debug|x64  unit tests only, never distributed

The static configurations exist solely so the unit test can link wolfProvider's
internals. The DLL exports exactly one symbol, OSSL_provider_init, via a .def
rather than adding __declspec to the sources. A static library cannot serve as a
provider at all -- OpenSSL loads one only through LoadLibraryA plus
DSO_bind_func("OSSL_provider_init") -- so this costs nothing and keeps internal
crypto symbols off the shipped ABI.

Naming diverges from wolfSSH deliberately. There, unprefixed means static; here
the unprefixed names would be the test-only ones, and Visual Studio's default
selection sorts to them. "DLL" sorts before "Static" under either ordering, so
the default selection is always a customer artifact.

Three latent defects fixed, none of them Windows-specific:

  - wolfProvider never called wolfCrypt_Init(). wolfSSL's drbgStateMutex is
    declared with a static-initializer clause that expands to nothing off
    pthreads, and a Win32 CRITICAL_SECTION has no static-initializer form, so
    the mutex stayed zeroed and wc_InitRng() faulted inside ntdll. Only
    wolfCrypt_Init() runs wc_DrbgState_MutexInit(). Paired with
    wolfCrypt_Cleanup() in teardown and on the init failure path, since OpenSSL
    does not call teardown when init returns 0.

  - wolfProvider never called wc_curve25519_set_rng(), so blinded curve25519 was
    broken: X25519 derive, pkey -pubout, and the default TLS 1.3 group. Blinding
    is on whenever USE_INTEL_SPEEDUP is off, so this breaks any
    --disable-intelasm build on any platform. wp_ecx_gen was worse than a NULL
    pointer: wc_curve25519_make_key attaches the generation context's RNG, which
    is then freed. Now a per-key WC_RNG, mirroring wp_ecc_kmgmt.c.

  - wp_fips.h gated WP_FIPS_CHECKS_DEFAULT on HAVE_FIPS but included no wolfSSL
    configuration under WOLFSSL_USER_SETTINGS, so HAVE_FIPS was invisible and the
    mask silently evaluated to 0. src/wp_fips.c includes only that header, so
    fipsChecks initialised to zero and every wolfProvider FIPS check was
    disabled -- the provider still claimed P-192, RSA-SHA1 and small RSA keys but
    no longer rejected them. Now includes wolfssl/wolfcrypt/settings.h.

Portability: options.h guarded behind WOLFSSL_USER_SETTINGS (it is an autotools
output that does not exist in such a build); strcasecmp -> XSTRCASECMP;
XSTRLEN("literal") -> sizeof("literal") - 1 in two static tables, which GCC
constant-folds and MSVC does not; the FIPS CAST mutex initialiser moved off
__attribute__((constructor)), which MSVC has no equivalent for, to a
CRYPTO_THREAD_run_once from wolfssl_provider_init(); and a local byte-swap
replacing ByteReverseWord32, which is static in misc.c and never linkable.

include/wolfprovider/version.h is now tracked. It is an AC_CONFIG_FILES output
that was gitignored, so a fresh clone had no way to produce it without running
configure -- which Windows does not have. wolfSSL and wolfSSH both track theirs.

Distribution: IDE is enumerated file by file through nested include.am rather
than named as a directory, because automake's distdir rule is a plain recursive
cp that is not gitignore-aware and the Visual Studio projects write build output
inside the repo. The same reasoning removes EXTRA_DIST+=examples, which shipped
a built binary. Two source-list gates run from make check.

Verified in a Windows Server 2025 guest, MSVC v143 x64:

  non-FIPS   199/199 unit tests; 11/11 shipped-artifact checks
  FIPS       the same, against four bundles --
             5.9.2+v5.2.4, 5.8.4+v5.2.3, 5.9.2+v5.2.1, 5.9.1+FIPS-Ready

wolfSSL is built SHARED in every case, including FIPS, and the in-core integrity
check passes. IDE/WIN10/README.txt says FIPS "must be built as a static library,
for the moment", but specifies the linker settings required for a DLL twenty
lines later; the blocker is that their project never applies them to x64 and
never disables Whole Program Optimization for a DLL configuration. A static
wolfSSL would put the FIPS boundary inside libwolfprov.dll, so every wolfProvider
rebuild would invalidate the module hash.

USE_INTEL_SPEEDUP is deliberately omitted: wolfSSL ships x86-64 assembly for nine
features as GAS .S only, with no MASM equivalent, so enabling it fails to link.
WOLFSSL_AESNI and WOLFSSL_SP_X86_64_ASM are kept.

See IDE/WINVS/README.md for the build procedure, including what a FIPS build
requires beyond wolfSSL's own documented steps and why each of those is not
optional. The Linux autotools build is unaffected and still compiles clean under
-Werror.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant