]> granicus.if.org Git - php/commitdiff
Fix bug #73478 (openssl_pkey_new() generates wrong pub/priv keys with Diffie Hellman)
authorJakub Zelenka <bukka@php.net>
Sun, 20 Nov 2016 20:06:39 +0000 (20:06 +0000)
committerJakub Zelenka <bukka@php.net>
Sun, 20 Nov 2016 20:06:39 +0000 (20:06 +0000)
NEWS
ext/openssl/openssl.c
ext/openssl/tests/bug73478.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index ec2ef165f8074b8321dc42ef77b9cd6020cdf791..4f2bd9518d78b665a18836762b4e503d35ec4899 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,10 @@ PHP                                                                        NEWS
 - Opcache:
   . Fixed bug #69090 (check cached files permissions)
 
+- OpenSSL:
+  . Fixed bug #73478 (openssl_pkey_new() generates wrong pub/priv keys with
+    Diffie Hellman). (Jakub Zelenka)
+
 - PCRE:
   . Fixed bug #73483 (Segmentation fault on pcre_replace_callback). (Laruence)
 
index 528d8235a570a6418dd80e412ba2f8ec67c43a74..7e8d6496598ffb68972f12c7fe918669cce36e2c 100644 (file)
@@ -4091,6 +4091,47 @@ zend_bool php_openssl_pkey_init_dsa(DSA *dsa, zval *data)
 }
 /* }}} */
 
+/* {{{ php_openssl_dh_pub_from_priv */
+static BIGNUM *php_openssl_dh_pub_from_priv(DH *dh, BIGNUM *priv_key, BIGNUM *g, BIGNUM *p)
+{
+       BIGNUM *pub_key, *priv_key_const_time;
+       BN_CTX *ctx;
+
+       pub_key = BN_new();
+       if (pub_key == NULL) {
+               php_openssl_store_errors();
+               return NULL;
+       }
+
+       priv_key_const_time = BN_new();
+       if (priv_key_const_time == NULL) {
+               BN_free(pub_key);
+               php_openssl_store_errors();
+               return NULL;
+       }
+       ctx = BN_CTX_new();
+       if (priv_key_const_time == NULL) {
+               BN_free(pub_key);
+               BN_free(priv_key_const_time);
+               php_openssl_store_errors();
+               return NULL;
+       }
+
+       BN_with_flags(priv_key_const_time, priv_key, BN_FLG_CONSTTIME);
+
+       if (!BN_mod_exp_mont(pub_key, g, priv_key_const_time, p, ctx, NULL)) {
+               BN_free(pub_key);
+               php_openssl_store_errors();
+               pub_key = NULL;
+       }
+
+       BN_free(priv_key_const_time);
+       BN_CTX_free(ctx);
+
+       return pub_key;
+}
+/* }}} */
+
 /* {{{ php_openssl_pkey_init_dh */
 zend_bool php_openssl_pkey_init_dh(DH *dh, zval *data)
 {
@@ -4108,6 +4149,13 @@ zend_bool php_openssl_pkey_init_dh(DH *dh, zval *data)
        if (pub_key) {
                return DH_set0_key(dh, pub_key, priv_key);
        }
+       if (priv_key) {
+               pub_key = php_openssl_dh_pub_from_priv(dh, priv_key, g, p);
+               if (pub_key == NULL) {
+                       return 0;
+               }
+               return DH_set0_key(dh, pub_key, priv_key);
+       }
 
        /* generate key */
        PHP_OPENSSL_RAND_ADD_TIME();
diff --git a/ext/openssl/tests/bug73478.phpt b/ext/openssl/tests/bug73478.phpt
new file mode 100644 (file)
index 0000000..1dfc584
--- /dev/null
@@ -0,0 +1,25 @@
+--TEST--
+Bug #73478: openssl_pkey_new() generates wrong pub/priv keys with Diffie Hellman
+--SKIPIF--
+<?php
+if (!extension_loaded("openssl")) die("skip openssl not loaded");
+?>
+--FILE--
+<?php
+$details = [
+  'p' => base64_decode('3Pk6C4g5cuwOGZiaxaLOMQ4dN3F+jZVxu3Yjcxhm5h73Wi4niYsFf5iRwuJ6Y5w/KbYIFFgc07LKOYbSaDcFV31FwuflLcgcehcYduXOp0sUSL/frxiCjv0lGfFOReOCZjSvGUnltTXMgppIO4p2Ij5dSQolfwW9/xby+yLFg6s='),
+  'g' => base64_decode('Ag=='),
+  'priv_key' => base64_decode('jUdcV++P/m7oUodWiqKqKXZVenHRuj92Ig6Fmzs7QlqVdUc5mNBxmEWjug+ObffanPpOeab/LyXwjNMzevtBz3tW4oROau++9EIMJVVQr8fW9zdYBJcYieC5l4t8nRj5/Uu/Z0G2rWVLBleSi28mqqNEvnUs7uxYxrar69lwQYs=')
+];
+
+$opensslKeyResource = openssl_pkey_new(['dh' => $details]);
+$data = openssl_pkey_get_details($opensslKeyResource);
+
+printf("Private key:\n%s\n", base64_encode($data['dh']['priv_key']));
+printf("Public key:\n%s\n", base64_encode($data['dh']['pub_key']));
+?>
+--EXPECT--
+Private key:
+jUdcV++P/m7oUodWiqKqKXZVenHRuj92Ig6Fmzs7QlqVdUc5mNBxmEWjug+ObffanPpOeab/LyXwjNMzevtBz3tW4oROau++9EIMJVVQr8fW9zdYBJcYieC5l4t8nRj5/Uu/Z0G2rWVLBleSi28mqqNEvnUs7uxYxrar69lwQYs=
+Public key:
+0DmJUe9dr02pAtVoGyLHdC+rfBU3mDCelKGPXRDFHofx6mFfN2gcZCmp/ab4ezDXfpIBOatpVdbn2fTNUGo64DtKE2WGTsZCl90RgrGUv8XW/4WDPXeE7g5u7KWHBG/LCE5+XsilE5P5/GIyqr9gsiudTmk+H/hiYZl9Smar9k0=