]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
OpenSSL: don't use direct access to the internal of RSA
authorEmmanuel Deloget <logout@free.fr>
Mon, 12 Jun 2017 13:43:25 +0000 (15:43 +0200)
committerGert Doering <gert@greenie.muc.de>
Sun, 18 Jun 2017 10:11:35 +0000 (12:11 +0200)
OpenSSL 1.1 does not allow us to directly access the internal of
any data type, including RSA. We have to use the defined
functions to do so.

Compatibility with OpenSSL 1.0 is kept by defining the corresponding
functions when they are not found in the library.

Signed-off-by: Emmanuel Deloget <logout@free.fr>
Acked-by: Steffan Karger <steffan.karger@fox-it.com>
Message-Id: <20170612134330.20971-4-logout@free.fr>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14790.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
(cherry picked from commit f7780af6f1aaffcbbfb8b4dde0f2af052f84b28a)

configure.ac
src/openvpn/openssl_compat.h
src/openvpn/ssl_openssl.c

index 16a6fd809516cd9af9b436f4dfba1dc75678f38c..5f7b4f0aa03d8e0855ae7c7efcef10663ff7c759 100644 (file)
@@ -908,6 +908,10 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then
                        EVP_PKEY_id \
                        EVP_PKEY_get0_RSA \
                        EVP_PKEY_get0_DSA \
+                       RSA_set_flags \
+                       RSA_bits \
+                       RSA_get0_key \
+                       RSA_set0_key \
                        RSA_meth_new \
                        RSA_meth_free \
                        RSA_meth_set_pub_enc \
index 604985953201f64b8a17c82364389934580ba4ad..e3f20b739e0f3f099ae829dff3940d038ab71ac5 100644 (file)
@@ -175,6 +175,106 @@ EVP_PKEY_get0_DSA(EVP_PKEY *pkey)
 }
 #endif
 
+#if !defined(HAVE_RSA_SET_FLAGS)
+/**
+ * Set the RSA flags
+ *
+ * @param rsa                 The RSA object
+ * @param flags               New flags value
+ */
+static inline void
+RSA_set_flags(RSA *rsa, int flags)
+{
+    if (rsa)
+    {
+        rsa->flags = flags;
+    }
+}
+#endif
+
+#if !defined(HAVE_RSA_GET0_KEY)
+/**
+ * Get the RSA parameters
+ *
+ * @param rsa                 The RSA object
+ * @param n                   The @c n parameter
+ * @param e                   The @c e parameter
+ * @param d                   The @c d parameter
+ */
+static inline void
+RSA_get0_key(const RSA *rsa, const BIGNUM **n,
+             const BIGNUM **e, const BIGNUM **d)
+{
+    if (n != NULL)
+    {
+        *n = rsa ? rsa->n : NULL;
+    }
+    if (e != NULL)
+    {
+        *e = rsa ? rsa->e : NULL;
+    }
+    if (d != NULL)
+    {
+        *d = rsa ? rsa->d : NULL;
+    }
+}
+#endif
+
+#if !defined(HAVE_RSA_SET0_KEY)
+/**
+ * Set the RSA parameters
+ *
+ * @param rsa                 The RSA object
+ * @param n                   The @c n parameter
+ * @param e                   The @c e parameter
+ * @param d                   The @c d parameter
+ * @return                    1 on success, 0 on error
+ */
+static inline int
+RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d)
+{
+    if ((rsa->n == NULL && n == NULL)
+        || (rsa->e == NULL && e == NULL))
+    {
+        return 0;
+    }
+
+    if (n != NULL)
+    {
+        BN_free(rsa->n);
+        rsa->n = n;
+    }
+    if (e != NULL)
+    {
+        BN_free(rsa->e);
+        rsa->e = e;
+    }
+    if (d != NULL)
+    {
+        BN_free(rsa->d);
+        rsa->d = d;
+    }
+
+    return 1;
+}
+#endif
+
+#if !defined(HAVE_RSA_BITS)
+/**
+ * Number of significant RSA bits
+ *
+ * @param rsa                The RSA object ; shall not be NULL
+ * @return                   The number of RSA bits or 0 on error
+ */
+static inline int
+RSA_bits(const RSA *rsa)
+{
+    const BIGNUM *n = NULL;
+    RSA_get0_key(rsa, &n, NULL, NULL);
+    return n ? BN_num_bits(n) : 0;
+}
+#endif
+
 #if !defined(HAVE_RSA_METH_NEW)
 /**
  * Allocate a new RSA method object
index a0e810098f70b3a371cb6d16fc25c20b4ac583c2..50ae29f971ae16e63f2fdd62f704c676990b7781 100644 (file)
@@ -976,10 +976,13 @@ rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i
 
 /* called at RSA_free */
 static int
-rsa_finish(RSA *rsa)
+openvpn_extkey_rsa_finish(RSA *rsa)
 {
-    RSA_meth_free(rsa->meth);
-    rsa->meth = NULL;
+    /* meth was allocated in tls_ctx_use_external_private_key() ; since
+     * this function is called when the parent RSA object is destroyed,
+     * it is no longer used after this point so kill it. */
+    const RSA_METHOD *meth = RSA_get_method(rsa);
+    RSA_meth_free((RSA_METHOD *)meth);
     return 1;
 }
 
@@ -1061,7 +1064,7 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,
     RSA_meth_set_priv_enc(rsa_meth, rsa_priv_enc);
     RSA_meth_set_priv_dec(rsa_meth, rsa_priv_dec);
     RSA_meth_set_init(rsa_meth, NULL);
-    RSA_meth_set_finish(rsa_meth, rsa_finish);
+    RSA_meth_set_finish(rsa_meth, openvpn_extkey_rsa_finish);
     RSA_meth_set0_app_data(rsa_meth, NULL);
 
     /* allocate RSA object */
@@ -1078,8 +1081,11 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,
     pub_rsa = EVP_PKEY_get0_RSA(pkey);
 
     /* initialize RSA object */
-    rsa->n = BN_dup(pub_rsa->n);
-    rsa->flags |= RSA_FLAG_EXT_PKEY;
+    const BIGNUM *n = NULL;
+    const BIGNUM *e = NULL;
+    RSA_get0_key(pub_rsa, &n, &e, NULL);
+    RSA_set0_key(rsa, BN_dup(n), BN_dup(e), NULL);
+    RSA_set_flags(rsa, RSA_flags(rsa) | RSA_FLAG_EXT_PKEY);
     if (!RSA_set_method(rsa, rsa_meth))
     {
         goto err;
@@ -1680,11 +1686,11 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix)
         EVP_PKEY *pkey = X509_get_pubkey(cert);
         if (pkey != NULL)
         {
-            if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA && EVP_PKEY_get0_RSA(pkey) != NULL
-                && pkey->pkey.rsa->n != NULL)
+            if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA && EVP_PKEY_get0_RSA(pkey) != NULL)
             {
+                RSA *rsa = EVP_PKEY_get0_RSA(pkey);
                 openvpn_snprintf(s2, sizeof(s2), ", %d bit RSA",
-                                 BN_num_bits(pkey->pkey.rsa->n));
+                                 RSA_bits(rsa));
             }
             else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA && EVP_PKEY_get0_DSA(pkey) != NULL
                      && pkey->pkey.dsa->p != NULL)