From efaf4928aa3ff238f2038098e3f58201f5d07328 Mon Sep 17 00:00:00 2001 From: Aki Tuomi Date: Sun, 8 Mar 2015 20:35:41 +0200 Subject: [PATCH] Cleanup code and support multiple signing threads --- pdns/pkcs11signers.cc | 893 ++++++++++++++++++++---------------------- 1 file changed, 423 insertions(+), 470 deletions(-) diff --git a/pdns/pkcs11signers.cc b/pdns/pkcs11signers.cc index b23c57b9c..7c002d24e 100644 --- a/pdns/pkcs11signers.cc +++ b/pdns/pkcs11signers.cc @@ -7,6 +7,7 @@ #include #include // for 'operator+=()' #include +#include #include #include @@ -14,22 +15,20 @@ #include "pdns/logger.hh" #include "pdns/pdnsexception.hh" #include "pdns/sha.hh" -#include "pkcs11signers.hh" +#include "pdns/lock.hh" +#include "pkcs11signers.hh" /* TODO - list possible tokens and supported modes - Engine: , Slot: , PIN: - - fallback if not supported to polarssl (for hashing) - ECDSA support (how to test?) - - Physical token testing? - - module-slot locking (as they do not support parallel) NB! If you do use this, here is a simple way to get softhsm working create /etc/pkcs11/modules/softhsm.module -put +put module: /usr/lib/softhsm/libsofthsm.so managed: yes @@ -38,7 +37,9 @@ in it. you need to use softhsm tools to manage this all. */ - +#ifdef HAVE_P11KIT1_V2 +static CK_FUNCTION_LIST** p11_modules; +#endif // map for signing algorithms static std::map dnssec2smech = boost::assign::map_list_of @@ -58,17 +59,8 @@ static std::map dnssec2hmech = boost::assign::ma (13, CKM_SHA256) (14, CKM_SHA384); -// p11 handler for modules - -class P11KitModule; -class P11KitSlot; - typedef enum { Attribute_Byte, Attribute_Long, Attribute_String } CkaValueType; -#ifdef HAVE_P11KIT1_V2 -static CK_FUNCTION_LIST** p11_modules; -#endif - // Attribute handling class P11KitAttribute { private: @@ -206,410 +198,412 @@ public: }; }; -// representation of slot -class P11KitSlot { -private: - CK_SESSION_HANDLE d_session; - CK_SLOT_ID d_slot; - P11KitModule *d_module; - -public: - P11KitSlot(); - P11KitSlot(CK_SLOT_ID slot, P11KitModule *module); - P11KitSlot(const P11KitSlot& rhs); - ~P11KitSlot(); +class Pkcs11Token { + private: + CK_FUNCTION_LIST* f; // module functions + CK_SESSION_HANDLE d_session; + CK_SLOT_ID d_slot; + CK_OBJECT_HANDLE d_public_key; + CK_OBJECT_HANDLE d_private_key; + CK_KEY_TYPE d_key_type; + + CK_ULONG d_bits; + std::string d_exponent; + std::string d_modulus; + std::string d_ec_point; + std::string d_ecdsa_params; + + std::string d_label; + + CK_RV d_err; + bool d_logged_in; + pthread_mutex_t m; + + void logError(const std::string& operation) const { + if (d_err) { + L<C_Login(this->d_session, CKU_USER, uPin, pin.size()); + memset(uPin, 0, pin.size()); + delete [] uPin; + logError("C_Login"); + if (d_err == 0) { + d_logged_in = true; + LoadAttributes(); + } + return d_err; + } - CK_RV OpenSession(CK_FLAGS flags); - CK_RV CloseSession(); + bool LoggedIn() const { return d_logged_in; } - CK_RV GetInfo(CK_SLOT_INFO_PTR info) const; - CK_RV GetTokenInfo(CK_TOKEN_INFO_PTR info) const; + void LoadAttributes() { + std::vector attr; + std::vector key; - CK_RV Login(const std::string& pin, CK_USER_TYPE user); - CK_RV Logout(); + attr.push_back(P11KitAttribute(CKA_CLASS, (unsigned long)CKO_PRIVATE_KEY)); + attr.push_back(P11KitAttribute(CKA_SIGN, (char)CK_TRUE)); + attr.push_back(P11KitAttribute(CKA_LABEL, d_label)); + FindObjects2(attr, key, 1); + if (key.size() == 0) { + L<& pubAttributes, std::vector& privAttributes, CK_OBJECT_HANDLE_PTR pubKey, CK_OBJECT_HANDLE_PTR privKey); - CK_RV FindObjects(const std::vector& attributes, std::vector& objects, CK_ULONG maxobjects) const; - CK_RV SetAttributeValue(CK_OBJECT_HANDLE object, const std::vector& attributes); - CK_RV GetAttributeValue(CK_OBJECT_HANDLE object, std::vector& attributes) const; + int GenerateKeyPair(CK_MECHANISM_PTR mechanism, std::vector& pubAttributes, std::vector& privAttributes, CK_OBJECT_HANDLE_PTR pubKey, CK_OBJECT_HANDLE_PTR privKey) { + Lock l(&m); - CK_RV Sign(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key) const; - CK_RV Verify(const std::string& data, const std::string& result, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key) const; + size_t k; + CK_ATTRIBUTE_PTR pubAttr, privAttr; + pubAttr = new CK_ATTRIBUTE[pubAttributes.size()]; + privAttr = new CK_ATTRIBUTE[privAttributes.size()]; - CK_RV Digest(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism) const; + k = 0; + BOOST_FOREACH(P11KitAttribute& attribute, pubAttributes) { + attribute.rattr(pubAttr+k); + k++; + } - CK_RV DigestInit(CK_MECHANISM_PTR mechanism) const; - CK_RV DigestUpdate(const std::string& data) const; - CK_RV DigestUpdate(CK_OBJECT_HANDLE key) const; - CK_RV DigestFinal(std::string& result) const; -}; + k = 0; + BOOST_FOREACH(P11KitAttribute& attribute, privAttributes) { + attribute.rattr(privAttr+k); + k++; + } -// representation of module (or Engine) -class P11KitModule -{ - public: - std::string d_module; - CK_FUNCTION_LIST_PTR functions; + d_err = this->f->C_GenerateKeyPair(d_session, mechanism, pubAttr, pubAttributes.size(), privAttr, privAttributes.size(), pubKey, privKey); + logError("C_GenerateKeyPair"); + delete [] pubAttr; + delete [] privAttr; - P11KitModule() {} + if (d_err == 0) LoadAttributes(); - P11KitModule(const std::string& module) { - this->d_module = module; + return d_err; } - P11KitModule(const P11KitModule& rhs) { - functions = rhs.functions; - d_module = rhs.d_module; - } + int Sign(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism) { + Lock l(&m); - void setModule(const std::string& module) { - this->d_module = module; - }; + CK_BYTE buffer[1024]; + CK_ULONG buflen = sizeof buffer; // should be enough for most signatures. -// basically get the function list - bool initialize() { -#ifdef HAVE_P11KIT1_V2 - functions = p11_kit_module_for_name(p11_modules, d_module.c_str()); -#else - functions = p11_kit_registered_name_to_module(d_module.c_str()); -#endif - if (functions == NULL) return false; - return true; - }; + // perform signature + if ((d_err = this->f->C_SignInit(d_session, mechanism, d_private_key))) { logError("C_SignInit"); return d_err; } + d_err = this->f->C_Sign(d_session, (unsigned char*)data.c_str(), data.size(), buffer, &buflen); -// convenience method + checking that slot exists - bool GetSlot(CK_SLOT_ID slotId, P11KitSlot &slot) { - _CK_SLOT_INFO info; - if (this->functions->C_GetSlotInfo(slotId, &info)) { - return false; + if (!d_err) { + result.assign((char*)buffer, buflen); } - slot.SetSlot(slotId); - slot.SetModule(this); - return true; - }; -}; -P11KitSlot::P11KitSlot() { d_module = NULL; }; + memset(buffer,0,sizeof buffer); + logError("C_Sign"); + return d_err; + } -P11KitSlot::P11KitSlot(CK_SLOT_ID slot, P11KitModule *module) -{ - this->d_slot = slot; - this->d_module = module; -} + int Verify(const std::string& data, const std::string& signature, CK_MECHANISM_PTR mechanism) { + Lock l(&m); -P11KitSlot::P11KitSlot(const P11KitSlot &rhs) -{ - this->d_slot = rhs.d_slot; - this->d_module = rhs.d_module; - this->d_session = rhs.d_session; -} + if ((d_err = this->f->C_VerifyInit(d_session, mechanism, d_public_key))) { logError("C_VerifyInit"); return d_err; } + d_err = this->f->C_Verify(d_session, (unsigned char*)data.c_str(), data.size(), (unsigned char*)signature.c_str(), signature.size()); + logError("C_Verify"); + return d_err; + } -P11KitSlot::~P11KitSlot() -{ - if (this->d_module && this->d_session) - this->d_module->functions->C_CloseSession(this->d_session); -} + int Digest(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism) { + Lock l(&m); -// DO NOT CALL THIS ON YOUR OWN -void P11KitSlot::SetSlot(CK_SLOT_ID slot) { - this->d_slot = slot; -} + CK_BYTE buffer[1024]; + CK_ULONG buflen = sizeof buffer; // should be enough for most digests + if ((d_err = this->f->C_DigestInit(d_session, mechanism))) { logError("C_DigestInit"); return d_err; } + d_err = this->f->C_Digest(d_session, (unsigned char*)data.c_str(), data.size(), buffer, &buflen); + if (!d_err) { + result.assign((char*)buffer, buflen); + } + memset(buffer,0,sizeof buffer); + logError("C_Digest"); + return d_err; + } -// DO NOT CALL THIS ON YOUR OWN -void P11KitSlot::SetModule(P11KitModule *module) { - this->d_module = module; -} + int DigestInit(CK_MECHANISM_PTR mechanism) { + d_err = f->C_DigestInit(d_session, mechanism); + logError("C_DigestInit"); + return d_err; + } -// Create new session, mostly uses CKF_SERIAL_SESSION (which is mandatory flag) -// Another flag you can pass is CFK_RW_SESSION -CK_RV P11KitSlot::OpenSession(CK_FLAGS flags) -{ - if (!this->d_module) return 0xff; - return this->d_module->functions->C_OpenSession(this->d_slot, flags, 0, 0, &(this->d_session)); -} + int DigestUpdate(const std::string& data) { + d_err = f->C_DigestUpdate(d_session, (unsigned char*)data.c_str(), data.size()); + logError("C_DigestUpdate"); + return d_err; + } -CK_RV P11KitSlot::CloseSession() -{ - if (!this->d_module) return 0xff; - CK_RV rv = this->d_module->functions->C_CloseSession(this->d_session); - this->d_session = 0; - return rv; -} + int DigestKey(std::string& result) { + Lock l(&m); + CK_MECHANISM mech; + mech.mechanism = CKM_SHA_1; -CK_RV P11KitSlot::GetInfo(CK_SLOT_INFO_PTR info) const -{ - if (!this->d_module) return 0xff; - return this->d_module->functions->C_GetSlotInfo(this->d_slot, info); -} + DigestInit(&mech); -CK_RV P11KitSlot::GetTokenInfo(CK_TOKEN_INFO_PTR info) const -{ - if (!this->d_module) return 0xff; - return this->d_module->functions->C_GetTokenInfo(this->d_slot, info); -} + if (d_key_type == CKK_RSA) { + DigestUpdate(d_modulus); + DigestUpdate(d_exponent); + } else if (d_key_type == CKK_EC || d_key_type == CKK_ECDSA) { + DigestUpdate(d_ec_point); + } -CK_RV P11KitSlot::Login(const std::string& pin, CK_USER_TYPE user) -{ - if (!this->d_module) return 0xff; - CK_RV rv; - unsigned char *pPin; - pPin = new unsigned char[pin.size()]; - pin.copy(reinterpret_cast(pPin), pin.size()); - rv = this->d_module->functions->C_Login(this->d_session, user, pPin, pin.size()); - delete [] pPin; - return rv; -} + DigestFinal(result); -CK_RV P11KitSlot::Logout() -{ - if (!this->d_module) return 0xff; - return this->d_module->functions->C_Logout(this->d_slot); -} + return d_err; + } -CK_RV P11KitSlot::GenerateKeyPair(CK_MECHANISM_PTR mechanism, std::vector& pubAttributes, std::vector& privAttributes, CK_OBJECT_HANDLE_PTR pubKey, CK_OBJECT_HANDLE_PTR privKey) { - if (!this->d_module) return 0xff; + int DigestFinal(std::string& result) { + CK_BYTE buffer[1024] = {0}; + CK_ULONG buflen = sizeof buffer; // should be enough for most digests + d_err = f->C_DigestFinal(d_session, buffer, &buflen); + if (!d_err) { + result.assign((char*)buffer, buflen); + } + memset(buffer,0,sizeof buffer); + logError("C_DigestFinal"); + return d_err; + } - CK_RV rv; - size_t k; - CK_ATTRIBUTE_PTR pubAttr, privAttr; - pubAttr = new CK_ATTRIBUTE[pubAttributes.size()]; - privAttr = new CK_ATTRIBUTE[privAttributes.size()]; - - k = 0; - BOOST_FOREACH(P11KitAttribute& attribute, pubAttributes) { - attribute.rattr(pubAttr+k); - k++; - } + int FindObjects(const std::vector& attributes, std::vector& objects, int maxobjects) { + Lock l(&m); + return FindObjects2(attributes, objects, maxobjects); + } - k = 0; - BOOST_FOREACH(P11KitAttribute& attribute, privAttributes) { - attribute.rattr(privAttr+k); - k++; - } + int FindObjects2(const std::vector& attributes, std::vector& objects, int maxobjects) { + CK_RV rv; + size_t k; + unsigned long count; - rv = this->d_module->functions->C_GenerateKeyPair(d_session, mechanism, pubAttr, pubAttributes.size(), privAttr, privAttributes.size(), pubKey, privKey); + CK_ATTRIBUTE_PTR attr; + CK_OBJECT_HANDLE_PTR handles = new CK_OBJECT_HANDLE[maxobjects]; + attr = new CK_ATTRIBUTE[attributes.size()]; - delete [] pubAttr; - delete [] privAttr; + k = 0; + BOOST_FOREACH(const P11KitAttribute& attribute, attributes) { + attribute.rattr(attr+k); + k++; + } - return rv; -} + // perform search + d_err = this->f->C_FindObjectsInit(d_session, attr, k); -// Finds object(s) that match exactly to attributes -CK_RV P11KitSlot::FindObjects(const std::vector& attributes, std::vector& objects, unsigned long maxobjects) const -{ - if (!this->d_module) return 0xff; - CK_RV rv; - size_t k; - unsigned long count; - CK_ATTRIBUTE_PTR attr; - CK_OBJECT_HANDLE_PTR handles = new CK_OBJECT_HANDLE[maxobjects]; - attr = new CK_ATTRIBUTE[attributes.size()]; - - k = 0; - BOOST_FOREACH(const P11KitAttribute& attribute, attributes) { - attribute.rattr(attr+k); - k++; - } + if (d_err) { + delete [] attr; + delete [] handles; + logError("C_FindObjectsInit"); + return d_err; + } - // perform search - rv = this->d_module->functions->C_FindObjectsInit(d_session, attr, k); + count = maxobjects; + rv = d_err = this->f->C_FindObjects(d_session, handles, maxobjects, &count); + objects.clear(); - if (rv) { - delete [] attr; - delete [] handles; - return rv; - } + if (!rv) { + for(k=0;kd_module->functions->C_FindObjects(d_session, handles, maxobjects, &count); + d_err = this->f->C_FindObjectsFinal(d_session); + logError("C_FindObjectsFinal"); - if (!rv) { - objects.clear(); - for(k=0;k& attributes) + { + Lock l(&m); + return GetAttributeValue2(object, attributes); + } - this->d_module->functions->C_FindObjectsFinal(d_session); + int GetAttributeValue2(const CK_OBJECT_HANDLE& object, std::vector& attributes) + { + size_t k; + CK_ATTRIBUTE_PTR attr; + attr = new CK_ATTRIBUTE[attributes.size()]; - return rv; -}; + k = 0; + BOOST_FOREACH(P11KitAttribute &attribute, attributes) { + attribute.wattr(attr+k); + k++; + } -// TODO: Untested codepath -CK_RV P11KitSlot::SetAttributeValue(CK_OBJECT_HANDLE object, const std::vector& attributes) -{ - if (!this->d_module) return 0xff; - CK_RV rv; - size_t k; - CK_ATTRIBUTE_PTR attr; - attr = new CK_ATTRIBUTE[attributes.size()]; - - k = 0; - BOOST_FOREACH(const P11KitAttribute &attribute, attributes) { - attribute.rattr(attr+k); - k++; - } + // round 1 - get attribute sizes + d_err = f->C_GetAttributeValue(d_session, object, attr, attributes.size()); + logError("C_GetAttributeValue"); + if (d_err) { + delete [] attr; + return d_err; + } - rv = this->d_module->functions->C_SetAttributeValue(d_session, object, attr, attributes.size()); + // then allocate memory + for(size_t k=0; k < attributes.size(); k++) { + if (attributes[k].valueType() == Attribute_String) { + attr[k].pValue = attributes[k].allocate(attr[k].ulValueLen); + } + } - delete [] attr; - return rv; -} + // round 2 - get actual values + d_err = f->C_GetAttributeValue(d_session, object, attr, attributes.size()); + logError("C_GetAttributeValue"); -CK_RV P11KitSlot::GetAttributeValue(CK_OBJECT_HANDLE object, std::vector& attributes) const -{ - if (!this->d_module) return 0xff; - CK_RV rv; - size_t k; - CK_ATTRIBUTE_PTR attr; - attr = new CK_ATTRIBUTE[attributes.size()]; - - k = 0; - BOOST_FOREACH(P11KitAttribute &attribute, attributes) { - attribute.wattr(attr+k); - k++; - } + // copy values to map and release allocated memory + for(size_t k=0; k < attributes.size(); k++) { + if (attributes[k].valueType() == Attribute_String) { + attributes[k].commit(attr[k].ulValueLen); + } + } - // round 1 - get attribute sizes - rv = this->d_module->functions->C_GetAttributeValue(d_session, object, attr, attributes.size()); + delete [] attr; - if (rv) { - delete [] attr; - return rv; - } + return d_err; + }; - // then allocate memory - for(size_t k=0; k < attributes.size(); k++) { - if (attributes[k].valueType() == Attribute_String) { - attr[k].pValue = attributes[k].allocate(attr[k].ulValueLen); + const std::string& Modulus() { + return d_modulus; } - } - // round 2 - get actual values - rv = this->d_module->functions->C_GetAttributeValue(d_session, object, attr, attributes.size()); + const std::string& Exponent() { + return d_exponent; + } - // copy values to map and release allocated memory - for(size_t k=0; k < attributes.size(); k++) { - if (attributes[k].valueType() == Attribute_String) { - attributes[k].commit(attr[k].ulValueLen); + const std::string& ECPoint() { + return d_ec_point; } - } - delete [] attr; + const std::string& ECParameters() { + return d_ecdsa_params; + } - return rv; -}; + CK_KEY_TYPE KeyType() { + return d_key_type; + } -CK_RV P11KitSlot::Sign(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key) const -{ - if (!this->d_module) return 0xff; - CK_RV rv; - CK_BYTE buffer[1024]; - CK_ULONG buflen = sizeof buffer; // should be enough for most signatures. - - // perform signature - if ((rv = this->d_module->functions->C_SignInit(d_session, mechanism, key))) return rv; // well that failed. - rv = this->d_module->functions->C_Sign(d_session, (unsigned char*)data.c_str(), data.size(), buffer, &buflen); - if (!rv) { - result.assign((char*)buffer, buflen); - } - memset(buffer,0,sizeof buffer); + CK_ULONG Bits() { + return d_bits; + } - return rv; + static boost::shared_ptr GetToken(const std::string& module, const CK_SLOT_ID& slotId, const std::string& label); }; -CK_RV P11KitSlot::Verify(const std::string& data, const std::string& signature, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key) const -{ - if (!this->d_module) return 0xff; - CK_RV rv; - if ((rv = this->d_module->functions->C_VerifyInit(d_session, mechanism, key))) return rv; - rv = this->d_module->functions->C_Verify(d_session, (unsigned char*)data.c_str(), data.size(), (unsigned char*)signature.c_str(), signature.size()); - return rv; -}; +static std::map > pkcs11_tokens; -CK_RV P11KitSlot::Digest(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism) const -{ - if (!this->d_module) return 0xff; - CK_RV rv; - CK_BYTE buffer[1024]; - CK_ULONG buflen = sizeof buffer; // should be enough for most digests - if ((rv = this->d_module->functions->C_DigestInit(d_session, mechanism))) return rv; - rv = this->d_module->functions->C_Digest(d_session, (unsigned char*)data.c_str(), data.size(), buffer, &buflen); - if (!rv) { - result.assign((char*)buffer, buflen); - } - memset(buffer,0,sizeof buffer); +boost::shared_ptr Pkcs11Token::GetToken(const std::string& module, const CK_SLOT_ID& slotId, const std::string& label) { + // see if we can find module + std::string idx = module; + idx.append("|"); + idx.append(boost::lexical_cast(slotId)); + std::map >::iterator tokenIter; + CK_FUNCTION_LIST* functions; - return rv; -}; + if ((tokenIter = pkcs11_tokens.find(idx)) != pkcs11_tokens.end()) return tokenIter->second; -CK_RV P11KitSlot::DigestInit(CK_MECHANISM_PTR mechanism) const -{ - if (!this->d_module) return 0xff; - return this->d_module->functions->C_DigestInit(d_session, mechanism); -} +#ifdef HAVE_P11KIT1_V2 + functions = p11_kit_module_for_name(p11_modules, module.c_str()); +#else + functions = p11_kit_registered_name_to_module(module.c_str()); +#endif + if (functions == NULL) throw PDNSException("Cannot find PKCS#11 module " + module); + functions->C_Initialize(NULL); // initialize the module in case it hasn't been done yet. -CK_RV P11KitSlot::DigestUpdate(const std::string& data) const -{ - if (!this->d_module) return 0xff; - return this->d_module->functions->C_DigestUpdate(d_session, (unsigned char*)data.c_str(), data.size()); -} + // try to locate a slot + _CK_SLOT_INFO info; + if (functions->C_GetSlotInfo(slotId, &info)) { + throw PDNSException(std::string("Cannot find PKCS#11 slot ") + boost::lexical_cast(slotId) + std::string(" on module ") + module); + } -CK_RV P11KitSlot::DigestUpdate(CK_OBJECT_HANDLE key) const -{ - if (!this->d_module) return 0xff; - return this->d_module->functions->C_DigestKey(d_session, key); -} + // looks ok to me. + pkcs11_tokens[idx] = boost::make_shared(slotId, label, functions); -CK_RV P11KitSlot::DigestFinal(std::string& result) const -{ - if (!this->d_module) return 0xff; - CK_RV rv; - CK_BYTE buffer[1024]; - CK_ULONG buflen = sizeof buffer; // should be enough for most digests - rv = this->d_module->functions->C_DigestFinal(d_session, buffer, &buflen); - if (!rv) { - result.assign((char*)buffer, buflen); - } - memset(buffer,0,sizeof buffer); - return rv; + return pkcs11_tokens[idx]; } -// map between engine names and engines -static std::map pkcs11_engines; -// map between engine names and slots (not used now) -//static std::map pkcs11_slots; - -static bool pkcs11_GetSlot(const std::string& engine, CK_SLOT_ID slotId, const std::string& pin, CK_FLAGS flags, P11KitSlot& slot) -{ - CK_RV rv; - if (engine.empty()) return false; +Pkcs11Token::Pkcs11Token(const CK_SLOT_ID& slotId, const std::string& label, CK_FUNCTION_LIST* functions) { + // open a session + int err; + this->d_bits = 0; + this->d_slot = slotId; + this->d_label = label; + this->d_err = 0; + this->f = functions; + this->d_logged_in = false; + this->d_session = 0; + this->m = PTHREAD_MUTEX_INITIALIZER; + Lock l(&m); - // open module if necessary - if (pkcs11_engines.find(engine) == pkcs11_engines.end()) { - P11KitModule module(engine); - if (module.initialize() == false) { - throw PDNSException("Cannot initialize or unknown PKCS#11 engine " + engine); - } - pkcs11_engines[engine] = module; + if ((err = f->C_OpenSession(this->d_slot, CKF_SERIAL_SESSION|CKF_RW_SESSION, 0, 0, &(this->d_session)))) { + throw PDNSException(std::string("Could not open session: ") + boost::lexical_cast(err)); } - pkcs11_engines[engine].GetSlot(slotId, slot); - rv = slot.OpenSession(flags); - if (rv) { - return false; - }; - rv = slot.Login(pin, CKU_USER); - if (rv) { - L< d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin)) + throw PDNSException("Not logged in to token"); + std::string pubExp("\000\001\000\001", 4); // 65537 - + pubAttr.push_back(P11KitAttribute(CKA_CLASS, (unsigned long)CKO_PUBLIC_KEY)); pubAttr.push_back(P11KitAttribute(CKA_KEY_TYPE, (unsigned long)CKK_RSA)); pubAttr.push_back(P11KitAttribute(CKA_TOKEN, (char)CK_TRUE)); @@ -633,7 +631,7 @@ void PKCS11DNSCryptoKeyEngine::create(unsigned int bits) { pubAttr.push_back(P11KitAttribute(CKA_VERIFY, (char)CK_TRUE)); pubAttr.push_back(P11KitAttribute(CKA_WRAP, (char)CK_TRUE)); pubAttr.push_back(P11KitAttribute(CKA_MODULUS_BITS, (unsigned long)bits)); - pubAttr.push_back(P11KitAttribute(CKA_PUBLIC_EXPONENT, pubExp)); + pubAttr.push_back(P11KitAttribute(CKA_PUBLIC_EXPONENT, pubExp)); pubAttr.push_back(P11KitAttribute(CKA_LABEL, d_label)); privAttr.push_back(P11KitAttribute(CKA_CLASS, (unsigned long)CKO_PRIVATE_KEY)); @@ -652,31 +650,24 @@ void PKCS11DNSCryptoKeyEngine::create(unsigned int bits) { mech.pParameter = NULL; mech.ulParameterLen = 0; - if ((rv = d_slot.GenerateKeyPair(&mech, pubAttr, privAttr, &pubKey, &privKey))) { - std::ostringstream error; - error << "Keypair generation failed with " << rv; - throw PDNSException(error.str()); + if ((rv = d_slot->GenerateKeyPair(&mech, pubAttr, privAttr, &pubKey, &privKey))) { + throw PDNSException("Keypair generation failed"); } }; -std::string PKCS11DNSCryptoKeyEngine::sign(const std::string& msg) const { +std::string PKCS11DNSCryptoKeyEngine::sign(const std::string& msg) const { std::string result; - std::vector key; - std::vector attr; - P11KitSlot d_slot; - pkcs11_GetSlot(d_engine, d_slot_id, d_pin, CKF_SERIAL_SESSION, d_slot); - // find key that can be used for signing - attr.push_back(P11KitAttribute(CKA_SIGN, (char)CK_TRUE)); - attr.push_back(P11KitAttribute(CKA_LABEL, d_label)); - d_slot.FindObjects(attr, key, 1); - // hopefully we have a key - if (key.size() == 0) return ""; - // choose mech + boost::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin)) + throw PDNSException("Not logged in to token"); + CK_MECHANISM mech; mech.mechanism = dnssec2smech[d_algorithm]; mech.pParameter = NULL; mech.ulParameterLen = 0; - d_slot.Sign(msg, result, &mech, key[0]); + if (d_slot->Sign(msg, result, &mech)) throw PDNSException("Could not sign data"); return result; }; @@ -686,10 +677,13 @@ std::string PKCS11DNSCryptoKeyEngine::hash(const std::string& msg) const { mech.mechanism = dnssec2hmech[d_algorithm]; mech.pParameter = NULL; mech.ulParameterLen = 0; - P11KitSlot d_slot; - pkcs11_GetSlot(d_engine, d_slot_id, d_pin, CKF_SERIAL_SESSION, d_slot); + boost::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin)) + throw PDNSException("Not logged in to token"); - if (d_slot.Digest(msg, result, &mech)) { + if (d_slot->Digest(msg, result, &mech)) { // FINE! I'll do this myself, then, shall I? switch(d_algorithm) { case 5: { @@ -723,116 +717,75 @@ std::string PKCS11DNSCryptoKeyEngine::hash(const std::string& msg) const { }; bool PKCS11DNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const { - bool result; - std::vector key; - std::vector attr; - // find a key that can be used to verify signatures - attr.push_back(P11KitAttribute(CKA_VERIFY, (char)CK_TRUE)); - attr.push_back(P11KitAttribute(CKA_LABEL, d_label)); - P11KitSlot d_slot; - pkcs11_GetSlot(d_engine, d_slot_id, d_pin, CKF_SERIAL_SESSION, d_slot); - - d_slot.FindObjects(attr, key, 1); - // hopefully we have a key - if (key.size() == 0) return ""; - // choose mech + boost::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin)) + throw PDNSException("Not logged in to token"); + CK_MECHANISM mech; mech.mechanism = dnssec2smech[d_algorithm]; mech.pParameter = NULL; mech.ulParameterLen = 0; - result = d_slot.Verify(msg, signature, &mech, key[0]); - return result; + return (d_slot->Verify(msg, signature, &mech) == 0); }; -std::string PKCS11DNSCryptoKeyEngine::getPubKeyHash() const { - std::string result = ""; - std::vector key; - std::vector attr; +std::string PKCS11DNSCryptoKeyEngine::getPubKeyHash() const { // find us a public key - attr.push_back(P11KitAttribute(CKA_CLASS, CKO_PUBLIC_KEY)); - attr.push_back(P11KitAttribute(CKA_LABEL, d_label)); - P11KitSlot d_slot; - pkcs11_GetSlot(d_engine, d_slot_id, d_pin, CKF_SERIAL_SESSION, d_slot); - - d_slot.FindObjects(attr, key, 1); - if (key.size() > 0) { - attr.clear(); - attr.push_back(P11KitAttribute(CKA_MODULUS, "")); - attr.push_back(P11KitAttribute(CKA_PUBLIC_EXPONENT, "")); - if (d_slot.GetAttributeValue(key[0], attr) == 0) { - CK_MECHANISM mech; - mech.mechanism = CKM_SHA_1; - d_slot.DigestInit(&mech); - d_slot.DigestUpdate(attr[0].str()); - d_slot.DigestUpdate(attr[1].str()); - d_slot.DigestFinal(result); - } - } - return result; + boost::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin)) + throw PDNSException("Not logged in to token"); + + std::string result; + if (d_slot->DigestKey(result) == 0) return result; + return ""; }; std::string PKCS11DNSCryptoKeyEngine::getPublicKeyString() const { std::string result(""); - std::vector key; - std::vector attr; - attr.push_back(P11KitAttribute(CKA_LABEL, d_label)); - P11KitSlot d_slot; - pkcs11_GetSlot(d_engine, d_slot_id, d_pin, CKF_SERIAL_SESSION, d_slot); - - d_slot.FindObjects(attr, key, 1); - if (key.size() > 0) { - attr.clear(); - attr.push_back(P11KitAttribute(CKA_MODULUS, "")); - attr.push_back(P11KitAttribute(CKA_PUBLIC_EXPONENT, "")); - if (d_slot.GetAttributeValue(key[0], attr) == 0) { - if(attr[1].str().length() < 255) - result.assign(1, (char) (unsigned int) attr[1].str().length()); - else { - result.assign(1, 0); - uint16_t len=htons(attr[1].str().length()); - result.append((char*)&len, 2); - } - result.append(attr[1].str()); - result.append(attr[0].str()); - } -// } else { -// std::cerr << "Could not find key" << std::endl; - } - return result; + boost::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin)) + throw PDNSException("Not logged in to token"); + + if (d_slot->KeyType() == CKK_RSA) { + if (d_slot->Exponent().length() < 255) { + result.assign(1, (char) (unsigned int) d_slot->Exponent().length()); + } else { + result.assign(1, 0); + uint16_t len=htons(d_slot->Exponent().length()); + result.append((char*)&len, 2); + } + result.append(d_slot->Exponent()); + result.append(d_slot->Modulus()); + } else { + result.append(d_slot->ECPoint()); + } + return result; }; int PKCS11DNSCryptoKeyEngine::getBits() const { int bits = -1; - std::vector key; - std::vector attr; - attr.push_back(P11KitAttribute(CKA_CLASS, CKO_PUBLIC_KEY)); - attr.push_back(P11KitAttribute(CKA_LABEL, d_label)); - P11KitSlot d_slot; - pkcs11_GetSlot(d_engine, d_slot_id, d_pin, CKF_SERIAL_SESSION, d_slot); - -// std::cerr << "Looking for " << d_label << " from " << d_slot_id << std::endl; - - d_slot.FindObjects(attr, key, 1); - if (key.size() > 0) { - attr.clear(); - attr.push_back(P11KitAttribute(CKA_MODULUS_BITS, 0UL)); - if (d_slot.GetAttributeValue(key[0], attr) == 0) { - bits = static_cast(attr[0].ulong()); - } -// } else { -// std::cerr << "Could not find key" << std::endl; - } - return bits; + boost::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin)) + throw PDNSException("Not logged in to token"); + + return d_slot->Bits(); }; -DNSCryptoKeyEngine::storvector_t PKCS11DNSCryptoKeyEngine::convertToISCVector() const { +DNSCryptoKeyEngine::storvector_t PKCS11DNSCryptoKeyEngine::convertToISCVector() const { storvector_t storvect; typedef std::vector > outputs_t; outputs_t outputs; boost::assign::push_back(storvect) (make_pair("Algorithm", boost::lexical_cast(d_algorithm))) - (make_pair("Engine", d_engine)) + (make_pair("Engine", d_module)) (make_pair("Slot", boost::lexical_cast(d_slot_id))) (make_pair("PIN", d_pin)) (make_pair("Label", d_label)); @@ -846,22 +799,22 @@ DNSCryptoKeyEngine* PKCS11DNSCryptoKeyEngine::maker(unsigned int algorithm) // this is called during program startup namespace { -struct LoaderStruct -{ - LoaderStruct() + static struct LoaderStruct { + LoaderStruct() + { #ifdef HAVE_P11KIT1_V2 - p11_modules = p11_kit_modules_load_and_initialize(0); + p11_modules = p11_kit_modules_load_and_initialize(0); #else - p11_kit_initialize_registered(); + p11_kit_initialize_registered(); #endif - }; - ~LoaderStruct() { + }; + ~LoaderStruct() { #ifdef HAVE_P11KIT1_V2 - p11_kit_modules_release(p11_modules); + p11_kit_modules_release(p11_modules); #else - p11_kit_finalize_registered(); + p11_kit_finalize_registered(); #endif - }; -} loaderPkcs11; + }; + } loaderPkcs11; } -- 2.49.0