2005-10-13 10:38:41 +02:00
|
|
|
/*
|
|
|
|
* 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-2005 OpenVPN Solutions LLC <info@openvpn.net>
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The routines in this file deal with providing private key cryptography
|
|
|
|
* using RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki).
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if defined(WIN32)
|
|
|
|
#include "config-win32.h"
|
|
|
|
#else
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "syshead.h"
|
2005-10-15 14:14:56 +02:00
|
|
|
|
|
|
|
#if defined(ENABLE_PKCS11)
|
|
|
|
|
2005-10-20 07:58:08 +02:00
|
|
|
#define PKCS11H_NO_NEED_INCLUDE_CONFIG
|
2005-10-13 10:38:41 +02:00
|
|
|
|
2005-10-20 07:58:08 +02:00
|
|
|
#include "pkcs11-helper.h"
|
|
|
|
#include "pkcs11.h"
|
2005-10-13 10:38:41 +02:00
|
|
|
|
|
|
|
static
|
2005-10-20 07:58:08 +02:00
|
|
|
void
|
|
|
|
_pkcs11_openvpn_print (
|
|
|
|
IN const void *pData,
|
|
|
|
IN const char * const szFormat,
|
|
|
|
IN ...
|
2005-10-13 10:38:41 +02:00
|
|
|
) {
|
2005-10-20 07:58:08 +02:00
|
|
|
char Buffer[10*1024];
|
|
|
|
va_list args;
|
2005-10-13 10:38:41 +02:00
|
|
|
|
2005-10-20 07:58:08 +02:00
|
|
|
va_start (args, szFormat);
|
|
|
|
vsnprintf (Buffer, sizeof (Buffer), szFormat, args);
|
|
|
|
va_end (args);
|
|
|
|
Buffer[sizeof (Buffer)-1] = 0;
|
2005-10-17 09:39:41 +02:00
|
|
|
|
2005-10-20 07:58:08 +02:00
|
|
|
msg (M_INFO|M_NOPREFIX|M_NOLF, "%s", Buffer);
|
2005-10-13 10:38:41 +02:00
|
|
|
}
|
|
|
|
|
2005-10-17 09:39:41 +02:00
|
|
|
static
|
|
|
|
bool
|
2005-10-20 07:58:08 +02:00
|
|
|
_pkcs11_openvpn_card_prompt (
|
2005-10-17 09:39:41 +02:00
|
|
|
IN const void *pData,
|
|
|
|
IN const char * const szLabel
|
|
|
|
) {
|
2005-10-24 02:38:40 +02:00
|
|
|
static struct user_pass token_resp;
|
2005-10-17 09:39:41 +02:00
|
|
|
|
|
|
|
ASSERT (szLabel!=NULL);
|
|
|
|
|
2005-10-24 02:38:40 +02:00
|
|
|
CLEAR (token_resp);
|
|
|
|
token_resp.defined = false;
|
|
|
|
token_resp.nocache = true;
|
|
|
|
openvpn_snprintf (token_resp.username, sizeof (token_resp.username), "Please insert %s token", szLabel);
|
|
|
|
get_user_pass (&token_resp, NULL, "token-insertion-request", GET_USER_PASS_MANAGEMENT|GET_USER_PASS_NEED_OK);
|
2005-10-17 09:39:41 +02:00
|
|
|
|
2005-10-24 02:38:40 +02:00
|
|
|
return strcmp (token_resp.password, "ok") == 0;
|
2005-10-17 09:39:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
bool
|
2005-10-20 07:58:08 +02:00
|
|
|
_pkcs11_openvpn_pin_prompt (
|
2005-10-17 09:39:41 +02:00
|
|
|
IN const void *pData,
|
|
|
|
IN const char * const szLabel,
|
|
|
|
OUT char * const szPIN,
|
|
|
|
IN const size_t nMaxPIN
|
|
|
|
) {
|
|
|
|
static struct user_pass token_pass;
|
|
|
|
char szPrompt[1024];
|
|
|
|
|
|
|
|
ASSERT (szLabel!=NULL);
|
|
|
|
|
|
|
|
openvpn_snprintf (szPrompt, sizeof (szPrompt), "%s token", szLabel);
|
|
|
|
|
|
|
|
token_pass.defined = false;
|
|
|
|
token_pass.nocache = true;
|
2005-10-20 07:58:08 +02:00
|
|
|
get_user_pass (&token_pass, NULL, szPrompt, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_PASSWORD_ONLY);
|
2005-10-17 09:39:41 +02:00
|
|
|
strncpynt (szPIN, token_pass.password, nMaxPIN);
|
|
|
|
purge_user_pass (&token_pass, true);
|
|
|
|
|
|
|
|
if (strlen (szPIN) == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-24 02:38:40 +02:00
|
|
|
bool
|
2005-10-20 07:58:08 +02:00
|
|
|
pkcs11_initialize (
|
2005-10-17 09:39:41 +02:00
|
|
|
const int nPINCachePeriod
|
|
|
|
) {
|
2005-10-24 02:38:40 +02:00
|
|
|
CK_RV rv = CKR_OK;
|
2005-10-17 09:39:41 +02:00
|
|
|
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (
|
|
|
|
PKCS11_LOG_DEBUG2,
|
|
|
|
"PKCS#11: pkcs11_initialize - entered"
|
2005-10-17 09:39:41 +02:00
|
|
|
);
|
|
|
|
|
2005-10-24 02:38:40 +02:00
|
|
|
if (
|
|
|
|
rv == CKR_OK &&
|
|
|
|
(rv = pkcs11h_initialize ()) != CKR_OK
|
|
|
|
) {
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (PKCS11_LOG_ERROR, "PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11h_getMessage (rv));
|
2005-10-17 09:39:41 +02:00
|
|
|
}
|
2005-10-20 07:58:08 +02:00
|
|
|
|
2005-10-24 02:38:40 +02:00
|
|
|
if (
|
|
|
|
rv == CKR_OK &&
|
|
|
|
(rv = pkcs11h_setCardPromptHook (_pkcs11_openvpn_card_prompt, NULL)) != CKR_OK
|
|
|
|
) {
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (PKCS11_LOG_ERROR, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv));
|
2005-10-17 09:39:41 +02:00
|
|
|
}
|
2005-10-20 07:58:08 +02:00
|
|
|
|
2005-10-24 02:38:40 +02:00
|
|
|
if (
|
|
|
|
rv == CKR_OK &&
|
|
|
|
(rv = pkcs11h_setPINPromptHook (_pkcs11_openvpn_pin_prompt, NULL)) != CKR_OK
|
|
|
|
) {
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (PKCS11_LOG_ERROR, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv));
|
2005-10-17 09:39:41 +02:00
|
|
|
}
|
|
|
|
|
2005-10-24 02:38:40 +02:00
|
|
|
if (
|
|
|
|
rv == CKR_OK &&
|
|
|
|
(rv = pkcs11h_setPINCachePeriod (nPINCachePeriod)) != CKR_OK
|
|
|
|
) {
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (PKCS11_LOG_ERROR, "PKCS#11: Cannot set PIN cache period %ld-'%s'", rv, pkcs11h_getMessage (rv));
|
2005-10-17 09:39:41 +02:00
|
|
|
}
|
|
|
|
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (
|
|
|
|
PKCS11_LOG_DEBUG2,
|
2005-10-24 02:38:40 +02:00
|
|
|
"PKCS#11: pkcs11_initialize - return %ld-'%s'",
|
|
|
|
rv,
|
|
|
|
pkcs11h_getMessage (rv)
|
2005-10-17 09:39:41 +02:00
|
|
|
);
|
2005-10-24 02:38:40 +02:00
|
|
|
|
|
|
|
return rv == CKR_OK;
|
2005-10-17 09:39:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-10-20 07:58:08 +02:00
|
|
|
pkcs11_terminate () {
|
|
|
|
PKCS11LOG (
|
|
|
|
PKCS11_LOG_DEBUG2,
|
|
|
|
"PKCS#11: pkcs11_terminate - entered"
|
2005-10-17 09:39:41 +02:00
|
|
|
);
|
|
|
|
|
2005-10-20 07:58:08 +02:00
|
|
|
pkcs11h_terminate ();
|
2005-10-17 09:39:41 +02:00
|
|
|
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (
|
|
|
|
PKCS11_LOG_DEBUG2,
|
|
|
|
"PKCS#11: pkcs11_terminate - return"
|
2005-10-17 09:39:41 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-10-20 07:58:08 +02:00
|
|
|
pkcs11_forkFixup () {
|
|
|
|
pkcs11h_forkFixup ();
|
2005-10-17 09:39:41 +02:00
|
|
|
}
|
|
|
|
|
2005-10-24 02:38:40 +02:00
|
|
|
bool
|
2005-10-20 07:58:08 +02:00
|
|
|
pkcs11_addProvider (
|
2005-10-17 09:39:41 +02:00
|
|
|
IN const char * const provider,
|
|
|
|
IN const char * const sign_mode
|
|
|
|
) {
|
2005-10-24 02:38:40 +02:00
|
|
|
CK_RV rv = CKR_OK;
|
2005-10-17 09:39:41 +02:00
|
|
|
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (
|
|
|
|
PKCS11_LOG_DEBUG2,
|
|
|
|
"PKCS#11: pkcs11_addProvider - entered - provider='%s', sign_mode='%s'",
|
2005-10-17 09:39:41 +02:00
|
|
|
provider,
|
|
|
|
sign_mode == NULL ? "default" : sign_mode
|
|
|
|
);
|
|
|
|
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (
|
|
|
|
PKCS11_LOG_INFO,
|
2005-10-17 09:39:41 +02:00
|
|
|
"PKCS#11: Adding PKCS#11 provider '%s'",
|
|
|
|
provider
|
|
|
|
);
|
|
|
|
|
2005-10-24 02:38:40 +02:00
|
|
|
if (
|
|
|
|
rv == CKR_OK &&
|
|
|
|
(rv = pkcs11h_addProvider (provider, sign_mode)) != CKR_OK
|
|
|
|
) {
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot initialize provider '%s' %ld-'%s'", provider, rv, pkcs11h_getMessage (rv));
|
2005-10-17 09:39:41 +02:00
|
|
|
}
|
|
|
|
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (
|
|
|
|
PKCS11_LOG_DEBUG2,
|
2005-10-24 02:38:40 +02:00
|
|
|
"PKCS#11: pkcs11_addProvider - return rv=%ld-'%s'",
|
|
|
|
rv,
|
|
|
|
pkcs11h_getMessage (rv)
|
2005-10-17 09:39:41 +02:00
|
|
|
);
|
2005-10-24 02:38:40 +02:00
|
|
|
|
|
|
|
return rv == CKR_OK;
|
2005-10-17 09:39:41 +02:00
|
|
|
}
|
|
|
|
|
2005-10-13 10:38:41 +02:00
|
|
|
int
|
|
|
|
SSL_CTX_use_pkcs11 (
|
|
|
|
IN OUT SSL_CTX * const ssl_ctx,
|
2005-11-01 23:42:58 +01:00
|
|
|
IN const char * const pkcs11_slot_type,
|
|
|
|
IN const char * const pkcs11_slot,
|
|
|
|
IN const char * const pkcs11_id_type,
|
|
|
|
IN const char * const pkcs11_id,
|
|
|
|
IN const bool pkcs11_protected_authentication,
|
|
|
|
IN const bool pkcs11_cert_private
|
2005-10-13 10:38:41 +02:00
|
|
|
) {
|
|
|
|
X509 *x509 = NULL;
|
|
|
|
RSA *rsa = NULL;
|
2005-10-20 07:58:08 +02:00
|
|
|
pkcs11h_openssl_session_t pkcs11h_openssl_session = NULL;
|
2005-10-13 10:38:41 +02:00
|
|
|
CK_RV rv = CKR_OK;
|
|
|
|
|
|
|
|
bool fOK = true;
|
|
|
|
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (
|
|
|
|
PKCS11_LOG_DEBUG2,
|
2005-11-01 23:42:58 +01:00
|
|
|
"PKCS#11: SSL_CTX_use_pkcs11 - entered - ssl_ctx=%p, pkcs11_slot_type='%s', pkcs11_slot='%s', pkcs11_id_type='%s', pkcs11_id='%s', pkcs11_protected_authentication=%d",
|
2005-10-17 09:39:41 +02:00
|
|
|
(void *)ssl_ctx,
|
2005-11-01 23:42:58 +01:00
|
|
|
pkcs11_slot_type,
|
|
|
|
pkcs11_slot,
|
|
|
|
pkcs11_id_type,
|
|
|
|
pkcs11_id,
|
|
|
|
pkcs11_protected_authentication ? 1 : 0
|
2005-10-13 10:38:41 +02:00
|
|
|
);
|
|
|
|
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11ASSERT (ssl_ctx!=NULL);
|
2005-11-01 23:42:58 +01:00
|
|
|
PKCS11ASSERT (pkcs11_slot_type!=NULL);
|
|
|
|
PKCS11ASSERT (pkcs11_slot!=NULL);
|
|
|
|
PKCS11ASSERT (pkcs11_id_type!=NULL);
|
|
|
|
PKCS11ASSERT (pkcs11_id!=NULL);
|
2005-10-13 10:38:41 +02:00
|
|
|
|
|
|
|
if (
|
|
|
|
fOK &&
|
2005-10-24 02:38:40 +02:00
|
|
|
(pkcs11h_openssl_session = pkcs11h_openssl_createSession ()) == NULL
|
2005-10-13 10:38:41 +02:00
|
|
|
) {
|
|
|
|
fOK = false;
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot initialize openssh session");
|
2005-10-13 10:38:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
fOK &&
|
2005-10-24 02:38:40 +02:00
|
|
|
(rv = pkcs11h_createCertificateSession (
|
2005-11-01 23:42:58 +01:00
|
|
|
pkcs11_slot_type,
|
|
|
|
pkcs11_slot,
|
|
|
|
pkcs11_id_type,
|
|
|
|
pkcs11_id,
|
|
|
|
pkcs11_protected_authentication,
|
|
|
|
pkcs11_cert_private,
|
2005-10-24 02:38:40 +02:00
|
|
|
PKCS11H_PIN_CACHE_INFINITE,
|
2005-11-01 23:42:58 +01:00
|
|
|
&pkcs11h_openssl_session->certificate
|
2005-10-13 10:38:41 +02:00
|
|
|
)) != CKR_OK
|
|
|
|
) {
|
|
|
|
fOK = false;
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot set parameters %ld-'%s'", rv, pkcs11h_getMessage (rv));
|
2005-10-13 10:38:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
fOK &&
|
2005-10-20 07:58:08 +02:00
|
|
|
(rsa = pkcs11h_openssl_getRSA (pkcs11h_openssl_session)) == NULL
|
2005-10-13 10:38:41 +02:00
|
|
|
) {
|
|
|
|
fOK = false;
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Unable get rsa object");
|
2005-10-13 10:38:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
fOK &&
|
2005-10-20 07:58:08 +02:00
|
|
|
(x509 = pkcs11h_openssl_getX509 (pkcs11h_openssl_session)) == NULL
|
2005-10-13 10:38:41 +02:00
|
|
|
) {
|
|
|
|
fOK = false;
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Unable get certificate object");
|
2005-10-13 10:38:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
fOK &&
|
2005-10-20 07:58:08 +02:00
|
|
|
!SSL_CTX_use_RSAPrivateKey (ssl_ctx, rsa)
|
2005-10-13 10:38:41 +02:00
|
|
|
) {
|
|
|
|
fOK = false;
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot set private key for openssl");
|
2005-10-13 10:38:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
fOK &&
|
|
|
|
!SSL_CTX_use_certificate (ssl_ctx, x509)
|
|
|
|
) {
|
|
|
|
fOK = false;
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot set certificate for openssl");
|
2005-10-13 10:38:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* openssl objects have reference
|
|
|
|
* count, so release them
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (x509 != NULL) {
|
|
|
|
X509_free (x509);
|
|
|
|
x509 = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rsa != NULL) {
|
|
|
|
RSA_free (rsa);
|
|
|
|
rsa = NULL;
|
|
|
|
}
|
2005-10-20 07:58:08 +02:00
|
|
|
|
|
|
|
if (pkcs11h_openssl_session != NULL) {
|
|
|
|
pkcs11h_openssl_freeSession (pkcs11h_openssl_session);
|
|
|
|
pkcs11h_openssl_session = NULL;
|
2005-10-13 10:38:41 +02:00
|
|
|
}
|
|
|
|
|
2005-10-20 07:58:08 +02:00
|
|
|
PKCS11LOG (
|
|
|
|
PKCS11_LOG_DEBUG2,
|
2005-10-13 10:38:41 +02:00
|
|
|
"PKCS#11: SSL_CTX_use_pkcs11 - return fOK=%d, rv=%ld",
|
|
|
|
fOK ? 1 : 0,
|
|
|
|
rv
|
|
|
|
);
|
|
|
|
|
2005-10-24 02:38:40 +02:00
|
|
|
return fOK ? 1 : 0;
|
2005-10-13 10:38:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
show_pkcs11_slots (
|
2005-10-20 07:58:08 +02:00
|
|
|
const char * const provider
|
2005-10-17 09:39:41 +02:00
|
|
|
) {
|
2005-10-20 07:58:08 +02:00
|
|
|
pkcs11h_standalone_dump_slots (
|
|
|
|
_pkcs11_openvpn_print,
|
|
|
|
NULL,
|
|
|
|
provider
|
|
|
|
);
|
2005-10-13 10:38:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
show_pkcs11_objects (
|
2005-10-20 07:58:08 +02:00
|
|
|
const char * const provider,
|
|
|
|
const char * const slot,
|
|
|
|
const char * const pin
|
2005-10-13 10:38:41 +02:00
|
|
|
) {
|
2005-10-20 07:58:08 +02:00
|
|
|
pkcs11h_standalone_dump_objects (
|
|
|
|
_pkcs11_openvpn_print,
|
|
|
|
NULL,
|
|
|
|
provider,
|
|
|
|
slot,
|
|
|
|
pin
|
2005-10-13 10:38:41 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
static void dummy (void) {}
|
2005-10-17 09:39:41 +02:00
|
|
|
#endif /* ENABLE_PKCS11 */
|