Skip to content

Commit

Permalink
Support cross-compilation using MingGW-W64.
Browse files Browse the repository at this point in the history
So far PKCS11 modules encountered on Windows use packed structures, thus
PKCS#11 API needs to obey call convention.

Implemented pthread-abstraction layer to allow use of windows native
syncapi primitives, although this implementation uses MingGW-W64
provided pthreads abstraction.

Dynamic module linking using LoadLibrary() and GetProcAddress.

Do not use `interface` as struct member field name, as it is a MSVC
reserved word.

Make outcome depend on libpthread.

To compile: `meson setup --cross-file x86_64-w64-mingw32.txt`.

Signed-off-by: Tero Mononen <[email protected]>
  • Loading branch information
Tero Mononen committed Jan 17, 2025
1 parent 5dec656 commit f61f976
Show file tree
Hide file tree
Showing 15 changed files with 387 additions and 143 deletions.
9 changes: 9 additions & 0 deletions BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ Otherwise, you can set `CFLAGS`/`LDFLAGS`:

- `CFLAGS="-I$OPENSSL_DIR/include" LDFLAGS="-L$OPENSSL_DIR/lib64" meson setup builddir`

### Cross compiling for Windows x86_64 platform

Install MinGW-W64 toolchain from https://www.mingw-w64.org/, then

- `meson setup --cross-file x86_64-w64-mingw32.txt builddir`
- `meson compile -C builddir`

This module depends on MinGW `libwinpthread-1.dll`. Make that DLL available for the applications.

### Installation

The usual command to install is:
Expand Down
6 changes: 3 additions & 3 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ extra_c_args = [
'-fdiagnostics-show-option',
]

add_project_arguments(cc.get_supported_arguments(warning_c_args + extra_c_args),
add_project_arguments(cc.get_supported_arguments(warning_c_args + extra_c_args + meson.get_external_property('cross_c_args', [])),
language: 'c')

configinc = include_directories('.')
Expand All @@ -46,7 +46,8 @@ conf.set('PACKAGE_MAJOR', major_version)
conf.set('PACKAGE_MINOR', minor_version)

libcrypto = dependency('libcrypto', version: '>= 3.0.7')
provider_path = libcrypto.get_variable(pkgconfig: 'modulesdir')
provider_path = libcrypto.get_variable(pkgconfig: 'modulesdir', default_value: 'ossl_modules')

libssl = dependency('libssl', version: '>= 3.0.7')

host_system = host_machine.system()
Expand Down Expand Up @@ -89,4 +90,3 @@ meson.add_dist_script('scripts/clean-dist.sh')
subdir('src')
subdir('docs')
subdir('tests')

24 changes: 18 additions & 6 deletions src/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,19 @@
SPDX-License-Identifier: Apache-2.0 */

#include "provider.h"

#if defined(WIN32)
#include <windows.h>
#define dlopen(path, flags) LoadLibrary((path))
#define dlerror() strdup("Error while loading DLL")
#define dlsym(module, name) (void *)GetProcAddress((module), (name))
#define dlclose(module) do {} while(0)
typedef HINSTANCE P11PROV_DLHANDLE;
#else
#include <dlfcn.h>
typedef void * P11PROV_DLHANDLE;
#endif

#include <string.h>

/* Wrapper Interface on top of PKCS#11 interfaces.
Expand All @@ -16,12 +28,12 @@ struct p11prov_module_ctx {
char *path;
char *init_args;

void *dlhandle;
P11PROV_INTERFACE *interface;
P11PROV_DLHANDLE dlhandle;
P11PROV_INTERFACE *iface;

CK_INFO ck_info;

pthread_mutex_t lock;
P11PROV_MUTEX lock;
bool initialized;
bool reinit;
};
Expand Down Expand Up @@ -202,7 +214,7 @@ static CK_RV p11prov_interface_init(P11PROV_MODULE *mctx)
}
if (ret == CKR_OK) {
populate_interface(intf, ck_interface);
mctx->interface = intf;
mctx->iface = intf;
} else {
OPENSSL_free(intf);
}
Expand Down Expand Up @@ -345,7 +357,7 @@ P11PROV_INTERFACE *p11prov_module_get_interface(P11PROV_MODULE *mctx)
if (!mctx) {
return NULL;
}
return mctx->interface;
return mctx->iface;
}

void p11prov_module_free(P11PROV_MODULE *mctx)
Expand All @@ -358,7 +370,7 @@ void p11prov_module_free(P11PROV_MODULE *mctx)
p11prov_Finalize(mctx->provctx, NULL);
dlclose(mctx->dlhandle);
}
OPENSSL_free(mctx->interface);
OPENSSL_free(mctx->iface);
OPENSSL_free(mctx->path);
OPENSSL_free(mctx->init_args);
OPENSSL_free(mctx);
Expand Down
5 changes: 4 additions & 1 deletion src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,21 @@ pkcs11_provider_sources = [
'store.c',
'tls.c',
'util.c',
'mutex.c',
]

pkcs11_provider_map = meson.current_source_dir() / 'provider.map'
pkcs11_provider_ldflags = cc.get_supported_link_arguments([
'-Wl,--version-script,' + pkcs11_provider_map
])

threads = dependency('threads')

pkcs11_provider = shared_module(
'pkcs11',
pkcs11_provider_sources,
name_prefix: '',
dependencies: [libcrypto],
dependencies: [libcrypto, threads],
include_directories: [configinc],
link_depends: [pkcs11_provider_map],
link_args: pkcs11_provider_ldflags,
Expand Down
236 changes: 236 additions & 0 deletions src/mutex.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
/* Copyright (C) 2022 Simo Sorce <[email protected]>
SPDX-License-Identifier: Apache-2.0 */

#include "provider.h"
#include "platform/endian.h"

#if 1

#define MUTEX_RAISE_ERROR(_errstr) \
P11PROV_raise(provctx, ret, "%s %s mutex (errno=%d)", _errstr, obj, err); \
P11PROV_debug("Called from [%s:%d]%s()", file, line, func)


CK_RV p11prov_mutex_init(P11PROV_CTX *provctx, P11PROV_MUTEX *lock,
const char *obj, const char *file, int line,
const char *func)
{
CK_RV ret = CKR_OK;
int err;

err = pthread_mutex_init(lock, NULL);
if (err != 0) {
err = errno;
ret = CKR_CANT_LOCK;
MUTEX_RAISE_ERROR("Failed to init");
}
return ret;
}

CK_RV p11prov_mutex_lock(P11PROV_CTX *provctx, P11PROV_MUTEX *lock,
const char *obj, const char *file, int line,
const char *func)
{
CK_RV ret = CKR_OK;
int err;

err = pthread_mutex_lock(lock);
if (err != 0) {
err = errno;
ret = CKR_CANT_LOCK;
MUTEX_RAISE_ERROR("Failed to lock");
}
return ret;
}

CK_RV p11prov_mutex_unlock(P11PROV_CTX *provctx, P11PROV_MUTEX *lock,
const char *obj, const char *file, int line,
const char *func)
{
CK_RV ret = CKR_OK;
int err;

err = pthread_mutex_unlock(lock);
if (err != 0) {
err = errno;
ret = CKR_CANT_LOCK;
MUTEX_RAISE_ERROR("Failed to unlock");
}
return ret;
}

CK_RV p11prov_mutex_destroy(P11PROV_CTX *provctx, P11PROV_MUTEX *lock,
const char *obj, const char *file, int line,
const char *func)
{
CK_RV ret = CKR_OK;
int err;

err = pthread_mutex_destroy(lock);
if (err != 0) {
err = errno;
ret = CKR_CANT_LOCK;
MUTEX_RAISE_ERROR("Failed to destroy");
}
return ret;
}

void p11prov_force_rwlock_reinit(P11PROV_RWLOCK *lock)
{
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
memcpy(lock, &rwlock, sizeof(rwlock));
}

CK_RV p11prov_rwlock_init(P11PROV_RWLOCK *lock)
{
CK_RV ret = CKR_OK;
if (pthread_rwlock_init(lock, NULL) != 0) {
ret = CKR_CANT_LOCK;
}
return ret;
}

CK_RV p11prov_rwlock_trywrlock(P11PROV_RWLOCK *lock)
{
CK_RV ret = CKR_OK;
if (pthread_rwlock_trywrlock(lock) != 0) {
ret = CKR_CANT_LOCK;
}
return ret;
}

CK_RV p11prov_rwlock_rdlock(P11PROV_RWLOCK *lock)
{
CK_RV ret = CKR_OK;
if (pthread_rwlock_rdlock(lock) != 0) {
ret = CKR_CANT_LOCK;
}
return ret;
}

CK_RV p11prov_rwlock_wrlock(P11PROV_RWLOCK *lock)
{
CK_RV ret = CKR_OK;
if (pthread_rwlock_wrlock(lock) != 0) {
ret = CKR_CANT_LOCK;
}
return ret;
}

CK_RV p11prov_rwlock_unlock(P11PROV_RWLOCK *lock)
{
CK_RV ret = CKR_OK;
if (pthread_rwlock_unlock(lock) != 0) {
ret = CKR_CANT_LOCK;
}
return ret;
}

CK_RV p11prov_rwlock_destroy(P11PROV_RWLOCK *lock)
{
CK_RV ret = CKR_OK;
if (pthread_rwlock_destroy(lock) != 0) {
ret = CKR_CANT_LOCK;
}
return ret;
}

#else

CK_RV p11prov_mutex_init(P11PROV_CTX *provctx, P11PROV_MUTEX *lock,
const char *obj, const char *file, int line,
const char *func)
{
CK_RV ret = CKR_OK;
InitializeCriticalSection(lock);
return ret;
}

CK_RV p11prov_mutex_lock(P11PROV_CTX *provctx, P11PROV_MUTEX *lock,
const char *obj, const char *file, int line,
const char *func)
{
CK_RV ret = CKR_OK;
EnterCriticalSection(lock);
return ret;
}

CK_RV p11prov_mutex_unlock(P11PROV_CTX *provctx, P11PROV_MUTEX *lock,
const char *obj, const char *file, int line,
const char *func)
{
CK_RV ret = CKR_OK;
LeaveCriticalSection(lock);
return ret;
}

CK_RV p11prov_mutex_destroy(P11PROV_CTX *provctx, P11PROV_MUTEX *lock,
const char *obj, const char *file, int line,
const char *func)
{
CK_RV ret = CKR_OK;
DeleteCriticalSection(lock);
return ret;
}

void p11prov_force_rwlock_reinit(P11PROV_RWLOCK *lock)
{
P11PROV_RWLOCK rwlock;
p11prov_rwlock_init(&rwlock);
memcpy(lock, &rwlock, sizeof(rwlock));
}

CK_RV p11prov_rwlock_init(P11PROV_RWLOCK *lock)
{
CK_RV ret = CKR_OK;
InitializeSRWLock(&lock->srwlock);
lock->exclusive = 0;
return ret;
}

CK_RV p11prov_rwlock_rdlock(P11PROV_RWLOCK *lock)
{
CK_RV ret = CKR_OK;
AcquireSRWLockShared(&lock->srwlock);
lock->exclusive = 0;
return ret;
}

CK_RV p11prov_rwlock_trywrlock(P11PROV_RWLOCK *lock)
{
CK_RV ret = CKR_OK;
if (!TryAcquireSRWLockExclusive(&lock->srwlock)) {
ret = CKR_CANT_LOCK;
} else {
lock->exclusive = 1;
}
return ret;
}

CK_RV p11prov_rwlock_wrlock(P11PROV_RWLOCK *lock)
{
CK_RV ret = CKR_OK;
AcquireSRWLockExclusive(&lock->srwlock);
lock->exclusive = 1;
return ret;
}

CK_RV p11prov_rwlock_unlock(P11PROV_RWLOCK *lock)
{
CK_RV ret = CKR_OK;
if (lock->exclusive) {
ReleaseSRWLockExclusive(&lock->srwlock);
} else {
ReleaseSRWLockShared(&lock->srwlock);
}
lock->exclusive = 0;
return ret;
}

CK_RV p11prov_rwlock_destroy(P11PROV_RWLOCK *lock)
{
CK_RV ret = CKR_OK;
return ret;
}

#endif
2 changes: 1 addition & 1 deletion src/objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ struct p11prov_obj_pool {
int num;
int first_free;

pthread_mutex_t lock;
P11PROV_MUTEX lock;
};

CK_RV p11prov_obj_pool_init(P11PROV_CTX *ctx, CK_SLOT_ID id,
Expand Down
8 changes: 8 additions & 0 deletions src/pkcs11.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
#ifndef _PD_PKCS11_
#define _PD_PKCS11_

#ifdef WIN32
# pragma pack(push, 1)
#endif

#define CRYPTOKI_VERSION_MAJOR 3
#define CRYPTOKI_VERSION_MINOR 1
#define CRYPTOKI_VERSION_AMENDMENT 0
Expand Down Expand Up @@ -2407,5 +2411,9 @@ struct CK_FUNCTION_LIST {
CK_C_WaitForSlotEvent C_WaitForSlotEvent;
};

#ifdef WIN32
# pragma pack(pop)
#endif


#endif
Loading

0 comments on commit f61f976

Please sign in to comment.