From 18597b93f7b43f63173f373fbd8548f2d08e25bb Mon Sep 17 00:00:00 2001 From: james Date: Wed, 5 Apr 2006 07:17:02 +0000 Subject: I've recently worked on a better version of pkcs11-helper. I've also merged it into QCA (Qt Cryptographic Architecture), so that KDE 4 will finally be able to use smartcards. The changes allows the following features: 1. Thread safe, is activated if USE_PTHREAD. 2. Slot event - Will allow us in the future to disconnect VPN when smartcard is removed. In order to support this OpenVPN must support threading... At least SIGUSR1 from a different thread. Threading should be supported in both Windows and Linux. -- currently disabled. When I talk about threading support it is just support in configuration script and that the method that SIGUSR1 self can be called from a different thread. I already handle the monitor threads. 3. Certificate enumeration - Will allow us to finally have one configuration file for all users! When you add the plugin GUI stuff you talked about, we will be able to display a list of available certificates for the user to select. -- currently disabled. 4. Data object manipulation - Will allow us to store tls-auth on the smartcard as well. -- currently disabled. 5. Many other minor improvements. Alon Bar-Lev git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@990 e7ae566f-a301-0410-adde-c780ea21d3b5 --- pkcs11.c | 315 +++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 248 insertions(+), 67 deletions(-) (limited to 'pkcs11.c') diff --git a/pkcs11.c b/pkcs11.c index a8875cf..3b136c5 100644 --- a/pkcs11.c +++ b/pkcs11.c @@ -43,6 +43,74 @@ #include "pkcs11-helper.h" #include "pkcs11.h" +static +unsigned +_pkcs11_msg_pkcs112openvpn ( + IN const unsigned flags +) { + unsigned openvpn_flags; + + switch (flags) { + case PKCS11H_LOG_DEBUG2: + openvpn_flags = D_PKCS11_DEBUG; + break; + case PKCS11H_LOG_DEBUG1: + openvpn_flags = D_SHOW_PKCS11; + break; + case PKCS11H_LOG_INFO: + openvpn_flags = M_INFO; + break; + case PKCS11H_LOG_WARN: + openvpn_flags = M_WARN; + break; + case PKCS11H_LOG_ERROR: + openvpn_flags = M_FATAL; + break; + default: + openvpn_flags = M_FATAL; + break; + } + +#if defined(ENABLE_PKCS11_FORCE_DEBUG) + openvpn_flags=M_INFO; +#endif + + return openvpn_flags; +} + +static +unsigned +_pkcs11_msg_openvpn2pkcs11 ( + IN const unsigned flags +) { + unsigned pkcs11_flags; + + if ((flags & D_PKCS11_DEBUG) != 0) { + pkcs11_flags = PKCS11H_LOG_DEBUG2; + } + else if ((flags & D_SHOW_PKCS11) != 0) { + pkcs11_flags = PKCS11H_LOG_DEBUG1; + } + else if ((flags & M_INFO) != 0) { + pkcs11_flags = PKCS11H_LOG_INFO; + } + else if ((flags & M_WARN) != 0) { + pkcs11_flags = PKCS11H_LOG_WARN; + } + else if ((flags & M_FATAL) != 0) { + pkcs11_flags = PKCS11H_LOG_ERROR; + } + else { + pkcs11_flags = PKCS11H_LOG_ERROR; + } + +#if defined(ENABLE_PKCS11_FORCE_DEBUG) + pkcs11_flags = PKCS11H_LOG_DEBUG2; +#endif + + return pkcs11_flags; +} + static void _pkcs11_openvpn_print ( @@ -61,21 +129,47 @@ _pkcs11_openvpn_print ( msg (M_INFO|M_NOPREFIX|M_NOLF, "%s", Buffer); } +static +void +_pkcs11_openvpn_log ( + IN const void *pData, + IN unsigned flags, + IN const char * const szFormat, + IN va_list args +) { + char Buffer[10*1024]; + + vsnprintf (Buffer, sizeof (Buffer), szFormat, args); + Buffer[sizeof (Buffer)-1] = 0; + + msg (_pkcs11_msg_pkcs112openvpn (flags), "%s", Buffer); +} + static bool -_pkcs11_openvpn_card_prompt ( +_pkcs11_openvpn_token_prompt ( IN const void *pData, - IN const char * const szLabel + IN const pkcs11h_token_id_t token ) { static struct user_pass token_resp; - ASSERT (szLabel!=NULL); + ASSERT (token!=NULL); 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); + openvpn_snprintf ( + token_resp.username, + sizeof (token_resp.username), + "Please insert %s token", + token->label + ); + get_user_pass ( + &token_resp, + NULL, + "token-insertion-request", + GET_USER_PASS_MANAGEMENT|GET_USER_PASS_NEED_OK + ); return strcmp (token_resp.password, "ok") == 0; } @@ -84,16 +178,16 @@ static bool _pkcs11_openvpn_pin_prompt ( IN const void *pData, - IN const char * const szLabel, + IN const pkcs11h_token_id_t token, OUT char * const szPIN, IN const size_t nMaxPIN ) { static struct user_pass token_pass; char szPrompt[1024]; - ASSERT (szLabel!=NULL); + ASSERT (token!=NULL); - openvpn_snprintf (szPrompt, sizeof (szPrompt), "%s token", szLabel); + openvpn_snprintf (szPrompt, sizeof (szPrompt), "%s token", token->label); token_pass.defined = false; token_pass.nocache = true; @@ -111,12 +205,13 @@ _pkcs11_openvpn_pin_prompt ( bool pkcs11_initialize ( - const int nPINCachePeriod + IN const bool fProtectedAuthentication, + IN const int nPINCachePeriod ) { CK_RV rv = CKR_OK; - PKCS11LOG ( - PKCS11_LOG_DEBUG2, + dmsg ( + D_PKCS11_DEBUG, "PKCS#11: pkcs11_initialize - entered" ); @@ -124,32 +219,50 @@ pkcs11_initialize ( rv == CKR_OK && (rv = pkcs11h_initialize ()) != CKR_OK ) { - PKCS11LOG (PKCS11_LOG_ERROR, "PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11h_getMessage (rv)); + msg (M_FATAL, "PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11h_getMessage (rv)); } if ( rv == CKR_OK && - (rv = pkcs11h_setCardPromptHook (_pkcs11_openvpn_card_prompt, NULL)) != CKR_OK + (rv = pkcs11h_setLogHook (_pkcs11_openvpn_log, NULL)) != CKR_OK ) { - PKCS11LOG (PKCS11_LOG_ERROR, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv)); + msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv)); + } + + if (rv == CKR_OK) { + pkcs11h_setLogLevel (_pkcs11_msg_openvpn2pkcs11 (get_debug_level ())); + } + + if ( + rv == CKR_OK && + (rv = pkcs11h_setTokenPromptHook (_pkcs11_openvpn_token_prompt, NULL)) != CKR_OK + ) { + msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv)); } if ( rv == CKR_OK && (rv = pkcs11h_setPINPromptHook (_pkcs11_openvpn_pin_prompt, NULL)) != CKR_OK ) { - PKCS11LOG (PKCS11_LOG_ERROR, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv)); + msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv)); + } + + if ( + rv == CKR_OK && + (rv = pkcs11h_setProtectedAuthentication (fProtectedAuthentication)) != CKR_OK + ) { + msg (M_FATAL, "PKCS#11: Cannot set protected authentication mode %ld-'%s'", rv, pkcs11h_getMessage (rv)); } if ( rv == CKR_OK && (rv = pkcs11h_setPINCachePeriod (nPINCachePeriod)) != CKR_OK ) { - PKCS11LOG (PKCS11_LOG_ERROR, "PKCS#11: Cannot set PIN cache period %ld-'%s'", rv, pkcs11h_getMessage (rv)); + msg (M_FATAL, "PKCS#11: Cannot set PIN cache period %ld-'%s'", rv, pkcs11h_getMessage (rv)); } - PKCS11LOG ( - PKCS11_LOG_DEBUG2, + dmsg ( + D_PKCS11_DEBUG, "PKCS#11: pkcs11_initialize - return %ld-'%s'", rv, pkcs11h_getMessage (rv) @@ -160,15 +273,15 @@ pkcs11_initialize ( void pkcs11_terminate () { - PKCS11LOG ( - PKCS11_LOG_DEBUG2, + dmsg ( + D_PKCS11_DEBUG, "PKCS#11: pkcs11_terminate - entered" ); pkcs11h_terminate (); - PKCS11LOG ( - PKCS11_LOG_DEBUG2, + dmsg ( + D_PKCS11_DEBUG, "PKCS#11: pkcs11_terminate - return" ); } @@ -181,32 +294,69 @@ pkcs11_forkFixup () { bool pkcs11_addProvider ( IN const char * const provider, - IN const char * const sign_mode + IN const bool fProtectedAuthentication, + IN const char * const sign_mode, + IN const bool fCertIsPrivate ) { + unsigned maskSignMode = 0; + CK_RV rv = CKR_OK; - PKCS11LOG ( - PKCS11_LOG_DEBUG2, + ASSERT (provider!=NULL); + /*ASSERT (sign_mode!=NULL); NULL is default */ + + dmsg ( + D_PKCS11_DEBUG, "PKCS#11: pkcs11_addProvider - entered - provider='%s', sign_mode='%s'", provider, sign_mode == NULL ? "default" : sign_mode ); - PKCS11LOG ( - PKCS11_LOG_INFO, + msg ( + M_INFO, "PKCS#11: Adding PKCS#11 provider '%s'", provider ); + if (rv == CKR_OK) { + if (sign_mode == NULL || !strcmp (sign_mode, "auto")) { + maskSignMode = 0; + } + else if (!strcmp (sign_mode, "sign")) { + maskSignMode = PKCS11H_SIGNMODE_MASK_SIGN; + } + else if (!strcmp (sign_mode, "recover")) { + maskSignMode = PKCS11H_SIGNMODE_MASK_RECOVER; + } + else if (!strcmp (sign_mode, "any")) { + maskSignMode = ( + PKCS11H_SIGNMODE_MASK_SIGN | + PKCS11H_SIGNMODE_MASK_RECOVER + ); + } + else { + msg (M_FATAL, "PKCS#11: Invalid sign mode '%s'", sign_mode); + rv = CKR_ARGUMENTS_BAD; + } + } + if ( rv == CKR_OK && - (rv = pkcs11h_addProvider (provider, sign_mode)) != CKR_OK + (rv = pkcs11h_addProvider ( + provider, + provider, + fProtectedAuthentication, + maskSignMode, + PKCS11H_SLOTEVENT_METHOD_AUTO, + 0, + fCertIsPrivate + )) != CKR_OK ) { - PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot initialize provider '%s' %ld-'%s'", provider, rv, pkcs11h_getMessage (rv)); + msg (M_WARN, "PKCS#11: Cannot initialize provider '%s' %ld-'%s'", provider, rv, pkcs11h_getMessage (rv)); } - PKCS11LOG ( - PKCS11_LOG_DEBUG2, + dmsg ( + D_PKCS11_DEBUG, "PKCS#11: pkcs11_addProvider - return rv=%ld-'%s'", rv, pkcs11h_getMessage (rv) @@ -221,73 +371,94 @@ SSL_CTX_use_pkcs11 ( 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 + IN const char * const pkcs11_id ) { X509 *x509 = NULL; RSA *rsa = NULL; - pkcs11h_openssl_session_t pkcs11h_openssl_session = 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 fOK = true; - PKCS11LOG ( - PKCS11_LOG_DEBUG2, - "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", + ASSERT (ssl_ctx!=NULL); + ASSERT (pkcs11_slot_type!=NULL); + ASSERT (pkcs11_slot!=NULL); + ASSERT (pkcs11_id_type!=NULL); + ASSERT (pkcs11_id!=NULL); + + dmsg ( + D_PKCS11_DEBUG, + "PKCS#11: SSL_CTX_use_pkcs11 - entered - ssl_ctx=%p, pkcs11_slot_type='%s', pkcs11_slot='%s', pkcs11_id_type='%s', pkcs11_id='%s'", (void *)ssl_ctx, pkcs11_slot_type, pkcs11_slot, pkcs11_id_type, - pkcs11_id, - pkcs11_protected_authentication ? 1 : 0 + pkcs11_id ); - PKCS11ASSERT (ssl_ctx!=NULL); - PKCS11ASSERT (pkcs11_slot_type!=NULL); - PKCS11ASSERT (pkcs11_slot!=NULL); - PKCS11ASSERT (pkcs11_id_type!=NULL); - PKCS11ASSERT (pkcs11_id!=NULL); + ASSERT (ssl_ctx!=NULL); + ASSERT (pkcs11_slot_type!=NULL); + ASSERT (pkcs11_slot!=NULL); + ASSERT (pkcs11_id_type!=NULL); + ASSERT (pkcs11_id!=NULL); if ( fOK && - (pkcs11h_openssl_session = pkcs11h_openssl_createSession ()) == NULL + (rv = pkcs11h_locate_certificate ( + pkcs11_slot_type, + pkcs11_slot, + pkcs11_id_type, + pkcs11_id, + &certificate_id + )) != CKR_OK ) { fOK = false; - PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot initialize openssh session"); + msg (M_WARN, "PKCS#11: Cannot set parameters %ld-'%s'", rv, pkcs11h_getMessage (rv)); } if ( fOK && - (rv = pkcs11h_createCertificateSession ( - pkcs11_slot_type, - pkcs11_slot, - pkcs11_id_type, - pkcs11_id, - pkcs11_protected_authentication, - pkcs11_cert_private, + (rv = pkcs11h_certificate_create ( + certificate_id, PKCS11H_PIN_CACHE_INFINITE, - &pkcs11h_openssl_session->certificate + &certificate )) != CKR_OK ) { fOK = false; - PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot set parameters %ld-'%s'", rv, pkcs11h_getMessage (rv)); + msg (M_WARN, "PKCS#11: Cannot get certificate %ld-'%s'", rv, pkcs11h_getMessage (rv)); } if ( fOK && - (rsa = pkcs11h_openssl_getRSA (pkcs11h_openssl_session)) == NULL + (openssl_session = pkcs11h_openssl_createSession (certificate)) == NULL ) { fOK = false; - PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Unable get rsa object"); + msg (M_WARN, "PKCS#11: Cannot initialize openssl session"); + } + + if (fOK) { + /* + * Will be released by openssl_session + */ + certificate = NULL; } if ( fOK && - (x509 = pkcs11h_openssl_getX509 (pkcs11h_openssl_session)) == NULL + (rsa = pkcs11h_openssl_getRSA (openssl_session)) == NULL ) { fOK = false; - PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Unable get certificate object"); + msg (M_WARN, "PKCS#11: Unable get rsa object"); + } + + if ( + fOK && + (x509 = pkcs11h_openssl_getX509 (openssl_session)) == NULL + ) { + fOK = false; + msg (M_WARN, "PKCS#11: Unable get certificate object"); } if ( @@ -295,7 +466,7 @@ SSL_CTX_use_pkcs11 ( !SSL_CTX_use_RSAPrivateKey (ssl_ctx, rsa) ) { fOK = false; - PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot set private key for openssl"); + msg (M_WARN, "PKCS#11: Cannot set private key for openssl"); } if ( @@ -303,7 +474,7 @@ SSL_CTX_use_pkcs11 ( !SSL_CTX_use_certificate (ssl_ctx, x509) ) { fOK = false; - PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot set certificate for openssl"); + msg (M_WARN, "PKCS#11: Cannot set certificate for openssl"); } /* @@ -320,14 +491,24 @@ SSL_CTX_use_pkcs11 ( RSA_free (rsa); rsa = NULL; } + + if (certificate != NULL) { + pkcs11h_freeCertificate (certificate); + certificate = NULL; + } + + if (certificate_id != NULL) { + pkcs11h_freeCertificateId (certificate_id); + certificate_id = NULL; + } - if (pkcs11h_openssl_session != NULL) { - pkcs11h_openssl_freeSession (pkcs11h_openssl_session); - pkcs11h_openssl_session = NULL; + if (openssl_session != NULL) { + pkcs11h_openssl_freeSession (openssl_session); + openssl_session = NULL; } - PKCS11LOG ( - PKCS11_LOG_DEBUG2, + dmsg ( + D_PKCS11_DEBUG, "PKCS#11: SSL_CTX_use_pkcs11 - return fOK=%d, rv=%ld", fOK ? 1 : 0, rv -- cgit v1.2.3