FIPS 180-3 requires some indication that the current operation is running in FIPS mode. This isn't just that the algorithms are FIPS algorithms, but that the algorithms are being used in a FIPS compliant way for the given token, and the algorithms are algorithms that have the appropriate certificate. A lot of what has traditionally been handled in the module's security policy now has to exist in code. Modules can accomplish FIPS 180-3 in one of three ways: 1) Some call the indicates the current operation is running in a FIPS compliant way. 2) Any calls to the module with is outside the security policy always fails. 3) The application can query the function to see if a given operation will be FIPS compliant. In strategy 2, which is often used by hardware tokens, not changes to PKCS #11 are necessary. Failure of the operation itself inidicates it's not FIPS compliant. For NSS I needed something different. Proposal in Brief: To handle strategy 1, I propose a new FIPS indicator function C_GetFIPSStatus(). It can be called on a session to determine if the current operation is FIPS compliant. Single shot operations (like C_GenerateKey(), C_Derive(), C_UnwrapKey) return key objects. The key object will also record it's FIPS status, which can also be returned by C_GetFIPSStatus. If you use a key object that wasn't generated by a FIPS compliant method, then using that key in an operation will make the entire operation not-FIPS. More detail: I've written out a proposal, including how to incorporate it into NSS:
https://docs.google.com/document/d/1Me9YksPE7K1Suvk9Ls5PqJXPpDmpAboLsrq0z54m_tA/edit I've implemented this in NSS here:
https://hg.mozilla.org/projects/nss/rev/40edc4f4c1170398c1409a2c04a79fb59fe65df7 with the following differences: The state machine is on a per session class, rather than a per session bases. (class means encrypt/decrypt sign/verify/hash). The various session class states are combined as follows: unknown + unknown = unknown unknown + not fips = not fips unknown + fips = fips not fips + not fips = not fips not fips + fips = not fips fips + fips = fips Most of the time one of the states will be unknown. This varies from the global state machine in that if you C_Finalize a not FIPS operation before a FIPS operation, the state can swith from FIPS to not FIPS. session also keeps a state - last operation FIPS status. This gets on C_xxxFinal, or after a single shot operation. This is necessary to get the FIPS status of a C_WrapKey operation, which doesn't return a key object, so can't return FIPS status on that option C_GetFIPSStatus has a new type CKT_SESSION_LAST_CHECK. This is also necessary to handle non-FIPS operations on things like C_SignFinal, where the application requests too short a value from the hash function (I didn't specifically need this for NSS because NSS explicitly fails this case, but it might be necessary in other tokens). the block list is now a allow list, with the default being empty (since you need to get a FIPS validation to supply the list). This detail isn't relevant to the PKCS #11 spec as it's an implementation detail. The patch includes how NSS uses the function to rollup general FIPS compliance on a given operation (most notably SSL). Some questions for the committe: I did not try to address option 3. It seems an almost intractable problem since a FIPS compliance of a particular operation depends. My thought is you need to specify pretty much what you tell C_Initialize anyway, so your query could be C_Initialize C_GetFIPStatus C_Finalize. For NSS as a vendor supplied function, it comes from a vendor supplied interface, for FIPS it should be in the normal Function table, or in a set of FIPS specific interfaces. We need to decide. Spellings of the various states and types are certainly up for grabs at this point. What do you think about the modified state machine, and should there be cross-talk between the various states. Should the FIPS status of a key be an attribute? (and should it persist for token attributes -- for NSS I assume all token attributes are FIPS). Bob