@@ -114,6 +114,77 @@ using v8::Value;
114114
115115
116116#if OPENSSL_VERSION_NUMBER < 0x10100000L
117+ static void RSA_get0_key (const RSA* r, const BIGNUM** n, const BIGNUM** e,
118+ const BIGNUM** d) {
119+ if (n != nullptr ) {
120+ *n = r->n ;
121+ }
122+ if (e != nullptr ) {
123+ *e = r->e ;
124+ }
125+ if (d != nullptr ) {
126+ *d = r->d ;
127+ }
128+ }
129+
130+ static void DH_get0_pqg (const DH* dh, const BIGNUM** p, const BIGNUM** q,
131+ const BIGNUM** g) {
132+ if (p != nullptr ) {
133+ *p = dh->p ;
134+ }
135+ if (q != nullptr ) {
136+ *q = dh->q ;
137+ }
138+ if (g != nullptr ) {
139+ *g = dh->g ;
140+ }
141+ }
142+
143+ static int DH_set0_pqg (DH* dh, BIGNUM* p, BIGNUM* q, BIGNUM* g) {
144+ if ((dh->p == nullptr && p == nullptr ) ||
145+ (dh->g == nullptr && g == nullptr )) {
146+ return 0 ;
147+ }
148+
149+ if (p != nullptr ) {
150+ BN_free (dh->p );
151+ dh->p = p;
152+ }
153+ if (q != nullptr ) {
154+ BN_free (dh->q );
155+ dh->q = q;
156+ }
157+ if (g != nullptr ) {
158+ BN_free (dh->g );
159+ dh->g = g;
160+ }
161+
162+ return 1 ;
163+ }
164+
165+ static void DH_get0_key (const DH* dh, const BIGNUM** pub_key,
166+ const BIGNUM** priv_key) {
167+ if (pub_key != nullptr ) {
168+ *pub_key = dh->pub_key ;
169+ }
170+ if (priv_key != nullptr ) {
171+ *priv_key = dh->priv_key ;
172+ }
173+ }
174+
175+ static int DH_set0_key (DH* dh, BIGNUM* pub_key, BIGNUM* priv_key) {
176+ if (pub_key != nullptr ) {
177+ BN_free (dh->pub_key );
178+ dh->pub_key = pub_key;
179+ }
180+ if (priv_key != nullptr ) {
181+ BN_free (dh->priv_key );
182+ dh->priv_key = priv_key;
183+ }
184+
185+ return 1 ;
186+ }
187+
117188static void SSL_SESSION_get0_ticket (const SSL_SESSION* s,
118189 const unsigned char ** tick, size_t * len) {
119190 *len = s->tlsext_ticklen ;
@@ -1015,7 +1086,9 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo<Value>& args) {
10151086 if (dh == nullptr )
10161087 return ;
10171088
1018- const int size = BN_num_bits (dh->p );
1089+ const BIGNUM* p;
1090+ DH_get0_pqg (dh, &p, nullptr , nullptr );
1091+ const int size = BN_num_bits (p);
10191092 if (size < 1024 ) {
10201093 return env->ThrowError (" DH parameter is less than 1024 bits" );
10211094 } else if (size < 2048 ) {
@@ -1635,14 +1708,17 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
16351708 rsa = EVP_PKEY_get1_RSA (pkey);
16361709
16371710 if (rsa != nullptr ) {
1638- BN_print (bio, rsa->n );
1711+ const BIGNUM* n;
1712+ const BIGNUM* e;
1713+ RSA_get0_key (rsa, &n, &e, nullptr );
1714+ BN_print (bio, n);
16391715 BIO_get_mem_ptr (bio, &mem);
16401716 info->Set (env->modulus_string (),
16411717 String::NewFromUtf8 (env->isolate (), mem->data ,
16421718 String::kNormalString , mem->length ));
16431719 (void ) BIO_reset (bio);
16441720
1645- uint64_t exponent_word = static_cast <uint64_t >(BN_get_word (rsa-> e ));
1721+ uint64_t exponent_word = static_cast <uint64_t >(BN_get_word (e));
16461722 uint32_t lo = static_cast <uint32_t >(exponent_word);
16471723 uint32_t hi = static_cast <uint32_t >(exponent_word >> 32 );
16481724 if (hi == 0 ) {
@@ -4633,10 +4709,15 @@ bool DiffieHellman::Init(int primeLength, int g) {
46334709
46344710bool DiffieHellman::Init (const char * p, int p_len, int g) {
46354711 dh = DH_new ();
4636- dh->p = BN_bin2bn (reinterpret_cast <const unsigned char *>(p), p_len, 0 );
4637- dh->g = BN_new ();
4638- if (!BN_set_word (dh->g , g))
4712+ BIGNUM* bn_p =
4713+ BN_bin2bn (reinterpret_cast <const unsigned char *>(p), p_len, nullptr );
4714+ BIGNUM* bn_g = BN_new ();
4715+ if (!BN_set_word (bn_g, g) ||
4716+ !DH_set0_pqg (dh, bn_p, nullptr , bn_g)) {
4717+ BN_free (bn_p);
4718+ BN_free (bn_g);
46394719 return false ;
4720+ }
46404721 bool result = VerifyContext ();
46414722 if (!result)
46424723 return false ;
@@ -4647,8 +4728,13 @@ bool DiffieHellman::Init(const char* p, int p_len, int g) {
46474728
46484729bool DiffieHellman::Init (const char * p, int p_len, const char * g, int g_len) {
46494730 dh = DH_new ();
4650- dh->p = BN_bin2bn (reinterpret_cast <const unsigned char *>(p), p_len, 0 );
4651- dh->g = BN_bin2bn (reinterpret_cast <const unsigned char *>(g), g_len, 0 );
4731+ BIGNUM *bn_p = BN_bin2bn (reinterpret_cast <const unsigned char *>(p), p_len, 0 );
4732+ BIGNUM *bn_g = BN_bin2bn (reinterpret_cast <const unsigned char *>(g), g_len, 0 );
4733+ if (!DH_set0_pqg (dh, bn_p, nullptr , bn_g)) {
4734+ BN_free (bn_p);
4735+ BN_free (bn_g);
4736+ return false ;
4737+ }
46524738 bool result = VerifyContext ();
46534739 if (!result)
46544740 return false ;
@@ -4736,22 +4822,25 @@ void DiffieHellman::GenerateKeys(const FunctionCallbackInfo<Value>& args) {
47364822 return ThrowCryptoError (env, ERR_get_error (), " Key generation failed" );
47374823 }
47384824
4739- size_t size = BN_num_bytes (diffieHellman->dh ->pub_key );
4825+ const BIGNUM* pub_key;
4826+ DH_get0_key (diffieHellman->dh , &pub_key, nullptr );
4827+ size_t size = BN_num_bytes (pub_key);
47404828 char * data = Malloc (size);
4741- BN_bn2bin (diffieHellman-> dh -> pub_key , reinterpret_cast <unsigned char *>(data));
4829+ BN_bn2bin (pub_key, reinterpret_cast <unsigned char *>(data));
47424830 args.GetReturnValue ().Set (Buffer::New (env, data, size).ToLocalChecked ());
47434831}
47444832
47454833
47464834void DiffieHellman::GetField (const FunctionCallbackInfo<Value>& args,
4747- BIGNUM* (DH::*field), const char * err_if_null) {
4835+ const BIGNUM* (*get_field)(const DH*),
4836+ const char * err_if_null) {
47484837 Environment* env = Environment::GetCurrent (args);
47494838
47504839 DiffieHellman* dh;
47514840 ASSIGN_OR_RETURN_UNWRAP (&dh, args.Holder ());
47524841 if (!dh->initialised_ ) return env->ThrowError (" Not initialized" );
47534842
4754- const BIGNUM* num = (dh->dh )->*field ;
4843+ const BIGNUM* num = get_field (dh->dh );
47554844 if (num == nullptr ) return env->ThrowError (err_if_null);
47564845
47574846 size_t size = BN_num_bytes (num);
@@ -4761,24 +4850,38 @@ void DiffieHellman::GetField(const FunctionCallbackInfo<Value>& args,
47614850}
47624851
47634852void DiffieHellman::GetPrime (const FunctionCallbackInfo<Value>& args) {
4764- GetField (args, &DH::p, " p is null" );
4853+ GetField (args, [](const DH* dh) -> const BIGNUM* {
4854+ const BIGNUM* p;
4855+ DH_get0_pqg (dh, &p, nullptr , nullptr );
4856+ return p;
4857+ }, " p is null" );
47654858}
47664859
47674860
47684861void DiffieHellman::GetGenerator (const FunctionCallbackInfo<Value>& args) {
4769- GetField (args, &DH::g, " g is null" );
4862+ GetField (args, [](const DH* dh) -> const BIGNUM* {
4863+ const BIGNUM* g;
4864+ DH_get0_pqg (dh, nullptr , nullptr , &g);
4865+ return g;
4866+ }, " g is null" );
47704867}
47714868
47724869
47734870void DiffieHellman::GetPublicKey (const FunctionCallbackInfo<Value>& args) {
4774- GetField (args, &DH::pub_key,
4775- " No public key - did you forget to generate one?" );
4871+ GetField (args, [](const DH* dh) -> const BIGNUM* {
4872+ const BIGNUM* pub_key;
4873+ DH_get0_key (dh, &pub_key, nullptr );
4874+ return pub_key;
4875+ }, " No public key - did you forget to generate one?" );
47764876}
47774877
47784878
47794879void DiffieHellman::GetPrivateKey (const FunctionCallbackInfo<Value>& args) {
4780- GetField (args, &DH::priv_key,
4781- " No private key - did you forget to generate one?" );
4880+ GetField (args, [](const DH* dh) -> const BIGNUM* {
4881+ const BIGNUM* priv_key;
4882+ DH_get0_key (dh, nullptr , &priv_key);
4883+ return priv_key;
4884+ }, " No private key - did you forget to generate one?" );
47824885}
47834886
47844887
@@ -4854,16 +4957,14 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
48544957 args.GetReturnValue ().Set (rc);
48554958}
48564959
4857-
48584960void DiffieHellman::SetKey (const v8::FunctionCallbackInfo<v8::Value>& args,
4859- BIGNUM* (DH::*field ), const char * what) {
4961+ void (*set_field)(DH*, BIGNUM* ), const char * what) {
48604962 Environment* env = Environment::GetCurrent (args);
48614963
48624964 DiffieHellman* dh;
48634965 ASSIGN_OR_RETURN_UNWRAP (&dh, args.Holder ());
48644966 if (!dh->initialised_ ) return env->ThrowError (" Not initialized" );
48654967
4866- BIGNUM** num = &((dh->dh )->*field);
48674968 char errmsg[64 ];
48684969
48694970 if (args.Length () == 0 ) {
@@ -4876,19 +4977,28 @@ void DiffieHellman::SetKey(const v8::FunctionCallbackInfo<v8::Value>& args,
48764977 return env->ThrowTypeError (errmsg);
48774978 }
48784979
4879- *num = BN_bin2bn (reinterpret_cast <unsigned char *>(Buffer::Data (args[0 ])),
4880- Buffer::Length (args[0 ]), *num);
4881- CHECK_NE (*num, nullptr );
4980+ BIGNUM* num =
4981+ BN_bin2bn (reinterpret_cast <unsigned char *>(Buffer::Data (args[0 ])),
4982+ Buffer::Length (args[0 ]), nullptr );
4983+ CHECK_NE (num, nullptr );
4984+ set_field (dh->dh , num);
48824985}
48834986
48844987
48854988void DiffieHellman::SetPublicKey (const FunctionCallbackInfo<Value>& args) {
4886- SetKey (args, &DH::pub_key, " Public key" );
4989+ SetKey (args, [](DH* dh, BIGNUM* num) { DH_set0_key (dh, num, nullptr ); },
4990+ " Public key" );
48874991}
48884992
4889-
48904993void DiffieHellman::SetPrivateKey (const FunctionCallbackInfo<Value>& args) {
4891- SetKey (args, &DH::priv_key, " Private key" );
4994+ #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
4995+ OPENSSL_VERSION_NUMBER < 0x10100070L
4996+ // Older versions of OpenSSL 1.1.0 have a DH_set0_key which does not work for
4997+ // Node. See https://github.com/openssl/openssl/pull/4384.
4998+ #error "OpenSSL 1.1.0 revisions before 1.1.0g are not supported"
4999+ #endif
5000+ SetKey (args, [](DH* dh, BIGNUM* num) { DH_set0_key (dh, nullptr , num); },
5001+ " Private key" );
48925002}
48935003
48945004
0 commit comments