Skip to content

Commit

Permalink
Bugzilla Bug 298506: implemented FIPS 140-2 Security Level 2 audit
Browse files Browse the repository at this point in the history
requirements. r=glen.beasley.
Modified Files:
	fipstokn.c pkcs11.c pkcs11c.c pkcs11i.h softoken.h softoknt.h
  • Loading branch information
wtchang%redhat.com committed May 5, 2006
1 parent df17ba2 commit 27e7398
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 29 deletions.
188 changes: 163 additions & 25 deletions security/nss/lib/softoken/fipstokn.c
Expand Up @@ -55,9 +55,17 @@
#include "pcert.h"
#include "pkcs11.h"
#include "pkcs11i.h"
#include "prenv.h"
#include "prprf.h"

#include <ctype.h>

#ifdef XP_UNIX
#define NSS_AUDIT_WITH_SYSLOG 1
#include <syslog.h>
#include <unistd.h>
#endif


/*
* ******************** Password Utilities *******************************
Expand Down Expand Up @@ -251,6 +259,58 @@ fips_login_if_key_object(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
return rv;
}

/**********************************************************************
*
* FIPS 140 auditable event logging
*
**********************************************************************/

PRBool sftk_audit_enabled = PR_FALSE;

/*
* Each audit record must have the following information:
* - Date and time of the event
* - Type of event
* - user (subject) identity
* - outcome (success or failure) of the event
* - process ID
* - name (ID) of the object
* - for changes to data (except for authentication data and CSPs), the new
* and old values of the data
* - for authentication attempts, the origin of the attempt (e.g., terminal
* identifier)
* - for assuming a role, the type of role, and the location of the request
*/
void
sftk_LogAuditMessage(NSSAuditSeverity severity, const char *msg)
{
#ifdef NSS_AUDIT_WITH_SYSLOG
SFTKSlot *slot = sftk_SlotFromID(FIPS_SLOT_ID, PR_FALSE);
const char *tokenLabel =
slot ? slot->tokDescription : sftk_getDefTokName(FIPS_SLOT_ID);
int level;

switch (severity) {
case NSS_AUDIT_ERROR:
level = LOG_ERR;
break;
case NSS_AUDIT_WARNING:
level = LOG_WARNING;
break;
default:
level = LOG_INFO;
break;
}
/* timestamp is provided by syslog in the message header */
/* tokenLabel points to a 32-byte label, which is not null-terminated */
syslog(level | LOG_USER /* facility */,
"%.32s[pid=%d uid=%d]: %s",
tokenLabel, (int)getpid(), (int)getuid(), msg);
#else
/* do nothing */
#endif
}


/**********************************************************************
*
Expand All @@ -268,12 +328,17 @@ PRBool nsf_init = PR_FALSE;

/* FC_Initialize initializes the PKCS #11 library. */
CK_RV FC_Initialize(CK_VOID_PTR pReserved) {
const char *envp;
CK_RV crv;

if (nsf_init) {
return CKR_CRYPTOKI_ALREADY_INITIALIZED;
}

if ((envp = PR_GetEnv("NSS_ENABLE_AUDIT")) != NULL) {
sftk_audit_enabled = (atoi(envp) == 1);
}

crv = nsc_CommonInitialize(pReserved, PR_TRUE);

/* not an 'else' rv can be set by either SFTK_LowInit or SFTK_SlotInit*/
Expand All @@ -288,6 +353,14 @@ CK_RV FC_Initialize(CK_VOID_PTR pReserved) {
if (crv != CKR_OK) {
nsc_CommonFinalize(NULL, PR_TRUE);
fatalError = PR_TRUE;
if (sftk_audit_enabled) {
char msg[128];
PR_snprintf(msg,sizeof msg,
"C_Initialize()=0x%08lX "
"self-test: cryptographic algorithm test failed",
(PRUint32)crv);
sftk_LogAuditMessage(NSS_AUDIT_ERROR, msg);
}
return crv;
}
nsf_init = PR_TRUE;
Expand Down Expand Up @@ -321,15 +394,7 @@ CK_RV FC_GetSlotList(CK_BBOOL tokenPresent,

/* FC_GetSlotInfo obtains information about a particular slot in the system. */
CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {

CK_RV crv;

crv = NSC_GetSlotInfo(slotID,pInfo);
if (crv != CKR_OK) {
return crv;
}

return CKR_OK;
return NSC_GetSlotInfo(slotID,pInfo);
}


Expand Down Expand Up @@ -369,17 +434,41 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
/* FC_InitToken initializes a token. */
CK_RV FC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin,
CK_ULONG usPinLen,CK_CHAR_PTR pLabel) {
return NSC_InitToken(slotID,pPin,usPinLen,pLabel);
CK_RV crv;

crv = NSC_InitToken(slotID,pPin,usPinLen,pLabel);
if (sftk_audit_enabled) {
char msg[128];
NSSAuditSeverity severity = (crv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
/* pLabel points to a 32-byte label, which is not null-terminated */
PR_snprintf(msg,sizeof msg,
"C_InitToken(slotID=%lu, pLabel=\"%.32s\")=0x%08lX",
(PRUint32)slotID,pLabel,(PRUint32)crv);
sftk_LogAuditMessage(severity, msg);
}
return crv;
}


/* FC_InitPIN initializes the normal user's PIN. */
CK_RV FC_InitPIN(CK_SESSION_HANDLE hSession,
CK_CHAR_PTR pPin, CK_ULONG ulPinLen) {
CK_RV rv;
SFTK_FIPSFATALCHECK();
if ((rv = sftk_newPinCheck(pPin,ulPinLen)) != CKR_OK) return rv;
return NSC_InitPIN(hSession,pPin,ulPinLen);
if (fatalError) return CKR_DEVICE_ERROR;
if ((rv = sftk_newPinCheck(pPin,ulPinLen)) == CKR_OK) {
rv = NSC_InitPIN(hSession,pPin,ulPinLen);
}
if (sftk_audit_enabled) {
char msg[128];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
PR_snprintf(msg,sizeof msg,
"C_InitPIN(hSession=%lu)=0x%08lX",
(PRUint32)hSession,(PRUint32)rv);
sftk_LogAuditMessage(severity, msg);
}
return rv;
}


Expand All @@ -388,9 +477,20 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
CK_RV FC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
CK_ULONG usOldLen, CK_CHAR_PTR pNewPin, CK_ULONG usNewLen) {
CK_RV rv;
if ((rv = sftk_fipsCheck()) != CKR_OK) return rv;
if ((rv = sftk_newPinCheck(pNewPin,usNewLen)) != CKR_OK) return rv;
return NSC_SetPIN(hSession,pOldPin,usOldLen,pNewPin,usNewLen);
if ((rv = sftk_fipsCheck()) == CKR_OK &&
(rv = sftk_newPinCheck(pNewPin,usNewLen)) == CKR_OK) {
rv = NSC_SetPIN(hSession,pOldPin,usOldLen,pNewPin,usNewLen);
}
if (sftk_audit_enabled) {
char msg[128];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
PR_snprintf(msg,sizeof msg,
"C_SetPIN(hSession=%lu)=0x%08lX",
(PRUint32)hSession,(PRUint32)rv);
sftk_LogAuditMessage(severity, msg);
}
return rv;
}

/* FC_OpenSession opens a session between an application and a token. */
Expand Down Expand Up @@ -435,30 +535,58 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
CK_RV FC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
CK_CHAR_PTR pPin, CK_ULONG usPinLen) {
CK_RV rv;
SFTK_FIPSFATALCHECK();
if (fatalError) return CKR_DEVICE_ERROR;
rv = NSC_Login(hSession,userType,pPin,usPinLen);
if (rv == CKR_OK)
isLoggedIn = PR_TRUE;
else if (rv == CKR_USER_ALREADY_LOGGED_IN)
{
isLoggedIn = PR_TRUE;

/* Provide FIPS PUB 140-1 power-up self-tests on demand. */
/* Provide FIPS PUB 140-2 power-up self-tests on demand. */
rv = sftk_fipsPowerUpSelfTest();
if (rv == CKR_OK)
return CKR_USER_ALREADY_LOGGED_IN;
rv = CKR_USER_ALREADY_LOGGED_IN;
else
fatalError = PR_TRUE;
}
if (sftk_audit_enabled) {
char msg[128];
NSSAuditSeverity severity;
if (fatalError) {
severity = NSS_AUDIT_ERROR;
PR_snprintf(msg,sizeof msg,
"C_Login(hSession=%lu, userType=%lu)=0x%08lX ",
"self-test: cryptographic algorithm test failed",
(PRUint32)hSession,(PRUint32)userType,(PRUint32)rv);
} else {
severity = (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
PR_snprintf(msg,sizeof msg,
"C_Login(hSession=%lu, userType=%lu)=0x%08lX",
(PRUint32)hSession,(PRUint32)userType,(PRUint32)rv);
}
sftk_LogAuditMessage(severity, msg);
}
return rv;
}

/* FC_Logout logs a user out from a token. */
CK_RV FC_Logout(CK_SESSION_HANDLE hSession) {
SFTK_FIPSCHECK();

rv = NSC_Logout(hSession);
isLoggedIn = PR_FALSE;
CK_RV rv;
if ((rv = sftk_fipsCheck()) == CKR_OK) {
rv = NSC_Logout(hSession);
isLoggedIn = PR_FALSE;
}
if (sftk_audit_enabled) {
char msg[128];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
PR_snprintf(msg,sizeof msg,
"C_Logout(hSession=%lu)=0x%08lX",
(PRUint32)hSession,(PRUint32)rv);
sftk_LogAuditMessage(severity, msg);
}
return rv;
}

Expand Down Expand Up @@ -982,13 +1110,23 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {

/* FC_GenerateRandom generates random data. */
CK_RV FC_GenerateRandom(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pRandomData, CK_ULONG usRandomLen) {
CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) {
CK_RV crv;

SFTK_FIPSFATALCHECK();
crv = NSC_GenerateRandom(hSession,pRandomData,usRandomLen);
crv = NSC_GenerateRandom(hSession,pRandomData,ulRandomLen);
if (crv != CKR_OK) {
fatalError = PR_TRUE;
if (sftk_audit_enabled) {
char msg[128];
PR_snprintf(msg,sizeof msg,
"C_GenerateRandom(hSession=%lu, pRandomData=%p, "
"ulRandomLen=%lu)=0x%08lX "
"self-test: continuous RNG test failed",
(PRUint32)hSession,pRandomData,
(PRUint32)ulRandomLen,(PRUint32)crv);
sftk_LogAuditMessage(NSS_AUDIT_ERROR, msg);
}
}
return crv;
}
Expand Down
24 changes: 21 additions & 3 deletions security/nss/lib/softoken/pkcs11.c
Expand Up @@ -2356,7 +2356,7 @@ sftk_getDefTokName(CK_SLOT_ID slotID)
case PRIVATE_KEY_SLOT_ID:
return "NSS Certificate DB ";
case FIPS_SLOT_ID:
return "NSS FIPS-140-1 Certificate DB ";
return "NSS FIPS 140-2 Certificate DB ";
default:
break;
}
Expand All @@ -2378,7 +2378,7 @@ sftk_getDefSlotName(CK_SLOT_ID slotID)
"NSS User Private Key and Certificate Services ";
case FIPS_SLOT_ID:
return
"Netscape FIPS-140-1 User Private Key Services ";
"NSS FIPS 140-2 User Private Key Services ";
default:
break;
}
Expand Down Expand Up @@ -2411,6 +2411,9 @@ sftk_SlotFromID(CK_SLOT_ID slotID, PRBool all)
{
SFTKSlot *slot;
int index = sftk_GetModuleIndex(slotID);
if (nscSlotHashTable[index] == NULL) {
return NULL;
}
slot = (SFTKSlot *)PL_HashTableLookupConst(nscSlotHashTable[index],
(void *)slotID);
/* cleared slots shouldn't 'show up' */
Expand Down Expand Up @@ -2982,6 +2985,14 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
if (!BLAPI_VerifySelf(NULL) ||
!BLAPI_SHVerify(SOFTOKEN_LIB_NAME, (PRFuncPtr) sftk_closePeer)) {
crv = CKR_DEVICE_ERROR; /* better error code? checksum error? */
if (sftk_audit_enabled) {
char msg[128];
PR_snprintf(msg,sizeof msg,
"C_Initialize()=0x%08lX "
"self-test: software/firmware integrity test failed",
(PRUint32)crv);
sftk_LogAuditMessage(NSS_AUDIT_ERROR, msg);
}
return crv;
}

Expand Down Expand Up @@ -3052,6 +3063,13 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
* don't clobber each other. */
if ((isFIPS && nsc_init) || (!isFIPS && nsf_init)) {
sftk_closePeer(isFIPS);
if (sftk_audit_enabled) {
if (isFIPS && nsc_init) {
sftk_LogAuditMessage(NSS_AUDIT_INFO, "enabled FIPS mode");
} else {
sftk_LogAuditMessage(NSS_AUDIT_INFO, "disabled FIPS mode");
}
}
}

for (i=0; i < paramStrings.token_count; i++) {
Expand Down Expand Up @@ -3581,7 +3599,7 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
handle = sftk_getKeyDB(slot);
if (handle == NULL) {
sftk_FreeSession(sp);
return CKR_PIN_LEN_RANGE;
return CKR_PIN_LEN_RANGE; /* XXX FIXME wrong return value */
}

if (slot->needLogin && sp->info.state != CKS_RW_USER_FUNCTIONS) {
Expand Down
11 changes: 11 additions & 0 deletions security/nss/lib/softoken/pkcs11c.c
Expand Up @@ -73,6 +73,7 @@

#include "pcert.h"
#include "ssl3prot.h" /* for SSL3_RANDOM_LENGTH */
#include "prprf.h"

#define __PASTE(x,y) x##y

Expand Down Expand Up @@ -3770,6 +3771,16 @@ CK_RV NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession,
sftk_FreeObject(publicKey);
NSC_DestroyObject(hSession,privateKey->handle);
sftk_FreeObject(privateKey);
if (sftk_audit_enabled) {
char msg[128];
PR_snprintf(msg,sizeof msg,
"C_GenerateKeyPair(hSession=%lu, "
"pMechanism->mechanism=0x%08lX)=0x%08lX "
"self-test: pair-wise consistency test failed",
(PRUint32)hSession,(PRUint32)pMechanism->mechanism,
(PRUint32)crv);
sftk_LogAuditMessage(NSS_AUDIT_ERROR, msg);
}
return crv;
}

Expand Down
3 changes: 2 additions & 1 deletion security/nss/lib/softoken/pkcs11i.h
Expand Up @@ -555,7 +555,7 @@ typedef struct sftk_parametersStr {

SEC_BEGIN_PROTOS

/* shared functions between PKCS11.c and SFTKFIPS.c */
/* shared functions between pkcs11.c and fipstokn.c */
extern int nsf_init;
extern CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS);
extern CK_RV nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS);
Expand Down Expand Up @@ -635,6 +635,7 @@ extern SFTKSession *sftk_SessionFromHandle(CK_SESSION_HANDLE handle);
extern void sftk_FreeSession(SFTKSession *session);
extern SFTKSession *sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify,
CK_VOID_PTR pApplication, CK_FLAGS flags);
extern const char *sftk_getDefTokName(CK_SLOT_ID slotID);
extern void sftk_update_state(SFTKSlot *slot,SFTKSession *session);
extern void sftk_update_all_states(SFTKSlot *slot);
extern void sftk_FreeContext(SFTKSessionContext *context);
Expand Down

0 comments on commit 27e7398

Please sign in to comment.