diff options
28 files changed, 901 insertions, 120 deletions
diff --git a/automation/abi-check/expected-report-libnss3.so.txt b/automation/abi-check/expected-report-libnss3.so.txt index e69de29bb..d34243d92 100644 --- a/automation/abi-check/expected-report-libnss3.so.txt +++ b/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); diff --git a/automation/abi-check/expected-report-libssl3.so.txt b/automation/abi-check/expected-report-libssl3.so.txt index e69de29bb..e3bb57179 100644 --- a/automation/abi-check/expected-report-libssl3.so.txt +++ b/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 diff --git a/cmd/selfserv/selfserv.c b/cmd/selfserv/selfserv.c index 00de3a6b7..5094cc7bf 100644 --- a/cmd/selfserv/selfserv.c +++ b/cmd/selfserv/selfserv.c @@ -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", diff --git a/cmd/strsclnt/strsclnt.c b/cmd/strsclnt/strsclnt.c index 3d9fc4f78..7bc36db3f 100644 --- a/cmd/strsclnt/strsclnt.c +++ b/cmd/strsclnt/strsclnt.c @@ -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", diff --git a/cmd/tstclnt/tstclnt.c b/cmd/tstclnt/tstclnt.c index 2c108c612..8b9efa007 100644 --- a/cmd/tstclnt/tstclnt.c +++ b/cmd/tstclnt/tstclnt.c @@ -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" diff --git a/lib/nss/nss.def b/lib/nss/nss.def index 46bd41a60..e87395ba9 100644 --- a/lib/nss/nss.def +++ b/lib/nss/nss.def @@ -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: ;+ *; ;+}; diff --git a/lib/pk11wrap/pk11cxt.c b/lib/pk11wrap/pk11cxt.c index 3e80e8754..d94d6fc68 100644 --- a/lib/pk11wrap/pk11cxt.c +++ b/lib/pk11wrap/pk11cxt.c @@ -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); +} diff --git a/lib/pk11wrap/pk11load.c b/lib/pk11wrap/pk11load.c index 2bc41dbc4..a318e92fa 100644 --- a/lib/pk11wrap/pk11load.c +++ b/lib/pk11wrap/pk11load.c @@ -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 @@ -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; diff --git a/lib/pk11wrap/pk11obj.c b/lib/pk11wrap/pk11obj.c index aaaf6586f..8ece7a6d4 100644 --- a/lib/pk11wrap/pk11obj.c +++ b/lib/pk11wrap/pk11obj.c @@ -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); +} diff --git a/lib/pk11wrap/pk11priv.h b/lib/pk11wrap/pk11priv.h index e9977cfdb..faf9ad298 100644 --- a/lib/pk11wrap/pk11priv.h +++ b/lib/pk11wrap/pk11priv.h @@ -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 diff --git a/lib/pk11wrap/pk11pub.h b/lib/pk11wrap/pk11pub.h index 53350f76d..a2a647320 100644 --- a/lib/pk11wrap/pk11pub.h +++ b/lib/pk11wrap/pk11pub.h @@ -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 diff --git a/lib/pk11wrap/pk11slot.c b/lib/pk11wrap/pk11slot.c index 2f805431d..c320019f9 100644 --- a/lib/pk11wrap/pk11slot.c +++ b/lib/pk11wrap/pk11slot.c @@ -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. diff --git a/lib/pk11wrap/secmodt.h b/lib/pk11wrap/secmodt.h index 34fd4cce1..5f15e5967 100644 --- a/lib/pk11wrap/secmodt.h +++ b/lib/pk11wrap/secmodt.h @@ -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 */ diff --git a/lib/softoken/config.mk b/lib/softoken/config.mk index 14ea5d6e4..771b93a3f 100644 --- a/lib/softoken/config.mk +++ b/lib/softoken/config.mk @@ -54,3 +54,8 @@ endif ifeq ($(OS_TARGET),AIX) OS_LIBS += -lpthread endif + +ifdef NSS_ENABLE_FIPS_INDICATORS +DEFINES += -DNSS_ENABLE_FIPS_INDICATORS +endif + diff --git a/lib/softoken/fips_algorithms.h b/lib/softoken/fips_algorithms.h new file mode 100644 index 000000000..c964d2eea --- /dev/null +++ b/lib/softoken/fips_algorithms.h @@ -0,0 +1,170 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Vendors should replace this header file with the file containing those + * algorithms which have NIST algorithm Certificates. + */ + +/* handle special cases. Classes require existing code to already be + * in place for that class */ +typedef enum { + SFTKFIPSNone = 0, + SFTKFIPSDH, /* allow only specific primes */ + SFTKFIPSECC, /* not just keys but specific curves */ + SFTKFIPSAEAD /* single shot AEAD functions not allowed in FIPS mode */ +} SFTKFIPSSpecialClass; + +typedef struct SFTKFIPSAlgorithmListStr SFTKFIPSAlgorithmList; +struct SFTKFIPSAlgorithmListStr { + CK_MECHANISM_TYPE type; + CK_MECHANISM_INFO info; + CK_ULONG step; + SFTKFIPSSpecialClass special; +}; + +SFTKFIPSAlgorithmList sftk_fips_mechs[] = { +/* A sample set of algorithms to allow basic testing in our continous + * testing infrastructure. The vendor version should replace this with + * a version that matches their algorithm testing and security policy */ +/* NOTE, This looks a lot like the PKCS #11 mechanism list in pkcs11.c, it + * differs in the following ways: + * 1) the addition of step and class elements to help restrict + * the supported key sizes and types. + * 2) The mechanism flags are restricted to only those that map to + * fips approved operations. + * 3) All key sizes are in bits, independent of mechanism. + * 4) You can add more then one entry for the same mechanism to handle + * multiple descrete keys where the MIN/MAX/STEP semantics doesn't apply + * or where different operations have different key requirements. + * This table does not encode all the modules legal FIPS semantics, only + * those semantics that might possibly change due to algorithms dropping + * of the security policy late in the process. */ +/* handy common flag types */ +#define CKF_KPG CKF_GENERATE_KEY_PAIR +#define CKF_GEN CKF_GENERATE +#define CKF_SGN (CKF_SIGN | CKF_VERIFY) +#define CKF_ENC (CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP) +#define CKF_KEK (CKF_WRAP | CKF_UNWRAP) +#define CKF_KEA CKF_DERIVE +#define CKF_KDF CKF_DERIVE +#define CKF_HSH CKF_DIGEST +#define CK_MAX 0xffffffffUL +/* mechanisms using the same key types share the same key type + * limits */ +#define RSA_FB_KEY 2048, 4096 /* min, max */ +#define RSA_FB_STEP 1024 +#define DSA_FB_KEY 2048, 4096 /* min, max */ +#define DSA_FB_STEP 1024 +#define DH_FB_KEY 2048, 4096 /* min, max */ +#define DH_FB_STEP 1024 +#define EC_FB_KEY 256, 521 /* min, max */ +#define EC_FB_STEP 1 /* key limits handled by special operation */ +#define AES_FB_KEY 128, 256 +#define AES_FB_STEP 64 + { CKM_RSA_PKCS_KEY_PAIR_GEN, { RSA_FB_KEY, CKF_KPG }, RSA_FB_STEP, SFTKFIPSNone }, + { CKM_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, + { CKM_RSA_PKCS_OAEP, { RSA_FB_KEY, CKF_ENC }, RSA_FB_STEP, SFTKFIPSNone }, + /* -------------- RSA Multipart Signing Operations -------------------- */ + { CKM_SHA224_RSA_PKCS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, + { CKM_SHA256_RSA_PKCS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, + { CKM_SHA384_RSA_PKCS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, + { CKM_SHA512_RSA_PKCS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, + { CKM_SHA224_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, + { CKM_SHA256_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, + { CKM_SHA384_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, + { CKM_SHA512_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, + /* ------------------------- DSA Operations --------------------------- */ + { CKM_DSA_KEY_PAIR_GEN, { DSA_FB_KEY, CKF_KPG }, DSA_FB_STEP, SFTKFIPSNone }, + { CKM_DSA, { DSA_FB_KEY, CKF_SGN }, DSA_FB_STEP, SFTKFIPSNone }, + { CKM_DSA_PARAMETER_GEN, { DSA_FB_KEY, CKF_KPG }, DSA_FB_STEP, SFTKFIPSNone }, + { CKM_DSA_SHA224, { DSA_FB_KEY, CKF_SGN }, DSA_FB_STEP, SFTKFIPSNone }, + { CKM_DSA_SHA256, { DSA_FB_KEY, CKF_SGN }, DSA_FB_STEP, SFTKFIPSNone }, + { CKM_DSA_SHA384, { DSA_FB_KEY, CKF_SGN }, DSA_FB_STEP, SFTKFIPSNone }, + { CKM_DSA_SHA512, { DSA_FB_KEY, CKF_SGN }, DSA_FB_STEP, SFTKFIPSNone }, + /* -------------------- Diffie Hellman Operations --------------------- */ + /* no diffie hellman yet */ + { CKM_DH_PKCS_KEY_PAIR_GEN, { DH_FB_KEY, CKF_KPG }, DH_FB_STEP, SFTKFIPSDH }, + { CKM_DH_PKCS_DERIVE, { DH_FB_KEY, CKF_KEA }, DH_FB_STEP, SFTKFIPSDH }, + /* -------------------- Elliptic Curve Operations --------------------- */ + { CKM_EC_KEY_PAIR_GEN, { EC_FB_KEY, CKF_KPG }, EC_FB_STEP, SFTKFIPSECC }, + { CKM_ECDH1_DERIVE, { EC_FB_KEY, CKF_KEA }, EC_FB_STEP, SFTKFIPSECC }, + { CKM_ECDSA, { EC_FB_KEY, CKF_SGN }, EC_FB_STEP, SFTKFIPSECC }, + { CKM_ECDSA_SHA224, { EC_FB_KEY, CKF_SGN }, EC_FB_STEP, SFTKFIPSECC }, + { CKM_ECDSA_SHA256, { EC_FB_KEY, CKF_SGN }, EC_FB_STEP, SFTKFIPSECC }, + { CKM_ECDSA_SHA384, { EC_FB_KEY, CKF_SGN }, EC_FB_STEP, SFTKFIPSECC }, + { CKM_ECDSA_SHA512, { EC_FB_KEY, CKF_SGN }, EC_FB_STEP, SFTKFIPSECC }, + /* ------------------------- RC2 Operations --------------------------- */ + /* ------------------------- AES Operations --------------------------- */ + { CKM_AES_KEY_GEN, { AES_FB_KEY, CKF_GEN }, AES_FB_STEP, SFTKFIPSNone }, + { CKM_AES_ECB, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone }, + { CKM_AES_CBC, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone }, + { CKM_AES_MAC, { AES_FB_KEY, CKF_SGN }, AES_FB_STEP, SFTKFIPSNone }, + { CKM_AES_MAC_GENERAL, { AES_FB_KEY, CKF_SGN }, AES_FB_STEP, SFTKFIPSNone }, + { CKM_AES_CMAC, { AES_FB_KEY, CKF_SGN }, AES_FB_STEP, SFTKFIPSNone }, + { CKM_AES_CMAC_GENERAL, { AES_FB_KEY, CKF_SGN }, AES_FB_STEP, SFTKFIPSNone }, + { CKM_AES_CBC_PAD, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone }, + { CKM_AES_CTS, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone }, + { CKM_AES_CTR, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone }, + { CKM_AES_GCM, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSAEAD }, + { CKM_AES_KEY_WRAP, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone }, + { CKM_AES_KEY_WRAP_PAD, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone }, + { CKM_AES_KEY_WRAP_KWP, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone }, + { CKM_AES_XCBC_MAC_96, { 96, 96, CKF_SGN }, 1, SFTKFIPSNone }, + { CKM_AES_XCBC_MAC, { 128, 128, CKF_SGN }, 1, SFTKFIPSNone }, + /* ------------------------- Hashing Operations ----------------------- */ + { CKM_SHA224, { 0, 0, CKF_HSH }, 1, SFTKFIPSNone }, + { CKM_SHA224_HMAC, { 112, 224, CKF_SGN }, 1, SFTKFIPSNone }, + { CKM_SHA224_HMAC_GENERAL, { 112, 224, CKF_SGN }, 1, SFTKFIPSNone }, + { CKM_SHA256, { 0, 0, CKF_HSH }, 1, SFTKFIPSNone }, + { CKM_SHA256_HMAC, { 128, 256, CKF_SGN }, 1, SFTKFIPSNone }, + { CKM_SHA256_HMAC_GENERAL, { 128, 256, CKF_SGN }, 1, SFTKFIPSNone }, + { CKM_SHA384, { 0, 0, CKF_HSH }, 1, SFTKFIPSNone }, + { CKM_SHA384_HMAC, { 192, 384, CKF_SGN }, 1, SFTKFIPSNone }, + { CKM_SHA384_HMAC_GENERAL, { 192, 384, CKF_SGN }, 1, SFTKFIPSNone }, + { CKM_SHA512, { 0, 0, CKF_HSH }, 1, SFTKFIPSNone }, + { CKM_SHA512_HMAC, { 256, 512, CKF_SGN }, 1, SFTKFIPSNone }, + { CKM_SHA512_HMAC_GENERAL, { 256, 512, CKF_SGN }, 1, SFTKFIPSNone }, + /* --------------------- Secret Key Operations ------------------------ */ + { CKM_GENERIC_SECRET_KEY_GEN, { 8, 256, CKF_GEN }, 1, SFTKFIPSNone }, + /* ---------------------- SSL/TLS operations ------------------------- */ + { CKM_SHA224_KEY_DERIVATION, { 112, 224, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_SHA256_KEY_DERIVATION, { 128, 256, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_SHA384_KEY_DERIVATION, { 192, 284, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_SHA512_KEY_DERIVATION, { 256, 512, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_TLS12_MASTER_KEY_DERIVE, { 384, 384, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_TLS12_MASTER_KEY_DERIVE_DH, { DH_FB_KEY, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_TLS12_KEY_AND_MAC_DERIVE, { 384, 384, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_TLS_PRF_GENERAL, { 8, 512, CKF_SGN }, 1, SFTKFIPSNone }, + { CKM_TLS_MAC, { 8, 512, CKF_SGN }, 1, SFTKFIPSNone }, + /* sigh, is this algorithm really tested. ssl doesn't seem to have a + * way of turning the extension off */ + { CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE, { 192, 1024, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH, { 192, 1024, CKF_DERIVE }, 1, SFTKFIPSNone }, + + /* ------------------------- HKDF Operations -------------------------- */ + { CKM_HKDF_DERIVE, { 8, 255 * 64 * 8, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_HKDF_DATA, { 8, 255 * 64 * 8, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_HKDF_KEY_GEN, { 160, 224, CKF_GEN }, 1, SFTKFIPSNone }, + { CKM_HKDF_KEY_GEN, { 256, 512, CKF_GEN }, 128, SFTKFIPSNone }, + /* ------------------ NIST 800-108 Key Derivations ------------------- */ + { CKM_SP800_108_COUNTER_KDF, { 0, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_SP800_108_FEEDBACK_KDF, { 0, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_SP800_108_DOUBLE_PIPELINE_KDF, { 0, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone }, + /* --------------------IPSEC ----------------------- */ + { CKM_NSS_IKE_PRF_PLUS_DERIVE, { 8, 255 * 64, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_NSS_IKE_PRF_DERIVE, { 8, 64, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_NSS_IKE1_PRF_DERIVE, { 8, 64, CKF_KDF }, 1, SFTKFIPSNone }, + { CKM_NSS_IKE1_APP_B_PRF_DERIVE, { 8, 255 * 64, CKF_KDF }, 1, SFTKFIPSNone }, + /* ------------------ PBE Key Derivations ------------------- */ + { CKM_PKCS5_PBKD2, { 1, 256, CKF_GEN }, 1, SFTKFIPSNone }, + { CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN, { 224, 224, CKF_GEN }, 1, SFTKFIPSNone }, + { CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN, { 256, 256, CKF_GEN }, 1, SFTKFIPSNone }, + { CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN, { 384, 384, CKF_GEN }, 1, SFTKFIPSNone }, + { CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN, { 512, 512, CKF_GEN }, 1, SFTKFIPSNone } +}; +const int SFTK_NUMBER_FIPS_ALGORITHMS = PR_ARRAY_SIZE(sftk_fips_mechs); diff --git a/lib/softoken/fipstokn.c b/lib/softoken/fipstokn.c index 1dabc59e2..43e8c3847 100644 --- a/lib/softoken/fipstokn.c +++ b/lib/softoken/fipstokn.c @@ -301,10 +301,11 @@ static CK_FUNCTION_LIST sftk_fipsTable_v2 = { static CK_INTERFACE fips_interfaces[] = { { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_fipsTable, NSS_INTERFACE_FLAGS }, { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_fipsTable_v2, NSS_INTERFACE_FLAGS }, - { (CK_UTF8CHAR_PTR) "Vendor NSS Module Interface", &sftk_module_funcList, NSS_INTERFACE_FLAGS } + { (CK_UTF8CHAR_PTR) "Vendor NSS Module Interface", &sftk_module_funcList, NSS_INTERFACE_FLAGS }, + { (CK_UTF8CHAR_PTR) "Vendor NSS FIPS Interface", &sftk_fips_funcList, NSS_INTERFACE_FLAGS } }; /* must match the count of interfaces in fips_interfaces above*/ -#define FIPS_INTERFACE_COUNT 3 +#define FIPS_INTERFACE_COUNT 4 /* CKO_NOT_A_KEY can be any object class that's not a key object. */ #define CKO_NOT_A_KEY CKO_DATA diff --git a/lib/softoken/pkcs11.c b/lib/softoken/pkcs11.c index eba27d208..3f49333f8 100644 --- a/lib/softoken/pkcs11.c +++ b/lib/softoken/pkcs11.c @@ -145,16 +145,27 @@ CK_NSS_MODULE_FUNCTIONS sftk_module_funcList = { NSC_ModuleDBFunc }; +static CK_RV +nsc_NSSGetFIPSStatus(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ULONG ulOperationType, + CK_ULONG *pulFIPSStatus); +CK_NSS_FIPS_FUNCTIONS sftk_fips_funcList = { + { 1, 0 }, + nsc_NSSGetFIPSStatus +}; + /* * Array is orderd by default first */ static CK_INTERFACE nss_interfaces[] = { { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_funcList, NSS_INTERFACE_FLAGS }, { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_funcList_v2, NSS_INTERFACE_FLAGS }, - { (CK_UTF8CHAR_PTR) "Vendor NSS Module Interface", &sftk_module_funcList, NSS_INTERFACE_FLAGS } + { (CK_UTF8CHAR_PTR) "Vendor NSS Module Interface", &sftk_module_funcList, NSS_INTERFACE_FLAGS }, + { (CK_UTF8CHAR_PTR) "Vendor NSS FIPS Interface", &sftk_fips_funcList, NSS_INTERFACE_FLAGS } }; /* must match the count of interfaces in nss_interfaces above */ -#define NSS_INTERFACE_COUNT 3 +#define NSS_INTERFACE_COUNT 4 /* List of DES Weak Keys */ typedef unsigned char desKey[8]; @@ -3849,50 +3860,10 @@ CK_RV sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op) { CK_ULONG i; - CK_FLAGS flags; + CK_FLAGS flags = sftk_AttributeToFlags(op); - switch (op) { - case CKA_ENCRYPT: - flags = CKF_ENCRYPT; - break; - case CKA_DECRYPT: - flags = CKF_DECRYPT; - break; - case CKA_WRAP: - flags = CKF_WRAP; - break; - case CKA_UNWRAP: - flags = CKF_UNWRAP; - break; - case CKA_SIGN: - flags = CKF_SIGN; - break; - case CKA_SIGN_RECOVER: - flags = CKF_SIGN_RECOVER; - break; - case CKA_VERIFY: - flags = CKF_VERIFY; - break; - case CKA_VERIFY_RECOVER: - flags = CKF_VERIFY_RECOVER; - break; - case CKA_DERIVE: - flags = CKF_DERIVE; - break; - case CKA_NSS_MESSAGE | CKA_ENCRYPT: - flags = CKF_MESSAGE_ENCRYPT; - break; - case CKA_NSS_MESSAGE | CKA_DECRYPT: - flags = CKF_MESSAGE_DECRYPT; - break; - case CKA_NSS_MESSAGE | CKA_SIGN: - flags = CKF_MESSAGE_SIGN; - break; - case CKA_NSS_MESSAGE | CKA_VERIFY: - flags = CKF_MESSAGE_VERIFY; - break; - default: - return CKR_ARGUMENTS_BAD; + if (flags == 0) { + return CKR_ARGUMENTS_BAD; } for (i = 0; i < mechanismCount; i++) { if (type == mechanisms[i].type) { @@ -4625,6 +4596,8 @@ NSC_CreateObject(CK_SESSION_HANDLE hSession, if (object == NULL) { return CKR_HOST_MEMORY; } + object->isFIPS = PR_FALSE; /* if we created the object on the fly, + * it's not a FIPS object */ /* * load the template values into the object @@ -5298,3 +5271,106 @@ NSC_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, return CKR_FUNCTION_NOT_SUPPORTED; } + +static CK_RV +nsc_NSSGetFIPSStatus(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ULONG ulOperationType, + CK_ULONG *pulFIPSStatus) +{ + CK_ULONG sessionState = CKS_NSS_UNINITIALIZED; + CK_ULONG objectState = CKS_NSS_UNINITIALIZED; + PRBool needSession = PR_FALSE; + PRBool needObject = PR_FALSE; + SFTKSession *session; + SFTKObject *object; + + *pulFIPSStatus = CKS_NSS_FIPS_NOT_OK; + + /* first determine what we need to look up */ + switch (ulOperationType) { + case CKT_NSS_SESSION_CHECK: + case CKT_NSS_SESSION_LAST_CHECK: + needSession = PR_TRUE; + needObject = PR_FALSE; + break; + case CKT_NSS_OBJECT_CHECK: + needSession = PR_FALSE; + needObject = PR_TRUE; + break; + case CKT_NSS_BOTH_CHECK: + needSession = PR_TRUE; + needObject = PR_TRUE; + break; + default: + return CKR_ARGUMENTS_BAD; + } + + /* we always need the session handle, the object handle is only + * meaningful if there is a session */ + session = sftk_SessionFromHandle(hSession); + if (!session) { + return CKR_SESSION_HANDLE_INVALID; + } + if (needSession) { + if (CKT_NSS_SESSION_LAST_CHECK == ulOperationType) { + sessionState = session->lastOpWasFIPS ? CKS_NSS_FIPS_OK : CKS_NSS_FIPS_NOT_OK; + } else { + if (session->enc_context) { + sessionState = session->enc_context->isFIPS ? CKS_NSS_FIPS_OK : CKS_NSS_FIPS_NOT_OK; + } + if (sessionState != CKS_NSS_FIPS_NOT_OK && session->hash_context) { + sessionState = session->hash_context->isFIPS ? CKS_NSS_FIPS_OK : CKS_NSS_FIPS_NOT_OK; + } + /* sessionState is set to CKS_NSS_UNINITIALIZED if neither + * context exists */ + } + } + + if (needObject) { + object = sftk_ObjectFromHandle(hObject, session); + if (!object) { + sftk_FreeSession(session); + return CKR_OBJECT_HANDLE_INVALID; + } + objectState = object->isFIPS ? CKS_NSS_FIPS_OK : CKS_NSS_FIPS_NOT_OK; + sftk_FreeObject(object); + } + + sftk_FreeSession(session); + + /* If we didn't fetch the state, then it is uninitialized. + * The session state can also be uninitialized if there are no active + * crypto operations on the session. Turns out the rules for combining + * the states are the same whether or not the state was uninitialzed + * because we didn't fetch it or because there wasn't a state to fetch. + */ + + /* if the object State is uninitialized, return the state of the session. */ + if (objectState == CKS_NSS_UNINITIALIZED) { + /* if they are both uninitalized, return CKS_FIPS_NOT_OK */ + if (sessionState == CKS_NSS_UNINITIALIZED) { + /* *pulFIPSStatus already set to CKS_FIPS_NOT_OK */ + return CKR_OK; + } + *pulFIPSStatus = sessionState; + return CKR_OK; + } + /* objectState is initialized, if sessionState is uninitialized, we can + * just return objectState */ + if (sessionState == CKS_NSS_UNINITIALIZED) { + *pulFIPSStatus = objectState; + return CKR_OK; + } + + /* they are are not equal, one must be CKS_FIPS_NOT_OK, so we return that + * value CKS_FIPS_NOT_OK */ + if (objectState != sessionState) { + /* *pulFIPSStatus already set to CKS_FIPS_NOT_OK */ + return CKR_OK; + } + + /* objectState and sessionState or the same, so we can return either */ + *pulFIPSStatus = sessionState; + return CKR_OK; +} diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c index 977880ed2..c3216b3fd 100644 --- a/lib/softoken/pkcs11c.c +++ b/lib/softoken/pkcs11c.c @@ -400,6 +400,7 @@ void sftk_TerminateOp(SFTKSession *session, SFTKContextType ctype, SFTKSessionContext *context) { + session->lastOpWasFIPS = context->isFIPS; sftk_FreeContext(context); sftk_SetContextByType(session, ctype, NULL); } @@ -413,7 +414,8 @@ sftk_TerminateOp(SFTKSession *session, SFTKContextType ctype, * all need to do at the beginning. This is done here. */ CK_RV -sftk_InitGeneric(SFTKSession *session, SFTKSessionContext **contextPtr, +sftk_InitGeneric(SFTKSession *session, CK_MECHANISM *pMechanism, + SFTKSessionContext **contextPtr, SFTKContextType ctype, SFTKObject **keyPtr, CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr, CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation) @@ -435,7 +437,9 @@ sftk_InitGeneric(SFTKSession *session, SFTKSessionContext **contextPtr, } /* make sure it's a valid key for this operation */ - if (((key->objclass != CKO_SECRET_KEY) && (key->objclass != pubKeyType)) || !sftk_isTrue(key, operation)) { + if (((key->objclass != CKO_SECRET_KEY) && + (key->objclass != pubKeyType)) || + !sftk_isTrue(key, operation)) { sftk_FreeObject(key); return CKR_KEY_TYPE_INCONSISTENT; } @@ -473,7 +477,8 @@ sftk_InitGeneric(SFTKSession *session, SFTKSessionContext **contextPtr, context->key = key; context->blockSize = 0; context->maxLen = 0; - + context->isFIPS = sftk_operationIsFIPS(session->slot, pMechanism, + operation, key); *contextPtr = context; return CKR_OK; } @@ -813,8 +818,10 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, if (session == NULL) return CKR_SESSION_HANDLE_INVALID; - crv = sftk_InitGeneric(session, &context, contextType, &key, hKey, &key_type, - isEncrypt ? CKO_PUBLIC_KEY : CKO_PRIVATE_KEY, keyUsage); + crv = sftk_InitGeneric(session, pMechanism, &context, contextType, &key, + hKey, &key_type, + isEncrypt ? CKO_PUBLIC_KEY : CKO_PRIVATE_KEY, + keyUsage); if (crv != CKR_OK) { sftk_FreeSession(session); @@ -1900,7 +1907,8 @@ NSC_DigestInit(CK_SESSION_HANDLE hSession, session = sftk_SessionFromHandle(hSession); if (session == NULL) return CKR_SESSION_HANDLE_INVALID; - crv = sftk_InitGeneric(session, &context, SFTK_HASH, NULL, 0, NULL, 0, 0); + crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_HASH, + NULL, 0, NULL, 0, CKA_DIGEST); if (crv != CKR_OK) { sftk_FreeSession(session); return crv; @@ -2766,8 +2774,8 @@ NSC_SignInit(CK_SESSION_HANDLE hSession, session = sftk_SessionFromHandle(hSession); if (session == NULL) return CKR_SESSION_HANDLE_INVALID; - crv = sftk_InitGeneric(session, &context, SFTK_SIGN, &key, hKey, &key_type, - CKO_PRIVATE_KEY, CKA_SIGN); + crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_SIGN, &key, + hKey, &key_type, CKO_PRIVATE_KEY, CKA_SIGN); if (crv != CKR_OK) { sftk_FreeSession(session); return crv; @@ -3565,8 +3573,8 @@ NSC_VerifyInit(CK_SESSION_HANDLE hSession, session = sftk_SessionFromHandle(hSession); if (session == NULL) return CKR_SESSION_HANDLE_INVALID; - crv = sftk_InitGeneric(session, &context, SFTK_VERIFY, &key, hKey, &key_type, - CKO_PUBLIC_KEY, CKA_VERIFY); + crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY, &key, + hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY); if (crv != CKR_OK) { sftk_FreeSession(session); return crv; @@ -3894,7 +3902,7 @@ NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession, session = sftk_SessionFromHandle(hSession); if (session == NULL) return CKR_SESSION_HANDLE_INVALID; - crv = sftk_InitGeneric(session, &context, SFTK_VERIFY_RECOVER, + crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY_RECOVER, &key, hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY_RECOVER); if (crv != CKR_OK) { sftk_FreeSession(session); @@ -6536,6 +6544,9 @@ NSC_UnwrapKey(CK_SESSION_HANDLE hSession, return CKR_SESSION_HANDLE_INVALID; } + /* mark the key as FIPS if the previous operation was all FIPS */ + key->isFIPS = session->lastOpWasFIPS; + /* * handle the base object stuff */ @@ -7006,6 +7017,16 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_SESSION_HANDLE hSession, if (saltKey == NULL) { return CKR_KEY_HANDLE_INVALID; } + /* if the base key is not fips, but the salt key is, the + * resulting key can be fips */ + if (isFIPS && (key->isFIPS == 0) && (saltKey->isFIPS == 1)) { + CK_MECHANISM mech; + mech.mechanism = CKM_HKDF_DERIVE; + mech.pParameter = params; + mech.ulParameterLen = sizeof(*params); + key->isFIPS = sftk_operationIsFIPS(saltKey->slot, &mech, + CKA_DERIVE, saltKey); + } saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE); if (saltKey_att == NULL) { sftk_FreeObject(saltKey); @@ -7251,6 +7272,9 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession, sourceKey = sftk_ObjectFromHandle(hBaseKey, session); sftk_FreeSession(session); + /* is this eventually succeeds, lastOpWasFIPS will be set the resulting key's + * FIPS state below. */ + session->lastOpWasFIPS = PR_FALSE; if (sourceKey == NULL) { sftk_FreeObject(key); return CKR_KEY_HANDLE_INVALID; @@ -7265,6 +7289,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession, return CKR_KEY_HANDLE_INVALID; } } + key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_DERIVE, sourceKey); switch (mechanism) { /* get a public key from a private key. nsslowkey_ConvertToPublickey() @@ -8704,6 +8729,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession, } crv = sftk_handleObject(key, session); + session->lastOpWasFIPS = key->isFIPS; sftk_FreeSession(session); *phKey = key->handle; sftk_FreeObject(key); diff --git a/lib/softoken/pkcs11i.h b/lib/softoken/pkcs11i.h index 26efe158b..aa212f09e 100644 --- a/lib/softoken/pkcs11i.h +++ b/lib/softoken/pkcs11i.h @@ -191,6 +191,7 @@ struct SFTKObjectStr { SFTKSlot *slot; void *objectInfo; SFTKFree infoFree; + PRBool isFIPS; }; struct SFTKTokenObjectStr { @@ -266,6 +267,7 @@ struct SFTKSessionContextStr { PRBool rsa; /* is rsa */ PRBool doPad; /* use PKCS padding for block ciphers */ PRBool isXCBC; /* xcbc, use special handling in final */ + PRBool isFIPS; /* current operation is in FIPS mode */ unsigned int blockSize; /* blocksize for padding */ unsigned int padDataLength; /* length of the valid data in padbuf */ /** latest incomplete block of data for block cipher */ @@ -307,6 +309,7 @@ struct SFTKSessionStr { SFTKSessionContext *enc_context; SFTKSessionContext *hash_context; SFTKSessionContext *sign_context; + PRBool lastOpWasFIPS; SFTKObjectList *objects[1]; }; @@ -689,6 +692,7 @@ struct sftk_MACCtxStr { typedef struct sftk_MACCtxStr sftk_MACCtx; extern CK_NSS_MODULE_FUNCTIONS sftk_module_funcList; +extern CK_NSS_FIPS_FUNCTIONS sftk_fips_funcList; SEC_BEGIN_PROTOS @@ -795,6 +799,7 @@ extern void sftk_CleanupFreeLists(void); * Helper functions to handle the session crypto contexts */ extern CK_RV sftk_InitGeneric(SFTKSession *session, + CK_MECHANISM *pMechanism, SFTKSessionContext **contextPtr, SFTKContextType ctype, SFTKObject **keyPtr, CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr, @@ -944,7 +949,12 @@ char **NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args); const SECItem *sftk_VerifyDH_Prime(SECItem *dhPrime); /* check if dhSubPrime claims dhPrime is a safe prime. */ SECStatus sftk_IsSafePrime(SECItem *dhPrime, SECItem *dhSubPrime, PRBool *isSafe); - +/* map an operation Attribute to a Mechanism flag */ +CK_FLAGS sftk_AttributeToFlags(CK_ATTRIBUTE_TYPE op); +/* check the FIPS table to determine if this current operation is allowed by + * FIPS security policy */ +PRBool sftk_operationIsFIPS(SFTKSlot *slot, CK_MECHANISM *mech, + CK_ATTRIBUTE_TYPE op, SFTKObject *source); SEC_END_PROTOS #endif /* _PKCS11I_H_ */ diff --git a/lib/softoken/pkcs11u.c b/lib/softoken/pkcs11u.c index 4b314f4b8..43d4ba9d5 100644 --- a/lib/softoken/pkcs11u.c +++ b/lib/softoken/pkcs11u.c @@ -13,6 +13,18 @@ #include "prnetdb.h" /* for PR_ntohl */ #include "sftkdb.h" #include "softoken.h" +#include "secoid.h" + +#if !defined(NSS_FIPS_DISABLED) && defined(NSS_ENABLE_FIPS_INDICATORS) +/* this file should be supplied by the vendor and include all the + * algorithms which have Algorithm certs and have been reviewed by + * the lab. A blank file is included for the base so that FIPS mode + * will still be compiled and run, but FIPS indicators will always + * return PR_FALSE + */ +#include "fips_algorithms.h" +#define NSS_HAS_FIPS_INDICATORS 1 +#endif /* * ******************** Error mapping ******************************* @@ -1081,6 +1093,7 @@ sftk_NewObject(SFTKSlot *slot) object->handle = 0; object->next = object->prev = NULL; object->slot = slot; + object->isFIPS = sftk_isFIPS(slot->slotID); object->refCount = 1; sessObject->sessionList.next = NULL; @@ -1634,6 +1647,7 @@ sftk_CopyObject(SFTKObject *destObject, SFTKObject *srcObject) SFTKSessionObject *src_so = sftk_narrowToSessionObject(srcObject); unsigned int i; + destObject->isFIPS = srcObject->isFIPS; if (src_so == NULL) { return sftk_CopyTokenObject(destObject, srcObject); } @@ -1871,6 +1885,8 @@ sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication, session->info.slotID = slotID; session->info.ulDeviceError = 0; sftk_update_state(slot, session); + /* no ops completed yet, so the last one couldn't be a FIPS op */ + session->lastOpWasFIPS = PR_FALSE; return session; } @@ -1994,6 +2010,7 @@ sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle) goto loser; } object->slot = slot; + object->isFIPS = sftk_isFIPS(slot->slotID); object->objectInfo = NULL; object->infoFree = NULL; if (!hasLocks) { @@ -2122,3 +2139,250 @@ sftk_EncodeInteger(PRUint64 integer, CK_ULONG num_bits, CK_BBOOL littleEndian, } } } + +CK_FLAGS +sftk_AttributeToFlags(CK_ATTRIBUTE_TYPE op) +{ + CK_FLAGS flags = 0; + + switch (op) { + case CKA_ENCRYPT: + flags = CKF_ENCRYPT; + break; + case CKA_DECRYPT: + flags = CKF_DECRYPT; + break; + case CKA_WRAP: + flags = CKF_WRAP; + break; + case CKA_UNWRAP: + flags = CKF_UNWRAP; + break; + case CKA_SIGN: + flags = CKF_SIGN; + break; + case CKA_SIGN_RECOVER: + flags = CKF_SIGN_RECOVER; + break; + case CKA_VERIFY: + flags = CKF_VERIFY; + break; + case CKA_VERIFY_RECOVER: + flags = CKF_VERIFY_RECOVER; + break; + case CKA_DERIVE: + flags = CKF_DERIVE; + break; + /* fake attribute to select digesting */ + case CKA_DIGEST: + flags = CKF_DIGEST; + break; + case CKA_NSS_MESSAGE | CKA_ENCRYPT: + flags = CKF_MESSAGE_ENCRYPT; + break; + case CKA_NSS_MESSAGE | CKA_DECRYPT: + flags = CKF_MESSAGE_DECRYPT; + break; + case CKA_NSS_MESSAGE | CKA_SIGN: + flags = CKF_MESSAGE_SIGN; + break; + case CKA_NSS_MESSAGE | CKA_VERIFY: + flags = CKF_MESSAGE_VERIFY; + break; + default: + break; + } + return flags; +} + +#ifdef NSS_HAS_FIPS_INDICATORS +/* sigh, we probably need a version of this in secutil so that both + * softoken and NSS can use it */ +static SECOidTag +sftk_quickGetECCCurveOid(SFTKObject *source) +{ + SFTKAttribute *attribute = sftk_FindAttribute(source, CKA_EC_PARAMS); + unsigned char *encoded; + int len; + SECItem oid; + SECOidTag tag; + + if (attribute == NULL) { + return SEC_OID_UNKNOWN; + } + encoded = attribute->attrib.pValue; + len = attribute->attrib.ulValueLen; + if ((len < 2) || (encoded[0] != SEC_ASN1_OBJECT_ID) || + (len != encoded[1] + 2)) { + sftk_FreeAttribute(attribute); + return SEC_OID_UNKNOWN; + } + oid.data = encoded + 2; + oid.len = len - 2; + tag = SECOID_FindOIDTag(&oid); + sftk_FreeAttribute(attribute); + return tag; +} + +/* This function currently only returns valid lengths for + * FIPS approved ECC curves. If we want to make this generic + * in the future, that Curve determination can be done in + * the sftk_handleSpecial. Since it's currently only used + * in FIPS indicators, it's currently only compiled with + * the FIPS indicator code */ +static int +sftk_getKeyLength(SFTKObject *source) +{ + CK_KEY_TYPE keyType = CK_INVALID_HANDLE; + CK_ATTRIBUTE_TYPE keyAttribute; + CK_ULONG keyLength = 0; + SFTKAttribute *attribute; + CK_RV crv; + + /* If we don't have a key, then it doesn't have a length. + * this may be OK (say we are hashing). The mech info will + * sort this out because algorithms which expect no keys + * will accept zero length for the keys */ + if (source == NULL) { + return 0; + } + + crv = sftk_GetULongAttribute(source, CKA_KEY_TYPE, &keyType); + if (crv != CKR_OK) { + /* sometimes we're passed a data object, in that case the + * key length is CKA_VALUE, which is the default */ + keyType = CKK_INVALID_KEY_TYPE; + } + if (keyType == CKK_EC) { + SECOidTag curve = sftk_quickGetECCCurveOid(source); + switch (curve) { + case SEC_OID_CURVE25519: + /* change when we start algorithm testing on curve25519 */ + return 0; + case SEC_OID_SECG_EC_SECP256R1: + return 256; + case SEC_OID_SECG_EC_SECP384R1: + return 384; + case SEC_OID_SECG_EC_SECP521R1: + /* this is a lie, but it makes the table easier. We don't + * have to have a double entry for every ECC mechanism */ + return 512; + default: + break; + } + /* other curves aren't NIST approved, returning 0 will cause these + * curves to fail FIPS length criteria */ + return 0; + } + + switch (keyType) { + case CKK_RSA: + keyAttribute = CKA_MODULUS; + break; + case CKK_DSA: + case CKK_DH: + keyAttribute = CKA_PRIME; + break; + default: + keyAttribute = CKA_VALUE; + break; + } + attribute = sftk_FindAttribute(source, keyAttribute); + if (attribute) { + keyLength = attribute->attrib.ulValueLen * 8; + sftk_FreeAttribute(attribute); + } + return keyLength; +} + +/* + * handle specialized FIPS semantics that are too complicated to + * handle with just a table. NOTE: this means any additional semantics + * would have to be coded here before they can be added to the table */ +static PRBool +sftk_handleSpecial(SFTKSlot *slot, CK_MECHANISM *mech, + SFTKFIPSAlgorithmList *mechInfo, SFTKObject *source) +{ + switch (mechInfo->special) { + case SFTKFIPSDH: { + SECItem dhPrime; + const SECItem *dhSubPrime; + CK_RV crv = sftk_Attribute2SecItem(NULL, &dhPrime, + source, CKA_PRIME); + if (crv != CKR_OK) { + return PR_FALSE; + } + dhSubPrime = sftk_VerifyDH_Prime(&dhPrime); + SECITEM_ZfreeItem(&dhPrime, PR_FALSE); + return (dhSubPrime) ? PR_TRUE : PR_FALSE; + } + case SFTKFIPSNone: + return PR_FALSE; + case SFTKFIPSECC: + /* we've already handled the curve selection in the 'getlength' + * function */ + return PR_TRUE; + case SFTKFIPSAEAD: { + if (mech->ulParameterLen == 0) { + /* AEAD ciphers are only in FIPS mode if we are using the + * MESSAGE interface. This takes an empty parameter + * in the init function */ + return PR_TRUE; + } + return PR_FALSE; + } + default: + break; + } + /* if we didn't understand the special processing, mark it non-fips */ + return PR_FALSE; +} +#endif + +PRBool +sftk_operationIsFIPS(SFTKSlot *slot, CK_MECHANISM *mech, CK_ATTRIBUTE_TYPE op, + SFTKObject *source) +{ +#ifndef NSS_HAS_FIPS_INDICATORS + return PR_FALSE; +#else + int i; + CK_FLAGS opFlags; + CK_ULONG keyLength; + + /* handle all the quick stuff first */ + if (!sftk_isFIPS(slot->slotID)) { + return PR_FALSE; + } + if (source && !source->isFIPS) { + return PR_FALSE; + } + if (mech == NULL) { + return PR_FALSE; + } + + /* now get the calculated values */ + opFlags = sftk_AttributeToFlags(op); + if (opFlags == 0) { + return PR_FALSE; + } + keyLength = sftk_getKeyLength(source); + + /* check against our algorithm array */ + for (i = 0; i < SFTK_NUMBER_FIPS_ALGORITHMS; i++) { + SFTKFIPSAlgorithmList *mechs = &sftk_fips_mechs[i]; + /* if we match the number of records exactly, then we are an + * approved algorithm in the approved mode with an approved key */ + if (((mech->mechanism == mechs->type) && + (opFlags == (mechs->info.flags & opFlags)) && + (keyLength <= mechs->info.ulMaxKeySize) && + (keyLength >= mechs->info.ulMinKeySize) && + ((keyLength - mechs->info.ulMinKeySize) % mechs->step) == 0) && + ((mechs->special == SFTKFIPSNone) || + sftk_handleSpecial(slot, mech, mechs, source))) { + return PR_TRUE; + } + } + return PR_FALSE; +#endif +} diff --git a/lib/softoken/sftkmessage.c b/lib/softoken/sftkmessage.c index 76bc9b479..3e45445e8 100644 --- a/lib/softoken/sftkmessage.c +++ b/lib/softoken/sftkmessage.c @@ -72,8 +72,8 @@ sftk_MessageCryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, if (session == NULL) return CKR_SESSION_HANDLE_INVALID; - crv = sftk_InitGeneric(session, &context, contextType, &key, hKey, - &key_type, CKO_SECRET_KEY, operation); + crv = sftk_InitGeneric(session, pMechanism, &context, contextType, &key, + hKey, &key_type, CKO_SECRET_KEY, operation); if (crv != CKR_OK) { sftk_FreeSession(session); return crv; diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c index fd491f896..a3f0a776e 100644 --- a/lib/ssl/ssl3con.c +++ b/lib/ssl/ssl3con.c @@ -13876,6 +13876,41 @@ ssl3_DestroySSL3Info(sslSocket *ss) sslBuffer_Clear(&ss->ssl3.hs.greaseEchBuf); } +/* check if the current cipher spec is FIPS. We only need to + * check the contexts here, if the kea, prf or keys were not FIPS, + * that status would have been rolled up in the create context + * call */ +static PRBool +ssl_cipherSpecIsFips(ssl3CipherSpec *spec) +{ + if (!spec || !spec->cipherDef) { + return PR_FALSE; + } + + if (spec->cipherDef->type != type_aead) { + if (spec->keyMaterial.macContext == NULL) { + return PR_FALSE; + } + if (!PK11_ContextGetFIPSStatus(spec->keyMaterial.macContext)) { + return PR_FALSE; + } + } + if (!spec->cipherContext) { + return PR_FALSE; + } + return PK11_ContextGetFIPSStatus(spec->cipherContext); +} + +/* return true if the current operation is running in FIPS mode */ +PRBool +ssl_isFIPS(sslSocket *ss) +{ + if (!ssl_cipherSpecIsFips(ss->ssl3.crSpec)) { + return PR_FALSE; + } + return ssl_cipherSpecIsFips(ss->ssl3.cwSpec); +} + /* * parse the policy value for a single algorithm in a cipher_suite, * return TRUE if we disallow by the cipher suite by policy diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h index 1b7dfb107..f4264b834 100644 --- a/lib/ssl/sslimpl.h +++ b/lib/ssl/sslimpl.h @@ -1847,6 +1847,9 @@ PK11SymKey *ssl_unwrapSymKey(PK11SymKey *wrapKey, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize, CK_FLAGS keyFlags, void *pinArg); +/* determine if the current ssl connection is operating in FIPS mode */ +PRBool ssl_isFIPS(sslSocket *ss); + /* Experimental APIs. Remove when stable. */ SECStatus SSLExp_SetResumptionTokenCallback(PRFileDesc *fd, diff --git a/lib/ssl/sslinfo.c b/lib/ssl/sslinfo.c index 65aafe94a..d0f0701ae 100644 --- a/lib/ssl/sslinfo.c +++ b/lib/ssl/sslinfo.c @@ -110,6 +110,7 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) sidLen = PR_MIN(sidLen, sizeof inf.sessionID); inf.sessionIDLength = sidLen; memcpy(inf.sessionID, sid->u.ssl3.sessionID, sidLen); + inf.isFIPS = ssl_isFIPS(ss); } } diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h index 2bc151c63..f8210ccfb 100644 --- a/lib/ssl/sslt.h +++ b/lib/ssl/sslt.h @@ -373,6 +373,11 @@ typedef struct SSLChannelInfoStr { * with TLS 1.3 Encrypted Client Hello. */ PRBool echAccepted; + /* The following field was added in NSS 3.66 */ + /* This filed is PR_TRUE if the FIPS indicator is true for the + * current connection */ + PRBool isFIPS; + /* When adding new fields to this structure, please document the * NSS version in which they were added. */ } SSLChannelInfo; diff --git a/lib/util/pkcs11n.h b/lib/util/pkcs11n.h index 193985044..9a8126a82 100644 --- a/lib/util/pkcs11n.h +++ b/lib/util/pkcs11n.h @@ -269,6 +269,16 @@ #define CKM_TLS_PRF_GENERAL 0x80000373UL +/* FIPS Indicator defines */ +#define CKS_NSS_UNINITIALIZED 0xffffffffUL +#define CKS_NSS_FIPS_NOT_OK 0UL +#define CKS_NSS_FIPS_OK 1UL + +#define CKT_NSS_SESSION_CHECK 1UL +#define CKT_NSS_OBJECT_CHECK 2UL +#define CKT_NSS_BOTH_CHECK 3UL +#define CKT_NSS_SESSION_LAST_CHECK 4UL + typedef struct CK_NSS_JPAKEPublicValue { CK_BYTE *pGX; CK_ULONG ulGXLen; @@ -589,6 +599,18 @@ typedef struct CK_NSS_MODULE_FUNCTIONS { CK_NSS_ModuleDBFunc NSC_ModuleDBFunc; } CK_NSS_MODULE_FUNCTIONS; +/* FIPS Indicator Interface. This may move to the normal PKCS #11 table + * in the future. For now it's called "Vendor NSS FIPS Interface" */ +typedef CK_RV (*CK_NSS_GetFIPSStatus)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ULONG ulOperationType, + CK_ULONG *pulFIPSStatus); + +typedef struct CK_NSS_FIPS_FUNCTIONS { + CK_VERSION version; + CK_NSS_GetFIPSStatus NSC_NSSGetFIPSStatus; +} CK_NSS_FIPS_FUNCTIONS; + /* There was an inconsistency between the spec and the header file in defining * the CK_GCM_PARAMS structure. The authoritative reference is the header file, * but NSS used the spec when adding it to its own header. In V3 we've @@ -613,7 +635,7 @@ typedef CK_NSS_GCM_PARAMS CK_PTR CK_NSS_GCM_PARAMS_PTR; #define CK_INVALID_SESSION CK_INVALID_HANDLE #define CKR_KEY_PARAMS_INVALID 0x0000006B -/* use the old wrong CK_GCM_PARAMS is NSS_PCKS11_2_0_COMPAT is defined */ +/* use the old wrong CK_GCM_PARAMS if NSS_PCKS11_2_0_COMPAT is defined */ typedef struct CK_NSS_GCM_PARAMS CK_GCM_PARAMS; typedef CK_NSS_GCM_PARAMS CK_PTR CK_GCM_PARAMS_PTR; diff --git a/tests/ssl/ssl.sh b/tests/ssl/ssl.sh index 7e74397c9..acd4c8cda 100755 --- a/tests/ssl/ssl.sh +++ b/tests/ssl/ssl.sh @@ -115,9 +115,20 @@ ssl_init() NON_EC_SUITES=":0016:0032:0033:0038:0039:003B:003C:003D:0040:0041:0067:006A:006B" NON_EC_SUITES="${NON_EC_SUITES}:0084:009C:009D:009E:009F:00A2:00A3:CCAAcdeinvyz" + TLS13_SUITES=":1301:1302:1303" # List of cipher suites to test, including ECC cipher suites. CIPHER_SUITES="-c ${EC_SUITES}${NON_EC_SUITES}" + TLS13_CIPHER_SUITES="-c ${TLS13_SUITES}${EC_SUITES}${NON_EC_SUITES}" + + # in fips mode, turn off curve25519 until it's NIST approved + FIPS_OPTIONS="-I P256,P384,P521,FF2048,FF3072,FF4096,FF6144,FF8192" + + # in non-fips mode, tstclnt may run without the db password in some + # cases, but in fips mode it's always needed + CLIENT_PW="" + CLIENT_PW_FIPS="-w nss" + CLIENT_PW_NORMAL="" if [ "${OS_ARCH}" != "WINNT" ]; then ulimit -n 1000 # make sure we have enough file descriptors @@ -292,17 +303,30 @@ ignore_blank_lines() ######################################################################## ssl_cov() { - #verbose="-v" + verbose_save=${verbose} + verbose="-v" html_head "SSL Cipher Coverage $NORM_EXT - server $SERVER_MODE/client $CLIENT_MODE" testname="" + SAVE_SERVER_OPTIONS=${SERVER_OPTIONS} + if [ "${SERVER_MODE}" = "fips" ] ; then + SERVER_OPTIONS="${SERVER_OPTIONS} ${FIPS_OPTIONS}" + fi + SAVE_CLIENT_OPTIONS=${CLIENT_OPTIONS} + if [ "${CLIENT_MODE}" = "fips" ] ; then + CLIENT_OPTIONS="${CLIENT_OPTIONS} ${FIPS_OPTIONS}" + fi + start_selfserv $CIPHER_SUITES # Launch the server VMIN="ssl3" VMAX="tls1.1" - - ignore_blank_lines ${SSLCOV} | \ + # can't use a pipe here, because we may have to restart selfserv, and + # doing so hides the server pid environment variable in the subshell in + # cygwin, which means we can't kill selfserv at the end here. + SSL_COV_TMP=$(mktemp /tmp/ssl_cov.XXXXXX) + ignore_blank_lines ${SSLCOV} > ${SSL_COV_TMP} while read ectype testmax param testname do echo "${testname}" | grep "EXPORT" > /dev/null @@ -326,6 +350,31 @@ ssl_cov() if [ "$testmax" = "TLS12" ]; then VMAX="tls1.2" fi + if [ "$testmax" = "TLS13" ]; then + # if our selfserv can only do up to tls1.2 + # restart it so it can do tls1.3, This requires + # moving VMIN up to tls1.0 because you can't enable SSL3 and + # TLS 1.3. + if [ "$VMIN" = "ssl3" ]; then + SERVER_VMIN="tls1.0" + SERVER_VMAX="tls1.3" + kill_selfserv + start_selfserv ${TLS13_CIPHER_SUITES} + unset SERVER_VMIN + unset SERVER_VMAX + VMIN="tls1.0" + fi + VMAX="tls1.3" + fi + # if we are testing ssl3 and our server can only do down to tls1.1, + # restart it to enable ssl3 + if [ "$VMAX" = "ssl3" -a "$VMIN" = "tls1.1" ]; then + kill_selfserv + start_selfserv $CIPHER_SUITES + VMIN="ssl3" + fi + + echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} \\" echo " -f -d ${P_R_CLIENTDIR} $verbose -w nss < ${REQUEST_FILE}" @@ -339,8 +388,12 @@ ssl_cov() rm ${TMP}/$HOST.tmp.$$ 2>/dev/null html_msg $ret 0 "${testname}" \ "produced a returncode of $ret, expected is 0" - done + done < ${SSL_COV_TMP} + rm -f ${SSL_COV_TMP} + SERVER_OPTIONS=${SAVE_SERVER_OPTIONS} + CLIENT_OPTIONS=${SAVE_CLIENT_OPTIONS} + verbose=${verbose_save} kill_selfserv html "</TABLE><BR>" } @@ -469,10 +522,6 @@ ssl_stapling_sub() echo "$SCRIPTNAME: skipping $testname for $NORM_EXT" return 0 fi - if [ "$SERVER_MODE" = "fips" -o "$CLIENT_MODE" = "fips" ] ; then - echo "$SCRIPTNAME: skipping $testname (non-FIPS only)" - return 0 - fi SAVE_SERVER_OPTIONS=${SERVER_OPTIONS} SERVER_OPTIONS="${SERVER_OPTIONS} ${SO}" @@ -485,10 +534,10 @@ ssl_stapling_sub() start_selfserv echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f -d ${P_R_CLIENTDIR} $verbose ${CLIENT_OPTIONS} \\" - echo " -c v -T -O -F -M 1 -V ssl3:tls1.2 < ${REQUEST_FILE}" + echo " -c v -T -O -F -M 1 -V ssl3:tls1.2 ${CLIENT_PW} < ${REQUEST_FILE}" rm ${TMP}/$HOST.tmp.$$ 2>/dev/null ${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f ${CLIENT_OPTIONS} \ - -d ${P_R_CLIENTDIR} $verbose -c v -T -O -F -M 1 -V ssl3:tls1.2 < ${REQUEST_FILE} \ + -d ${P_R_CLIENTDIR} $verbose -c v -T -O -F -M 1 -V ssl3:tls1.2 ${CLIENT_PW} < ${REQUEST_FILE} \ >${TMP}/$HOST.tmp.$$ 2>&1 ret=$? cat ${TMP}/$HOST.tmp.$$ @@ -518,10 +567,6 @@ ssl_stapling_stress() echo "$SCRIPTNAME: skipping $testname for $NORM_EXT" return 0 fi - if [ "$SERVER_MODE" = "fips" -o "$CLIENT_MODE" = "fips" ] ; then - echo "$SCRIPTNAME: skipping $testname (non-FIPS only)" - return 0 - fi SAVE_SERVER_OPTIONS=${SERVER_OPTIONS} SERVER_OPTIONS="${SERVER_OPTIONS} ${SO}" @@ -592,11 +637,6 @@ ssl_signed_cert_timestamps() testname="ssl_signed_cert_timestamps" value=0 - if [ "$SERVER_MODE" = "fips" -o "$CLIENT_MODE" = "fips" ] ; then - echo "$SCRIPTNAME: skipping $testname (non-FIPS only)" - return 0 - fi - echo "${testname}" start_selfserv @@ -604,10 +644,10 @@ ssl_signed_cert_timestamps() # Since we don't have server-side support, this test only covers advertising the # extension in the client hello. echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f -d ${P_R_CLIENTDIR} $verbose ${CLIENT_OPTIONS} \\" - echo " -U -V tls1.0:tls1.2 < ${REQUEST_FILE}" + echo " -U -V tls1.0:tls1.2 ${CLIENT_PW} < ${REQUEST_FILE}" rm ${TMP}/$HOST.tmp.$$ 2>/dev/null ${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f ${CLIENT_OPTIONS} \ - -d ${P_R_CLIENTDIR} $verbose -U -V tls1.0:tls1.2 < ${REQUEST_FILE} \ + -d ${P_R_CLIENTDIR} $verbose -U -V tls1.0:tls1.2 ${CLIENT_PW} < ${REQUEST_FILE} \ >${TMP}/$HOST.tmp.$$ 2>&1 ret=$? cat ${TMP}/$HOST.tmp.$$ @@ -652,7 +692,7 @@ ssl_stress() start_selfserv `echo "$sparam" | sed -e 's,_, ,g'` if [ "`uname -n`" = "sjsu" ] ; then - echo "debugging disapering selfserv... ps -ef | grep selfserv" + echo "debugging disappearing selfserv... ps -ef | grep selfserv" ps -ef | grep selfserv fi @@ -1275,27 +1315,22 @@ ssl_dtls() testname="ssl_dtls" value=0 - if [ "$SERVER_MODE" = "fips" -o "$CLIENT_MODE" = "fips" ] ; then - echo "$SCRIPTNAME: skipping $testname (non-FIPS only)" - return 0 - fi - echo "${testname}" - echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f -d ${P_R_SERVERDIR} $verbose ${SERVER_OPTIONS} \\" - echo " -U -V tls1.1:tls1.2 -P server -Q < ${REQUEST_FILE} &" + echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f ${SERVER_OPTIONS} \\" + echo " -d ${P_R_SERVERDIR} $verbose -U -V tls1.1:tls1.2 -P server -n ${HOSTADDR} -w nss < ${REQUEST_FILE} &" - ${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f ${SERVER_OPTIONS} \ - -d ${P_R_SERVERDIR} $verbose -U -V tls1.1:tls1.2 -P server -n ${HOSTADDR} -w nss < ${REQUEST_FILE} 2>&1 & + (sleep 2; cat ${REQUEST_FILE}) | ${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f ${SERVER_OPTIONS} \ + -d ${P_R_SERVERDIR} $verbose -U -V tls1.1:tls1.2 -P server -n ${HOSTADDR} -w nss 2>&1 & PID=$! sleep 1 - echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f -d ${P_R_CLIENTDIR} $verbose ${CLIENT_OPTIONS} \\" - echo " -U -V tls1.1:tls1.2 -P client -Q < ${REQUEST_FILE}" + echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f ${CLIENT_OPTIONS} \\" + echo " -d ${P_R_CLIENTDIR} $verbose -U -V tls1.1:tls1.2 -P client -Q ${CLIENT_PW} < ${REQUEST_FILE}" ${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f ${CLIENT_OPTIONS} \ - -d ${P_R_CLIENTDIR} $verbose -U -V tls1.1:tls1.2 -P client -Q < ${REQUEST_FILE} 2>&1 + -d ${P_R_CLIENTDIR} $verbose -U -V tls1.1:tls1.2 -P client -Q ${CLIENT_PW} < ${REQUEST_FILE} 2>&1 ret=$? html_msg $ret $value "${testname}" \ "produced a returncode of $ret, expected is $value" @@ -1310,11 +1345,6 @@ ssl_dtls() ######################################################################### ssl_scheme() { - if [ "$SERVER_MODE" = "fips" -o "$CLIENT_MODE" = "fips" ] ; then - echo "$SCRIPTNAME: skipping $testname (non-FIPS only)" - return 0 - fi - html_head "SSL SCHEME $NORM_EXT - server $SERVER_MODE/client $CLIENT_MODE" NO_ECC_CERTS=1 @@ -1327,9 +1357,9 @@ ssl_scheme() start_selfserv -V tls1.2:tls1.2 -J "$sscheme" echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f -d ${P_R_CLIENTDIR} $verbose ${CLIENT_OPTIONS} \\" - echo " -V tls1.2:tls1.2 -J "$cscheme" < ${REQUEST_FILE}" + echo " -V tls1.2:tls1.2 -J "$cscheme" ${CLIENT_PW} < ${REQUEST_FILE}" ${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f ${CLIENT_OPTIONS} \ - -d ${P_R_CLIENTDIR} $verbose -V tls1.2:tls1.2 -J "$cscheme" < ${REQUEST_FILE} 2>&1 + -d ${P_R_CLIENTDIR} $verbose -V tls1.2:tls1.2 -J "$cscheme" ${CLIENT_PW} < ${REQUEST_FILE} 2>&1 ret=$? # If both schemes include just one option and those options don't # match, then the test should fail; otherwise, assume that it works. @@ -1355,11 +1385,6 @@ ssl_scheme() ######################################################################### ssl_scheme_stress() { - if [ "$SERVER_MODE" = "fips" -o "$CLIENT_MODE" = "fips" ] ; then - echo "$SCRIPTNAME: skipping $testname (non-FIPS only)" - return 0 - fi - html_head "SSL SCHEME $NORM_EXT - server $SERVER_MODE/client $CLIENT_MODE" NO_ECC_CERTS=1 @@ -1372,9 +1397,9 @@ ssl_scheme_stress() start_selfserv -V tls1.2:tls1.2 -J "$sscheme" echo "strsclnt -4 -q -p ${PORT} -d ${P_R_CLIENTDIR} $verbose ${CLIENT_OPTIONS} \\" - echo " -V tls1.2:tls1.2 -J "$cscheme" ${HOSTADDR} < ${REQUEST_FILE}" + echo " -V tls1.2:tls1.2 -J "$cscheme" ${HOSTADDR} ${CLIENT_PW} < ${REQUEST_FILE}" ${PROFTOOL} ${BINDIR}/strsclnt -4 -q -p ${PORT} ${CLIENT_OPTIONS} \ - -d ${P_R_CLIENTDIR} $verbose -V tls1.2:tls1.2 -J "$cscheme" ${HOSTADDR} < ${REQUEST_FILE} 2>&1 + -d ${P_R_CLIENTDIR} $verbose -V tls1.2:tls1.2 -J "$cscheme" ${HOSTADDR} ${CLIENT_PW} < ${REQUEST_FILE} 2>&1 ret=$? # If both schemes include just one option and those options don't # match, then the test should fail; otherwise, assume that it works. @@ -1411,9 +1436,9 @@ ssl_exporter() start_selfserv -V tls1.2:tls1.2 -x "$exporter" echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f -d ${P_R_CLIENTDIR} $verbose ${CLIENT_OPTIONS} \\" - echo " -V tls1.2:tls1.2 -x $exporter < ${REQUEST_FILE}" + echo " -V tls1.2:tls1.2 -x $exporter ${CLIENT_PW} < ${REQUEST_FILE}" ${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f ${CLIENT_OPTIONS} \ - -d ${P_R_CLIENTDIR} $verbose -V tls1.2:tls1.2 -x "$exporter" < ${REQUEST_FILE} 2>&1 > client.out + -d ${P_R_CLIENTDIR} $verbose -V tls1.2:tls1.2 -x "$exporter" ${CLIENT_PW} < ${REQUEST_FILE} 2>&1 > client.out kill_selfserv diff <(LC_ALL=C grep -A1 "^ *Keying Material:" server.out) \ <(LC_ALL=C grep -A1 "^ *Keying Material:" client.out) @@ -1629,9 +1654,11 @@ ssl_run_tests() case "${CLIENT_MODE}" in "normal") CLIENT_OPTIONS= + CLIENT_PW=${CLIENT_PW_NORMAL} ;; "fips") - SERVER_OPTIONS= + CLIENT_OPTIONS= + CLIENT_PW=${CLIENT_PW_FIPS} ssl_set_fips client on ;; *) diff --git a/tests/ssl/sslcov.txt b/tests/ssl/sslcov.txt index 93f247b96..ca79a5e09 100644 --- a/tests/ssl/sslcov.txt +++ b/tests/ssl/sslcov.txt @@ -66,6 +66,9 @@ noECC TLS12 :009E TLS12_DHE_RSA_WITH_AES_128_GCM_SHA256 noECC TLS12 :00A2 TLS12_DHE_DSS_WITH_AES_128_GCM_SHA256 noECC TLS12 :CCAA TLS12_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + noECC TLS13 :1301 TLS13_DHE_WITH_AES_128_GCM_SHA256 + noECC TLS13 :1302 TLS13_DHE_WITH_AES_256_GCM_SHA384 + noECC TLS13 :1303 TLS13_DHE_WITH_CHACHA20_POLY1305_SHA256 # # ECC ciphers (TLS) # @@ -146,3 +149,7 @@ # ECC TLS12 :C02F TLS12_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - RSA-PSS ECC TLS12 :C030 TLS12_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - RSA-PSS +# test TLS 1.3 + ECC TLS13 :1301 TLS13_ECDHE_WITH_AES_128_GCM_SHA256 + ECC TLS13 :1302 TLS13_ECDHE_WITH_AES_256_GCM_SHA384 + ECC TLS13 :1303 TLS13_ECDHE_WITH_CHACHA20_POLY1305_SHA256 |