> ## Documentation Index
> Fetch the complete documentation index at: https://docs.futurex.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Install and configure the FxPKCS11 module

> Procedural guide to install and configure Futurex PKCS #11 on the machine running OpenVPN Connect.

<Note>These steps are typically performed by the **CryptoHub Admin** on the device that will be hosting the OpenVPN Connect v3 application. See [Underlying Responsibility Roles](./Before_you_start#underlying-responsibility-roles) for more information.</Note>

## Windows

Perform the following steps to install and configure FxPKCS11 on your OpenVPN Connect Windows host.

### Step 1: Extract the CryptoHub package and create the FxPKCS11 directory

<Steps>
  <Step>
    On the Windows hosting OpenVPN Connect, open PowerShell as Administrator.
  </Step>

  <Step>
    Extract `Identifier-OpenVPN.zip` into `C:\Program Files\Futurex\fxpkcs11`. If the `fxpkcs11` folder doesn’t exist, it will be created automatically

    ```powershell expandable lines wrap title="PowerShell" theme={null}
    Expand-Archive -Path "C:\path\to\Identifier-OpenVPN.zip" -DestinationPath "C:\Program Files\Futurex\fxpkcs11" -Force
    ```

    <Note>
      Update `-Path` to the actual filepath, the filename of your CryptoHub package, and `-DestinationPath` to your preferred extraction location.

      The `-Force` flag creates the destination directory if it does not already exist and overwrites any existing files if it does.
    </Note>

    The endpoint zip file downloaded from your browser contains the following files:

    <table>
      <thead>
        <th>Filename</th>
        <th>Description</th>
      </thead>

      <tbody>
        <tr>
          <td><code>PKCS11Manager.exe</code></td>
          <td>Program to test the connection to the CryptoHub and perform basic functions through the <strong>FXPKCS11</strong> module, such as logging in and generating random data.</td>
        </tr>

        <tr>
          <td><code>ca-chain.pem</code></td>
          <td>CA certificate bundle</td>
        </tr>

        <tr>
          <td><code>client-cert.pem</code></td>
          <td>Client TLS certificate</td>
        </tr>

        <tr>
          <td><code>client.p12</code></td>
          <td>Full Client PKI in encrypted PKCS #12 format (contains the CA chain, client certificate, and client private key)</td>
        </tr>

        <tr>
          <td><code>configTest.exe</code></td>
          <td>Program to test the configuration and connection to the CryptoHub</td>
        </tr>

        <tr>
          <td><code>fxpkcs11.cfg</code></td>
          <td>Configuration file for the Futurex PKCS #11 library</td>
        </tr>

        <tr>
          <td><code>fxpkcs11.dll</code></td>
          <td>The Futurex PKCS #11 library file.</td>
        </tr>

        <tr>
          <td><code>CryptoHub \<number>.cer</code></td>
          <td>Auto-generated self-signed CA certificate used to issue client endpoint TLS certs (number is random)</td>
        </tr>

        <tr>
          <td><code>Futurex Test Root CA (ECC).cer</code> or <code>Futurex Test Root SSL CA.cer</code></td>
          <td>Futurex Test Root CA for embedded Futurex Test TLS certs (ECC or RSA, based on the algorithm configured for the connection pair)</td>
        </tr>
      </tbody>
    </table>
  </Step>
</Steps>

#### Optional: Use a custom configuration location

By default, `fxpkcs11.dll` looks for `fxpkcs11.cfg` in `C:\Program Files\Futurex\fxpkcs11`. If you have moved `fxpkcs11.cfg` to a custom location, set the `FXPKCS11_CFG` environment variable to point to it.

For the current PowerShell session only:

```powershell expandable lines wrap title="PowerShell" theme={null}
$env:FXPKCS11_CFG = "C:\custom\path\to\fxpkcs11.cfg"
```

For a permanent system-wide setting that persists across all sessions:

```powershell expandable lines wrap title="PowerShell" theme={null}
[System.Environment]::SetEnvironmentVariable("FXPKCS11_CFG", "C:\custom\path\to\fxpkcs11.cfg", "Machine")
```

<Note>
  If you choose the permanent option, you will need to restart your PowerShell session for the changes to take effect.
</Note>

#### Optional: Use custom certificate paths

By default, the FxPKCS11 module expects certificate files to be in the same directory as the `fxpkcs11.cfg` file (whether at the default `C:\Program Files\Futurex\fxpkcs11` location or your custom location via `FXPKCS11_CFG`). You can customize the paths to your certificate files directly in the `fxpkcs11.cfg` file by modifying the following settings:

* `PROD-TLS-KEY`: Path to the `client.p12` PKCS#12 file
* `PROD-TLS-CA`: Path to the `CryptoHub 1234567890.cer` file
* `PROD-TLS-CA`: Path to the `Futurex Test Root CA (ECC).cer` or `Futurex Test Root SSL CA.cer` file (depending on your CryptoHub connection type)

<Note> Make sure to enter the path without quotes, so an example path would be `C:\ProgramData\fxpkcs11\certs\CryptoHub 1234567890.cer` instead of `"C:\ProgramData\fxpkcs11\certs\CryptoHub 1234567890.cer"` </Note>

### Step 2: Securing the PKCS #12 password

By default, the PKCS #12 password resides in plaintext inside `fxpkcs11.cfg`. To improve security, the recommended approach is to extract the password and store it separately, reducing the risk of accidental exposure.

On Windows, the recommended approach is to store the password as a system environment variable at the **Machine** scope, which persists across all sessions and is available to all shells and services without needing to be re-set.

<Note>
  Update the path to `fxpkcs11.cfg` in the commands below if you have changed it from the default location.
</Note>

<Steps>
  <Step>
    Extract the password from `fxpkcs11.cfg`:

    ```powershell expandable lines wrap title="PowerShell" theme={null}
    $pass = (Get-Content "C:\Program Files\Futurex\fxpkcs11\fxpkcs11.cfg" | Select-String "PROD-TLS-KEY-PASS").Line -replace '.*<PROD-TLS-KEY-PASS>\s*(.*?)\s*<\/PROD-TLS-KEY-PASS>.*', '$1'
    ```
  </Step>

  <Step>
    Store it as a permanent system environment variable at the Machine scope

    ```powershell expandable lines wrap title="PowerShell" theme={null}
    [System.Environment]::SetEnvironmentVariable("PKCS11_P12", $pass, "Machine")
    ```
  </Step>

  <Step>
    Close the current PowerShell session and open a new one with administrator privileges. Confirm the environment variable was set correctly:

    ```powershell expandable lines wrap title="PowerShell" theme={null}
    [System.Environment]::GetEnvironmentVariable("PKCS11_P12", "Machine")
    ```
  </Step>

  <Step>
    Update the `<PROD-TLS-KEY-PASS>` entry in `fxpkcs11.cfg` to reference the environment variable:

    ```powershell expandable lines wrap title="PowerShell" theme={null}
    $config = Get-Content "C:\Program Files\Futurex\fxpkcs11\fxpkcs11.cfg" -Raw
    $config = $config -replace '<PROD-TLS-KEY-PASS>.*?</PROD-TLS-KEY-PASS>', '<PROD-TLS-KEY-PASS> env:PKCS11_P12 </PROD-TLS-KEY-PASS>'
    Set-Content "C:\Program Files\Futurex\fxpkcs11\fxpkcs11.cfg" $config
    ```
  </Step>

  <Step>
    Confirm the change was applied correctly in `fxpkcs11.cfg`:

    ```powershell expandable lines wrap title="PowerShell" theme={null}
    Select-String -Path "C:\Program Files\Futurex\fxpkcs11\fxpkcs11.cfg" -Pattern "<PROD-TLS-KEY-PASS> env:PKCS11_P12 </PROD-TLS-KEY-PASS>"
    ```

    It should have `env:PKCS11_P12` in the line now instead of the plaintext password.
  </Step>
</Steps>

### Step 3: Comment out or remove the plaintext password in `fxpkcs11.cfg`

The `<CRYPTO-OPR-PASS>` entry in `fxpkcs11.cfg` contains the plaintext password used to authenticate the crypto user. Since we're defining the password in the OpenVPN Connect application (required for this integration), comment out this line by adding a `#` at the beginning, or delete the line entirely from `fxpkcs11.cfg`.

To comment out the line:

```powershell expandable lines wrap title="PowerShell" theme={null}
$configPath = "C:\Program Files\Futurex\fxpkcs11\fxpkcs11.cfg"
(Get-Content $configPath) -replace '^\s*(<CRYPTO-OPR-PASS>)', '# $1' | Set-Content $configPath
```

<Warning>
  If you remove the `<CRYPTO-OPR-PASS>` line, store the password in a secure location of your choice for future reference.
</Warning>

### Step 4: Create the pkcs11\_modules directory and copy the Futurex PKCS #11 module for OpenVPN Connect to recognize it

<Steps>
  <Step>
    Open PowerShell terminal as an Administrator.
  </Step>

  <Step>
    Add `fxpkcs11` to the system PATH:

    ```powershell expandable lines wrap title="PowerShell" theme={null}
    [Environment]::SetEnvironmentVariable("Path", [Environment]::GetEnvironmentVariable("Path", "Machine") + ";C:\Program Files\Futurex\fxpkcs11","Machine")
    ```
  </Step>

  <Step>
    Create the `pkcs11_modules` in OpenVPN Connect folder:

    ```powershell expandable lines wrap title="PowerShell" theme={null}
    New-Item -Path "C:\Program Files\OpenVPN Connect\pkcs11_modules" -ItemType Directory
    ```
  </Step>

  <Step>
    Copy the `fxpkcs11.dll` to the newly created directory:

    ```powershell expandable lines wrap title="PowerShell" theme={null}
    Copy-Item "C:\Program Files\Futurex\fxpkcs11\fxpkcs11.dll" -Destination "C:\Program Files\OpenVPN Connect\pkcs11_modules\fxpkcs11.dll"
    ```
  </Step>
</Steps>

### Step 5: Validate with configTest (recommended)

<Steps>
  <Step>
    Run the configuration test tool:

    ```PowerShell expandable lines wrap title="PowerShell" theme={null}
     & 'C:\Program Files\Futurex\fxpkcs11\configTest.exe'
    ```
  </Step>

  <Step>
    Confirm the connection test succeeds.
  </Step>
</Steps>

If you see the message **Windows protected your PC**, click on **More info**, and click on **Run anyway** to allow the test to run.

<Tip>
  If you encounter issues during validation, check the `Troubleshoot validation issues` steps at the end of this guide.
</Tip>

## macOS

Perform the following steps to install and configure FxPKCS11 on your OpenVPN Connect macOS host.

### Step 1: Create the FxPKCS11 directory and extract the CryptoHub package

<Steps>
  <Step>
    On the macOS hosting OpenVPN Connect, open a terminal window.
  </Step>

  <Step>
    Create the following directory:

    ```zsh expandable lines wrap title="zsh" theme={null}
    sudo mkdir -p /usr/local/lib/fxpkcs11
    ```

    <Note>`-p` flag creates parent directories as needed and does not throw an error if the directory already exists.</Note>
  </Step>

  <Step>
    Extract the ZIP file.

    ```zsh expandable lines wrap title="zsh" theme={null}
    sudo unzip /path/to/Identifier-OpenVPN.zip -d /usr/local/lib/fxpkcs11
    ```

    <Note>Update the path to the actual filepath and filename of your CryptoHub package.</Note>
  </Step>

  <Step>
    The endpoint zip file downloaded from your browser contains the following files:

    <table>
      <thead>
        <th>Filename</th>
        <th>Description</th>
      </thead>

      <tbody>
        <tr>
          <td><code>PKCS11Manager</code></td>
          <td>Program to test the connection to the CryptoHub and perform basic functions through the <strong>FXPKCS11</strong> module, such as logging in and generating random data.</td>
        </tr>

        <tr>
          <td><code>ca-chain.pem</code></td>
          <td>CA certificate bundle</td>
        </tr>

        <tr>
          <td><code>client-cert.pem</code></td>
          <td>Client TLS certificate</td>
        </tr>

        <tr>
          <td><code>client.p12</code></td>
          <td>Full Client PKI in encrypted PKCS #12 format (contains the CA chain, client certificate, and client private key)</td>
        </tr>

        <tr>
          <td><code>configTest</code></td>
          <td>Program to test the configuration and connection to the CryptoHub</td>
        </tr>

        <tr>
          <td><code>fxpkcs11.cfg</code></td>
          <td>Configuration file for the Futurex PKCS #11 library</td>
        </tr>

        <tr>
          <td><code>libfxpkcs11.dylib</code></td>
          <td>The Futurex PKCS #11 library file.</td>
        </tr>

        <tr>
          <td><code>CryptoHub \<number>.cer</code></td>
          <td>Auto-generated self-signed CA certificate used to issue client endpoint TLS certs (number is random)</td>
        </tr>

        <tr>
          <td><code>Futurex Test Root CA (ECC).cer</code> or <code>Futurex Test Root SSL CA.cer</code></td>
          <td>Futurex Test Root CA for embedded Futurex Test TLS certs (ECC or RSA, based on the algorithm configured for the connection pair)</td>
        </tr>
      </tbody>
    </table>
  </Step>

  <Step>
    Remove the macOS quarantine attribute from the extracted files:

    ```zsh expandable lines wrap title="zsh" theme={null}
    sudo xattr -dr com.apple.quarantine /usr/local/lib/fxpkcs11
    ```

    <Note>When files are downloaded through a browser, macOS attaches a `com.apple.quarantine` extended attribute that triggers Gatekeeper to block them on first use. This command strips the attribute from the PKCS #11 library and helper binaries in one pass so that OpenVPN Connect can load the module and `configTest` can run without being blocked by macOS Privacy & Security warnings. Skipping this step will require you to manually approve each binary in **\[ System Settings ]** > **\[ Privacy & Security ]** and restart OpenVPN Connect before the integration will work.</Note>
  </Step>

  <Step>
    Navigate to the `/usr/local/lib/fxpkcs11` directory:

    ```zsh expandable lines wrap title="zsh" theme={null}
    cd /usr/local/lib/fxpkcs11
    ```
  </Step>

  <Step>
    Move the following files to `/etc` (the default expected location):

    * `CryptoHub 1234567890.cer`
    * `Futurex Test Root CA (ECC).cer` or `Futurex Test Root SSL CA.cer`
    * `client.p12`
    * `fxpkcs11.cfg`

    ```zsh expandable lines wrap title="zsh" theme={null}
    sudo mv 'CryptoHub '*.cer 'Futurex Test Root '*.cer client.p12 fxpkcs11.cfg /etc/
    ```
  </Step>
</Steps>

#### Optional: Use a custom configuration location

If you prefer to store the configuration file elsewhere, define the environment variable for the current terminal session:

```zsh expandable lines wrap title="zsh" theme={null}
export FXPKCS11_CFG=/path/to/your/fxpkcs11.cfg
```

#### Optional: Use custom certificate paths

By default, the FxPKCS11 module expects certificate files to be in the same directory as the `fxpkcs11.cfg` file (whether at the default `/etc/` location or your custom location via `FXPKCS11_CFG`). You can customize the paths to your certificate files directly in the `fxpkcs11.cfg` file by modifying the following settings:

* `PROD-TLS-KEY`: Path to the `client.p12` PKCS#12 file
* `PROD-TLS-CA`: Path to the `CryptoHub 1234567890.cer` file
* `PROD-TLS-CA`: Path to the `Futurex Test Root CA (ECC).cer` or `Futurex Test Root SSL CA.cer` file (depending on your CryptoHub connection type)

### Step 2: Configure secrets (PKCS #12 password)

By default, the PKCS #12 password resides in plaintext inside `fxpkcs11.cfg`. To improve security, the recommended approach is to extract the password and store it separately, reducing the risk of accidental exposure.

On macOS, there are two ways to achieve this:

* **Session environment variable**: Temporary, only available for the current shell session. Must be re-set each time a new shell is opened.
* **macOS Keychain**: Permanent, persists across all sessions and is available to all shells and services without needing to be re-set.

<Note>
  Update the path to `fxpkcs11.cfg` in the commands below if you have changed it from the default location.
</Note>

<Tabs>
  <Tab title="Session environment variable">
    <Steps>
      <Step>
        Extract the password from `fxpkcs11.cfg` and store it as a session environment variable:

        ```zsh expandable lines wrap title="zsh" theme={null}
        export PKCS11_P12=$(grep PROD-TLS-KEY-PASS /etc/fxpkcs11.cfg | sed 's/.*<PROD-TLS-KEY-PASS>\s*\(.*\)\s*<\/PROD-TLS-KEY-PASS>.*/\1/')
        ```
      </Step>

      <Step>
        Confirm the environment variable was set correctly:

        ```zsh expandable lines wrap title="zsh" theme={null}
        echo $PKCS11_P12
        ```
      </Step>

      <Step>
        Update the `<PROD-TLS-KEY-PASS>` entry in `fxpkcs11.cfg` to point to the environment variable:

        ```zsh expandable lines wrap title="zsh" theme={null}
        sed -i '' 's|<PROD-TLS-KEY-PASS>.*</PROD-TLS-KEY-PASS>|<PROD-TLS-KEY-PASS> env:PKCS11_P12 </PROD-TLS-KEY-PASS>|' /etc/fxpkcs11.cfg
        ```
      </Step>

      <Step>
        Confirm the change was applied correctly in `fxpkcs11.cfg`:

        ```zsh expandable lines wrap title="zsh" theme={null}
        grep "PROD-TLS-KEY-PASS" /etc/fxpkcs11.cfg
        ```
      </Step>
    </Steps>
  </Tab>

  <Tab title="macOS Keychain">
    <Steps>
      <Step>
        Extract the password from `fxpkcs11.cfg` and store it securely in the macOS Keychain:

        ```zsh expandable lines wrap title="zsh" theme={null}
        security add-generic-password -a "pkcs12" -s "fxpkcs11" -w "$(grep PROD-TLS-KEY-PASS /etc/fxpkcs11.cfg | sed 's/.*<PROD-TLS-KEY-PASS>\s*\(.*\)\s*<\/PROD-TLS-KEY-PASS>.*/\1/')"
        ```
      </Step>

      <Step>
        Add to `~/.zshrc` to load from Keychain automatically on every session:

        ```zsh expandable lines wrap title="zsh" theme={null}
        echo 'export PKCS11_P12=$(security find-generic-password -a "pkcs12" -s "fxpkcs11" -w)' >> ~/.zshrc
        source ~/.zshrc
        ```

        <Note>If you are using bash shell instead, replace `~/.zshrc` with `~/.bash_profile`.</Note>
      </Step>

      <Step>
        Confirm the environment variable was set correctly:

        ```zsh expandable lines wrap title="zsh" theme={null}
        echo $PKCS11_P12
        ```
      </Step>

      <Step>
        Update the `<PROD-TLS-KEY-PASS>` entry in `fxpkcs11.cfg` to point to the environment variable:

        ```zsh expandable lines wrap title="zsh" theme={null}
        sed -i '' 's|<PROD-TLS-KEY-PASS>.*</PROD-TLS-KEY-PASS>|<PROD-TLS-KEY-PASS> env:PKCS11_P12 </PROD-TLS-KEY-PASS>|' /etc/fxpkcs11.cfg
        ```
      </Step>

      <Step>
        Confirm the change was applied correctly in `fxpkcs11.cfg`:

        ```zsh expandable lines wrap title="zsh" theme={null}
        grep "PROD-TLS-KEY-PASS" /etc/fxpkcs11.cfg
        ```
      </Step>
    </Steps>
  </Tab>
</Tabs>

### Step 3: Comment out or remove the plaintext password in `fxpkcs11.cfg`

The `<CRYPTO-OPR-PASS>` entry in `fxpkcs11.cfg` contains the plaintext password used to authenticate the crypto user. Since we're defining the password in the OpenVPN Connect application (required for this integration), comment out this line by adding a `#` at the beginning, or delete the line entirely from `fxpkcs11.cfg`.

<Note>
  If you remove the `<CRYPTO-OPR-PASS>` line, store the password in a secure location of your choice for future reference.
</Note>

### Step 4: Create a symlink to the Futurex PKCS #11 module for OpenVPN Connect to recognize it

<Steps>
  <Step>
    Locate the library at `/usr/local/lib/fxpkcs11/libfxpkcs11.dylib`.
  </Step>

  <Step>
    Open Terminal and create the `.pkcs11_modules` directory if it does not already exist:

    ```zsh expandable lines wrap title="zsh" theme={null}
    mkdir -p ~/.pkcs11_modules
    ```
  </Step>

  <Step>
    Create a symlink to the library file:

    ```zsh expandable lines wrap title="zsh" theme={null}
    ln -s /usr/local/lib/fxpkcs11/libfxpkcs11.dylib ~/.pkcs11_modules/libfxpkcs11.dylib
    ```
  </Step>

  <Step>
    Confirm the symlink was created successfully:

    ```zsh expandable lines wrap title="zsh" theme={null}
    ls -al ~/.pkcs11_modules
    ```

    You should see output similar to the following:

    ```text expandable lines wrap title="Output" theme={null}
    lrwxr-xr-x  1 username  staff  45 Jan 1 12:00 libfxpkcs11.dylib -> /usr/local/lib/fxpkcs11/libfxpkcs11.dylib
    ```
  </Step>
</Steps>

### Step 5: Validate with configTest (recommended)

<Steps>
  <Step>
    Run the configuration test tool:

    ```zsh expandable lines wrap title="zsh" theme={null}
    /usr/local/lib/fxpkcs11/configTest
    ```
  </Step>

  <Step>
    Confirm the connection test succeeds.

    If you see:

    ```zsh expandable lines wrap title="zsh" theme={null}
    -bash: /usr/local/lib/fxpkcs11/configTest: Permission denied
    ```

    Make the file executable:

    ```zsh expandable lines wrap title="zsh" theme={null}
    chmod +x /usr/local/lib/fxpkcs11/configTest
    ```

    Then, run the test again.
  </Step>
</Steps>

## Troubleshoot validation issues

If `configTest` fails:

<Steps>
  <Step>
    Check the FxPKCS11 log file:

    * Default location: same directory as `fxpkcs11.cfg`.
    * To customize, modify the `LOG-FILE` setting in `fxpkcs11.cfg`.
  </Step>

  <Step>
    Ensure that:

    * The PKCS #11 PIN is correct.
    * `fxpkcs11.cfg` resides at `/etc/fxpkcs11.cfg` (or confirm `FXPKCS11_CFG` points to the correct location).
    * By default, all TLS files listed below must reside in the same directory as `fxpkcs11.cfg`. If you customized the file paths in `fxpkcs11.cfg`, place each file in its configured location instead:
      * `client.p12`
      * `CryptoHub 1234567890.cer`
      * `Futurex Test Root CA (ECC).cer` (for ECC connections) or `Futurex Test Root SSL CA.cer` (for RSA connections)
    * `PKCS11_P12` has the correct value.
  </Step>

  <Step>
    If you see a macOS dialog stating that `libfxpkcs11.dylib` or `configTest` was blocked or could not be verified, the quarantine attribute was not removed during Step 1. Re-run:

    ```zsh expandable lines wrap title="zsh" theme={null}
    sudo xattr -dr com.apple.quarantine /usr/local/lib/fxpkcs11
    ```

    Then restart OpenVPN Connect and try again.
  </Step>
</Steps>
