1b6f66
diff --git a/lib/pk11wrap/pk11pars.c b/lib/pk11wrap/pk11pars.c
1b6f66
--- a/lib/pk11wrap/pk11pars.c
1b6f66
+++ b/lib/pk11wrap/pk11pars.c
1b6f66
@@ -159,16 +159,20 @@ SECMOD_CreateModuleEx(const char *librar
1b6f66
     if (parameters) {
1b6f66
 	mod->libraryParams = PORT_ArenaStrdup(mod->arena,parameters);
1b6f66
     }
1b6f66
     if (config) {
1b6f66
 	/* XXX: Apply configuration */
f57139
     }
f57139
     mod->internal   = NSSUTIL_ArgHasFlag("flags","internal",nssc);
f57139
     mod->isFIPS     = NSSUTIL_ArgHasFlag("flags","FIPS",nssc);
f57139
+    /* if the system FIPS mode is enabled, force FIPS to be on */
f57139
+    if (SECMOD_GetSystemFIPSEnabled()) {
f57139
+	mod->isFIPS = PR_TRUE;
f57139
+    }
f57139
     mod->isCritical = NSSUTIL_ArgHasFlag("flags","critical",nssc);
f57139
     slotParams      = NSSUTIL_ArgGetParamValue("slotParams",nssc);
f57139
     mod->slotInfo   = NSSUTIL_ArgParseSlotInfo(mod->arena,slotParams,
1b6f66
 							&mod->slotInfoCount);
1b6f66
     if (slotParams) PORT_Free(slotParams);
1b6f66
     /* new field */
1b6f66
     mod->trustOrder  = NSSUTIL_ArgReadLong("trustOrder",nssc,
1b6f66
 					NSSUTIL_DEFAULT_TRUST_ORDER,NULL);
1b6f66
diff --git a/lib/pk11wrap/pk11util.c b/lib/pk11wrap/pk11util.c
1b6f66
--- a/lib/pk11wrap/pk11util.c
1b6f66
+++ b/lib/pk11wrap/pk11util.c
1b6f66
@@ -90,16 +90,35 @@ SECMOD_Shutdown()
1b6f66
 #endif
1b6f66
     if (secmod_PrivateModuleCount) {
1b6f66
     	PORT_SetError(SEC_ERROR_BUSY);
1b6f66
 	return SECFailure;
1b6f66
     }
f57139
     return SECSuccess;
f57139
 }
f57139
 
f57139
+int SECMOD_GetSystemFIPSEnabled(void) {
f57139
+#ifdef LINUX
f57139
+    FILE *f;
f57139
+    char d;
f57139
+    size_t size;
f57139
+
f57139
+    f = fopen("/proc/sys/crypto/fips_enabled", "r");
f57139
+    if (!f)
f57139
+        return 0;
f57139
+
f57139
+    size = fread(&d, 1, 1, f);
f57139
+    fclose(f);
f57139
+    if (size != 1)
f57139
+        return 0;
f57139
+    if (d == '1')
f57139
+        return 1;
f57139
+#endif
f57139
+    return 0;
f57139
+}
f57139
 
f57139
 /*
f57139
  * retrieve the internal module
1b6f66
  */
1b6f66
 SECMODModule *
1b6f66
 SECMOD_GetInternalModule(void)
1b6f66
 {
1b6f66
    return internalModule;
1b6f66
@@ -412,17 +431,17 @@ SECMOD_DeleteModule(const char *name, in
1b6f66
  */
1b6f66
 SECStatus
1b6f66
 SECMOD_DeleteInternalModule(const char *name) 
1b6f66
 {
1b6f66
     SECMODModuleList *mlp;
f57139
     SECMODModuleList **mlpp;
f57139
     SECStatus rv = SECFailure;
f57139
 
f57139
-    if (pendingModule) {
f57139
+    if (SECMOD_GetSystemFIPSEnabled() || pendingModule) {
f57139
 	PORT_SetError(SEC_ERROR_MODULE_STUCK);
f57139
 	return rv;
f57139
     }
1b6f66
     if (!moduleLock) {
1b6f66
     	PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1b6f66
 	return rv;
1b6f66
     }
1b6f66
 
1b6f66
@@ -883,17 +902,17 @@ SECMOD_DestroyModuleList(SECMODModuleLis
1b6f66
     SECMODModuleList *lp;
1b6f66
 
1b6f66
     for ( lp = list; lp != NULL; lp = SECMOD_DestroyModuleListElement(lp)) ;
1b6f66
 }
1b6f66
 
f57139
 PRBool
f57139
 SECMOD_CanDeleteInternalModule(void)
f57139
 {
f57139
-    return (PRBool) (pendingModule == NULL);
1b6f66
+    return (PRBool) ((pendingModule == NULL) && !SECMOD_GetSystemFIPSEnabled());
f57139
 }
f57139
 
f57139
 /*
1b6f66
  * check to see if the module has added new slots. PKCS 11 v2.20 allows for
1b6f66
  * modules to add new slots, but never remove them. Slots cannot be added 
1b6f66
  * between a call to C_GetSlotLlist(Flag, NULL, &count) and the subsequent
1b6f66
  * C_GetSlotList(flag, &data, &count) so that the array doesn't accidently
1b6f66
  * grow on the caller. It is permissible for the slots to increase between
1b6f66
diff --git a/lib/pk11wrap/secmodi.h b/lib/pk11wrap/secmodi.h
1b6f66
--- a/lib/pk11wrap/secmodi.h
1b6f66
+++ b/lib/pk11wrap/secmodi.h
1b6f66
@@ -108,17 +108,22 @@ SECStatus PBE_PK11ParamToAlgid(SECOidTag
1b6f66
 PK11SymKey *pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot,
1b6f66
 	CK_MECHANISM_TYPE type, SECItem *param, CK_KEY_TYPE keyType, 
1b6f66
 	int keySize, SECItem *keyId, CK_FLAGS opFlags, 
1b6f66
 	PK11AttrFlags attrFlags, void *wincx);
1b6f66
 
f57139
 CK_MECHANISM_TYPE pk11_GetPBECryptoMechanism(SECAlgorithmID *algid,
f57139
                    SECItem **param, SECItem *pwd, PRBool faulty3DES);
f57139
 
f57139
-
f57139
+/* Get the state of the system FIPS mode */
f57139
+/* NSS uses this to force FIPS mode if the system bit is on. Applications which
f57139
+ * use the SECMOD_CanDeleteInteral() to check to see if they can switch to or
f57139
+ * from FIPS mode will automatically be told that they can't swith out of FIPS
f57139
+ * mode */
f57139
+int SECMOD_GetSystemFIPSEnabled();
f57139
 
f57139
 extern void pk11sdr_Init(void);
f57139
 extern void pk11sdr_Shutdown(void);
1b6f66
 
1b6f66
 /*
1b6f66
  * Private to pk11wrap.
1b6f66
  */
1b6f66