Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Bug 1710773 NSS needs FIPS 180-3 FIPS indicators. r=mt
Changes from the review:
The while loop was taken out of it's subshell pipe, which prevented the selfserv PID from being passed on to the final selfserv-kill. This eventally lead to a freeze on windows.

The last paragraph of ISO 19790:2012 section 7.2.4.2 states:

All services shall [02.24] provide an indicator when the service utilises an approved cryptographic algorithm, security function or process in an approved manner and those services or processes specified in 7.4.3

This means our libraries need to grow an API or provide some additional information via contexts or similar in order for an application to be able to query this indicator. This can't be just a Security Policy description because ISO 24759:2017 section 6.2.4.2 states:

TE02.24.02: The tester shall execute all services and verify that the indicator provides an unambiguous indication of whether the service utilizes an approved cryptographic algorithm, security function or process in an approved manner or not.

The indicator can't be just a marker over an algorithm either, because it needs to show different values based on whether the algorithm parameters causes the algorithm to run in approved or non-approved mode (ie keys outside of valid range for RSA means RSA is being used in non-approved mode ...)

For NSS, there is a PKCS #11 design:
https://docs.google.com/document/d/1Me9YksPE7K1Suvk9Ls5PqJXPpDmpAboLsrq0z54m_tA/edit?usp=sharing

This patch implments the above design as well as:
   1) NSS proper functions to access these indicators from either the pk11wrap layer or the ssl layer.
   2) Updates to the ssl tests which will output the value of the

Changes decription by file:
cmd/selfserv/selfserv.c
   Add a FIPS indicator if the connection was excuted in FIPS mode on a FIPS token.
cmd/strsclnt/strsclnt.c
   Add a FIPS indicator if the connection was excuted in FIPS mode on a FIPS token.
cmd/tstclnt/tstclnt.c
   Add a FIPS indicator if the connection was excuted in FIPS mode on a FIPS token.
lib/nss/nss.def
   Add the new pk11 functions to access the fips indicator.
lib/pk11wrap/pk11cxt.c
   Implement a function to get the FIPS indicator for the current PK11Context.
lib/pk11wrap/pk11load.c
   Get the fips indicator function from the PKCS #11 module using the vendor function interface from PKCS #11 v3.0
lib/pk11wrap/pk11obj.c
   Implement a function to get the FIPS indicator for a specific PKCS #11 object.
lib/pk11wrap/pk11priv.h
   Add a generalized helper function to get the FIPS indicator used by all the other exported functions to get FIPS indicator.
lib/pk11wrap/pk11pub.h
   Add function to get the FIPS indicator for the current PK11Context.
lib/pk11wrap/pk11slot.c
   Implement a generalized helper function to get the FIPS indicator.
   Implement a function to get the FIPS indicator for the latest single shot operation on the slot.
lib/pk11wrap/secmodt.h
   Add a new field to hold the fipsIndicator function.
lib/softoken/fips_algorithms.h
   New sample header which vendors can replace with their own table. In the default NSS case, the table in this header will be empty.
lib/softoken/fipstokn.c
   Add Vendor specific interface for the FIPS indicator to the FIPS token.
lib/softoken/pkcs11.c
   Add Vendor specific interface for the FIPS indicator to the non-FIPS token.
   Factor out the code tha maps an attribute value to a mechanism flag to it's own file so it can
be used by other parts of softoken. (new function is in pkcs11u.c
   Implement the function that returns the FIPS indicator. This function fetches the indicator from either the session or the object or both. The session indicator is in the crypto context (except the last operation indicator, which is in the session itself. The object indicator is in the base object.
lib/softoken/pkcs11c.c
   Record the FIPS indicator in the various helper function.
    - sftk_TerminateOp is called when a crypto operation had been finalized, so we can store that fips indicator in the lastOpWasFIPS field.
    - sftk_InitGeneric is called when a crypto operation has been initialized, so we can make a preliminary determination if the operation is within the FIPS policy (could later change bases on other operations. For this to work, we need the actual mechanism, so pMechanism is now a parameter to sftk_InitGeneric.
    - sftk_HKDF - HKDF when used in TLS has the unusual characteristic that the salt could actually be a key. In this case, usually the base key is some known public value which would not be FIPS generated, but the security is based on whether the salt is really a FIPS generated key. In this case we redo the calculation based on the salt key.
lib/softoken/pkcs11i.h
    - add the FIPS indicators to the various structures (crypto contexts, sessions, objects).
    - add the FIPS indicators function list
    - add pMechanism the the sftkInitGeneric function.
    - add the helper function to map Attribute Types to Mechanism Flags.
    - add the function that will look up the current operation in the FIPS table to determine that it is allowed by policy.
lib/softoken/pkcs11u.c
    - include the new fips_algorithms.h (if NSS_FIPS_DISABLED is not on)
    - handle the FIPS status for objects and session on creation an copy.
    - implement the helper function to map Attribute Types to Mechanism Flags.
    - get the key length of a key. This involves getting the key type and then using the key type to determin the appropriate attribute to fetch. Most keys it's simply the CKA_VALUE. ECC is special, we get the key length from the curve. Since only a subset of curves can be FIPS Curves, we use key length to return false for other curves.
    - the handle special function handles any unusal semantics for various mechanism types. This function precodes possible mechanism semantics we may need to check. The special handling can be selected by the mechanism table in fips_algorithms.h
    - sftk_operationIsFIPS - the actual function to determine if the givelib/n operation is in the FIPS table.
lib/softoken/sftkmessage.c
    - just need to update the sftk_InitGeneric function to pass the mechanism.
lib/ssl/ssl3con.c
    - and functions to query the underlying crypto contexts to see if the current ssl session is running in FIPS approved mode based on the security policy. It does so by checking the CipherSpecIsFIPS function to verify that both the mac and the encryption algorithm FIPS conforms to the ciphers in the security profile (using PK11_GetFIPSStatus). We check both the cipher specs for read and write. These underlying specs depends on the keys used in these specs being generated with FIPS approved algorithms as well, so this verifies the kea and kdf functions as well.
lib/ssl/sslimpl.h
   - ass ssl_isFIPS() so it can be used by other files here in the ssl directory.
lib/ssl/sslinfo.c
   - set the new isFIPS field in the existing sslinfo structure. SSL_GetChannelInfo knows how to handle sslinfo structures that are smaller then expected and larger than expected. unknown fields will be set to '0' (so new applications running against old versions will always get zero for new fields). sslinfo that are smaller will only return a the subset the calling application expects (so old applications will not get the new fields).
lib/ssl/sslt.h
    - Add the new isFIPS field (must be at the end of the ChannelInfo structure).
lib/util/pkcs11n.h
    - add the new FIPS indicator defines.
tests/ssl/ssl.h
    - The main changes was to turn on verbose for the coverage tests so we can test the FIPS indicators on various cipher suites. NOTE: this only works with either NSS_TEST_FIPS_ALGORIHTMS set, or a vendor fips_algorthims.h, so vendors will need to do their own test interpretation. While working in ssl.sh I fixed an number of other issues:
    - many tests that were skipped in FIPS mode were skipped not because they didn't work in FIPS mode, but because tstclnt requires a password when running in FIPS mode. I've now added the password if the function is running in fips mode and removed the fips restrictions.
    - dtls had a race condition. the server side needed to come up before the client, but couldn't end before the client ran. We already had a sleep to guarrentee the former, I added a sleep before sending the server it's data to handle the latter.
    - CURVE25519 is the default ECC curve, but it's not a fiPS curve, so I disable it in FIPS mode so we will actually get FIPS indicators when using ECDHE.
    - I added TLS 1.3 to the coverage tests.

Differential Revision: https://phabricator.services.mozilla.com/D115034

--HG--
extra : rebase_source : a1362bcf8107d26492578475d95522001ed0c3bd
  • Loading branch information
rjrelyea committed May 12, 2021
1 parent 6c61c1f commit 595deb8
Show file tree
Hide file tree
Showing 28 changed files with 901 additions and 120 deletions.
17 changes: 17 additions & 0 deletions automation/abi-check/expected-report-libnss3.so.txt
@@ -0,0 +1,17 @@

3 Added functions:

'function PRBool PK11_ContextGetFIPSStatus(PK11Context*)' {PK11_ContextGetFIPSStatus@@NSS_3.66}
'function PRBool PK11_ObjectGetFIPSStatus(PK11ObjectType, void*)' {PK11_ObjectGetFIPSStatus@@NSS_3.66}
'function PRBool PK11_SlotGetLastFIPSStatus(PK11SlotInfo*)' {PK11_SlotGetLastFIPSStatus@@NSS_3.66}

1 function with some indirect sub-type change:

[C]'function SECStatus PK11_GetModInfo(SECMODModule*, CK_INFO*)' at pk11util.c:613:1 has some indirect sub-type changes:
parameter 1 of type 'SECMODModule*' has sub-type changes:
in pointed to type 'typedef SECMODModule' at secmodt.h:29:1:
underlying type 'struct SECMODModuleStr' at secmodt.h:44:1 changed:
type size changed from 1664 to 1728 bits
1 data member insertion:
'CK_NSS_GetFIPSStatus SECMODModuleStr::fipsIndicator', at offset 1664 (in bits) at secmodt.h:79:1
no data member changes (2 filtered);
10 changes: 10 additions & 0 deletions automation/abi-check/expected-report-libssl3.so.txt
@@ -0,0 +1,10 @@

1 function with some indirect sub-type change:

[C]'function SECStatus SSL_GetChannelInfo(PRFileDesc*, SSLChannelInfo*, PRUintn)' at sslinfo.c:14:1 has some indirect sub-type changes:
parameter 2 of type 'SSLChannelInfo*' has sub-type changes:
in pointed to type 'typedef SSLChannelInfo' at sslt.h:383:1:
underlying type 'struct SSLChannelInfoStr' at sslt.h:299:1 changed:
type size changed from 1024 to 1088 bits
1 data member insertion:
'PRBool SSLChannelInfoStr::isFIPS', at offset 1024 (in bits) at sslt.h:379:1
5 changes: 3 additions & 2 deletions cmd/selfserv/selfserv.c
Expand Up @@ -404,10 +404,11 @@ printSecurityInfo(PRFileDesc *fd)
&suite, sizeof suite);
if (result == SECSuccess) {
FPRINTF(stderr,
"selfserv: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
"selfserv: SSL version %d.%d using %d-bit %s with %d-bit %s MAC%s\n",
channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
suite.effectiveKeyBits, suite.symCipherName,
suite.macBits, suite.macAlgorithmName);
suite.macBits, suite.macAlgorithmName,
channel.isFIPS ? " FIPS" : "");
FPRINTF(stderr,
"selfserv: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n"
" Compression: %s, Extended Master Secret: %s\n",
Expand Down
5 changes: 3 additions & 2 deletions cmd/strsclnt/strsclnt.c
Expand Up @@ -295,10 +295,11 @@ printSecurityInfo(PRFileDesc *fd)
&suite, sizeof suite);
if (result == SECSuccess) {
FPRINTF(stderr,
"strsclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
"strsclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC%s\n",
channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
suite.effectiveKeyBits, suite.symCipherName,
suite.macBits, suite.macAlgorithmName);
suite.macBits, suite.macAlgorithmName,
channel.isFIPS ? " FIPS" : "");
FPRINTF(stderr,
"strsclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n"
" Compression: %s\n",
Expand Down
5 changes: 3 additions & 2 deletions cmd/tstclnt/tstclnt.c
Expand Up @@ -168,10 +168,11 @@ printSecurityInfo(PRFileDesc *fd)
&suite, sizeof suite);
if (result == SECSuccess) {
FPRINTF(stderr,
"tstclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
"tstclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC%s\n",
channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
suite.effectiveKeyBits, suite.symCipherName,
suite.macBits, suite.macAlgorithmName);
suite.macBits, suite.macAlgorithmName,
channel.isFIPS ? " FIPS" : "");
FPRINTF(stderr,
"tstclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n"
" Compression: %s, Extended Master Secret: %s\n"
Expand Down
10 changes: 9 additions & 1 deletion lib/nss/nss.def
Expand Up @@ -1222,11 +1222,19 @@ PK11_HPKE_ImportContext;
;+};
;+NSS_3.65 { # NSS 3.65 release
;+ global:
HASH_GetHMACOidTagByHashOidTag;
PK11_CreateContextByPubKey;
PK11_CreateContextByPrivKey;
PK11_ExportEncryptedPrivKeyInfoV2;
PK11_ExportEncryptedPrivateKeyInfoV2;
HASH_GetHMACOidTagByHashOidTag;
;+ local:
;+ *;
;+};
;+NSS_3.66 { # NSS 3.66 release
;+ global:
PK11_ContextGetFIPSStatus;
PK11_ObjectGetFIPSStatus;
PK11_SlotGetLastFIPSStatus;
;+ local:
;+ *;
;+};
10 changes: 10 additions & 0 deletions lib/pk11wrap/pk11cxt.c
Expand Up @@ -1783,3 +1783,13 @@ PK11_DigestFinal(PK11Context *context, unsigned char *data,
*outLen = (unsigned int)len;
return SECSuccess;
}

PRBool
PK11_ContextGetFIPSStatus(PK11Context *context)
{
if (context->slot == NULL) {
return PR_FALSE;
}
return pk11slot_GetFIPSStatus(context->slot, context->session,
CK_INVALID_HANDLE, context->init ? CKT_NSS_SESSION_CHECK : CKT_NSS_SESSION_LAST_CHECK);
}
7 changes: 7 additions & 0 deletions lib/pk11wrap/pk11load.c
Expand Up @@ -409,6 +409,8 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
if (mod->loaded)
return SECSuccess;

mod->fipsIndicator = NULL;

/* internal modules get loaded from their internal list */
if (mod->internal && (mod->dllName == NULL)) {
#ifdef NSS_STATIC_SOFTOKEN
Expand Down Expand Up @@ -514,6 +516,11 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
}
mod->functionList = interface->pFunctionList;
mod->flags = interface->flags;
/* if we have a fips indicator, grab it */
if ((*ientry)((CK_UTF8CHAR_PTR) "Vendor NSS FIPS Interface", NULL,
&interface, 0) == CKR_OK) {
mod->fipsIndicator = ((CK_NSS_FIPS_FUNCTIONS *)(interface->pFunctionList))->NSC_NSSGetFIPSStatus;
}
} else {
if ((*fentry)((CK_FUNCTION_LIST_PTR *)&mod->functionList) != CKR_OK)
goto fail;
Expand Down
15 changes: 15 additions & 0 deletions lib/pk11wrap/pk11obj.c
Expand Up @@ -2265,3 +2265,18 @@ pk11_GetLowLevelKeyFromHandle(PK11SlotInfo *slot, CK_OBJECT_HANDLE handle)

return item;
}

PRBool
PK11_ObjectGetFIPSStatus(PK11ObjectType objType, void *objSpec)
{
PK11SlotInfo *slot = NULL;
CK_OBJECT_HANDLE handle = 0;

handle = PK11_GetObjectHandle(objType, objSpec, &slot);
if (handle == CK_INVALID_HANDLE) {
PORT_SetError(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
return PR_FALSE;
}
return pk11slot_GetFIPSStatus(slot, slot->session, handle,
CKT_NSS_OBJECT_CHECK);
}
5 changes: 5 additions & 0 deletions lib/pk11wrap/pk11priv.h
Expand Up @@ -200,6 +200,11 @@ SECStatus pk11_setGlobalOptions(PRBool noSingleThreadedModules,
/* return whether NSS is allowed to call C_Finalize */
PRBool pk11_getFinalizeModulesOption(void);

/* fetch the FIPS state from the fips indicator, public versions of
* this function operate on the slot, the context, and the object */
PRBool pk11slot_GetFIPSStatus(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE object, CK_ULONG operationType);

SEC_END_PROTOS

#endif
18 changes: 18 additions & 0 deletions lib/pk11wrap/pk11pub.h
Expand Up @@ -1029,6 +1029,24 @@ PRBool SECMOD_HasRootCerts(void);
*/
int SECMOD_GetSystemFIPSEnabled(void);

/* FIPS indicator functions. Some operations are physically allowed, but
* are against the NSS FIPS security policy. This is because sometimes NSS
* functions are used in non-security contexts. You can call these functions
* to determine if you are operating inside or outside the the current vendor's
* FIPS Security Policy for NSS. NOTE: if the current version of NSS is not
* actually FIPS certified, then these functions will always return PR_FALSE */

/* This function tells if if the last single shot operation on the slot
* was inside or outside the FIPS security policy */
PRBool PK11_SlotGetLastFIPSStatus(PK11SlotInfo *slot);
/* This tells you if the current operation is within the FIPS security policy. If
* you have called finalize on the context, it tells you if the last operation
* was within the FIPS security policy */
PRBool PK11_ContextGetFIPSStatus(PK11Context *context);
/* This tells you if the requested object was created in accordance to the
* NSS FIPS security policy. */
PRBool PK11_ObjectGetFIPSStatus(PK11ObjectType objType, void *objSpec);

SEC_END_PROTOS

#endif
33 changes: 33 additions & 0 deletions lib/pk11wrap/pk11slot.c
Expand Up @@ -2665,6 +2665,39 @@ PK11Slot_GetNSSToken(PK11SlotInfo *sl)
return sl->nssToken;
}

PRBool
pk11slot_GetFIPSStatus(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE object, CK_ULONG operationType)
{
SECMODModule *mod = slot->module;
CK_RV crv;
CK_ULONG fipsState = CKS_NSS_FIPS_NOT_OK;

/* handle the obvious conditions:
* 1) the module doesn't have a fipsIndicator - fips state must be false */
if (mod->fipsIndicator == NULL) {
return PR_FALSE;
}
/* 2) the session doesn't exist - fips state must be false */
if (session == CK_INVALID_HANDLE) {
return PR_FALSE;
}

/* go fetch the state */
crv = mod->fipsIndicator(session, object, operationType, &fipsState);
if (crv != CKR_OK) {
return PR_FALSE;
}
return (fipsState == CKS_NSS_FIPS_OK) ? PR_TRUE : PR_FALSE;
}

PRBool
PK11_SlotGetLastFIPSStatus(PK11SlotInfo *slot)
{
return pk11slot_GetFIPSStatus(slot, slot->session, CK_INVALID_HANDLE,
CKT_NSS_SESSION_LAST_CHECK);
}

/*
* wait for a token to change it's state. The application passes in the expected
* new state in event.
Expand Down
3 changes: 3 additions & 0 deletions lib/pk11wrap/secmodt.h
Expand Up @@ -74,6 +74,9 @@ struct SECMODModuleStr {
* events (SECMOD_WaitForAnyTokenEvent) */
CK_VERSION cryptokiVersion; /* version of this library */
CK_FLAGS flags; /* pkcs11 v3 flags */
/* Warning this could go way in future versions of NSS
* when FIPS indicators wind up in the functionList */
CK_NSS_GetFIPSStatus fipsIndicator;
};

/* evControlMask flags */
Expand Down
5 changes: 5 additions & 0 deletions lib/softoken/config.mk
Expand Up @@ -54,3 +54,8 @@ endif
ifeq ($(OS_TARGET),AIX)
OS_LIBS += -lpthread
endif

ifdef NSS_ENABLE_FIPS_INDICATORS
DEFINES += -DNSS_ENABLE_FIPS_INDICATORS
endif

0 comments on commit 595deb8

Please sign in to comment.