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  */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include <openssl/obj_mac.h>
26 #ifdef HAVE_LIBCRYPTO_ECDSA
27 #include <openssl/ecdsa.h>
28 #endif
29 #if defined(HAVE_LIBCRYPTO_ED25519) || defined(HAVE_LIBCRYPTO_ED448)
30 #include <openssl/evp.h>
31 #endif
32 #include <openssl/bn.h>
33 #include <openssl/sha.h>
34 #include <openssl/rand.h>
35 #include <openssl/rsa.h>
36 #include <openssl/opensslv.h>
37 #include <openssl/err.h>
38 #include "opensslsigners.hh"
39 #include "dnssecinfra.hh"
40 #include "dnsseckeeper.hh"
41 
42 #if (OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2090100fL)
43 /* OpenSSL < 1.1.0 needs support for threading/locking in the calling application. */
44 
45 #include "lock.hh"
46 static std::vector<std::mutex> openssllocks;
47 
48 extern "C" {
openssl_pthreads_locking_callback(int mode,int type,const char * file,int line)49 static void openssl_pthreads_locking_callback(int mode, int type, const char *file, int line)
50 {
51   if (mode & CRYPTO_LOCK) {
52     openssllocks.at(type).lock();
53 
54   } else {
55     openssllocks.at(type).unlock();
56   }
57 }
58 
openssl_pthreads_id_callback(void)59 static unsigned long openssl_pthreads_id_callback(void)
60 {
61   return (unsigned long)pthread_self();
62 }
63 }
64 
openssl_thread_setup()65 void openssl_thread_setup()
66 {
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);
70 }
71 
openssl_thread_cleanup()72 void openssl_thread_cleanup()
73 {
74   CRYPTO_set_locking_callback(nullptr);
75   openssllocks.clear();
76 }
77 
78 #ifndef HAVE_RSA_GET0_KEY
79 /* those symbols are defined in LibreSSL 2.7.0+ */
80 /* compat helpers. These DO NOT do any of the checking that the libssl 1.1 functions do. */
RSA_get0_key(const RSA * rsakey,const BIGNUM ** n,const BIGNUM ** e,const BIGNUM ** d)81 static 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 
RSA_set0_key(RSA * rsakey,BIGNUM * n,BIGNUM * e,BIGNUM * d)87 static 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 
RSA_get0_factors(const RSA * rsakey,const BIGNUM ** p,const BIGNUM ** q)103 static inline void RSA_get0_factors(const RSA* rsakey, const BIGNUM** p, const BIGNUM** q) {
104   *p = rsakey->p;
105   *q = rsakey->q;
106 }
107 
RSA_set0_factors(RSA * rsakey,BIGNUM * p,BIGNUM * q)108 static 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 
RSA_get0_crt_params(const RSA * rsakey,const BIGNUM ** dmp1,const BIGNUM ** dmq1,const BIGNUM ** iqmp)116 static 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 
RSA_set0_crt_params(RSA * rsakey,BIGNUM * dmp1,BIGNUM * dmq1,BIGNUM * iqmp)122 static 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 
132 #ifdef HAVE_LIBCRYPTO_ECDSA
ECDSA_SIG_get0(const ECDSA_SIG * signature,const BIGNUM ** pr,const BIGNUM ** ps)133 static 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 
ECDSA_SIG_set0(ECDSA_SIG * signature,BIGNUM * pr,BIGNUM * ps)138 static 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 }
145 #endif /* HAVE_LIBCRYPTO_ECDSA */
146 
147 #endif /* HAVE_RSA_GET0_KEY */
148 
149 #else
openssl_thread_setup()150 void openssl_thread_setup() {}
openssl_thread_cleanup()151 void openssl_thread_cleanup() {}
152 #endif
153 
154 
155 /* seeding PRNG */
156 
openssl_seed()157 void 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 
172 class OpenSSLRSADNSCryptoKeyEngine : public DNSCryptoKeyEngine
173 {
174 public:
OpenSSLRSADNSCryptoKeyEngine(unsigned int algo)175   explicit OpenSSLRSADNSCryptoKeyEngine(unsigned int algo): DNSCryptoKeyEngine(algo), d_key(std::unique_ptr<RSA, void(*)(RSA*)>(nullptr, RSA_free))
176   {
177     int ret = RAND_status();
178     if (ret != 1) {
179       throw runtime_error(getName()+" insufficient entropy");
180     }
181   }
182 
~OpenSSLRSADNSCryptoKeyEngine()183   ~OpenSSLRSADNSCryptoKeyEngine()
184   {
185   }
186 
getName() const187   string getName() const override { return "OpenSSL RSA"; }
getBits() const188   int getBits() const override { return RSA_size(d_key.get()) << 3; }
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   std::unique_ptr<BIGNUM, void(*)(BIGNUM*)>parse(std::map<std::string, std::string>& stormap, const std::string& key) const;
198   void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) override;
199   void fromPublicKeyString(const std::string& content) override;
200   bool checkKey(vector<string> *errorMessages) const override;
201 
maker(unsigned int algorithm)202   static std::unique_ptr<DNSCryptoKeyEngine> maker(unsigned int algorithm)
203   {
204     return make_unique<OpenSSLRSADNSCryptoKeyEngine>(algorithm);
205   }
206 
207 private:
208   static int hashSizeToKind(size_t hashSize);
209 
210   std::unique_ptr<RSA, void(*)(RSA*)> d_key;
211 };
212 
213 
create(unsigned int bits)214 void OpenSSLRSADNSCryptoKeyEngine::create(unsigned int bits)
215 {
216   // When changing the bitsizes, also edit them in ::checkKey
217   if ((d_algorithm == DNSSECKeeper::RSASHA1 || d_algorithm == DNSSECKeeper::RSASHA1NSEC3SHA1) && (bits < 512 || bits > 4096)) {
218     /* RFC3110 */
219     throw runtime_error(getName()+" RSASHA1 key generation failed for invalid bits size " + std::to_string(bits));
220   }
221   if (d_algorithm == DNSSECKeeper::RSASHA256 && (bits < 512 || bits > 4096)) {
222     /* RFC5702 */
223     throw runtime_error(getName()+" RSASHA256 key generation failed for invalid bits size " + std::to_string(bits));
224   }
225   if (d_algorithm == DNSSECKeeper::RSASHA512 && (bits < 1024 || bits > 4096)) {
226     /* RFC5702 */
227     throw runtime_error(getName()+" RSASHA512 key generation failed for invalid bits size " + std::to_string(bits));
228   }
229 
230   auto e = std::unique_ptr<BIGNUM, void(*)(BIGNUM*)>(BN_new(), BN_clear_free);
231   if (!e) {
232     throw runtime_error(getName()+" key generation failed, unable to allocate e");
233   }
234 
235   /* RSA_F4 is a public exponent value of 65537 */
236   int res = BN_set_word(e.get(), RSA_F4);
237 
238   if (res == 0) {
239     throw runtime_error(getName()+" key generation failed while setting e");
240   }
241 
242   auto key = std::unique_ptr<RSA, void(*)(RSA*)>(RSA_new(), RSA_free);
243   if (!key) {
244     throw runtime_error(getName()+" allocation of key structure failed");
245   }
246 
247   res = RSA_generate_key_ex(key.get(), bits, e.get(), nullptr);
248   if (res == 0) {
249     throw runtime_error(getName()+" key generation failed");
250   }
251 
252   d_key = std::move(key);
253 }
254 
255 
convertToISCVector() const256 DNSCryptoKeyEngine::storvector_t OpenSSLRSADNSCryptoKeyEngine::convertToISCVector() const
257 {
258   storvector_t storvect;
259   typedef vector<pair<string, const BIGNUM*> > outputs_t;
260   outputs_t outputs;
261   const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
262   RSA_get0_key(d_key.get(), &n, &e, &d);
263   RSA_get0_factors(d_key.get(), &p, &q);
264   RSA_get0_crt_params(d_key.get(), &dmp1, &dmq1, &iqmp);
265   outputs.push_back(make_pair("Modulus", n));
266   outputs.push_back(make_pair("PublicExponent", e));
267   outputs.push_back(make_pair("PrivateExponent", d));
268   outputs.push_back(make_pair("Prime1", p));
269   outputs.push_back(make_pair("Prime2", q));
270   outputs.push_back(make_pair("Exponent1", dmp1));
271   outputs.push_back(make_pair("Exponent2", dmq1));
272   outputs.push_back(make_pair("Coefficient", iqmp));
273 
274   string algorithm=std::to_string(d_algorithm);
275   switch(d_algorithm) {
276     case DNSSECKeeper::RSASHA1:
277     case DNSSECKeeper::RSASHA1NSEC3SHA1:
278       algorithm += " (RSASHA1)";
279       break;
280     case DNSSECKeeper::RSASHA256:
281       algorithm += " (RSASHA256)";
282       break;
283     case DNSSECKeeper::RSASHA512:
284       algorithm += " (RSASHA512)";
285       break;
286     default:
287       algorithm += " (?)";
288   }
289   storvect.push_back(make_pair("Algorithm", algorithm));
290 
291   for(const outputs_t::value_type& value :  outputs) {
292     std::string tmp;
293     tmp.resize(BN_num_bytes(value.second));
294     int len = BN_bn2bin(value.second, reinterpret_cast<unsigned char*>(&tmp.at(0)));
295     if (len >= 0) {
296       tmp.resize(len);
297       storvect.push_back(make_pair(value.first, tmp));
298     }
299   }
300 
301   return storvect;
302 }
303 
304 
hash(const std::string & orig) const305 std::string OpenSSLRSADNSCryptoKeyEngine::hash(const std::string& orig) const
306 {
307   if (d_algorithm == DNSSECKeeper::RSASHA1 || d_algorithm == DNSSECKeeper::RSASHA1NSEC3SHA1) {
308     unsigned char l_hash[SHA_DIGEST_LENGTH];
309     SHA1((unsigned char*) orig.c_str(), orig.length(), l_hash);
310     return string((char*) l_hash, sizeof(l_hash));
311   }
312   else if (d_algorithm == DNSSECKeeper::RSASHA256) {
313     unsigned char l_hash[SHA256_DIGEST_LENGTH];
314     SHA256((unsigned char*) orig.c_str(), orig.length(), l_hash);
315     return string((char*) l_hash, sizeof(l_hash));
316   }
317   else if (d_algorithm == DNSSECKeeper::RSASHA512) {
318     unsigned char l_hash[SHA512_DIGEST_LENGTH];
319     SHA512((unsigned char*) orig.c_str(), orig.length(), l_hash);
320     return string((char*) l_hash, sizeof(l_hash));
321   }
322 
323   throw runtime_error(getName()+" does not support hash operation for algorithm "+std::to_string(d_algorithm));
324 }
325 
hashSizeToKind(const size_t hashSize)326 int OpenSSLRSADNSCryptoKeyEngine::hashSizeToKind(const size_t hashSize)
327 {
328   switch(hashSize) {
329     case SHA_DIGEST_LENGTH:
330       return NID_sha1;
331     case SHA256_DIGEST_LENGTH:
332       return NID_sha256;
333     case SHA384_DIGEST_LENGTH:
334       return NID_sha384;
335     case SHA512_DIGEST_LENGTH:
336       return NID_sha512;
337     default:
338       throw runtime_error("OpenSSL RSA does not handle hash of size " + std::to_string(hashSize));
339   }
340 }
341 
sign(const std::string & msg) const342 std::string OpenSSLRSADNSCryptoKeyEngine::sign(const std::string& msg) const
343 {
344   string l_hash = this->hash(msg);
345   int hashKind = hashSizeToKind(l_hash.size());
346   std::string signature;
347   signature.resize(RSA_size(d_key.get()));
348   unsigned int signatureLen = 0;
349 
350   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());
351   if (res != 1) {
352     throw runtime_error(getName()+" failed to generate signature");
353   }
354 
355   signature.resize(signatureLen);
356   return signature;
357 }
358 
359 
verify(const std::string & msg,const std::string & signature) const360 bool OpenSSLRSADNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const
361 {
362   string l_hash = this->hash(msg);
363   int hashKind = hashSizeToKind(l_hash.size());
364 
365   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());
366 
367   return (ret == 1);
368 }
369 
370 
getPubKeyHash() const371 std::string OpenSSLRSADNSCryptoKeyEngine::getPubKeyHash() const
372 {
373   const BIGNUM *n, *e, *d;
374   RSA_get0_key(d_key.get(), &n, &e, &d);
375   std::vector<unsigned char> tmp;
376   tmp.resize(std::max(BN_num_bytes(e), BN_num_bytes(n)));
377   unsigned char l_hash[SHA_DIGEST_LENGTH];
378   SHA_CTX ctx;
379 
380   int res = SHA1_Init(&ctx);
381 
382   if (res != 1) {
383     throw runtime_error(getName()+" failed to init hash context for generating the public key hash");
384   }
385 
386   int len = BN_bn2bin(e, tmp.data());
387   res = SHA1_Update(&ctx, tmp.data(), len);
388   if (res != 1) {
389     throw runtime_error(getName()+" failed to update hash context for generating the public key hash");
390   }
391 
392   len = BN_bn2bin(n, tmp.data());
393   res = SHA1_Update(&ctx, tmp.data(), len);
394   if (res != 1) {
395     throw runtime_error(getName()+" failed to update hash context for generating the public key hash");
396   }
397 
398   res = SHA1_Final(l_hash, &ctx);
399   if (res != 1) {
400     throw runtime_error(getName()+" failed to finish hash context for generating the public key hash");
401   }
402 
403   return string((char*)l_hash, sizeof(l_hash));
404 }
405 
406 
getPublicKeyString() const407 std::string OpenSSLRSADNSCryptoKeyEngine::getPublicKeyString() const
408 {
409   const BIGNUM *n, *e, *d;
410   RSA_get0_key(d_key.get(), &n, &e, &d);
411   string keystring;
412   std::string tmp;
413   tmp.resize(std::max(BN_num_bytes(e), BN_num_bytes(n)));
414 
415   int len = BN_bn2bin(e, reinterpret_cast<unsigned char*>(&tmp.at(0)));
416   if (len < 255) {
417     keystring.assign(1, (char) (unsigned int) len);
418   } else {
419     keystring.assign(1, 0);
420     uint16_t tempLen = len;
421     tempLen = htons(tempLen);
422     keystring.append((char*)&tempLen, 2);
423   }
424   keystring.append(&tmp.at(0), len);
425 
426   len = BN_bn2bin(n, reinterpret_cast<unsigned char*>(&tmp.at(0)));
427   keystring.append(&tmp.at(0), len);
428 
429   return keystring;
430 }
431 
432 
parse(std::map<std::string,std::string> & stormap,const std::string & key) const433 std::unique_ptr<BIGNUM, void(*)(BIGNUM*)>OpenSSLRSADNSCryptoKeyEngine::parse(std::map<std::string, std::string>& stormap, const std::string& key) const
434 {
435   const std::string& v = stormap.at(key);
436   auto n = std::unique_ptr<BIGNUM, void(*)(BIGNUM*)>(BN_bin2bn(reinterpret_cast<const unsigned char*>(v.data()), v.length(), nullptr), BN_clear_free);
437 
438   if (!n) {
439     throw runtime_error(getName() + " parsing of " + key + " failed");
440   }
441   return n;
442 }
443 
fromISCMap(DNSKEYRecordContent & drc,std::map<std::string,std::string> & stormap)444 void OpenSSLRSADNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap)
445 {
446   auto key = std::unique_ptr<RSA, void(*)(RSA*)>(RSA_new(), RSA_free);
447   if (!key) {
448     throw runtime_error(getName() + " allocation of key structure failed");
449   }
450 
451   auto n = parse(stormap, "modulus");
452   auto e = parse(stormap, "publicexponent");
453   auto d = parse(stormap, "privateexponent");
454 
455   auto p = parse(stormap, "prime1");
456   auto q = parse(stormap, "prime2");
457 
458   auto dmp1 = parse(stormap, "exponent1");
459   auto dmq1 = parse(stormap, "exponent2");
460   auto iqmp = parse(stormap, "coefficient");
461 
462   drc.d_algorithm = pdns_stou(stormap["algorithm"]);
463 
464   if (drc.d_algorithm != d_algorithm) {
465     throw runtime_error(getName() + " tried to feed an algorithm " + std::to_string(drc.d_algorithm) + " to a " + std::to_string(d_algorithm) + " key");
466   }
467   // Everything OK, we're releasing ownership since the RSA_* functions want it
468   RSA_set0_key(key.get(), n.release(), e.release(), d.release());
469   RSA_set0_factors(key.get(), p.release(), q.release());
470   RSA_set0_crt_params(key.get(), dmp1.release(), dmq1.release(), iqmp.release());
471 
472   d_key = std::move(key);
473 }
474 
checkKey(vector<string> * errorMessages) const475 bool OpenSSLRSADNSCryptoKeyEngine::checkKey(vector<string> *errorMessages) const
476 {
477   bool retval = true;
478   // When changing the bitsizes, also edit them in ::create
479   if ((d_algorithm == DNSSECKeeper::RSASHA1 || d_algorithm == DNSSECKeeper::RSASHA1NSEC3SHA1 || d_algorithm == DNSSECKeeper::RSASHA256) && (getBits() < 512 || getBits()> 4096)) {
480     retval = false;
481     if (errorMessages != nullptr) {
482       errorMessages->push_back("key is " + std::to_string(getBits()) + " bytes, should be between 512 and 4096");
483     }
484   }
485   if (d_algorithm == DNSSECKeeper::RSASHA512 && (getBits() < 1024 || getBits() > 4096)) {
486     retval = false;
487     if (errorMessages != nullptr) {
488       errorMessages->push_back("key is " + std::to_string(getBits()) + " bytes, should be between 1024 and 4096");
489     }
490   }
491   if (RSA_check_key(d_key.get()) != 1) {
492     retval = false;
493     if (errorMessages != nullptr) {
494       errorMessages->push_back(ERR_reason_error_string(ERR_get_error()));
495     }
496   }
497   return retval;
498 }
499 
fromPublicKeyString(const std::string & input)500 void OpenSSLRSADNSCryptoKeyEngine::fromPublicKeyString(const std::string& input)
501 {
502   string exponent, modulus;
503   const size_t inputLen = input.length();
504   const unsigned char* raw = (const unsigned char*)input.c_str();
505 
506   if (inputLen < 1) {
507     throw runtime_error(getName()+" invalid input size for the public key");
508   }
509 
510   if (raw[0] != 0) {
511     const size_t exponentSize = raw[0];
512     if (inputLen < (exponentSize + 2)) {
513       throw runtime_error(getName()+" invalid input size for the public key");
514     }
515     exponent = input.substr(1, exponentSize);
516     modulus = input.substr(exponentSize + 1);
517   } else {
518     if (inputLen < 3) {
519       throw runtime_error(getName()+" invalid input size for the public key");
520     }
521     const size_t exponentSize = raw[1]*0xff + raw[2];
522     if (inputLen < (exponentSize + 4)) {
523       throw runtime_error(getName()+" invalid input size for the public key");
524     }
525     exponent = input.substr(3, exponentSize);
526     modulus = input.substr(exponentSize + 3);
527   }
528 
529   auto key = std::unique_ptr<RSA, void(*)(RSA*)>(RSA_new(), RSA_free);
530   if (!key) {
531     throw runtime_error(getName()+" allocation of key structure failed");
532   }
533 
534   auto e = std::unique_ptr<BIGNUM, void(*)(BIGNUM*)>(BN_bin2bn((unsigned char*)exponent.c_str(), exponent.length(), nullptr), BN_clear_free);
535   if (!e) {
536     throw runtime_error(getName()+" error loading e value of public key");
537   }
538   auto n = std::unique_ptr<BIGNUM, void(*)(BIGNUM*)>(BN_bin2bn((unsigned char*)modulus.c_str(), modulus.length(), nullptr), BN_clear_free);
539   if (!n) {
540     throw runtime_error(getName()+" error loading n value of public key");
541   }
542 
543   RSA_set0_key(key.get(), n.release(), e.release(), nullptr);
544   d_key = std::move(key);
545 }
546 
547 #ifdef HAVE_LIBCRYPTO_ECDSA
548 class OpenSSLECDSADNSCryptoKeyEngine : public DNSCryptoKeyEngine
549 {
550 public:
OpenSSLECDSADNSCryptoKeyEngine(unsigned int algo)551   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))
552   {
553 
554     int ret = RAND_status();
555     if (ret != 1) {
556       throw runtime_error(getName()+" insufficient entropy");
557     }
558 
559     if (!d_eckey) {
560       throw runtime_error(getName()+" allocation of key structure failed");
561     }
562 
563     if(d_algorithm == 13) {
564       d_ecgroup = std::unique_ptr<EC_GROUP, void(*)(EC_GROUP*)>(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1), EC_GROUP_clear_free);
565       d_len = 32;
566     } else if (d_algorithm == 14) {
567       d_ecgroup = std::unique_ptr<EC_GROUP, void(*)(EC_GROUP*)>(EC_GROUP_new_by_curve_name(NID_secp384r1), EC_GROUP_clear_free);
568       d_len = 48;
569     } else {
570       throw runtime_error(getName()+" unknown algorithm "+std::to_string(d_algorithm));
571     }
572 
573     if (!d_ecgroup) {
574       throw runtime_error(getName()+" allocation of group structure failed");
575     }
576 
577     ret = EC_KEY_set_group(d_eckey.get(), d_ecgroup.get());
578     if (ret != 1) {
579       throw runtime_error(getName()+" setting key group failed");
580     }
581   }
582 
~OpenSSLECDSADNSCryptoKeyEngine()583   ~OpenSSLECDSADNSCryptoKeyEngine()
584   {
585   }
586 
getName() const587   string getName() const override { return "OpenSSL ECDSA"; }
getBits() const588   int getBits() const override { return d_len << 3; }
589 
590   void create(unsigned int bits) override;
591   storvector_t convertToISCVector() const override;
592   std::string hash(const std::string& hash) const override;
593   std::string sign(const std::string& hash) const override;
594   bool verify(const std::string& hash, const std::string& signature) const override;
595   std::string getPubKeyHash() const override;
596   std::string getPublicKeyString() const override;
597   void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) override;
598   void fromPublicKeyString(const std::string& content) override;
599   bool checkKey(vector<string> *errorMessages) const override;
600 
maker(unsigned int algorithm)601   static std::unique_ptr<DNSCryptoKeyEngine> maker(unsigned int algorithm)
602   {
603     return make_unique<OpenSSLECDSADNSCryptoKeyEngine>(algorithm);
604   }
605 
606 private:
607   unsigned int d_len;
608 
609   std::unique_ptr<EC_KEY, void(*)(EC_KEY*)> d_eckey;
610   std::unique_ptr<EC_GROUP, void(*)(EC_GROUP*)> d_ecgroup;
611 };
612 
613 
create(unsigned int bits)614 void OpenSSLECDSADNSCryptoKeyEngine::create(unsigned int bits)
615 {
616   if (bits >> 3 != d_len) {
617     throw runtime_error(getName()+" unknown key length of "+std::to_string(bits)+" bits requested");
618   }
619 
620   int res = EC_KEY_generate_key(d_eckey.get());
621   if (res == 0) {
622     throw runtime_error(getName()+" key generation failed");
623   }
624 }
625 
626 
convertToISCVector() const627 DNSCryptoKeyEngine::storvector_t OpenSSLECDSADNSCryptoKeyEngine::convertToISCVector() const
628 {
629   storvector_t storvect;
630   string algorithm;
631 
632   if(d_algorithm == 13)
633     algorithm = "13 (ECDSAP256SHA256)";
634   else if(d_algorithm == 14)
635     algorithm = "14 (ECDSAP384SHA384)";
636   else
637     algorithm = " ? (?)";
638 
639   storvect.push_back(make_pair("Algorithm", algorithm));
640 
641   const BIGNUM *key = EC_KEY_get0_private_key(d_eckey.get());
642   if (key == nullptr) {
643     throw runtime_error(getName()+" private key not set");
644   }
645 
646   std::string tmp;
647   tmp.resize(BN_num_bytes(key));
648   int len = BN_bn2bin(key, reinterpret_cast<unsigned char*>(&tmp.at(0)));
649 
650   string prefix;
651   if (d_len - len)
652     prefix.append(d_len - len, 0x00);
653 
654   storvect.push_back(make_pair("PrivateKey", prefix + tmp));
655 
656   return storvect;
657 }
658 
659 
hash(const std::string & orig) const660 std::string OpenSSLECDSADNSCryptoKeyEngine::hash(const std::string& orig) const
661 {
662   if(getBits() == 256) {
663     unsigned char l_hash[SHA256_DIGEST_LENGTH];
664     SHA256((unsigned char*) orig.c_str(), orig.length(), l_hash);
665     return string((char*)l_hash, sizeof(l_hash));
666   }
667   else if(getBits() == 384) {
668     unsigned char l_hash[SHA384_DIGEST_LENGTH];
669     SHA384((unsigned char*) orig.c_str(), orig.length(), l_hash);
670     return string((char*)l_hash, sizeof(l_hash));
671   }
672 
673   throw runtime_error(getName()+" does not support a hash size of "+std::to_string(getBits())+" bits");
674 }
675 
676 
sign(const std::string & msg) const677 std::string OpenSSLECDSADNSCryptoKeyEngine::sign(const std::string& msg) const
678 {
679   string l_hash = this->hash(msg);
680 
681   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);
682   if (!signature) {
683     throw runtime_error(getName()+" failed to generate signature");
684   }
685 
686   string ret;
687   std::string tmp;
688   tmp.resize(d_len);
689 
690   const BIGNUM *pr, *ps;
691   ECDSA_SIG_get0(signature.get(), &pr, &ps);
692   int len = BN_bn2bin(pr, reinterpret_cast<unsigned char*>(&tmp.at(0)));
693   if (d_len - len)
694     ret.append(d_len - len, 0x00);
695   ret.append(&tmp.at(0), len);
696 
697   len = BN_bn2bin(ps, reinterpret_cast<unsigned char*>(&tmp.at(0)));
698   if (d_len - len)
699     ret.append(d_len - len, 0x00);
700   ret.append(&tmp.at(0), len);
701 
702   return ret;
703 }
704 
705 
verify(const std::string & msg,const std::string & signature) const706 bool OpenSSLECDSADNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const
707 {
708   if (signature.length() != (d_len * 2)) {
709     throw runtime_error(getName()+" invalid signature size "+std::to_string(signature.length()));
710   }
711 
712   string l_hash = this->hash(msg);
713 
714   auto sig = std::unique_ptr<ECDSA_SIG, void(*)(ECDSA_SIG*)>(ECDSA_SIG_new(), ECDSA_SIG_free);
715   if (!sig) {
716     throw runtime_error(getName()+" allocation of signature structure failed");
717   }
718 
719   auto r = std::unique_ptr<BIGNUM, void(*)(BIGNUM*)>(BN_bin2bn((unsigned char*) signature.c_str(), d_len, nullptr), BN_clear_free);
720   auto s = std::unique_ptr<BIGNUM, void(*)(BIGNUM*)>(BN_bin2bn((unsigned char*) signature.c_str() + d_len, d_len, nullptr), BN_clear_free);
721   if (!r || !s) {
722     throw runtime_error(getName()+" invalid signature");
723   }
724 
725   ECDSA_SIG_set0(sig.get(), r.release(), s.release());
726   int ret = ECDSA_do_verify((unsigned char*) l_hash.c_str(), l_hash.length(), sig.get(), d_eckey.get());
727 
728   if (ret == -1){
729     throw runtime_error(getName()+" verify error");
730   }
731 
732   return (ret == 1);
733 }
734 
735 
getPubKeyHash() const736 std::string OpenSSLECDSADNSCryptoKeyEngine::getPubKeyHash() const
737 {
738   string pubKey = getPublicKeyString();
739   unsigned char l_hash[SHA_DIGEST_LENGTH];
740   SHA1((unsigned char*) pubKey.c_str(), pubKey.length(), l_hash);
741   return string((char*) l_hash, sizeof(l_hash));
742 }
743 
744 
getPublicKeyString() const745 std::string OpenSSLECDSADNSCryptoKeyEngine::getPublicKeyString() const
746 {
747   std::string binaryPoint;
748   binaryPoint.resize((d_len * 2) + 1);
749 
750   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);
751   if (ret == 0) {
752     throw runtime_error(getName()+" exporting point to binary failed");
753   }
754 
755   /* we skip the first byte as the other backends use
756      raw field elements, as opposed to the format described in
757      SEC1: "2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion" */
758   binaryPoint.erase(0, 1);
759   return binaryPoint;
760 }
761 
762 
fromISCMap(DNSKEYRecordContent & drc,std::map<std::string,std::string> & stormap)763 void OpenSSLECDSADNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap)
764 {
765   drc.d_algorithm = atoi(stormap["algorithm"].c_str());
766 
767   if (drc.d_algorithm != d_algorithm) {
768     throw runtime_error(getName()+" tried to feed an algorithm "+std::to_string(drc.d_algorithm)+" to a "+std::to_string(d_algorithm)+" key");
769   }
770 
771   string privateKey = stormap["privatekey"];
772 
773   auto prv_key = std::unique_ptr<BIGNUM, void(*)(BIGNUM*)>(BN_bin2bn((unsigned char*) privateKey.c_str(), privateKey.length(), nullptr), BN_clear_free);
774   if (!prv_key) {
775     throw runtime_error(getName()+" reading private key from binary failed");
776   }
777 
778   int ret = EC_KEY_set_private_key(d_eckey.get(), prv_key.get());
779   if (ret != 1) {
780     throw runtime_error(getName()+" setting private key failed");
781   }
782 
783   auto pub_key = std::unique_ptr<EC_POINT, void(*)(EC_POINT*)>(EC_POINT_new(d_ecgroup.get()), EC_POINT_free);
784   if (!pub_key) {
785     throw runtime_error(getName()+" allocation of public key point failed");
786   }
787 
788   ret = EC_POINT_mul(d_ecgroup.get(), pub_key.get(), prv_key.get(), nullptr, nullptr, nullptr);
789   if (ret != 1) {
790     throw runtime_error(getName()+" computing public key from private failed");
791   }
792 
793   ret = EC_KEY_set_public_key(d_eckey.get(), pub_key.get());
794   if (ret != 1) {
795     throw runtime_error(getName()+" setting public key failed");
796   }
797 }
798 
checkKey(vector<string> * errorMessages) const799 bool OpenSSLECDSADNSCryptoKeyEngine::checkKey(vector<string> *errorMessages) const
800 {
801   bool retval = true;
802   if (EC_KEY_check_key(d_eckey.get()) != 1) {
803     retval = false;
804     if (errorMessages != nullptr) {
805       errorMessages->push_back(ERR_reason_error_string(ERR_get_error()));
806     }
807   }
808   return retval;
809 }
810 
fromPublicKeyString(const std::string & input)811 void OpenSSLECDSADNSCryptoKeyEngine::fromPublicKeyString(const std::string& input)
812 {
813   /* uncompressed point, from SEC1:
814      "2.3.4 Octet-String-to-Elliptic-Curve-Point Conversion" */
815   string ecdsaPoint= "\x04";
816   ecdsaPoint.append(input);
817 
818   auto pub_key = std::unique_ptr<EC_POINT, void(*)(EC_POINT*)>(EC_POINT_new(d_ecgroup.get()), EC_POINT_free);
819   if (!pub_key) {
820     throw runtime_error(getName()+" allocation of point structure failed");
821   }
822 
823   int ret = EC_POINT_oct2point(d_ecgroup.get(), pub_key.get(), (unsigned char*) ecdsaPoint.c_str(), ecdsaPoint.length(), nullptr);
824   if (ret != 1) {
825     throw runtime_error(getName()+" reading ECP point from binary failed");
826   }
827 
828   ret = EC_KEY_set_private_key(d_eckey.get(), nullptr);
829   if (ret == 1) {
830     throw runtime_error(getName()+" setting private key failed");
831   }
832 
833   ret = EC_KEY_set_public_key(d_eckey.get(), pub_key.get());
834   if (ret != 1) {
835     throw runtime_error(getName()+" setting public key failed");
836   }
837 }
838 #endif
839 
840 #ifdef HAVE_LIBCRYPTO_EDDSA
841 class OpenSSLEDDSADNSCryptoKeyEngine : public DNSCryptoKeyEngine
842 {
843 public:
OpenSSLEDDSADNSCryptoKeyEngine(unsigned int algo)844   explicit OpenSSLEDDSADNSCryptoKeyEngine(unsigned int algo) : DNSCryptoKeyEngine(algo), d_edkey(std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)>(nullptr, EVP_PKEY_free))
845   {
846 
847     int ret = RAND_status();
848     if (ret != 1) {
849       throw runtime_error(getName()+" insufficient entropy");
850     }
851 
852 #ifdef HAVE_LIBCRYPTO_ED25519
853     if(d_algorithm == 15) {
854       d_len = 32;
855       d_id = NID_ED25519;
856     }
857 #endif
858 #ifdef HAVE_LIBCRYPTO_ED448
859     if (d_algorithm == 16) {
860       d_len = 57;
861       d_id = NID_ED448;
862     }
863 #endif
864     if (d_len == 0) {
865       throw runtime_error(getName()+" unknown algorithm "+std::to_string(d_algorithm));
866     }
867   }
868 
~OpenSSLEDDSADNSCryptoKeyEngine()869   ~OpenSSLEDDSADNSCryptoKeyEngine()
870   {
871   }
872 
getName() const873   string getName() const override { return "OpenSSL EDDSA"; }
getBits() const874   int getBits() const override { return d_len << 3; }
875 
876   void create(unsigned int bits) override;
877   storvector_t convertToISCVector() const override;
878   std::string sign(const std::string& msg) const override;
879   bool verify(const std::string& msg, const std::string& signature) const override;
880   std::string getPubKeyHash() const override;
881   std::string getPublicKeyString() const override;
882   void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) override;
883   void fromPublicKeyString(const std::string& content) override;
884   bool checkKey(vector<string> *errorMessages) const override;
885 
maker(unsigned int algorithm)886   static std::unique_ptr<DNSCryptoKeyEngine> maker(unsigned int algorithm)
887   {
888     return make_unique<OpenSSLEDDSADNSCryptoKeyEngine>(algorithm);
889   }
890 
891 private:
892   size_t d_len{0};
893   int d_id{0};
894 
895   std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)> d_edkey;
896 };
897 
checkKey(vector<string> * errorMessages) const898 bool OpenSSLEDDSADNSCryptoKeyEngine::checkKey(vector<string> *errorMessages) const
899 {
900   return (d_edkey ? true : false);
901 }
902 
create(unsigned int bits)903 void OpenSSLEDDSADNSCryptoKeyEngine::create(unsigned int bits)
904 {
905   auto pctx = std::unique_ptr<EVP_PKEY_CTX, void(*)(EVP_PKEY_CTX*)>(EVP_PKEY_CTX_new_id(d_id, nullptr), EVP_PKEY_CTX_free);
906   if (!pctx) {
907     throw runtime_error(getName()+" context initialization failed");
908   }
909   if (EVP_PKEY_keygen_init(pctx.get()) < 1) {
910     throw runtime_error(getName()+" keygen initialization failed");
911   }
912   EVP_PKEY* newKey = nullptr;
913   if (EVP_PKEY_keygen(pctx.get(), &newKey) < 1) {
914     throw runtime_error(getName()+" key generation failed");
915   }
916   d_edkey = std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)>(newKey, EVP_PKEY_free);
917 }
918 
convertToISCVector() const919 DNSCryptoKeyEngine::storvector_t OpenSSLEDDSADNSCryptoKeyEngine::convertToISCVector() const
920 {
921   storvector_t storvect;
922   string algorithm;
923 
924 #ifdef HAVE_LIBCRYPTO_ED25519
925   if(d_algorithm == 15) {
926     algorithm = "15 (ED25519)";
927   }
928 #endif
929 #ifdef HAVE_LIBCRYPTO_ED448
930   if(d_algorithm == 16) {
931     algorithm = "16 (ED448)";
932   }
933 #endif
934   if (algorithm.empty()) {
935     algorithm = " ? (?)";
936   }
937 
938   storvect.push_back(make_pair("Algorithm", algorithm));
939 
940   string buf;
941   size_t len = d_len;
942   buf.resize(len);
943   if (EVP_PKEY_get_raw_private_key(d_edkey.get(), reinterpret_cast<unsigned char*>(&buf.at(0)), &len) < 1) {
944     throw runtime_error(getName() + " Could not get private key from d_edkey");
945   }
946   storvect.push_back(make_pair("PrivateKey", buf));
947   return storvect;
948 }
949 
sign(const std::string & msg) const950 std::string OpenSSLEDDSADNSCryptoKeyEngine::sign(const std::string& msg) const
951 {
952   auto mdctx = std::unique_ptr<EVP_MD_CTX, void(*)(EVP_MD_CTX*)>(EVP_MD_CTX_new(), EVP_MD_CTX_free);
953   if (!mdctx) {
954     throw runtime_error(getName()+" MD context initialization failed");
955   }
956   if(EVP_DigestSignInit(mdctx.get(), nullptr, nullptr, nullptr, d_edkey.get()) < 1) {
957     throw runtime_error(getName()+" unable to initialize signer");
958   }
959 
960   string msgToSign = msg;
961 
962   size_t siglen = d_len * 2;
963   string signature;
964   signature.resize(siglen);
965 
966   if (EVP_DigestSign(mdctx.get(),
967         reinterpret_cast<unsigned char*>(&signature.at(0)), &siglen,
968         reinterpret_cast<unsigned char*>(&msgToSign.at(0)), msgToSign.length()) < 1) {
969     throw runtime_error(getName()+" signing error");
970   }
971 
972   return signature;
973 }
974 
verify(const std::string & msg,const std::string & signature) const975 bool OpenSSLEDDSADNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const
976 {
977   auto mdctx = std::unique_ptr<EVP_MD_CTX, void(*)(EVP_MD_CTX*)>(EVP_MD_CTX_new(), EVP_MD_CTX_free);
978   if (!mdctx) {
979     throw runtime_error(getName()+" MD context initialization failed");
980   }
981   if(EVP_DigestVerifyInit(mdctx.get(), nullptr, nullptr, nullptr, d_edkey.get()) < 1) {
982     throw runtime_error(getName()+" unable to initialize signer");
983   }
984 
985   string checkSignature = signature;
986   string checkMsg = msg;
987 
988   auto r = EVP_DigestVerify(mdctx.get(),
989       reinterpret_cast<unsigned char*>(&checkSignature.at(0)), checkSignature.length(),
990       reinterpret_cast<unsigned char*>(&checkMsg.at(0)), checkMsg.length());
991   if (r < 0) {
992     throw runtime_error(getName()+" verification failure");
993   }
994 
995   return (r == 1);
996 }
997 
getPubKeyHash() const998 std::string OpenSSLEDDSADNSCryptoKeyEngine::getPubKeyHash() const
999 {
1000   return this->getPublicKeyString();
1001 }
1002 
getPublicKeyString() const1003 std::string OpenSSLEDDSADNSCryptoKeyEngine::getPublicKeyString() const
1004 {
1005   string buf;
1006   size_t len = d_len;
1007   buf.resize(len);
1008   if (EVP_PKEY_get_raw_public_key(d_edkey.get(), reinterpret_cast<unsigned char*>(&buf.at(0)), &len) < 1) {
1009     throw std::runtime_error(getName() + " unable to get public key from key struct");
1010   }
1011   return buf;
1012 }
1013 
fromISCMap(DNSKEYRecordContent & drc,std::map<std::string,std::string> & stormap)1014 void OpenSSLEDDSADNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) {
1015   drc.d_algorithm = atoi(stormap["algorithm"].c_str());
1016   if (drc.d_algorithm != d_algorithm) {
1017     throw runtime_error(getName()+" tried to feed an algorithm "+std::to_string(drc.d_algorithm)+" to a "+std::to_string(d_algorithm)+" key");
1018   }
1019 
1020   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);
1021   if (!d_edkey) {
1022     throw std::runtime_error(getName() + " could not create key structure from private key");
1023   }
1024 }
1025 
fromPublicKeyString(const std::string & content)1026 void OpenSSLEDDSADNSCryptoKeyEngine::fromPublicKeyString(const std::string& content)
1027 {
1028   if (content.length() != d_len) {
1029     throw runtime_error(getName() + " wrong public key length for algorithm " + std::to_string(d_algorithm));
1030   }
1031 
1032   const unsigned char* raw = reinterpret_cast<const unsigned char*>(content.c_str());
1033 
1034   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);
1035   if (!d_edkey) {
1036     throw runtime_error(getName()+" allocation of public key structure failed");
1037   }
1038 }
1039 #endif // HAVE_LIBCRYPTO_EDDSA
1040 
1041 namespace {
1042   struct LoaderStruct
1043   {
LoaderStruct__anon203c62be0111::LoaderStruct1044     LoaderStruct()
1045     {
1046       DNSCryptoKeyEngine::report(5, &OpenSSLRSADNSCryptoKeyEngine::maker);
1047       DNSCryptoKeyEngine::report(7, &OpenSSLRSADNSCryptoKeyEngine::maker);
1048       DNSCryptoKeyEngine::report(8, &OpenSSLRSADNSCryptoKeyEngine::maker);
1049       DNSCryptoKeyEngine::report(10, &OpenSSLRSADNSCryptoKeyEngine::maker);
1050 #ifdef HAVE_LIBCRYPTO_ECDSA
1051       DNSCryptoKeyEngine::report(13, &OpenSSLECDSADNSCryptoKeyEngine::maker);
1052       DNSCryptoKeyEngine::report(14, &OpenSSLECDSADNSCryptoKeyEngine::maker);
1053 #endif
1054 #ifdef HAVE_LIBCRYPTO_ED25519
1055       DNSCryptoKeyEngine::report(15, &OpenSSLEDDSADNSCryptoKeyEngine::maker);
1056 #endif
1057 #ifdef HAVE_LIBCRYPTO_ED448
1058       DNSCryptoKeyEngine::report(16, &OpenSSLEDDSADNSCryptoKeyEngine::maker);
1059 #endif
1060     }
1061   } loaderOpenSSL;
1062 }
1063