veracrypt / VeraCrypt

Disk encryption with strong security based on TrueCrypt
https://www.veracrypt.fr
Other
6.71k stars 936 forks source link

OpenPGP: select different PDO slot #689

Open szszszsz opened 3 years ago

szszszsz commented 3 years ago

As a user I would like to have an option to select the PDO slot on my OpenPGP smart card, while saving the keyfile. Instead of the PDO1 I would like to use PDO3 or PDO4, which require User/Admin PIN (respectively) for the read operation. Changing defaults to PDO3 (instead of PDO1) for OpenPGP smart card would also work.

Right now Veracrypt saves keyfiles on the OpenPGP smart card in PDO1, where it is available to read without providing the PIN.

alt3r-3go commented 3 years ago

Hey @szszszsz, I could look into this one as indeed the request makes sense.

I however don't have a HW token (and don't use VC with one), would you be able to recommend any SW-based setup with e.g. some emulator, so that I could test this out properly? I guess you may have used something like that when working on Nitrokeys ;)

jans23 commented 3 years ago

@alt3r-3go We are glad to provide you the necessary Nitrokeys for free. Please send us your shipping address to info@ (contact).

alt3r-3go commented 3 years ago

Thanks @jans23, that would be quite useful, thank you. I also wanted to take a deeper look and maybe contribute to Nitrokeys from the dev standpoint for a while now, this could be a great excuse to finally find the time to do that :) I'll contact you over the email soon to discuss what can be arranged here - however please also see below, as it may not be strictly necessary for fulfilling this particular request.

On this particular one, I've conducted some initial research (so the below is preliminary and I'll investigate more) and looks like it may not be possible to change this at the VC level.

This particular limitation of using the OpenPGP PDO 0101 when going via OpenSC's PKCS#11 (which is I guess what @szszszsz is using as the default recommendation for Nitrokeys) is hardcoded into OpenSC due to specific technical limitation of exposing PIN-protected DOs: https://github.com/OpenSC/OpenSC/blob/master/src/pkcs15init/pkcs15-openpgp.c#L451-L457 (this functionality in general was added at some point to provide TC/VC support in OpenSC).

From its end, VC just uses PKCS#11's C_CreateObject() (https://github.com/veracrypt/VeraCrypt/blob/master/src/Common/SecurityToken.cpp#L145) and there doesn't seem to be any PKCS#11 API for specifying the OpenPGP's PDO directly (which generally makes sense as these are different APIs/abstractions of course).

So at this level of elaboration, it looks like it would rather be an OpenSC change to somehow overcome that hardcoding and expose other DOs, or a noticeable change of the usage model at the VC end, to actually start using smartcard as such, and not as a glorified USB flash drive. There were arguments about that - which I generally share - during the review of that OpenSC PR, indicating that this way of storing the keyfile may be relatively meaningless, especially on a PIN-less DO.

alt3r-3go commented 3 years ago

@idrassi, FWIW, please feel free to assign this one to me as I'm willing to drive it to conclusion (whatever it is - we'll see).

alt3r-3go commented 3 years ago

I'm looking further into this, to see how this could be implemented with minimal changes, given the limitations: VeraCrypt's established keyfile feature expectations (VC needs to have access to keyfile contents to produce the key and there's even a "threshold" functionality where keyfile may be split into pieces!) and OpenSC's current - "hardcoded" to a noticeable degree - implementation.

I'm currently thinking of maybe leaving the PDO 0101/OpenSC alone, but adding a token-based encryption/decryption operation on top - i.e. VC would ask the token to encrypt/decrypt the keyfile when storing/reading it to/from the PDO. Assuming the operation requires authentication (haven't checked the details yet, but that's key usage, so should be authenticated somehow), that would leave OpenSC as-is, preserve the keyfile functionality and increase the security of keyfile storage (encrypted and access is authenticated) at the cost of creating a dependency on a token-internal key, which makes sense for this use case. Stay tuned (and feel free to comment if you have any better ideas or don't like this one) :)

Fun fact I've noticed during further code analysis: OpenSC actually does require PW1 when reading the PDO, but as it's implemented in the PKCS#11/15 emulation layer on top of the underlying OpenPGP functionality, when one uses OpenPGP interface directly, that is of course not happening and PDO 0101 requires no PIN for reading. This difference can be observed via OpenSC's own pkcs11-tool and openpgp-tool. The former requires login: pkcs11-tool.exe --read-object --type data --label PrivDO1 --login to display the contents, the latter - doesn't: openpgp-tool.exe --do 1.

And just for reference, here are the relevant OpenSC PRs where TC/VC-related PDO functionality was added (thank you @hongquan!):

  1. https://github.com/OpenSC/OpenSC/pull/150 (initial version, was abandoned)
  2. https://github.com/OpenSC/OpenSC/pull/303 (this one added Gnuk support and accidentally included most of the PDO functionality)
  3. https://github.com/OpenSC/OpenSC/pull/817 (this one was created to document the PDO functionality inclusion properly + add missing minor commits)
alt3r-3go commented 3 years ago

Just to note - I've not forgotten about this one, it's just that the solution given the limitations is not as elegant as I'd like it to be + I have only part of the weekend(s) to work on this right now, slowing it down. I'm still determined to drive it to the conclusion though.

jans23 commented 3 years ago

I'm currently thinking of maybe leaving the PDO 0101/OpenSC alone, but adding a token-based encryption/decryption operation on top - i.e. VC would ask the token to encrypt/decrypt the keyfile when storing/reading it to/from the PDO.

This is how tokens and smart cards are usually used. It gives the best security and least dependency on available PDOs for example.

If the keyfile is encrypted with the key stored in the token, I suggest to not store the encrypted keyfile in the PDO but in VC's volume header instead.

Assuming the operation requires authentication

Yes, decryption operations require authentication through PIN.

idrassi commented 3 years ago

If the keyfile is encrypted with the key stored in the token, I suggest to not store the encrypted keyfile in the PDO but in VC's volume header instead.

Currently VC volume header size is limited to 512 bytes and it is already mostly full with needed parameters so we can't use it to store an encrypted key file. Also keyfiles can have a large size. Of course, we can limit their size for smart card integration to 128 bytes (same as maximum password length) but depending on the size of key used, their encrypted form can be large (for example 512 bytes for 4096-bits RSA key if it is encrypted directly using CKM_RSA_PKCS or CKM_RSA_PKCS_OAEP).

In my opinion, it makes more sens from the security point of view to put the encrypted key file on the smart card than in the volume itself: an attacker that somehow can break the RSA or EC key used for encryption (for example by compromising a backup of the key) will not be able to access the volume since the encrypted keyfile resides on the smart card and it is protected by a PIN.

jans23 commented 3 years ago

From the security point of view I don't see a practical benefit of storing the encrypted key file in the smart card. Smart cards and HSMs are used for all sorts of encryption and signing applications and their approach to only store private keys has proven to be working well and secure. However, if volume header doesn't have sufficient space, that's a strong argument for doing so nevertheless.

alt3r-3go commented 3 years ago

Looking further into this, I found out that no one (tokens and OpenSC as an interface) implements public key encryption. AFAIU that's based on the assumption that those who need to do that just export the public key from the token and do encryption "outside". Only private-key operations are supported on the device and that means for PKE we'd need to implement this in VeraCrypt itself.

That IMO makes no sense in the current approach with no crypto library being used and only necessary pieces being added to the source tree when necessary. Addint PKE to VC would require a lot of that and if that's a desirable direction at all, I'd say a prerequisite would be to switch to using some crypto library first (I think a BSI report published recently suggested that as well).

An additional, smaller and more arguable thing (depending on specific attack scenarios I haven't thought through) is that OpenPGP (at least 3.3 I'm looking at) doesn't seem to support OAEP, only the PKCS#1_v1.5, which is a big no-no these days due to padding oracle attacks.

Now, while Nitrokey Pro (unlike Start) does support storing an AES key and encryption/decryption using it, it's (1) not supported in OpenSC AFAICS and (2) seems to support only the CBC mode (AFAIU it implements what the OpenPGP spec says) - and that's again not the best choice for key/key material encryption due to no integrity protection and potential padding oracle attacks. And of course that limits the choice of users toonly those tokens that support symmetric keys/ops.

So unless someone has any other ideas, it looks like we're back to square one and the only approach left is to try to see if we can add PDO3/4 support into OpenSC.

alt3r-3go commented 3 years ago

Just as an update, I'm moving on with the DO-based approach, did some testing with OpenSC today and it looks promising - looks like there's at least some possibility to pick the actual DO even via the OpenSC's PKCS#11 interface (by hijacking the Label values and with respective changes at the OpenSC side - so that's a bit sketchy at the moment), but there also seems to be some bug in there, as some of the pkcs11-tool commands don't work properly with DOs 0102-0104 when populated and I'm investigating.

alt3r-3go commented 3 years ago

Just so stale-bot doesn't intervene :) This is still in progress, just not having enough time to work on this more actively.

alt3r-3go commented 3 years ago

It's been a long while, but I still haven't got to that, all my free time is essentially filled up now with something else. This is still on the list though, so there's hope.

alt3r-3go commented 3 years ago

As you can imagine this hasn't moved much since the last update, but I now have a more firm plan to work on this - around the end of September I should have time for this. I plan to move forward with the idea described above, which is, while a bit hacky, hopefully won't be rejected outright by the OpenSC folks, as it still IMO fits their current approach to managing private DOs. We'll see.