makinako / OpenFIPS201

An open source reference card application for NIST FIPS 201-2 / NIST SP800-73-4, targeting Javacard 3.0.4+

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Optional means to limit the crypto operations which can be performed on a key

dmercer-google opened this issue · comments

There is currently no way limit what can be done with a given key. For example: Keys 9A, 9C and 9E can be used to perform ECDH as well as ECDSA. This is why the PIV specs talk about ECDSA only for keys 9A, 9C and 9E whereas ECDH is only talked about for keys 04 and 9D. See Table 7-1 of NIST SP 800-78-4.

In general one should use a key for exactly one thing (e.g. key agreement but not signing or vice versa). There is also an attack there using carefully crafted points during an ECDH can compromise a card based private key. Disallowing these attacks on keys where ECDH is not intended improves the security of the keys. Note: Checking for these points is covered in issue #28

I propose that during the creation of the key objects that there be a bit mask that specifies exactly what can be done with a key. Not specifying the mask would allow the key to be used for anything so as to not break any current functionality. Mask elements might include:

  private static final short USAGE_SIGN          = (short)0b00000001;
  private static final short USAGE_VERIFY        = (short)0b00000010;
  private static final short USAGE_ENCRYPT       = (short)0b00000100;
  private static final short USAGE_DECRYPT       = (short)0b00001000;
  private static final short USAGE_KEY_AGREEMENT = (short)0b00010000;
  private static final short USAGE_ALL           = (short)0b11111111;

When a EC key is generated on the card, The EC private key will have to be used to sign a certificate request, even if it is for the 9D key. This actually works with real PIV cards. The certificate is then expected to have the appropriate keyUsage bits set by the CA. So the usage is actually not controlled by the card, but by the CA and PKI applications using the keyUsage bits in the certificates.

The OpenSC PIV driver (for non gov cards i.e. CHUID FASC-N start with 9999 or no FASC-N or CHUID) will look at the certificate keyUsage bits, to assist the application and card. For Yubico and other PIV-like cards allow the user to create their own keys and certificates and so the Retired Certificates for Key Management (actually any certificate/key) can be used for any purpose.

@dengert: The PIV specs do not talk about CSRs. While using a CSR signed by the requestors private is a good idea it is not mandated and certificates can be minted using just a public key. The security of doing so is an issue for the user of OpenFIPS201 to assess.

If signed CSRs are needed the on card key usage restrictions I am proposing could be waved for an admin session.

As for respecting key usage bits in the certificate: Well behaved systems will respect these bits, an attacker will not. See issue #28 for a scenario where misuse of a key could lead to the compromise of a private.

Ok revisiting this, the current plan is to rearrange things to make use of the existing 'Key Role' parameter in pre-personalisation for this purpose.
One of the problems in SP800-73 is that there is no explicit statement of intention about what operation you want to perform. Instead, it is deduced by the key id and the presence/length of the witness/challenge/response/exponentiation tags. Added to the confusion is that the same challenge/response elements are used for signing, auth and key management in the case of RSA.

So the idea is to change KeyRole from having PIV-centric description (Internal Auth, External Auth, Mutual Auth, etc) to more the generic values and their meanings for each key type (SYM=Symmetric/RSA/ECC/SM=Secure Messaging):

  • Authenticate (SYM = External or Mutual Auth, RSA=Signing w/o Padding, ECC not permitted, SM not permitted)
  • Signature (SYM not permitted, RSA=Signing w/o Padding, ECC = ECSDA, SM not permitted)
  • Key Establish (SYM not permitted, RSA=Private Decrypt, ECC = ECDH, SM = Opacity-ZKM)

Then a separate optional field 'Key Attribute' will be added to provide additional modifiers for keys:

  • Admin (SYM the key can be used for card administration, RSA/ECC/SM no effect), default FALSE
  • Generate Only (SYM no effect, RSA/ECC/SM no injection permitted), default FALSE
  • Restrict Auth (SYM mutual auth only, RSA/ECC/SM no effect), default FALSE

As @dengert mentioned, there are still cases where signing needs to be available for the certificate, so @dmercer-google I like your idea of having an administrative override (if admin, allow any operation that key type can do).

EDIT: Added missing ECC=ECDH to the Key Establish role

Key Establish (SYM not permitted, RSA=Private Decrypt, SM = Opacity-ZKM)
Did you leave out ECC=ECDH ?

One of the problems in SP800-73 is that there is no explicit statement of intention about what operation you want to perform.

There is an implicate statement, in that each key will have a certificate with key usage and the issuing CA will set up the keys and certificates as per 800-73. The recipients of any crypto is expected to check the certificate usage and thus the card does not double check the usage.

Note: Yubikey started using the the retired keys for other usage, and so the OpenSC PIV driver when the card is not a gov issued card (i.e. CHUID FASC-N in not present, or starts with 9999) will read the certificate (it has to to get the public key and key type and key size anyway) and set PKCS15 and PKCS11 attributes based on certificate usage. The recipients of any crypto is still expected to check the certificate usage.

I agree with this, but since card-level enforcement is in play this was more of a card-centric view of how to know intention. I am happy with the flexibility we have, but this is one of the down-sides as we have to generically describe everything.
I'm not a big fan of trying to re-use existing things (i.e. retired keys) for different purposes. It's a slippery slope. Maybe they had good reasons with PIV middleware that had static lists of possible keys, etc.

You can have card enforcement, but the receiver of any certificate should still verify the use. And I assume you can also read the pubkey from the card, so a certificate is not required? With 800-73 a certificate is required on the card or off-card as defined by the history object to middleware can get key type and size/curve.

The Yubico does not reuse a key. A new key is generated or written to one of the retired key slots (and maybe a certificate) and the history object is setup per 800-73. in effect it can have 34 keys and certificates on the card. They also have a way to set the "Pin Always" on selected keys and/or touch required on selected keys. They added additional commands to access these. https://developers.yubico.com/PIV/Introduction/Yubico_extensions.html
I am not saying I agree but that is what they do.

Key Establish (SYM not permitted, RSA=Private Decrypt, SM = Opacity-ZKM)
Did you leave out ECC=ECDH ?

Whoops missed this on my mobile. Yep totally missed that out.. edited to fix.

You can have card enforcement, but the receiver of any certificate should still verify the use. And I assume you can also read the pubkey from the card, so a certificate is not required? With 800-73 a certificate is required on the card or off-card as defined by the history object to middleware can get key type and size/curve.
Totally agree, it's the responsibility of the receiver to do this. We're just providing a card edge enforcement mechanism to avoid misuse, intentional or otherwise.

The Yubico does not reuse a key. A new key is generated or written to one of the retired key slots (and maybe a certificate) and the history object is setup per 800-73. in effect it can have 34 keys and certificates on the card. They also have a way to set the "Pin Always" on selected keys and/or touch required on selected keys. They added additional commands to access these. https://developers.yubico.com/PIV/Introduction/Yubico_extensions.html
I am not saying I agree but that is what they do.
When I used re-use I meant using a key that was intended for one purpose (archival), for a different purpose.. It's philosophical more than anything.

This change has been integrated into the feature/ecc-review-changes branch and will be merged up at the end of this week.

  • Roles have been changed generally in line with my comments above.
  • Attributes have been added, but modified slightly to default to the most conservative/least permissive option.
  • Verify / Encrypt / Decrypt have been assigned but reserved to make PIV a bit more versatile if we decide to make a PKCS#11 driver down the track

See definitions below:

NEW ROLES

 // Undefined role
 public static final byte ROLE_NONE = (byte) 0x00;

 // This key can be used for card/host authentication
 // SYM: Supported for all types
 // RSA: Not supported (RSA authentication is just signing)
 // ECC: Not supported (ECC authentication is just signing)
 public static final byte ROLE_AUTHENTICATE = (byte) 0x01;

 // This key can be used for key establishment schemes
 // SYM: Not supported
 // RSA: RSA Key Management (decryption)
 // ECC: ECDH
 public static final byte ROLE_KEY_ESTABLISH = (byte) 0x02;

 // This key can be used for digital signature generation
 // SYM: Not supported (Could be a MAC mechanism in the future?)
 // RSA: RSA Digital Signature
 // ECC: ECDSA
 public static final byte ROLE_SIGN = (byte) 0x04;

 // Used for digital signature verification
 // NOTE: Currently there is no PIV case for this, but reserve it in case we want the extension
 // SYM: Not supported (Could be a MAC mechanism in the future?)
 // RSA: Not supported
 // ECC: Not supported
 public static final byte ROLE_VERIFY = (byte) 0x08;

 // This key can be used for secure messaging establishment
 // SYM: Not supported
 // RSA: Not supported
 // ECC: Opacity ZKM (Must have CVC component)
 public static final byte ROLE_SECURE_MESSAGING = (byte) 0x10;

 // RESERVED - This key can be used for encryption operations
 public static final byte ROLE_ENCRYPT = (byte) 0x20;

 // RESERVED - This key can be used for decryption operations
 public static final byte ROLE_DECRYPT = (byte) 0x40;

ATTRIBUTES

  // Undefined attribute
  public static final byte ATTR_NONE = (byte) 0x00;

  // This key can be used for administrative authentication
  // SYM: Supported
  // RSA: Not supported
  // ECC: Not supported
  public static final byte ATTR_ADMIN = (byte) 0x01;

  // This symmetric key permits INTERNAL authentication (encrypting a challenge).
  // NOTE: Don't ever use this as it is totally insecure! See SECURITY.MD
  // SYM: Supported
  // RSA: Not supported
  // ECC: Not supported
  public static final byte ATTR_PERMIT_INTERNAL = (byte) 0x02;

  // This symmetric key permits EXTERNAL authentication (one-way challenge).
  // NOTE: Using this method does not provide any authentication of the card,
  //       so it is recommended to use MUTUAL authentication only.
  // SYM: Supported
  // RSA: Not supported
  // ECC: Not supported
  public static final byte ATTR_PERMIT_EXTERNAL = (byte) 0x04;

  // This key value may be injected under an administrative session
  // SYM: Supported (Must always be set!)
  // RSA: Supported
  // ECC: Supported
  public static final byte ATTR_IMPORTABLE = (byte) 0x10;

Let me know if there are any concerns with this. It is a breaking change in terms of the pre-perso commands so I'm open to suggestions on this.

Verify / Encrypt / Decrypt have been assigned but reserved to make PIV a bit more versatile if we decide to make a PKCS#11 driver down the track

With OpenSC, we found that Yubico users wanted more flexibility in the use of keys, including the retired keys. The PIV specs call for specific usage for each key. But the the encrypt and decrypt APDU commands are the same for RSA RAW so the card has no way to enforce usage. The OpenSC middleware will enforce the usage if the CHUID FASC-N does not start with 9999, which says it is a non gov issued card. In this case the keyUsage from corresponding certificates is used for enforce key usage in the PIV driver.

Closing as this has now been in for a while. Hopefully in the future we will implement some of the extended roles!