]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Separated OpenSSL-specific parts of the PKCS#11 driver
authorAdriaan de Jong <dejong@fox-it.com>
Thu, 30 Jun 2011 14:28:56 +0000 (16:28 +0200)
committerDavid Sommerseth <davids@redhat.com>
Sat, 22 Oct 2011 09:43:28 +0000 (11:43 +0200)
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>
Makefile.am
pkcs11.c
pkcs11.h
pkcs11_backend.h [new file with mode: 0644]
pkcs11_openssl.c [new file with mode: 0644]
ssl.c
ssl_backend.h
ssl_openssl.c

index bdda0be9657a9926b09329054eca0f4b338008ff..0108d8fef139369230f58f83323e32c6afcd3e5e 100644 (file)
@@ -114,7 +114,7 @@ openvpn_SOURCES = \
        multi.c multi.h \
         ntlm.c ntlm.h \
        occ.c occ.h occ-inline.h \
-       pkcs11.c pkcs11.h \
+       pkcs11.c pkcs11.h pkcs11_backend.h \
        openvpn.c openvpn.h \
        openvpn-plugin.h \
        options.c options.h \
@@ -156,6 +156,7 @@ configure.h: Makefile
 if USE_OPENSSL
 openvpn_SOURCES += \
        crypto_openssl.c crypto_openssl.h \
+       pkcs11_openssl.c \
        ssl_openssl.c ssl_openssl.h \
        ssl_verify_openssl.c ssl_verify_openssl.h
 endif
index 9cf18e5f5a1a9fcbdd64d64f91e5b3ef7111614a..5e051b856d8175b1c876e0051a34556bd045da89 100644 (file)
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -27,7 +27,6 @@
 #if defined(ENABLE_PKCS11)
 
 #include <pkcs11-helper-1.0/pkcs11h-certificate.h>
-#include <pkcs11-helper-1.0/pkcs11h-openssl.h>
 #include "basic.h"
 #include "error.h"
 #include "manage.h"
@@ -35,6 +34,7 @@
 #include "pkcs11.h"
 #include "misc.h"
 #include "otime.h"
+#include "pkcs11_backend.h"
 
 static
 time_t
@@ -605,16 +605,13 @@ cleanup:
 }
 
 int
-SSL_CTX_use_pkcs11 (
-       SSL_CTX * const ssl_ctx,
+tls_ctx_use_pkcs11 (
+       struct tls_root_ctx * const ssl_ctx,
        bool pkcs11_id_management,
        const char * const pkcs11_id
 ) {
-       X509 *x509 = NULL;
-       RSA *rsa = NULL;
        pkcs11h_certificate_id_t certificate_id = NULL;
        pkcs11h_certificate_t certificate = NULL;
-       pkcs11h_openssl_session_t openssl_session = NULL;
        CK_RV rv = CKR_OK;
 
        bool ok = false;
@@ -624,7 +621,7 @@ SSL_CTX_use_pkcs11 (
 
        dmsg (
                D_PKCS11_DEBUG,
-               "PKCS#11: SSL_CTX_use_pkcs11 - entered - ssl_ctx=%p, pkcs11_id_management=%d, pkcs11_id='%s'",
+               "PKCS#11: tls_ctx_use_pkcs11 - entered - ssl_ctx=%p, pkcs11_id_management=%d, pkcs11_id='%s'",
                (void *)ssl_ctx,
                pkcs11_id_management ? 1 : 0,
                pkcs11_id
@@ -689,54 +686,22 @@ SSL_CTX_use_pkcs11 (
                goto cleanup;
        }
 
-       if ((openssl_session = pkcs11h_openssl_createSession (certificate)) == NULL     ) {
-               msg (M_WARN, "PKCS#11: Cannot initialize openssl session");
+       if (
+               (pkcs11_init_tls_session (
+                   certificate,
+                   ssl_ctx
+               ))
+       ) {
+               /* Handled by SSL context free */
+               certificate = NULL;
                goto cleanup;
        }
 
-       /*
-        * Will be released by openssl_session
-        */
+       /* Handled by SSL context free */
        certificate = NULL;
-
-       if ((rsa = pkcs11h_openssl_session_getRSA (openssl_session)) == NULL) {
-               msg (M_WARN, "PKCS#11: Unable get rsa object");
-               goto cleanup;
-       }
-
-       if ((x509 = pkcs11h_openssl_session_getX509 (openssl_session)) == NULL) {
-               msg (M_WARN, "PKCS#11: Unable get certificate object");
-               goto cleanup;
-       }
-
-       if (!SSL_CTX_use_RSAPrivateKey (ssl_ctx, rsa)) {
-               msg (M_WARN, "PKCS#11: Cannot set private key for openssl");
-               goto cleanup;
-       }
-
-       if (!SSL_CTX_use_certificate (ssl_ctx, x509)) {
-               msg (M_WARN, "PKCS#11: Cannot set certificate for openssl");
-               goto cleanup;
-       }
-
        ok = true;
 
 cleanup:
-       /*
-        * openssl objects have reference
-        * count, so release them
-        */
-
-       if (x509 != NULL) {
-               X509_free (x509);
-               x509 = NULL;
-       }
-
-       if (rsa != NULL) {
-               RSA_free (rsa);
-               rsa = NULL;
-       }
-
        if (certificate != NULL) {
                pkcs11h_certificate_freeCertificate (certificate);
                certificate = NULL;
@@ -746,15 +711,10 @@ cleanup:
                pkcs11h_certificate_freeCertificateId (certificate_id);
                certificate_id = NULL;
        }
-       
-       if (openssl_session != NULL) {
-               pkcs11h_openssl_freeSession (openssl_session);
-               openssl_session = NULL;
-       }
 
        dmsg (
                D_PKCS11_DEBUG,
-               "PKCS#11: SSL_CTX_use_pkcs11 - return ok=%d, rv=%ld",
+               "PKCS#11: tls_ctx_use_pkcs11 - return ok=%d, rv=%ld",
                ok ? 1 : 0,
                rv
        );
@@ -867,13 +827,10 @@ show_pkcs11_ids (
        );
        for (current = user_certificates;current != NULL; current = current->next) {
                pkcs11h_certificate_t certificate = NULL;
-               X509 *x509 = NULL;
-               BIO *bio = NULL;
                char dn[1024] = {0};
                char serial[1024] = {0};
                char *ser = NULL;
                size_t ser_len = 0;
-               int n;
 
                if (
                        (rv = pkcs11h_certificate_serializeCertificateId (
@@ -918,31 +875,26 @@ show_pkcs11_ids (
                        goto cleanup1;
                }
 
-               if ((x509 = pkcs11h_openssl_getX509 (certificate)) == NULL) {
-                       msg (M_FATAL, "PKCS#11: Cannot get X509");
+               if (
+                     (pkcs11_certificate_dn (
+                               certificate,
+                               dn,
+                               sizeof(dn)
+                     ))
+               ) {
                        goto cleanup1;
                }
 
-               X509_NAME_oneline (
-                       X509_get_subject_name (x509),
-                       dn,
-                       sizeof (dn)
-               );
-
-               if ((bio = BIO_new (BIO_s_mem ())) == NULL) {
-                       msg (M_FATAL, "PKCS#11: Cannot create BIO");
+               if (
+                     (pkcs11_certificate_serial (
+                               certificate,
+                               serial,
+                               sizeof(serial)
+                     ))
+               ) {
                        goto cleanup1;
                }
 
-               i2a_ASN1_INTEGER(bio, X509_get_serialNumber (x509));
-               n = BIO_read (bio, serial, sizeof (serial)-1);
-               if (n<0) {
-                       serial[0] = '\x0';
-               }
-               else {
-                       serial[n] = 0;
-               }
-
                msg (
                        M_INFO|M_NOPREFIX|M_NOLF,
                        (
@@ -958,10 +910,6 @@ show_pkcs11_ids (
                );
 
        cleanup1:
-               if (x509 != NULL) {
-                       X509_free (x509);
-                       x509 = NULL;
-               }
 
                if (certificate != NULL) {
                        pkcs11h_certificate_freeCertificate (certificate);
index abe03b9a69ff182cc494d58ddd0ff077c3b0fd60..4261871d44614db1638a5cd92ca009767a5cf330 100644 (file)
--- a/pkcs11.h
+++ b/pkcs11.h
@@ -27,7 +27,7 @@
 
 #if defined(ENABLE_PKCS11)
 
-#include <openssl/ssl.h>
+#include "ssl_common.h"
 
 bool
 pkcs11_initialize (
@@ -63,8 +63,8 @@ pkcs11_management_id_get (
 );
 
 int
-SSL_CTX_use_pkcs11 (
-       SSL_CTX * const ssl_ctx,
+tls_ctx_use_pkcs11 (
+       struct tls_root_ctx * const ssl_ctx,
        bool pkcs11_id_management,
        const char * const pkcs11_id
 );
diff --git a/pkcs11_backend.h b/pkcs11_backend.h
new file mode 100644 (file)
index 0000000..6b5ad31
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ *  OpenVPN -- An application to securely tunnel IP networks
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
+ *             session authentication and key exchange,
+ *             packet encryption, packet authentication, and
+ *             packet compression.
+ *
+ *  Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ *  Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program (see the file COPYING included with this
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/**
+ * @file PKCS #11 SSL library-specific backend
+ */
+
+#ifndef PKCS11_BACKEND_H_
+#define PKCS11_BACKEND_H_
+
+#include "syshead.h"
+
+#if defined(ENABLE_PKCS11)
+
+#include "ssl_common.h"
+
+#include <pkcs11-helper-1.0/pkcs11h-certificate.h>
+
+/**
+ * Retrieve PKCS #11 Certificate's DN in a printable format.
+ *
+ * @param certificate  The PKCS #11 helper certificate object
+ * @param dn           Buffer that the certificate subject DN will be placed in.
+ * @param dn_len       Size of said buffer.
+ *
+ * @return             1 on failure, 0 on success
+ */
+int pkcs11_certificate_dn (pkcs11h_certificate_t certificate, char *dn,
+    size_t dn_len);
+
+/**
+ * Retrieve PKCS #11 Certificate's serial number in a printable format.
+ *
+ * @param certificate  The PKCS #11 helper certificate object
+ * @param serial       Buffer that the certificate's serial will be placed in.
+ * @param serial_len   Size of said buffer.
+ *
+ * @return             1 on failure, 0 on success
+ */
+int pkcs11_certificate_serial (pkcs11h_certificate_t certificate, char *serial,
+    size_t serial_len);
+
+/**
+ * Load PKCS #11 Certificate's information into the given TLS context
+ *
+ * @param certificate  The PKCS #11 helper certificate object
+ * @param ssl_ctx      TLS context to use.
+ *
+ * @return             1 on failure, 0 on success
+ */
+int pkcs11_init_tls_session(pkcs11h_certificate_t certificate,
+    struct tls_root_ctx * const ssl_ctx);
+
+#endif /* defined(ENABLE_PKCS11) */
+#endif /* PKCS11_BACKEND_H_ */
diff --git a/pkcs11_openssl.c b/pkcs11_openssl.c
new file mode 100644 (file)
index 0000000..5c99bf3
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ *  OpenVPN -- An application to securely tunnel IP networks
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
+ *             session authentication and key exchange,
+ *             packet encryption, packet authentication, and
+ *             packet compression.
+ *
+ *  Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ *  Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program (see the file COPYING included with this
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/**
+ * @file PKCS #11 OpenSSL backend
+ */
+
+#include "syshead.h"
+
+#ifdef ENABLE_PKCS11
+
+#include "errlevel.h"
+#include "pkcs11_backend.h"
+#include <pkcs11-helper-1.0/pkcs11h-openssl.h>
+
+int
+pkcs11_init_tls_session(pkcs11h_certificate_t certificate,
+    struct tls_root_ctx * const ssl_ctx)
+{
+  int ret = 1;
+
+  X509 *x509 = NULL;
+  RSA *rsa = NULL;
+  pkcs11h_openssl_session_t openssl_session = NULL;
+
+  if ((openssl_session = pkcs11h_openssl_createSession (certificate)) == NULL)
+    {
+      msg (M_WARN, "PKCS#11: Cannot initialize openssl session");
+      goto cleanup;
+    }
+
+  /*
+   * Will be released by openssl_session
+   */
+  certificate = NULL;
+
+  if ((rsa = pkcs11h_openssl_session_getRSA (openssl_session)) == NULL)
+    {
+      msg (M_WARN, "PKCS#11: Unable get rsa object");
+      goto cleanup;
+    }
+
+  if ((x509 = pkcs11h_openssl_session_getX509 (openssl_session)) == NULL)
+    {
+      msg (M_WARN, "PKCS#11: Unable get certificate object");
+      goto cleanup;
+    }
+
+  if (!SSL_CTX_use_RSAPrivateKey (ssl_ctx->ctx, rsa))
+    {
+      msg (M_WARN, "PKCS#11: Cannot set private key for openssl");
+      goto cleanup;
+    }
+
+  if (!SSL_CTX_use_certificate (ssl_ctx->ctx, x509))
+    {
+      msg (M_WARN, "PKCS#11: Cannot set certificate for openssl");
+      goto cleanup;
+    }
+  ret = 0;
+
+cleanup:
+  /*
+   * Certificate freeing is usually handled by openssl_session.
+   * If something went wrong, creating the session we have to do it manually.
+   */
+  if (certificate != NULL) {
+    pkcs11h_certificate_freeCertificate (certificate);
+    certificate = NULL;
+  }
+
+  /*
+   * openssl objects have reference
+   * count, so release them
+   */
+  if (x509 != NULL)
+    {
+      X509_free (x509);
+      x509 = NULL;
+    }
+
+  if (rsa != NULL)
+    {
+      RSA_free (rsa);
+      rsa = NULL;
+    }
+
+  if (openssl_session != NULL)
+    {
+      pkcs11h_openssl_freeSession (openssl_session);
+      openssl_session = NULL;
+    }
+  return ret;
+}
+
+int
+pkcs11_certificate_dn (pkcs11h_certificate_t certificate, char *dn,
+    size_t dn_len)
+{
+  X509 *x509 = NULL;
+  int ret = 1;
+
+  if ((x509 = pkcs11h_openssl_getX509 (certificate)) == NULL)
+    {
+      msg (M_FATAL, "PKCS#11: Cannot get X509");
+      ret = 1;
+      goto cleanup;
+    }
+
+  X509_NAME_oneline (X509_get_subject_name (x509), dn, dn_len);
+
+  ret = 0;
+
+cleanup:
+  if (x509 != NULL)
+    {
+      X509_free (x509);
+      x509 = NULL;
+    }
+
+  return ret;
+}
+
+int
+pkcs11_certificate_serial (pkcs11h_certificate_t certificate, char *serial,
+    size_t serial_len)
+{
+  X509 *x509 = NULL;
+  BIO *bio = NULL;
+  int ret = 1;
+  int n;
+
+  if ((x509 = pkcs11h_openssl_getX509 (certificate)) == NULL)
+    {
+      msg (M_FATAL, "PKCS#11: Cannot get X509");
+      goto cleanup;
+    }
+
+  if ((bio = BIO_new (BIO_s_mem ())) == NULL)
+    {
+      msg (M_FATAL, "PKCS#11: Cannot create BIO");
+      goto cleanup;
+    }
+
+  i2a_ASN1_INTEGER(bio, X509_get_serialNumber (x509));
+  n = BIO_read (bio, serial, serial_len-1);
+
+  if (n<0) {
+    serial[0] = '\x0';
+  }
+  else {
+    serial[n] = 0;
+  }
+
+  ret = 0;
+
+cleanup:
+
+  if (x509 != NULL)
+    {
+      X509_free (x509);
+      x509 = NULL;
+    }
+  return ret;
+}
+#endif /* ENABLE_PKCS11 */
diff --git a/ssl.c b/ssl.c
index 516ed1a41f9568ec7d13cc2944a4c9608036a00a..407eba055ba91b29ca88fe6ce7ad980b6ed152cf 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -328,8 +328,12 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx)
 #ifdef ENABLE_PKCS11
   else if (options->pkcs11_providers[0])
     {
-      if (0 != tls_ctx_load_pkcs11(new_ctx, options->pkcs11_id_management, options->pkcs11_id))
-         goto err;
+      if (!tls_ctx_use_pkcs11 (new_ctx, options->pkcs11_id_management, options->pkcs11_id))
+       {
+         msg (M_WARN, "Cannot load certificate \"%s\" using PKCS#11 interface",
+             options->pkcs11_id);
+         goto err;
+       }
     }
 #endif
 #ifdef WIN32
index c532a20b64209a3aac21fbf5e6e3799109dd9d18..b0c9a6d4470fdc1b0d2fb3263baa8782bc8153d3 100644 (file)
@@ -158,17 +158,6 @@ int tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file,
     bool load_ca_file
     );
 
-/*
- * Load PKCS #11 information for key and cert, and add to library-specific TLS
- * context.
- *
- * TODO: document
- */
-#ifdef ENABLE_PKCS11
-int tls_ctx_load_pkcs11(struct tls_root_ctx *ctx,
-    bool pkcs11_id_management, const char *pkcs11_id);
-#endif /* ENABLE_PKCS11 */
-
 /**
  * Use Windows cryptoapi for key and cert, and add to library-specific TLS
  * context.
index 2d5e914cdc6c13a5d8a93fe305fe5b387a991223..f85f81a9e6ebbe40f769c3f72e0b66ddc57e4b75 100644 (file)
@@ -323,23 +323,6 @@ tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file,
   return 0;
 }
 
-#ifdef ENABLE_PKCS11
-int
-tls_ctx_load_pkcs11(struct tls_root_ctx *ctx, bool pkcs11_id_management,
-    const char *pkcs11_id)
-{
-  ASSERT(NULL != ctx);
-
-  /* Load Certificate and Private Key */
-  if (!SSL_CTX_use_pkcs11 (ctx->ctx, pkcs11_id_management, pkcs11_id))
-    {
-      msg (M_WARN, "Cannot load certificate \"%s\" using PKCS#11 interface", pkcs11_id);
-      return 1;
-    }
-  return 0;
-}
-#endif /* ENABLE_PKCS11 */
-
 #ifdef WIN32
 void
 tls_ctx_load_cryptoapi(struct tls_root_ctx *ctx, const char *cryptoapi_cert)