1

I am designing a C application using a third-party implementation of the PKCS#11 cryptography API monitoring cryptographic operations of a Hardware Security Module.

The PKCS#11 standard specifies (among other things) basic access control on cryptographic objects the library may be in charge of (keys, certificates, etc.).

To access a private object, my application open a PKCS#11 session (C_OpenSession) and then call the PKCS#11 C_Login function with a login and a password (UTF8 strings). Both of them are then checked by the hardware device. If the (login, password) couple is a valid one, the session is updated to an « authenticated » one and my application can access the private objects.

Note : the private objects are hosted by the harware device and "accessing the private objects" means "being able to use them within the hardware device" (secret and private keys are never exported in my application's virtual address space, and every cryptographic operation is performed by the hardware device).

Thus, the cryptographic material storage seems to be properly addressed ; however, my application has to provide the password to the C_Login function.

Note : the encryption part of my application is not going to be launched by a user ; keyboard input of a password or smart card-based authentication/password decryption can't be used here. Password obfuscation (or plaintext storage...) is not an option either.

I may be wrong (and I hope so) but I think there's no ultimate solution to prevent password leak (any debugger catching the C_Login call will easily retrieve the password from the proper CPU register - or memory location it may points to).

So I'm not looking for a way to prevent this kind of leak (of course, if someone has a solution to this problem - which is a very general one I think (prevent leaks induced by the CPU processing sensitive data) -, I would be happy to read it !).

My intention is to provide a reasonable security level (even if a plaintext version of the password will be alive in my application address space and will be moved in (or referenced by) a CPU register).

For now, in my test environment, the password is hard-coded (as a plaintext argument to be provided to the C_Login function). Because of efficient live debugging prevention being a difficult problem (I only have a pair of hands, some coffee and a GNU compiler), I guess « reason » would be about preventing :

  1. password stealing through static analysis,
  2. password copy from plaintext storage.

Thus, I am thinking of password storage on disk with software-based encryption. My application would have an access to a local encryption key owned by a dedicated user account. This key would be used to encrypt/decrypt a file containing the password (using software cryptography API).

Note : the key would be hosted in a key store (Java Key Store, MSCPI/CNG Key Storage Provider, etc.)

It doesn’t prevent the password to be leaked by the CPU, but at least requires the user to have been authenticated by the OS. Then, any (static) reverse-engineering of my code won’t leak the password and only the authorized user will be able to decrypt it.

Of course, it is just about reporting the problem on the OS users management and authentication abilities. But I'm kind of helpless on this one, I can’t think of anything else.

Maybe someone has an idea on the ways to prevent password leaks (static analysis of assembly code, unauthorized access to host machine) when it has to be programmatically provided as plaintext argument to a function ?

1 Answers1

0

Perhaps some whitebox-crypto product could arrange your binaries so that the PKCS#11 device PIN code is never in one place in memory and so easily accessible for debuggers.

hasa
  • 208
  • 1
  • 4