Skip to content

Instantly share code, notes, and snippets.

@jpopesculian
Created May 22, 2019 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpopesculian/d1980cd74e885fb7b927e24b719d94f2 to your computer and use it in GitHub Desktop.
Save jpopesculian/d1980cd74e885fb7b927e24b719d94f2 to your computer and use it in GitHub Desktop.
PKCS11 play
CFLAGS=-Wall
LDFLAGS=-leprimus -lprimusP11 -I/usr/local/primus/include -L/usr/local/primus/lib -lsodium
CC = gcc
SRC = pkcs11_play.c
OUT = pkcs11_play.o
LOG = /tmp/primus.log
.PHONY:all clean watch build
all: build run # logs
build:
$(CC) $(CFLAGS) -o $(OUT) $(SRC) $(LDFLAGS)
clean: clean-log
rm -f $(OUT)
clean-log:
rm -f $(LOG)
run: clean-log
./$(OUT) || printf "failed 0x%x\n" "$$?"
debug: build clean-log
gdb $(OUT)
logs:
cat $(LOG)
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <pkcs11.h>
#include <sodium.h>
typedef void (*CK_OBJECT_HANDLER)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject);
const char user[] = "";
const unsigned long ulUserLen = 000;
const char pass[] = "";
const unsigned long ulPassLen = 000;
const char pin[] = "";
const unsigned long ulPinLen = 000;
#define GEN_PRIV_KEY 1
const char privKey[] = "MIIBHwIBAAKCAQEAsGz0H3/n5nQf+0pch2zan6wc/soBwGPIVYT/HcTao2XWWQJn/r5WHLCAcn0rEf67+GvcOYmTbY7+sJ5rq/pjg8BvZX6rtY7OzZ2vMW2DXjjriIzBsrECEvFN+1zbCIpNDt5H8+2IlXwpNBNmQxKau6+TBiSscHk/UxbZN9l+bXlXJQoyZpl50WkkrHk9plpaOujDbxrYKPGZoaNLaIGz7NsSeG7ydKQM5qOyuEwx38wCt0bRc6R/KqV4YA3SO7YtxfkApktXCMaqh+MJCuE/k+hnQfvQgol5t7BtvS/LqIQxHpijXLThZQeDheiQmmqeCCSmiH05sYjDbiztJhrfiQIDAQABAgEBAgEBAgEBAgEBAgEBAgEB";
const size_t privKeyLen = 388;
void notify(CK_SESSION_HANDLE session, CK_NOTIFICATION event, CK_VOID_PTR app_ptr) {
printf("happens");
}
void login(
CK_SESSION_HANDLE_PTR phSession,
unsigned const char *pin,
unsigned const long ulPinLen
) {
int rv;
/* rv = C_Initialize(NULL); */
/* rv = C_InitializeOpenSSL("/usr/local/primus/etc/primus.cfg"); */
rv = C_InitializeWithLogFile(NULL, "/usr/local/primus/etc/primus.cfg");
assert(rv == CKR_OK && "initialize");
rv = C_OpenSession(
0,
CKF_SERIAL_SESSION | CKF_RW_SESSION,
NULL,
(CK_NOTIFY) notify,
phSession
);
assert(rv == CKR_OK && "open session");
rv = C_Login(*phSession, CKU_USER, (CK_UTF8CHAR_PTR) pin, ulPinLen);
assert(rv == CKR_OK && "login");
}
void logout(
CK_SESSION_HANDLE hSession
) {
int rv = 0;
rv |= C_Logout(hSession);
rv |= C_CloseSession(hSession);
rv |= C_Finalize(NULL);
assert(rv == CKR_OK && "logout");
}
void printChallenge(
unsigned const char *user,
unsigned const long ulUserLen,
unsigned const char *pass,
unsigned const long ulPassLen,
unsigned const char *pin,
unsigned const long ulPinLen
) {
int rv;
unsigned char *challenge;
unsigned long ulChallengeLen;
rv = C_GetUserChallenge(
(unsigned char*) user,
ulUserLen,
(unsigned char*) pass,
ulPassLen,
(unsigned char*) pin,
ulPinLen,
NULL,
&ulChallengeLen
);
assert(rv == CKR_OK && "get challenge");
challenge = (unsigned char*) malloc(ulChallengeLen);
rv = C_GetUserChallenge(
(unsigned char*) user,
ulUserLen,
(unsigned char*) pass,
ulPassLen,
(unsigned char*) pin,
ulPinLen,
challenge,
&ulChallengeLen
);
assert(rv == CKR_OK && "set challenge");
printf("challenge (%ld bytes): ", ulChallengeLen);
for (int i = 0; i < ulChallengeLen; i++) {
printf("%d ", challenge[i]);
}
printf("\n");
free(challenge);
}
void loop_objects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLER handler) {
int rv;
rv = C_FindObjectsInit(hSession, NULL, 0);
assert(rv == CKR_OK && "find objects init");
CK_ULONG ulObjectCount;
CK_OBJECT_HANDLE hObject;
while (1) {
rv = C_FindObjects(hSession, &hObject, 1, &ulObjectCount);
assert(rv == CKR_OK && "find objects");
if (ulObjectCount < 1) { break; }
handler(hSession, hObject);
}
rv = C_FindObjectsFinal(hSession);
assert(rv == CKR_OK && "find objects final");
}
void handle_public_key(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) {
int rv;
CK_ATTRIBUTE template[] = {
{CKA_VALUE, NULL, 0}
};
unsigned long ulTemplateLen = 1;
CK_BYTE_PTR value;
rv = C_GetAttributeValue(
hSession,
hObject,
(CK_ATTRIBUTE_PTR) &template,
ulTemplateLen
);
assert(rv == CKR_OK && "get attribute");
value = (CK_BYTE_PTR) malloc(template[0].ulValueLen);
template[0].pValue = value;
rv = C_GetAttributeValue(
hSession,
hObject,
(CK_ATTRIBUTE_PTR) &template,
ulTemplateLen
);
assert(rv == CKR_OK && "set attribute");
printf("public_key:\n");
for (int i = 0; i < template[0].ulValueLen; i++) {
printf("%d ", value[i]);
}
printf("\n");
free(value);
}
void handle_private_key2(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) {
int rv;
CK_ATTRIBUTE template[] = {
{CKA_MODULUS, NULL, 0},
{CKA_PUBLIC_EXPONENT, NULL, 0}
};
unsigned long ulTemplateLen = 2;
CK_BYTE_PTR modulus;
CK_BYTE_PTR exp1;
rv = C_GetAttributeValue(
hSession,
hObject,
(CK_ATTRIBUTE_PTR) &template,
ulTemplateLen
);
assert(rv == CKR_OK && "get attribute");
modulus = (CK_BYTE_PTR) malloc(template[0].ulValueLen);
template[0].pValue = modulus;
exp1 = (CK_BYTE_PTR) malloc(template[1].ulValueLen);
template[1].pValue = exp1;
rv = C_GetAttributeValue(
hSession,
hObject,
(CK_ATTRIBUTE_PTR) &template,
ulTemplateLen
);
assert(rv == CKR_OK && "set attribute");
printf("private_key:\n");
printf("\tmod: ");
for (int i = 0; i < template[0].ulValueLen; i++) {
printf("%d ", modulus[i]);
}
printf("\n\tpublic_exp: ");
for (int i = 0; i < template[1].ulValueLen; i++) {
printf("%d ", exp1[i]);
}
printf("\n");
free(modulus);
free(exp1);
}
void handle_private_key(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) {
int rv;
CK_BBOOL unwrap;
CK_ATTRIBUTE template[] = {
{CKA_UNWRAP, &unwrap, 1}
};
unsigned long ulTemplateLen = 1;
rv = C_GetAttributeValue(
hSession,
hObject,
(CK_ATTRIBUTE_PTR) &template,
ulTemplateLen
);
assert(rv == CKR_OK && "get unwrap");
if (unwrap) {
printf("Private key unwrappable\n");
/*
* TODO figure out how to unwrap private key
* The key seems to be wrapped in an RSA encryption
* but requires another private key to unwrap it.
* maybe related to the user challenge? but 32 bytes
* is too short for any private key...
*/
}
}
void handle_object(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) {
int rv;
unsigned char classVal[8];
CK_ATTRIBUTE classTemplate[] = {
{CKA_CLASS, &classVal, 8},
};
rv = C_GetAttributeValue(
hSession,
hObject,
(CK_ATTRIBUTE_PTR) &classTemplate,
1
);
assert(rv == CKR_OK && "get class val");
printf("\n");
switch (classVal[0]) {
case CKO_PRIVATE_KEY:
handle_private_key2(hSession, hObject);
break;
default:
handle_public_key(hSession, hObject);
break;
}
}
void create_private_key(CK_OBJECT_HANDLE_PTR phObject, CK_SESSION_HANDLE hSession) {
int rv;
int valueLen = 256;
unsigned char value[256];
sodium_base642bin(value, valueLen, privKey, privKeyLen, NULL, NULL, NULL, sodium_base64_VARIANT_ORIGINAL);
CK_BBOOL true = CK_TRUE;
CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
CK_KEY_TYPE keyType = CKK_RSA;
CK_ATTRIBUTE keyTemplate[] = {
{CKA_CLASS, &keyClass, sizeof(keyClass)},
{CKA_KEY_TYPE, &keyType, sizeof(keyType)},
{CKA_WRAP, &true, sizeof(true)},
{CKA_VALUE, &value, valueLen}
};
rv = C_CreateObject(hSession, &keyTemplate, 4, phObject);
assert(rv == CKR_OK && "object create");
}
int main(void) {
CK_SESSION_HANDLE hSession;
login(&hSession, (unsigned char *) pin, ulPinLen);
printChallenge(
(unsigned char*) user,
ulUserLen,
(unsigned char*) pass,
ulPassLen,
(unsigned char*) pin,
ulPinLen
);
#ifdef GEN_PRIV_KEY
CK_OBJECT_HANDLE hObject;
create_private_key(&hObject, hSession);
#else
loop_objects(hSession, handle_object);
#endif
logout(hSession);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment