/* * 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-2018 OpenVPN Inc * Copyright (C) 2010-2018 Fox Crypto B.V. * * 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; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /** * @file PKCS #11 OpenSSL backend */ #ifdef HAVE_CONFIG_H #include "config.h" #elif defined(_MSC_VER) #include "config-msvc.h" #endif #include "syshead.h" #if defined(ENABLE_PKCS11) && defined(ENABLE_CRYPTO_OPENSSL) #include "errlevel.h" #include "pkcs11_backend.h" #include "ssl_verify.h" #include int pkcs11_init_tls_session(pkcs11h_certificate_t certificate, struct tls_root_ctx *const ssl_ctx) { int ret = 1; X509 *x509 = NULL; EVP_PKEY *evp = 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 ((evp = pkcs11h_openssl_session_getEVP(openssl_session)) == NULL) { msg(M_WARN, "PKCS#11: Unable get evp 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_PrivateKey(ssl_ctx->ctx, evp)) { 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 (evp != NULL) { EVP_PKEY_free(evp); evp = NULL; } if (openssl_session != NULL) { pkcs11h_openssl_freeSession(openssl_session); openssl_session = NULL; } return ret; } char * pkcs11_certificate_dn(pkcs11h_certificate_t certificate, struct gc_arena *gc) { X509 *x509 = NULL; char *dn = NULL; if ((x509 = pkcs11h_openssl_getX509(certificate)) == NULL) { msg(M_FATAL, "PKCS#11: Cannot get X509"); goto cleanup; } dn = x509_get_subject(x509, gc); cleanup: if (x509 != NULL) { X509_free(x509); x509 = NULL; } return dn; } 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 /* defined(ENABLE_PKCS11) && defined(ENABLE_OPENSSL) */