PeculiarVentures / node-webcrypto-p11

A WebCrypto Polyfill for Node in typescript built on PKCS#11.
MIT License
44 stars 15 forks source link

Support `CKA_ALWAYS_AUTHENTICATE` #72

Closed microshine closed 2 years ago

microshine commented 2 years ago

node-webcrypto-p11 doesn't support CKA_ALWAYS_AUTHENTICATE attribute.

PKCS#11 doc

Attribute Data type Meaning
CKA_ALWAYS_AUTHENTICATE CK_BBOOL If CK_TRUE, the user has to supply the PIN for each use (sign or decrypt) with the key. Default is CK_FALSE.

The CKA_ALWAYS_AUTHENTICATE attribute can be used to force re-authentication (i.e. force the user to provide a PIN) for each use of a private key. "Use" in this case means a cryptographic operation such as sign or decrypt. This attribute may only be set to CK_TRUE when CKA_PRIVATE is also CK_TRUE.

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). In this call, the actual user type is implicitly given by the usage requirements of the active key. If C_Login returns CKR_OK the user was successfully authenticated and this sets the active key in an authenticated state that lasts until the cryptographic operation has successfully or unsuccessfully been completed (e.g. by C_Sign, C_SignFinal,..). A return value CKR_PIN_INCORRECT from C_Login means that the user was denied permission to use the key and continuing the cryptographic operation will result in a behavior as if C_Login had not been called. In both of these cases the session state will remain the same, however repeated failed re-authentication attempts may cause the PIN to be locked. C_Login returns in this case CKR_PIN_LOCKED and this also logs the user out from the token. Failing or omitting to re-authenticate when CKA_ALWAYS_AUTHENTICATE is set to CK_TRUE will result in CKR_USER_NOT_LOGGED_IN to be returned from calls using the key. C_Login will return CKR_OPERATION_NOT_INITIALIZED, but the active cryptographic operation will not be affected, if an attempt is made to re-authenticate when CKA_ALWAYS_AUTHENTICATE is set to CK_FALSE.

More info

PKCS#11 API

C_SignInit(session, key)
if (key.CKA_ALWAYS_AUTHENTICATE == true)
  C_Login(PIN, CKU_CONTEXT_SPECIFIC)
C_SignUpdate(...)
C_SignFinal(...)

graphene API

const signer = session.createSign(mechanism, key);
if (key.alwaysAuthenticate == true) {
  session.login(pin, graphene.UserType.CONTEXT_SPECIFIC);
}
const signature = signer.once(data);

WebCrypto API

Interface

type AlwaysAuthenticateHandleResult = string | null;
type AlwaysAuthenticateHandle = (key: CryptoKey, crypto: Crypto) => string | Promise<AlwaysAuthenticateHandleResult>

interface Crypto {
  onAlwaysAuthenticate?: AlwaysAuthenticateHandle
}

Usage

const crypto = new Crypto({
  library,
  slot: 0,
  pin,
});

// Add handler for alwaysAuthenticate
crypto.onAlwaysAuthenticate = (key, crypto) => {
  return pin;
}

const signature = await crypto.subtle.sign(alg, key, data);
microshine commented 2 years ago

I've created the PR #73

microshine commented 2 years ago

Solved in v2.6.0