diff options
Diffstat (limited to 'SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp')
-rw-r--r-- | SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp | 704 |
1 files changed, 704 insertions, 0 deletions
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp b/SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp new file mode 100644 index 0000000..cecc0ce --- /dev/null +++ b/SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp @@ -0,0 +1,704 @@ +/* + * 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-botan.cpp + + Code specific for Botan + *****************************************************************************/ + +#include <config.h> +#define UTIL_BOTAN +#include "softhsm2-util.h" +#include "softhsm2-util-botan.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <iostream> +#include <fstream> + +#include <botan/init.h> +#include <botan/auto_rng.h> +#include <botan/pkcs8.h> +#include <botan/bigint.h> +#include <botan/version.h> +#include <botan/der_enc.h> + +#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14) +#include <botan/libstate.h> +bool wasInitialized = false; +#endif + +// Init Botan +void crypto_init() +{ +#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14) + // The PKCS#11 library might be using Botan + // Check if it has already initialized Botan + if (Botan::Global_State_Management::global_state_exists()) + { + wasInitialized = true; + } + + if (!wasInitialized) + { + Botan::LibraryInitializer::initialize("thread_safe=true"); + } +#else + Botan::LibraryInitializer::initialize("thread_safe=true"); +#endif +} + +// Final Botan +void crypto_final() +{ +#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14) + if (!wasInitialized) + { + Botan::LibraryInitializer::deinitialize(); + } +#else + Botan::LibraryInitializer::deinitialize(); +#endif +} + +// Import a aes secret key from given path +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 +) +{ + Botan::Private_Key* pkey = crypto_read_file(filePath, filePIN); + if (pkey == NULL) + { + return 1; + } + + Botan::RSA_PrivateKey* rsa = NULL; + Botan::DSA_PrivateKey* dsa = NULL; +#ifdef WITH_ECC + Botan::ECDSA_PrivateKey* ecdsa = NULL; +#endif + + if (pkey->algo_name().compare("RSA") == 0) + { + rsa = dynamic_cast<Botan::RSA_PrivateKey*>(pkey); + } + else if (pkey->algo_name().compare("DSA") == 0) + { + dsa = dynamic_cast<Botan::DSA_PrivateKey*>(pkey); + } +#ifdef WITH_ECC + else if (pkey->algo_name().compare("ECDSA") == 0) + { + ecdsa = dynamic_cast<Botan::ECDSA_PrivateKey*>(pkey); + } +#endif + else + { + fprintf(stderr, "ERROR: %s is not a supported algorithm.\n", + pkey->algo_name().c_str()); + delete pkey; + return 1; + } + + int result = 0; + + if (rsa) + { + result = crypto_save_rsa(hSession, label, objID, objIDLen, noPublicKey, rsa); + } + else if (dsa) + { + result = crypto_save_dsa(hSession, label, objID, objIDLen, noPublicKey, dsa); + } +#ifdef WITH_ECC + else if (ecdsa) + { + result = crypto_save_ecdsa(hSession, label, objID, objIDLen, noPublicKey, ecdsa); + } +#endif + else + { + fprintf(stderr, "ERROR: Could not get the key material.\n"); + result = 1; + } + + delete pkey; + return result; +} + +// Read the key from file +Botan::Private_Key* crypto_read_file(char* filePath, char* filePIN) +{ + if (filePath == NULL) + { + return NULL; + } + + Botan::AutoSeeded_RNG* rng = new Botan::AutoSeeded_RNG(); + Botan::Private_Key* pkey = NULL; + + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + if (filePIN == NULL) + { + pkey = Botan::PKCS8::load_key(std::string(filePath), *rng); + } + else + { + pkey = Botan::PKCS8::load_key(std::string(filePath), *rng, std::string(filePIN)); + } +#else + if (filePIN == NULL) + { + pkey = Botan::PKCS8::load_key(filePath, *rng); + } + else + { + pkey = Botan::PKCS8::load_key(filePath, *rng, filePIN); + } +#endif + } + catch (std::exception& e) + { + fprintf(stderr, "%s\n", e.what()); + fprintf(stderr, "ERROR: Perhaps wrong path to file, wrong file format, " + "or wrong PIN to file (--file-pin <PIN>).\n"); + delete rng; + return NULL; + } + delete rng; + + 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, + Botan::RSA_PrivateKey* 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 Botan key to binary +rsa_key_material_t* crypto_malloc_rsa(Botan::RSA_PrivateKey* 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; + } + + keyMat->sizeE = rsa->get_e().bytes(); + keyMat->sizeN = rsa->get_n().bytes(); + keyMat->sizeD = rsa->get_d().bytes(); + keyMat->sizeP = rsa->get_p().bytes(); + keyMat->sizeQ = rsa->get_q().bytes(); + keyMat->sizeDMP1 = rsa->get_d1().bytes(); + keyMat->sizeDMQ1 = rsa->get_d2().bytes(); + keyMat->sizeIQMP = rsa->get_c().bytes(); + + 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; + } + + rsa->get_e().binary_encode((Botan::byte*)keyMat->bigE); + rsa->get_n().binary_encode((Botan::byte*)keyMat->bigN); + rsa->get_d().binary_encode((Botan::byte*)keyMat->bigD); + rsa->get_p().binary_encode((Botan::byte*)keyMat->bigP); + rsa->get_q().binary_encode((Botan::byte*)keyMat->bigQ); + rsa->get_d1().binary_encode((Botan::byte*)keyMat->bigDMP1); + rsa->get_d2().binary_encode((Botan::byte*)keyMat->bigDMQ1); + rsa->get_c().binary_encode((Botan::byte*)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, + Botan::DSA_PrivateKey* 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 Botan key to binary +dsa_key_material_t* crypto_malloc_dsa(Botan::DSA_PrivateKey* 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; + } + + keyMat->sizeP = dsa->group_p().bytes(); + keyMat->sizeQ = dsa->group_q().bytes(); + keyMat->sizeG = dsa->group_g().bytes(); + keyMat->sizeX = dsa->get_x().bytes(); + keyMat->sizeY = dsa->get_y().bytes(); + + 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; + } + + dsa->group_p().binary_encode((Botan::byte*)keyMat->bigP); + dsa->group_q().binary_encode((Botan::byte*)keyMat->bigQ); + dsa->group_g().binary_encode((Botan::byte*)keyMat->bigG); + dsa->get_x().binary_encode((Botan::byte*)keyMat->bigX); + dsa->get_y().binary_encode((Botan::byte*)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, + Botan::ECDSA_PrivateKey* 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_ECDSA; + 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 Botan key to binary +ecdsa_key_material_t* crypto_malloc_ecdsa(Botan::ECDSA_PrivateKey* ecdsa) +{ + if (ecdsa == NULL) + { + return NULL; + } + + ecdsa_key_material_t *keyMat = (ecdsa_key_material_t *)malloc(sizeof(ecdsa_key_material_t)); + if (keyMat == NULL) + { + return NULL; + } + +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + std::vector<Botan::byte> derEC = ecdsa->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID); + Botan::secure_vector<Botan::byte> derPoint; +#else + Botan::SecureVector<Botan::byte> derEC = ecdsa->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID); + Botan::SecureVector<Botan::byte> derPoint; +#endif + + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + Botan::secure_vector<Botan::byte> repr = Botan::EC2OSP(ecdsa->public_point(), + Botan::PointGFp::UNCOMPRESSED); +#else + Botan::SecureVector<Botan::byte> repr = Botan::EC2OSP(ecdsa->public_point(), + Botan::PointGFp::UNCOMPRESSED); +#endif + + derPoint = Botan::DER_Encoder() + .encode(repr, Botan::OCTET_STRING) + .get_contents(); + } + catch (...) + { + return NULL; + } + + keyMat->sizeParams = derEC.size(); + keyMat->sizeD = ecdsa->private_value().bytes(); + keyMat->sizeQ = derPoint.size(); + + keyMat->derParams = (CK_VOID_PTR)malloc(keyMat->sizeParams); + keyMat->bigD = (CK_VOID_PTR)malloc(keyMat->sizeD); + keyMat->derQ = (CK_VOID_PTR)malloc(keyMat->sizeQ); + + if (!keyMat->derParams || !keyMat->bigD || !keyMat->derQ) + { + crypto_free_ecdsa(keyMat); + return NULL; + } + + memcpy(keyMat->derParams, &derEC[0], derEC.size()); + ecdsa->private_value().binary_encode((Botan::byte*)keyMat->bigD); + memcpy(keyMat->derQ, &derPoint[0], derPoint.size()); + + 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 |