### Example Callback Implementations Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Provides example implementations for the defined callback types: `on_progress`, `on_complete`, and `on_sign_done`. These functions demonstrate how to handle progress updates and completion notifications. ```c static CK_RV on_progress(int pct, const char* msg) { printf("[%3d%%] %s\n", pct, msg ? msg : ""); return CKR_OK; } static CK_RV on_complete(const char* pan, const char* name, const char* serial) { printf("Enrolled: %s (%s), serial=%s\n", name, pan, serial); return CKR_OK; } static CK_RV on_sign_done(int ret) { printf("Sign result: %s\n", ret == 0 ? "OK" : "FAILED"); return CKR_OK; } ``` -------------------------------- ### Full Card Enrolment Example Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Provides a complete example (`enrol.c`) demonstrating the usage of `cie_enable` to enroll a card. It includes custom `on_progress` and `on_complete` callback functions and handles potential errors, such as incorrect PINs. ```c /* enrol.c — full enrolment example */ #include #include #include "opencie/cie_ext.h" static CK_RV on_progress(int pct, const char* msg) { printf("[%3d%%] %s\n", pct, msg ? msg : ""); return CKR_OK; } static CK_RV on_complete(const char* pan, const char* name, const char* serial) { printf("\nEnrolment complete:\n"); printf(" PAN: %s\n", pan ? pan : "(null)"); printf(" Name: %s\n", name ? name : "(null)"); printf(" Serial: %s\n", serial ? serial : "(null)"); return CKR_OK; } int main(int argc, char* argv[]) { /* argv[1] = 16-digit PAN, argv[2] = 8-digit PIN */ const char* pan = argv[1]; const char* pin = argv[2]; int attempts = -1; CK_RV rv = cie_enable(pan, pin, &attempts, on_progress, on_complete); if (rv != CKR_OK) { fprintf(stderr, "cie_enable failed: rv=0x%08lX", rv); if (attempts >= 0) fprintf(stderr, " (PIN attempts remaining: %d)", attempts); fprintf(stderr, "\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; } /* * Example output (success): * [ 0%] Connecting to card ... * [ 20%] Reading certificate ... * [ 80%] Caching ... * [100%] Done * * Enrolment complete: * PAN: 1234567890123456 * Name: MARIO ROSSI * Serial: 1A2B3C4D5E6F * * Example output (wrong PIN, 2 attempts left): * cie_enable failed: rv=0x000000A0 (PIN attempts remaining: 2) */ ``` -------------------------------- ### Build libopencie-pkcs11 on Linux (Native) Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Installs dependencies, sets up the build directory using Meson, and compiles the library. The output is `libopencie-pkcs11.so`. ```bash sudo apt install -y \ cmake g++ cryptopp-dev curl libfontconfig1-dev libfreetype6-dev libpcsclite-dev \ libpng-dev libssl-dev libxml2-dev pkg-config pip install meson ninja meson setup builddir meson compile -C builddir # Output: builddir/libopencie-pkcs11.so ``` -------------------------------- ### PDF Signing Example Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/examples/README.md Demonstrates PDF signing using the `cie_sign` function. ```c sign_pdf.c ``` -------------------------------- ### Build Basic Examples with gcc Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/examples/README.md Compile standalone C programs using gcc, linking against the opencie-pkcs11 library. ```bash gcc -o enrol enrol.c -lopencie-pkcs11 gcc -o sign_pdf sign_pdf.c -lopencie-pkcs11 gcc -o verify_doc verify_doc.c -lopencie-pkcs11 gcc -o get_cert get_cert.c -lopencie-pkcs11 gcc -o reader_watch reader_watch.c -lopencie-pkcs11 gcc -o timestamp timestamp.c -lopencie-pkcs11 ``` -------------------------------- ### Build Example with Explicit Library Path Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/examples/README.md Compile a C program with explicit include and library paths, and set the runtime library path. ```bash gcc -o enrol enrol.c -I../include -L../builddir -lopencie-pkcs11 -Wl,-rpath,../builddir ``` -------------------------------- ### Document Verification Example Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/examples/README.md Demonstrates document verification using `cie_verify` and `cie_get_verify_info`. ```c verify_doc.c ``` -------------------------------- ### Direct PKCS#11 C_Sign Flow Example Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Illustrates a direct usage of the PKCS#11 v2.40 interface in C, demonstrating the steps for initializing the library, finding a slot, opening a session, logging in, and performing a signature operation. ```c /* Direct PKCS#11 usage — C_Sign flow */ #include /* any standard PKCS#11 header */ CK_FUNCTION_LIST* pFunctionList; C_GetFunctionList(&pFunctionList); pFunctionList->C_Initialize(NULL); CK_ULONG slotCount = 0; pFunctionList->C_GetSlotList(CK_TRUE, NULL, &slotCount); CK_SLOT_ID slots[16]; pFunctionList->C_GetSlotList(CK_TRUE, slots, &slotCount); CK_SESSION_HANDLE hSession; pFunctionList->C_OpenSession(slots[0], CKF_SERIAL_SESSION, NULL, NULL, &hSession); /* PIN = last 4 digits of the 8-digit card PIN */ CK_UTF8CHAR pin[] = "5678"; pFunctionList->C_Login(hSession, CKU_USER, pin, sizeof(pin) - 1); CK_MECHANISM mech = { CKM_RSA_PKCS, NULL, 0 }; CK_OBJECT_HANDLE hKey; /* obtained via C_FindObjects on CKO_PRIVATE_KEY */ pFunctionList->C_SignInit(hSession, &mech, hKey); CK_BYTE data[] = { /* pre-hashed data bytes ... */ }; CK_BYTE sig[256]; CK_ULONG sigLen = sizeof(sig); pFunctionList->C_Sign(hSession, data, sizeof(data), sig, &sigLen); pFunctionList->C_Logout(hSession); pFunctionList->C_CloseSession(hSession); pFunctionList->C_Finalize(NULL); ``` -------------------------------- ### Build OpenCIE PKCS#11 on Linux (Native) Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/README.md Installs dependencies and builds the library using Meson and Ninja. Package names are for Debian/Ubuntu; adapt as needed for other distributions. ```bash sudo apt install -y \ cmake g++ libcrypto++-dev libcurl4-openssl-dev \ libfontconfig1-dev libfreetype6-dev libopenjp2-7-dev libpcsclite-dev \ libpng-dev libssl-dev libxml2-dev pkg-config pip install meson ninja meson setup builddir meson compile -C builddir # Output: builddir/libopencie-pkcs11.so ``` -------------------------------- ### Card Enrolment Example Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/examples/README.md Demonstrates card enrolment using the `cie_enable` function. ```c enrol.c ``` -------------------------------- ### Certificate Retrieval Example Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/examples/README.md Demonstrates certificate retrieval using the `cie_get_certificate` function. ```c get_cert.c ``` -------------------------------- ### PKCS#11 Token Operations Flow Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/ARCHITECTURE.md Illustrates the sequence of PKCS#11 function calls for token operations, starting from getting a slot list to signing data. ```text Browser / TLS stack │ C_GetSlotList → C_OpenSession → C_Login(PIN) → C_Sign(data) ▼ pkcs11/pkcs11/pkcs11_functions.cpp (dispatch table) │ ├─ Slot/session management: pkcs11/pkcs11/slot.cpp, session.cpp ├─ Object management: pkcs11/pkcs11/p11_object.cpp ├─ Mechanism handling: pkcs11/pkcs11/mechanism.cpp │ ▼ pkcs11/csp/ → shared/pcsc/ → card ``` -------------------------------- ### Build libopencie-pkcs11 on Android (Cross-compile) Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Installs Android dependencies via vcpkg, configures the cross-compilation toolchain, and builds the library for the `arm64-v8a` ABI. The output is `libopencie-pkcs11.so`. ```bash vcpkg install --triplet arm64-android \ cryptopp curl freetype libpng libxml2 openssl zlib sed -i "s|/opt/android-ndk|$ANDROID_NDK_ROOT|g" toolchains/cross-android-arm64.ini sed -i "s|@SOURCE_ROOT@|$(pwd)|g" toolchains/cross-android-arm64.ini PKG_CONFIG_LIBDIR=$VCPKG_ROOT/installed/arm64-android/lib/pkgconfig \ ANDROID_ABI=arm64-v8a ANDROID_PLATFORM=android-28 \ VCPKG_INSTALLED_DIR=$VCPKG_ROOT/installed VCPKG_TARGET_TRIPLET=arm64-android \ meson setup builddir-android --cross-file toolchains/cross-android-arm64.ini meson compile -C builddir-android # Output: builddir-android/libopencie-pkcs11.so ``` -------------------------------- ### Build OpenCIE PKCS#11 on macOS Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/README.md Installs dependencies using Homebrew and builds the library using Meson and Ninja. ```bash brew install openssl cryptopp curl freetype libpng libxml2 openjpeg podofo zlib meson setup builddir meson compile -C builddir # Output: builddir/libopencie-pkcs11.dylib ``` -------------------------------- ### Reader Hot-Plug Detection Example Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/examples/README.md Demonstrates reader hot-plug detection using the `cie_reader_watch` function. ```c reader_watch.c ``` -------------------------------- ### Example: Signing a PDF with a Visible Widget Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Demonstrates how to use the `cie_sign` function to sign a PDF file with a visible signature widget on a specified page. Includes callback functions for progress reporting and completion status. Ensure correct arguments for PAN, PIN, input/output files, and widget positioning. ```c /* sign_pdf.c — sign a PDF with a visible widget on page 0 */ #include #include #include "opencie/cie_ext.h" static CK_RV on_progress(int pct, const char* msg) { printf("[%3d%%] %s\n", pct, msg ? msg : ""); return CKR_OK; } static CK_RV on_sign_done(int ret) { if (ret == 0) printf("\nSigning completed successfully.\n"); else fprintf(stderr, "\nSigning failed (ret=%d).\n", ret); return CKR_OK; } int main(int argc, char* argv[]) { /* argv[1]=PAN argv[2]=PIN argv[3]=input.pdf argv[4]=output.pdf */ const char* pan = argv[1]; const char* pin = argv[2]; const char* in_pdf = argv[3]; const char* out_pdf = argv[4]; CK_RV rv = cie_sign( in_pdf, /* input file */ "PDF", /* type: "PDF" or "P7M" */ pin, /* 8-digit card PIN */ pan, /* 16-digit card PAN */ 0, /* page index (0-based) */ 10.0f, /* x position in PDF points */ 10.0f, /* y position in PDF points */ 200.0f, /* widget width in PDF points */ 50.0f, /* widget height in PDF points */ NULL, 0, /* no PNG stamp image */ out_pdf, /* signed output path */ on_progress, on_sign_done ); if (rv != CKR_OK) { fprintf(stderr, "cie_sign returned rv=0x%08lX\n", rv); return EXIT_FAILURE; } return EXIT_SUCCESS; } /* * Example output: * [ 0%] Opening document ... * [ 30%] Computing hash ... * [ 60%] Requesting card signature ... * [ 90%] Embedding CMS signature ... * [100%] Done * * Signing completed successfully. */ ``` -------------------------------- ### RFC 3161 Timestamping Example Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/examples/README.md Demonstrates RFC 3161 timestamping using the `cie_timestamp` function. ```c timestamp.c ``` -------------------------------- ### Hot-Plug Reader Monitoring Example Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Demonstrates how to use `cie_reader_count`, `cie_reader_watch`, and `cie_reader_name` to monitor connected smart-card readers for hot-plug events. The program continuously prints the reader count and the name of the first reader, blocking when the count changes. ```c /* reader_watch.c — monitor hot-plug events */ #include #include "opencie/cie_ext.h" int main(void) { printf("Watching for reader changes. Press Ctrl-C to exit.\n\n"); int current = cie_reader_count(); for (;;) { char name[256] = {0}; cie_reader_name(name, sizeof(name)); printf("Readers connected: %d", current); if (current > 0 && name[0]) printf(" (first: \"%s\")", name); printf("\n"); /* Blocks until the count changes, returns new count */ current = cie_reader_watch(current); } return 0; } /* * Example output: * Readers connected: 0 * Readers connected: 1 (first: "ACS ACR122U PICC Interface 00 00") * Readers connected: 0 */ ``` -------------------------------- ### Reader Discovery Functions Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Declares three functions for managing smart-card readers: `cie_reader_count` to get the number of connected readers, `cie_reader_watch` to block until the reader count changes, and `cie_reader_name` to retrieve the name of the first reader. ```c int cie_reader_count(void); // Number of connected readers int cie_reader_watch(int current_count); // Block until count changes; returns new count int cie_reader_name(char* buf, int len); // Copy first reader name into buf ``` -------------------------------- ### Get Verification Info Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/docs/api.md Retrieves detailed information about a specific signature from the results of a `cie_verify` call. The `index` parameter specifies which signature's information to retrieve. ```c CK_RV cie_get_verify_info(int index, struct verifyInfo_t* vInfos); ``` -------------------------------- ### Android NFC Reader Mode Setup Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Java/Kotlin code to enable NFC reader mode and wire up the detected NFC tag to the native PKCS#11 layer. Sets the data directory for certificate caching. ```java // Java/Kotlin NFC dispatch — wire up the tag to the native layer import android.nfc.NfcAdapter; import android.nfc.Tag; public class CieActivity extends AppCompatActivity { static { System.loadLibrary("opencie-pkcs11"); } // Declare JNI stubs public static native void setNfcTag(Tag tag); public static native void clearNfcTag(void); public static native void setDataDir(String path); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Set the app-private data directory for the certificate cache setDataDir(getFilesDir().getAbsolutePath()); NfcAdapter.getDefaultAdapter(this).enableReaderMode(this, tag -> { setNfcTag(tag); // Now cie_enable / cie_sign etc. will use this NFC tag runEnrolment(tag); clearNfcTag(); }, NfcAdapter.FLAG_READER_NFC_B, null); } } ``` -------------------------------- ### Dynamically Load libopencie-pkcs11 Library Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Demonstrates how to dynamically load the `libopencie-pkcs11.so` library at runtime using `dlopen` and retrieve a function pointer to `cie_enable`. Ensure the library path is correct for your system. ```c #include #include "opencie/cie_ext.h" void* lib = dlopen("/usr/lib/libopencie-pkcs11.so", RTLD_LAZY); if (!lib) { fprintf(stderr, "dlopen: %s\n", dlerror()); return 1; } typedef CK_RV (*cie_enable_fn)(const char*, const char*, int*, PROGRESS_CALLBACK, COMPLETED_CALLBACK); cie_enable_fn fn_enable = (cie_enable_fn)dlsym(lib, "cie_enable"); // ... use the function, then: dlclose(lib); ``` -------------------------------- ### Build libopencie-pkcs11 on Linux (Containerized) Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Builds a container image for compiling the library, then runs it to produce platform-independent binaries for x86_64 and aarch64 architectures. Output files are placed in the `output` directory. ```bash podman build -t libopencie-builder -f Containerfile . mkdir -p output podman run --rm -v $(pwd)/output:/output libopencie-builder x86_64 podman run --rm -v $(pwd)/output:/output libopencie-builder aarch64 # Output: output/libopencie-pkcs11-x86_64.so # output/libopencie-pkcs11-aarch64.so ``` -------------------------------- ### Get Signature Count Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/docs/api.md Retrieves the number of signatures found during the last `cie_verify` operation. This function does not require any parameters. ```c CK_RV cie_get_sign_count(void); ``` -------------------------------- ### Build OpenCIE PKCS#11 Library using Podman Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/llms.txt Builds the library in a portable container environment using Podman. Mounts an output directory to retrieve the built library. ```bash # Portable (container) podman build -t libopencie-builder -f Containerfile . podman run --rm -v $(pwd)/output:/output libopencie-builder x86_64 ``` -------------------------------- ### Build OpenCIE PKCS#11 Library on Linux Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/llms.txt Builds the library using Meson on Linux. The output is a shared library file. ```bash # Linux (native) meson setup builddir && meson compile -C builddir # Output: builddir/libopencie-pkcs11.so ``` -------------------------------- ### Build OpenCIE PKCS#11 on Linux (Portable) Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/README.md Builds a portable version of the library using Podman or Docker, linking dependencies statically. Targets glibc 2.35 for compatibility. ```bash podman build -t libopencie-builder -f Containerfile . mkdir -p output podman run --rm -v $(pwd)/output:/output libopencie-builder x86_64 podman run --rm -v $(pwd)/output:/output libopencie-builder aarch64 # Output: output/libopencie-pkcs11-x86_64.so # output/libopencie-pkcs11-aarch64.so ``` ```meson meson setup builddir-portable-${ARCH} \ -Dportable=true -Dprefer_static=true \ -Dbuildtype=release -Dstrip=true \ [--cross-file toolchains/cross-aarch64.ini] ``` -------------------------------- ### Build OpenCIE PKCS#11 on Windows (Cross-compile) Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/README.md Cross-compiles the library from Linux using MinGW-w64 and vcpkg. Requires setting PKG_CONFIG_LIBDIR. ```bash vcpkg install --triplet x64-mingw-dynamic \ cryptopp curl freetype libpng libxml2 openjpeg openssl podofo zlib PKG_CONFIG_LIBDIR=$VCPKG_ROOT/installed/x64-mingw-dynamic/lib/pkgconfig \ meson setup builddir-win --cross-file toolchains/cross-mingw.ini PKG_CONFIG_LIBDIR=$VCPKG_ROOT/installed/x64-mingw-dynamic/lib/pkgconfig \ meson compile -C builddir-win # Output: builddir-win/libopencie-pkcs11.dll ``` -------------------------------- ### Dynamically Load Library Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/docs/usage.md Load the shared library dynamically, recommended for plugins. Ensure the library path is correct. ```c #include #include "opencie/cie_ext.h" void* lib = dlopen("/usr/lib/libopencie-pkcs11.so", RTLD_LAZY); if (!lib) { fprintf(stderr, "%s\n", dlerror()); return 1; } typedef CK_RV (*cie_enable_fn)(const char*, const char*, int*, PROGRESS_CALLBACK, COMPLETED_CALLBACK); cies_enable_fn enable = (cie_enable_fn)dlsym(lib, "cie_enable"); ``` -------------------------------- ### Configure Chromium/Chrome/Edge (NSS) Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/docs/usage.md Add the opencie-pkcs11 library as a security module for NSS-based browsers like Chromium, Chrome, and Edge. ```bash modutil -dbdir sql:$HOME/.pki/nssdb -add "CIE" \ -libfile /usr/lib/libopencie-pkcs11.so ``` -------------------------------- ### libopencie-pkcs11 Module Structure Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/ARCHITECTURE.md Illustrates the layered architecture of the libopencie-pkcs11 shared library, showing how the pkcs11/, sign-sdk/, and shared/ modules are integrated. ```text ┌─────────────────────────────────────────────────────────┐ │ libopencie-pkcs11 (shared library) │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌───────────────┐ │ │ │ pkcs11/ │ │ sign-sdk/ │ │ shared/ │ │ │ │ (final SO) │ │ (static .a) │ │ (static .a) │ │ │ └──────┬───────┘ └──────┬───────┘ └───────┬───────┘ │ │ └─────────────────┴──────────────────┘ │ └─────────────────────────────────────────────────────────┘ ``` -------------------------------- ### Build OpenCIE PKCS#11 on Android (Cross-compile) Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/README.md Cross-compiles the library from Linux for Android using vcpkg and the Android NDK. Requires modifying toolchain files and setting environment variables. ```bash # arm64-v8a vcpkg install --triplet arm64-android \ cryptopp curl freetype libpng libxml2 openjpeg openssl zlib sed -i "s|/opt/android-ndk|$ANDROID_NDK_ROOT|g" toolchains/cross-android-arm64.ini sed -i "s|@SOURCE_ROOT@|$(pwd)|g" toolchains/cross-android-arm64.ini PKG_CONFIG_LIBDIR=$VCPKG_ROOT/installed/arm64-android/lib/pkgconfig \ ANDROID_ABI=arm64-v8a ANDROID_PLATFORM=android-28 \ VCPKG_INSTALLED_DIR=$VCPKG_ROOT/installed VCPKG_TARGET_TRIPLET=arm64-android \ meson setup builddir-android --cross-file toolchains/cross-android-arm64.ini meson compile -C builddir-android # Output: builddir-android/libopencie-pkcs11.so ``` -------------------------------- ### Register PKCS#11 Library with Chromium/Chrome/Edge Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/README.md Registers the built PKCS#11 library with the browser's NSS database. Replace the placeholder with the actual library path. ```bash modutil -dbdir sql:$HOME/.pki/nssdb -add "CIE" \ -libfile /path/to/libopencie-pkcs11.so modutil -dbdir sql:$HOME/.pki/nssdb -list ``` -------------------------------- ### cie_enable Function Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Reads the CIE chip's X.509 certificate and stores it locally. Must be called before PKCS#11 or signing operations. ```APIDOC ## `cie_enable` — Card Enrolment Reads the CIE chip's X.509 certificate over PC/SC (or NFC on Android) using the IAS protocol, then stores it in a local AES-encrypted cache keyed by PAN. Must be called once per card before any PKCS#11 or signing operation. Returns `CKR_PIN_INCORRECT` with `*attempts` decremented on wrong PIN, and `CKR_PIN_LOCKED` when no attempts remain. ```c CK_RV cie_enable(const char* szPAN, const char* szPIN, int* attempts, PROGRESS_CALLBACK progressCallBack, COMPLETED_CALLBACK completedCallBack); ``` ### Example Usage ```c /* enrol.c — full enrolment example */ #include #include #include "opencie/cie_ext.h" static CK_RV on_progress(int pct, const char* msg) { printf("[%3d%%] %s\n", pct, msg ? msg : ""); return CKR_OK; } static CK_RV on_complete(const char* pan, const char* name, const char* serial) { printf("\nEnrolment complete:\n"); printf(" PAN: %s\n", pan ? pan : "(null)"); printf(" Name: %s\n", name ? name : "(null)"); printf(" Serial: %s\n", serial ? serial : "(null)"); return CKR_OK; } int main(int argc, char* argv[]) { /* argv[1] = 16-digit PAN, argv[2] = 8-digit PIN */ const char* pan = argv[1]; const char* pin = argv[2]; int attempts = -1; CK_RV rv = cie_enable(pan, pin, &attempts, on_progress, on_complete); if (rv != CKR_OK) { fprintf(stderr, "cie_enable failed: rv=0x%08lX", rv); if (attempts >= 0) fprintf(stderr, " (PIN attempts remaining: %d)", attempts); fprintf(stderr, "\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; } /* * Example output (success): * [ 0%] Connecting to card ... * [ 20%] Reading certificate ... * [ 80%] Caching ... * [100%] Done * * Enrolment complete: * PAN: 1234567890123456 * Name: MARIO ROSSI * Serial: 1A2B3C4D5E6F * * Example output (wrong PIN, 2 attempts left): * cie_enable failed: rv=0x000000A0 (PIN attempts remaining: 2) */ ``` ``` -------------------------------- ### cie_enable Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/docs/api.md Enrols a CIE card by reading its certificate and storing it in a local cache. It requires the card's PAN and PIN, and accepts progress and completion callbacks. ```APIDOC ## cie_enable ### Description Enrol a CIE card. Reads the card's certificate and stores it in an AES-encrypted local cache keyed by PAN. ### Method `CK_RV cie_enable(const char* szPAN, const char* szPIN, int* attempts, PROGRESS_CALLBACK progressCallBack, COMPLETED_CALLBACK completedCallBack);` ### Parameters #### Path Parameters - `szPAN` (const char*) - Required - PAN identifying the card (NUL-terminated) - `szPIN` (const char*) - Required - 8-digit numeric PIN (NUL-terminated) - `attempts` (int*) - Optional - Set to remaining PIN attempts on error; may be `NULL` - `progressCallBack` (PROGRESS_CALLBACK) - Required - Progress callback; must not be `NULL` - `completedCallBack` (COMPLETED_CALLBACK) - Required - Completion callback; must not be `NULL` ### Returns `CKR_OK` on success. `CKR_PIN_INCORRECT` with `*attempts` decremented on wrong PIN. ``` -------------------------------- ### OpenSSL PKCS#11 Module Listing Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/docs/usage.md List certificates available through the opencie-pkcs11 module using OpenSSL. ```bash openssl pkcs11 -module /usr/lib/libopencie-pkcs11.so -list-certs ``` -------------------------------- ### Static Link Signing SDK Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Links the PDF signing SDK as a static archive, providing access to signing functionalities without exposing all PKCS#11 entry points. This is useful when only signing capabilities are needed. ```bash gcc myapp.c -I include/ -L builddir/ -lopencie-sign-sdk -lopencie-pkcs11 -o myapp ``` -------------------------------- ### Browser and NSS Integration Commands Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Shell commands for registering the PKCS#11 library with Firefox, Chromium-based browsers (via NSS database), and OpenSSL. Includes instructions for p11-kit system-wide registration. ```bash # Firefox / Librewolf: via GUI # about:preferences → Privacy & Security → Security Devices → Load # Point to: /usr/lib/libopencie-pkcs11.so # Chromium / Chrome / Edge — register in the NSS database modutil -dbdir sql:$HOME/.pki/nssdb \ -add "CIE" \ -libfile /usr/lib/libopencie-pkcs11.so modutil -dbdir sql:$HOME/.pki/nssdb -list # Expected output includes: # 2. CIE # library name: /usr/lib/libopencie-pkcs11.so # ... # slots: 1 slot attached # OpenSSL — list certificates from the token openssl pkcs11 -module /usr/lib/libopencie-pkcs11.so -list-certs # p11-kit — system-wide registration # Add to /etc/pkcs11/modules/opencie.module: # module: /usr/lib/libopencie-pkcs11.so # Then query via p11-kit: p11-kit list-modules p11tool --provider /usr/lib/libopencie-pkcs11.so --list-all ``` -------------------------------- ### Timestamping Workflow Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/ARCHITECTURE.md Details the process for timestamping a file, including reading the file, generating a digest, creating a TimeStampRequest, and parsing the TimeStampToken. ```text Application │ cie_timestamp(inFilePath, tsaUrl, ...) ▼ pkcs11/csp/cie_timestamp_csp.cpp │ fread(inFilePath) → CSHA256::Digest ▼ sign-sdk/tsa_client.cpp │ RFC 3161 TimeStampRequest (libcurl HTTP POST) ▼ sign-sdk/asn1/ (parse TimeStampToken DER) ▼ Output: DER-encoded TimeStampToken (.tst) ``` -------------------------------- ### Enrol Card Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/docs/usage.md Enrol a card by reading its X.509 certificate and storing it in a local cache. This must be done once per card before signing or PKCS#11 operations. Progress and completion callbacks are provided. ```c #include "opencie/cie_ext.h" static CK_RV on_progress(int pct, const char* msg) { printf("[%3d%%] %s\n", pct, msg); return CKR_OK; } static CK_RV on_complete(const char* pan, const char* name, const char* serial) { printf("Enrolled: %s (%s), serial=%s\n", name, pan, serial); return CKR_OK; } int attempts = 0; CK_RV rv = cie_enable("1234567890123456", "12345678", &attempts, on_progress, on_complete); if (rv != CKR_OK) { fprintf(stderr, "Enrolment failed (rv=%lu, attempts left=%d)\n", rv, attempts); } ``` -------------------------------- ### Verify Signatures in PDF/P7M Documents Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Use `cie_verify` to check all signatures in a document. Retrieve signature counts with `cie_get_sign_count` and details with `cie_get_verify_info`. Supports optional HTTP proxy for OCSP/CRL fetching. ```c CK_RV cie_verify(const char* inFilePath, const char* proxyAddress, /* NULL = no proxy */ int proxyPort, /* 0 = no proxy */ const char* usrPass); /* NULL = no auth */ CK_RV cie_get_sign_count(void); CK_RV cie_get_verify_info(int index, struct verifyInfo_t* vInfos); ``` ```c /* verify_doc.c — verify all signatures in a signed PDF or P7M */ #include #include #include "opencie/cie_ext.h" int main(int argc, char* argv[]) { const char* path = argv[1]; printf("Verifying: %s\n\n", path); /* NULL proxy arguments = direct network access */ CK_RV rv = cie_verify(path, NULL, 0, NULL); if (rv != CKR_OK) { fprintf(stderr, "cie_verify failed: rv=0x%08lX\n", rv); return EXIT_FAILURE; } int count = (int)cie_get_sign_count(); printf("Signatures found: %d\n\n", count); for (int i = 0; i < count; i++) { struct verifyInfo_t info = {0}; CK_RV r = cie_get_verify_info(i, &info); if (r != CKR_OK) { fprintf(stderr, " [%d] cie_get_verify_info failed: rv=0x%08lX\n", i, r); continue; } printf(" Signature %d:\n", i); printf(" Name: %s %s\n", info.name, info.surname); printf(" CN: %s\n", info.cn); printf(" Signed at: %s\n", info.signingTime); printf(" CA DN: %s\n", info.cadn); printf(" Sig valid: %s\n", info.isSignValid ? "YES" : "NO"); printf(" Cert valid: %s\n", info.isCertValid ? "YES" : "NO"); printf(" Cert revoc: %d\n", info.CertRevocStatus); printf("\n"); } return EXIT_SUCCESS; } /* * Example output: * Verifying: contract_signed.pdf * * Signatures found: 1 * * Signature 0: * Name: MARIO ROSSI * CN: RSSMRA80A01H501U * Signed at: 2024-03-15T10:32:11Z * CA DN: CN=Ministero dell'Interno CA, O=Ministero dell'Interno, C=IT * Sig valid: YES * Cert valid: YES * Cert revoc: 0 */ ``` -------------------------------- ### PDF Signing Data Flow Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/ARCHITECTURE.md Outlines the process for signing a PDF document using `cie_sign`, including the interaction with the smart card for raw RSA signature generation and optional timestamping. ```text Application │ cie_sign(inPath, "PDF", pin, pan, ...) ▼ pkcs11/sign/cie_sign.cpp │ ▼ sign-sdk/cie_sign_api.cpp │ Open PDF (PoDoFo), compute document hash ▼ sign-sdk/cie_signer.cpp │ Request raw RSA signature from card ▼ pkcs11/csp/cie_sign_csp.cpp │ PC/SC APDU: INTERNAL AUTHENTICATE ▼ shared/pcsc/pcsc.cpp → smart card reader / Android NFC │ Raw RSA signature bytes ▼ sign-sdk/pdf_signature_generator.cpp │ Embed CMS/PKCS#7 signature into PDF ▼ sign-sdk/tsa_client.cpp (optional: RFC 3161 timestamp) │ ▼ Output signed PDF ``` -------------------------------- ### make_digest_info Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Build a DER-encoded PKCS#1 `DigestInfo` structure for raw RSA signing flows outside the standard `cie_sign` pipeline. Supported `algid` values are OpenSSL NIDs: `NID_sha1` (65), `NID_sha256` (672), `NID_sha384` (673), `NID_sha512` (674). Returns `1` on success, `0` if the output buffer is too small. ```APIDOC ## `make_digest_info` — Low-Level DigestInfo Builder Build a DER-encoded PKCS#1 `DigestInfo` structure for raw RSA signing flows outside the standard `cie_sign` pipeline. Supported `algid` values are OpenSSL NIDs: `NID_sha1` (65), `NID_sha256` (672), `NID_sha384` (673), `NID_sha512` (674). Returns `1` on success, `0` if the output buffer is too small. ### Function Signature ```c int make_digest_info(int algid, const unsigned char* pbtDigest, size_t btDigestLen, unsigned char* pbtDigestInfo, size_t* pbtDigestInfoLen); ``` ### Description This function constructs a DER-encoded `DigestInfo` structure, which is a prerequisite for raw RSA signing operations. It takes a digest algorithm identifier, the digest value, and output buffer information to create the structure. ### Parameters - **algid** (int) - Required - The algorithm identifier for the digest. Supported values include OpenSSL NIDs like `NID_sha1` (65), `NID_sha256` (672), `NID_sha384` (673), `NID_sha512` (674). - **pbtDigest** (const unsigned char*) - Required - A pointer to the raw digest bytes. - **btDigestLen** (size_t) - Required - The length of the digest in bytes. - **pbtDigestInfo** (unsigned char*) - Optional - A pointer to the buffer where the DER-encoded `DigestInfo` will be written. If NULL, the function will only calculate the required buffer size. - **pbtDigestInfoLen** (size_t*) - Required - A pointer to a size_t variable. On input, it should contain the size of the `pbtDigestInfo` buffer. On output, it will contain the actual size of the generated `DigestInfo` structure. ### Return Values - `int`: Returns `1` on success. Returns `0` if the provided output buffer (`pbtDigestInfo`) is too small to hold the `DigestInfo` structure. ``` -------------------------------- ### Card Enrolment Data Flow Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/ARCHITECTURE.md Details the sequence of operations during card enrolment using the `cie_enable` function, from the application call to the completion callback, highlighting interactions between different modules and PC/SC communication. ```text Application │ cie_enable(pan, pin, ...) ▼ pkcs11/csp/cie_enable.cpp │ Establish PC/SC session ▼ shared/pcsc/pcsc.cpp ──────────────────────────────────────────────────────┐ │ APDU: SELECT, EXTERNAL AUTHENTICATE │ Android: ▼ │ shared/pcsc/android_nfc_transport.cpp shared/csp/ias.cpp (IAS protocol: extended auth key derivation) │ (JNI NFC bridge) │ Read EF.SOD, EF.DH, certificate file └────────────── ▼ shared/crypto/ (RSA, AES, SHA for key derivation and cert decryption) │ ▼ pkcs11/csp/cie_enable.cpp │ AES-encrypt certificate → local cache ▼ COMPLETED_CALLBACK(pan, name, serial) ``` -------------------------------- ### Enrol CIE Card with cie_enable Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/docs/api.md Enrols a CIE card by reading its certificate and storing it in a local cache. Requires PAN, PIN, and callback functions for progress and completion. Handles PIN attempts and returns success or specific errors. ```c CK_RV cie_enable(const char* szPAN, const char* szPIN, int* attempts, PROGRESS_CALLBACK progressCallBack, COMPLETED_CALLBACK completedCallBack); ``` -------------------------------- ### cie_verify, cie_get_sign_count, cie_get_verify_info Source: https://context7.com/m0rf30/opencie-pkcs11/llms.txt Verify all signatures in a signed PDF or P7M document. Results are stored internally and retrieved via `cie_get_sign_count()` and `cie_get_verify_info()`. Optionally routes OCSP/CRL fetching through an HTTP proxy. ```APIDOC ## `cie_verify` / `cie_get_sign_count` / `cie_get_verify_info` — Document Verification Verify all signatures in a signed PDF or P7M document. Results are stored internally and retrieved via `cie_get_sign_count()` and `cie_get_verify_info()`. Optionally routes OCSP/CRL fetching through an HTTP proxy. ### Function Signatures ```c CK_RV cie_verify(const char* inFilePath, const char* proxyAddress, /* NULL = no proxy */ int proxyPort, /* 0 = no proxy */ const char* usrPass); /* NULL = no auth */ CK_RV cie_get_sign_count(void); CK_RV cie_get_verify_info(int index, struct verifyInfo_t* vInfos); ``` ### Description - `cie_verify`: Verifies all signatures in a given file. It can optionally use an HTTP proxy for OCSP/CRL fetching. - `cie_get_sign_count`: Retrieves the number of signatures found after a `cie_verify` operation. - `cie_get_verify_info`: Retrieves detailed information about a specific signature found during verification. ### Parameters #### `cie_verify` Parameters - **inFilePath** (const char*) - Required - Path to the signed document file. - **proxyAddress** (const char*) - Optional - The address of the HTTP proxy. If NULL, no proxy is used. - **proxyPort** (int) - Optional - The port of the HTTP proxy. If 0, no proxy is used. - **usrPass** (const char*) - Optional - User password for authentication. If NULL, no authentication is used. #### `cie_get_sign_count` Parameters None. #### `cie_get_verify_info` Parameters - **index** (int) - Required - The index of the signature to retrieve information for. - **vInfos** (struct verifyInfo_t*) - Required - A pointer to a `verifyInfo_t` structure to be filled with the signature information. ### Return Values - `CK_RV`: A `CK_RV` type indicating the success or failure of the operation. `CKR_OK` indicates success. ``` -------------------------------- ### Sign PDF or P7M with CIE Card Source: https://github.com/m0rf30/opencie-pkcs11/blob/main/docs/api.md Use this function to sign a PDF file or create a P7M envelope using an enrolled CIE card. It supports specifying signature widget position for PDFs and provides callbacks for progress and completion. ```c CK_RV cie_sign(const char* inFilePath, const char* type, const char* pin, const char* pan, int page, float x, float y, float w, float h, const unsigned char* imageData, int imageDataLen, const char* outFilePath, PROGRESS_CALLBACK progressCallBack, SIGN_COMPLETED_CALLBACK completedCallBack); ```