PeculiarVentures / pkcs11js

A Node.js implementation of the PKCS#11 2.40 interface
MIT License
111 stars 34 forks source link

C_Login CKR_FUNCTION_NOT_SUPPORTED #57

Open spanmatej opened 4 years ago

spanmatej commented 4 years ago

I am trying to sign a PDF signature using a Gemalto USB Key Smart Card. I am able to find the slot, open session and generally access it, but I am not able to Login with PIN.

Usually you have to enter the PIN during the signing process, for example you select the certificate from the list in Adobe Reader, then choose to sign with it after which you are shown the window to enter the PIN.

C_Login & C_Logout both return CKR_FUNCTION_NOT_SUPPORTED.

Here is some info and the code.

Using pvpkcs11.dll as library (from Fortify app). C_GetInfo image

C_GetSlotInfo image

C_GetTokenInfo (seems to be lacking data) image

While trying to login, I receive the following error: **pkcs11.C_Login(session, 1, 1234);** image

HOWEVER if I comment out the login, the rest of the signing process successfully completes and the verfication of the signature returns as true. Afterwards I attach this signature to an actual PDF document on the server side (C# .NET Core), where it shows as invalid.

const lib = 'pvpkcs11_fortify.dll';
const pkcs11 = new pkcs11js.PKCS11();
pkcs11.load(lib);
pkcs11.C_Initialize();

const slots = pkcs11.C_GetSlotList(true);
const slot = slots[1];

const session = pkcs11.C_OpenSession(slot, pkcs11js.CKF_SERIAL_SESSION);
// pkcs11.C_Login(session, 1, 1234); // GEMALTO UNSUPPORTED?

const publicKeyTemplate = [
  { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PUBLIC_KEY },
  { type: pkcs11js.CKA_TOKEN, value: false },
  { type: pkcs11js.CKA_LABEL, value: 'My RSA Public Key' },
  { type: pkcs11js.CKA_PUBLIC_EXPONENT, value: Buffer.from([1, 0, 1]) },
  { type: pkcs11js.CKA_MODULUS_BITS, value: 2048 },
  { type: pkcs11js.CKA_VERIFY, value: true }
];

const privateKeyTemplate = [
  { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PRIVATE_KEY },
  { type: pkcs11js.CKA_TOKEN, value: false },
  { type: pkcs11js.CKA_LABEL, value: 'My RSA Private Key' },
  { type: pkcs11js.CKA_SIGN, value: true },
];

const keys = pkcs11.C_GenerateKeyPair(session, { mechanism: pkcs11js.CKM_RSA_PKCS_KEY_PAIR_GEN }, publicKeyTemplate, privateKeyTemplate);

pkcs11.C_SignInit(session, { mechanism: pkcs11js.CKM_SHA256_RSA_PKCS }, keys.privateKey);

const pdfBinary = decodeFromBase64(bytesToSign); // data to sign

pkcs11.C_SignUpdate(session, new Buffer(pdfBinary));

const signature = pkcs11.C_SignFinal(session, new Buffer(256));

pkcs11.C_VerifyInit(session, { mechanism: pkcs11js.CKM_SHA256_RSA_PKCS }, keys.publicKey);

pkcs11.C_VerifyUpdate(session, new Buffer(pdfBinary));

const verify = pkcs11.C_VerifyFinal(session, signature);

// pkcs11.C_Logout(session); // GEMALTO UNSUPPORTED?
pkcs11.C_CloseSession(session);
rmhrisk commented 4 years ago

Within fortify can you send us the log of whe you use the fortify app to generate a CSR on this card?

spanmatej commented 4 years ago

I suppose I didn't provide enough context as to how I am using pkcs11js exactly..

This code lives inside an Electron Angular app. I am not directly using Fortify, only it's .dll to provide the layer for communication with smart cards.

I haven't found much information online on how exactly you get to these libraries, so that's why I used Fortify's dll, as it's the most relevant in my use case.

I would love to get some more insights in how exactly I should go about this.

rmhrisk commented 4 years ago

The error you are having suggests there is something your smart card isn’t supporting related to login.

It is easier for us to troubleshoot this if you use Fortify, enable logging, perform the CSR generation, send us a log.

spanmatej commented 4 years ago

Thank you for the suggestion. Will do that as soon as possible and report back to you.

spanmatej commented 4 years ago

While starting Fortify, I am presented with the notice that the smart card is not supported and if I'd like to request support.

Reader name: Gemalto USB Key Smart Card Reader 0 ATR: 3B7D96000080318065B0830201F383009000

{
   "cards": [{
    "atr": "3B7D96000080318065B0830201F383009000",
    "name": "Token name",
    "driver": "B1B9E460251886FDB4207F3D1D243AB05A6AF3D6"
   }],
   "drivers": [{
    "id": "B1B9E460251886FDB4207F3D1D243AB05A6AF3D6",
    "name": "Driver name",
    "file": {
        "windows": "path/to/pkcs11.dll",
        "osx": "path/to/pkcs11.dylib"
    }
   }]
}

Smart card ATR parsing 3B7D96000080318065B0830201F383009000

It is the same token as in the following issue: https://github.com/PeculiarVentures/fortify/issues/120

Nexus Personal is usually used with the smart card. image

rmhrisk commented 4 years ago

The card itself appears to be aGemalto IDClassic 340

Is that correct? Or is this some other card that’s been provisioned onto this card?

What PKCS11 library do you use with this card?

Where on your system do you find that PKCS11 library?

Does this card have a certificate on it already and read only (most National ID cards) or is it blank that you can arbitrary things to?

spanmatej commented 4 years ago

I do not know the exact name at this time but I would presume so. There is no information about it in the Nexus client nor the SafeNet Authorization client, which usually shows all the relevant card information. It's over 3 years old and searching through the internet I can see that it probably is the IDClassic one.

I am not using a specific library myself. What I am using is the Nexus Personal client which allows me to enter the PIN while signing data.

The card does have a certificate on it and is regularly used to access certificate-restricted government /bank sites and to manually sign PDF documents.

These are the .dll files of the program, also listed as "components" in the program itself. image image image image

microshine commented 4 years ago

You can add your token to Fortify config file ~/.fortify/config.json. Please don't forget to restart your Fortify application.

Example

{
  "locale": "en",
  "logging": true,
  "cards": [
    {
      "atr": "3b8b015275746f6b656e20445320c1",
      "libraries": [
        "/usr/local/lib/librtpkcs11ecp1.dylib"
      ],
      "name": "Rutoken",
      "readOnly": true
    }
  ]
}
rmhrisk commented 4 years ago

This suggests (https://doc.nexusgroup.com/display/PUB/Personal+Desktop+Client+overview) that the nexus client includes a mini driver and a PKCS#11.

As per @microshine's comment if you can specify which one to use in the fortify config file it should work. Once you confirm we can add it to the global config.

rmhrisk commented 4 years ago

It seems maybe this smart card is related to Swedish BankID (www.bankid.com)?

According to this The software client includes both a CSP and a PKCS11 module that is, however, not used nor formally supported.

I've asked a knowlegable friend for more information here : https://twitter.com/rmhrisk/status/1202905241177542656?s=20

spanmatej commented 4 years ago

The smart card is issued by Halcom (http://www.halcom.si/en/) a Slovenian provider of digital certification software/products. I am not aware of any connection between them and the Swedish BankID.

As suggested, I found the library which Nexus Personal is using (personal64.dll) and am trying it out at the moment. I will shorty report if there is any more information available through it.

rmhrisk commented 4 years ago

Actually I may have found it; according to this it is personal.dll.

If so I think the configuration you need to test would be:

{
    "cards": [{
        "atr": "3B7D96000080318065B0830201F383009000",
        "name": "Gemalto IDClassic 340",
        "driver": "0da8b1af9bd641a8955316eebf393b4d",
        "readOnly": true
    }],
    "drivers": [{
        "id": "71789068c5ff4891aeeaf7fb9608a22f",
        "name": "Nexus Personal,
        "file": {
            "windows": {
                "x86": "%PROGRAMFILES(X86)/Personal/bin/personal.dll"
                "x64": "%PROGRAMFILES/Personal/bin/personal64.dll"
            }
        }
    }]
}
rmhrisk commented 4 years ago

Please try the above configuration and see if it works.

spanmatej commented 4 years ago

I have tested the library with pkcs11js and I have successfully logged in with the correct PIN. The token info is now populated and shows the correct manufacturer and serial number, which means this is the correct one to be used.

I am now presented with the error CKR_GENERAL_ERROR at crypto_final:637 on line: const signature = pkcs11.C_SignFinal(session, new Buffer(256));

Any ideas as to how to check what causes this?

rmhrisk commented 4 years ago

We will need the fortify log associated with that transaction.

spanmatej commented 4 years ago

Do you mean generating a CSR?

I don't know how I would do the signing process with Fortify or how it is connected with it in any way, as I am using pkcs11js inside an Angular Electron application.

Please advise on how to get some more information out of the error, as that is all I get: Error: CKR_GENERAL_ERROR:5 at Error (:4200/native) crypto_final:637

Do you know of any tool I could use to check if the signing process works manually (Windows)?

microshine commented 4 years ago

image You can enable logging and get a detailed exception message

spanmatej commented 4 years ago

I am aware of the process for enabling and checking the log and I have checked it after the signing process but nothing is logged inside it.

And how would Fortify know of any signing process outside the app itself? I need some more explanation on that.

Note: I am using pkcs11js by itself, stand-alone inside an Electron app, not connected to Fortify in any way.

microshine commented 4 years ago

I am using pkcs11js inside an Angular Electron application

Can you share a part of your source code where you are using pkcs11js

It's interesting to see which mechanisms you are using for signing

spanmatej commented 4 years ago

Here is the updated code from my initial issue comment:

const lib = 'personal64.dll';
const pkcs11 = new pkcs11js.PKCS11();
pkcs11.load(lib);
pkcs11.C_Initialize();

const slots = pkcs11.C_GetSlotList(true);
const slot = slots[1];

const session = pkcs11.C_OpenSession(slot, pkcs11js.CKF_SERIAL_SESSION);
pkcs11.C_Login(session, 1, '1234');

const publicKeyTemplate = [
  { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PUBLIC_KEY },
  { type: pkcs11js.CKA_TOKEN, value: false },
  { type: pkcs11js.CKA_LABEL, value: 'My RSA Public Key' },
  { type: pkcs11js.CKA_PUBLIC_EXPONENT, value: Buffer.from([1, 0, 1]) },
  { type: pkcs11js.CKA_MODULUS_BITS, value: 2048 },
  { type: pkcs11js.CKA_VERIFY, value: true }
];

const privateKeyTemplate = [
  { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PRIVATE_KEY },
  { type: pkcs11js.CKA_TOKEN, value: false },
  { type: pkcs11js.CKA_LABEL, value: 'My RSA Private Key' },
  { type: pkcs11js.CKA_SIGN, value: true },
];

const keys = pkcs11.C_GenerateKeyPair(session, { mechanism: pkcs11js.CKM_RSA_PKCS_KEY_PAIR_GEN }, publicKeyTemplate, privateKeyTemplate);

pkcs11.C_SignInit(session, { mechanism: pkcs11js.CKM_SHA256_RSA_PKCS }, keys.privateKey);

const pdfBinary = decodeFromBase64(bytesToSign); // data to sign

pkcs11.C_SignUpdate(session, Buffer.from(pdfBinary));

const signature = pkcs11.C_SignFinal(session, Buffer.allocUnsafe(256));

pkcs11.C_VerifyInit(session, { mechanism: pkcs11js.CKM_SHA256_RSA_PKCS }, keys.publicKey);

pkcs11.C_VerifyUpdate(session, Buffer.from(pdfBinary));

const verify = pkcs11.C_VerifyFinal(session, signature);

pkcs11.C_Logout(session);
pkcs11.C_CloseSession(session);
microshine commented 4 years ago

try to increase buffer for a signature object to 1024

spanmatej commented 4 years ago

try to increase buffer for a signature object to 1024

Did so, no effect, the same error persists..

microshine commented 4 years ago

this is strange

  1. PKCS#11 libraries support own loggers. You can try to enable it and get additional information about that error

  2. You can try to use another mechanism CKM_RSA_PKCS1 (if your token supports it) 2.1 Compute hash from data you want to sign 2.2 Compute signature from hash value

microshine commented 4 years ago

@spanmatej Please try node-webcrypto-p11 module.

const { Crypto } = require("node-webcrypto-p11");

async function main() {
  const crypto = new Crypto({
    library: "personal64.dll",
    slot: 1,
    pin: "1234",
  });

  const alg = {
    name: "RSASSA-PKCS1-v1_5",
    hash: "SHA-256",
    publicExponent: new Uint8Array([1, 0, 1]),
    modulusLength: 2048,
  }

  const keys = await crypto.subtle.generateKey(alg, false, ["sign", "verify"])

  const data = Buffer.from("some message to be signed");
  const signature = await crypto.subtle.sign(alg, keys.privateKey, data);
  const ok = await crypto.subtle.verify(alg, keys.publicKey, signature, data);

  console.log("Signature:", ok);
}

main().catch((e) => console.error(e));
spanmatej commented 4 years ago

@microshine I'm sorry for the late response.

Error still persists, even though now instead of pointing to crypto_final, it points to crypto_update.

const signature = await crypto.subtle.sign(alg, keys.privateKey, data);

Error: Uncaught (in promise): Error: CKR_GENERAL_ERROR:5
    at Error (native) crypto_update:592
rmhrisk commented 4 years ago

I am aware of the process for enabling and checking the log and I have checked it after the signing process but nothing is logged inside it.

And how would Fortify know of any signing process outside the app itself? I need some more explanation on that.

Note: I am using pkcs11js by itself, stand-alone inside an Electron app, not connected to Fortify in any way.

Can you, as requested earlier, add support for your smart card to fortify with the above details, use fortify to create a CSR, and send the log.

It is easier for us to troubleshoot this if you use Fortify, enable logging, perform > the CSR generation, send us a log.

This may tell us something new.

Alternatively maybe you can contact your middleware provider for examples of how to perform a working transaction with their middleware.

Each P11 unfortunately behaves a little different, some more than others. This is made worse by the middleware returning awesome errors like GENERAL ERROR. Some offer additional logging that can be enabled to see what it was doing when the error was encountered which can help tease out why the middleware is not happy.

microshine commented 4 years ago

@spanmatej What about node-webcrypto-p11 application. Does it throw the same exception?

microshine commented 4 years ago

I found some information about personal64.dll logging

https://blog.goranrakic.com/uploads/pkcs11_putanje.pdf

Name Windows 32bit Windows 64bit
Nexus Personal C:\Program Files (x86)\Personal\bin\personal.dll C:\Program Files (x86)\Personal\bin64\personal64.dll

https://doc.nexusgroup.com/display/PUB/Personal+Desktop+Client+user%27s+guide

Nexus desktop client

Logging is enabled by default.

To disable logging:

  1. Edit personal.cfg.
  2. Set Enabled to 0 under section Diagnostics.

The files are located at:

On Windows: %APPDATA%\Personal\log
spanmatej commented 4 years ago

@microshine My previous comment is from using the node-webcrypto-p11 module. It also produces that error.

Thank you for finding that! I will try enabling the logging and get back to you with more info.

@rmhrisk I added the suggested data inside the config file, done the CSR generation and this is the log.

{"message":"Application started at Sat Dec 07 2019 15:49:14 GMT+0100 (Central European Standard Time)","level":"info"}
{"message":"OS win32 x64 ","level":"info"}
{"message":"Fortify v1.0.20","level":"info"}
{"message":"System locale is 'en-US'","level":"info"}
{"message":"Locale: Set language to 'en'","level":"info"}
{"message":"Fortify: Create window index","level":"info"}
{"message":"Update: Check for new update","level":"info"}
{"message":"Update: New version wasn't found","level":"info"}
{"message":"SSL certificate is loaded","level":"info"}
{"message":"Comparing current version of card.json file with remote","level":"info"}
{"message":"card.json has the latest version","level":"info"}
{"message":"Server: Started at 127.0.0.1:31337","level":"info"}
{"message":"Provider: Add crypto 'Windows CryptoAPI' 9f7dab1bb0d6c10da015c3dd4aa20393548bac2b","level":"info"}
{"message":"Provider:AddCrypto: PKCS#11 'C:\\Program Files\\Fortify\\pvpkcs11.dll' 'C:\\Program Files\\Fortify\\pvpkcs11.dll'","level":"info"}
{"message":"Provider:Opened","level":"info"}
{"message":"PCSCWatcher: New reader detected AKS ifdh 0","level":"info"}
{"message":"PCSCWatcher: New reader detected AKS ifdh 1","level":"info"}
{"message":"PCSCWatcher: New reader detected AKS VR 0","level":"info"}
{"message":"PCSCWatcher: New reader detected Gemalto USB Key Smart Card Reader 0","level":"info"}
{"message":"PCSCWatcher: New reader detected Rainbow Technologies iKeyVirtualReader 0","level":"info"}
{"message":"PCSCWatcher: New reader detected Rainbow Technologies iKeyVirtualReader 1","level":"info"}
{"message":"PCSCWatcher: New reader detected AKS ifdh 0","level":"info"}
{"message":"PCSCWatcher: New reader detected AKS ifdh 1","level":"info"}
{"message":"PCSCWatcher: New reader detected AKS VR 0","level":"info"}
{"message":"PCSCWatcher: New reader detected Gemalto USB Key Smart Card Reader 0","level":"info"}
{"message":"PCSCWatcher: New reader detected Rainbow Technologies iKeyVirtualReader 0","level":"info"}
{"message":"PCSCWatcher: New reader detected Rainbow Technologies iKeyVirtualReader 1","level":"info"}
{"message":"PCSCWatcher:Insert reader:'Gemalto USB Key Smart Card Reader 0' ATR:3b7d96000080318065b0830201f383009000","level":"info"}
{"message":"PCSCWatcher:Insert reader:'Gemalto USB Key Smart Card Reader 0' ATR:3b7d96000080318065b0830201f383009000","level":"info"}
{"message":"TypeError: customCard.libraries is not iterable\n    at CardWatcher.getCard (C:\\Program Files\\Fortify\\resources\\app.asar\\node_modules\\@webcrypto-local\\server\\build\\index.js:938:43)\n    at PCSCWatcher.<anonymous> (C:\\Program Files\\Fortify\\resources\\app.asar\\node_modules\\@webcrypto-local\\server\\build\\index.js:854:41)\n    at PCSCWatcher.emit (events.js:194:13)\n    at Timeout._onTimeout (C:\\Program Files\\Fortify\\resources\\app.asar\\node_modules\\@webcrypto-local\\server\\build\\index.js:798:38)\n    at listOnTimeout (internal/timers.js:535:17)\n    at processTimers (internal/timers.js:479:7)","level":"error"}
{"message":"TypeError: customCard.libraries is not iterable\n    at CardWatcher.getCard (C:\\Program Files\\Fortify\\resources\\app.asar\\node_modules\\@webcrypto-local\\server\\build\\index.js:938:43)\n    at PCSCWatcher.<anonymous> (C:\\Program Files\\Fortify\\resources\\app.asar\\node_modules\\@webcrypto-local\\server\\build\\index.js:854:41)\n    at PCSCWatcher.emit (events.js:194:13)\n    at Timeout._onTimeout (C:\\Program Files\\Fortify\\resources\\app.asar\\node_modules\\@webcrypto-local\\server\\build\\index.js:798:38)\n    at listOnTimeout (internal/timers.js:535:17)\n    at processTimers (internal/timers.js:479:7)","level":"error"}
{"message":"Server: New session connect https://tools.fortifyapp.com","level":"info"}
{"message":"Server: Push session to stack","level":"info"}
{"message":"Server: Cannot parse MessageSignedProtocol","level":"info"}
{"message":"Server: Initialize secure session origin:https://tools.fortifyapp.com id:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 authorized:true","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 server/isLoggedIn","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider/action/info","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider/action/getCrypto","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/isLoggedIn","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider/action/getCrypto","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/isLoggedIn","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/keyStorage/keys","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/keys","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/getItem","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/getItem","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/getItem","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/getItem","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/getItem","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/getItem","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/getItem","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/getItem","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/export","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/export","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/export","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/export","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/export","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/export","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/export","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/export","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider/action/getCrypto","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/subtle/generateKey","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/subtle/exportKey","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/subtle/sign","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/import","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/setItem","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/keyStorage/setItem","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/keyStorage/setItem","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/getItem","level":"info"}
{"message":"Server: session:94ce20c1f25f17967fead981d90d745a6e826cf0a9a14d7b9b3e327708196927 provider:9f7dab1bb0d6c10da015c3dd4aa20393548bac2b crypto/certificateStorage/export","level":"info"}
spanmatej commented 4 years ago

@microshine The logging/diagnostics was actually already enabled and the log file was present.

As there is no functional difference between node-webcrypto-p11 and pkcs11js, except for it adding an additional layer, I'm going forward with pkcs11js at this moment, so all logging is relevant to that code.

I've checked the log and I can't find anything relevant myself, except for this message (logged after SignFinal starts): 2019-12-07 16:11:29 [9584:5680] CEnginePSCBaseNoHash<64>::CreateSignature - No pin object found.

Would this mean that I would need to provide the PIN again for the signing process, even though the login was a success? Is there any case with such a procedure?

pkcs11.log

microshine commented 4 years ago

Have you tried to use another hash mechanism?

Try SHA-1

spanmatej commented 4 years ago

Have you tried to use another hash mechanism?

Try SHA-1

@microshine Unfortunately, the same thing happens. pkcs11.log

microshine commented 4 years ago

Would this mean that I would need to provide the PIN again for the signing process, even though the login was a success? Is there any case with such a procedure?

@spanmatej Please try to get CKA_ALWAYS_AUTHENTICATE attribute from your private key

If CK_TRUE, the user has to supply the PIN for each use (sign or decrypt) with the key. Default is CK_FALSE.
microshine commented 4 years ago
Re-authentication occurs by calling C_Login with userType set to CKU_CONTEXT_SPECIFIC
immediately after a cryptographic operation using the key has been initiated (e.g. after C_SignInit).
spanmatej commented 4 years ago

@microshine I am not sure how to get the CKA_ALWAYS_AUTHENTICATE attribute exactly. I got it once before but I switched between graphene, node-webcrypto, pkcs11js so many times that I forgot and I'm lost..

pkcs11js.CKA_ALWAYS_AUTHENTICATE returns value 514 which doesn't seem right as that is probably just it's assigned value.

I'd like to note that I messed up in my code at opening the session, instead of (suggested in documentation): pkcs11.C_OpenSession(slot, pkcs11js.CKF_RW_SESSION | pkcs11js.CKF_SERIAL_SESSION); I had the following for whatever reason: pkcs11.C_OpenSession(slot, pkcs11js.CKF_SERIAL_SESSION);

Without knowing the value of CKA_ALWAYS_AUTHENTICATE, I went ahead and did as suggested, calling login immediately after SignInit with CKU_CONTEXT_SPECIFIC user: pkcs11.C_Login(session, pkcs11js.CKU_CONTEXT_SPECIFIC, '1234');

That causes: CKR_USER_ANOTHER_ALREADY_LOGGED_IN

I'm sorry for the dumb questions at times.. I'm doing my best to get a deeper understanding of all this and it's a lot to take in. I really do appreciate all the help.

microshine commented 4 years ago

I'll create a script. ~10 minutes

microshine commented 4 years ago

You need update lib, pin and slotIndex values

const pkcs11js = require("pkcs11js");

const lib = '/usr/local/Cellar/softhsm/2.5.0/lib/softhsm/libsofthsm2.so';
const pin = '12345';
const slotIndex = 0;

const pkcs11 = new pkcs11js.PKCS11();
pkcs11.load(lib);
pkcs11.C_Initialize();

const slots = pkcs11.C_GetSlotList(true);
const slot = slots[slotIndex];

const session = pkcs11.C_OpenSession(slot, pkcs11js.CKF_SERIAL_SESSION);
pkcs11.C_Login(session, pkcs11js.CKU_USER, pin); // GEMALTO UNSUPPORTED?

const publicKeyTemplate = [
  { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PUBLIC_KEY },
  { type: pkcs11js.CKA_TOKEN, value: false },
  { type: pkcs11js.CKA_LABEL, value: 'My RSA Public Key' },
  { type: pkcs11js.CKA_PUBLIC_EXPONENT, value: Buffer.from([1, 0, 1]) },
  { type: pkcs11js.CKA_MODULUS_BITS, value: 2048 },
  { type: pkcs11js.CKA_VERIFY, value: true }
];

const privateKeyTemplate = [
  { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PRIVATE_KEY },
  { type: pkcs11js.CKA_TOKEN, value: false },
  { type: pkcs11js.CKA_LABEL, value: 'My RSA Private Key' },
  { type: pkcs11js.CKA_SIGN, value: true },
];

const keys = pkcs11.C_GenerateKeyPair(session, { mechanism: pkcs11js.CKM_RSA_PKCS_KEY_PAIR_GEN }, publicKeyTemplate, privateKeyTemplate);

pkcs11.C_SignInit(session, { mechanism: pkcs11js.CKM_SHA256_RSA_PKCS }, keys.privateKey);

// Check private key attribute
const alwaysAuthenticate = pkcs11.C_GetAttributeValue(session, keys.privateKey, [{ type: pkcs11js.CKA_ALWAYS_AUTHENTICATE }])[0].value;
if (alwaysAuthenticate.length && alwaysAuthenticate[0]) {
  pkcs11.C_Login(session, pkcs11js.CKU_CONTEXT_SPECIFIC, pin);
}

const pdfBinary = decodeFromBase64(bytesToSign); // data to sign

pkcs11.C_SignUpdate(session, new Buffer(pdfBinary));

const signature = pkcs11.C_SignFinal(session, new Buffer(256));

pkcs11.C_VerifyInit(session, { mechanism: pkcs11js.CKM_SHA256_RSA_PKCS }, keys.publicKey);

pkcs11.C_VerifyUpdate(session, new Buffer(pdfBinary));

const verify = pkcs11.C_VerifyFinal(session, signature);

// pkcs11.C_Logout(session); // GEMALTO UNSUPPORTED?
pkcs11.C_CloseSession(session);
spanmatej commented 4 years ago

CKR_ATTRIBUTE_TYPE_INVALID PKCS11::C_GetAttributeValue:447 at pkcs11.C_GetAttributeValue(session, keys.privateKey, [{ type: pkcs11js.CKA_ALWAYS_AUTHENTICATE }])[0].value;

logged:

2019-12-07 17:43:20 [11008:9564] C_SignInit: hSession = 0x1, Mechanism = 0x40, hKey = 0x2
2019-12-07 17:43:20 [11008:9564] Return 0x0
2019-12-07 17:43:20 [11008:9564] C_GetAttributeValue: hSession = 0x1, hObject = 0x2
2019-12-07 17:43:20 [11008:9564] CProfile::GetAttributeValues() failed, rv = 0x12
2019-12-07 17:43:20 [11008:9564] C_GetAttributeValue: Session get attribute value failed
2019-12-07 17:43:20 [11008:9564] Template[0] type : CKA_ALWAYS_AUTHENTICATE
2019-12-07 17:43:20 [11008:9564]             value: NULL
2019-12-07 17:43:20 [11008:9564] Return 0x12
microshine commented 4 years ago

Please comment this attr getting and call your app again. It must login to session with CKU_CONTEXT_SPECIFIC after C_SignInit

microshine commented 4 years ago

I mean to call pkcs11.C_Login(session, pkcs11js.CKU_CONTEXT_SPECIFIC, pin) without CKA_ALWAYS_AUTHENTICATE getting

spanmatej commented 4 years ago

Yes of course, done just that, commented out the attribute getting lines and left the login immediately after SignInit. image

CKR_SESSION_READ_ONLY_EXISTS:183
    at Error (native) PKCS11::C_Login:372

I previously got that error and figured the session must be opened as read-only..

microshine commented 4 years ago
const session = pkcs11.C_OpenSession(slot, pkcs11js.CKF_RW_SESSION | pkcs11js.CKF_SERIAL_SESSION);
spanmatej commented 4 years ago
const session = pkcs11.C_OpenSession(slot, pkcs11js.CKF_RW_SESSION | pkcs11js.CKF_SERIAL_SESSION);

Changing to that gives

CKR_USER_ANOTHER_ALREADY_LOGGED_IN:260
    at Error (native) PKCS11::C_Login:372
microshine commented 4 years ago

Can we move our chat to Skype? Please contact me via email microshine@mail.ru

spanmatej commented 4 years ago

The issue has been resolved. I will update this comment shortly and describe the solution.

ferikeem commented 4 years ago

@spanmatej Can you elaborate on what solved your issue?