diff options
Diffstat (limited to 'contrib/pkcs11-keygen/writekey.c')
-rw-r--r-- | contrib/pkcs11-keygen/writekey.c | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/contrib/pkcs11-keygen/writekey.c b/contrib/pkcs11-keygen/writekey.c new file mode 100644 index 0000000..3d1ba99 --- /dev/null +++ b/contrib/pkcs11-keygen/writekey.c @@ -0,0 +1,360 @@ +/* writekey [-s $slot] [-p $pin] -l $label -i $id -f $filename */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#ifndef OPENCRYPTOKI +#include <security/cryptoki.h> +#include <security/pkcs11.h> +#else +#include <opencryptoki/pkcs11.h> +#endif +#include <openssl/conf.h> +#include <openssl/engine.h> +#include <openssl/err.h> +#include <openssl/rsa.h> +#include <openssl/pem.h> + +/* Define static key template values */ +static CK_BBOOL truevalue = TRUE; +static CK_BBOOL falsevalue = FALSE; + +int +main(int argc, char *argv[]) +{ + ENGINE *e; + RSA *rsa = NULL; + FILE *fp; + CK_RV rv; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE hSession; + CK_UTF8CHAR *pin = NULL; + CK_BYTE new_id[2]; + CK_OBJECT_HANDLE key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS kclass; + CK_KEY_TYPE ktype = CKK_RSA; + CK_ATTRIBUTE template[50]; + CK_ULONG template_size; + CK_BYTE data[8][1024]; + CK_ULONG ulObjectCount; + char *label = NULL, *filename = NULL; + int id = 0; + int error = 0; + int c, errflg = 0; + extern char *optarg; + extern int optopt; + + while ((c = getopt(argc, argv, ":s:l:i:p:f:")) != -1) { + switch (c) { + case 's': + slot = atoi(optarg); + break; + case 'l': + label = optarg; + break; + case 'i': + id = atoi(optarg); + id &= 0xffff; + break; + case 'p': + pin = (CK_UTF8CHAR *)optarg; + break; + case 'f': + filename = optarg; + break; + case ':': + fprintf(stderr, "Option -%c requires an operand\n", optopt); + errflg++; + break; + case '?': + default: + fprintf(stderr, "Unrecognised option: -%c\n", optopt); + errflg++; + } + } + if ((errflg) || (!label) || (!id) || (!filename)) { + fprintf(stderr, + "usage: writekey [-s slot] [-p pin] -l label -i id " + "-f filename\n"); + exit(2); + } + + /* Load the config file */ + OPENSSL_config(NULL); + + /* Register engine */ + e = ENGINE_by_id("pkcs11"); + if (!e) { + /* the engine isn't available */ + printf("The engine isn't available\n"); + ERR_print_errors_fp(stderr); + exit(1); + } + + if (!ENGINE_init(e)) { + /* the engine couldn't initialise, release 'e' */ + printf("The engine couldn't initialise\n"); + ERR_print_errors_fp(stderr); + ENGINE_free(e); + exit(1); + } + + /* Read the key */ + fp = fopen(filename, "r"); + if (fp == NULL) { + printf("Error opening input file.\n"); + ENGINE_free(e); + exit(1); + } + + rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); + (void) fclose(fp); + if (rsa == NULL) { + printf("Error reading input file.\n"); + ERR_print_errors_fp(stderr); + ENGINE_free(e); + exit(1); + } + + /* Initialize the CRYPTOKI library */ + rv = C_Initialize(NULL_PTR); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) { + fprintf(stderr, "C_Initialize: Error = 0x%.8X\n", rv); + ENGINE_free(e); + exit(1); + } + + /* Open a session on the slot found */ + rv = C_OpenSession(slot, CKF_RW_SESSION+CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &hSession); + if (rv != CKR_OK) { + fprintf(stderr, "C_OpenSession: Error = 0x%.8X\n", rv); + error = 1; + goto exit_program; + } + + /* Login to the Token (Keystore) */ + if (!pin) +#ifndef OPENCRYPTOKI + pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: "); +#else + pin = (CK_UTF8CHAR *)getpass("Enter Pin: "); +#endif + rv = C_Login(hSession, CKU_USER, pin, strlen((char *)pin)); + memset(pin, 0, strlen((char *)pin)); + if (rv != CKR_OK) { + fprintf(stderr, "C_Login: Error = 0x%.8X\n", rv); + error = 1; + goto exit_session; + } + + /* fill the search template */ + if (strstr(label, "pkcs11:") == label) + label = strstr(label, ":") + 1; + kclass = CKO_PRIVATE_KEY; + template[0].type = CKA_TOKEN; + template[0].pValue = &truevalue; + template[0].ulValueLen = sizeof (truevalue); + template[1].type = CKA_CLASS; + template[1].pValue = &kclass; + template[1].ulValueLen = sizeof (kclass); + template[2].type = CKA_LABEL; + template[2].pValue = label; + template[2].ulValueLen = strlen(label); + + /* check if a key with the same label already exists */ + rv = C_FindObjectsInit(hSession, template, 3); + if (rv != CKR_OK) { + fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8X\n", rv); + error = 1; + goto exit_session; + } + rv = C_FindObjects(hSession, &key, 1, &ulObjectCount); + if (rv != CKR_OK) { + fprintf(stderr, "C_FindObjects: Error = 0x%.8X\n", rv); + error = 1; + goto exit_search; + } + if (ulObjectCount != 0) { + fprintf(stderr, "Key already exists.\n"); + error = 1; + goto exit_search; + } + + /* fill attributes for the public key */ + new_id[0] = (id >> 8) & 0xff; + new_id[1] = id & 0xff; + kclass = CKO_PUBLIC_KEY; + if (BN_num_bytes(rsa->n) > 1024) { + fprintf(stderr, "RSA modulus too large\n"); + error = 1; + goto exit_search; + } + BN_bn2bin(rsa->n, data[0]); + if (BN_num_bytes(rsa->e) > 1024) { + fprintf(stderr, "RSA public exponent too large\n"); + error = 1; + goto exit_search; + } + BN_bn2bin(rsa->e, data[1]); + if (BN_num_bytes(rsa->d) > 1024) { + fprintf(stderr, "RSA private exponent too large\n"); + error = 1; + goto exit_search; + } + BN_bn2bin(rsa->d, data[2]); + if (BN_num_bytes(rsa->p) > 1024) { + fprintf(stderr, "RSA prime 1 too large\n"); + error = 1; + goto exit_search; + } + BN_bn2bin(rsa->p, data[3]); + if (BN_num_bytes(rsa->q) > 1024) { + fprintf(stderr, "RSA prime 2 too large\n"); + error = 1; + goto exit_search; + } + BN_bn2bin(rsa->q, data[4]); + if (BN_num_bytes(rsa->dmp1) > 1024) { + fprintf(stderr, "RSA exponent 1 too large\n"); + error = 1; + goto exit_search; + } + BN_bn2bin(rsa->dmp1, data[5]); + if (BN_num_bytes(rsa->dmq1) > 1024) { + fprintf(stderr, "RSA exponent 2 too large\n"); + error = 1; + goto exit_search; + } + BN_bn2bin(rsa->dmq1, data[6]); + if (BN_num_bytes(rsa->iqmp) > 1024) { + fprintf(stderr, "RSA coefficient too large\n"); + error = 1; + goto exit_search; + } + BN_bn2bin(rsa->iqmp, data[7]); + + template[0].type = CKA_TOKEN; + template[0].pValue = &truevalue; + template[0].ulValueLen = sizeof (truevalue); + template[1].type = CKA_CLASS; + template[1].pValue = &kclass; + template[1].ulValueLen = sizeof (kclass); + template[2].type = CKA_LABEL; + template[2].pValue = label; + template[2].ulValueLen = strlen(label); + template[3].type = CKA_ID; + template[3].pValue = new_id; + template[3].ulValueLen = sizeof (new_id); + template[4].type = CKA_KEY_TYPE; + template[4].pValue = &ktype; + template[4].ulValueLen = sizeof (ktype); + template[5].type = CKA_ENCRYPT; + template[5].pValue = &truevalue; + template[5].ulValueLen = sizeof (truevalue); + template[6].type = CKA_VERIFY; + template[6].pValue = &truevalue; + template[6].ulValueLen = sizeof (truevalue); + template[7].type = CKA_VERIFY_RECOVER; + template[7].pValue = &truevalue; + template[7].ulValueLen = sizeof (truevalue); + template[8].type = CKA_MODULUS; + template[8].pValue = data[0]; + template[8].ulValueLen = BN_num_bytes(rsa->n); + template[9].type = CKA_PUBLIC_EXPONENT; + template[9].pValue = data[1]; + template[9].ulValueLen = BN_num_bytes(rsa->e); + + rv = C_CreateObject(hSession, template, 10, &key); + if (rv != CKR_OK) { + fprintf(stderr, "C_CreateObject (pub): Error = 0x%.8X\n", rv); + error = 1; + goto exit_search; + } + + /* fill attributes for the private key */ + kclass = CKO_PRIVATE_KEY; + template[0].type = CKA_TOKEN; + template[0].pValue = &truevalue; + template[0].ulValueLen = sizeof (truevalue); + template[1].type = CKA_CLASS; + template[1].pValue = &kclass; + template[1].ulValueLen = sizeof (kclass); + template[2].type = CKA_LABEL; + template[2].pValue = label; + template[2].ulValueLen = strlen(label); + template[3].type = CKA_ID; + template[3].pValue = new_id; + template[3].ulValueLen = sizeof (new_id); + template[4].type = CKA_KEY_TYPE; + template[4].pValue = &ktype; + template[4].ulValueLen = sizeof (ktype); + template[5].type = CKA_SENSITIVE; + template[5].pValue = &falsevalue; + template[5].ulValueLen = sizeof (falsevalue); + template[6].type = CKA_EXTRACTABLE; + template[6].pValue = &truevalue; + template[6].ulValueLen = sizeof (truevalue); + template[7].type = CKA_DECRYPT; + template[7].pValue = &truevalue; + template[7].ulValueLen = sizeof (truevalue); + template[8].type = CKA_SIGN; + template[8].pValue = &truevalue; + template[8].ulValueLen = sizeof (truevalue); + template[9].type = CKA_SIGN_RECOVER; + template[9].pValue = &truevalue; + template[9].ulValueLen = sizeof (truevalue); + template[10].type = CKA_MODULUS; + template[10].pValue = data[0]; + template[10].ulValueLen = BN_num_bytes(rsa->n); + template[11].type = CKA_PUBLIC_EXPONENT; + template[11].pValue = data[1]; + template[11].ulValueLen = BN_num_bytes(rsa->e); + template[12].type = CKA_PRIVATE_EXPONENT; + template[12].pValue = data[2]; + template[12].ulValueLen = BN_num_bytes(rsa->d); + template[13].type = CKA_PRIME_1; + template[13].pValue = data[3]; + template[13].ulValueLen = BN_num_bytes(rsa->p); + template[14].type = CKA_PRIME_2; + template[14].pValue = data[4]; + template[14].ulValueLen = BN_num_bytes(rsa->q); + template[15].type = CKA_EXPONENT_1; + template[15].pValue = data[5]; + template[15].ulValueLen = BN_num_bytes(rsa->dmp1); + template[16].type = CKA_EXPONENT_2; + template[16].pValue = data[6]; + template[16].ulValueLen = BN_num_bytes(rsa->dmq1); + template[17].type = CKA_COEFFICIENT; + template[17].pValue = data[7]; + template[17].ulValueLen = BN_num_bytes(rsa->iqmp); + + rv = C_CreateObject(hSession, template, 18, &key); + if (rv != CKR_OK) { + fprintf(stderr, "C_CreateObject (priv): Error = 0x%.8X\n", rv); + (void) C_DestroyObject(hSession, key); + error = 1; + goto exit_search; + } + + exit_search: + rv = C_FindObjectsFinal(hSession); + if (rv != CKR_OK) { + fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8X\n", rv); + error = 1; + } + + exit_session: + (void) C_CloseSession(hSession); + + exit_program: + (void) C_Finalize(NULL_PTR); + ENGINE_free(e); + ENGINE_cleanup(); + + exit(error); +} |