}
#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
/* 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;
}
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 */
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;
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)