Open mistial-dev opened 2 years ago
Hi @mistial-dev, yes this has been on the non-allocated TODO list for a while now. The idea of identifying whether a key has been generated or imported makes total sense, it's just how to effectively do it.
Yubikey has it's F9 key, which as you described is comes factory-populated by their own key with an established trust chain. The same is true for the TPM EK's as you've described.
OpenFIPS201 doesn't have that luxury being a self-installed applet, so the remaining options are:
Have individual generated keys self-sign Since the key will most likely be permitted to sign arbitrary host-supplied values after generation, this is out.
Generate the attestation key pair off-card and inject it The entity that generated the attestation certificate in the first place can sign attestation certs now, so this seems out.
Generate a unique per-card attestation key at applet install or similar This seems to be the remaining option, but there needs to be a chain of trust in place here.
What would you think of something like the following?
This is very rough, but doesn't seem too significant to implement and so could be considered.
OpenFIPS201 doesn't have that luxury being a self-installed applet,
That's going to depend on the organization making the cards. As an example, I know of one org that is looking to have a card manufacturer load a bunch of PIV cards with applets for them. The card mfg could easily provision some key to all the cards.
Generate the attestation key pair off-card and inject it The entity that generated the attestation certificate in the first place can sign attestation certs now, so this seems out.
Not necessarily. If a company wants to know "this is one of our cards", then injecting it themselves makes perfect sense. They know it's one of their cards, even if the user (or issuing department) generates new keys.
Ultimately, the organization that issues the attestation certificate does have the capability to either inject it to multiple devices, or to generate certificates for keys not generated on some cryptographic module. For a government, or a company (the general users of this), a key they control is still extremely useful, even if that attestation becomes meaningless to third parties.
If a manufacturer chooses to use this to make OpenFIPS201 cards available, then the cards themselves are only as trustworthy as the manufacturer. The manufacturer could backdoor the applet anyway, which gets you essentially to where things are with YubiKeys. They take reasonable care, and if you rely upon that signature, you are ultimately trusting them.
The same is true with most cryptographic modules, come to think of it. The rather expensive HSMs I use for work still ultimately rely on me trusting the manufacturer to not backdoor them, and to not issue bad firmware for them. Even with an Open Source HSM, I'm trusting that's the applet that's loaded if I didn't compile and load it myself.
Generate a unique per-card attestation key at applet install or similar This seems to be the remaining option, but there needs to be a chain of trust in place here.
That's one of the things we're looking at doing. The practical reality is that it slows down the card issuance process tremendously, but it increases security if the module itself is compromised. With YubiKeys, their loading of one attestation key to multiple devices means that a compromised device potentially can be used to fake other devices. That's less of a risk with per-device attestation keys, but that also potentially provides a mechanism to identify the user (which is why FIDO2 requires the same attestation cert to be used on 100,000+ devices).
As for your workflow:
Add an Options.attestationKey configuration param or something similar to indicate which key is used for attestation (0 for disabled)
Making it disableable makes sense.
During pre-perso, you must also define this key and OF201. It would have to have a (newly created) ROLE_ATTEST flag set and would need to be prohibited from having any other role, or the 'importable' attribute set.
What do you mean by "and OF201"?
Having attestation be a defined role is a good thing, as there are quite a few attacks that rely on using keys for the wrong things. I don't think that importation itself is a bad thing, especially when used properly. For example, in my CMS now, I'm using a PKCS11 HSM to generate per-device certificates and keys (in the interest of time). They aren't retained, they are unique, and it's much, much, much faster than trying to generate a keypair on card and have it do a signature operation.
The CMS generates that key, pulls the public value, signs it and possibly decorates the cert with an Attestation OID and writes it to whichever data object it decides is the attestation cert.
The attestation OID serves a couple purposes. One of the important ones is that the card is essentially a CA, so it's a good place to put a nice critical extension to poison pill it for anything other than attestation. If an application doesn't know what an attestation cert is, it shouldn't accept it.
PIVApplet writes its own self-issued CA certificate, which means that if you do an attestation at initialization you can store the public key of the CA, and use it to verify future attestation certs generated by the card.
It doesn't set subjectKeyIdentifier or authorityKeyIdentifier, which is a problem for a CMS (as building the path is difficult), but that's one of the things being changed in my upcoming patch. When the CA is just "PIVApplet Attestation Cert", for every card, with different keys, it's a pain.
With the subject and authority identifiers, it's relatively straightforward for a CMS to just let the cards issue their own certs, store them, and validate any later cert based on the authority key identifier.
In the interest of speed and space, I've made the generation of this key and cert optional. PivApplet just generated it automatically without returning the public key, which made it difficult to use.
My upcoming pull request changes this to empty attestation by default (since it's fairly useless on its own). A CMS can call generate on the F9 slot, and get the public key returned to it. This will be the authority key identifier on any subsequent attestation cert. I'm also placing the card UUID into the issuer CN, to further help in identifying cards and their certificates.
During key generation, OF201 will check if Options.attestationKey is non-zero and if so (and the attestation key is populated), it will generate the attestation cert for the generated key. I guess it does this for itself too?
Why not generate the certificate on demand? PivApplet (and yubikeys) just keep track of whether or not a key is generated on card, and refuse to issue attestation certs on imported keys.
This way, normal operation of the token is unaffected.
As for doing it for itself, a self-signed one works if one is looking to use this only within a CMS. There are situations (like Adobe Trust List) where it's better to have this attached to a root of some sort. As such, it is nice to be able to import a signed attestation CA (what goes in the F9 slot on a yubikey).
With YubiKeys, that CA can be a root or an intermediate. The certificate is parsed to get the subject, which gets written into the issuer field on the attestation certificates themselves. They are x509, verifiable with OpenSSL, issued to the public key of the generated key, signed by the F9 key.
When key enumeration is completed (should be next minor release), return a flag to show if each key is imported or generated.
Useful. Attestation makes this more secure, but if done over a secure channel it could be done remotely in a reasonably secure and trustworthy manner.
The user calls a Get Attestation command on a given key id/mechanism pair. If attestation cert is available this is returned.
From a memory/space tradeoff, why not calculate that signature then?
When General Authenticate is called, the key associated with Options.attestationKey could not be used for any purpose. This would be implicit in the enforced roles/attributes, but we might add a double-check here anyway because it's cheap.
Absolutely makes sense.
Hi @mistial-dev, just wanted to let you know I've been on leave but still have this on my list to reply to. Once I'm back on board (~9th May) so I'll try to address any questions then, and meanwhile we will discuss adding this internally, get more specific on the design and feed it back to this comment chain before going ahead, but your feedback and suggestions have been really useful, so thanks!
Looking at things from a CMS standpoint, attestation certificates in some form or another help provide assurance that keys were generated on-module. As an example of such a process from the windows server documentation:
YubiKey PIV support does something similar by burning in a key and certificate that is used to essentially issue X509 certs for public keys on the YubiKey, with metadata about the slot (PIN and Touch policy) present. This allows card management software to identify the serial number of the token, verify that it was generated within the cryptographic boundary, ensure the appropriate PIN policy is set, and that it is in the appropriate DO (which matters in terms of Windows assumptions with the built-in PIV driver).
There are three specific use cases in which attestation is extremely useful for card issuers.
The first is for organizations that wish to buy or make a batch of cards. These cards would be initialized with an attestation key (exactly like YubiKeys are now), and could be provided to users later for remote personalization. This can greatly aid in legal non-repudiation, as the keys are generated and the certificate issued only after the user has taken physical possession of the card and set the PIN.
The second use is for easy re-keying. Given the industry trends towards shorter certificate and key lifetimes (something the CA/Browser forum enforces for web browsers), users will need to re-key and re-issue certificates more often. Doing so without attestation, however, increases the chance of a user providing a CSR for keys not protected within a hardware cryptographic boundary.
The third use is to assist with compliance requirements. For example, Adobe Trust List (PDF signing) requires:
SSL.com uses YubiKey attestation to allow them to meet these requirements on user-possessed tokens, keyed and re-keyed in the field.
Would some sort of attestation mechanism make sense for OpenFIPS201?