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