Browse code

Refactored external key loading from management

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>

Adriaan de Jong authored on 2011/06/30 15:57:52
Showing 3 changed files
... ...
@@ -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
 {