2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
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.
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.
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.
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.
25 #include <openssl/obj_mac.h>
26 #ifdef HAVE_LIBCRYPTO_ECDSA
27 #include <openssl/ecdsa.h>
29 #include <openssl/sha.h>
30 #include <openssl/rand.h>
31 #include <openssl/rsa.h>
32 #include <openssl/opensslv.h>
33 #include "opensslsigners.hh"
34 #include "dnssecinfra.hh"
36 #if (OPENSSL_VERSION_NUMBER < 0x1010000fL || defined LIBRESSL_VERSION_NUMBER)
37 /* OpenSSL < 1.1.0 needs support for threading/locking in the calling application. */
38 static pthread_mutex_t
*openssllocks
;
41 void openssl_pthreads_locking_callback(int mode
, int type
, const char *file
, int line
)
43 if (mode
& CRYPTO_LOCK
) {
44 pthread_mutex_lock(&(openssllocks
[type
]));
47 pthread_mutex_unlock(&(openssllocks
[type
]));
51 unsigned long openssl_pthreads_id_callback()
53 return (unsigned long)pthread_self();
57 void openssl_thread_setup()
59 openssllocks
= (pthread_mutex_t
*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t
));
61 for (int i
= 0; i
< CRYPTO_num_locks(); i
++)
62 pthread_mutex_init(&(openssllocks
[i
]), NULL
);
64 CRYPTO_set_id_callback(openssl_pthreads_id_callback
);
65 CRYPTO_set_locking_callback(openssl_pthreads_locking_callback
);
68 void openssl_thread_cleanup()
70 CRYPTO_set_locking_callback(NULL
);
72 for (int i
=0; i
<CRYPTO_num_locks(); i
++) {
73 pthread_mutex_destroy(&(openssllocks
[i
]));
76 OPENSSL_free(openssllocks
);
79 #if !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER < 0x2070000fL
80 /* those symbols are defined in LibreSSL 2.7.0+ */
81 /* compat helpers. These DO NOT do any of the checking that the libssl 1.1 functions do. */
82 static inline void RSA_get0_key(const RSA
* rsakey
, const BIGNUM
** n
, const BIGNUM
** e
, const BIGNUM
** d
) {
88 static inline int RSA_set0_key(RSA
* rsakey
, BIGNUM
* n
, BIGNUM
* e
, BIGNUM
* d
) {
90 BN_clear_free(rsakey
->n
);
94 BN_clear_free(rsakey
->e
);
98 BN_clear_free(rsakey
->d
);
104 static inline void RSA_get0_factors(const RSA
* rsakey
, const BIGNUM
** p
, const BIGNUM
** q
) {
109 static inline int RSA_set0_factors(RSA
* rsakey
, BIGNUM
* p
, BIGNUM
* q
) {
110 BN_clear_free(rsakey
->p
);
112 BN_clear_free(rsakey
->q
);
117 static inline void RSA_get0_crt_params(const RSA
* rsakey
, const BIGNUM
** dmp1
, const BIGNUM
** dmq1
, const BIGNUM
** iqmp
) {
118 *dmp1
= rsakey
->dmp1
;
119 *dmq1
= rsakey
->dmq1
;
120 *iqmp
= rsakey
->iqmp
;
123 static inline int RSA_set0_crt_params(RSA
* rsakey
, BIGNUM
* dmp1
, BIGNUM
* dmq1
, BIGNUM
* iqmp
) {
124 BN_clear_free(rsakey
->dmp1
);
126 BN_clear_free(rsakey
->dmq1
);
128 BN_clear_free(rsakey
->iqmp
);
133 #ifdef HAVE_LIBCRYPTO_ECDSA
134 static inline void ECDSA_SIG_get0(const ECDSA_SIG
* signature
, const BIGNUM
** pr
, const BIGNUM
** ps
) {
139 static inline int ECDSA_SIG_set0(ECDSA_SIG
* signature
, BIGNUM
* pr
, BIGNUM
* ps
) {
140 BN_clear_free(signature
->r
);
141 BN_clear_free(signature
->s
);
146 #endif /* HAVE_LIBCRYPTO_ECDSA */
148 #endif /* !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER < 0x2070000fL */
151 void openssl_thread_setup() {}
152 void openssl_thread_cleanup() {}
161 entropy
.reserve(1024);
164 for(int i
=0; i
<1024; i
+=4) {
165 r
=dns_random(0xffffffff);
166 entropy
.append((const char*)&r
, 4);
169 RAND_seed((const unsigned char*)entropy
.c_str(), 1024);
173 class OpenSSLRSADNSCryptoKeyEngine
: public DNSCryptoKeyEngine
176 explicit OpenSSLRSADNSCryptoKeyEngine(unsigned int algo
) : DNSCryptoKeyEngine(algo
)
178 int ret
= RAND_status();
180 throw runtime_error(getName()+" insufficient entropy");
184 ~OpenSSLRSADNSCryptoKeyEngine()
190 string
getName() const override
{ return "OpenSSL RSA"; }
191 int getBits() const override
{ return RSA_size(d_key
) << 3; }
193 void create(unsigned int bits
) override
;
194 storvector_t
convertToISCVector() const override
;
195 std::string
hash(const std::string
& hash
) const override
;
196 std::string
sign(const std::string
& hash
) const override
;
197 bool verify(const std::string
& hash
, const std::string
& signature
) const override
;
198 std::string
getPubKeyHash() const override
;
199 std::string
getPublicKeyString() const override
;
200 void fromISCMap(DNSKEYRecordContent
& drc
, std::map
<std::string
, std::string
>& stormap
) override
;
201 void fromPublicKeyString(const std::string
& content
) override
;
202 bool checkKey() const override
;
204 static std::shared_ptr
<DNSCryptoKeyEngine
> maker(unsigned int algorithm
)
206 return std::make_shared
<OpenSSLRSADNSCryptoKeyEngine
>(algorithm
);
210 static int hashSizeToKind(size_t hashSize
);
216 void OpenSSLRSADNSCryptoKeyEngine::create(unsigned int bits
)
218 BIGNUM
*e
= BN_new();
220 throw runtime_error(getName()+" key generation failed, unable to allocate e");
223 /* RSA_F4 is a public exponent value of 65537 */
224 int res
= BN_set_word(e
, RSA_F4
);
228 throw runtime_error(getName()+" key generation failed while setting e");
231 RSA
* key
= RSA_new();
234 throw runtime_error(getName()+" allocation of key structure failed");
237 res
= RSA_generate_key_ex(key
, bits
, e
, NULL
);
241 throw runtime_error(getName()+" key generation failed");
251 DNSCryptoKeyEngine::storvector_t
OpenSSLRSADNSCryptoKeyEngine::convertToISCVector() const
253 storvector_t storvect
;
254 typedef vector
<pair
<string
, const BIGNUM
*> > outputs_t
;
256 const BIGNUM
*n
, *e
, *d
, *p
, *q
, *dmp1
, *dmq1
, *iqmp
;
257 RSA_get0_key(d_key
, &n
, &e
, &d
);
258 RSA_get0_factors(d_key
, &p
, &q
);
259 RSA_get0_crt_params(d_key
, &dmp1
, &dmq1
, &iqmp
);
260 outputs
.push_back(make_pair("Modulus", n
));
261 outputs
.push_back(make_pair("PublicExponent", e
));
262 outputs
.push_back(make_pair("PrivateExponent", d
));
263 outputs
.push_back(make_pair("Prime1", p
));
264 outputs
.push_back(make_pair("Prime2", q
));
265 outputs
.push_back(make_pair("Exponent1", dmp1
));
266 outputs
.push_back(make_pair("Exponent2", dmq1
));
267 outputs
.push_back(make_pair("Coefficient", iqmp
));
269 string algorithm
=std::to_string(d_algorithm
);
270 switch(d_algorithm
) {
273 algorithm
+= " (RSASHA1)";
276 algorithm
+= " (RSASHA256)";
279 algorithm
+= " (RSASHA512)";
284 storvect
.push_back(make_pair("Algorithm", algorithm
));
286 for(outputs_t::value_type value
: outputs
) {
287 unsigned char tmp
[BN_num_bytes(value
.second
)];
288 int len
= BN_bn2bin(value
.second
, tmp
);
289 storvect
.push_back(make_pair(value
.first
, string((char*) tmp
, len
)));
296 std::string
OpenSSLRSADNSCryptoKeyEngine::hash(const std::string
& orig
) const
298 if (d_algorithm
== 5 || d_algorithm
== 7) {
300 unsigned char hash
[SHA_DIGEST_LENGTH
];
301 SHA1((unsigned char*) orig
.c_str(), orig
.length(), hash
);
302 return string((char*) hash
, sizeof(hash
));
304 else if (d_algorithm
== 8) {
306 unsigned char hash
[SHA256_DIGEST_LENGTH
];
307 SHA256((unsigned char*) orig
.c_str(), orig
.length(), hash
);
308 return string((char*) hash
, sizeof(hash
));
310 else if (d_algorithm
== 10) {
312 unsigned char hash
[SHA512_DIGEST_LENGTH
];
313 SHA512((unsigned char*) orig
.c_str(), orig
.length(), hash
);
314 return string((char*) hash
, sizeof(hash
));
317 throw runtime_error(getName()+" does not support hash operation for algorithm "+std::to_string(d_algorithm
));
320 int OpenSSLRSADNSCryptoKeyEngine::hashSizeToKind(const size_t hashSize
)
323 case SHA_DIGEST_LENGTH
:
325 case SHA256_DIGEST_LENGTH
:
327 case SHA384_DIGEST_LENGTH
:
329 case SHA512_DIGEST_LENGTH
:
332 throw runtime_error("OpenSSL RSA does not handle hash of size " + std::to_string(hashSize
));
336 std::string
OpenSSLRSADNSCryptoKeyEngine::sign(const std::string
& msg
) const
338 string hash
= this->hash(msg
);
339 int hashKind
= hashSizeToKind(hash
.size());
340 unsigned char signature
[RSA_size(d_key
)];
341 unsigned int signatureLen
= 0;
343 int res
= RSA_sign(hashKind
, (unsigned char*) hash
.c_str(), hash
.length(), signature
, &signatureLen
, d_key
);
345 throw runtime_error(getName()+" failed to generate signature");
348 return string((char*) signature
, signatureLen
);
352 bool OpenSSLRSADNSCryptoKeyEngine::verify(const std::string
& msg
, const std::string
& signature
) const
354 string hash
= this->hash(msg
);
355 int hashKind
= hashSizeToKind(hash
.size());
357 int ret
= RSA_verify(hashKind
, (const unsigned char*) hash
.c_str(), hash
.length(), (unsigned char*) signature
.c_str(), signature
.length(), d_key
);
363 std::string
OpenSSLRSADNSCryptoKeyEngine::getPubKeyHash() const
365 const BIGNUM
*n
, *e
, *d
;
366 RSA_get0_key(d_key
, &n
, &e
, &d
);
367 unsigned char tmp
[std::max(BN_num_bytes(e
), BN_num_bytes(n
))];
368 unsigned char hash
[SHA_DIGEST_LENGTH
];
371 int res
= SHA1_Init(&ctx
);
374 throw runtime_error(getName()+" failed to init hash context for generating the public key hash");
377 int len
= BN_bn2bin(e
, tmp
);
378 res
= SHA1_Update(&ctx
, tmp
, len
);
380 throw runtime_error(getName()+" failed to update hash context for generating the public key hash");
383 len
= BN_bn2bin(n
, tmp
);
384 res
= SHA1_Update(&ctx
, tmp
, len
);
386 throw runtime_error(getName()+" failed to update hash context for generating the public key hash");
389 res
= SHA1_Final(hash
, &ctx
);
391 throw runtime_error(getName()+" failed to finish hash context for generating the public key hash");
394 return string((char*) hash
, sizeof(hash
));
398 std::string
OpenSSLRSADNSCryptoKeyEngine::getPublicKeyString() const
400 const BIGNUM
*n
, *e
, *d
;
401 RSA_get0_key(d_key
, &n
, &e
, &d
);
403 unsigned char tmp
[std::max(BN_num_bytes(e
), BN_num_bytes(n
))];
405 int len
= BN_bn2bin(e
, tmp
);
407 keystring
.assign(1, (char) (unsigned int) len
);
409 keystring
.assign(1, 0);
410 uint16_t tempLen
= len
;
411 tempLen
= htons(tempLen
);
412 keystring
.append((char*)&tempLen
, 2);
414 keystring
.append((char *) tmp
, len
);
416 len
= BN_bn2bin(n
, tmp
);
417 keystring
.append((char *) tmp
, len
);
423 void OpenSSLRSADNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent
& drc
, std::map
<std::string
, std::string
>& stormap
)
425 typedef map
<string
, BIGNUM
**> places_t
;
427 RSA
* key
= RSA_new();
429 throw runtime_error(getName()+" allocation of key structure failed");
432 BIGNUM
*n
, *e
, *d
, *p
, *q
, *dmp1
, *dmq1
, *iqmp
;
436 throw runtime_error(getName()+" allocation of BIGNUM n failed");
442 throw runtime_error(getName()+" allocation of BIGNUM e failed");
449 throw runtime_error(getName()+" allocation of BIGNUM d failed");
451 RSA_set0_key(key
, n
, e
, d
);
456 throw runtime_error(getName()+" allocation of BIGNUM p failed");
462 throw runtime_error(getName()+" allocation of BIGNUM q failed");
464 RSA_set0_factors(key
, p
, q
);
469 throw runtime_error(getName()+" allocation of BIGNUM dmp1 failed");
475 throw runtime_error(getName()+" allocation of BIGNUM dmq1 failed");
482 throw runtime_error(getName()+" allocation of BIGNUM iqmp failed");
484 RSA_set0_crt_params(key
, dmp1
, dmq1
, iqmp
);
486 places
["Modulus"]=&n
;
487 places
["PublicExponent"]=&e
;
488 places
["PrivateExponent"]=&d
;
491 places
["Exponent1"]=&dmp1
;
492 places
["Exponent2"]=&dmq1
;
493 places
["Coefficient"]=&iqmp
;
495 drc
.d_algorithm
= pdns_stou(stormap
["algorithm"]);
498 for(const places_t::value_type
& val
: places
) {
499 raw
=stormap
[toLower(val
.first
)];
504 *val
.second
= BN_bin2bn((unsigned char*) raw
.c_str(), raw
.length(), *val
.second
);
507 throw runtime_error(getName()+" error loading " + val
.first
);
511 if (drc
.d_algorithm
!= d_algorithm
) {
513 throw runtime_error(getName()+" tried to feed an algorithm "+std::to_string(drc
.d_algorithm
)+" to a "+std::to_string(d_algorithm
)+" key");
522 bool OpenSSLRSADNSCryptoKeyEngine::checkKey() const
524 return (RSA_check_key(d_key
) == 1);
527 void OpenSSLRSADNSCryptoKeyEngine::fromPublicKeyString(const std::string
& input
)
529 string exponent
, modulus
;
530 const size_t inputLen
= input
.length();
531 const unsigned char* raw
= (const unsigned char*)input
.c_str();
534 throw runtime_error(getName()+" invalid input size for the public key");
538 const size_t exponentSize
= raw
[0];
539 if (inputLen
< (exponentSize
+ 2)) {
540 throw runtime_error(getName()+" invalid input size for the public key");
542 exponent
= input
.substr(1, exponentSize
);
543 modulus
= input
.substr(exponentSize
+ 1);
546 throw runtime_error(getName()+" invalid input size for the public key");
548 const size_t exponentSize
= raw
[1]*0xff + raw
[2];
549 if (inputLen
< (exponentSize
+ 4)) {
550 throw runtime_error(getName()+" invalid input size for the public key");
552 exponent
= input
.substr(3, exponentSize
);
553 modulus
= input
.substr(exponentSize
+ 3);
556 RSA
* key
= RSA_new();
558 throw runtime_error(getName()+" allocation of key structure failed");
561 BIGNUM
*e
= BN_bin2bn((unsigned char*)exponent
.c_str(), exponent
.length(), NULL
);
564 throw runtime_error(getName()+" error loading e value of public key");
566 BIGNUM
*n
= BN_bin2bn((unsigned char*)modulus
.c_str(), modulus
.length(), NULL
);
570 throw runtime_error(getName()+" error loading n value of public key");
576 RSA_set0_key(key
, n
, e
, NULL
);
580 #ifdef HAVE_LIBCRYPTO_ECDSA
581 class OpenSSLECDSADNSCryptoKeyEngine
: public DNSCryptoKeyEngine
584 explicit OpenSSLECDSADNSCryptoKeyEngine(unsigned int algo
) : DNSCryptoKeyEngine(algo
)
587 int ret
= RAND_status();
589 throw runtime_error(getName()+" insufficient entropy");
592 d_eckey
= EC_KEY_new();
593 if (d_eckey
== NULL
) {
594 throw runtime_error(getName()+" allocation of key structure failed");
597 if(d_algorithm
== 13) {
598 d_ecgroup
= EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1
);
600 } else if (d_algorithm
== 14) {
601 d_ecgroup
= EC_GROUP_new_by_curve_name(NID_secp384r1
);
604 EC_KEY_free(d_eckey
);
605 throw runtime_error(getName()+" unknown algorithm "+std::to_string(d_algorithm
));
608 if (d_ecgroup
== NULL
) {
609 EC_KEY_free(d_eckey
);
610 throw runtime_error(getName()+" allocation of group structure failed");
613 ret
= EC_KEY_set_group(d_eckey
, d_ecgroup
);
615 EC_KEY_free(d_eckey
);
616 EC_GROUP_free(d_ecgroup
);
617 throw runtime_error(getName()+" setting key group failed");
622 ~OpenSSLECDSADNSCryptoKeyEngine()
624 EC_KEY_free(d_eckey
);
625 EC_GROUP_free(d_ecgroup
);
629 string
getName() const override
{ return "OpenSSL ECDSA"; }
630 int getBits() const override
{ return d_len
<< 3; }
632 void create(unsigned int bits
) override
;
633 storvector_t
convertToISCVector() const override
;
634 std::string
hash(const std::string
& hash
) const override
;
635 std::string
sign(const std::string
& hash
) const override
;
636 bool verify(const std::string
& hash
, const std::string
& signature
) const override
;
637 std::string
getPubKeyHash() const override
;
638 std::string
getPublicKeyString() const override
;
639 void fromISCMap(DNSKEYRecordContent
& drc
, std::map
<std::string
, std::string
>& stormap
) override
;
640 void fromPublicKeyString(const std::string
& content
) override
;
641 bool checkKey() const override
;
643 static std::shared_ptr
<DNSCryptoKeyEngine
> maker(unsigned int algorithm
)
645 return std::make_shared
<OpenSSLECDSADNSCryptoKeyEngine
>(algorithm
);
651 EC_KEY
*d_eckey
= NULL
;
652 EC_GROUP
*d_ecgroup
= NULL
;
653 BN_CTX
*d_ctx
= NULL
;
657 void OpenSSLECDSADNSCryptoKeyEngine::create(unsigned int bits
)
659 if (bits
>> 3 != d_len
) {
660 throw runtime_error(getName()+" unknown key length of "+std::to_string(bits
)+" bits requested");
663 int res
= EC_KEY_generate_key(d_eckey
);
665 throw runtime_error(getName()+" key generation failed");
670 DNSCryptoKeyEngine::storvector_t
OpenSSLECDSADNSCryptoKeyEngine::convertToISCVector() const
672 storvector_t storvect
;
675 if(d_algorithm
== 13)
676 algorithm
= "13 (ECDSAP256SHA256)";
677 else if(d_algorithm
== 14)
678 algorithm
= "14 (ECDSAP384SHA384)";
680 algorithm
= " ? (?)";
682 storvect
.push_back(make_pair("Algorithm", algorithm
));
684 const BIGNUM
*key
= EC_KEY_get0_private_key(d_eckey
);
686 throw runtime_error(getName()+" private key not set");
689 unsigned char tmp
[BN_num_bytes(key
)];
690 int len
= BN_bn2bin(key
, tmp
);
694 prefix
.append(d_len
- len
, 0x00);
696 storvect
.push_back(make_pair("PrivateKey", prefix
+ string((char*) tmp
, sizeof(tmp
))));
702 std::string
OpenSSLECDSADNSCryptoKeyEngine::hash(const std::string
& orig
) const
704 if(getBits() == 256) {
705 unsigned char hash
[SHA256_DIGEST_LENGTH
];
706 SHA256((unsigned char*) orig
.c_str(), orig
.length(), hash
);
707 return string((char*) hash
, sizeof(hash
));
709 else if(getBits() == 384) {
710 unsigned char hash
[SHA384_DIGEST_LENGTH
];
711 SHA384((unsigned char*) orig
.c_str(), orig
.length(), hash
);
712 return string((char*) hash
, sizeof(hash
));
715 throw runtime_error(getName()+" does not support a hash size of "+std::to_string(getBits())+" bits");
719 std::string
OpenSSLECDSADNSCryptoKeyEngine::sign(const std::string
& msg
) const
721 string hash
= this->hash(msg
);
723 ECDSA_SIG
*signature
= ECDSA_do_sign((unsigned char*) hash
.c_str(), hash
.length(), d_eckey
);
724 if (NULL
== signature
) {
725 throw runtime_error(getName()+" failed to generate signature");
729 unsigned char tmp
[d_len
];
731 const BIGNUM
*pr
, *ps
;
732 ECDSA_SIG_get0(signature
, &pr
, &ps
);
733 int len
= BN_bn2bin(pr
, tmp
);
735 ret
.append(d_len
- len
, 0x00);
736 ret
.append(string((char*) tmp
, len
));
738 len
= BN_bn2bin(ps
, tmp
);
740 ret
.append(d_len
- len
, 0x00);
741 ret
.append(string((char*) tmp
, len
));
743 ECDSA_SIG_free(signature
);
749 bool OpenSSLECDSADNSCryptoKeyEngine::verify(const std::string
& msg
, const std::string
& signature
) const
751 if (signature
.length() != (d_len
* 2)) {
752 throw runtime_error(getName()+" invalid signature size "+std::to_string(signature
.length()));
755 string hash
= this->hash(msg
);
758 sig
= ECDSA_SIG_new();
760 throw runtime_error(getName()+" allocation of signature structure failed");
764 r
= BN_bin2bn((unsigned char*) signature
.c_str(), d_len
, NULL
);
765 s
= BN_bin2bn((unsigned char*) signature
.c_str() + d_len
, d_len
, NULL
);
774 throw runtime_error(getName()+" invalid signature");
777 ECDSA_SIG_set0(sig
, r
, s
);
778 int ret
= ECDSA_do_verify((unsigned char*) hash
.c_str(), hash
.length(), sig
, d_eckey
);
783 throw runtime_error(getName()+" verify error");
790 std::string
OpenSSLECDSADNSCryptoKeyEngine::getPubKeyHash() const
792 string pubKey
= getPublicKeyString();
793 unsigned char hash
[SHA_DIGEST_LENGTH
];
794 SHA1((unsigned char*) pubKey
.c_str(), pubKey
.length(), hash
);
795 return string((char*) hash
, sizeof(hash
));
799 std::string
OpenSSLECDSADNSCryptoKeyEngine::getPublicKeyString() const
801 unsigned char binaryPoint
[(d_len
* 2) + 1];
803 int ret
= EC_POINT_point2oct(d_ecgroup
, EC_KEY_get0_public_key(d_eckey
), POINT_CONVERSION_UNCOMPRESSED
, binaryPoint
, sizeof(binaryPoint
), d_ctx
);
805 throw runtime_error(getName()+" exporting point to binary failed");
808 /* we skip the first byte as the other backends use
809 raw field elements, as opposed to the format described in
810 SEC1: "2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion" */
811 return string((const char *)(binaryPoint
+ 1), sizeof(binaryPoint
) - 1);
815 void OpenSSLECDSADNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent
& drc
, std::map
<std::string
, std::string
>& stormap
)
817 drc
.d_algorithm
= atoi(stormap
["algorithm"].c_str());
819 if (drc
.d_algorithm
!= d_algorithm
) {
820 throw runtime_error(getName()+" tried to feed an algorithm "+std::to_string(drc
.d_algorithm
)+" to a "+std::to_string(d_algorithm
)+" key");
823 string privateKey
= stormap
["privatekey"];
825 BIGNUM
*prv_key
= BN_bin2bn((unsigned char*) privateKey
.c_str(), privateKey
.length(), NULL
);
826 if (prv_key
== NULL
) {
827 throw runtime_error(getName()+" reading private key from binary failed");
830 int ret
= EC_KEY_set_private_key(d_eckey
, prv_key
);
832 BN_clear_free(prv_key
);
833 throw runtime_error(getName()+" setting private key failed");
836 EC_POINT
*pub_key
= EC_POINT_new(d_ecgroup
);
837 if (pub_key
== NULL
) {
838 BN_clear_free(prv_key
);
839 throw runtime_error(getName()+" allocation of public key point failed");
842 ret
= EC_POINT_mul(d_ecgroup
, pub_key
, prv_key
, NULL
, NULL
, d_ctx
);
844 EC_POINT_free(pub_key
);
845 BN_clear_free(prv_key
);
846 throw runtime_error(getName()+" computing public key from private failed");
849 BN_clear_free(prv_key
);
851 ret
= EC_KEY_set_public_key(d_eckey
, pub_key
);
853 EC_POINT_free(pub_key
);
854 throw runtime_error(getName()+" setting public key failed");
857 EC_POINT_free(pub_key
);
860 bool OpenSSLECDSADNSCryptoKeyEngine::checkKey() const
862 return (EC_KEY_check_key(d_eckey
) == 1);
865 void OpenSSLECDSADNSCryptoKeyEngine::fromPublicKeyString(const std::string
& input
)
867 /* uncompressed point, from SEC1:
868 "2.3.4 Octet-String-to-Elliptic-Curve-Point Conversion" */
869 string ecdsaPoint
= "\x04";
870 ecdsaPoint
.append(input
);
872 EC_POINT
*pub_key
= EC_POINT_new(d_ecgroup
);
873 if (pub_key
== NULL
) {
874 throw runtime_error(getName()+" allocation of point structure failed");
877 int ret
= EC_POINT_oct2point(d_ecgroup
, pub_key
, (unsigned char*) ecdsaPoint
.c_str(), ecdsaPoint
.length(), d_ctx
);
879 EC_POINT_free(pub_key
);
880 throw runtime_error(getName()+" reading ECP point from binary failed");
883 ret
= EC_KEY_set_private_key(d_eckey
, NULL
);
885 EC_POINT_free(pub_key
);
886 throw runtime_error(getName()+" setting private key failed");
889 ret
= EC_KEY_set_public_key(d_eckey
, pub_key
);
891 EC_POINT_free(pub_key
);
892 throw runtime_error(getName()+" setting public key failed");
895 EC_POINT_free(pub_key
);
905 DNSCryptoKeyEngine::report(5, &OpenSSLRSADNSCryptoKeyEngine::maker
);
906 DNSCryptoKeyEngine::report(7, &OpenSSLRSADNSCryptoKeyEngine::maker
);
907 DNSCryptoKeyEngine::report(8, &OpenSSLRSADNSCryptoKeyEngine::maker
);
908 DNSCryptoKeyEngine::report(10, &OpenSSLRSADNSCryptoKeyEngine::maker
);
909 #ifdef HAVE_LIBCRYPTO_ECDSA
910 DNSCryptoKeyEngine::report(13, &OpenSSLECDSADNSCryptoKeyEngine::maker
);
911 DNSCryptoKeyEngine::report(14, &OpenSSLECDSADNSCryptoKeyEngine::maker
);