11#include " QuickCryptoUtils.hpp"
2+ #include < iomanip>
23#include < openssl/bn.h>
34#include < openssl/core_names.h>
5+ #include < openssl/ec.h>
6+ #include < openssl/err.h>
47#include < openssl/evp.h>
58#include < openssl/param_build.h>
9+ #include < sstream>
610#include < stdexcept>
11+ #include < string>
712
813namespace margelo ::nitro::crypto {
914
15+ static std::string getOpenSslErrors () {
16+ std::ostringstream oss;
17+ bool first = true ;
18+ unsigned long errCode = ERR_get_error ();
19+ while (errCode != 0 ) {
20+ char buf[256 ];
21+ ERR_error_string_n (errCode, buf, sizeof (buf));
22+ if (!first)
23+ oss << " | " ;
24+ oss << buf;
25+ first = false ;
26+ errCode = ERR_get_error ();
27+ }
28+ return first ? " none" : oss.str ();
29+ }
30+
31+ static std::string toHexByte (uint8_t b) {
32+ std::ostringstream oss;
33+ oss << " 0x" << std::hex << std::setw (2 ) << std::setfill (' 0' ) << static_cast <int >(b);
34+ return oss.str ();
35+ }
36+
1037EVP_PKEY * createEcEvpPkey (const char * group_name, const uint8_t * pub_oct, size_t pub_len, const BIGNUM * priv_bn) {
38+ // Clear stale OpenSSL errors before entering this routine.
39+ ERR_clear_error ();
40+
41+ int nid = OBJ_txt2nid (group_name);
42+ bool pointDecodeOk = false ;
43+ if (nid != NID_undef && pub_oct != nullptr && pub_len > 0 ) {
44+ EC_GROUP * group = EC_GROUP_new_by_curve_name (nid);
45+ if (group != nullptr ) {
46+ EC_POINT * point = EC_POINT_new (group);
47+ if (point != nullptr ) {
48+ pointDecodeOk = (EC_POINT_oct2point (group, point, pub_oct, pub_len, nullptr ) == 1 );
49+ EC_POINT_free (point);
50+ }
51+ EC_GROUP_free (group);
52+ }
53+ }
54+
1155 OSSL_PARAM_BLD * bld = OSSL_PARAM_BLD_new ();
1256 if (!bld)
1357 throw std::runtime_error (" Failed to create OSSL_PARAM_BLD" );
@@ -31,9 +75,15 @@ EVP_PKEY* createEcEvpPkey(const char* group_name, const uint8_t* pub_oct, size_t
3175 int selection = priv_bn ? EVP_PKEY_KEYPAIR : EVP_PKEY_PUBLIC_KEY ;
3276 EVP_PKEY * pkey = nullptr ;
3377 if (EVP_PKEY_fromdata_init (ctx) <= 0 || EVP_PKEY_fromdata (ctx, &pkey, selection, params) <= 0 ) {
78+ std::string errors = getOpenSslErrors ();
79+ std::ostringstream message;
80+ message << " Failed to create EVP_PKEY from EC parameters"
81+ << " (group=" << (group_name ? group_name : " null" ) << " , pub_len=" << pub_len
82+ << " , pub_first=" << ((pub_oct != nullptr && pub_len > 0 ) ? toHexByte (pub_oct[0 ]) : " n/a" )
83+ << " , point_decode_ok=" << (pointDecodeOk ? " true" : " false" ) << " , openssl_errors=" << errors << " )" ;
3484 EVP_PKEY_CTX_free (ctx);
3585 OSSL_PARAM_free (params);
36- throw std::runtime_error (" Failed to create EVP_PKEY from EC parameters " );
86+ throw std::runtime_error (message. str () );
3787 }
3888
3989 EVP_PKEY_CTX_free (ctx);
0 commit comments