@@ -115,6 +115,77 @@ using v8::Value;
115115
116116
117117#if OPENSSL_VERSION_NUMBER < 0x10100000L
118+ static void RSA_get0_key (const RSA* r, const BIGNUM** n, const BIGNUM** e,
119+ const BIGNUM** d) {
120+ if (n != nullptr ) {
121+ *n = r->n ;
122+ }
123+ if (e != nullptr ) {
124+ *e = r->e ;
125+ }
126+ if (d != nullptr ) {
127+ *d = r->d ;
128+ }
129+ }
130+
131+ static void DH_get0_pqg (const DH* dh, const BIGNUM** p, const BIGNUM** q,
132+ const BIGNUM** g) {
133+ if (p != nullptr ) {
134+ *p = dh->p ;
135+ }
136+ if (q != nullptr ) {
137+ *q = dh->q ;
138+ }
139+ if (g != nullptr ) {
140+ *g = dh->g ;
141+ }
142+ }
143+
144+ static int DH_set0_pqg (DH* dh, BIGNUM* p, BIGNUM* q, BIGNUM* g) {
145+ if ((dh->p == nullptr && p == nullptr ) ||
146+ (dh->g == nullptr && g == nullptr )) {
147+ return 0 ;
148+ }
149+
150+ if (p != nullptr ) {
151+ BN_free (dh->p );
152+ dh->p = p;
153+ }
154+ if (q != nullptr ) {
155+ BN_free (dh->q );
156+ dh->q = q;
157+ }
158+ if (g != nullptr ) {
159+ BN_free (dh->g );
160+ dh->g = g;
161+ }
162+
163+ return 1 ;
164+ }
165+
166+ static void DH_get0_key (const DH* dh, const BIGNUM** pub_key,
167+ const BIGNUM** priv_key) {
168+ if (pub_key != nullptr ) {
169+ *pub_key = dh->pub_key ;
170+ }
171+ if (priv_key != nullptr ) {
172+ *priv_key = dh->priv_key ;
173+ }
174+ }
175+
176+ static int DH_set0_key (DH* dh, BIGNUM* pub_key, BIGNUM* priv_key) {
177+ if (pub_key != nullptr ) {
178+ BN_free (dh->pub_key );
179+ dh->pub_key = pub_key;
180+ }
181+ if (priv_key != nullptr ) {
182+ BN_free (dh->priv_key );
183+ dh->priv_key = priv_key;
184+ }
185+
186+ return 1 ;
187+ }
188+
118189static void SSL_SESSION_get0_ticket (const SSL_SESSION* s,
119190 const unsigned char ** tick, size_t * len) {
120191 *len = s->tlsext_ticklen ;
@@ -1011,7 +1082,9 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo<Value>& args) {
10111082 if (dh == nullptr )
10121083 return ;
10131084
1014- const int size = BN_num_bits (dh->p );
1085+ const BIGNUM* p;
1086+ DH_get0_pqg (dh, &p, nullptr , nullptr );
1087+ const int size = BN_num_bits (p);
10151088 if (size < 1024 ) {
10161089 return env->ThrowError (" DH parameter is less than 1024 bits" );
10171090 } else if (size < 2048 ) {
@@ -1631,14 +1704,17 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
16311704 rsa = EVP_PKEY_get1_RSA (pkey);
16321705
16331706 if (rsa != nullptr ) {
1634- BN_print (bio, rsa->n );
1707+ const BIGNUM* n;
1708+ const BIGNUM* e;
1709+ RSA_get0_key (rsa, &n, &e, nullptr );
1710+ BN_print (bio, n);
16351711 BIO_get_mem_ptr (bio, &mem);
16361712 info->Set (env->modulus_string (),
16371713 String::NewFromUtf8 (env->isolate (), mem->data ,
16381714 String::kNormalString , mem->length ));
16391715 (void ) BIO_reset (bio);
16401716
1641- uint64_t exponent_word = static_cast <uint64_t >(BN_get_word (rsa-> e ));
1717+ uint64_t exponent_word = static_cast <uint64_t >(BN_get_word (e));
16421718 uint32_t lo = static_cast <uint32_t >(exponent_word);
16431719 uint32_t hi = static_cast <uint32_t >(exponent_word >> 32 );
16441720 if (hi == 0 ) {
@@ -4719,10 +4795,15 @@ bool DiffieHellman::Init(int primeLength, int g) {
47194795
47204796bool DiffieHellman::Init (const char * p, int p_len, int g) {
47214797 dh = DH_new ();
4722- dh->p = BN_bin2bn (reinterpret_cast <const unsigned char *>(p), p_len, 0 );
4723- dh->g = BN_new ();
4724- if (!BN_set_word (dh->g , g))
4798+ BIGNUM* bn_p =
4799+ BN_bin2bn (reinterpret_cast <const unsigned char *>(p), p_len, nullptr );
4800+ BIGNUM* bn_g = BN_new ();
4801+ if (!BN_set_word (bn_g, g) ||
4802+ !DH_set0_pqg (dh, bn_p, nullptr , bn_g)) {
4803+ BN_free (bn_p);
4804+ BN_free (bn_g);
47254805 return false ;
4806+ }
47264807 bool result = VerifyContext ();
47274808 if (!result)
47284809 return false ;
@@ -4733,8 +4814,13 @@ bool DiffieHellman::Init(const char* p, int p_len, int g) {
47334814
47344815bool DiffieHellman::Init (const char * p, int p_len, const char * g, int g_len) {
47354816 dh = DH_new ();
4736- dh->p = BN_bin2bn (reinterpret_cast <const unsigned char *>(p), p_len, 0 );
4737- dh->g = BN_bin2bn (reinterpret_cast <const unsigned char *>(g), g_len, 0 );
4817+ BIGNUM *bn_p = BN_bin2bn (reinterpret_cast <const unsigned char *>(p), p_len, 0 );
4818+ BIGNUM *bn_g = BN_bin2bn (reinterpret_cast <const unsigned char *>(g), g_len, 0 );
4819+ if (!DH_set0_pqg (dh, bn_p, nullptr , bn_g)) {
4820+ BN_free (bn_p);
4821+ BN_free (bn_g);
4822+ return false ;
4823+ }
47384824 bool result = VerifyContext ();
47394825 if (!result)
47404826 return false ;
@@ -4822,22 +4908,25 @@ void DiffieHellman::GenerateKeys(const FunctionCallbackInfo<Value>& args) {
48224908 return ThrowCryptoError (env, ERR_get_error (), " Key generation failed" );
48234909 }
48244910
4825- size_t size = BN_num_bytes (diffieHellman->dh ->pub_key );
4911+ const BIGNUM* pub_key;
4912+ DH_get0_key (diffieHellman->dh , &pub_key, nullptr );
4913+ size_t size = BN_num_bytes (pub_key);
48264914 char * data = Malloc (size);
4827- BN_bn2bin (diffieHellman-> dh -> pub_key , reinterpret_cast <unsigned char *>(data));
4915+ BN_bn2bin (pub_key, reinterpret_cast <unsigned char *>(data));
48284916 args.GetReturnValue ().Set (Buffer::New (env, data, size).ToLocalChecked ());
48294917}
48304918
48314919
48324920void DiffieHellman::GetField (const FunctionCallbackInfo<Value>& args,
4833- BIGNUM* (DH::*field), const char * err_if_null) {
4921+ const BIGNUM* (*get_field)(const DH*),
4922+ const char * err_if_null) {
48344923 Environment* env = Environment::GetCurrent (args);
48354924
48364925 DiffieHellman* dh;
48374926 ASSIGN_OR_RETURN_UNWRAP (&dh, args.Holder ());
48384927 if (!dh->initialised_ ) return env->ThrowError (" Not initialized" );
48394928
4840- const BIGNUM* num = (dh->dh )->*field ;
4929+ const BIGNUM* num = get_field (dh->dh );
48414930 if (num == nullptr ) return env->ThrowError (err_if_null);
48424931
48434932 size_t size = BN_num_bytes (num);
@@ -4847,24 +4936,38 @@ void DiffieHellman::GetField(const FunctionCallbackInfo<Value>& args,
48474936}
48484937
48494938void DiffieHellman::GetPrime (const FunctionCallbackInfo<Value>& args) {
4850- GetField (args, &DH::p, " p is null" );
4939+ GetField (args, [](const DH* dh) -> const BIGNUM* {
4940+ const BIGNUM* p;
4941+ DH_get0_pqg (dh, &p, nullptr , nullptr );
4942+ return p;
4943+ }, " p is null" );
48514944}
48524945
48534946
48544947void DiffieHellman::GetGenerator (const FunctionCallbackInfo<Value>& args) {
4855- GetField (args, &DH::g, " g is null" );
4948+ GetField (args, [](const DH* dh) -> const BIGNUM* {
4949+ const BIGNUM* g;
4950+ DH_get0_pqg (dh, nullptr , nullptr , &g);
4951+ return g;
4952+ }, " g is null" );
48564953}
48574954
48584955
48594956void DiffieHellman::GetPublicKey (const FunctionCallbackInfo<Value>& args) {
4860- GetField (args, &DH::pub_key,
4861- " No public key - did you forget to generate one?" );
4957+ GetField (args, [](const DH* dh) -> const BIGNUM* {
4958+ const BIGNUM* pub_key;
4959+ DH_get0_key (dh, &pub_key, nullptr );
4960+ return pub_key;
4961+ }, " No public key - did you forget to generate one?" );
48624962}
48634963
48644964
48654965void DiffieHellman::GetPrivateKey (const FunctionCallbackInfo<Value>& args) {
4866- GetField (args, &DH::priv_key,
4867- " No private key - did you forget to generate one?" );
4966+ GetField (args, [](const DH* dh) -> const BIGNUM* {
4967+ const BIGNUM* priv_key;
4968+ DH_get0_key (dh, nullptr , &priv_key);
4969+ return priv_key;
4970+ }, " No private key - did you forget to generate one?" );
48684971}
48694972
48704973
@@ -4940,16 +5043,14 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
49405043 args.GetReturnValue ().Set (rc);
49415044}
49425045
4943-
49445046void DiffieHellman::SetKey (const v8::FunctionCallbackInfo<v8::Value>& args,
4945- BIGNUM* (DH::*field ), const char * what) {
5047+ void (*set_field)(DH*, BIGNUM* ), const char * what) {
49465048 Environment* env = Environment::GetCurrent (args);
49475049
49485050 DiffieHellman* dh;
49495051 ASSIGN_OR_RETURN_UNWRAP (&dh, args.Holder ());
49505052 if (!dh->initialised_ ) return env->ThrowError (" Not initialized" );
49515053
4952- BIGNUM** num = &((dh->dh )->*field);
49535054 char errmsg[64 ];
49545055
49555056 if (args.Length () == 0 ) {
@@ -4962,19 +5063,28 @@ void DiffieHellman::SetKey(const v8::FunctionCallbackInfo<v8::Value>& args,
49625063 return env->ThrowTypeError (errmsg);
49635064 }
49645065
4965- *num = BN_bin2bn (reinterpret_cast <unsigned char *>(Buffer::Data (args[0 ])),
4966- Buffer::Length (args[0 ]), *num);
4967- CHECK_NE (*num, nullptr );
5066+ BIGNUM* num =
5067+ BN_bin2bn (reinterpret_cast <unsigned char *>(Buffer::Data (args[0 ])),
5068+ Buffer::Length (args[0 ]), nullptr );
5069+ CHECK_NE (num, nullptr );
5070+ set_field (dh->dh , num);
49685071}
49695072
49705073
49715074void DiffieHellman::SetPublicKey (const FunctionCallbackInfo<Value>& args) {
4972- SetKey (args, &DH::pub_key, " Public key" );
5075+ SetKey (args, [](DH* dh, BIGNUM* num) { DH_set0_key (dh, num, nullptr ); },
5076+ " Public key" );
49735077}
49745078
4975-
49765079void DiffieHellman::SetPrivateKey (const FunctionCallbackInfo<Value>& args) {
4977- SetKey (args, &DH::priv_key, " Private key" );
5080+ #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
5081+ OPENSSL_VERSION_NUMBER < 0x10100070L
5082+ // Older versions of OpenSSL 1.1.0 have a DH_set0_key which does not work for
5083+ // Node. See https://github.com/openssl/openssl/pull/4384.
5084+ #error "OpenSSL 1.1.0 revisions before 1.1.0g are not supported"
5085+ #endif
5086+ SetKey (args, [](DH* dh, BIGNUM* num) { DH_set0_key (dh, nullptr , num); },
5087+ " Private key" );
49785088}
49795089
49805090
0 commit comments