]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/opensslsigners.cc
opensslsigners: Add missing 'static' keyword
[thirdparty/pdns.git] / pdns / opensslsigners.cc
CommitLineData
12471842
PL
1/*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
7581a35b
KM
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25#include <openssl/obj_mac.h>
74d83458 26#ifdef HAVE_LIBCRYPTO_ECDSA
7581a35b 27#include <openssl/ecdsa.h>
de4e1d0d 28#endif
439974d7
PL
29#if defined(HAVE_LIBCRYPTO_ED25519) || defined(HAVE_LIBCRYPTO_ED448)
30#include <openssl/evp.h>
31#endif
fb46af61 32#include <openssl/bn.h>
7581a35b
KM
33#include <openssl/sha.h>
34#include <openssl/rand.h>
a41d80d1 35#include <openssl/rsa.h>
d366601f 36#include <openssl/opensslv.h>
ac3f3893 37#include <openssl/err.h>
42f01311 38#include "opensslsigners.hh"
7581a35b 39#include "dnssecinfra.hh"
86783480 40#include "dnsseckeeper.hh"
7581a35b 41
629440d4 42#if (OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2090100fL)
d366601f 43/* OpenSSL < 1.1.0 needs support for threading/locking in the calling application. */
69b8131b
RG
44
45#include "lock.hh"
46static std::vector<std::mutex> openssllocks;
42f01311 47
48extern "C" {
c2700b66 49static void openssl_pthreads_locking_callback(int mode, int type, const char *file, int line)
42f01311 50{
51 if (mode & CRYPTO_LOCK) {
69b8131b 52 openssllocks.at(type).lock();
42f01311 53
69b8131b
RG
54 } else {
55 openssllocks.at(type).unlock();
42f01311 56 }
57}
58
c2700b66 59static unsigned long openssl_pthreads_id_callback(void)
42f01311 60{
61 return (unsigned long)pthread_self();
62}
63}
64
65void openssl_thread_setup()
66{
69b8131b
RG
67 openssllocks = std::vector<std::mutex>(CRYPTO_num_locks());
68 CRYPTO_set_id_callback(&openssl_pthreads_id_callback);
69 CRYPTO_set_locking_callback(&openssl_pthreads_locking_callback);
42f01311 70}
71
72void openssl_thread_cleanup()
73{
69b8131b
RG
74 CRYPTO_set_locking_callback(nullptr);
75 openssllocks.clear();
42f01311 76}
888bc297 77
629440d4 78#ifndef HAVE_RSA_GET0_KEY
1648b8ff 79/* those symbols are defined in LibreSSL 2.7.0+ */
888bc297
CH
80/* compat helpers. These DO NOT do any of the checking that the libssl 1.1 functions do. */
81static inline void RSA_get0_key(const RSA* rsakey, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d) {
82 *n = rsakey->n;
83 *e = rsakey->e;
84 *d = rsakey->d;
85}
86
87static inline int RSA_set0_key(RSA* rsakey, BIGNUM* n, BIGNUM* e, BIGNUM* d) {
88 if (n) {
89 BN_clear_free(rsakey->n);
90 rsakey->n = n;
91 }
92 if (e) {
93 BN_clear_free(rsakey->e);
94 rsakey->e = e;
95 }
96 if (d) {
97 BN_clear_free(rsakey->d);
98 rsakey->d = d;
99 }
100 return 1;
101}
102
103static inline void RSA_get0_factors(const RSA* rsakey, const BIGNUM** p, const BIGNUM** q) {
104 *p = rsakey->p;
105 *q = rsakey->q;
106}
107
108static inline int RSA_set0_factors(RSA* rsakey, BIGNUM* p, BIGNUM* q) {
109 BN_clear_free(rsakey->p);
110 rsakey->p = p;
111 BN_clear_free(rsakey->q);
112 rsakey->q = q;
113 return 1;
114}
115
116static inline void RSA_get0_crt_params(const RSA* rsakey, const BIGNUM** dmp1, const BIGNUM** dmq1, const BIGNUM** iqmp) {
117 *dmp1 = rsakey->dmp1;
118 *dmq1 = rsakey->dmq1;
119 *iqmp = rsakey->iqmp;
120}
121
122static inline int RSA_set0_crt_params(RSA* rsakey, BIGNUM* dmp1, BIGNUM* dmq1, BIGNUM* iqmp) {
123 BN_clear_free(rsakey->dmp1);
124 rsakey->dmp1 = dmp1;
125 BN_clear_free(rsakey->dmq1);
126 rsakey->dmq1 = dmq1;
127 BN_clear_free(rsakey->iqmp);
128 rsakey->iqmp = iqmp;
129 return 1;
130}
131
aa74d164 132#ifdef HAVE_LIBCRYPTO_ECDSA
888bc297
CH
133static inline void ECDSA_SIG_get0(const ECDSA_SIG* signature, const BIGNUM** pr, const BIGNUM** ps) {
134 *pr = signature->r;
135 *ps = signature->s;
136}
137
138static inline int ECDSA_SIG_set0(ECDSA_SIG* signature, BIGNUM* pr, BIGNUM* ps) {
139 BN_clear_free(signature->r);
140 BN_clear_free(signature->s);
141 signature->r = pr;
142 signature->s = ps;
143 return 1;
144}
aa74d164
RG
145#endif /* HAVE_LIBCRYPTO_ECDSA */
146
629440d4 147#endif /* HAVE_RSA_GET0_KEY */
1648b8ff 148
d366601f
CH
149#else
150void openssl_thread_setup() {}
151void openssl_thread_cleanup() {}
152#endif
42f01311 153
888bc297 154
42f01311 155/* seeding PRNG */
156
157void openssl_seed()
158{
159 std::string entropy;
160 entropy.reserve(1024);
161
162 unsigned int r;
163 for(int i=0; i<1024; i+=4) {
164 r=dns_random(0xffffffff);
165 entropy.append((const char*)&r, 4);
166 }
167
168 RAND_seed((const unsigned char*)entropy.c_str(), 1024);
169}
170
171
a41d80d1
RG
172class OpenSSLRSADNSCryptoKeyEngine : public DNSCryptoKeyEngine
173{
174public:
5498c0a9 175 explicit OpenSSLRSADNSCryptoKeyEngine(unsigned int algo): DNSCryptoKeyEngine(algo), d_key(std::unique_ptr<RSA, void(*)(RSA*)>(nullptr, RSA_free))
a41d80d1
RG
176 {
177 int ret = RAND_status();
178 if (ret != 1) {
179 throw runtime_error(getName()+" insufficient entropy");
180 }
a41d80d1
RG
181 }
182
183 ~OpenSSLRSADNSCryptoKeyEngine()
184 {
a41d80d1
RG
185 }
186
d12b259b 187 string getName() const override { return "OpenSSL RSA"; }
5498c0a9 188 int getBits() const override { return RSA_size(d_key.get()) << 3; }
d12b259b
CH
189
190 void create(unsigned int bits) override;
191 storvector_t convertToISCVector() const override;
192 std::string hash(const std::string& hash) const override;
193 std::string sign(const std::string& hash) const override;
194 bool verify(const std::string& hash, const std::string& signature) const override;
195 std::string getPubKeyHash() const override;
196 std::string getPublicKeyString() const override;
197 void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) override;
198 void fromPublicKeyString(const std::string& content) override;
ac3f3893 199 bool checkKey(vector<string> *errorMessages) const override;
a41d80d1 200
e69c2dac 201 static std::shared_ptr<DNSCryptoKeyEngine> maker(unsigned int algorithm)
a41d80d1 202 {
e69c2dac 203 return std::make_shared<OpenSSLRSADNSCryptoKeyEngine>(algorithm);
a41d80d1
RG
204 }
205
206private:
349384bf
RG
207 static int hashSizeToKind(size_t hashSize);
208
5498c0a9 209 std::unique_ptr<RSA, void(*)(RSA*)> d_key;
a41d80d1
RG
210};
211
212
213void OpenSSLRSADNSCryptoKeyEngine::create(unsigned int bits)
214{
ac3f3893 215 // When changing the bitsizes, also edit them in ::checkKey
86783480
CH
216 if ((d_algorithm == DNSSECKeeper::RSASHA1 || d_algorithm == DNSSECKeeper::RSASHA1NSEC3SHA1) && (bits < 512 || bits > 4096)) {
217 /* RFC3110 */
218 throw runtime_error(getName()+" RSASHA1 key generation failed for invalid bits size " + std::to_string(bits));
219 }
220 if (d_algorithm == DNSSECKeeper::RSASHA256 && (bits < 512 || bits > 4096)) {
221 /* RFC5702 */
222 throw runtime_error(getName()+" RSASHA256 key generation failed for invalid bits size " + std::to_string(bits));
223 }
224 if (d_algorithm == DNSSECKeeper::RSASHA512 && (bits < 1024 || bits > 4096)) {
225 /* RFC5702 */
226 throw runtime_error(getName()+" RSASHA512 key generation failed for invalid bits size " + std::to_string(bits));
227 }
228
5498c0a9 229 auto e = std::unique_ptr<BIGNUM, void(*)(BIGNUM*)>(BN_new(), BN_clear_free);
a41d80d1
RG
230 if (!e) {
231 throw runtime_error(getName()+" key generation failed, unable to allocate e");
232 }
233
234 /* RSA_F4 is a public exponent value of 65537 */
5498c0a9 235 int res = BN_set_word(e.get(), RSA_F4);
a41d80d1
RG
236
237 if (res == 0) {
a41d80d1
RG
238 throw runtime_error(getName()+" key generation failed while setting e");
239 }
240
5498c0a9
RG
241 auto key = std::unique_ptr<RSA, void(*)(RSA*)>(RSA_new(), RSA_free);
242 if (!key) {
62be6888
RG
243 throw runtime_error(getName()+" allocation of key structure failed");
244 }
245
5498c0a9 246 res = RSA_generate_key_ex(key.get(), bits, e.get(), nullptr);
a41d80d1
RG
247 if (res == 0) {
248 throw runtime_error(getName()+" key generation failed");
249 }
62be6888 250
5498c0a9 251 d_key = std::move(key);
a41d80d1
RG
252}
253
254
255DNSCryptoKeyEngine::storvector_t OpenSSLRSADNSCryptoKeyEngine::convertToISCVector() const
256{
257 storvector_t storvect;
258 typedef vector<pair<string, const BIGNUM*> > outputs_t;
259 outputs_t outputs;
888bc297 260 const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
5498c0a9
RG
261 RSA_get0_key(d_key.get(), &n, &e, &d);
262 RSA_get0_factors(d_key.get(), &p, &q);
263 RSA_get0_crt_params(d_key.get(), &dmp1, &dmq1, &iqmp);
888bc297
CH
264 outputs.push_back(make_pair("Modulus", n));
265 outputs.push_back(make_pair("PublicExponent", e));
266 outputs.push_back(make_pair("PrivateExponent", d));
267 outputs.push_back(make_pair("Prime1", p));
268 outputs.push_back(make_pair("Prime2", q));
269 outputs.push_back(make_pair("Exponent1", dmp1));
270 outputs.push_back(make_pair("Exponent2", dmq1));
271 outputs.push_back(make_pair("Coefficient", iqmp));
a41d80d1
RG
272
273 string algorithm=std::to_string(d_algorithm);
274 switch(d_algorithm) {
902c4e9c
CH
275 case DNSSECKeeper::RSASHA1:
276 case DNSSECKeeper::RSASHA1NSEC3SHA1:
a41d80d1
RG
277 algorithm += " (RSASHA1)";
278 break;
902c4e9c 279 case DNSSECKeeper::RSASHA256:
a41d80d1
RG
280 algorithm += " (RSASHA256)";
281 break;
902c4e9c 282 case DNSSECKeeper::RSASHA512:
a41d80d1
RG
283 algorithm += " (RSASHA512)";
284 break;
349384bf
RG
285 default:
286 algorithm += " (?)";
a41d80d1
RG
287 }
288 storvect.push_back(make_pair("Algorithm", algorithm));
289
290 for(outputs_t::value_type value : outputs) {
e5f0dee1
RG
291 std::string tmp;
292 tmp.resize(BN_num_bytes(value.second));
293 int len = BN_bn2bin(value.second, reinterpret_cast<unsigned char*>(&tmp.at(0)));
294 if (len >= 0) {
295 tmp.resize(len);
296 storvect.push_back(make_pair(value.first, tmp));
297 }
a41d80d1
RG
298 }
299
300 return storvect;
301}
302
303
304std::string OpenSSLRSADNSCryptoKeyEngine::hash(const std::string& orig) const
305{
902c4e9c 306 if (d_algorithm == DNSSECKeeper::RSASHA1 || d_algorithm == DNSSECKeeper::RSASHA1NSEC3SHA1) {
41426b6f
AT
307 unsigned char l_hash[SHA_DIGEST_LENGTH];
308 SHA1((unsigned char*) orig.c_str(), orig.length(), l_hash);
309 return string((char*) l_hash, sizeof(l_hash));
a41d80d1 310 }
902c4e9c 311 else if (d_algorithm == DNSSECKeeper::RSASHA256) {
41426b6f
AT
312 unsigned char l_hash[SHA256_DIGEST_LENGTH];
313 SHA256((unsigned char*) orig.c_str(), orig.length(), l_hash);
314 return string((char*) l_hash, sizeof(l_hash));
a41d80d1 315 }
902c4e9c 316 else if (d_algorithm == DNSSECKeeper::RSASHA512) {
41426b6f
AT
317 unsigned char l_hash[SHA512_DIGEST_LENGTH];
318 SHA512((unsigned char*) orig.c_str(), orig.length(), l_hash);
319 return string((char*) l_hash, sizeof(l_hash));
a41d80d1
RG
320 }
321
322 throw runtime_error(getName()+" does not support hash operation for algorithm "+std::to_string(d_algorithm));
323}
324
349384bf
RG
325int OpenSSLRSADNSCryptoKeyEngine::hashSizeToKind(const size_t hashSize)
326{
327 switch(hashSize) {
328 case SHA_DIGEST_LENGTH:
329 return NID_sha1;
330 case SHA256_DIGEST_LENGTH:
331 return NID_sha256;
332 case SHA384_DIGEST_LENGTH:
333 return NID_sha384;
334 case SHA512_DIGEST_LENGTH:
335 return NID_sha512;
336 default:
337 throw runtime_error("OpenSSL RSA does not handle hash of size " + std::to_string(hashSize));
338 }
339}
a41d80d1
RG
340
341std::string OpenSSLRSADNSCryptoKeyEngine::sign(const std::string& msg) const
342{
41426b6f
AT
343 string l_hash = this->hash(msg);
344 int hashKind = hashSizeToKind(l_hash.size());
e5f0dee1 345 std::string signature;
5498c0a9 346 signature.resize(RSA_size(d_key.get()));
a41d80d1
RG
347 unsigned int signatureLen = 0;
348
41426b6f 349 int res = RSA_sign(hashKind, reinterpret_cast<unsigned char*>(&l_hash.at(0)), l_hash.length(), reinterpret_cast<unsigned char*>(&signature.at(0)), &signatureLen, d_key.get());
a41d80d1
RG
350 if (res != 1) {
351 throw runtime_error(getName()+" failed to generate signature");
352 }
353
e5f0dee1
RG
354 signature.resize(signatureLen);
355 return signature;
a41d80d1
RG
356}
357
358
359bool OpenSSLRSADNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const
360{
41426b6f
AT
361 string l_hash = this->hash(msg);
362 int hashKind = hashSizeToKind(l_hash.size());
a41d80d1 363
41426b6f 364 int ret = RSA_verify(hashKind, (const unsigned char*)l_hash.c_str(), l_hash.length(), (unsigned char*)signature.c_str(), signature.length(), d_key.get());
a41d80d1
RG
365
366 return (ret == 1);
367}
368
369
370std::string OpenSSLRSADNSCryptoKeyEngine::getPubKeyHash() const
371{
888bc297 372 const BIGNUM *n, *e, *d;
5498c0a9 373 RSA_get0_key(d_key.get(), &n, &e, &d);
e5f0dee1
RG
374 std::vector<unsigned char> tmp;
375 tmp.resize(std::max(BN_num_bytes(e), BN_num_bytes(n)));
41426b6f 376 unsigned char l_hash[SHA_DIGEST_LENGTH];
a41d80d1
RG
377 SHA_CTX ctx;
378
379 int res = SHA1_Init(&ctx);
380
381 if (res != 1) {
382 throw runtime_error(getName()+" failed to init hash context for generating the public key hash");
383 }
384
c2a16005
RG
385 int len = BN_bn2bin(e, tmp.data());
386 res = SHA1_Update(&ctx, tmp.data(), len);
a41d80d1
RG
387 if (res != 1) {
388 throw runtime_error(getName()+" failed to update hash context for generating the public key hash");
389 }
390
c2a16005
RG
391 len = BN_bn2bin(n, tmp.data());
392 res = SHA1_Update(&ctx, tmp.data(), len);
a41d80d1
RG
393 if (res != 1) {
394 throw runtime_error(getName()+" failed to update hash context for generating the public key hash");
395 }
396
41426b6f 397 res = SHA1_Final(l_hash, &ctx);
a41d80d1
RG
398 if (res != 1) {
399 throw runtime_error(getName()+" failed to finish hash context for generating the public key hash");
400 }
401
41426b6f 402 return string((char*)l_hash, sizeof(l_hash));
a41d80d1
RG
403}
404
405
406std::string OpenSSLRSADNSCryptoKeyEngine::getPublicKeyString() const
407{
888bc297 408 const BIGNUM *n, *e, *d;
5498c0a9 409 RSA_get0_key(d_key.get(), &n, &e, &d);
a41d80d1 410 string keystring;
e5f0dee1
RG
411 std::string tmp;
412 tmp.resize(std::max(BN_num_bytes(e), BN_num_bytes(n)));
a41d80d1 413
e5f0dee1 414 int len = BN_bn2bin(e, reinterpret_cast<unsigned char*>(&tmp.at(0)));
a41d80d1
RG
415 if (len < 255) {
416 keystring.assign(1, (char) (unsigned int) len);
417 } else {
418 keystring.assign(1, 0);
419 uint16_t tempLen = len;
420 tempLen = htons(tempLen);
421 keystring.append((char*)&tempLen, 2);
422 }
e5f0dee1 423 keystring.append(&tmp.at(0), len);
a41d80d1 424
e5f0dee1
RG
425 len = BN_bn2bin(n, reinterpret_cast<unsigned char*>(&tmp.at(0)));
426 keystring.append(&tmp.at(0), len);
a41d80d1
RG
427
428 return keystring;
429}
430
431
432void OpenSSLRSADNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap)
433{
a41d80d1
RG
434 typedef map<string, BIGNUM**> places_t;
435 places_t places;
5498c0a9
RG
436 auto key = std::unique_ptr<RSA, void(*)(RSA*)>(RSA_new(), RSA_free);
437 if (!key) {
62be6888
RG
438 throw runtime_error(getName()+" allocation of key structure failed");
439 }
a41d80d1 440
888bc297
CH
441 BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
442 n = BN_new();
5498c0a9 443 if (n == nullptr) {
888bc297
CH
444 throw runtime_error(getName()+" allocation of BIGNUM n failed");
445 }
446 e = BN_new();
5498c0a9 447 if (e == nullptr) {
888bc297
CH
448 BN_clear_free(n);
449 throw runtime_error(getName()+" allocation of BIGNUM e failed");
450 }
451 d = BN_new();
5498c0a9 452 if (d == nullptr) {
888bc297
CH
453 BN_clear_free(n);
454 BN_clear_free(e);
455 throw runtime_error(getName()+" allocation of BIGNUM d failed");
456 }
5498c0a9 457 RSA_set0_key(key.get(), n, e, d);
888bc297
CH
458
459 p = BN_new();
5498c0a9 460 if (p == nullptr) {
888bc297
CH
461 throw runtime_error(getName()+" allocation of BIGNUM p failed");
462 }
463 q = BN_new();
5498c0a9 464 if (q == nullptr) {
888bc297
CH
465 BN_clear_free(p);
466 throw runtime_error(getName()+" allocation of BIGNUM q failed");
467 }
5498c0a9 468 RSA_set0_factors(key.get(), p, q);
888bc297
CH
469
470 dmp1 = BN_new();
5498c0a9 471 if (dmp1 == nullptr) {
888bc297
CH
472 throw runtime_error(getName()+" allocation of BIGNUM dmp1 failed");
473 }
474 dmq1 = BN_new();
5498c0a9 475 if (dmq1 == nullptr) {
888bc297
CH
476 BN_clear_free(dmp1);
477 throw runtime_error(getName()+" allocation of BIGNUM dmq1 failed");
478 }
479 iqmp = BN_new();
5498c0a9 480 if (iqmp == nullptr) {
888bc297 481 BN_clear_free(dmq1);
e4238b33 482 BN_clear_free(dmp1);
888bc297
CH
483 throw runtime_error(getName()+" allocation of BIGNUM iqmp failed");
484 }
5498c0a9 485 RSA_set0_crt_params(key.get(), dmp1, dmq1, iqmp);
888bc297
CH
486
487 places["Modulus"]=&n;
488 places["PublicExponent"]=&e;
489 places["PrivateExponent"]=&d;
490 places["Prime1"]=&p;
491 places["Prime2"]=&q;
492 places["Exponent1"]=&dmp1;
493 places["Exponent2"]=&dmq1;
494 places["Coefficient"]=&iqmp;
a41d80d1
RG
495
496 drc.d_algorithm = pdns_stou(stormap["algorithm"]);
497
498 string raw;
499 for(const places_t::value_type& val : places) {
500 raw=stormap[toLower(val.first)];
349384bf
RG
501
502 if (!val.second)
503 continue;
504
888bc297 505 *val.second = BN_bin2bn((unsigned char*) raw.c_str(), raw.length(), *val.second);
a41d80d1
RG
506 if (!*val.second) {
507 throw runtime_error(getName()+" error loading " + val.first);
508 }
509 }
510
511 if (drc.d_algorithm != d_algorithm) {
512 throw runtime_error(getName()+" tried to feed an algorithm "+std::to_string(drc.d_algorithm)+" to a "+std::to_string(d_algorithm)+" key");
513 }
514
5498c0a9 515 d_key = std::move(key);
a41d80d1
RG
516}
517
ac3f3893 518bool OpenSSLRSADNSCryptoKeyEngine::checkKey(vector<string> *errorMessages) const
8ca3ea33 519{
ac3f3893
PL
520 bool retval = true;
521 // When changing the bitsizes, also edit them in ::create
522 if ((d_algorithm == DNSSECKeeper::RSASHA1 || d_algorithm == DNSSECKeeper::RSASHA1NSEC3SHA1 || d_algorithm == DNSSECKeeper::RSASHA256) && (getBits() < 512 || getBits()> 4096)) {
523 retval = false;
524 if (errorMessages != nullptr) {
525 errorMessages->push_back("key is " + std::to_string(getBits()) + " bytes, should be between 512 and 4096");
526 }
f59c4313
PL
527 }
528 if (d_algorithm == DNSSECKeeper::RSASHA512 && (getBits() < 1024 || getBits() > 4096)) {
ac3f3893
PL
529 retval = false;
530 if (errorMessages != nullptr) {
531 errorMessages->push_back("key is " + std::to_string(getBits()) + " bytes, should be between 1024 and 4096");
532 }
f59c4313 533 }
128bc6d2 534 if (RSA_check_key(d_key.get()) != 1) {
ac3f3893
PL
535 retval = false;
536 if (errorMessages != nullptr) {
537 errorMessages->push_back(ERR_reason_error_string(ERR_get_error()));
538 }
539 }
540 return retval;
8ca3ea33
RG
541}
542
a41d80d1
RG
543void OpenSSLRSADNSCryptoKeyEngine::fromPublicKeyString(const std::string& input)
544{
545 string exponent, modulus;
349384bf 546 const size_t inputLen = input.length();
a41d80d1
RG
547 const unsigned char* raw = (const unsigned char*)input.c_str();
548
349384bf
RG
549 if (inputLen < 1) {
550 throw runtime_error(getName()+" invalid input size for the public key");
551 }
552
a41d80d1 553 if (raw[0] != 0) {
349384bf
RG
554 const size_t exponentSize = raw[0];
555 if (inputLen < (exponentSize + 2)) {
556 throw runtime_error(getName()+" invalid input size for the public key");
557 }
558 exponent = input.substr(1, exponentSize);
559 modulus = input.substr(exponentSize + 1);
a41d80d1 560 } else {
349384bf
RG
561 if (inputLen < 3) {
562 throw runtime_error(getName()+" invalid input size for the public key");
563 }
564 const size_t exponentSize = raw[1]*0xff + raw[2];
565 if (inputLen < (exponentSize + 4)) {
566 throw runtime_error(getName()+" invalid input size for the public key");
567 }
568 exponent = input.substr(3, exponentSize);
569 modulus = input.substr(exponentSize + 3);
a41d80d1
RG
570 }
571
5498c0a9
RG
572 auto key = std::unique_ptr<RSA, void(*)(RSA*)>(RSA_new(), RSA_free);
573 if (!key) {
62be6888
RG
574 throw runtime_error(getName()+" allocation of key structure failed");
575 }
349384bf 576
5498c0a9 577 auto e = std::unique_ptr<BIGNUM, void(*)(BIGNUM*)>(BN_bin2bn((unsigned char*)exponent.c_str(), exponent.length(), nullptr), BN_clear_free);
888bc297 578 if (!e) {
a41d80d1
RG
579 throw runtime_error(getName()+" error loading e value of public key");
580 }
5498c0a9 581 auto n = std::unique_ptr<BIGNUM, void(*)(BIGNUM*)>(BN_bin2bn((unsigned char*)modulus.c_str(), modulus.length(), nullptr), BN_clear_free);
888bc297 582 if (!n) {
a41d80d1
RG
583 throw runtime_error(getName()+" error loading n value of public key");
584 }
8ca3ea33 585
5498c0a9
RG
586 RSA_set0_key(key.get(), n.release(), e.release(), nullptr);
587 d_key = std::move(key);
a41d80d1 588}
7581a35b 589
74d83458 590#ifdef HAVE_LIBCRYPTO_ECDSA
7581a35b
KM
591class OpenSSLECDSADNSCryptoKeyEngine : public DNSCryptoKeyEngine
592{
593public:
5498c0a9 594 explicit OpenSSLECDSADNSCryptoKeyEngine(unsigned int algo) : DNSCryptoKeyEngine(algo), d_eckey(std::unique_ptr<EC_KEY, void(*)(EC_KEY*)>(EC_KEY_new(), EC_KEY_free)), d_ecgroup(std::unique_ptr<EC_GROUP, void(*)(EC_GROUP*)>(nullptr, EC_GROUP_clear_free))
c00bd468 595 {
7581a35b
KM
596
597 int ret = RAND_status();
598 if (ret != 1) {
599 throw runtime_error(getName()+" insufficient entropy");
600 }
601
5498c0a9 602 if (!d_eckey) {
7581a35b
KM
603 throw runtime_error(getName()+" allocation of key structure failed");
604 }
605
606 if(d_algorithm == 13) {
5498c0a9 607 d_ecgroup = std::unique_ptr<EC_GROUP, void(*)(EC_GROUP*)>(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1), EC_GROUP_clear_free);
7581a35b
KM
608 d_len = 32;
609 } else if (d_algorithm == 14) {
5498c0a9 610 d_ecgroup = std::unique_ptr<EC_GROUP, void(*)(EC_GROUP*)>(EC_GROUP_new_by_curve_name(NID_secp384r1), EC_GROUP_clear_free);
7581a35b
KM
611 d_len = 48;
612 } else {
613 throw runtime_error(getName()+" unknown algorithm "+std::to_string(d_algorithm));
614 }
b141d89b 615
5498c0a9 616 if (!d_ecgroup) {
7581a35b
KM
617 throw runtime_error(getName()+" allocation of group structure failed");
618 }
619
5498c0a9 620 ret = EC_KEY_set_group(d_eckey.get(), d_ecgroup.get());
7581a35b
KM
621 if (ret != 1) {
622 throw runtime_error(getName()+" setting key group failed");
623 }
7581a35b
KM
624 }
625
626 ~OpenSSLECDSADNSCryptoKeyEngine()
627 {
7581a35b
KM
628 }
629
d12b259b
CH
630 string getName() const override { return "OpenSSL ECDSA"; }
631 int getBits() const override { return d_len << 3; }
7581a35b 632
d12b259b
CH
633 void create(unsigned int bits) override;
634 storvector_t convertToISCVector() const override;
635 std::string hash(const std::string& hash) const override;
636 std::string sign(const std::string& hash) const override;
637 bool verify(const std::string& hash, const std::string& signature) const override;
638 std::string getPubKeyHash() const override;
639 std::string getPublicKeyString() const override;
640 void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) override;
641 void fromPublicKeyString(const std::string& content) override;
ac3f3893 642 bool checkKey(vector<string> *errorMessages) const override;
7581a35b 643
e69c2dac 644 static std::shared_ptr<DNSCryptoKeyEngine> maker(unsigned int algorithm)
7581a35b 645 {
e69c2dac 646 return std::make_shared<OpenSSLECDSADNSCryptoKeyEngine>(algorithm);
7581a35b
KM
647 }
648
649private:
650 unsigned int d_len;
651
5498c0a9
RG
652 std::unique_ptr<EC_KEY, void(*)(EC_KEY*)> d_eckey;
653 std::unique_ptr<EC_GROUP, void(*)(EC_GROUP*)> d_ecgroup;
7581a35b
KM
654};
655
656
657void OpenSSLECDSADNSCryptoKeyEngine::create(unsigned int bits)
658{
659 if (bits >> 3 != d_len) {
660 throw runtime_error(getName()+" unknown key length of "+std::to_string(bits)+" bits requested");
661 }
662
5498c0a9 663 int res = EC_KEY_generate_key(d_eckey.get());
7581a35b
KM
664 if (res == 0) {
665 throw runtime_error(getName()+" key generation failed");
666 }
667}
668
669
670DNSCryptoKeyEngine::storvector_t OpenSSLECDSADNSCryptoKeyEngine::convertToISCVector() const
671{
672 storvector_t storvect;
673 string algorithm;
674
675 if(d_algorithm == 13)
676 algorithm = "13 (ECDSAP256SHA256)";
677 else if(d_algorithm == 14)
678 algorithm = "14 (ECDSAP384SHA384)";
679 else
680 algorithm = " ? (?)";
681
682 storvect.push_back(make_pair("Algorithm", algorithm));
683
5498c0a9
RG
684 const BIGNUM *key = EC_KEY_get0_private_key(d_eckey.get());
685 if (key == nullptr) {
7581a35b
KM
686 throw runtime_error(getName()+" private key not set");
687 }
688
e5f0dee1
RG
689 std::string tmp;
690 tmp.resize(BN_num_bytes(key));
691 int len = BN_bn2bin(key, reinterpret_cast<unsigned char*>(&tmp.at(0)));
7581a35b
KM
692
693 string prefix;
694 if (d_len - len)
695 prefix.append(d_len - len, 0x00);
696
e5f0dee1 697 storvect.push_back(make_pair("PrivateKey", prefix + tmp));
7581a35b
KM
698
699 return storvect;
700}
701
702
703std::string OpenSSLECDSADNSCryptoKeyEngine::hash(const std::string& orig) const
704{
705 if(getBits() == 256) {
41426b6f
AT
706 unsigned char l_hash[SHA256_DIGEST_LENGTH];
707 SHA256((unsigned char*) orig.c_str(), orig.length(), l_hash);
708 return string((char*)l_hash, sizeof(l_hash));
7581a35b
KM
709 }
710 else if(getBits() == 384) {
41426b6f
AT
711 unsigned char l_hash[SHA384_DIGEST_LENGTH];
712 SHA384((unsigned char*) orig.c_str(), orig.length(), l_hash);
713 return string((char*)l_hash, sizeof(l_hash));
7581a35b
KM
714 }
715
716 throw runtime_error(getName()+" does not support a hash size of "+std::to_string(getBits())+" bits");
717}
718
719
720std::string OpenSSLECDSADNSCryptoKeyEngine::sign(const std::string& msg) const
721{
41426b6f 722 string l_hash = this->hash(msg);
7581a35b 723
41426b6f 724 auto signature = std::unique_ptr<ECDSA_SIG, void(*)(ECDSA_SIG*)>(ECDSA_do_sign((unsigned char*) l_hash.c_str(), l_hash.length(), d_eckey.get()), ECDSA_SIG_free);
5498c0a9 725 if (!signature) {
7581a35b
KM
726 throw runtime_error(getName()+" failed to generate signature");
727 }
728
729 string ret;
e5f0dee1
RG
730 std::string tmp;
731 tmp.resize(d_len);
7581a35b 732
888bc297 733 const BIGNUM *pr, *ps;
5498c0a9 734 ECDSA_SIG_get0(signature.get(), &pr, &ps);
e5f0dee1 735 int len = BN_bn2bin(pr, reinterpret_cast<unsigned char*>(&tmp.at(0)));
7581a35b
KM
736 if (d_len - len)
737 ret.append(d_len - len, 0x00);
e5f0dee1 738 ret.append(&tmp.at(0), len);
7581a35b 739
e5f0dee1 740 len = BN_bn2bin(ps, reinterpret_cast<unsigned char*>(&tmp.at(0)));
7581a35b
KM
741 if (d_len - len)
742 ret.append(d_len - len, 0x00);
e5f0dee1 743 ret.append(&tmp.at(0), len);
7581a35b 744
7581a35b
KM
745 return ret;
746}
747
748
749bool OpenSSLECDSADNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const
750{
751 if (signature.length() != (d_len * 2)) {
752 throw runtime_error(getName()+" invalid signature size "+std::to_string(signature.length()));
753 }
754
41426b6f 755 string l_hash = this->hash(msg);
7581a35b 756
5498c0a9
RG
757 auto sig = std::unique_ptr<ECDSA_SIG, void(*)(ECDSA_SIG*)>(ECDSA_SIG_new(), ECDSA_SIG_free);
758 if (!sig) {
7581a35b
KM
759 throw runtime_error(getName()+" allocation of signature structure failed");
760 }
761
5498c0a9
RG
762 auto r = std::unique_ptr<BIGNUM, void(*)(BIGNUM*)>(BN_bin2bn((unsigned char*) signature.c_str(), d_len, nullptr), BN_clear_free);
763 auto s = std::unique_ptr<BIGNUM, void(*)(BIGNUM*)>(BN_bin2bn((unsigned char*) signature.c_str() + d_len, d_len, nullptr), BN_clear_free);
888bc297 764 if (!r || !s) {
7581a35b
KM
765 throw runtime_error(getName()+" invalid signature");
766 }
767
5498c0a9 768 ECDSA_SIG_set0(sig.get(), r.release(), s.release());
41426b6f 769 int ret = ECDSA_do_verify((unsigned char*) l_hash.c_str(), l_hash.length(), sig.get(), d_eckey.get());
7581a35b
KM
770
771 if (ret == -1){
772 throw runtime_error(getName()+" verify error");
773 }
774
775 return (ret == 1);
776}
777
778
779std::string OpenSSLECDSADNSCryptoKeyEngine::getPubKeyHash() const
780{
781 string pubKey = getPublicKeyString();
41426b6f
AT
782 unsigned char l_hash[SHA_DIGEST_LENGTH];
783 SHA1((unsigned char*) pubKey.c_str(), pubKey.length(), l_hash);
784 return string((char*) l_hash, sizeof(l_hash));
7581a35b
KM
785}
786
787
788std::string OpenSSLECDSADNSCryptoKeyEngine::getPublicKeyString() const
789{
e5f0dee1
RG
790 std::string binaryPoint;
791 binaryPoint.resize((d_len * 2) + 1);
7581a35b 792
5498c0a9 793 int ret = EC_POINT_point2oct(d_ecgroup.get(), EC_KEY_get0_public_key(d_eckey.get()), POINT_CONVERSION_UNCOMPRESSED, reinterpret_cast<unsigned char*>(&binaryPoint.at(0)), binaryPoint.size(), nullptr);
7581a35b
KM
794 if (ret == 0) {
795 throw runtime_error(getName()+" exporting point to binary failed");
796 }
797
798 /* we skip the first byte as the other backends use
799 raw field elements, as opposed to the format described in
800 SEC1: "2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion" */
e5f0dee1
RG
801 binaryPoint.erase(0, 1);
802 return binaryPoint;
7581a35b
KM
803}
804
805
806void OpenSSLECDSADNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap)
807{
808 drc.d_algorithm = atoi(stormap["algorithm"].c_str());
809
810 if (drc.d_algorithm != d_algorithm) {
811 throw runtime_error(getName()+" tried to feed an algorithm "+std::to_string(drc.d_algorithm)+" to a "+std::to_string(d_algorithm)+" key");
812 }
813
814 string privateKey = stormap["privatekey"];
815
5498c0a9
RG
816 auto prv_key = std::unique_ptr<BIGNUM, void(*)(BIGNUM*)>(BN_bin2bn((unsigned char*) privateKey.c_str(), privateKey.length(), nullptr), BN_clear_free);
817 if (!prv_key) {
7581a35b
KM
818 throw runtime_error(getName()+" reading private key from binary failed");
819 }
820
5498c0a9 821 int ret = EC_KEY_set_private_key(d_eckey.get(), prv_key.get());
7581a35b 822 if (ret != 1) {
7581a35b
KM
823 throw runtime_error(getName()+" setting private key failed");
824 }
825
5498c0a9
RG
826 auto pub_key = std::unique_ptr<EC_POINT, void(*)(EC_POINT*)>(EC_POINT_new(d_ecgroup.get()), EC_POINT_free);
827 if (!pub_key) {
7581a35b
KM
828 throw runtime_error(getName()+" allocation of public key point failed");
829 }
830
5498c0a9 831 ret = EC_POINT_mul(d_ecgroup.get(), pub_key.get(), prv_key.get(), nullptr, nullptr, nullptr);
7581a35b 832 if (ret != 1) {
7581a35b
KM
833 throw runtime_error(getName()+" computing public key from private failed");
834 }
835
5498c0a9 836 ret = EC_KEY_set_public_key(d_eckey.get(), pub_key.get());
7581a35b 837 if (ret != 1) {
7581a35b
KM
838 throw runtime_error(getName()+" setting public key failed");
839 }
7581a35b
KM
840}
841
ac3f3893 842bool OpenSSLECDSADNSCryptoKeyEngine::checkKey(vector<string> *errorMessages) const
8ca3ea33 843{
ac3f3893 844 bool retval = true;
128bc6d2 845 if (EC_KEY_check_key(d_eckey.get()) != 1) {
ac3f3893
PL
846 retval = false;
847 if (errorMessages != nullptr) {
848 errorMessages->push_back(ERR_reason_error_string(ERR_get_error()));
849 }
850 }
851 return retval;
8ca3ea33 852}
7581a35b
KM
853
854void OpenSSLECDSADNSCryptoKeyEngine::fromPublicKeyString(const std::string& input)
855{
856 /* uncompressed point, from SEC1:
857 "2.3.4 Octet-String-to-Elliptic-Curve-Point Conversion" */
858 string ecdsaPoint= "\x04";
859 ecdsaPoint.append(input);
860
5498c0a9
RG
861 auto pub_key = std::unique_ptr<EC_POINT, void(*)(EC_POINT*)>(EC_POINT_new(d_ecgroup.get()), EC_POINT_free);
862 if (!pub_key) {
7581a35b
KM
863 throw runtime_error(getName()+" allocation of point structure failed");
864 }
865
5498c0a9 866 int ret = EC_POINT_oct2point(d_ecgroup.get(), pub_key.get(), (unsigned char*) ecdsaPoint.c_str(), ecdsaPoint.length(), nullptr);
7581a35b
KM
867 if (ret != 1) {
868 throw runtime_error(getName()+" reading ECP point from binary failed");
869 }
870
5498c0a9 871 ret = EC_KEY_set_private_key(d_eckey.get(), nullptr);
7581a35b 872 if (ret == 1) {
7581a35b
KM
873 throw runtime_error(getName()+" setting private key failed");
874 }
875
5498c0a9 876 ret = EC_KEY_set_public_key(d_eckey.get(), pub_key.get());
7581a35b 877 if (ret != 1) {
7581a35b
KM
878 throw runtime_error(getName()+" setting public key failed");
879 }
7581a35b 880}
de4e1d0d 881#endif
7581a35b 882
439974d7
PL
883#ifdef HAVE_LIBCRYPTO_EDDSA
884class OpenSSLEDDSADNSCryptoKeyEngine : public DNSCryptoKeyEngine
885{
886public:
5498c0a9 887 explicit OpenSSLEDDSADNSCryptoKeyEngine(unsigned int algo) : DNSCryptoKeyEngine(algo), d_edkey(std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)>(nullptr, EVP_PKEY_free))
439974d7
PL
888 {
889
890 int ret = RAND_status();
891 if (ret != 1) {
892 throw runtime_error(getName()+" insufficient entropy");
893 }
894
9c1e4067 895#ifdef HAVE_LIBCRYPTO_ED25519
439974d7
PL
896 if(d_algorithm == 15) {
897 d_len = 32;
898 d_id = NID_ED25519;
9c1e4067
PL
899 }
900#endif
901#ifdef HAVE_LIBCRYPTO_ED448
902 if (d_algorithm == 16) {
439974d7
PL
903 d_len = 57;
904 d_id = NID_ED448;
9c1e4067
PL
905 }
906#endif
907 if (d_len == 0) {
439974d7
PL
908 throw runtime_error(getName()+" unknown algorithm "+std::to_string(d_algorithm));
909 }
439974d7
PL
910 }
911
912 ~OpenSSLEDDSADNSCryptoKeyEngine()
913 {
439974d7
PL
914 }
915
916 string getName() const override { return "OpenSSL EDDSA"; }
7f85e580 917 int getBits() const override { return d_len << 3; }
439974d7
PL
918
919 void create(unsigned int bits) override;
920 storvector_t convertToISCVector() const override;
8da77aa0 921 std::string sign(const std::string& msg) const override;
439974d7
PL
922 bool verify(const std::string& msg, const std::string& signature) const override;
923 std::string getPubKeyHash() const override;
924 std::string getPublicKeyString() const override;
925 void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) override;
926 void fromPublicKeyString(const std::string& content) override;
128bc6d2 927 bool checkKey(vector<string> *errorMessages) const override;
439974d7
PL
928
929 static std::shared_ptr<DNSCryptoKeyEngine> maker(unsigned int algorithm)
930 {
931 return std::make_shared<OpenSSLEDDSADNSCryptoKeyEngine>(algorithm);
932 }
933
934private:
9c1e4067
PL
935 size_t d_len{0};
936 int d_id{0};
439974d7 937
5498c0a9 938 std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)> d_edkey;
439974d7 939};
7581a35b 940
128bc6d2 941bool OpenSSLEDDSADNSCryptoKeyEngine::checkKey(vector<string> *errorMessages) const
439974d7 942{
5498c0a9 943 return (d_edkey ? true : false);
439974d7
PL
944}
945
946void OpenSSLEDDSADNSCryptoKeyEngine::create(unsigned int bits)
947{
5498c0a9
RG
948 auto pctx = std::unique_ptr<EVP_PKEY_CTX, void(*)(EVP_PKEY_CTX*)>(EVP_PKEY_CTX_new_id(d_id, nullptr), EVP_PKEY_CTX_free);
949 if (!pctx) {
439974d7
PL
950 throw runtime_error(getName()+" context initialization failed");
951 }
5498c0a9 952 if (EVP_PKEY_keygen_init(pctx.get()) < 1) {
aa2e4010
PL
953 throw runtime_error(getName()+" keygen initialization failed");
954 }
5498c0a9
RG
955 EVP_PKEY* newKey = nullptr;
956 if (EVP_PKEY_keygen(pctx.get(), &newKey) < 1) {
439974d7
PL
957 throw runtime_error(getName()+" key generation failed");
958 }
5498c0a9 959 d_edkey = std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)>(newKey, EVP_PKEY_free);
7581a35b 960}
439974d7
PL
961
962DNSCryptoKeyEngine::storvector_t OpenSSLEDDSADNSCryptoKeyEngine::convertToISCVector() const
963{
964 storvector_t storvect;
965 string algorithm;
966
9c1e4067
PL
967#ifdef HAVE_LIBCRYPTO_ED25519
968 if(d_algorithm == 15) {
439974d7 969 algorithm = "15 (ED25519)";
9c1e4067 970 }
de4e1d0d 971#endif
9c1e4067
PL
972#ifdef HAVE_LIBCRYPTO_ED448
973 if(d_algorithm == 16) {
439974d7 974 algorithm = "16 (ED448)";
9c1e4067
PL
975 }
976#endif
977 if (algorithm.empty()) {
439974d7 978 algorithm = " ? (?)";
9c1e4067 979 }
439974d7
PL
980
981 storvect.push_back(make_pair("Algorithm", algorithm));
982
983 string buf;
984 size_t len = d_len;
985 buf.resize(len);
5498c0a9 986 if (EVP_PKEY_get_raw_private_key(d_edkey.get(), reinterpret_cast<unsigned char*>(&buf.at(0)), &len) < 1) {
aa2e4010
PL
987 throw runtime_error(getName() + " Could not get private key from d_edkey");
988 }
439974d7
PL
989 storvect.push_back(make_pair("PrivateKey", buf));
990 return storvect;
991}
992
993std::string OpenSSLEDDSADNSCryptoKeyEngine::sign(const std::string& msg) const
994{
5498c0a9
RG
995 auto mdctx = std::unique_ptr<EVP_MD_CTX, void(*)(EVP_MD_CTX*)>(EVP_MD_CTX_new(), EVP_MD_CTX_free);
996 if (!mdctx) {
aa2e4010
PL
997 throw runtime_error(getName()+" MD context initialization failed");
998 }
5498c0a9 999 if(EVP_DigestSignInit(mdctx.get(), nullptr, nullptr, nullptr, d_edkey.get()) < 1) {
439974d7
PL
1000 throw runtime_error(getName()+" unable to initialize signer");
1001 }
1002
439974d7 1003 string msgToSign = msg;
439974d7 1004
b4d4e25c
PL
1005 size_t siglen = d_len * 2;
1006 string signature;
439974d7
PL
1007 signature.resize(siglen);
1008
5498c0a9 1009 if (EVP_DigestSign(mdctx.get(),
439974d7
PL
1010 reinterpret_cast<unsigned char*>(&signature.at(0)), &siglen,
1011 reinterpret_cast<unsigned char*>(&msgToSign.at(0)), msgToSign.length()) < 1) {
1012 throw runtime_error(getName()+" signing error");
1013 }
5498c0a9 1014
439974d7
PL
1015 return signature;
1016}
1017
1018bool OpenSSLEDDSADNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const
1019{
5498c0a9
RG
1020 auto mdctx = std::unique_ptr<EVP_MD_CTX, void(*)(EVP_MD_CTX*)>(EVP_MD_CTX_new(), EVP_MD_CTX_free);
1021 if (!mdctx) {
aa2e4010
PL
1022 throw runtime_error(getName()+" MD context initialization failed");
1023 }
5498c0a9 1024 if(EVP_DigestVerifyInit(mdctx.get(), nullptr, nullptr, nullptr, d_edkey.get()) < 1) {
aa2e4010 1025 throw runtime_error(getName()+" unable to initialize signer");
439974d7
PL
1026 }
1027
1028 string checkSignature = signature;
1029 string checkMsg = msg;
1030
5498c0a9 1031 auto r = EVP_DigestVerify(mdctx.get(),
439974d7
PL
1032 reinterpret_cast<unsigned char*>(&checkSignature.at(0)), checkSignature.length(),
1033 reinterpret_cast<unsigned char*>(&checkMsg.at(0)), checkMsg.length());
1034 if (r < 0) {
1035 throw runtime_error(getName()+" verification failure");
1036 }
1037
1038 return (r == 1);
1039}
1040
1041std::string OpenSSLEDDSADNSCryptoKeyEngine::getPubKeyHash() const
1042{
1043 return this->getPublicKeyString();
1044}
1045
1046std::string OpenSSLEDDSADNSCryptoKeyEngine::getPublicKeyString() const
1047{
1048 string buf;
1049 size_t len = d_len;
1050 buf.resize(len);
5498c0a9 1051 if (EVP_PKEY_get_raw_public_key(d_edkey.get(), reinterpret_cast<unsigned char*>(&buf.at(0)), &len) < 1) {
e6d63a77 1052 throw std::runtime_error(getName() + " unable to get public key from key struct");
439974d7
PL
1053 }
1054 return buf;
1055}
1056
1057void OpenSSLEDDSADNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) {
1058 drc.d_algorithm = atoi(stormap["algorithm"].c_str());
1059 if (drc.d_algorithm != d_algorithm) {
1060 throw runtime_error(getName()+" tried to feed an algorithm "+std::to_string(drc.d_algorithm)+" to a "+std::to_string(d_algorithm)+" key");
1061 }
7581a35b 1062
5498c0a9
RG
1063 d_edkey = std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)>(EVP_PKEY_new_raw_private_key(d_id, nullptr, reinterpret_cast<unsigned char*>(&stormap["privatekey"].at(0)), stormap["privatekey"].length()), EVP_PKEY_free);
1064 if (!d_edkey) {
439974d7
PL
1065 throw std::runtime_error(getName() + " could not create key structure from private key");
1066 }
439974d7
PL
1067}
1068
1069void OpenSSLEDDSADNSCryptoKeyEngine::fromPublicKeyString(const std::string& content)
1070{
7270ecca
PL
1071 if (content.length() != d_len) {
1072 throw runtime_error(getName() + " wrong public key length for algorithm " + std::to_string(d_algorithm));
439974d7
PL
1073 }
1074
7270ecca
PL
1075 const unsigned char* raw = reinterpret_cast<const unsigned char*>(content.c_str());
1076
5498c0a9
RG
1077 d_edkey = std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)>(EVP_PKEY_new_raw_public_key(d_id, nullptr, raw, d_len), EVP_PKEY_free);
1078 if (!d_edkey) {
439974d7
PL
1079 throw runtime_error(getName()+" allocation of public key structure failed");
1080 }
439974d7
PL
1081}
1082#endif // HAVE_LIBCRYPTO_EDDSA
7581a35b
KM
1083
1084namespace {
1085 struct LoaderStruct
1086 {
1087 LoaderStruct()
1088 {
a41d80d1
RG
1089 DNSCryptoKeyEngine::report(5, &OpenSSLRSADNSCryptoKeyEngine::maker);
1090 DNSCryptoKeyEngine::report(7, &OpenSSLRSADNSCryptoKeyEngine::maker);
1091 DNSCryptoKeyEngine::report(8, &OpenSSLRSADNSCryptoKeyEngine::maker);
1092 DNSCryptoKeyEngine::report(10, &OpenSSLRSADNSCryptoKeyEngine::maker);
74d83458 1093#ifdef HAVE_LIBCRYPTO_ECDSA
7581a35b
KM
1094 DNSCryptoKeyEngine::report(13, &OpenSSLECDSADNSCryptoKeyEngine::maker);
1095 DNSCryptoKeyEngine::report(14, &OpenSSLECDSADNSCryptoKeyEngine::maker);
439974d7
PL
1096#endif
1097#ifdef HAVE_LIBCRYPTO_ED25519
1098 DNSCryptoKeyEngine::report(15, &OpenSSLEDDSADNSCryptoKeyEngine::maker);
1099#endif
1100#ifdef HAVE_LIBCRYPTO_ED448
1101 DNSCryptoKeyEngine::report(16, &OpenSSLEDDSADNSCryptoKeyEngine::maker);
de4e1d0d 1102#endif
7581a35b
KM
1103 }
1104 } loaderOpenSSL;
1105}