From 0c89b3ccba7c9b7332ab67ae1936aff51ca62367 Mon Sep 17 00:00:00 2001 From: NingSun Date: Thu, 8 Feb 2018 08:34:03 -0800 Subject: Initial sshsm project structure Issue-ID: AAF-94 Change-Id: I5e82fff418e7567b161acf9b98013a9b85ffc5b4 Signed-off-by: NingSun --- SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp | 790 ++++++++++++++++++++++++++ 1 file changed, 790 insertions(+) create mode 100644 SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp (limited to 'SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp') diff --git a/SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp b/SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp new file mode 100644 index 0000000..fedfd28 --- /dev/null +++ b/SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp @@ -0,0 +1,790 @@ +/* + * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + softhsm2-util-ossl.cpp + + Code specific for OpenSSL + *****************************************************************************/ + +#include +#define UTIL_OSSL +#include "softhsm2-util.h" +#include "softhsm2-util-ossl.h" +#include "OSSLComp.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +// Init OpenSSL +void crypto_init() +{ + // We do not need to do this one + // OpenSSL_add_all_algorithms(); +#ifdef WITH_FIPS + // The PKCS#11 library might be using a FIPS capable OpenSSL + if (FIPS_mode()) + return; + if (!FIPS_mode_set(1)) + { + fprintf(stderr, "ERROR: can't enter into FIPS mode.\n"); + exit(0); + } +#endif +} + +// Final OpenSSL +void crypto_final() +{ + // EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); +} + +int crypto_import_aes_key +( + CK_SESSION_HANDLE hSession, + char* filePath, + char* label, + char* objID, + size_t objIDLen +) +{ + const size_t cMaxAesKeySize = 1024 + 1; // including null-character + char aesKeyValue[cMaxAesKeySize]; + FILE* fp = fopen(filePath, "rb"); + if (fp == NULL) + { + fprintf(stderr, "ERROR: Could not open the secret key file.\n"); + return 1; + } + if (fgets(aesKeyValue, cMaxAesKeySize, fp) == NULL) + { + fprintf(stderr, "ERROR: Could not read the secret key file.\n"); + fclose(fp); + return 1; + } + fclose(fp); + + CK_BBOOL ckTrue = CK_TRUE; + CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; + CK_KEY_TYPE keyType = CKK_AES; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &keyClass, sizeof(keyClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_LABEL, label, strlen(label) }, + { CKA_ID, objID, objIDLen }, + { CKA_TOKEN, &ckTrue, sizeof(ckTrue) }, + { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) }, + { CKA_VALUE, &aesKeyValue, strlen(aesKeyValue) } + }; + + CK_OBJECT_HANDLE hKey; + CK_RV rv = p11->C_CreateObject(hSession, keyTemplate, 9, &hKey); + if (rv != CKR_OK) + { + fprintf(stderr, "ERROR: Could not save the secret key in the token. " + "Maybe the algorithm is not supported.\n"); + return 1; + } + + return 0; +} + +// Import a key pair from given path +int crypto_import_key_pair +( + CK_SESSION_HANDLE hSession, + char* filePath, + char* filePIN, + char* label, + char* objID, + size_t objIDLen, + int noPublicKey +) +{ + EVP_PKEY* pkey = crypto_read_file(filePath, filePIN); + if (pkey == NULL) + { + return 1; + } + + RSA* rsa = NULL; + DSA* dsa = NULL; +#ifdef WITH_ECC + EC_KEY* ecdsa = NULL; +#endif + + switch (EVP_PKEY_type(EVP_PKEY_id(pkey))) + { + case EVP_PKEY_RSA: + rsa = EVP_PKEY_get1_RSA(pkey); + break; + case EVP_PKEY_DSA: + dsa = EVP_PKEY_get1_DSA(pkey); + break; +#ifdef WITH_ECC + case EVP_PKEY_EC: + ecdsa = EVP_PKEY_get1_EC_KEY(pkey); + break; +#endif + default: + fprintf(stderr, "ERROR: Cannot handle this algorithm.\n"); + EVP_PKEY_free(pkey); + return 1; + break; + } + EVP_PKEY_free(pkey); + + int result = 0; + + if (rsa) + { + result = crypto_save_rsa(hSession, label, objID, objIDLen, noPublicKey, rsa); + RSA_free(rsa); + } + else if (dsa) + { + result = crypto_save_dsa(hSession, label, objID, objIDLen, noPublicKey, dsa); + DSA_free(dsa); + } +#ifdef WITH_ECC + else if (ecdsa) + { + result = crypto_save_ecdsa(hSession, label, objID, objIDLen, noPublicKey, ecdsa); + EC_KEY_free(ecdsa); + } +#endif + else + { + fprintf(stderr, "ERROR: Could not get the key material.\n"); + result = 1; + } + + return result; +} + +// Read the key from file +EVP_PKEY* crypto_read_file(char* filePath, char* filePIN) +{ + BIO* in = NULL; + PKCS8_PRIV_KEY_INFO* p8inf = NULL; + EVP_PKEY* pkey = NULL; + X509_SIG* p8 = NULL; + + if (!(in = BIO_new_file(filePath, "rb"))) + { + fprintf(stderr, "ERROR: Could open the PKCS#8 file: %s\n", filePath); + return NULL; + } + + // The PKCS#8 file is encrypted + if (filePIN) + { + p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL); + BIO_free(in); + + if (!p8) + { + fprintf(stderr, "ERROR: Could not read the PKCS#8 file. " + "Maybe the file is not encrypted.\n"); + return NULL; + } + + p8inf = PKCS8_decrypt(p8, filePIN, strlen(filePIN)); + X509_SIG_free(p8); + + if (!p8inf) + { + fprintf(stderr, "ERROR: Could not decrypt the PKCS#8 file. " + "Maybe wrong PIN to file (--file-pin )\n"); + return NULL; + } + } + else + { + p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL); + BIO_free(in); + + if (!p8inf) + { + fprintf(stderr, "ERROR: Could not read the PKCS#8 file. " + "Maybe it is encypted (--file-pin )\n"); + return NULL; + } + } + + // Convert the PKCS#8 to OpenSSL + pkey = EVP_PKCS82PKEY(p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + if (!pkey) + { + fprintf(stderr, "ERROR: Could not convert the key.\n"); + return NULL; + } + + return pkey; +} + +// Save the key data in PKCS#11 +int crypto_save_rsa +( + CK_SESSION_HANDLE hSession, + char* label, + char* objID, + size_t objIDLen, + int noPublicKey, + RSA* rsa +) +{ + rsa_key_material_t* keyMat = crypto_malloc_rsa(rsa); + if (!keyMat) + { + fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n"); + return 1; + } + + CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY; + CK_KEY_TYPE keyType = CKK_RSA; + CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE; + if (noPublicKey) + { + ckToken = CK_FALSE; + } + CK_ATTRIBUTE pubTemplate[] = { + { CKA_CLASS, &pubClass, sizeof(pubClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_LABEL, label, strlen(label) }, + { CKA_ID, objID, objIDLen }, + { CKA_TOKEN, &ckToken, sizeof(ckToken) }, + { CKA_VERIFY, &ckTrue, sizeof(ckTrue) }, + { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_WRAP, &ckTrue, sizeof(ckTrue) }, + { CKA_PUBLIC_EXPONENT, keyMat->bigE, keyMat->sizeE }, + { CKA_MODULUS, keyMat->bigN, keyMat->sizeN } + }; + CK_ATTRIBUTE privTemplate[] = { + { CKA_CLASS, &privClass, sizeof(privClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_LABEL, label, strlen(label) }, + { CKA_ID, objID, objIDLen }, + { CKA_SIGN, &ckTrue, sizeof(ckTrue) }, + { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_UNWRAP, &ckTrue, sizeof(ckTrue) }, + { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) }, + { CKA_TOKEN, &ckTrue, sizeof(ckTrue) }, + { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) }, + { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) }, + { CKA_PUBLIC_EXPONENT, keyMat->bigE, keyMat->sizeE }, + { CKA_MODULUS, keyMat->bigN, keyMat->sizeN }, + { CKA_PRIVATE_EXPONENT, keyMat->bigD, keyMat->sizeD }, + { CKA_PRIME_1, keyMat->bigP, keyMat->sizeP }, + { CKA_PRIME_2, keyMat->bigQ, keyMat->sizeQ }, + { CKA_EXPONENT_1, keyMat->bigDMP1, keyMat->sizeDMP1 }, + { CKA_EXPONENT_2, keyMat->bigDMQ1, keyMat->sizeDMQ1 }, + { CKA_COEFFICIENT, keyMat->bigIQMP, keyMat->sizeIQMP } + }; + + CK_OBJECT_HANDLE hKey1, hKey2; + CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 19, &hKey1); + if (rv != CKR_OK) + { + fprintf(stderr, "ERROR: Could not save the private key in the token. " + "Maybe the algorithm is not supported.\n"); + crypto_free_rsa(keyMat); + return 1; + } + + rv = p11->C_CreateObject(hSession, pubTemplate, 10, &hKey2); + crypto_free_rsa(keyMat); + + if (rv != CKR_OK) + { + p11->C_DestroyObject(hSession, hKey1); + fprintf(stderr, "ERROR: Could not save the public key in the token.\n"); + return 1; + } + + printf("The key pair has been imported.\n"); + + return 0; +} + +// Convert the OpenSSL key to binary +rsa_key_material_t* crypto_malloc_rsa(RSA* rsa) +{ + if (rsa == NULL) + { + return NULL; + } + + rsa_key_material_t* keyMat = (rsa_key_material_t*)malloc(sizeof(rsa_key_material_t)); + if (keyMat == NULL) + { + return NULL; + } + + const BIGNUM* bn_e = NULL; + const BIGNUM* bn_n = NULL; + const BIGNUM* bn_d = NULL; + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_q = NULL; + const BIGNUM* bn_dmp1 = NULL; + const BIGNUM* bn_dmq1 = NULL; + const BIGNUM* bn_iqmp = NULL; + RSA_get0_factors(rsa, &bn_p, &bn_q); + RSA_get0_crt_params(rsa, &bn_dmp1, &bn_dmq1, &bn_iqmp); + RSA_get0_key(rsa, &bn_n, &bn_e, &bn_d); + + keyMat->sizeE = BN_num_bytes(bn_e); + keyMat->sizeN = BN_num_bytes(bn_n); + keyMat->sizeD = BN_num_bytes(bn_d); + keyMat->sizeP = BN_num_bytes(bn_p); + keyMat->sizeQ = BN_num_bytes(bn_q); + keyMat->sizeDMP1 = BN_num_bytes(bn_dmp1); + keyMat->sizeDMQ1 = BN_num_bytes(bn_dmq1); + keyMat->sizeIQMP = BN_num_bytes(bn_iqmp); + + keyMat->bigE = (CK_VOID_PTR)malloc(keyMat->sizeE); + keyMat->bigN = (CK_VOID_PTR)malloc(keyMat->sizeN); + keyMat->bigD = (CK_VOID_PTR)malloc(keyMat->sizeD); + keyMat->bigP = (CK_VOID_PTR)malloc(keyMat->sizeP); + keyMat->bigQ = (CK_VOID_PTR)malloc(keyMat->sizeQ); + keyMat->bigDMP1 = (CK_VOID_PTR)malloc(keyMat->sizeDMP1); + keyMat->bigDMQ1 = (CK_VOID_PTR)malloc(keyMat->sizeDMQ1); + keyMat->bigIQMP = (CK_VOID_PTR)malloc(keyMat->sizeIQMP); + + if + ( + !keyMat->bigE || + !keyMat->bigN || + !keyMat->bigD || + !keyMat->bigP || + !keyMat->bigQ || + !keyMat->bigDMP1 || + !keyMat->bigDMQ1 || + !keyMat->bigIQMP + ) + { + crypto_free_rsa(keyMat); + return NULL; + } + + BN_bn2bin(bn_e, (unsigned char*)keyMat->bigE); + BN_bn2bin(bn_n, (unsigned char*)keyMat->bigN); + BN_bn2bin(bn_d, (unsigned char*)keyMat->bigD); + BN_bn2bin(bn_p, (unsigned char*)keyMat->bigP); + BN_bn2bin(bn_q, (unsigned char*)keyMat->bigQ); + BN_bn2bin(bn_dmp1, (unsigned char*)keyMat->bigDMP1); + BN_bn2bin(bn_dmq1, (unsigned char*)keyMat->bigDMQ1); + BN_bn2bin(bn_iqmp, (unsigned char*)keyMat->bigIQMP); + + return keyMat; +} + +// Free the memory of the key +void crypto_free_rsa(rsa_key_material_t* keyMat) +{ + if (keyMat == NULL) return; + if (keyMat->bigE) free(keyMat->bigE); + if (keyMat->bigN) free(keyMat->bigN); + if (keyMat->bigD) free(keyMat->bigD); + if (keyMat->bigP) free(keyMat->bigP); + if (keyMat->bigQ) free(keyMat->bigQ); + if (keyMat->bigDMP1) free(keyMat->bigDMP1); + if (keyMat->bigDMQ1) free(keyMat->bigDMQ1); + if (keyMat->bigIQMP) free(keyMat->bigIQMP); + free(keyMat); +} + +// Save the key data in PKCS#11 +int crypto_save_dsa +( + CK_SESSION_HANDLE hSession, + char* label, + char* objID, + size_t objIDLen, + int noPublicKey, + DSA* dsa +) +{ + dsa_key_material_t* keyMat = crypto_malloc_dsa(dsa); + if (keyMat == NULL) + { + fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n"); + return 1; + } + + CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY; + CK_KEY_TYPE keyType = CKK_DSA; + CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE; + if (noPublicKey) + { + ckToken = CK_FALSE; + } + CK_ATTRIBUTE pubTemplate[] = { + { CKA_CLASS, &pubClass, sizeof(pubClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_LABEL, label, strlen(label) }, + { CKA_ID, objID, objIDLen }, + { CKA_TOKEN, &ckToken, sizeof(ckToken) }, + { CKA_VERIFY, &ckTrue, sizeof(ckTrue) }, + { CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) }, + { CKA_WRAP, &ckFalse, sizeof(ckFalse) }, + { CKA_PRIME, keyMat->bigP, keyMat->sizeP }, + { CKA_SUBPRIME, keyMat->bigQ, keyMat->sizeQ }, + { CKA_BASE, keyMat->bigG, keyMat->sizeG }, + { CKA_VALUE, keyMat->bigY, keyMat->sizeY } + }; + CK_ATTRIBUTE privTemplate[] = { + { CKA_CLASS, &privClass, sizeof(privClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_LABEL, label, strlen(label) }, + { CKA_ID, objID, objIDLen }, + { CKA_SIGN, &ckTrue, sizeof(ckTrue) }, + { CKA_DECRYPT, &ckFalse, sizeof(ckFalse) }, + { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) }, + { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) }, + { CKA_TOKEN, &ckTrue, sizeof(ckTrue) }, + { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) }, + { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) }, + { CKA_PRIME, keyMat->bigP, keyMat->sizeP }, + { CKA_SUBPRIME, keyMat->bigQ, keyMat->sizeQ }, + { CKA_BASE, keyMat->bigG, keyMat->sizeG }, + { CKA_VALUE, keyMat->bigX, keyMat->sizeX } + }; + + CK_OBJECT_HANDLE hKey1, hKey2; + CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 15, &hKey1); + if (rv != CKR_OK) + { + fprintf(stderr, "ERROR: Could not save the private key in the token. " + "Maybe the algorithm is not supported.\n"); + crypto_free_dsa(keyMat); + return 1; + } + + rv = p11->C_CreateObject(hSession, pubTemplate, 12, &hKey2); + crypto_free_dsa(keyMat); + + if (rv != CKR_OK) + { + p11->C_DestroyObject(hSession, hKey1); + fprintf(stderr, "ERROR: Could not save the public key in the token.\n"); + return 1; + } + + printf("The key pair has been imported.\n"); + + return 0; +} + +// Convert the OpenSSL key to binary +dsa_key_material_t* crypto_malloc_dsa(DSA* dsa) +{ + if (dsa == NULL) + { + return NULL; + } + + dsa_key_material_t* keyMat = (dsa_key_material_t*)malloc(sizeof(dsa_key_material_t)); + if (keyMat == NULL) + { + return NULL; + } + + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_q = NULL; + const BIGNUM* bn_g = NULL; + const BIGNUM* bn_priv_key = NULL; + const BIGNUM* bn_pub_key = NULL; + DSA_get0_pqg(dsa, &bn_p, &bn_q, &bn_g); + DSA_get0_key(dsa, &bn_pub_key, &bn_priv_key); + + keyMat->sizeP = BN_num_bytes(bn_p); + keyMat->sizeQ = BN_num_bytes(bn_q); + keyMat->sizeG = BN_num_bytes(bn_g); + keyMat->sizeX = BN_num_bytes(bn_priv_key); + keyMat->sizeY = BN_num_bytes(bn_pub_key); + + keyMat->bigP = (CK_VOID_PTR)malloc(keyMat->sizeP); + keyMat->bigQ = (CK_VOID_PTR)malloc(keyMat->sizeQ); + keyMat->bigG = (CK_VOID_PTR)malloc(keyMat->sizeG); + keyMat->bigX = (CK_VOID_PTR)malloc(keyMat->sizeX); + keyMat->bigY = (CK_VOID_PTR)malloc(keyMat->sizeY); + + if (!keyMat->bigP || !keyMat->bigQ || !keyMat->bigG || !keyMat->bigX || !keyMat->bigY) + { + crypto_free_dsa(keyMat); + return NULL; + } + + BN_bn2bin(bn_p, (unsigned char*)keyMat->bigP); + BN_bn2bin(bn_q, (unsigned char*)keyMat->bigQ); + BN_bn2bin(bn_g, (unsigned char*)keyMat->bigG); + BN_bn2bin(bn_priv_key, (unsigned char*)keyMat->bigX); + BN_bn2bin(bn_pub_key, (unsigned char*)keyMat->bigY); + + return keyMat; +} + +// Free the memory of the key +void crypto_free_dsa(dsa_key_material_t* keyMat) +{ + if (keyMat == NULL) return; + if (keyMat->bigP) free(keyMat->bigP); + if (keyMat->bigQ) free(keyMat->bigQ); + if (keyMat->bigG) free(keyMat->bigG); + if (keyMat->bigX) free(keyMat->bigX); + if (keyMat->bigY) free(keyMat->bigY); + free(keyMat); +} + +#ifdef WITH_ECC + +// Save the key data in PKCS#11 +int crypto_save_ecdsa +( + CK_SESSION_HANDLE hSession, + char* label, + char* objID, + size_t objIDLen, + int noPublicKey, + EC_KEY* ecdsa +) +{ + ecdsa_key_material_t* keyMat = crypto_malloc_ecdsa(ecdsa); + if (keyMat == NULL) + { + fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n"); + return 1; + } + + CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY; + CK_KEY_TYPE keyType = CKK_EC; + CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE; + if (noPublicKey) + { + ckToken = CK_FALSE; + } + CK_ATTRIBUTE pubTemplate[] = { + { CKA_CLASS, &pubClass, sizeof(pubClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_LABEL, label, strlen(label) }, + { CKA_ID, objID, objIDLen }, + { CKA_TOKEN, &ckToken, sizeof(ckToken) }, + { CKA_VERIFY, &ckTrue, sizeof(ckTrue) }, + { CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) }, + { CKA_WRAP, &ckFalse, sizeof(ckFalse) }, + { CKA_EC_PARAMS, keyMat->derParams, keyMat->sizeParams }, + { CKA_EC_POINT, keyMat->derQ, keyMat->sizeQ }, + }; + CK_ATTRIBUTE privTemplate[] = { + { CKA_CLASS, &privClass, sizeof(privClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_LABEL, label, strlen(label) }, + { CKA_ID, objID, objIDLen }, + { CKA_SIGN, &ckTrue, sizeof(ckTrue) }, + { CKA_DECRYPT, &ckFalse, sizeof(ckFalse) }, + { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) }, + { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) }, + { CKA_TOKEN, &ckTrue, sizeof(ckTrue) }, + { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) }, + { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) }, + { CKA_EC_PARAMS, keyMat->derParams, keyMat->sizeParams }, + { CKA_VALUE, keyMat->bigD, keyMat->sizeD } + }; + + CK_OBJECT_HANDLE hKey1, hKey2; + CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 13, &hKey1); + if (rv != CKR_OK) + { + fprintf(stderr, "ERROR: Could not save the private key in the token. " + "Maybe the algorithm is not supported.\n"); + crypto_free_ecdsa(keyMat); + return 1; + } + + rv = p11->C_CreateObject(hSession, pubTemplate, 10, &hKey2); + crypto_free_ecdsa(keyMat); + + if (rv != CKR_OK) + { + p11->C_DestroyObject(hSession, hKey1); + fprintf(stderr, "ERROR: Could not save the public key in the token.\n"); + return 1; + } + + printf("The key pair has been imported.\n"); + + return 0; +} + +// Convert the OpenSSL key to binary +ecdsa_key_material_t* crypto_malloc_ecdsa(EC_KEY* ec_key) +{ + int result; + + if (ec_key == NULL) + { + return NULL; + } + + ecdsa_key_material_t* keyMat = (ecdsa_key_material_t*)malloc(sizeof(ecdsa_key_material_t)); + if (keyMat == NULL) + { + return NULL; + } + + const BIGNUM *d = EC_KEY_get0_private_key(ec_key); + const EC_GROUP *group = EC_KEY_get0_group(ec_key); + const EC_POINT *point = EC_KEY_get0_public_key(ec_key); + + keyMat->sizeParams = i2d_ECPKParameters(group, NULL); + keyMat->sizeD = BN_num_bytes(d); + + keyMat->derParams = (CK_VOID_PTR)malloc(keyMat->sizeParams); + keyMat->bigD = (CK_VOID_PTR)malloc(keyMat->sizeD); + keyMat->derQ = NULL; + + if (!keyMat->derParams || !keyMat->bigD) + { + crypto_free_ecdsa(keyMat); + return NULL; + } + + /* + * i2d functions increment the pointer, so we have to use a + * sacrificial pointer + */ + unsigned char *derParams = (unsigned char*) keyMat->derParams; + result = i2d_ECPKParameters(group, &derParams); + if (result == 0) + { + crypto_free_ecdsa(keyMat); + return NULL; + } + BN_bn2bin(d, (unsigned char*)keyMat->bigD); + + size_t point_length = EC_POINT_point2oct(group, + point, + POINT_CONVERSION_UNCOMPRESSED, + NULL, + 0, + NULL); + + // Definite, short + if (point_length <= 0x7f) + { + keyMat->sizeQ = 2 + point_length; + keyMat->derQ = (CK_VOID_PTR)malloc(keyMat->sizeQ); + if (!keyMat->derQ) + { + crypto_free_ecdsa(keyMat); + return NULL; + } + + unsigned char *derQ = (unsigned char *)keyMat->derQ; + derQ[0] = V_ASN1_OCTET_STRING; + derQ[1] = point_length & 0x7f; + result = EC_POINT_point2oct(group, + point, + POINT_CONVERSION_UNCOMPRESSED, + &derQ[2], + point_length, + NULL); + if (result == 0) + { + crypto_free_ecdsa(keyMat); + return NULL; + } + } + // Definite, long + else + { + // Count significate bytes + size_t bytes = sizeof(size_t); + for(; bytes > 0; bytes--) + { + size_t value = point_length >> ((bytes - 1) * 8); + if (value & 0xFF) break; + } + + keyMat->sizeQ = 2 + bytes + point_length; + keyMat->derQ = (CK_VOID_PTR)malloc(keyMat->sizeQ); + if (!keyMat->derQ) + { + crypto_free_ecdsa(keyMat); + return NULL; + } + + unsigned char *derQ = (unsigned char *)keyMat->derQ; + derQ[0] = V_ASN1_OCTET_STRING; + derQ[1] = 0x80 | bytes; + + size_t len = point_length; + for (size_t i = 1; i <= bytes; i++) + { + derQ[2+bytes-i] = (unsigned char) (len & 0xFF); + len >>= 8; + } + + result = EC_POINT_point2oct(group, + point, + POINT_CONVERSION_UNCOMPRESSED, + &derQ[2+bytes], + point_length, + NULL); + if (result == 0) + { + crypto_free_ecdsa(keyMat); + return NULL; + } + } + + return keyMat; +} + +// Free the memory of the key +void crypto_free_ecdsa(ecdsa_key_material_t* keyMat) +{ + if (keyMat == NULL) return; + if (keyMat->derParams) free(keyMat->derParams); + if (keyMat->bigD) free(keyMat->bigD); + if (keyMat->derQ) free(keyMat->derQ); + free(keyMat); +} + +#endif -- cgit 1.2.3-korg