1/*
2 *  OpenVPN -- An application to securely tunnel IP networks
3 *             over a single TCP/UDP port, with support for SSL/TLS-based
4 *             session authentication and key exchange,
5 *             packet encryption, packet authentication, and
6 *             packet compression.
7 *
8 *  Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
9 *  Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com>
10 *
11 *  This program is free software; you can redistribute it and/or modify
12 *  it under the terms of the GNU General Public License version 2
13 *  as published by the Free Software Foundation.
14 *
15 *  This program is distributed in the hope that it will be useful,
16 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 *  GNU General Public License for more details.
19 *
20 *  You should have received a copy of the GNU General Public License
21 *  along with this program (see the file COPYING included with this
22 *  distribution); if not, write to the Free Software Foundation, Inc.,
23 *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24 */
25
26/**
27 * @file PKCS #11 OpenSSL backend
28 */
29
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#elif defined(_MSC_VER)
33#include "config-msvc.h"
34#endif
35
36#include "syshead.h"
37
38#if defined(ENABLE_PKCS11) && defined(ENABLE_CRYPTO_OPENSSL)
39
40#include "errlevel.h"
41#include "pkcs11_backend.h"
42#include "ssl_verify.h"
43#include <pkcs11-helper-1.0/pkcs11h-openssl.h>
44
45int
46pkcs11_init_tls_session(pkcs11h_certificate_t certificate,
47    struct tls_root_ctx * const ssl_ctx)
48{
49  int ret = 1;
50
51  X509 *x509 = NULL;
52  RSA *rsa = NULL;
53  pkcs11h_openssl_session_t openssl_session = NULL;
54
55  if ((openssl_session = pkcs11h_openssl_createSession (certificate)) == NULL)
56    {
57      msg (M_WARN, "PKCS#11: Cannot initialize openssl session");
58      goto cleanup;
59    }
60
61  /*
62   * Will be released by openssl_session
63   */
64  certificate = NULL;
65
66  if ((rsa = pkcs11h_openssl_session_getRSA (openssl_session)) == NULL)
67    {
68      msg (M_WARN, "PKCS#11: Unable get rsa object");
69      goto cleanup;
70    }
71
72  if ((x509 = pkcs11h_openssl_session_getX509 (openssl_session)) == NULL)
73    {
74      msg (M_WARN, "PKCS#11: Unable get certificate object");
75      goto cleanup;
76    }
77
78  if (!SSL_CTX_use_RSAPrivateKey (ssl_ctx->ctx, rsa))
79    {
80      msg (M_WARN, "PKCS#11: Cannot set private key for openssl");
81      goto cleanup;
82    }
83
84  if (!SSL_CTX_use_certificate (ssl_ctx->ctx, x509))
85    {
86      msg (M_WARN, "PKCS#11: Cannot set certificate for openssl");
87      goto cleanup;
88    }
89  ret = 0;
90
91cleanup:
92  /*
93   * Certificate freeing is usually handled by openssl_session.
94   * If something went wrong, creating the session we have to do it manually.
95   */
96  if (certificate != NULL) {
97    pkcs11h_certificate_freeCertificate (certificate);
98    certificate = NULL;
99  }
100
101  /*
102   * openssl objects have reference
103   * count, so release them
104   */
105  if (x509 != NULL)
106    {
107      X509_free (x509);
108      x509 = NULL;
109    }
110
111  if (rsa != NULL)
112    {
113      RSA_free (rsa);
114      rsa = NULL;
115    }
116
117  if (openssl_session != NULL)
118    {
119      pkcs11h_openssl_freeSession (openssl_session);
120      openssl_session = NULL;
121    }
122  return ret;
123}
124
125char *
126pkcs11_certificate_dn (pkcs11h_certificate_t certificate, struct gc_arena *gc)
127{
128  X509 *x509 = NULL;
129
130  char *dn = NULL;
131
132  if ((x509 = pkcs11h_openssl_getX509 (certificate)) == NULL)
133    {
134      msg (M_FATAL, "PKCS#11: Cannot get X509");
135      goto cleanup;
136    }
137
138  dn = x509_get_subject (x509, gc);
139
140cleanup:
141  if (x509 != NULL)
142    {
143      X509_free (x509);
144      x509 = NULL;
145    }
146
147  return dn;
148}
149
150int
151pkcs11_certificate_serial (pkcs11h_certificate_t certificate, char *serial,
152    size_t serial_len)
153{
154  X509 *x509 = NULL;
155  BIO *bio = NULL;
156  int ret = 1;
157  int n;
158
159  if ((x509 = pkcs11h_openssl_getX509 (certificate)) == NULL)
160    {
161      msg (M_FATAL, "PKCS#11: Cannot get X509");
162      goto cleanup;
163    }
164
165  if ((bio = BIO_new (BIO_s_mem ())) == NULL)
166    {
167      msg (M_FATAL, "PKCS#11: Cannot create BIO");
168      goto cleanup;
169    }
170
171  i2a_ASN1_INTEGER(bio, X509_get_serialNumber (x509));
172  n = BIO_read (bio, serial, serial_len-1);
173
174  if (n<0) {
175    serial[0] = '\x0';
176  }
177  else {
178    serial[n] = 0;
179  }
180
181  ret = 0;
182
183cleanup:
184
185  if (x509 != NULL)
186    {
187      X509_free (x509);
188      x509 = NULL;
189    }
190  return ret;
191}
192#endif /* defined(ENABLE_PKCS11) && defined(ENABLE_OPENSSL) */
193