Skip to content

Can not re-connect TLS when using PKCS #11 #50851

Open
@dachrillz

Description

@dachrillz

Version

v21.2.0 (However have tried with node 18,19,20)

Platform

Linux szabo 6.2.16-2-MANJARO #1 SMP PREEMPT_DYNAMIC Sun Jun 4 12:09:09 UTC 2023 x86_64 GNU/Linux

Subsystem

tls

What steps will reproduce the bug?

Background: I am using mqtt.js. I recently had flaky internet meaning that the client disconnected. I noticed that it fails to reconnect. Some debugging lead me to believe that the problem's entry point is somewhere in Node (but it has something to do with the interaction with the crypto engine)

All scripts are run as follows:

  "scripts": {
    "start": "PKCS11_MODULE_PATH='/usr/lib/libykcs11.so' node index.js"
  },

The most minimal example i managed to create of looks as follows

const tls = require("tls");

const config = {
  privateKeyIdentifier:
    "pkcs11:model=YubiKey%20YK5;manufacturer=Yubico%20%28www.yubico.com%29;serial=22484003;token=YubiKey%20PIV%20%2322484003;id=%04;object=Private%20key%20for%20Card%20Authentication;type=private;pin-value=123456",
  privateKeyEngine: "pkcs11",
};

tls.createSecureContext(config);
console.log("First time around ok!");
tls.createSecureContext(config);
console.log("We never get here");

This produces

npm start

> what@1.0.0 start
> PKCS11_MODULE_PATH='/usr/lib/libykcs11.so' node index.js

First time around ok!
node:internal/tls/secure-context:207
        context.setEngineKey(privateKeyIdentifier, privateKeyEngine);
                ^

Error: error:12800067:DSO support routines::could not load the shared library
    at configSecureContext (node:internal/tls/secure-context:207:17)
    at Object.createSecureContext (node:_tls_common:116:3)
    at Object.<anonymous> (/home/dachrillz/temp/minimal/index.js:11:5)
    at Module._compile (node:internal/modules/cjs/loader:1376:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
    at Module.load (node:internal/modules/cjs/loader:1207:32)
    at Module._load (node:internal/modules/cjs/loader:1023:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12)
    at node:internal/main/run_main_module:28:49 {
  opensslErrorStack: [
    'error:1300006D:engine routines::init failed',
    'error:13000074:engine routines::no such engine',
    'error:13000084:engine routines::dso not found',
    'error:12800067:DSO support routines::could not load the shared library'
  ]
}

To prove that it is not a timing issue i also ran

tls.createSecureContext(config1);

setTimeout(() => {
  tls.createSecureContext(config1);
}, 5000);

Which produces the same error.

I realize that a "normal" use case is not to fiddle with createContext, but to use something like tls.connect instead. Here is an example using that as well.

const configTLS = {
  privateKeyIdentifier:
    "pkcs11:model=YubiKey%20YK5;manufacturer=Yubico%20%28www.yubico.com%29;serial=22484003;token=YubiKey%20PIV%20%2322484003;id=%04;object=Private%20key%20for%20Card%20Authentication;type=private;pin-value=123456",
  privateKeyEngine: "pkcs11",
  rejectUnauthorized: false,
};

const a = tls.connect(443, "google.com", configTLS, () => {
  console.log("connected!");
  a.end(() => {
    console.log("ended");
    tls.connect(443, "google.com", configTLS, () => {
      console.log("connected again!");
      a.end();
    });
  });
});

This produces a similar error:

npm start

> what@1.0.0 start
> PKCS11_MODULE_PATH='/usr/lib/libykcs11.so' node index.js

connected!
ended
node:internal/tls/secure-context:207
        context.setEngineKey(privateKeyIdentifier, privateKeyEngine);
                ^

Error: error:12800067:DSO support routines::could not load the shared library
    at configSecureContext (node:internal/tls/secure-context:207:17)
    at Object.createSecureContext (node:_tls_common:116:3)
    at Object.connect (node:_tls_wrap:1759:48)
    at Array.<anonymous> (/home/dachrillz/temp/minimal/index.js:24:9)
    at callFinishedCallbacks (node:internal/streams/writable:972:25)
    at finish (node:internal/streams/writable:943:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  opensslErrorStack: [
    'error:1300006D:engine routines::init failed',
    'error:13000074:engine routines::no such engine',
    'error:13000084:engine routines::dso not found',
    'error:12800067:DSO support routines::could not load the shared library'
  ]
}

My application that uses mqtt.js (which in turn uses tls.connect) itself works fine as long as the tls connection is not interrupted. Meaning that everything works as expected the first time around a tls connection is created using the pkcs11 device. It is the second time around that Node.js throws the exception.

How often does it reproduce? Is there a required condition?

Every time

What is the expected behavior? Why is that the expected behavior?

We expect Node to be able to create a tls connection.

What do you see instead?

Please see reproduce steps

Additional information

  1. I have tried with different pkcs11 providers, and they seem to produce the same result.
  2. I have not tried other platforms yet (E.g. Windows)

Please let me know if I should try some other configuration.

Metadata

Metadata

Assignees

No one assigned

    Labels

    tlsIssues and PRs related to the tls subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions