Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 38 additions & 23 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
name: Tests
on:
push:
push: {}
workflow_dispatch: {}
env:
UV_PYTHON_PREFERENCE: only-system
PKCS11_TOKEN_LABEL: TEST
PKCS11_TOKEN_PIN: 1234
PKCS11_TOKEN_SO_PIN: 5678
jobs:
run:
# Run in Ubuntu 22.04 right now, as oscrypto fails on OpenSSL versions with a
# double-digit patch number (such as provided by Ubuntu 24.04):
# https://community.snowflake.com/s/article/Python-Connector-fails-to-connect-with-LibraryNotFoundError-Error-detecting-the-version-of-libcrypto
# https://github.com/wbond/oscrypto/issues/78
runs-on: ubuntu-22.04
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-latest
- windows-latest
- macos-latest
python-version:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
# 3.13.4 has a regression in C extension builds,
# need to stick to 3.13.3 until 3.13.5 is available on runners
- "3.13.3"

steps:
- name: Acquire sources
Expand All @@ -30,28 +33,40 @@ jobs:
uses: actions/[email protected]
with:
python-version: ${{ matrix.python-version }}
architecture: x64

- name: Install Softhsm
shell: bash
run: |
if [[ $OS_NAME == 'ubuntu-latest' ]]; then
sudo apt-get install softhsm2
mkdir softhsm_tokens
echo "directories.tokendir = $(pwd)/softhsm_tokens" > /tmp/softhsm2.conf
echo "SOFTHSM2_CONF=/tmp/softhsm2.conf" >> "$GITHUB_ENV"
echo "PKCS11_MODULE=/usr/lib/softhsm/libsofthsm2.so" >> "$GITHUB_ENV"
elif [[ $OS_NAME == 'macos-latest' ]]; then
brew install softhsm
echo "PKCS11_MODULE=/opt/homebrew/lib/softhsm/libsofthsm2.so" >> "$GITHUB_ENV"
elif [[ $OS_NAME == 'windows-latest' ]]; then
choco install softhsm.install
echo "SOFTHSM2_CONF=D:/SoftHSM2/etc/softhsm2.conf" >> "$GITHUB_ENV"
echo "PKCS11_MODULE=D:/SoftHSM2/lib/softhsm2-x64.dll" >> "$GITHUB_ENV"
echo "D:/SoftHSM2/bin" >> "$GITHUB_PATH"
echo "D:/SoftHSM2/lib" >> "$GITHUB_PATH"
else
echo "$OS_NAME is not a supported target system"
exit 1
fi
env:
OS_NAME: ${{ matrix.os }}
- name: Initialize SoftHSM token
shell: bash
run: |
softhsm2-util --init-token --free --label $PKCS11_TOKEN_LABEL --pin $PKCS11_TOKEN_PIN --so-pin $PKCS11_TOKEN_SO_PIN
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
python-version: ${{ matrix.python-version }}

- name: Install dev dependencies
run: uv sync --all-extras

# Locally compile softhsmv2. For unknown reasons, the version installed by Ubuntu fails on
# Github Actions (while working e.g. in Docker).
- name: Install Softhsm
run: |
curl https://dist.opendnssec.org/source/softhsm-2.6.1.tar.gz | tar -zxv
(cd softhsm-2.6.1 && ./configure --prefix=$HOME --disable-p11-kit --disable-gost && make all install CC="gcc" CXX="g++")
echo "$HOME/bin" >> "$GITHUB_PATH"
echo "PKCS11_MODULE=$HOME/lib/softhsm/libsofthsm2.so" >> "$GITHUB_ENV"

- name: Initialize token
run: softhsm2-util --init-token --free --label $PKCS11_TOKEN_LABEL --pin $PKCS11_TOKEN_PIN --so-pin $PKCS11_TOKEN_SO_PIN

- name: Run tests
run: uv run pytest -v
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
graft extern/
include pkcs11/*.pxd
1 change: 1 addition & 0 deletions extern/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!*.c
99 changes: 99 additions & 0 deletions extern/load_module.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#define PY_SSIZE_T_CLEAN
#include "load_module.h"


#ifdef _WIN32
static PyObject* p11_error() {
DWORD dwMessageId = GetLastError();
LPWSTR msgbuffer = NULL;

if (dwMessageId != 0) {
DWORD l = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwMessageId,
MAKELANGID(LANG_USER_DEFAULT, SUBLANG_DEFAULT),
(LPWSTR) &msgbuffer,
0,
NULL);
PyObject* errmsg = PyUnicode_FromWideChar(msgbuffer, l);
LocalFree(msgbuffer);
return errmsg;
} else {
return NULL;
}
}

static P11_HANDLE* p11_open(PyObject *path_str) {
wchar_t *path = PyUnicode_AsWideCharString(path_str, NULL);
LIB_HANDLE handle = LoadLibraryW(path);
PyMem_Free(path);

P11_HANDLE* result = NULL;
if (handle != NULL) {
void * ptr = GetProcAddress(handle, "C_GetFunctionList");
if (ptr != NULL) {
result = (P11_HANDLE*) PyMem_Malloc(sizeof(P11_HANDLE));
result->lib_handle = handle;
result->get_function_list_ptr = ptr;
}
}
return result;
}

static int p11_close(P11_HANDLE* handle) {
if(handle != NULL) {
LIB_HANDLE lib_handle = handle->lib_handle;
PyMem_Free(handle);
if (lib_handle != NULL) {
return FreeLibrary(lib_handle);
}
}
return 0;
}

#else

static PyObject* p11_error() {
char* error = dlerror();

if (error == NULL) {
return NULL;
}
int len = strlen(error);
PyObject* result = PyUnicode_DecodeUTF8(error, len, NULL);
PyMem_Free(error);
return result;
}

static P11_HANDLE* p11_open(PyObject *path_str) {
const char *path = PyUnicode_AsUTF8AndSize(path_str, NULL);
// Note: python manages this buffer, no need to deallocate it here


P11_HANDLE* result = NULL;

LIB_HANDLE handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL);

if (handle != NULL) {
void * ptr = dlsym(handle, "C_GetFunctionList");
if (ptr != NULL) {
result = (P11_HANDLE*) PyMem_Malloc(sizeof(P11_HANDLE));
result->lib_handle = handle;
result->get_function_list_ptr = ptr;
}
}
return result;
}

static int p11_close(P11_HANDLE* handle) {
if(handle != NULL) {
LIB_HANDLE lib_handle = handle->lib_handle;
PyMem_Free(handle);
if (lib_handle != NULL) {
return dlclose(lib_handle);
}
}
return 0;
}

#endif
21 changes: 21 additions & 0 deletions extern/load_module.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#define PY_SSIZE_T_CLEAN
#include <Python.h>

#ifdef _WIN32
#include "Windows.h"
typedef HINSTANCE LIB_HANDLE;
#else
#include <dlfcn.h>
typedef void *LIB_HANDLE;
#endif

#ifndef P11_HANDLE
typedef struct P11_HANDLE {
LIB_HANDLE lib_handle;
void * get_function_list_ptr;
} P11_HANDLE;
#endif

static PyObject* p11_error();
static P11_HANDLE* p11_open(PyObject *path_str);
static int p11_close(P11_HANDLE* handle);
90 changes: 0 additions & 90 deletions pkcs11/_errors.pyx

This file was deleted.

Loading