Skip to main content

How to Add Dual-Factor Authentication to an OpenVPN Configuration Using Client-Side Smart Cards

Dual-factor authentication is a method of authentication that combines two elements: something you have and something you know.

Something you have should be a device that cannot be duplicated; such a device can be a cryptographic token that contains a private secret key. This private key is generated inside the device and never leaves it. If a user possessing this token attempts to access protected services on a remote network, the authorization process that grants or denies network access can establish, with a high degree of certainty, that the user seeking access is in physical possession of a known, certified token.

Something you know can be a password presented to the cryptographic device. You can't access the private secret key without presenting the proper password. Another feature of cryptographic devices is that they are prohibited from using the private secret key if the wrong password has been presented more than an allowed number of times. This behavior ensures that if a user loses his device, it would be infeasible for another person to use it.

Cryptographic devices are commonly called "smart cards" or "tokens" and are used in conjunction with a PKI (Public Key Infrastructure). The VPN server can examine an X.509 certificate and verify the user holds the corresponding private secret key. Since the device cannot be duplicated and requires a valid password, the server can authenticate the user with high confidence.

Dual-factor authentication is much stronger than password-based authentication because, in the worst-case scenario, only one person at a time can use the cryptographic token. Passwords can be guessed and exposed to other users. In the worst-case scenario, an infinite number of people could attempt to gain unauthorized access when resources are protected using password-only authentication.

If you store the secret private key in a file, the key is usually encrypted by a password. The problem with this approach is that the encrypted key is exposed to decryption attacks or spyware/malware running on the client machine. Unlike when using a cryptographic device, the file cannot erase itself automatically after several failed decryption attempts.

This standard specifies an API, called Cryptoki, to devices which hold cryptographic information and perform cryptographic functions. Cryptoki, pronounced "crypto-key" and short for cryptographic token interface, follows a simple object-based approach, addressing the goals of technology independence (any kind of device) and resource sharing (multiple applications accessing multiple devices), presenting to applications a common, logical view of the device called a cryptographic token.

Source: RSA Security Inc.

To summarize, PKCS#11 is a standard that can be used by application software to access cryptographic tokens such as smart cards and other devices. Most device vendors provide a library that implements the PKCS#11 provider interface -- this library can be used by applications to access these devices. PKCS#11 is a cross-platform, vendor-independent free standard.

The first thing you need to do is to find the provider library, it should be installed with the device drivers. Each vendor has its own library. For example, the OpenSC PKCS#11 provider is located at /usr/lib/pkcs11/opensc-pkcs11.so on Unix or at opensc-pkcs11.dll on Windows.

You should follow an enrollment procedure:

  1. Initialize the PKCS#11 token.

  2. Generate RSA key pair on the PKCS#11 token.

  3. Create a certificate request based on the key pair; you can use OpenSC and OpenSSL.

  4. Submit the certificate request to a certificate authority and receive a certificate.

  5. Load the certificate onto the token while noting that the ID and label attributes of the certificate must match those of the private key.

A configured token is a token that has a private key object and a certificate object, where both share the same ID and label attributes.

A simple enrollment utility is Easy-RSA 2.0, part of the OpenVPN 2.1 series. Follow the instructions in the README file, and then use the pkitool to enroll.

Initialize a token using the following command:

$ ./pkitool --pkcs11-slots /usr/lib/pkcs11/
$ ./pkitool --pkcs11-init /usr/lib/pkcs11/  

Enroll a certificate using the following command:

$ ./pkitool --pkcs11 /usr/lib/pkcs11/   client1

You should have OpenVPN 2.1 or above to use the PKCS#11 features.

Determine the correct object

Each PKCS#11 provider can support multiple devices. To view the available object list, you can use the following command:

$ openvpn --show-pkcs11-ids /usr/lib/pkcs11/

The following objects are available for use.
Each object shown below may be used as parameter to
--pkcs11-id option please remember to use single quote mark.

Certificate
       DN:             /CN=User1
       Serial:         490B82C4000000000075
       Serialized id:  aaaa/bbb/41545F5349474E415455524581D2A1A1B23C4AA4CB17FAF7A4600

Each certificate/private key pair has a unique "Serialized id" string. The serialized id string of the requested certificate should be specified to the pkcs11-id option using single quote marks.

pkcs11-id 'aaaa/bbb/41545F5349474E415455524581D2A1A1B23C4AA4CB17FAF7A4600'

Using OpenVPN with PKCS#11

A typical set of OpenVPN options for PKCS#11:

pkcs11-providers /usr/lib/pkcs11/
pkcs11-id 'aaaa/bbb/41545F5349474E415455524581D2A1A1B23C4AA4CB17FAF7A4600'

This will select the object that matches the pkcs11-id string.

Advanced OpenVPN options for PKCS#11:

pkcs11-providers /usr/lib/pkcs11/provider1.so /usr/lib/pkcs11/provider2.so
pkcs11-id 'aaaa/bbb/41545F5349474E415455524581D2A1A1B23C4AA4CB17FAF7A4600'
pkcs11-pin-cache 300
daemon
auth-retry nointeract
management-hold
management-signal
management 127.0.0.1 8888
management-query-passwords

This will load two providers into OpenVPN, use the certificate specified on the pkcs11-id option, and use the management interface to query passwords. The daemon will resume in a hold state if the token cannot be accessed. The token will be used for 300 seconds, after which the password will be re-queried and the session will disconnect if the management session disconnects.

PKCS#11 implementation considerations

Many PKCS#11 providers make use of threads. To avoid problems caused by the implementation of LinuxThreads (setuid, chroot), it's highly recommended to upgrade to Native POSIX Thread Library (NPTL) enabled glibc if you intend to use PKCS#11.

OpenSC PKCS#11 provider

OpenSC PKCS#11 provider is located at /usr/lib/pkcs11/opensc-pkcs11.so on Unix or at opensc-pkcs11.dll on Windows.

PKCS#11 is a free, cross-platform, vendor-independent standard. CryptoAPI is a Microsoft-specific API. Most smart card vendors provide support for both interfaces. In the Windows environment, the user should select which interface to use.

The current implementation of OpenVPN that uses the MS CryptoAPI (cryptoapicert option) works well as long as you don't run OpenVPN as a service. If you wish to run OpenVPN in an administrative environment using a service, the implementation will not work with most smart cards because of the following reasons:

  • Most smart card providers do not load certificates into the local machine store, so the implementation can't access the user certificate.

  • If the OpenVPN client is running as a service without direct interaction with the end-user, the service cannot query the user to provide a password for the smart card, causing the password-verification process on the smart card to fail.

Using the PKCS#11 interface, you can use smart cards with OpenVPN in any implementation because PKCS#11 doesn't access Microsoft stores and doesn't necessarily require direct interaction with the end user.