Last active
November 13, 2024 21:28
-
-
Save joostd/26498f94f9eea136277b23e70ce58eb1 to your computer and use it in GitHub Desktop.
Generate an RSA key in slot 9a of a YubiKey using YKCS11
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 <dlfcn.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <pkcs11y.h> | |
/* | |
* Generate an RSA key in slot 9a of a YubiKey | |
* Adapted from the YubiHSM example at: | |
* https://github.com/Yubico/yubihsm-shell/blob/master/examples/p11_generate_rsa.c | |
* Note that not all attributes types are supported. See | |
* https://developers.yubico.com/yubico-piv-tool/YKCS11/Functions_and_values.html | |
*/ | |
int main(int argc, char *argv[]) { | |
if (argc != 2) { | |
fprintf(stderr, "usage: ykcs11_generate_rsa /path/to/yubikey_pkcs11/module\n"); | |
exit(EXIT_FAILURE); | |
} | |
CK_C_GetFunctionList fn; | |
void *handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL); | |
assert(handle != NULL); | |
*(void **) (&fn) = dlsym(handle, "C_GetFunctionList"); | |
assert(fn != NULL); | |
CK_FUNCTION_LIST_PTR p11; | |
CK_RV rv = fn(&p11); | |
assert(rv == CKR_OK); | |
rv = p11->C_Initialize(NULL_PTR); | |
assert(rv == CKR_OK); | |
CK_SLOT_ID pSlotList[16]; | |
CK_ULONG pulCount = 16; | |
rv = p11->C_GetSlotList(true, pSlotList, &pulCount); | |
assert(rv == CKR_OK); | |
CK_SESSION_HANDLE session; | |
rv = p11->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session); | |
assert(rv == CKR_OK); | |
char password[] = "010203040506070801020304050607080102030405060708"; | |
rv = p11->C_Login(session, CKU_SO, (CK_UTF8CHAR_PTR) password, (CK_ULONG) strlen(password)); | |
assert(rv == CKR_OK); | |
CK_MECHANISM mechanism = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0}; | |
CK_ULONG modulus = 2048; | |
CK_BYTE exponent[] = {0x00, 0x1, 0x0, 0x1}; // 65537 | |
CK_BYTE id[] = {1}; | |
CK_BBOOL ck_true = CK_TRUE; | |
CK_BBOOL ck_false = CK_FALSE; | |
char pub_label[] = "RSA 2048 key"; | |
char priv_label[] = "RSA 2048 key"; | |
CK_ATTRIBUTE publicKeyTemplate[] = { | |
{CKA_ENCRYPT, &ck_true, sizeof(ck_true)}, | |
{CKA_DECRYPT, &ck_false, sizeof(ck_false)}, | |
{CKA_SIGN, &ck_false, sizeof(ck_false)}, | |
{CKA_VERIFY, &ck_true, sizeof(ck_true)}, | |
{CKA_WRAP, &ck_true, sizeof(ck_true)}, | |
{CKA_UNWRAP, &ck_false, sizeof(ck_false)}, | |
{CKA_TOKEN, &ck_true, sizeof(ck_true)}, | |
{CKA_PRIVATE, &ck_false, sizeof(ck_false)}, | |
{CKA_EXTRACTABLE, &ck_true, sizeof(ck_true)}, | |
{CKA_EXTRACTABLE, &ck_false, sizeof(ck_false)}, | |
//{CKA_MODIFIABLE, &ck_false, sizeof(ck_false)}, // not supported | |
{CKA_COPYABLE, &ck_false, sizeof(ck_false)}, | |
{CKA_DESTROYABLE, &ck_true, sizeof(ck_true)}, | |
{CKA_ID, id, sizeof(id)}, | |
{CKA_MODULUS_BITS, &modulus, sizeof(modulus)}, | |
{CKA_PUBLIC_EXPONENT, exponent, sizeof(exponent)}, | |
{CKA_LABEL, pub_label, sizeof(pub_label)}, | |
}; | |
CK_ULONG publicKeyAttributeCount = | |
sizeof(publicKeyTemplate) / sizeof(publicKeyTemplate[0]); | |
CK_ATTRIBUTE privateKeyTemplate[] = { | |
{CKA_ENCRYPT, &ck_false, sizeof(ck_false)}, | |
{CKA_DECRYPT, &ck_true, sizeof(ck_true)}, | |
{CKA_SIGN, &ck_true, sizeof(ck_true)}, | |
{CKA_VERIFY, &ck_false, sizeof(ck_false)}, | |
{CKA_WRAP, &ck_false, sizeof(ck_false)}, | |
{CKA_UNWRAP, &ck_true, sizeof(ck_true)}, | |
{CKA_TOKEN, &ck_true, sizeof(ck_true)}, | |
{CKA_PRIVATE, &ck_true, sizeof(ck_true)}, | |
//{CKA_EXTRACTABLE, &ck_true, sizeof(ck_true)}, // not supported | |
{CKA_EXTRACTABLE, &ck_false, sizeof(ck_false)}, | |
//{CKA_MODIFIABLE, &ck_false, sizeof(ck_false)}, // not supported | |
{CKA_COPYABLE, &ck_false, sizeof(ck_false)}, | |
{CKA_DESTROYABLE, &ck_true, sizeof(ck_true)}, | |
{CKA_ID, id, sizeof(id)}, | |
{CKA_LABEL, priv_label, sizeof(priv_label)}, | |
}; | |
CK_ULONG privateKeyAttributeCount = | |
sizeof(privateKeyTemplate) / sizeof(privateKeyTemplate[0]); | |
CK_OBJECT_HANDLE publicKey, privateKey; | |
rv = | |
p11->C_GenerateKeyPair(session, &mechanism, publicKeyTemplate, | |
publicKeyAttributeCount, privateKeyTemplate, | |
privateKeyAttributeCount, &publicKey, &privateKey); | |
assert(rv == CKR_OK); | |
rv = p11->C_Logout(session); | |
assert(rv == CKR_OK); | |
rv = p11->C_CloseSession(session); | |
assert(rv == CKR_OK); | |
rv = p11->C_Finalize(NULL); | |
assert(rv == CKR_OK); | |
dlclose(handle); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Compile with
Run with