]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/pkcs11signers.cc
pkcs11signers: Use emplace_back for attributes
[thirdparty/pdns.git] / pdns / pkcs11signers.cc
CommitLineData
6516cf63 1#include <openssl/evp.h>
870a0fe4
AT
2#ifdef HAVE_CONFIG_H
3#include "config.h"
4#endif
8daea594
AT
5#include <boost/assign/std/vector.hpp> // for 'operator+=()'
6#include <boost/assign/list_of.hpp>
fa8fd4d2 7
a1d465f3 8#include <boost/format.hpp>
8daea594
AT
9#include <p11-kit/p11-kit.h>
10
887b696b
RK
11#include "pdns/dnssecinfra.hh"
12#include "pdns/logger.hh"
13#include "pdns/pdnsexception.hh"
14#include "pdns/sha.hh"
efaf4928 15#include "pdns/lock.hh"
8daea594 16
357468bc 17#ifdef HAVE_LIBCRYPTO_ECDSA
fb46af61 18#include <openssl/bn.h>
357468bc
AT
19#include <openssl/ec.h>
20#endif
21
1dec433d 22#include "misc.hh"
efaf4928 23#include "pkcs11signers.hh"
8daea594
AT
24/* TODO
25
26 - list possible tokens and supported modes
27 - Engine: <name>, Slot: <slot>, PIN: <pin>
8daea594 28 - ECDSA support (how to test?)
8daea594
AT
29
30NB! If you do use this, here is a simple way to get softhsm working
31
32create /etc/pkcs11/modules/softhsm.module
33
efaf4928 34put
8daea594
AT
35
36module: /usr/lib/softhsm/libsofthsm.so
37managed: yes
38
39in it. you need to use softhsm tools to manage this all.
40
41*/
42
efaf4928
AT
43#ifdef HAVE_P11KIT1_V2
44static CK_FUNCTION_LIST** p11_modules;
45#endif
8daea594 46
1dec433d
FM
47static constexpr const char* ECDSA256_PARAMS{"\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07"};
48static constexpr const char* ECDSA384_PARAMS{"\x06\x05\x2b\x81\x04\x00\x22"};
73db7e76 49
8daea594
AT
50// map for signing algorithms
51static std::map<unsigned int,CK_MECHANISM_TYPE> dnssec2smech = boost::assign::map_list_of
52(5, CKM_SHA1_RSA_PKCS)
53(7, CKM_SHA1_RSA_PKCS)
54(8, CKM_SHA256_RSA_PKCS)
55(10, CKM_SHA512_RSA_PKCS)
56(13, CKM_ECDSA)
57(14, CKM_ECDSA);
58
59// map for hashing algorithms
60static std::map<unsigned int,CK_MECHANISM_TYPE> dnssec2hmech = boost::assign::map_list_of
61(5, CKM_SHA_1)
62(7, CKM_SHA_1)
63(8, CKM_SHA256)
64(10, CKM_SHA512)
65(13, CKM_SHA256)
66(14, CKM_SHA384);
67
7e520f03
PD
68static std::map<unsigned int,CK_MECHANISM_TYPE> dnssec2cmech = boost::assign::map_list_of
69(5, CKM_RSA_PKCS_KEY_PAIR_GEN)
70(7, CKM_RSA_PKCS_KEY_PAIR_GEN)
71(8, CKM_RSA_PKCS_KEY_PAIR_GEN)
72(10, CKM_RSA_PKCS_KEY_PAIR_GEN)
73(13, CKM_ECDSA_KEY_PAIR_GEN)
74(14, CKM_ECDSA_KEY_PAIR_GEN);
75
1dec433d 76using CkaValueType = enum { Attribute_Byte, Attribute_Long, Attribute_String };
8daea594
AT
77
78// Attribute handling
79class P11KitAttribute {
80private:
81 CK_ATTRIBUTE_TYPE type;
82 CK_BYTE ckByte;
83 CK_ULONG ckLong;
84 std::string ckString;
85 CkaValueType ckType;
c2826d2e 86 std::unique_ptr<unsigned char[]> buffer;
8daea594
AT
87 CK_ULONG buflen;
88protected:
89 void Init() {
8daea594
AT
90 buflen = 0;
91 };
92public:
2010ac95 93 P11KitAttribute(CK_ATTRIBUTE_TYPE type_, const std::string& value) {
8daea594 94 Init();
2010ac95 95 this->type = type_;
8daea594
AT
96 setString(value);
97 }
98
2010ac95 99 P11KitAttribute(CK_ATTRIBUTE_TYPE type_, char value) {
8daea594 100 Init();
2010ac95 101 this->type = type_;
8daea594
AT
102 setByte(value);
103 }
104
2010ac95 105 P11KitAttribute(CK_ATTRIBUTE_TYPE type_, unsigned char value) {
8daea594 106 Init();
2010ac95 107 this->type = type_;
8daea594
AT
108 setByte(value);
109 }
110
2010ac95 111 P11KitAttribute(CK_ATTRIBUTE_TYPE type_, unsigned long value) {
8daea594 112 Init();
2010ac95 113 this->type = type_;
8daea594
AT
114 setLong(value);
115 }
116
1dec433d 117 [[nodiscard]] CkaValueType valueType() const {
8daea594
AT
118 return ckType;
119 }
120
1dec433d 121 [[nodiscard]] const std::string &str() const {
8daea594
AT
122 return ckString;
123 };
124
1dec433d 125 [[nodiscard]] unsigned char byte() const {
8daea594
AT
126 return ckByte;
127 }
128
1dec433d 129 [[nodiscard]] unsigned long ulong() const {
8daea594
AT
130 return ckLong;
131 }
132
133 void setString(const std::string& value) {
134 this->ckString = value;
135 this->ckType = Attribute_String;
136 }
137
138 void setByte(char value) {
139 this->ckByte = value;
140 this->ckType = Attribute_Byte;
141 }
142
143 void setByte(unsigned char value) {
144 this->ckByte = value;
145 this->ckType = Attribute_Byte;
146 }
147
148 void setLong(unsigned long value) {
149 this->ckLong = value;
150 this->ckType = Attribute_Long;
151 }
152
153// this bit is used for getting attribute from object
154// we provide a pointer for GetAttributeValue to write to
155 CK_BYTE_PTR allocate(CK_ULONG amount) {
2bbc9eb0 156 buffer = std::make_unique<unsigned char[]>(amount);
8daea594 157 buflen = amount;
c2826d2e 158 return buffer.get();
8daea594
AT
159 }
160
161// and here we copy the results back and delete buffer
162 void commit(CK_ULONG amount) {
163 if (buffer) {
c2826d2e 164 this->ckString.assign((char*)buffer.get(), amount);
8daea594 165 }
c2826d2e 166 buffer.reset();
8daea594
AT
167 buflen = 0;
168 }
169
170// this is *writable* attribute (you write into it)
171 void wattr(CK_ATTRIBUTE_PTR attr) {
172 attr->type = type;
173 switch(ckType) {
174 case Attribute_Byte: {
175 attr->pValue = (void*)&ckByte;
176 attr->ulValueLen = 1;
177 break;
178 }
179 case Attribute_Long: {
180 attr->pValue = (void*)&ckLong;
181 attr->ulValueLen = sizeof(CK_ULONG);
182 break;
183 }
184 case Attribute_String: {
c2826d2e 185 attr->pValue = buffer.get();
8daea594
AT
186 attr->ulValueLen = buflen;
187 }
188 };
189 };
190
191// this is *readable* attribute (you read from it)
192 void rattr(CK_ATTRIBUTE_PTR attr) const {
193 attr->type = type;
194 switch(ckType) {
195 case Attribute_Byte: {
196 attr->pValue = (void*)&ckByte;
197 attr->ulValueLen = 1;
198 break;
199 }
200 case Attribute_Long: {
201 attr->pValue = (void*)&ckLong;
202 attr->ulValueLen = sizeof(CK_ULONG);
203 break;
204 }
205 case Attribute_String: {
206 attr->pValue = (void*)ckString.c_str();
207 attr->ulValueLen = ckString.size();
208 }
209 };
210 };
211};
212
8daea594 213
85e7248d 214class Pkcs11Slot {
efaf4928 215 private:
1dec433d 216 bool d_logged_in{};
85e7248d 217 CK_FUNCTION_LIST* d_functions; // module functions
efaf4928
AT
218 CK_SESSION_HANDLE d_session;
219 CK_SLOT_ID d_slot;
1dec433d 220 CK_RV d_err{};
8daea594 221
85e7248d
AT
222 void logError(const std::string& operation) const {
223 if (d_err) {
7e520f03 224 std::string msg = boost::str( boost::format("PKCS#11 operation %s failed: %s (0x%X) (%s)") % operation % p11_kit_strerror(d_err) % d_err % p11_kit_message() );
e6a9dde5 225 g_log<<Logger::Error<< msg << endl;
85e7248d
AT
226 }
227 }
248d701f 228
85e7248d 229 public:
1dec433d
FM
230 Pkcs11Slot(CK_FUNCTION_LIST* functions, const CK_SLOT_ID& slot) :
231 d_logged_in(false),
232 d_functions(functions),
233 d_slot(slot),
234 d_err(0)
235 {
85e7248d 236 CK_TOKEN_INFO tokenInfo;
85e7248d
AT
237
238 if ((d_err = d_functions->C_OpenSession(this->d_slot, CKF_SERIAL_SESSION|CKF_RW_SESSION, 0, 0, &(this->d_session)))) {
239 logError("C_OpenSession");
240 throw PDNSException("Could not open session");
241 }
242 // check if we need to login
243 if ((d_err = d_functions->C_GetTokenInfo(d_slot, &tokenInfo)) == 0) {
ecb8dc68 244 d_logged_in = !((tokenInfo.flags & CKF_LOGIN_REQUIRED) == CKF_LOGIN_REQUIRED);
85e7248d
AT
245 } else {
246 logError("C_GetTokenInfo");
335da0ba 247 throw PDNSException("Cannot get token info for slot " + std::to_string(slot));
85e7248d
AT
248 }
249 }
8daea594 250
85e7248d
AT
251 bool Login(const std::string& pin) {
252 if (d_logged_in) return true;
8daea594 253
2bbc9eb0 254 auto uPin = std::make_unique<unsigned char[]>(pin.size());
c2826d2e
RG
255 memcpy(uPin.get(), pin.c_str(), pin.size());
256 d_err = d_functions->C_Login(this->d_session, CKU_USER, uPin.get(), pin.size());
257 memset(uPin.get(), 0, pin.size());
85e7248d 258 logError("C_Login");
8daea594 259
85e7248d
AT
260 if (d_err == 0) {
261 d_logged_in = true;
262 }
8daea594 263
85e7248d
AT
264 return d_logged_in;
265 }
8daea594 266
85e7248d 267 bool LoggedIn() const { return d_logged_in; }
8daea594 268
85e7248d 269 CK_SESSION_HANDLE& Session() { return d_session; }
8daea594 270
85e7248d
AT
271 CK_FUNCTION_LIST* f() { return d_functions; }
272
87f56f3f 273 static std::shared_ptr<LockGuarded<Pkcs11Slot>> GetSlot(const std::string& module, const string& tokenId);
248d701f 274 static CK_RV HuntSlot(const string& tokenId, CK_SLOT_ID &slotId, _CK_SLOT_INFO* info, CK_FUNCTION_LIST* functions);
8daea594
AT
275};
276
85e7248d
AT
277class Pkcs11Token {
278 private:
87f56f3f 279 std::shared_ptr<LockGuarded<Pkcs11Slot>> d_slot;
85e7248d 280
efaf4928
AT
281 CK_OBJECT_HANDLE d_public_key;
282 CK_OBJECT_HANDLE d_private_key;
283 CK_KEY_TYPE d_key_type;
284
285 CK_ULONG d_bits;
286 std::string d_exponent;
287 std::string d_modulus;
288 std::string d_ec_point;
289 std::string d_ecdsa_params;
290
291 std::string d_label;
9ee32859
AT
292 std::string d_pub_label;
293
24e0b305 294 bool d_loaded;
efaf4928 295 CK_RV d_err;
efaf4928
AT
296
297 void logError(const std::string& operation) const {
298 if (d_err) {
7e520f03 299 std::string msg = boost::str( boost::format("PKCS#11 operation %s failed: %s (0x%X) (%s)") % operation % p11_kit_strerror(d_err) % d_err % p11_kit_message());
e6a9dde5 300 g_log<<Logger::Error<< msg << endl;
efaf4928 301 }
a1d465f3 302 }
8daea594 303
1dec433d 304 [[nodiscard]] unsigned int ecparam2bits(const std::string& obj) const {
357468bc
AT
305 // if we can use some library to parse the EC parameters, better use it.
306 // otherwise fall back to using hardcoded primev256 and secp384r1
307#ifdef HAVE_LIBCRYPTO_ECDSA
6516cf63
FM
308#if OPENSSL_VERSION_MAJOR >= 3
309 using Key = std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>;
310#else
1dec433d
FM
311 using Key = std::unique_ptr<EC_KEY, decltype(&EC_KEY_free)>;
312 using BigNum = std::unique_ptr<BIGNUM, decltype(&BN_clear_free)>;
6516cf63 313#endif
1dec433d 314
357468bc 315 unsigned int bits = 0;
1dec433d
FM
316
317 // NOLINTNEXTLINE(*-cast): Using OpenSSL C APIs.
318 const auto* objCStr = reinterpret_cast<const unsigned char*>(obj.c_str());
6516cf63
FM
319#if OPENSSL_VERSION_MAJOR >= 3
320 auto key = Key(d2i_KeyParams(EVP_PKEY_EC, nullptr, &objCStr, static_cast<long>(obj.size())), EVP_PKEY_free);
321#else
1dec433d 322 auto key = Key(d2i_ECParameters(nullptr, &objCStr, static_cast<long>(obj.size())), EC_KEY_free);
6516cf63 323#endif
1dec433d
FM
324 if (key == nullptr) {
325 throw pdns::OpenSSL::error("PKCS11", "Cannot parse EC parameters from DER");
357468bc
AT
326 }
327
6516cf63
FM
328#if OPENSSL_VERSION_MAJOR >= 3
329 bits = EVP_PKEY_get_bits(key.get());
330#else
1dec433d
FM
331 const auto* group = EC_KEY_get0_group(key.get());
332 auto order = BigNum(BN_new(), BN_clear_free);
333 if (EC_GROUP_get_order(group, order.get(), nullptr) == 1) {
334 bits = BN_num_bits(order.get());
335 }
6516cf63 336#endif
1dec433d
FM
337
338 if (bits == 0) {
357468bc 339 throw PDNSException("Unsupported EC key");
1dec433d 340 }
357468bc
AT
341
342 return bits;
343#else
73db7e76
PD
344 if (d_ecdsa_params == ECDSA256_PARAMS) return 256;
345 else if (d_ecdsa_params == ECDSA384_PARAMS) return 384;
357468bc
AT
346 else throw PDNSException("Unsupported EC key");
347#endif
348 }
349
8daea594 350 public:
a0383aad 351 Pkcs11Token(const std::shared_ptr<LockGuarded<Pkcs11Slot>>& slot, const std::string& label, const std::string& pub_label);
efaf4928
AT
352 ~Pkcs11Token();
353
85e7248d 354 bool Login(const std::string& pin) {
24e0b305 355 if (pin.empty()) return false; // no empty pin.
87f56f3f 356 if (d_slot->lock()->Login(pin) == true) {
efaf4928
AT
357 LoadAttributes();
358 }
8daea594 359
85e7248d 360 return LoggedIn();
8daea594
AT
361 }
362
24e0b305 363 bool LoggedIn() {
87f56f3f 364 if (d_loaded == false && d_slot->lock()->LoggedIn() == true) {
24e0b305
AT
365 LoadAttributes();
366 }
87f56f3f 367 return d_slot->lock()->LoggedIn();
24e0b305 368 }
8daea594 369
efaf4928 370 void LoadAttributes() {
87f56f3f 371 auto slot = d_slot->lock();
efaf4928
AT
372 std::vector<P11KitAttribute> attr;
373 std::vector<CK_OBJECT_HANDLE> key;
990102db
AT
374 attr.emplace_back(CKA_CLASS, (unsigned long)CKO_PRIVATE_KEY);
375 attr.emplace_back(CKA_LABEL, d_label);
87f56f3f 376 FindObjects2(*slot, attr, key, 1);
efaf4928 377 if (key.size() == 0) {
890add84 378 g_log<<Logger::Warning<<"Cannot load PKCS#11 private key "<<d_label<<std::endl;;
efaf4928
AT
379 return;
380 }
381 d_private_key = key[0];
382 attr.clear();
990102db
AT
383 attr.emplace_back(CKA_CLASS, (unsigned long)CKO_PUBLIC_KEY);
384 attr.emplace_back(CKA_LABEL, d_pub_label);
87f56f3f 385 FindObjects2(*slot, attr, key, 1);
efaf4928 386 if (key.size() == 0) {
890add84 387 g_log<<Logger::Warning<<"Cannot load PKCS#11 public key "<<d_pub_label<<std::endl;
efaf4928
AT
388 return;
389 }
390 d_public_key = key[0];
391
392 attr.clear();
990102db 393 attr.emplace_back(CKA_KEY_TYPE, 0UL);
efaf4928 394
87f56f3f 395 if (GetAttributeValue2(*slot, d_public_key, attr)==0) {
efaf4928
AT
396 d_key_type = attr[0].ulong();
397 if (d_key_type == CKK_RSA) {
398 attr.clear();
990102db
AT
399 attr.emplace_back(CKA_MODULUS, "");
400 attr.emplace_back(CKA_PUBLIC_EXPONENT, "");
401 attr.emplace_back(CKA_MODULUS_BITS, 0UL);
efaf4928 402
87f56f3f 403 if (!GetAttributeValue2(*slot, d_public_key, attr)) {
efaf4928
AT
404 d_modulus = attr[0].str();
405 d_exponent = attr[1].str();
406 d_bits = attr[2].ulong();
407 } else {
890add84 408 throw PDNSException("Cannot load attributes for PKCS#11 public key " + d_pub_label);
efaf4928
AT
409 }
410 } else if (d_key_type == CKK_EC || d_key_type == CKK_ECDSA) {
411 attr.clear();
990102db
AT
412 attr.emplace_back(CKA_ECDSA_PARAMS, "");
413 attr.emplace_back(CKA_EC_POINT, "");
87f56f3f 414 if (!GetAttributeValue2(*slot, d_public_key, attr)) {
efaf4928 415 d_ecdsa_params = attr[0].str();
357468bc 416 d_bits = ecparam2bits(d_ecdsa_params);
7ecb693d 417 if (attr[1].str().length() != (d_bits*2/8 + 3)) throw PDNSException("EC Point data invalid");
415c31ae 418 d_ec_point = attr[1].str().substr(3);
efaf4928 419 } else {
890add84 420 throw PDNSException("Cannot load attributes for PKCS#11 public key " + d_pub_label);
efaf4928
AT
421 }
422 } else {
890add84 423 throw PDNSException("Cannot determine type for PKCS#11 public key " + d_pub_label);
efaf4928
AT
424 }
425 } else {
890add84 426 throw PDNSException("Cannot load attributes for PKCS#11 public key " + d_pub_label);
efaf4928 427 }
24e0b305
AT
428
429 d_loaded = true;
8daea594
AT
430 }
431
efaf4928 432 int GenerateKeyPair(CK_MECHANISM_PTR mechanism, std::vector<P11KitAttribute>& pubAttributes, std::vector<P11KitAttribute>& privAttributes, CK_OBJECT_HANDLE_PTR pubKey, CK_OBJECT_HANDLE_PTR privKey) {
80d33e0c 433 {
87f56f3f 434 auto slot = d_slot->lock();
8daea594 435
efaf4928 436 size_t k;
2bbc9eb0 437 auto pubAttr = std::make_unique<CK_ATTRIBUTE[]>(pubAttributes.size());
48789026 438 auto privAttr = std::make_unique<CK_ATTRIBUTE[]>(privAttributes.size());
8daea594 439
efaf4928 440 k = 0;
ef7cd021 441 for(P11KitAttribute& attribute : pubAttributes) {
c2826d2e 442 attribute.rattr(pubAttr.get()+k);
efaf4928 443 k++;
8daea594 444 }
8daea594 445
efaf4928 446 k = 0;
ef7cd021 447 for(P11KitAttribute& attribute : privAttributes) {
c2826d2e 448 attribute.rattr(privAttr.get()+k);
efaf4928
AT
449 k++;
450 }
8daea594 451
87f56f3f 452 d_err = slot->f()->C_GenerateKeyPair(slot->Session(), mechanism, pubAttr.get(), pubAttributes.size(), privAttr.get(), privAttributes.size(), pubKey, privKey);
efaf4928 453 logError("C_GenerateKeyPair");
80d33e0c 454 }
8daea594 455
efaf4928 456 if (d_err == 0) LoadAttributes();
8daea594 457
efaf4928 458 return d_err;
8daea594 459 }
8daea594 460
efaf4928 461 int Sign(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism) {
efaf4928
AT
462 CK_BYTE buffer[1024];
463 CK_ULONG buflen = sizeof buffer; // should be enough for most signatures.
87f56f3f 464 auto slot = d_slot->lock();
8daea594 465
efaf4928 466 // perform signature
87f56f3f
RG
467 if ((d_err = slot->f()->C_SignInit(slot->Session(), mechanism, d_private_key))) { logError("C_SignInit"); return d_err; }
468 d_err = slot->f()->C_Sign(slot->Session(), (unsigned char*)data.c_str(), data.size(), buffer, &buflen);
8daea594 469
efaf4928
AT
470 if (!d_err) {
471 result.assign((char*)buffer, buflen);
8daea594 472 }
8daea594 473
efaf4928
AT
474 memset(buffer,0,sizeof buffer);
475 logError("C_Sign");
476 return d_err;
477 }
8daea594 478
efaf4928 479 int Verify(const std::string& data, const std::string& signature, CK_MECHANISM_PTR mechanism) {
87f56f3f 480 auto slot = d_slot->lock();
8daea594 481
87f56f3f
RG
482 if ((d_err = slot->f()->C_VerifyInit(slot->Session(), mechanism, d_public_key))) { logError("C_VerifyInit"); return d_err; }
483 d_err = slot->f()->C_Verify(slot->Session(), (unsigned char*)data.c_str(), data.size(), (unsigned char*)signature.c_str(), signature.size());
efaf4928
AT
484 logError("C_Verify");
485 return d_err;
486 }
8daea594 487
efaf4928 488 int Digest(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism) {
efaf4928
AT
489 CK_BYTE buffer[1024];
490 CK_ULONG buflen = sizeof buffer; // should be enough for most digests
87f56f3f
RG
491
492 auto slot = d_slot->lock();
493 if ((d_err = slot->f()->C_DigestInit(slot->Session(), mechanism))) { logError("C_DigestInit"); return d_err; }
494 d_err = slot->f()->C_Digest(slot->Session(), (unsigned char*)data.c_str(), data.size(), buffer, &buflen);
efaf4928
AT
495 if (!d_err) {
496 result.assign((char*)buffer, buflen);
497 }
498 memset(buffer,0,sizeof buffer);
499 logError("C_Digest");
500 return d_err;
501 }
8daea594 502
87f56f3f
RG
503 int DigestInit(Pkcs11Slot& slot, CK_MECHANISM_PTR mechanism) {
504 d_err = slot.f()->C_DigestInit(slot.Session(), mechanism);
efaf4928
AT
505 logError("C_DigestInit");
506 return d_err;
507 }
8daea594 508
87f56f3f
RG
509 int DigestUpdate(Pkcs11Slot& slot, const std::string& data) {
510 d_err = slot.f()->C_DigestUpdate(slot.Session(), (unsigned char*)data.c_str(), data.size());
efaf4928
AT
511 logError("C_DigestUpdate");
512 return d_err;
513 }
8daea594 514
87f56f3f 515 int DigestFinal(Pkcs11Slot& slot, std::string& result) {
efaf4928
AT
516 CK_BYTE buffer[1024] = {0};
517 CK_ULONG buflen = sizeof buffer; // should be enough for most digests
87f56f3f
RG
518
519 d_err = slot.f()->C_DigestFinal(slot.Session(), buffer, &buflen);
efaf4928
AT
520 if (!d_err) {
521 result.assign((char*)buffer, buflen);
522 }
523 memset(buffer,0,sizeof buffer);
524 logError("C_DigestFinal");
525 return d_err;
526 }
8daea594 527
87f56f3f 528 int FindObjects2(Pkcs11Slot& slot, const std::vector<P11KitAttribute>& attributes, std::vector<CK_OBJECT_HANDLE>& objects, int maxobjects) {
efaf4928
AT
529 CK_RV rv;
530 size_t k;
531 unsigned long count;
8daea594 532
2bbc9eb0
RP
533 auto handles = std::make_unique<CK_OBJECT_HANDLE[]>(maxobjects);
534 auto attr = std::make_unique<CK_ATTRIBUTE[]>(attributes.size());
8daea594 535
efaf4928 536 k = 0;
ef7cd021 537 for(const P11KitAttribute& attribute : attributes) {
c2826d2e 538 attribute.rattr(attr.get()+k);
efaf4928
AT
539 k++;
540 }
8daea594 541
efaf4928 542 // perform search
87f56f3f 543 d_err = slot.f()->C_FindObjectsInit(slot.Session(), attr.get(), k);
8daea594 544
efaf4928 545 if (d_err) {
efaf4928
AT
546 logError("C_FindObjectsInit");
547 return d_err;
548 }
8daea594 549
efaf4928 550 count = maxobjects;
87f56f3f 551 rv = d_err = slot.f()->C_FindObjects(slot.Session(), handles.get(), maxobjects, &count);
efaf4928 552 objects.clear();
8daea594 553
efaf4928
AT
554 if (!rv) {
555 for(k=0;k<count;k++) {
c2826d2e 556 objects.push_back((handles.get())[k]);
efaf4928
AT
557 }
558 }
559
560 logError("C_FindObjects");
561
87f56f3f 562 d_err = slot.f()->C_FindObjectsFinal(slot.Session());
efaf4928 563 logError("C_FindObjectsFinal");
8daea594 564
efaf4928 565 return rv;
8daea594 566 }
8daea594 567
87f56f3f 568 int GetAttributeValue2(Pkcs11Slot& slot, const CK_OBJECT_HANDLE& object, std::vector<P11KitAttribute>& attributes)
efaf4928
AT
569 {
570 size_t k;
2bbc9eb0 571 auto attr = std::make_unique<CK_ATTRIBUTE[]>(attributes.size());
8daea594 572
efaf4928 573 k = 0;
ef7cd021 574 for(P11KitAttribute &attribute : attributes) {
c2826d2e 575 attribute.wattr(attr.get()+k);
efaf4928
AT
576 k++;
577 }
8daea594 578
efaf4928 579 // round 1 - get attribute sizes
87f56f3f 580 d_err = slot.f()->C_GetAttributeValue(slot.Session(), object, attr.get(), attributes.size());
efaf4928
AT
581 logError("C_GetAttributeValue");
582 if (d_err) {
efaf4928
AT
583 return d_err;
584 }
8daea594 585
efaf4928 586 // then allocate memory
2010ac95
RG
587 for(size_t idx=0; idx < attributes.size(); idx++) {
588 if (attributes[idx].valueType() == Attribute_String) {
c2826d2e 589 (attr.get())[idx].pValue = attributes[idx].allocate((attr.get())[idx].ulValueLen);
efaf4928
AT
590 }
591 }
8daea594 592
efaf4928 593 // round 2 - get actual values
87f56f3f 594 d_err = slot.f()->C_GetAttributeValue(slot.Session(), object, attr.get(), attributes.size());
efaf4928 595 logError("C_GetAttributeValue");
8daea594 596
efaf4928 597 // copy values to map and release allocated memory
2010ac95
RG
598 for(size_t idx=0; idx < attributes.size(); idx++) {
599 if (attributes[idx].valueType() == Attribute_String) {
c2826d2e 600 attributes[idx].commit((attr.get())[idx].ulValueLen);
efaf4928
AT
601 }
602 }
8daea594 603
efaf4928
AT
604 return d_err;
605 };
8daea594 606
efaf4928
AT
607 const std::string& Modulus() {
608 return d_modulus;
8daea594 609 }
8daea594 610
efaf4928
AT
611 const std::string& Exponent() {
612 return d_exponent;
613 }
8daea594 614
efaf4928
AT
615 const std::string& ECPoint() {
616 return d_ec_point;
8daea594 617 }
8daea594 618
efaf4928
AT
619 const std::string& ECParameters() {
620 return d_ecdsa_params;
621 }
8daea594 622
efaf4928
AT
623 CK_KEY_TYPE KeyType() {
624 return d_key_type;
8daea594 625 }
8daea594 626
efaf4928
AT
627 CK_ULONG Bits() {
628 return d_bits;
629 }
8daea594 630
9ee32859 631 static std::shared_ptr<Pkcs11Token> GetToken(const std::string& module, const string& tokenId, const std::string& label, const std::string& pub_label);
8daea594
AT
632};
633
87f56f3f 634static std::map<std::string, std::shared_ptr<LockGuarded<Pkcs11Slot> > > pkcs11_slots;
4d68b3b1 635static std::map<std::string, std::shared_ptr<Pkcs11Token> > pkcs11_tokens;
8daea594 636
248d701f
AT
637CK_RV Pkcs11Slot::HuntSlot(const string& tokenId, CK_SLOT_ID &slotId, _CK_SLOT_INFO* info, CK_FUNCTION_LIST* functions)
638{
639 CK_RV err;
d6d13132 640 unsigned int i;
248d701f
AT
641 unsigned long slots;
642 _CK_TOKEN_INFO tinfo;
643
644 // go thru all slots
645 // this is required by certain tokens, otherwise C_GetSlotInfo will not return a token
646 err = functions->C_GetSlotList(CK_FALSE, NULL_PTR, &slots);
647 if (err) {
e6a9dde5 648 g_log<<Logger::Warning<<"C_GetSlotList(CK_FALSE, NULL_PTR, &slots) = " << err << std::endl;
248d701f
AT
649 return err;
650 }
651
d6d13132 652 // get the actual slot ids
2c001eb6 653 std::vector<CK_SLOT_ID> slotIds(slots);
c2a16005 654 err = functions->C_GetSlotList(CK_FALSE, slotIds.data(), &slots);
d6d13132 655 if (err) {
e6a9dde5 656 g_log<<Logger::Warning<<"C_GetSlotList(CK_FALSE, slotIds, &slots) = " << err << std::endl;
d6d13132
AT
657 return err;
658 }
659
248d701f 660 // iterate all slots
d6d13132
AT
661 for(i=0;i<slots;i++) {
662 slotId=slotIds[i];
663 if (slotId == static_cast<CK_SLOT_ID>(-1))
664 continue;
248d701f 665 if ((err = functions->C_GetSlotInfo(slotId, info))) {
e6a9dde5 666 g_log<<Logger::Warning<<"C_GetSlotList("<<slotId<<", info) = " << err << std::endl;
248d701f
AT
667 return err;
668 }
669 if ((err = functions->C_GetTokenInfo(slotId, &tinfo))) {
e6a9dde5 670 g_log<<Logger::Warning<<"C_GetSlotList("<<slotId<<", &tinfo) = " << err << std::endl;
248d701f
AT
671 return err;
672 }
673 std::string slotName;
674 slotName.assign(reinterpret_cast<char*>(tinfo.label), 32);
675 // trim it
676 boost::trim(slotName);
d6d13132 677
248d701f
AT
678 if (boost::iequals(slotName, tokenId)) {
679 return 0;
680 }
681 }
682
683 // see if we can find it with slotId
684 try {
335da0ba 685 slotId = std::stoi(tokenId);
248d701f 686 if ((err = functions->C_GetSlotInfo(slotId, info))) {
e6a9dde5 687 g_log<<Logger::Warning<<"C_GetSlotList("<<slotId<<", info) = " << err << std::endl;
248d701f
AT
688 return err;
689 }
e6a9dde5 690 g_log<<Logger::Warning<<"Specifying PKCS#11 token by SLOT ID is deprecated and should not be used"<<std::endl;
248d701f
AT
691 return 0;
692 } catch (...) {
5a427f84 693 return CKR_SLOT_ID_INVALID;
248d701f 694 }
5a427f84 695 return CKR_SLOT_ID_INVALID;
248d701f
AT
696}
697
87f56f3f 698std::shared_ptr<LockGuarded<Pkcs11Slot>> Pkcs11Slot::GetSlot(const std::string& module, const string& tokenId) {
efaf4928 699 // see if we can find module
24e0b305
AT
700 std::string sidx = module;
701 sidx.append("|");
248d701f 702 sidx.append(tokenId);
87f56f3f 703 std::map<std::string, std::shared_ptr<LockGuarded<Pkcs11Slot> > >::iterator slotIter;
989c2e30 704 CK_RV err;
efaf4928 705 CK_FUNCTION_LIST* functions;
8daea594 706
85e7248d
AT
707 // see if we have slot
708 if ((slotIter = pkcs11_slots.find(sidx)) != pkcs11_slots.end()) {
24e0b305 709 return slotIter->second;
8daea594 710 }
8daea594 711
efaf4928
AT
712#ifdef HAVE_P11KIT1_V2
713 functions = p11_kit_module_for_name(p11_modules, module.c_str());
714#else
715 functions = p11_kit_registered_name_to_module(module.c_str());
716#endif
87f56f3f
RG
717 if (functions == nullptr) throw PDNSException("Cannot find PKCS#11 module " + module);
718 functions->C_Initialize(nullptr); // initialize the module in case it hasn't been done yet.
8daea594 719
efaf4928
AT
720 // try to locate a slot
721 _CK_SLOT_INFO info;
248d701f 722 CK_SLOT_ID slotId;
96ac321d 723
248d701f 724 if ((err = Pkcs11Slot::HuntSlot(tokenId, slotId, &info, functions))) {
5a427f84 725 throw PDNSException(std::string("Cannot find PKCS#11 token ") + tokenId + std::string(" on module ") + module + std::string(": ") + boost::str( boost::format("%s (0x%X)") % p11_kit_strerror(err) % err));
8daea594 726 }
8daea594 727
85e7248d 728 // store slot
87f56f3f 729 pkcs11_slots[sidx] = std::make_shared<LockGuarded<Pkcs11Slot>>(Pkcs11Slot(functions, slotId));
8daea594 730
24e0b305
AT
731 return pkcs11_slots[sidx];
732}
733
9ee32859 734std::shared_ptr<Pkcs11Token> Pkcs11Token::GetToken(const std::string& module, const string& tokenId, const std::string& label, const std::string& pub_label) {
24e0b305
AT
735 // see if we can find module
736 std::string tidx = module;
737 tidx.append("|");
335da0ba 738 tidx.append(tokenId);
24e0b305
AT
739 tidx.append("|");
740 tidx.append(label);
741 std::map<std::string, std::shared_ptr<Pkcs11Token> >::iterator tokenIter;
742 if ((tokenIter = pkcs11_tokens.find(tidx)) != pkcs11_tokens.end()) return tokenIter->second;
8daea594 743
87f56f3f 744 std::shared_ptr<LockGuarded<Pkcs11Slot>> slot = Pkcs11Slot::GetSlot(module, tokenId);
9ee32859 745 pkcs11_tokens[tidx] = std::make_shared<Pkcs11Token>(slot, label, pub_label);
85e7248d 746 return pkcs11_tokens[tidx];
8daea594
AT
747}
748
87f56f3f 749Pkcs11Token::Pkcs11Token(const std::shared_ptr<LockGuarded<Pkcs11Slot>>& slot, const std::string& label, const std::string& pub_label) :
8a70e507 750 d_slot(slot),
c2826d2e 751 d_bits(0),
8a70e507
CHB
752 d_label(label),
753 d_pub_label(pub_label),
c2826d2e
RG
754 d_loaded(false),
755 d_err(0)
8a70e507 756{
efaf4928 757 // open a session
87f56f3f 758 if (this->d_slot->lock()->LoggedIn()) LoadAttributes();
8daea594
AT
759}
760
efaf4928 761Pkcs11Token::~Pkcs11Token() {
8daea594
AT
762}
763
248d701f 764bool PKCS11ModuleSlotLogin(const std::string& module, const string& tokenId, const std::string& pin)
24e0b305 765{
87f56f3f
RG
766 std::shared_ptr<LockGuarded<Pkcs11Slot>> slot = Pkcs11Slot::GetSlot(module, tokenId);
767 if (slot->lock()->LoggedIn()) return true; // no point failing
768 return slot->lock()->Login(pin);
24e0b305
AT
769}
770
8daea594
AT
771PKCS11DNSCryptoKeyEngine::PKCS11DNSCryptoKeyEngine(unsigned int algorithm): DNSCryptoKeyEngine(algorithm) {}
772PKCS11DNSCryptoKeyEngine::~PKCS11DNSCryptoKeyEngine() {}
773PKCS11DNSCryptoKeyEngine::PKCS11DNSCryptoKeyEngine(const PKCS11DNSCryptoKeyEngine& orig) : DNSCryptoKeyEngine(orig.d_algorithm) {}
774
775void PKCS11DNSCryptoKeyEngine::create(unsigned int bits) {
776 std::vector<P11KitAttribute> pubAttr;
777 std::vector<P11KitAttribute> privAttr;
778 CK_MECHANISM mech;
779 CK_OBJECT_HANDLE pubKey, privKey;
4d68b3b1 780 std::shared_ptr<Pkcs11Token> d_slot;
9ee32859 781 d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label, d_pub_label);
efaf4928 782 if (d_slot->LoggedIn() == false)
85e7248d 783 if (d_slot->Login(d_pin) == false)
efaf4928
AT
784 throw PDNSException("Not logged in to token");
785
8daea594 786 std::string pubExp("\000\001\000\001", 4); // 65537
efaf4928 787
389a6742
PD
788 try {
789 mech.mechanism = dnssec2cmech.at(d_algorithm);
790 } catch (std::out_of_range& e) {
791 throw PDNSException("pkcs11: unsupported algorithm "+std::to_string(d_algorithm)+ " for key pair generation");
792 }
793
87f56f3f 794 mech.pParameter = nullptr;
8daea594
AT
795 mech.ulParameterLen = 0;
796
7e520f03
PD
797 if (mech.mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN) {
798 pubAttr.push_back(P11KitAttribute(CKA_CLASS, (unsigned long)CKO_PUBLIC_KEY));
799 pubAttr.push_back(P11KitAttribute(CKA_KEY_TYPE, (unsigned long)CKK_RSA));
800 pubAttr.push_back(P11KitAttribute(CKA_TOKEN, (char)CK_TRUE));
801 pubAttr.push_back(P11KitAttribute(CKA_ENCRYPT, (char)CK_TRUE));
802 pubAttr.push_back(P11KitAttribute(CKA_VERIFY, (char)CK_TRUE));
803 pubAttr.push_back(P11KitAttribute(CKA_WRAP, (char)CK_TRUE));
804 pubAttr.push_back(P11KitAttribute(CKA_MODULUS_BITS, (unsigned long)bits));
805 pubAttr.push_back(P11KitAttribute(CKA_PUBLIC_EXPONENT, pubExp));
806 pubAttr.push_back(P11KitAttribute(CKA_LABEL, d_pub_label));
807
808 privAttr.push_back(P11KitAttribute(CKA_CLASS, (unsigned long)CKO_PRIVATE_KEY));
809 privAttr.push_back(P11KitAttribute(CKA_KEY_TYPE, (unsigned long)CKK_RSA));
810 privAttr.push_back(P11KitAttribute(CKA_TOKEN, (char)CK_TRUE));
811 privAttr.push_back(P11KitAttribute(CKA_PRIVATE, (char)CK_TRUE));
812 // privAttr.push_back(P11KitAttribute(CKA_SUBJECT, "CN=keygen"));
813 privAttr.push_back(P11KitAttribute(CKA_ID, "\x01\x02\x03\x04")); // this is mandatory if you want to export anything
814 privAttr.push_back(P11KitAttribute(CKA_SENSITIVE, (char)CK_TRUE));
815 privAttr.push_back(P11KitAttribute(CKA_DECRYPT, (char)CK_TRUE));
816 privAttr.push_back(P11KitAttribute(CKA_SIGN, (char)CK_TRUE));
817 privAttr.push_back(P11KitAttribute(CKA_UNWRAP, (char)CK_TRUE));
818 privAttr.push_back(P11KitAttribute(CKA_LABEL, d_label));
819 } else if (mech.mechanism == CKM_ECDSA_KEY_PAIR_GEN) {
820 pubAttr.push_back(P11KitAttribute(CKA_CLASS, (unsigned long)CKO_PUBLIC_KEY));
821 pubAttr.push_back(P11KitAttribute(CKA_KEY_TYPE, (unsigned long)CKK_ECDSA));
822 pubAttr.push_back(P11KitAttribute(CKA_TOKEN, (char)CK_TRUE));
823 pubAttr.push_back(P11KitAttribute(CKA_ENCRYPT, (char)CK_TRUE));
824 pubAttr.push_back(P11KitAttribute(CKA_VERIFY, (char)CK_TRUE));
4b32ce75 825 pubAttr.push_back(P11KitAttribute(CKA_WRAP, (char)CK_TRUE));
7e520f03 826 pubAttr.push_back(P11KitAttribute(CKA_LABEL, d_pub_label));
73db7e76
PD
827 if (d_algorithm == 13) pubAttr.push_back(P11KitAttribute(CKA_ECDSA_PARAMS, ECDSA256_PARAMS));
828 else if (d_algorithm == 14) pubAttr.push_back(P11KitAttribute(CKA_ECDSA_PARAMS, ECDSA384_PARAMS));
389a6742 829 else throw PDNSException("pkcs11: unknown algorithm "+std::to_string(d_algorithm)+" for ECDSA key pair generation");
7e520f03
PD
830
831 privAttr.push_back(P11KitAttribute(CKA_CLASS, (unsigned long)CKO_PRIVATE_KEY));
832 privAttr.push_back(P11KitAttribute(CKA_KEY_TYPE, (unsigned long)CKK_ECDSA));
833 privAttr.push_back(P11KitAttribute(CKA_TOKEN, (char)CK_TRUE));
834 privAttr.push_back(P11KitAttribute(CKA_PRIVATE, (char)CK_TRUE));
835 // privAttr.push_back(P11KitAttribute(CKA_SUBJECT, "CN=keygen"));
836 privAttr.push_back(P11KitAttribute(CKA_ID, "\x01\x02\x03\x04")); // this is mandatory if you want to export anything
837 privAttr.push_back(P11KitAttribute(CKA_SENSITIVE, (char)CK_TRUE));
838 privAttr.push_back(P11KitAttribute(CKA_DECRYPT, (char)CK_TRUE));
839 privAttr.push_back(P11KitAttribute(CKA_SIGN, (char)CK_TRUE));
840 privAttr.push_back(P11KitAttribute(CKA_UNWRAP, (char)CK_TRUE));
841 privAttr.push_back(P11KitAttribute(CKA_LABEL, d_label));
842 } else {
843 throw PDNSException("pkcs11: don't know how make key for algorithm "+std::to_string(d_algorithm));
844 }
845
846
a5d2c081 847 if (d_slot->GenerateKeyPair(&mech, pubAttr, privAttr, &pubKey, &privKey)) {
efaf4928 848 throw PDNSException("Keypair generation failed");
8daea594
AT
849 }
850};
851
efaf4928 852std::string PKCS11DNSCryptoKeyEngine::sign(const std::string& msg) const {
8daea594 853 std::string result;
4d68b3b1 854 std::shared_ptr<Pkcs11Token> d_slot;
9ee32859 855 d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label, d_pub_label);
efaf4928 856 if (d_slot->LoggedIn() == false)
85e7248d 857 if (d_slot->Login(d_pin) == false)
efaf4928
AT
858 throw PDNSException("Not logged in to token");
859
8daea594
AT
860 CK_MECHANISM mech;
861 mech.mechanism = dnssec2smech[d_algorithm];
87f56f3f 862 mech.pParameter = nullptr;
8daea594 863 mech.ulParameterLen = 0;
ba9a0057
AT
864
865 if (mech.mechanism == CKM_ECDSA) {
866 if (d_slot->Sign(this->hash(msg), result, &mech)) throw PDNSException("Could not sign data");
867 } else {
868 if (d_slot->Sign(msg, result, &mech)) throw PDNSException("Could not sign data");
869 }
8daea594
AT
870 return result;
871};
872
873std::string PKCS11DNSCryptoKeyEngine::hash(const std::string& msg) const {
874 std::string result;
875 CK_MECHANISM mech;
876 mech.mechanism = dnssec2hmech[d_algorithm];
87f56f3f 877 mech.pParameter = nullptr;
8daea594 878 mech.ulParameterLen = 0;
4d68b3b1 879 std::shared_ptr<Pkcs11Token> d_slot;
9ee32859 880 d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label, d_pub_label);
efaf4928 881 if (d_slot->LoggedIn() == false)
85e7248d 882 if (d_slot->Login(d_pin) == false)
efaf4928 883 throw PDNSException("Not logged in to token");
8daea594 884
efaf4928 885 if (d_slot->Digest(msg, result, &mech)) {
e6a9dde5 886 g_log<<Logger::Error<<"Could not digest using PKCS#11 token - using software workaround"<<endl;
8daea594
AT
887 // FINE! I'll do this myself, then, shall I?
888 switch(d_algorithm) {
889 case 5: {
dd133337 890 return pdns_sha1sum(msg);
8daea594
AT
891 }
892 case 8: {
dd133337 893 return pdns_sha256sum(msg);
8daea594
AT
894 }
895 case 10: {
dd133337 896 return pdns_sha512sum(msg);
8daea594
AT
897 }
898 case 13: {
dd133337 899 return pdns_sha256sum(msg);
8daea594
AT
900 }
901 case 14: {
dd133337 902 return pdns_sha384sum(msg);
8daea594
AT
903 }
904 };
905 };
906 return result;
907};
908
909bool PKCS11DNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const {
4d68b3b1 910 std::shared_ptr<Pkcs11Token> d_slot;
9ee32859 911 d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label, d_pub_label);
efaf4928 912 if (d_slot->LoggedIn() == false)
85e7248d 913 if (d_slot->Login(d_pin) == false)
efaf4928
AT
914 throw PDNSException("Not logged in to token");
915
8daea594
AT
916 CK_MECHANISM mech;
917 mech.mechanism = dnssec2smech[d_algorithm];
87f56f3f 918 mech.pParameter = nullptr;
8daea594 919 mech.ulParameterLen = 0;
ba9a0057
AT
920 if (mech.mechanism == CKM_ECDSA) {
921 return (d_slot->Verify(this->hash(msg), signature, &mech)==0);
922 } else {
923 return (d_slot->Verify(msg, signature, &mech) == 0);
924 }
8daea594
AT
925};
926
8daea594
AT
927std::string PKCS11DNSCryptoKeyEngine::getPublicKeyString() const {
928 std::string result("");
4d68b3b1 929 std::shared_ptr<Pkcs11Token> d_slot;
9ee32859 930 d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label, d_pub_label);
efaf4928 931 if (d_slot->LoggedIn() == false)
85e7248d 932 if (d_slot->Login(d_pin) == false)
efaf4928
AT
933 throw PDNSException("Not logged in to token");
934
935 if (d_slot->KeyType() == CKK_RSA) {
936 if (d_slot->Exponent().length() < 255) {
937 result.assign(1, (char) (unsigned int) d_slot->Exponent().length());
938 } else {
939 result.assign(1, 0);
940 uint16_t len=htons(d_slot->Exponent().length());
941 result.append((char*)&len, 2);
942 }
943 result.append(d_slot->Exponent());
944 result.append(d_slot->Modulus());
945 } else {
946 result.append(d_slot->ECPoint());
947 }
948 return result;
8daea594
AT
949};
950
951int PKCS11DNSCryptoKeyEngine::getBits() const {
4d68b3b1 952 std::shared_ptr<Pkcs11Token> d_slot;
9ee32859 953 d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label, d_pub_label);
efaf4928 954 if (d_slot->LoggedIn() == false)
85e7248d 955 if (d_slot->Login(d_pin) == false)
efaf4928
AT
956 throw PDNSException("Not logged in to token");
957
958 return d_slot->Bits();
8daea594
AT
959};
960
efaf4928 961DNSCryptoKeyEngine::storvector_t PKCS11DNSCryptoKeyEngine::convertToISCVector() const {
e32a8d46
RP
962 auto storvect = storvector_t{
963 {"Algorithm", std::to_string(d_algorithm)},
964 {"Engine", d_module},
965 {"Slot", d_slot_id},
966 {"PIN", d_pin},
967 {"Label", d_label},
968 {"PubLabel", d_pub_label},
969 };
8daea594
AT
970 return storvect;
971};
972
3a3ecb9d 973void PKCS11DNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, stormap_t& stormap) {
a0383aad 974 pdns::checked_stoi_into(drc.d_algorithm, stormap["algorithm"]);
3a3ecb9d 975 d_module = stormap["engine"];
248d701f
AT
976 d_slot_id = stormap["slot"];
977 boost::trim(d_slot_id);
3a3ecb9d
AT
978 d_pin = stormap["pin"];
979 d_label = stormap["label"];
9ee32859
AT
980 if (stormap.find("publabel") != stormap.end())
981 d_pub_label = stormap["publabel"];
982 else
983 d_pub_label = d_label;
3a3ecb9d
AT
984 // validate parameters
985
4d68b3b1 986 std::shared_ptr<Pkcs11Token> d_slot;
9ee32859 987 d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label, d_pub_label);
3a3ecb9d
AT
988 if (d_pin != "" && d_slot->LoggedIn() == false)
989 if (d_slot->Login(d_pin) == false)
990 throw PDNSException("Could not log in to token (PIN wrong?)");
991};
992
a2c6e554 993std::unique_ptr<DNSCryptoKeyEngine> PKCS11DNSCryptoKeyEngine::maker(unsigned int algorithm)
8daea594 994{
a2c6e554 995 return make_unique<PKCS11DNSCryptoKeyEngine>(algorithm);
8daea594
AT
996}
997
998// this is called during program startup
999namespace {
efaf4928 1000 static struct LoaderStruct
8daea594 1001 {
efaf4928
AT
1002 LoaderStruct()
1003 {
fa8f416f 1004#ifdef HAVE_P11KIT1_V2
efaf4928 1005 p11_modules = p11_kit_modules_load_and_initialize(0);
fa8f416f 1006#else
efaf4928 1007 p11_kit_initialize_registered();
fa8f416f 1008#endif
efaf4928
AT
1009 };
1010 ~LoaderStruct() {
fa8f416f 1011#ifdef HAVE_P11KIT1_V2
efaf4928 1012 p11_kit_modules_release(p11_modules);
fa8f416f 1013#else
efaf4928 1014 p11_kit_finalize_registered();
fa8f416f 1015#endif
efaf4928
AT
1016 };
1017 } loaderPkcs11;
8daea594 1018}