Fixed a bug in external key loading, where if no certificate file was
specified, the program would still try to use an external private key.
Signed-off-by: Adriaan de Jong <dejong@fox-it.com>
Acked-by: James Yonan <james@openvpn.net>
Signed-off-by: David Sommerseth <davids@redhat.com>
... | ... |
@@ -1602,140 +1602,6 @@ tls_deauthenticate (struct tls_multi *multi) |
1602 | 1602 |
} |
1603 | 1603 |
} |
1604 | 1604 |
|
1605 |
-#ifdef MANAGMENT_EXTERNAL_KEY |
|
1606 |
- |
|
1607 |
-/* encrypt */ |
|
1608 |
-static int |
|
1609 |
-rsa_pub_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) |
|
1610 |
-{ |
|
1611 |
- ASSERT(0); |
|
1612 |
- return -1; |
|
1613 |
-} |
|
1614 |
- |
|
1615 |
-/* verify arbitrary data */ |
|
1616 |
-static int |
|
1617 |
-rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) |
|
1618 |
-{ |
|
1619 |
- ASSERT(0); |
|
1620 |
- return -1; |
|
1621 |
-} |
|
1622 |
- |
|
1623 |
-/* decrypt */ |
|
1624 |
-static int |
|
1625 |
-rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) |
|
1626 |
-{ |
|
1627 |
- ASSERT(0); |
|
1628 |
- return -1; |
|
1629 |
-} |
|
1630 |
- |
|
1631 |
-/* called at RSA_free */ |
|
1632 |
-static int |
|
1633 |
-rsa_finish(RSA *rsa) |
|
1634 |
-{ |
|
1635 |
- free ((void*)rsa->meth); |
|
1636 |
- rsa->meth = NULL; |
|
1637 |
- return 1; |
|
1638 |
-} |
|
1639 |
- |
|
1640 |
-/* sign arbitrary data */ |
|
1641 |
-static int |
|
1642 |
-rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) |
|
1643 |
-{ |
|
1644 |
- /* optional app data in rsa->meth->app_data; */ |
|
1645 |
- char *in_b64 = NULL; |
|
1646 |
- char *out_b64 = NULL; |
|
1647 |
- int ret = -1; |
|
1648 |
- int len; |
|
1649 |
- |
|
1650 |
- if (padding != RSA_PKCS1_PADDING) |
|
1651 |
- { |
|
1652 |
- RSAerr (RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); |
|
1653 |
- goto done; |
|
1654 |
- } |
|
1655 |
- |
|
1656 |
- /* convert 'from' to base64 */ |
|
1657 |
- if (base64_encode (from, flen, &in_b64) <= 0) |
|
1658 |
- goto done; |
|
1659 |
- |
|
1660 |
- /* call MI for signature */ |
|
1661 |
- if (management) |
|
1662 |
- out_b64 = management_query_rsa_sig (management, in_b64); |
|
1663 |
- if (!out_b64) |
|
1664 |
- goto done; |
|
1665 |
- |
|
1666 |
- /* decode base64 signature to binary */ |
|
1667 |
- len = RSA_size(rsa); |
|
1668 |
- ret = base64_decode (out_b64, to, len); |
|
1669 |
- |
|
1670 |
- /* verify length */ |
|
1671 |
- if (ret != len) |
|
1672 |
- ret = -1; |
|
1673 |
- |
|
1674 |
- done: |
|
1675 |
- if (in_b64) |
|
1676 |
- free (in_b64); |
|
1677 |
- if (out_b64) |
|
1678 |
- free (out_b64); |
|
1679 |
- return ret; |
|
1680 |
-} |
|
1681 |
- |
|
1682 |
-static int |
|
1683 |
-use_external_private_key (SSL_CTX *ssl_ctx, X509 *cert) |
|
1684 |
-{ |
|
1685 |
- RSA *rsa = NULL; |
|
1686 |
- RSA *pub_rsa; |
|
1687 |
- RSA_METHOD *rsa_meth; |
|
1688 |
- |
|
1689 |
- /* allocate custom RSA method object */ |
|
1690 |
- ALLOC_OBJ_CLEAR (rsa_meth, RSA_METHOD); |
|
1691 |
- rsa_meth->name = "OpenVPN external private key RSA Method"; |
|
1692 |
- rsa_meth->rsa_pub_enc = rsa_pub_enc; |
|
1693 |
- rsa_meth->rsa_pub_dec = rsa_pub_dec; |
|
1694 |
- rsa_meth->rsa_priv_enc = rsa_priv_enc; |
|
1695 |
- rsa_meth->rsa_priv_dec = rsa_priv_dec; |
|
1696 |
- rsa_meth->init = NULL; |
|
1697 |
- rsa_meth->finish = rsa_finish; |
|
1698 |
- rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK; |
|
1699 |
- rsa_meth->app_data = NULL; |
|
1700 |
- |
|
1701 |
- /* allocate RSA object */ |
|
1702 |
- rsa = RSA_new(); |
|
1703 |
- if (rsa == NULL) |
|
1704 |
- { |
|
1705 |
- SSLerr(SSL_F_SSL_USE_PRIVATEKEY, ERR_R_MALLOC_FAILURE); |
|
1706 |
- goto err; |
|
1707 |
- } |
|
1708 |
- |
|
1709 |
- /* get the public key */ |
|
1710 |
- ASSERT(cert->cert_info->key->pkey); /* NULL before SSL_CTX_use_certificate() is called */ |
|
1711 |
- pub_rsa = cert->cert_info->key->pkey->pkey.rsa; |
|
1712 |
- |
|
1713 |
- /* initialize RSA object */ |
|
1714 |
- rsa->n = BN_dup(pub_rsa->n); |
|
1715 |
- rsa->flags |= RSA_FLAG_EXT_PKEY; |
|
1716 |
- if (!RSA_set_method(rsa, rsa_meth)) |
|
1717 |
- goto err; |
|
1718 |
- |
|
1719 |
- /* bind our custom RSA object to ssl_ctx */ |
|
1720 |
- if (!SSL_CTX_use_RSAPrivateKey(ssl_ctx, rsa)) |
|
1721 |
- goto err; |
|
1722 |
- |
|
1723 |
- RSA_free(rsa); /* doesn't necessarily free, just decrements refcount */ |
|
1724 |
- return 1; |
|
1725 |
- |
|
1726 |
- err: |
|
1727 |
- if (rsa) |
|
1728 |
- RSA_free(rsa); |
|
1729 |
- else |
|
1730 |
- { |
|
1731 |
- if (rsa_meth) |
|
1732 |
- free(rsa_meth); |
|
1733 |
- } |
|
1734 |
- return 0; |
|
1735 |
-} |
|
1736 |
- |
|
1737 |
-#endif |
|
1738 |
- |
|
1739 | 1605 |
#if ENABLE_INLINE_FILES |
1740 | 1606 |
|
1741 | 1607 |
static int |
... | ... |
@@ -1891,17 +1757,13 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx) |
1891 | 1891 |
} |
1892 | 1892 |
#endif |
1893 | 1893 |
#ifdef MANAGMENT_EXTERNAL_KEY |
1894 |
- else if (options->management_flags & MF_EXTERNAL_KEY) |
|
1894 |
+ else if ((options->management_flags & MF_EXTERNAL_KEY) && options->cert_file) |
|
1895 | 1895 |
{ |
1896 | 1896 |
X509 *my_cert = NULL; |
1897 |
+ tls_ctx_load_cert_file(new_ctx, options->cert_file, options->cert_file_inline, |
|
1898 |
+ &my_cert); |
|
1899 |
+ tls_ctx_use_external_private_key(new_ctx, my_cert); |
|
1897 | 1900 |
|
1898 |
- if (options->cert_file) |
|
1899 |
- { |
|
1900 |
- tls_ctx_load_cert_file(new_ctx, options->cert_file, options->cert_file_inline, &my_cert); |
|
1901 |
- } |
|
1902 |
- ASSERT (my_cert); |
|
1903 |
- if (!use_external_private_key(new_ctx->ctx, my_cert)) |
|
1904 |
- msg (M_SSLERR, "Cannot enable SSL external private key capability"); |
|
1905 | 1901 |
X509_free(my_cert); |
1906 | 1902 |
} |
1907 | 1903 |
#endif |
... | ... |
@@ -209,6 +209,23 @@ int tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file |
209 | 209 |
#endif |
210 | 210 |
); |
211 | 211 |
|
212 |
+#ifdef MANAGMENT_EXTERNAL_KEY |
|
213 |
+ |
|
214 |
+/** |
|
215 |
+ * Tell the management interface to load the external private key matching |
|
216 |
+ * the given certificate. |
|
217 |
+ * |
|
218 |
+ * @param ctx TLS context to use |
|
219 |
+ * @param cert The certificate file to load the private key for |
|
220 |
+ * "[[INLINE]]" in the case of inline files. |
|
221 |
+ * |
|
222 |
+ * @return 1 if an error occurred, 0 if parsing was |
|
223 |
+ * successful. |
|
224 |
+ */ |
|
225 |
+int tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, X509 *cert); |
|
226 |
+ |
|
227 |
+#endif |
|
228 |
+ |
|
212 | 229 |
/** |
213 | 230 |
* Show the TLS ciphers that are available for us to use in the OpenSSL |
214 | 231 |
* library. |
... | ... |
@@ -507,6 +507,144 @@ tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file |
507 | 507 |
|
508 | 508 |
} |
509 | 509 |
|
510 |
+#ifdef MANAGMENT_EXTERNAL_KEY |
|
511 |
+ |
|
512 |
+/* encrypt */ |
|
513 |
+static int |
|
514 |
+rsa_pub_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) |
|
515 |
+{ |
|
516 |
+ ASSERT(0); |
|
517 |
+ return -1; |
|
518 |
+} |
|
519 |
+ |
|
520 |
+/* verify arbitrary data */ |
|
521 |
+static int |
|
522 |
+rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) |
|
523 |
+{ |
|
524 |
+ ASSERT(0); |
|
525 |
+ return -1; |
|
526 |
+} |
|
527 |
+ |
|
528 |
+/* decrypt */ |
|
529 |
+static int |
|
530 |
+rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) |
|
531 |
+{ |
|
532 |
+ ASSERT(0); |
|
533 |
+ return -1; |
|
534 |
+} |
|
535 |
+ |
|
536 |
+/* called at RSA_free */ |
|
537 |
+static int |
|
538 |
+rsa_finish(RSA *rsa) |
|
539 |
+{ |
|
540 |
+ free ((void*)rsa->meth); |
|
541 |
+ rsa->meth = NULL; |
|
542 |
+ return 1; |
|
543 |
+} |
|
544 |
+ |
|
545 |
+/* sign arbitrary data */ |
|
546 |
+static int |
|
547 |
+rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) |
|
548 |
+{ |
|
549 |
+ /* optional app data in rsa->meth->app_data; */ |
|
550 |
+ char *in_b64 = NULL; |
|
551 |
+ char *out_b64 = NULL; |
|
552 |
+ int ret = -1; |
|
553 |
+ int len; |
|
554 |
+ |
|
555 |
+ if (padding != RSA_PKCS1_PADDING) |
|
556 |
+ { |
|
557 |
+ RSAerr (RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); |
|
558 |
+ goto done; |
|
559 |
+ } |
|
560 |
+ |
|
561 |
+ /* convert 'from' to base64 */ |
|
562 |
+ if (base64_encode (from, flen, &in_b64) <= 0) |
|
563 |
+ goto done; |
|
564 |
+ |
|
565 |
+ /* call MI for signature */ |
|
566 |
+ if (management) |
|
567 |
+ out_b64 = management_query_rsa_sig (management, in_b64); |
|
568 |
+ if (!out_b64) |
|
569 |
+ goto done; |
|
570 |
+ |
|
571 |
+ /* decode base64 signature to binary */ |
|
572 |
+ len = RSA_size(rsa); |
|
573 |
+ ret = base64_decode (out_b64, to, len); |
|
574 |
+ |
|
575 |
+ /* verify length */ |
|
576 |
+ if (ret != len) |
|
577 |
+ ret = -1; |
|
578 |
+ |
|
579 |
+ done: |
|
580 |
+ if (in_b64) |
|
581 |
+ free (in_b64); |
|
582 |
+ if (out_b64) |
|
583 |
+ free (out_b64); |
|
584 |
+ return ret; |
|
585 |
+} |
|
586 |
+ |
|
587 |
+int |
|
588 |
+tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, X509 *cert) |
|
589 |
+{ |
|
590 |
+ RSA *rsa = NULL; |
|
591 |
+ RSA *pub_rsa; |
|
592 |
+ RSA_METHOD *rsa_meth; |
|
593 |
+ |
|
594 |
+ ASSERT (NULL != ctx); |
|
595 |
+ ASSERT (NULL != cert); |
|
596 |
+ |
|
597 |
+ /* allocate custom RSA method object */ |
|
598 |
+ ALLOC_OBJ_CLEAR (rsa_meth, RSA_METHOD); |
|
599 |
+ rsa_meth->name = "OpenVPN external private key RSA Method"; |
|
600 |
+ rsa_meth->rsa_pub_enc = rsa_pub_enc; |
|
601 |
+ rsa_meth->rsa_pub_dec = rsa_pub_dec; |
|
602 |
+ rsa_meth->rsa_priv_enc = rsa_priv_enc; |
|
603 |
+ rsa_meth->rsa_priv_dec = rsa_priv_dec; |
|
604 |
+ rsa_meth->init = NULL; |
|
605 |
+ rsa_meth->finish = rsa_finish; |
|
606 |
+ rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK; |
|
607 |
+ rsa_meth->app_data = NULL; |
|
608 |
+ |
|
609 |
+ /* allocate RSA object */ |
|
610 |
+ rsa = RSA_new(); |
|
611 |
+ if (rsa == NULL) |
|
612 |
+ { |
|
613 |
+ SSLerr(SSL_F_SSL_USE_PRIVATEKEY, ERR_R_MALLOC_FAILURE); |
|
614 |
+ goto err; |
|
615 |
+ } |
|
616 |
+ |
|
617 |
+ /* get the public key */ |
|
618 |
+ ASSERT(cert->cert_info->key->pkey); /* NULL before SSL_CTX_use_certificate() is called */ |
|
619 |
+ pub_rsa = cert->cert_info->key->pkey->pkey.rsa; |
|
620 |
+ |
|
621 |
+ /* initialize RSA object */ |
|
622 |
+ rsa->n = BN_dup(pub_rsa->n); |
|
623 |
+ rsa->flags |= RSA_FLAG_EXT_PKEY; |
|
624 |
+ if (!RSA_set_method(rsa, rsa_meth)) |
|
625 |
+ goto err; |
|
626 |
+ |
|
627 |
+ /* bind our custom RSA object to ssl_ctx */ |
|
628 |
+ if (!SSL_CTX_use_RSAPrivateKey(ctx->ctx, rsa)) |
|
629 |
+ goto err; |
|
630 |
+ |
|
631 |
+ RSA_free(rsa); /* doesn't necessarily free, just decrements refcount */ |
|
632 |
+ return 1; |
|
633 |
+ |
|
634 |
+ err: |
|
635 |
+ if (rsa) |
|
636 |
+ RSA_free(rsa); |
|
637 |
+ else |
|
638 |
+ { |
|
639 |
+ if (rsa_meth) |
|
640 |
+ free(rsa_meth); |
|
641 |
+ } |
|
642 |
+ msg (M_SSLERR, "Cannot enable SSL external private key capability"); |
|
643 |
+ return 0; |
|
644 |
+} |
|
645 |
+ |
|
646 |
+#endif |
|
647 |
+ |
|
510 | 648 |
void |
511 | 649 |
show_available_tls_ciphers () |
512 | 650 |
{ |