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