Created
May 22, 2019 14:19
-
-
Save jpopesculian/d1980cd74e885fb7b927e24b719d94f2 to your computer and use it in GitHub Desktop.
PKCS11 play
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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