Repository: node
Issue: Can not re-connect TLS when using PKCS #11
Labels: tls

### 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.