Closed Bug 1561637 Opened 5 years ago Closed 4 years ago

TLS 1.3 does not work in FIPS mode


(NSS :: Libraries, defect, P2)



(Not tracked)



(Reporter: hkario, Assigned: rrelyea)


(Whiteboard: [tls13])


(2 files)

When NSS is switched to FIPS mode, TLS 1.3 doesn't work.
This is because NSS implements HKDF using the PKCS#11 functions prohibited under FIPS mode, namely PK11_ExtractKeyValue and PK11_ImportSymKey.

see also bug 1552767

Also relevant:

We had a discussion about this a few years back, but never really concluded anything. Driving the process through PKCS#11 was not something I had the time to pursue.

AFAIK, Bob did push it through OASIS so HKDF is part of PKCS#11 v3.0 (same for TLS PRFs), but it now needs to be implemented in NSS using official PKCS#11 mechanisms looks workable, if complex. Credit then to Bob for working this out.

The typo on CKM_HKDF_DATA is unfortunate:

All tokens must minimally support bExtract set to true and bInfo values which start with the value “tls1.3 vi”.

I definitely agree this needs to get done, but the Mozilla team probably can't get to it in the next 16 weeks (2 cycles), so marking as a P2. We'd happily help review the patches, however.

Priority: -- → P2
Whiteboard: [tls13]

Patches coming as part of the PKCS #11 v3.0 work.

Assignee: nobody → rrelyea

Patch 1 of 2.
This patch updates softoken and helper functions with the new PKCS #11 v3 HKDF,
which handles all the correct key management so that we can work in FIPS mode

  1. Salts can be passed in as data, as and explicit NULL (which per spec means
    a zero filled buffer of length of the underlying HMAC), or through a key handle
  2. A Data object can be used as a key (explicitly allowed for this mechanism by
    the spec).
  3. A special mechansism produces a data object rather than a key, the latter
    which can be exported. Softoken does not do the optional validation on the pInfo
    to verify that the requested values are supposed to be data rather than keys.
    Some other tokens may.

The old hkdf mechanism has been retained for compatibility (well namely until
patch 2 is created, tls is still using it). The hkdf function has been broken
off into it's own function rather than inline in the derive function.

Note: because the base key and/or the export key could really be a data object,
our explicit handling of sensitive and extractable are adjusted to take into
account that those flags do not exist in data objects.

This is great stuff. Bob, do you have any sense on how long you think we should keep the old mechanisms so that people can use a newer softoken with old TLS code? My impression is that the TLS code is unlikely to lag softoken by much, if anything, so the old proprietary stuff can be removed in fairly short order, if not immediately.

I think it depends on the mechanism. Even though TLS uses HKDF, it's also a generic mechanism, so people could be using it in other protocols. OTOH, it's an NSS specific mechanism, so that's less likely. On the 3rd hand, it's really sharing the code with the real PKCS #11 mechanism. so it's not an expensive mechanism to maintain.

We should check the rest of Firefox. Kevin found direct uses of AES_GCM inside firefox (beyond SSL or the experimental interface). HKDF could be the same. Probably the deprecation model could be #ifdef around the switch statement (based on if CKM_NSS_HKDF is defined), then move CKM_NSS_HKDF into the PKCS11_v_2_0 section. We'll likely turn PKCS11 v2.0 on in RHEL 7 and RHEL 8 rebases and not in Fedora (or any future RHEL). That means it can go away when we finally make PKCS 11_V2_0 go away.


Part 2 of 2

Use the official PKCS #11 HKDF mechanism to implement tls 1.3.

  1. The new mechanism is a single derive mechanism, so we no longer need to
    pick it based on the underlying hmac (Note, we still need to know the
    underlying hmac, which is passed in as a mechanism parameter).

  2. Use the new keygen to generate CKK_HKDF keys rather than doing it by hand
    with the random number generator (never was really the best way of doing this).

  3. modify tls13hkdf.c to use the new mechanisms:

    1. Extract: use the new key handle in the mechanism parameters to pass the
      salt when the salt is a key handle.
      Extract: use the explicit NULL salt parameter if for the hash len salt of
    2. Expand: Expand is mostly a helper function which takes a mechanism. For
      regular expand, the mechanism is the normal _Derive, for the Raw version
      its the _Data function. That creates a data object, which is extractable
      in FIPS mode.
  4. update slot handling in tls13hkdf.c:

    1. we need to make sure that the key and the salt key are in the same
      slot. Provide a PK11wrap function to make that guarrentee (and use that
      function in PK11_WrapKey, which already has to do the same function).
    2. When importing a 'data' key for the zero key case, make sure we import
      into the salt key's slot. If there is no salt key, use PK11_GetBestSlot()
      rather than PK11_GetInternal slot.
You need to log in before you can comment on or make changes to this bug.