diff options
Diffstat (limited to 'security/nss/lib/softoken')
26 files changed, 2437 insertions, 736 deletions
diff --git a/security/nss/lib/softoken/config.mk b/security/nss/lib/softoken/config.mk index 2e097c8a5..bc48130aa 100644 --- a/security/nss/lib/softoken/config.mk +++ b/security/nss/lib/softoken/config.mk @@ -91,6 +91,7 @@ ifeq ($(OS_TARGET),SunOS) # The -R '$ORIGIN' linker option instructs this library to search for its # dependencies in the same directory where it resides. MKSHLIB += -R '$$ORIGIN' +OS_LIBS += -lbsm endif ifeq ($(OS_TARGET),WINCE) diff --git a/security/nss/lib/softoken/dbinit.c b/security/nss/lib/softoken/dbinit.c index 2b7f81a73..d1f7fd303 100644 --- a/security/nss/lib/softoken/dbinit.c +++ b/security/nss/lib/softoken/dbinit.c @@ -291,6 +291,7 @@ sftk_freeCertDB(NSSLOWCERTCertDBHandle *certHandle) PRInt32 ref = PR_AtomicDecrement(&certHandle->ref); if (ref == 0) { nsslowcert_ClosePermCertDB(certHandle); + PORT_Free(certHandle); } } diff --git a/security/nss/lib/softoken/dbmshim.c b/security/nss/lib/softoken/dbmshim.c index 04c291d7f..f75f4d70d 100644 --- a/security/nss/lib/softoken/dbmshim.c +++ b/security/nss/lib/softoken/dbmshim.c @@ -406,14 +406,6 @@ dbs_readBlob(DBS *dbsp, DBT *data) loser: /* preserve the error code */ error = PR_GetError(); - if (addr) { - if (mapfile) { - PORT_Assert(len != -1); - PR_MemUnmap(addr,len); - } else { - PORT_Free(addr); - } - } if (mapfile) { PR_CloseFileMap(mapfile); } diff --git a/security/nss/lib/softoken/ecdecode.c b/security/nss/lib/softoken/ecdecode.c index e649ff899..dbf1cb3f8 100644 --- a/security/nss/lib/softoken/ecdecode.c +++ b/security/nss/lib/softoken/ecdecode.c @@ -49,7 +49,12 @@ #define CHECK_OK(func) if (func == NULL) goto cleanup #define CHECK_SEC_OK(func) if (SECSuccess != (rv = func)) goto cleanup -/* Initializes a SECItem from a hexadecimal string */ +/* + * Initializes a SECItem from a hexadecimal string + * + * Warning: This function ignores leading 00's, so any leading 00's + * in the hexadecimal string must be optional. + */ static SECItem * hexString2SECItem(PRArenaPool *arena, SECItem *item, const char *str) { @@ -59,6 +64,12 @@ hexString2SECItem(PRArenaPool *arena, SECItem *item, const char *str) if ((tmp % 2) != 0) return NULL; + /* skip leading 00's unless the hex string is "00" */ + while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) { + str += 2; + tmp -= 2; + } + item->data = (unsigned char *) PORT_ArenaAlloc(arena, tmp/2); if (item->data == NULL) return NULL; item->len = tmp/2; @@ -136,7 +147,8 @@ EC_FillParams(PRArenaPool *arena, const SECItem *encodedParams, SECOidTag tag; SECItem oid = { siBuffer, NULL, 0}; const ECCurveParams *curveParams; - char genenc[2 + 2 * 2 * MAX_ECKEY_LEN]; + /* 2 ['0'+'4'] + MAX_ECKEY_LEN * 2 [x,y] * 2 [hex string] + 1 ['\0'] */ + char genenc[3 + 2 * 2 * MAX_ECKEY_LEN]; #if EC_DEBUG int i; diff --git a/security/nss/lib/softoken/fipsaudt.c b/security/nss/lib/softoken/fipsaudt.c new file mode 100644 index 000000000..d17496deb --- /dev/null +++ b/security/nss/lib/softoken/fipsaudt.c @@ -0,0 +1,351 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Network Security Services (NSS). + * + * The Initial Developer of the Original Code is + * Red Hat, Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * This file implements audit logging required by FIPS 140-2 Security + * Level 2. + */ + +#include "prprf.h" +#include "softoken.h" + +/* + * Print the value of the returned object handle in the output buffer + * on a successful return of the PKCS #11 function. If the PKCS #11 + * function failed or the pointer to object handle is NULL (which is + * the case for C_DeriveKey with CKM_TLS_KEY_AND_MAC_DERIVE), an empty + * string is stored in the output buffer. + * + * out: the output buffer + * outlen: the length of the output buffer + * argName: the name of the "pointer to object handle" argument + * phObject: the pointer to object handle + * rv: the return value of the PKCS #11 function + */ +static void sftk_PrintReturnedObjectHandle(char *out, PRUint32 outlen, + const char *argName, CK_OBJECT_HANDLE_PTR phObject, CK_RV rv) +{ + if ((rv == CKR_OK) && phObject) { + PR_snprintf(out, outlen, + " *%s=0x%08lX", argName, (PRUint32)*phObject); + } else { + PORT_Assert(outlen != 0); + out[0] = '\0'; + } +} + +/* + * MECHANISM_BUFSIZE needs to be large enough for sftk_PrintMechanism, + * which uses <= 49 bytes. + */ +#define MECHANISM_BUFSIZE 64 + +static void sftk_PrintMechanism(char *out, PRUint32 outlen, + CK_MECHANISM_PTR pMechanism) +{ + if (pMechanism) { + /* + * If we change the format string, we need to make sure + * MECHANISM_BUFSIZE is still large enough. We allow + * 20 bytes for %p on a 64-bit platform. + */ + PR_snprintf(out, outlen, "%p {mechanism=0x%08lX, ...}", + pMechanism, (PRUint32)pMechanism->mechanism); + } else { + PR_snprintf(out, outlen, "%p", pMechanism); + } +} + +void sftk_AuditCreateObject(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phObject, CK_RV rv) +{ + char msg[256]; + char shObject[32]; + NSSAuditSeverity severity = (rv == CKR_OK) ? + NSS_AUDIT_INFO : NSS_AUDIT_ERROR; + + sftk_PrintReturnedObjectHandle(shObject, sizeof shObject, + "phObject", phObject, rv); + PR_snprintf(msg, sizeof msg, + "C_CreateObject(hSession=0x%08lX, pTemplate=%p, ulCount=%lu, " + "phObject=%p)=0x%08lX%s", + (PRUint32)hSession, pTemplate, (PRUint32)ulCount, + phObject, (PRUint32)rv, shObject); + sftk_LogAuditMessage(severity, msg); +} + +void sftk_AuditCopyObject(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phNewObject, CK_RV rv) +{ + char msg[256]; + char shNewObject[32]; + NSSAuditSeverity severity = (rv == CKR_OK) ? + NSS_AUDIT_INFO : NSS_AUDIT_ERROR; + + sftk_PrintReturnedObjectHandle(shNewObject, sizeof shNewObject, + "phNewObject", phNewObject, rv); + PR_snprintf(msg, sizeof msg, + "C_CopyObject(hSession=0x%08lX, hObject=0x%08lX, " + "pTemplate=%p, ulCount=%lu, phNewObject=%p)=0x%08lX%s", + (PRUint32)hSession, (PRUint32)hObject, + pTemplate, (PRUint32)ulCount, phNewObject, (PRUint32)rv, shNewObject); + sftk_LogAuditMessage(severity, msg); +} + +/* WARNING: hObject has been destroyed and can only be printed. */ +void sftk_AuditDestroyObject(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, CK_RV rv) +{ + char msg[256]; + NSSAuditSeverity severity = (rv == CKR_OK) ? + NSS_AUDIT_INFO : NSS_AUDIT_ERROR; + + PR_snprintf(msg, sizeof msg, + "C_DestroyObject(hSession=0x%08lX, hObject=0x%08lX)=0x%08lX", + (PRUint32)hSession, (PRUint32)hObject, (PRUint32)rv); + sftk_LogAuditMessage(severity, msg); +} + +void sftk_AuditGetObjectSize(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize, CK_RV rv) +{ + char msg[256]; + NSSAuditSeverity severity = (rv == CKR_OK) ? + NSS_AUDIT_INFO : NSS_AUDIT_ERROR; + + PR_snprintf(msg, sizeof msg, + "C_GetObjectSize(hSession=0x%08lX, hObject=0x%08lX, " + "pulSize=%p)=0x%08lX", + (PRUint32)hSession, (PRUint32)hObject, + pulSize, (PRUint32)rv); + sftk_LogAuditMessage(severity, msg); +} + +void sftk_AuditGetAttributeValue(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, CK_RV rv) +{ + char msg[256]; + NSSAuditSeverity severity = (rv == CKR_OK) ? + NSS_AUDIT_INFO : NSS_AUDIT_ERROR; + + PR_snprintf(msg, sizeof msg, + "C_GetAttributeValue(hSession=0x%08lX, hObject=0x%08lX, " + "pTemplate=%p, ulCount=%lu)=0x%08lX", + (PRUint32)hSession, (PRUint32)hObject, + pTemplate, (PRUint32)ulCount, (PRUint32)rv); + sftk_LogAuditMessage(severity, msg); +} + +void sftk_AuditSetAttributeValue(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, CK_RV rv) +{ + char msg[256]; + NSSAuditSeverity severity = (rv == CKR_OK) ? + NSS_AUDIT_INFO : NSS_AUDIT_ERROR; + + PR_snprintf(msg, sizeof msg, + "C_SetAttributeValue(hSession=0x%08lX, hObject=0x%08lX, " + "pTemplate=%p, ulCount=%lu)=0x%08lX", + (PRUint32)hSession, (PRUint32)hObject, + pTemplate, (PRUint32)ulCount, (PRUint32)rv); + sftk_LogAuditMessage(severity, msg); +} + +void sftk_AuditCryptInit(const char *opName, CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, CK_RV rv) +{ + char msg[256]; + char mech[MECHANISM_BUFSIZE]; + NSSAuditSeverity severity = (rv == CKR_OK) ? + NSS_AUDIT_INFO : NSS_AUDIT_ERROR; + + sftk_PrintMechanism(mech, sizeof mech, pMechanism); + PR_snprintf(msg, sizeof msg, + "C_%sInit(hSession=0x%08lX, pMechanism=%s, " + "hKey=0x%08lX)=0x%08lX", + opName, (PRUint32)hSession, mech, + (PRUint32)hKey, (PRUint32)rv); + sftk_LogAuditMessage(severity, msg); +} + +void sftk_AuditGenerateKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey, CK_RV rv) +{ + char msg[256]; + char mech[MECHANISM_BUFSIZE]; + char shKey[32]; + NSSAuditSeverity severity = (rv == CKR_OK) ? + NSS_AUDIT_INFO : NSS_AUDIT_ERROR; + + sftk_PrintMechanism(mech, sizeof mech, pMechanism); + sftk_PrintReturnedObjectHandle(shKey, sizeof shKey, "phKey", phKey, rv); + PR_snprintf(msg, sizeof msg, + "C_GenerateKey(hSession=0x%08lX, pMechanism=%s, " + "pTemplate=%p, ulCount=%lu, phKey=%p)=0x%08lX%s", + (PRUint32)hSession, mech, + pTemplate, (PRUint32)ulCount, phKey, (PRUint32)rv, shKey); + sftk_LogAuditMessage(severity, msg); +} + +void sftk_AuditGenerateKeyPair(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, + CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, + CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, + CK_OBJECT_HANDLE_PTR phPrivateKey, CK_RV rv) +{ + char msg[512]; + char mech[MECHANISM_BUFSIZE]; + char shPublicKey[32]; + char shPrivateKey[32]; + NSSAuditSeverity severity = (rv == CKR_OK) ? + NSS_AUDIT_INFO : NSS_AUDIT_ERROR; + + sftk_PrintMechanism(mech, sizeof mech, pMechanism); + sftk_PrintReturnedObjectHandle(shPublicKey, sizeof shPublicKey, + "phPublicKey", phPublicKey, rv); + sftk_PrintReturnedObjectHandle(shPrivateKey, sizeof shPrivateKey, + "phPrivateKey", phPrivateKey, rv); + PR_snprintf(msg, sizeof msg, + "C_GenerateKeyPair(hSession=0x%08lX, pMechanism=%s, " + "pPublicKeyTemplate=%p, ulPublicKeyAttributeCount=%lu, " + "pPrivateKeyTemplate=%p, ulPrivateKeyAttributeCount=%lu, " + "phPublicKey=%p, phPrivateKey=%p)=0x%08lX%s%s", + (PRUint32)hSession, mech, + pPublicKeyTemplate, (PRUint32)ulPublicKeyAttributeCount, + pPrivateKeyTemplate, (PRUint32)ulPrivateKeyAttributeCount, + phPublicKey, phPrivateKey, (PRUint32)rv, shPublicKey, shPrivateKey); + sftk_LogAuditMessage(severity, msg); +} + +void sftk_AuditWrapKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, + CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, + CK_ULONG_PTR pulWrappedKeyLen, CK_RV rv) +{ + char msg[256]; + char mech[MECHANISM_BUFSIZE]; + NSSAuditSeverity severity = (rv == CKR_OK) ? + NSS_AUDIT_INFO : NSS_AUDIT_ERROR; + + sftk_PrintMechanism(mech, sizeof mech, pMechanism); + PR_snprintf(msg, sizeof msg, + "C_WrapKey(hSession=0x%08lX, pMechanism=%s, hWrappingKey=0x%08lX, " + "hKey=0x%08lX, pWrappedKey=%p, pulWrappedKeyLen=%p)=0x%08lX", + (PRUint32)hSession, mech, (PRUint32)hWrappingKey, + (PRUint32)hKey, pWrappedKey, pulWrappedKeyLen, (PRUint32)rv); + sftk_LogAuditMessage(severity, msg); +} + +void sftk_AuditUnwrapKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, + CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, + CK_OBJECT_HANDLE_PTR phKey, CK_RV rv) +{ + char msg[256]; + char mech[MECHANISM_BUFSIZE]; + char shKey[32]; + NSSAuditSeverity severity = (rv == CKR_OK) ? + NSS_AUDIT_INFO : NSS_AUDIT_ERROR; + + sftk_PrintMechanism(mech, sizeof mech, pMechanism); + sftk_PrintReturnedObjectHandle(shKey, sizeof shKey, "phKey", phKey, rv); + PR_snprintf(msg, sizeof msg, + "C_UnwrapKey(hSession=0x%08lX, pMechanism=%s, " + "hUnwrappingKey=0x%08lX, pWrappedKey=%p, ulWrappedKeyLen=%lu, " + "pTemplate=%p, ulAttributeCount=%lu, phKey=%p)=0x%08lX%s", + (PRUint32)hSession, mech, + (PRUint32)hUnwrappingKey, pWrappedKey, (PRUint32)ulWrappedKeyLen, + pTemplate, (PRUint32)ulAttributeCount, phKey, (PRUint32)rv, shKey); + sftk_LogAuditMessage(severity, msg); +} + +void sftk_AuditDeriveKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, + CK_OBJECT_HANDLE_PTR phKey, CK_RV rv) +{ + char msg[512]; + char mech[MECHANISM_BUFSIZE]; + char shKey[32]; + char sTlsKeys[128]; + NSSAuditSeverity severity = (rv == CKR_OK) ? + NSS_AUDIT_INFO : NSS_AUDIT_ERROR; + + sftk_PrintMechanism(mech, sizeof mech, pMechanism); + sftk_PrintReturnedObjectHandle(shKey, sizeof shKey, "phKey", phKey, rv); + if ((rv == CKR_OK) && + (pMechanism->mechanism == CKM_TLS_KEY_AND_MAC_DERIVE)) { + CK_SSL3_KEY_MAT_PARAMS *param = + (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter; + CK_SSL3_KEY_MAT_OUT *keymat = param->pReturnedKeyMaterial; + PR_snprintf(sTlsKeys, sizeof sTlsKeys, + " hClientMacSecret=0x%08lX hServerMacSecret=0x%08lX" + " hClientKey=0x%08lX hServerKey=0x%08lX", + (PRUint32)keymat->hClientMacSecret, + (PRUint32)keymat->hServerMacSecret, + (PRUint32)keymat->hClientKey, + (PRUint32)keymat->hServerKey); + } else { + sTlsKeys[0] = '\0'; + } + PR_snprintf(msg, sizeof msg, + "C_DeriveKey(hSession=0x%08lX, pMechanism=%s, " + "hBaseKey=0x%08lX, pTemplate=%p, ulAttributeCount=%lu, " + "phKey=%p)=0x%08lX%s%s", + (PRUint32)hSession, mech, + (PRUint32)hBaseKey, pTemplate,(PRUint32)ulAttributeCount, + phKey, (PRUint32)rv, shKey, sTlsKeys); + sftk_LogAuditMessage(severity, msg); +} + +void sftk_AuditDigestKey(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hKey, CK_RV rv) +{ + char msg[256]; + NSSAuditSeverity severity = (rv == CKR_OK) ? + NSS_AUDIT_INFO : NSS_AUDIT_ERROR; + + PR_snprintf(msg, sizeof msg, + "C_DigestKey(hSession=0x%08lX, hKey=0x%08lX)=0x%08lX", + (PRUint32)hSession, (PRUint32)hKey, (PRUint32)rv); + sftk_LogAuditMessage(severity, msg); +} diff --git a/security/nss/lib/softoken/fipstest.c b/security/nss/lib/softoken/fipstest.c index acee77676..942bd4034 100644 --- a/security/nss/lib/softoken/fipstest.c +++ b/security/nss/lib/softoken/fipstest.c @@ -42,10 +42,21 @@ /* DES-CBC, DES3-ECB, DES3-CBC, RSA */ /* and DSA. */ #include "seccomon.h" /* Required for RSA and DSA. */ -#include "lowkeyi.h" /* Required for RSA and DSA. */ +#include "lowkeyi.h" /* Required for RSA and DSA. */ #include "pkcs11.h" /* Required for PKCS #11. */ #include "secerr.h" +#ifdef NSS_ENABLE_ECC +#include "secdert.h" /* Required for ECDSA */ +#include "ec.h" /* Required for ECDSA */ +extern SECStatus +EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams); +extern SECStatus +EC_CopyParams(PRArenaPool *arena, ECParams *dstParams, + const ECParams *srcParams); +#endif + + /* FIPS preprocessor directives for RC2-ECB and RC2-CBC. */ #define FIPS_RC2_KEY_LENGTH 5 /* 40-bits */ #define FIPS_RC2_ENCRYPT_LENGTH 8 /* 64-bits */ @@ -81,31 +92,33 @@ #define FIPS_KNOWN_HASH_MESSAGE_LENGTH 64 /* 512-bits */ -/* FIPS preprocessor directives for RSA. */ +/* FIPS preprocessor directives for RSA. */ #define FIPS_RSA_TYPE siBuffer -#define FIPS_RSA_PUBLIC_EXPONENT_LENGTH 1 /* 8-bits */ -#define FIPS_RSA_PRIVATE_VERSION_LENGTH 1 /* 8-bits */ -#define FIPS_RSA_MESSAGE_LENGTH 16 /* 128-bits */ -#define FIPS_RSA_COEFFICIENT_LENGTH 32 /* 256-bits */ -#define FIPS_RSA_PRIME0_LENGTH 33 /* 264-bits */ -#define FIPS_RSA_PRIME1_LENGTH 33 /* 264-bits */ -#define FIPS_RSA_EXPONENT0_LENGTH 33 /* 264-bits */ -#define FIPS_RSA_EXPONENT1_LENGTH 33 /* 264-bits */ -#define FIPS_RSA_PRIVATE_EXPONENT_LENGTH 64 /* 512-bits */ -#define FIPS_RSA_ENCRYPT_LENGTH 64 /* 512-bits */ -#define FIPS_RSA_DECRYPT_LENGTH 64 /* 512-bits */ -#define FIPS_RSA_CRYPTO_LENGTH 64 /* 512-bits */ -#define FIPS_RSA_SIGNATURE_LENGTH 64 /* 512-bits */ -#define FIPS_RSA_MODULUS_LENGTH 65 /* 520-bits */ +#define FIPS_RSA_PUBLIC_EXPONENT_LENGTH 3 /* 24-bits */ +#define FIPS_RSA_PRIVATE_VERSION_LENGTH 1 /* 8-bits */ +#define FIPS_RSA_MESSAGE_LENGTH 128 /* 1024-bits */ +#define FIPS_RSA_COEFFICIENT_LENGTH 64 /* 512-bits */ +#define FIPS_RSA_PRIME0_LENGTH 64 /* 512-bits */ +#define FIPS_RSA_PRIME1_LENGTH 64 /* 512-bits */ +#define FIPS_RSA_EXPONENT0_LENGTH 64 /* 512-bits */ +#define FIPS_RSA_EXPONENT1_LENGTH 64 /* 512-bits */ +#define FIPS_RSA_PRIVATE_EXPONENT_LENGTH 128 /* 1024-bits */ +#define FIPS_RSA_ENCRYPT_LENGTH 128 /* 1024-bits */ +#define FIPS_RSA_DECRYPT_LENGTH 128 /* 1024-bits */ +#define FIPS_RSA_SIGNATURE_LENGTH 128 /* 1024-bits */ +#define FIPS_RSA_MODULUS_LENGTH 128 /* 1024-bits */ /* FIPS preprocessor directives for DSA. */ #define FIPS_DSA_TYPE siBuffer -#define FIPS_DSA_DIGEST_LENGTH 20 /* 160-bits */ -#define FIPS_DSA_SUBPRIME_LENGTH 20 /* 160-bits */ -#define FIPS_DSA_SIGNATURE_LENGTH 40 /* 320-bits */ -#define FIPS_DSA_PRIME_LENGTH 64 /* 512-bits */ -#define FIPS_DSA_BASE_LENGTH 64 /* 512-bits */ +#define FIPS_DSA_DIGEST_LENGTH 20 /* 160-bits */ +#define FIPS_DSA_SUBPRIME_LENGTH 20 /* 160-bits */ +#define FIPS_DSA_SIGNATURE_LENGTH 40 /* 320-bits */ +#define FIPS_DSA_PRIME_LENGTH 128 /* 1024-bits */ +#define FIPS_DSA_BASE_LENGTH 128 /* 1024-bits */ + +/* FIPS preprocessor directives for RNG. */ +#define FIPS_RNG_XKEY_LENGTH 32 /* 256-bits */ static CK_RV sftk_fips_RC2_PowerUpSelfTest( void ) @@ -1046,121 +1059,324 @@ sftk_fips_SHA_PowerUpSelfTest( void ) return( CKR_OK ); } +/* +* Single round RSA Signature Known Answer Test +*/ +static SECStatus +sftk_fips_RSA_PowerUpSigSelfTest (HASH_HashType shaAlg, + NSSLOWKEYPublicKey *rsa_public_key, + NSSLOWKEYPrivateKey *rsa_private_key, + const unsigned char *rsa_known_msg, + const unsigned int rsa_kmsg_length, + const unsigned char *rsa_known_signature) +{ + SECOidTag shaOid; /* SHA OID */ + unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */ + unsigned int shaLength = 0; /* length of SHA */ + unsigned int rsa_bytes_signed; + unsigned char rsa_computed_signature[FIPS_RSA_SIGNATURE_LENGTH]; + SECStatus rv; + + if (shaAlg == HASH_AlgSHA1) { + if (SHA1_HashBuf(sha, rsa_known_msg, rsa_kmsg_length) + != SECSuccess) { + goto loser; + } + shaLength = SHA1_LENGTH; + shaOid = SEC_OID_SHA1; + } else if (shaAlg == HASH_AlgSHA256) { + if (SHA256_HashBuf(sha, rsa_known_msg, rsa_kmsg_length) + != SECSuccess) { + goto loser; + } + shaLength = SHA256_LENGTH; + shaOid = SEC_OID_SHA256; + } else if (shaAlg == HASH_AlgSHA384) { + if (SHA384_HashBuf(sha, rsa_known_msg, rsa_kmsg_length) + != SECSuccess) { + goto loser; + } + shaLength = SHA384_LENGTH; + shaOid = SEC_OID_SHA384; + } else if (shaAlg == HASH_AlgSHA512) { + if (SHA512_HashBuf(sha, rsa_known_msg, rsa_kmsg_length) + != SECSuccess) { + goto loser; + } + shaLength = SHA512_LENGTH; + shaOid = SEC_OID_SHA512; + } else { + goto loser; + } + + /*************************************************/ + /* RSA Single-Round Known Answer Signature Test. */ + /*************************************************/ + + /* Perform RSA signature with the RSA private key. */ + rv = RSA_HashSign( shaOid, + rsa_private_key, + rsa_computed_signature, + &rsa_bytes_signed, + FIPS_RSA_SIGNATURE_LENGTH, + sha, + shaLength); + + if( ( rv != SECSuccess ) || + ( rsa_bytes_signed != FIPS_RSA_SIGNATURE_LENGTH ) || + ( PORT_Memcmp( rsa_computed_signature, rsa_known_signature, + FIPS_RSA_SIGNATURE_LENGTH ) != 0 ) ) { + goto loser; + } + + /****************************************************/ + /* RSA Single-Round Known Answer Verification Test. */ + /****************************************************/ + + /* Perform RSA verification with the RSA public key. */ + rv = RSA_HashCheckSign( shaOid, + rsa_public_key, + rsa_computed_signature, + rsa_bytes_signed, + sha, + shaLength); + + if( rv != SECSuccess ) { + goto loser; + } + return( SECSuccess ); + +loser: + + return( SECFailure ); + +} static CK_RV sftk_fips_RSA_PowerUpSelfTest( void ) { - /* RSA Known Modulus used in both Public/Private Key Values (520-bits). */ + /* RSA Known Modulus used in both Public/Private Key Values (1024-bits). */ static const PRUint8 rsa_modulus[FIPS_RSA_MODULUS_LENGTH] = { - 0x00,0xa1,0xe9,0x5e,0x66,0x88,0xe2,0xf2, - 0x2b,0xe7,0x70,0x36,0x33,0xbc,0xeb,0x55, - 0x55,0xf1,0x60,0x18,0x3c,0xfb,0xd2,0x79, - 0xf6,0xc4,0xb8,0x09,0xe3,0x12,0xf6,0x63, - 0x6d,0xc7,0x8e,0x19,0xc0,0x0e,0x10,0x78, - 0xc1,0xfe,0x2a,0x41,0x74,0x2d,0xf7,0xc4, - 0x69,0xa7,0x3c,0xbc,0x8a,0xc8,0x31,0x2b, - 0x4f,0x60,0xf0,0xf1,0xec,0x5a,0x29,0xec, - 0x6b}; - - /* RSA Known Public Key Values (8-bits). */ - static const PRUint8 rsa_public_exponent[] = { 0x03 }; - - /* RSA Known Private Key Values (version is 8-bits), */ - /* (private exponent is 512-bits), */ - /* (private prime0 is 264-bits), */ - /* (private prime1 is 264-bits), */ - /* (private prime exponent0 is 264-bits), */ - /* (private prime exponent1 is 264-bits), */ - /* and (private coefficient is 256-bits). */ + 0xd5, 0x84, 0x95, 0x07, 0xf4, 0xd0, 0x1f, 0x82, + 0xf3, 0x79, 0xf4, 0x99, 0x48, 0x10, 0xe1, 0x71, + 0xa5, 0x62, 0x22, 0xa3, 0x4b, 0x00, 0xe3, 0x5b, + 0x3a, 0xcc, 0x10, 0x83, 0xe0, 0xaf, 0x61, 0x13, + 0x54, 0x6a, 0xa2, 0x6a, 0x2c, 0x5e, 0xb3, 0xcc, + 0xa3, 0x71, 0x9a, 0xb2, 0x3e, 0x78, 0xec, 0xb5, + 0x0e, 0x6e, 0x31, 0x3b, 0x77, 0x1f, 0x6e, 0x94, + 0x41, 0x60, 0xd5, 0x6e, 0xd9, 0xc6, 0xf9, 0x29, + 0xc3, 0x40, 0x36, 0x25, 0xdb, 0xea, 0x0b, 0x07, + 0xae, 0x76, 0xfd, 0x99, 0x29, 0xf4, 0x22, 0xc1, + 0x1a, 0x8f, 0x05, 0xfe, 0x98, 0x09, 0x07, 0x05, + 0xc2, 0x0f, 0x0b, 0x11, 0x83, 0x39, 0xca, 0xc7, + 0x43, 0x63, 0xff, 0x33, 0x80, 0xe7, 0xc3, 0x78, + 0xae, 0xf1, 0x73, 0x52, 0x98, 0x1d, 0xde, 0x5c, + 0x53, 0x6e, 0x01, 0x73, 0x0d, 0x12, 0x7e, 0x77, + 0x03, 0xf1, 0xef, 0x1b, 0xc8, 0xa8, 0x0f, 0x97}; + + /* RSA Known Public Key Values (24-bits). */ + static const PRUint8 rsa_public_exponent[FIPS_RSA_PUBLIC_EXPONENT_LENGTH] + = { 0x01, 0x00, 0x01 }; + /* RSA Known Private Key Values (version is 8-bits), */ + /* (private exponent is 1024-bits), */ + /* (private prime0 is 512-bits), */ + /* (private prime1 is 512-bits), */ + /* (private prime exponent0 is 512-bits), */ + /* (private prime exponent1 is 512-bits), */ + /* and (private coefficient is 512-bits). */ static const PRUint8 rsa_version[] = { 0x00 }; - static const PRUint8 rsa_private_exponent[FIPS_RSA_PRIVATE_EXPONENT_LENGTH] = { - 0x6b,0xf0,0xe9,0x99,0xb0,0x97,0x4c,0x1d, - 0x44,0xf5,0x79,0x77,0xd3,0x47,0x8e,0x39, - 0x4b,0x95,0x65,0x7d,0xfd,0x36,0xfb,0xf9, - 0xd8,0x7a,0xb1,0x42,0x0c,0xa4,0x42,0x48, - 0x20,0x1c,0x6b,0x7d,0x5d,0xa3,0x58,0xd6, - 0x95,0xd6,0x41,0xe3,0xd6,0x73,0xad,0xdb, - 0x3b,0x89,0x00,0x8a,0xcd,0x1d,0xb9,0x06, - 0xac,0xac,0x0e,0x02,0x72,0x1c,0xf8,0xab }; + + static const PRUint8 rsa_private_exponent[FIPS_RSA_PRIVATE_EXPONENT_LENGTH] + = { 0x85, 0x27, 0x47, 0x61, 0x4c, 0xd4, 0xb5, 0xb2, + 0x0e, 0x70, 0x91, 0x8f, 0x3d, 0x97, 0xf9, 0x5f, + 0xcc, 0x09, 0x65, 0x1c, 0x7c, 0x5b, 0xb3, 0x6d, + 0x63, 0x3f, 0x7b, 0x55, 0x22, 0xbb, 0x7c, 0x48, + 0x77, 0xae, 0x80, 0x56, 0xc2, 0x10, 0xd5, 0x03, + 0xdb, 0x31, 0xaf, 0x8d, 0x54, 0xd4, 0x48, 0x99, + 0xa8, 0xc4, 0x23, 0x43, 0xb8, 0x48, 0x0b, 0xc7, + 0xbc, 0xf5, 0xcc, 0x64, 0x72, 0xbf, 0x59, 0x06, + 0x04, 0x1c, 0x32, 0xf5, 0x14, 0x2e, 0x6e, 0xe2, + 0x0f, 0x5c, 0xde, 0x36, 0x3c, 0x6e, 0x7c, 0x4d, + 0xcc, 0xd3, 0x00, 0x6e, 0xe5, 0x45, 0x46, 0xef, + 0x4d, 0x25, 0x46, 0x6d, 0x7f, 0xed, 0xbb, 0x4f, + 0x4d, 0x9f, 0xda, 0x87, 0x47, 0x8f, 0x74, 0x44, + 0xb7, 0xbe, 0x9d, 0xf5, 0xdd, 0xd2, 0x4c, 0xa5, + 0xab, 0x74, 0xe5, 0x29, 0xa1, 0xd2, 0x45, 0x3b, + 0x33, 0xde, 0xd5, 0xae, 0xf7, 0x03, 0x10, 0x21}; + static const PRUint8 rsa_prime0[FIPS_RSA_PRIME0_LENGTH] = { - 0x00,0xd2,0x2c,0x9d,0xef,0x7c,0x8f,0x58, - 0x93,0x19,0xa1,0x77,0x0e,0x38,0x3e,0x85, - 0xb4,0xaf,0xcc,0x99,0xa5,0x43,0xbf,0x97, - 0xdc,0x46,0xb8,0x3f,0x6e,0x85,0x18,0x00, - 0x81}; + 0xf9, 0x74, 0x8f, 0x16, 0x02, 0x6b, 0xa0, 0xee, + 0x7f, 0x28, 0x97, 0x91, 0xdc, 0xec, 0xc0, 0x7c, + 0x49, 0xc2, 0x85, 0x76, 0xee, 0x66, 0x74, 0x2d, + 0x1a, 0xb8, 0xf7, 0x2f, 0x11, 0x5b, 0x36, 0xd8, + 0x46, 0x33, 0x3b, 0xd8, 0xf3, 0x2d, 0xa1, 0x03, + 0x83, 0x2b, 0xec, 0x35, 0x43, 0x32, 0xff, 0xdd, + 0x81, 0x7c, 0xfd, 0x65, 0x13, 0x04, 0x7c, 0xfc, + 0x03, 0x97, 0xf0, 0xd5, 0x62, 0xdc, 0x0d, 0xbf}; static const PRUint8 rsa_prime1[FIPS_RSA_PRIME1_LENGTH] = { - 0x00,0xc5,0x36,0xda,0x94,0x85,0x0c,0x1a, - 0xed,0x03,0xc7,0x67,0x90,0x34,0x0b,0xb9, - 0xec,0x1e,0x22,0xa2,0x15,0x50,0xc4,0xfd, - 0xe9,0x17,0x36,0x9d,0x7a,0x29,0xe6,0x76, - 0xeb}; + 0xdb, 0x1e, 0xa7, 0x3d, 0xe7, 0xfa, 0x8b, 0x04, + 0x83, 0x48, 0xf3, 0xa5, 0x31, 0x9d, 0x35, 0x5e, + 0x4d, 0x54, 0x77, 0xcc, 0x84, 0x09, 0xf3, 0x11, + 0x0d, 0x54, 0xed, 0x85, 0x39, 0xa9, 0xca, 0xa8, + 0xea, 0xae, 0x19, 0x9c, 0x75, 0xdb, 0x88, 0xb8, + 0x04, 0x8d, 0x54, 0xc6, 0xa4, 0x80, 0xf8, 0x93, + 0xf0, 0xdb, 0x19, 0xef, 0xd7, 0x87, 0x8a, 0x8f, + 0x5a, 0x09, 0x2e, 0x54, 0xf3, 0x45, 0x24, 0x29}; static const PRUint8 rsa_exponent0[FIPS_RSA_EXPONENT0_LENGTH] = { - 0x00,0x8c,0x1d,0xbe,0x9f,0xa8, - 0x5f,0x90,0x62,0x11,0x16,0x4f, - 0x5e,0xd0,0x29,0xae,0x78,0x75, - 0x33,0x11,0x18,0xd7,0xd5,0x0f, - 0xe8,0x2f,0x25,0x7f,0x9f,0x03, - 0x65,0x55,0xab}; + 0x6a, 0xd1, 0x25, 0x80, 0x18, 0x33, 0x3c, 0x2b, + 0x44, 0x19, 0xfe, 0xa5, 0x40, 0x03, 0xc4, 0xfc, + 0xb3, 0x9c, 0xef, 0x07, 0x99, 0x58, 0x17, 0xc1, + 0x44, 0xa3, 0x15, 0x7d, 0x7b, 0x22, 0x22, 0xdf, + 0x03, 0x58, 0x66, 0xf5, 0x24, 0x54, 0x52, 0x91, + 0x2d, 0x76, 0xfe, 0x63, 0x64, 0x4e, 0x0f, 0x50, + 0x2b, 0x65, 0x79, 0x1f, 0xf1, 0xbf, 0xc7, 0x41, + 0x26, 0xcc, 0xc6, 0x1c, 0xa9, 0x83, 0x6f, 0x03}; static const PRUint8 rsa_exponent1[FIPS_RSA_EXPONENT1_LENGTH] = { - 0x00,0x83,0x79,0xe7,0x0d,0xae, - 0x08,0x11,0xf3,0x57,0xda,0x45, - 0x0a,0xcd,0x5d,0x26,0x9d,0x69, - 0x6c,0x6c,0x0e,0x35,0xd8,0xa9, - 0x46,0x0f,0x79,0xbe,0x51,0x71, - 0x44,0x4f,0x47}; + 0x12, 0x84, 0x1a, 0x99, 0xce, 0x9a, 0x8b, 0x58, + 0xcc, 0x47, 0x43, 0xdf, 0x77, 0xbb, 0xd3, 0x20, + 0xae, 0xe4, 0x2e, 0x63, 0x67, 0xdc, 0xf7, 0x5f, + 0x3f, 0x83, 0x27, 0xb7, 0x14, 0x52, 0x56, 0xbf, + 0xc3, 0x65, 0x06, 0xe1, 0x03, 0xcc, 0x93, 0x57, + 0x09, 0x7b, 0x6f, 0xe8, 0x81, 0x4a, 0x2c, 0xb7, + 0x43, 0xa9, 0x20, 0x1d, 0xf6, 0x56, 0x8b, 0xcc, + 0xe5, 0x4c, 0xd5, 0x4f, 0x74, 0x67, 0x29, 0x51}; static const PRUint8 rsa_coefficient[FIPS_RSA_COEFFICIENT_LENGTH] = { - 0x54,0x8d,0xb8,0xdc,0x8b,0xde,0xbb, - 0x08,0xc9,0x67,0xb7,0xa9,0x5f,0xa5, - 0xc4,0x5e,0x67,0xaa,0xfe,0x1a,0x08, - 0xeb,0x48,0x43,0xcb,0xb0,0xb9,0x38, - 0x3a,0x31,0x39,0xde}; - - - /* RSA Known Plaintext (512-bits). */ - static const PRUint8 rsa_known_plaintext[] = { - "Known plaintext utilized for RSA" - " Encryption and Decryption test." }; - - /* RSA Known Ciphertext (512-bits). */ + 0x23, 0xab, 0xf4, 0x03, 0x2f, 0x29, 0x95, 0x74, + 0xac, 0x1a, 0x33, 0x96, 0x62, 0xed, 0xf7, 0xf6, + 0xae, 0x07, 0x2a, 0x2e, 0xe8, 0xab, 0xfb, 0x1e, + 0xb9, 0xb2, 0x88, 0x1e, 0x85, 0x05, 0x42, 0x64, + 0x03, 0xb2, 0x8b, 0xc1, 0x81, 0x75, 0xd7, 0xba, + 0xaa, 0xd4, 0x31, 0x3c, 0x8a, 0x96, 0x23, 0x9d, + 0x3f, 0x06, 0x3e, 0x44, 0xa9, 0x62, 0x2f, 0x61, + 0x5a, 0x51, 0x82, 0x2c, 0x04, 0x85, 0x73, 0xd1}; + + /* RSA Known Plaintext Message (1024-bits). */ + static const PRUint8 rsa_known_plaintext_msg[FIPS_RSA_MESSAGE_LENGTH] = { + "Known plaintext message utilized" + "for RSA Encryption & Decryption" + "block, SHA1, SHA256, SHA384 and" + "SHA512 RSA Signature KAT tests."}; + + /* RSA Known Ciphertext (1024-bits). */ static const PRUint8 rsa_known_ciphertext[] = { - 0x12,0x80,0x3a,0x53,0xee,0x93,0x81,0xa5, - 0xf7,0x40,0xc5,0xb1,0xef,0xd9,0x27,0xaf, - 0xef,0x4b,0x87,0x44,0x00,0xd0,0xda,0xcf, - 0x10,0x57,0x4c,0xd5,0xc3,0xed,0x84,0xdc, - 0x74,0x03,0x19,0x69,0x2c,0xd6,0x54,0x3e, - 0xd2,0xe3,0x90,0xb6,0x67,0x91,0x2f,0x1f, - 0x54,0x13,0x99,0x00,0x0b,0xfd,0x52,0x7f, - 0xd8,0xc6,0xdb,0x8a,0xfe,0x06,0xf3,0xb1}; - - /* RSA Known Message (128-bits). */ - static const PRUint8 rsa_known_message[] = { "Netscape Forever" }; - - /* RSA Known Signed Hash (512-bits). */ - static const PRUint8 rsa_known_signature[] = { - 0x27,0x23,0xa6,0x71,0x57,0xc8,0x70,0x5f, - 0x70,0x0e,0x06,0x7b,0x96,0x6a,0xaa,0x41, - 0x6e,0xab,0x67,0x4b,0x5f,0x76,0xc4,0x53, - 0x23,0xd7,0x57,0x7a,0x3a,0xbc,0x4c,0x27, - 0x65,0xca,0xde,0x9f,0xd3,0x1d,0xa4,0x5a, - 0xf9,0x8f,0xb2,0x05,0xa3,0x86,0xf9,0x66, - 0x55,0x4c,0x68,0x50,0x66,0xa4,0xe9,0x17, - 0x45,0x11,0xb8,0x1a,0xfc,0xbc,0x79,0x3b}; - - - static const RSAPublicKey bl_public_key = { NULL, - { FIPS_RSA_TYPE, (unsigned char *)rsa_modulus, FIPS_RSA_MODULUS_LENGTH }, - { FIPS_RSA_TYPE, (unsigned char *)rsa_public_exponent, FIPS_RSA_PUBLIC_EXPONENT_LENGTH } + 0x1e, 0x7e, 0x12, 0xbb, 0x15, 0x62, 0xd0, 0x23, + 0x53, 0x4c, 0x51, 0x97, 0x77, 0x06, 0xa0, 0xbb, + 0x26, 0x99, 0x9a, 0x8f, 0x39, 0xad, 0x88, 0x5c, + 0xc4, 0xce, 0x33, 0x40, 0x94, 0x92, 0xb4, 0x0e, + 0xab, 0x71, 0xa9, 0x5d, 0x9a, 0x37, 0xe3, 0x9a, + 0x24, 0x95, 0x13, 0xea, 0x0f, 0xbb, 0xf7, 0xff, + 0xdf, 0x31, 0x33, 0x23, 0x1d, 0xce, 0x26, 0x9e, + 0xd1, 0xde, 0x98, 0x40, 0xde, 0x57, 0x86, 0x12, + 0xf1, 0xe6, 0x5a, 0x3f, 0x08, 0x02, 0x81, 0x85, + 0xe0, 0xd9, 0xad, 0x3c, 0x8c, 0x71, 0xf8, 0xcf, + 0x0a, 0x98, 0xc5, 0x08, 0xdc, 0xc4, 0xca, 0x8c, + 0x23, 0x1b, 0x4d, 0x9b, 0xb5, 0x13, 0x44, 0xe1, + 0x5f, 0xf9, 0x30, 0x80, 0x25, 0xe0, 0x1e, 0x94, + 0xa3, 0x0c, 0xdc, 0x82, 0x2e, 0xfb, 0x30, 0xbe, + 0x89, 0xba, 0x76, 0xb6, 0x23, 0xf7, 0xda, 0x7c, + 0xca, 0xe6, 0x02, 0xbd, 0x92, 0xce, 0x64, 0xfc}; + + /* RSA Known Signed Hash (1024-bits). */ + static const PRUint8 rsa_known_sha1_signature[] = { + 0xd2, 0xa4, 0xe0, 0x2b, 0xc7, 0x03, 0x7f, 0xc6, + 0x06, 0x9e, 0xa2, 0x82, 0x19, 0xe9, 0x2b, 0xaf, + 0xe3, 0x48, 0x88, 0xc1, 0xf3, 0xb5, 0x0d, 0xe4, + 0x52, 0x9e, 0xad, 0xd5, 0x58, 0xb5, 0x9f, 0xe8, + 0x40, 0xe9, 0xb7, 0x2e, 0xc6, 0x71, 0x58, 0x56, + 0x04, 0xac, 0xb0, 0xf3, 0x3a, 0x42, 0x38, 0x08, + 0xc4, 0x43, 0x39, 0xba, 0x19, 0xce, 0xb1, 0x99, + 0xf1, 0x8d, 0x89, 0xd8, 0x50, 0x07, 0x14, 0x3d, + 0xcf, 0xd0, 0xb6, 0x79, 0xde, 0x9c, 0x89, 0x32, + 0xb0, 0x73, 0x3f, 0xed, 0x03, 0x0b, 0xdf, 0x6d, + 0x7e, 0xc9, 0x1c, 0x39, 0xe8, 0x2b, 0x16, 0x09, + 0xbb, 0x5f, 0x99, 0x2f, 0xeb, 0xf3, 0x37, 0x73, + 0x0d, 0x0e, 0xcc, 0x95, 0xad, 0x90, 0x80, 0x03, + 0x1d, 0x80, 0x55, 0x37, 0xa1, 0x2a, 0x71, 0x76, + 0x23, 0x87, 0x8c, 0x9b, 0x41, 0x07, 0xc6, 0x3d, + 0xc6, 0xa3, 0x7d, 0x1b, 0xff, 0x4e, 0x11, 0x19}; + + /* RSA Known Signed Hash (1024-bits). */ + static const PRUint8 rsa_known_sha256_signature[] = { + 0x27, 0x35, 0xdd, 0xc4, 0xf8, 0xe2, 0x0b, 0xa3, + 0xef, 0x63, 0x57, 0x3b, 0xe1, 0x58, 0x9a, 0xbc, + 0x20, 0x9c, 0x25, 0x12, 0x01, 0xbf, 0xbb, 0x29, + 0x80, 0x1a, 0xb1, 0x37, 0x9c, 0xcd, 0x67, 0xc7, + 0x0d, 0xf8, 0x64, 0x10, 0x9f, 0xe2, 0xa1, 0x9b, + 0x21, 0x90, 0xcc, 0xda, 0x8b, 0x76, 0x5e, 0x79, + 0x00, 0x9d, 0x58, 0x8b, 0x8a, 0xb3, 0xc3, 0xb5, + 0xf1, 0x54, 0xc5, 0x8c, 0x72, 0xba, 0xde, 0x51, + 0x3c, 0x6b, 0x94, 0xd6, 0xf3, 0x1b, 0xa2, 0x53, + 0xe6, 0x1a, 0x46, 0x1d, 0x7f, 0x14, 0x86, 0xcc, + 0xa6, 0x30, 0x92, 0x96, 0xc0, 0x96, 0x24, 0xf0, + 0x42, 0x53, 0x4c, 0xdd, 0x27, 0xdf, 0x1d, 0x2e, + 0x8b, 0x83, 0xbe, 0xed, 0x85, 0x1d, 0x50, 0x46, + 0xa3, 0x7d, 0x20, 0xea, 0x3e, 0x91, 0xfb, 0xf6, + 0x86, 0x51, 0xfd, 0x8c, 0xe5, 0x31, 0xe6, 0x7e, + 0x60, 0x08, 0x0e, 0xec, 0xa6, 0xea, 0x24, 0x8d}; + + /* RSA Known Signed Hash (1024-bits). */ + static const PRUint8 rsa_known_sha384_signature[] = { + 0x0b, 0x03, 0x94, 0x4f, 0x94, 0x78, 0x9b, 0x96, + 0x76, 0xeb, 0x72, 0x58, 0xe1, 0xc5, 0xc7, 0x5f, + 0x85, 0x01, 0xa8, 0xc4, 0xf6, 0x1a, 0xb5, 0x2c, + 0xd1, 0xd8, 0x87, 0xde, 0x3a, 0x9c, 0x9f, 0x57, + 0x81, 0x2a, 0x1e, 0x23, 0x07, 0x70, 0xb0, 0xf9, + 0x28, 0x3d, 0xfa, 0xe5, 0x2e, 0x1b, 0x9a, 0x72, + 0xc3, 0x74, 0xb3, 0x42, 0x1c, 0x9a, 0x13, 0xdc, + 0xc9, 0xd6, 0xd5, 0x88, 0xc9, 0x9c, 0x46, 0xf1, + 0x0c, 0xa6, 0xf7, 0xd8, 0x06, 0xa3, 0x1b, 0xdf, + 0x55, 0xb3, 0x1b, 0x7b, 0x58, 0x1d, 0xff, 0x19, + 0xc7, 0xe0, 0xdd, 0x59, 0xac, 0x2f, 0x78, 0x71, + 0xe7, 0xe0, 0x17, 0xa3, 0x1c, 0x5c, 0x92, 0xef, + 0xb6, 0x75, 0xed, 0xbe, 0x18, 0x39, 0x6b, 0xd7, + 0xc9, 0x08, 0x62, 0x55, 0x62, 0xac, 0x5d, 0xa1, + 0x9b, 0xd5, 0xb8, 0x98, 0x15, 0xc0, 0xf5, 0x41, + 0x85, 0x44, 0x96, 0xca, 0x10, 0xdc, 0x57, 0x21}; + + /* RSA Known Signed Hash (1024-bits). */ + static const PRUint8 rsa_known_sha512_signature[] = { + 0xa5, 0xd0, 0x80, 0x04, 0x22, 0xfc, 0x80, 0x73, + 0x7d, 0x46, 0xc8, 0x7b, 0xac, 0x44, 0x7b, 0xe6, + 0x07, 0xe5, 0x61, 0x4c, 0x33, 0x7f, 0x6f, 0x46, + 0x7c, 0x30, 0xe3, 0x75, 0x59, 0x4b, 0x42, 0xf3, + 0x9f, 0x35, 0x3c, 0x10, 0x56, 0xdb, 0xd2, 0x69, + 0x43, 0xcb, 0x77, 0xe9, 0x7d, 0xcd, 0x07, 0x43, + 0xc5, 0xd4, 0x0c, 0x9d, 0xf5, 0x92, 0xbd, 0x0e, + 0x3b, 0xb7, 0x68, 0x88, 0x84, 0xca, 0xae, 0x0d, + 0xab, 0x71, 0x10, 0xad, 0xab, 0x27, 0xe4, 0xa3, + 0x24, 0x41, 0xeb, 0x1c, 0xa6, 0x5f, 0xf1, 0x85, + 0xd0, 0xf6, 0x22, 0x74, 0x3d, 0x81, 0xbe, 0xdd, + 0x1b, 0x2a, 0x4c, 0xd1, 0x6c, 0xb5, 0x6d, 0x7a, + 0xbb, 0x99, 0x69, 0x01, 0xa6, 0xc0, 0x98, 0xfa, + 0x97, 0xa3, 0xd1, 0xb0, 0xdf, 0x09, 0xe3, 0x3d, + 0x88, 0xee, 0x90, 0xf3, 0x10, 0x41, 0x0f, 0x06, + 0x31, 0xe9, 0x60, 0x2d, 0xbf, 0x63, 0x7b, 0xf8}; + + static const RSAPublicKey bl_public_key = { NULL, + { FIPS_RSA_TYPE, (unsigned char *)rsa_modulus, + FIPS_RSA_MODULUS_LENGTH }, + { FIPS_RSA_TYPE, (unsigned char *)rsa_public_exponent, + FIPS_RSA_PUBLIC_EXPONENT_LENGTH } }; static const RSAPrivateKey bl_private_key = { NULL, - { FIPS_RSA_TYPE, (unsigned char *)rsa_version, FIPS_RSA_PRIVATE_VERSION_LENGTH }, - { FIPS_RSA_TYPE, (unsigned char *)rsa_modulus, FIPS_RSA_MODULUS_LENGTH }, - { FIPS_RSA_TYPE, (unsigned char *)rsa_public_exponent, FIPS_RSA_PUBLIC_EXPONENT_LENGTH }, - { FIPS_RSA_TYPE, (unsigned char *)rsa_private_exponent, FIPS_RSA_PRIVATE_EXPONENT_LENGTH }, - { FIPS_RSA_TYPE, (unsigned char *)rsa_prime0, FIPS_RSA_PRIME0_LENGTH }, - { FIPS_RSA_TYPE, (unsigned char *)rsa_prime1, FIPS_RSA_PRIME1_LENGTH }, - { FIPS_RSA_TYPE, (unsigned char *)rsa_exponent0, FIPS_RSA_EXPONENT0_LENGTH }, - { FIPS_RSA_TYPE, (unsigned char *)rsa_exponent1, FIPS_RSA_EXPONENT1_LENGTH }, - { FIPS_RSA_TYPE, (unsigned char *)rsa_coefficient, FIPS_RSA_COEFFICIENT_LENGTH } + { FIPS_RSA_TYPE, (unsigned char *)rsa_version, + FIPS_RSA_PRIVATE_VERSION_LENGTH }, + { FIPS_RSA_TYPE, (unsigned char *)rsa_modulus, + FIPS_RSA_MODULUS_LENGTH }, + { FIPS_RSA_TYPE, (unsigned char *)rsa_public_exponent, + FIPS_RSA_PUBLIC_EXPONENT_LENGTH }, + { FIPS_RSA_TYPE, (unsigned char *)rsa_private_exponent, + FIPS_RSA_PRIVATE_EXPONENT_LENGTH }, + { FIPS_RSA_TYPE, (unsigned char *)rsa_prime0, + FIPS_RSA_PRIME0_LENGTH }, + { FIPS_RSA_TYPE, (unsigned char *)rsa_prime1, + FIPS_RSA_PRIME1_LENGTH }, + { FIPS_RSA_TYPE, (unsigned char *)rsa_exponent0, + FIPS_RSA_EXPONENT0_LENGTH }, + { FIPS_RSA_TYPE, (unsigned char *)rsa_exponent1, + FIPS_RSA_EXPONENT1_LENGTH }, + { FIPS_RSA_TYPE, (unsigned char *)rsa_coefficient, + FIPS_RSA_COEFFICIENT_LENGTH } }; /* RSA variables. */ @@ -1170,14 +1386,12 @@ sftk_fips_RSA_PowerUpSelfTest( void ) #endif NSSLOWKEYPublicKey * rsa_public_key; NSSLOWKEYPrivateKey * rsa_private_key; - unsigned int rsa_bytes_signed; SECStatus rsa_status; NSSLOWKEYPublicKey low_public_key = { NULL, NSSLOWKEYRSAKey, }; NSSLOWKEYPrivateKey low_private_key = { NULL, NSSLOWKEYRSAKey, }; PRUint8 rsa_computed_ciphertext[FIPS_RSA_ENCRYPT_LENGTH]; PRUint8 rsa_computed_plaintext[FIPS_RSA_DECRYPT_LENGTH]; - PRUint8 rsa_computed_signature[FIPS_RSA_SIGNATURE_LENGTH]; /****************************************/ /* Compose RSA Public/Private Key Pair. */ @@ -1216,8 +1430,9 @@ sftk_fips_RSA_PowerUpSelfTest( void ) /**************************************************/ /* Perform RSA Public Key Encryption. */ - rsa_status = RSA_PublicKeyOp(&rsa_public_key->u.rsa, - rsa_computed_ciphertext, rsa_known_plaintext); + rsa_status = RSA_PublicKeyOp(&rsa_public_key->u.rsa, + rsa_computed_ciphertext, + rsa_known_plaintext_msg); if( ( rsa_status != SECSuccess ) || ( PORT_Memcmp( rsa_computed_ciphertext, rsa_known_ciphertext, @@ -1229,44 +1444,40 @@ sftk_fips_RSA_PowerUpSelfTest( void ) /**************************************************/ /* Perform RSA Private Key Decryption. */ - rsa_status = RSA_PrivateKeyOp(&rsa_private_key->u.rsa, - rsa_computed_plaintext, rsa_known_ciphertext); + rsa_status = RSA_PrivateKeyOp(&rsa_private_key->u.rsa, + rsa_computed_plaintext, + rsa_known_ciphertext); if( ( rsa_status != SECSuccess ) || - ( PORT_Memcmp( rsa_computed_plaintext, rsa_known_plaintext, + ( PORT_Memcmp( rsa_computed_plaintext, rsa_known_plaintext_msg, FIPS_RSA_DECRYPT_LENGTH ) != 0 ) ) goto rsa_loser; - - /*************************************************/ - /* RSA Single-Round Known Answer Signature Test. */ - /*************************************************/ - - /* Perform RSA signature with the RSA private key. */ - rsa_status = RSA_Sign( rsa_private_key, rsa_computed_signature, - &rsa_bytes_signed, - FIPS_RSA_SIGNATURE_LENGTH, - (unsigned char *)rsa_known_message, - FIPS_RSA_MESSAGE_LENGTH ); - - if( ( rsa_status != SECSuccess ) || - ( rsa_bytes_signed != FIPS_RSA_SIGNATURE_LENGTH ) || - ( PORT_Memcmp( rsa_computed_signature, rsa_known_signature, - FIPS_RSA_SIGNATURE_LENGTH ) != 0 ) ) + rsa_status = sftk_fips_RSA_PowerUpSigSelfTest (HASH_AlgSHA1, + rsa_public_key, rsa_private_key, + rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH, + rsa_known_sha1_signature); + if( rsa_status != SECSuccess ) goto rsa_loser; + rsa_status = sftk_fips_RSA_PowerUpSigSelfTest (HASH_AlgSHA256, + rsa_public_key, rsa_private_key, + rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH, + rsa_known_sha256_signature); + if( rsa_status != SECSuccess ) + goto rsa_loser; - /****************************************************/ - /* RSA Single-Round Known Answer Verification Test. */ - /****************************************************/ - - /* Perform RSA verification with the RSA public key. */ - rsa_status = RSA_CheckSign( rsa_public_key, - rsa_computed_signature, - FIPS_RSA_SIGNATURE_LENGTH, - (unsigned char *)rsa_known_message, - FIPS_RSA_MESSAGE_LENGTH ); + rsa_status = sftk_fips_RSA_PowerUpSigSelfTest (HASH_AlgSHA384, + rsa_public_key, rsa_private_key, + rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH, + rsa_known_sha384_signature); + if( rsa_status != SECSuccess ) + goto rsa_loser; + rsa_status = sftk_fips_RSA_PowerUpSigSelfTest (HASH_AlgSHA512, + rsa_public_key, rsa_private_key, + rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH, + rsa_known_sha512_signature); if( rsa_status != SECSuccess ) goto rsa_loser; @@ -1276,7 +1487,6 @@ sftk_fips_RSA_PowerUpSelfTest( void ) return( CKR_OK ); - rsa_loser: nsslowkey_DestroyPublicKey( rsa_public_key ); @@ -1285,33 +1495,235 @@ rsa_loser: return( CKR_DEVICE_ERROR ); } +#ifdef NSS_ENABLE_ECC + +static CK_RV +sftk_fips_ECDSA_Test(const PRUint8 *encodedParams, + unsigned int encodedParamsLen, + const PRUint8 *knownSignature, + unsigned int knownSignatureLen) { + + /* ECDSA Known Seed info for curves nistp256 and nistk283 */ + static const PRUint8 ecdsa_Known_Seed[] = { + 0x6a, 0x9b, 0xf6, 0xf7, 0xce, 0xed, 0x79, 0x11, + 0xf0, 0xc7, 0xc8, 0x9a, 0xa5, 0xd1, 0x57, 0xb1, + 0x7b, 0x5a, 0x3b, 0x76, 0x4e, 0x7b, 0x7c, 0xbc, + 0xf2, 0x76, 0x1c, 0x1c, 0x7f, 0xc5, 0x53, 0x2f}; + + static const PRUint8 msg[] = { + "Firefox and ThunderBird are awesome!"}; + + unsigned char sha1[SHA1_LENGTH]; /* SHA-1 hash (160 bits) */ + unsigned char sig[2*MAX_ECKEY_LEN]; + SECItem signature, digest; + SECItem encodedparams; + ECParams *ecparams = NULL; + ECPrivateKey *ecdsa_private_key = NULL; + ECPublicKey ecdsa_public_key; + SECStatus ecdsaStatus = SECSuccess; + + /* construct the ECDSA private/public key pair */ + encodedparams.type = siBuffer; + encodedparams.data = (unsigned char *) encodedParams; + encodedparams.len = encodedParamsLen; + + if (EC_DecodeParams(&encodedparams, &ecparams) != SECSuccess) { + return( CKR_DEVICE_ERROR ); + } + + /* Generates a new EC key pair. The private key is a supplied + * random value (in seed) and the public key is the result of + * performing a scalar point multiplication of that value with + * the curve's base point. + */ + ecdsaStatus = EC_NewKeyFromSeed(ecparams, &ecdsa_private_key, + ecdsa_Known_Seed, + sizeof(ecdsa_Known_Seed)); + /* free the ecparams they are no longer needed */ + PORT_FreeArena(ecparams->arena, PR_FALSE); + ecparams = NULL; + if (ecdsaStatus != SECSuccess) { + return ( CKR_DEVICE_ERROR ); + } + + /* construct public key from private key. */ + ecdsaStatus = EC_CopyParams(ecdsa_private_key->ecParams.arena, + &ecdsa_public_key.ecParams, + &ecdsa_private_key->ecParams); + if (ecdsaStatus != SECSuccess) { + goto loser; + } + ecdsa_public_key.publicValue = ecdsa_private_key->publicValue; + + /* validate public key value */ + ecdsaStatus = EC_ValidatePublicKey(&ecdsa_public_key.ecParams, + &ecdsa_public_key.publicValue); + if (ecdsaStatus != SECSuccess) { + goto loser; + } + + /* validate public key value */ + ecdsaStatus = EC_ValidatePublicKey(&ecdsa_private_key->ecParams, + &ecdsa_private_key->publicValue); + if (ecdsaStatus != SECSuccess) { + goto loser; + } + + /***************************************************/ + /* ECDSA Single-Round Known Answer Signature Test. */ + /***************************************************/ + + ecdsaStatus = SHA1_HashBuf(sha1, msg, sizeof msg); + if (ecdsaStatus != SECSuccess) { + goto loser; + } + digest.type = siBuffer; + digest.data = sha1; + digest.len = SHA1_LENGTH; + + memset(sig, 0, sizeof sig); + signature.type = siBuffer; + signature.data = sig; + signature.len = sizeof sig; + + ecdsaStatus = ECDSA_SignDigestWithSeed(ecdsa_private_key, &signature, + &digest, ecdsa_Known_Seed, sizeof ecdsa_Known_Seed); + if (ecdsaStatus != SECSuccess) { + goto loser; + } + + if( ( signature.len != knownSignatureLen ) || + ( PORT_Memcmp( signature.data, knownSignature, + knownSignatureLen ) != 0 ) ) { + ecdsaStatus = SECFailure; + goto loser; + } + + /******************************************************/ + /* ECDSA Single-Round Known Answer Verification Test. */ + /******************************************************/ + + /* Perform ECDSA verification process. */ + ecdsaStatus = ECDSA_VerifyDigest(&ecdsa_public_key, &signature, &digest); + +loser: + /* free the memory for the private key arena*/ + if (ecdsa_private_key != NULL) { + PORT_FreeArena(ecdsa_private_key->ecParams.arena, PR_FALSE); + } + + if (ecdsaStatus != SECSuccess) { + return CKR_DEVICE_ERROR ; + } + return( CKR_OK ); +} + +static CK_RV +sftk_fips_ECDSA_PowerUpSelfTest() { + + /* ECDSA Known curve nistp256 == SEC_OID_SECG_EC_SECP256R1 params */ + static const PRUint8 ecdsa_known_P256_EncodedParams[] = { + 0x06,0x08,0x2a,0x86,0x48,0xce,0x3d,0x03, + 0x01,0x07}; + + static const PRUint8 ecdsa_known_P256_signature[] = { + 0x07,0xb1,0xcb,0x57,0x20,0xa7,0x10,0xd6, + 0x9d,0x37,0x4b,0x1c,0xdc,0x35,0x90,0xff, + 0x1a,0x2d,0x98,0x95,0x1b,0x2f,0xeb,0x7f, + 0xbb,0x81,0xca,0xc0,0x69,0x75,0xea,0xc5, + 0x59,0x6a,0x62,0x49,0x3d,0x50,0xc9,0xe1, + 0x27,0x3b,0xff,0x9b,0x13,0x66,0x67,0xdd, + 0x7d,0xd1,0x0d,0x2d,0x7c,0x44,0x04,0x1b, + 0x16,0x21,0x12,0xc5,0xcb,0xbd,0x9e,0x75}; + +#ifdef NSS_ECC_MORE_THAN_SUITE_B + /* ECDSA Known curve nistk283 == SEC_OID_SECG_EC_SECT283K1 params */ + static const PRUint8 ecdsa_known_K283_EncodedParams[] = { + 0x06,0x05,0x2b,0x81,0x04,0x00,0x10}; + + static const PRUint8 ecdsa_known_K283_signature[] = { + 0x00,0x45,0x88,0xc0,0x79,0x09,0x07,0xd1, + 0x4e,0x88,0xe6,0xd5,0x2f,0x22,0x04,0x74, + 0x35,0x24,0x65,0xe8,0x15,0xde,0x90,0x66, + 0x94,0x70,0xdd,0x3a,0x14,0x70,0x02,0xd1, + 0xef,0x86,0xbd,0x15,0x00,0xd9,0xdc,0xfc, + 0x87,0x2e,0x7c,0x99,0xe2,0xe3,0x79,0xb8, + 0xd9,0x10,0x49,0x78,0x4b,0x59,0x8b,0x05, + 0x77,0xec,0x6c,0xe8,0x35,0xe6,0x2e,0xa9, + 0xf9,0x77,0x1f,0x71,0x86,0xa5,0x4a,0xd0}; +#endif + + CK_RV crv; + + /* ECDSA GF(p) prime field curve test */ + crv = sftk_fips_ECDSA_Test(ecdsa_known_P256_EncodedParams, + sizeof ecdsa_known_P256_EncodedParams, + ecdsa_known_P256_signature, + sizeof ecdsa_known_P256_signature ); + if (crv != CKR_OK) { + return( CKR_DEVICE_ERROR ); + } + +#ifdef NSS_ECC_MORE_THAN_SUITE_B + /* ECDSA GF(2m) binary field curve test */ + crv = sftk_fips_ECDSA_Test(ecdsa_known_K283_EncodedParams, + sizeof ecdsa_known_K283_EncodedParams, + ecdsa_known_K283_signature, + sizeof ecdsa_known_K283_signature ); + if (crv != CKR_OK) { + return( CKR_DEVICE_ERROR ); + } +#endif + + return( CKR_OK ); +} + +#endif /* NSS_ENABLE_ECC */ static CK_RV sftk_fips_DSA_PowerUpSelfTest( void ) { - /* DSA Known P (512-bits), Q (160-bits), and G (512-bits) Values. */ + /* DSA Known P (1024-bits), Q (160-bits), and G (1024-bits) Values. */ static const PRUint8 dsa_P[] = { - 0x8d,0xf2,0xa4,0x94,0x49,0x22,0x76,0xaa, - 0x3d,0x25,0x75,0x9b,0xb0,0x68,0x69,0xcb, - 0xea,0xc0,0xd8,0x3a,0xfb,0x8d,0x0c,0xf7, - 0xcb,0xb8,0x32,0x4f,0x0d,0x78,0x82,0xe5, - 0xd0,0x76,0x2f,0xc5,0xb7,0x21,0x0e,0xaf, - 0xc2,0xe9,0xad,0xac,0x32,0xab,0x7a,0xac, - 0x49,0x69,0x3d,0xfb,0xf8,0x37,0x24,0xc2, - 0xec,0x07,0x36,0xee,0x31,0xc8,0x02,0x91}; + 0x80,0xb0,0xd1,0x9d,0x6e,0xa4,0xf3,0x28, + 0x9f,0x24,0xa9,0x8a,0x49,0xd0,0x0c,0x63, + 0xe8,0x59,0x04,0xf9,0x89,0x4a,0x5e,0xc0, + 0x6d,0xd2,0x67,0x6b,0x37,0x81,0x83,0x0c, + 0xfe,0x3a,0x8a,0xfd,0xa0,0x3b,0x08,0x91, + 0x1c,0xcb,0xb5,0x63,0xb0,0x1c,0x70,0xd0, + 0xae,0xe1,0x60,0x2e,0x12,0xeb,0x54,0xc7, + 0xcf,0xc6,0xcc,0xae,0x97,0x52,0x32,0x63, + 0xd3,0xeb,0x55,0xea,0x2f,0x4c,0xd5,0xd7, + 0x3f,0xda,0xec,0x49,0x27,0x0b,0x14,0x56, + 0xc5,0x09,0xbe,0x4d,0x09,0x15,0x75,0x2b, + 0xa3,0x42,0x0d,0x03,0x71,0xdf,0x0f,0xf4, + 0x0e,0xe9,0x0c,0x46,0x93,0x3d,0x3f,0xa6, + 0x6c,0xdb,0xca,0xe5,0xac,0x96,0xc8,0x64, + 0x5c,0xec,0x4b,0x35,0x65,0xfc,0xfb,0x5a, + 0x1b,0x04,0x1b,0xa1,0x0e,0xfd,0x88,0x15}; + static const PRUint8 dsa_Q[] = { - 0xc7,0x73,0x21,0x8c,0x73,0x7e,0xc8,0xee, - 0x99,0x3b,0x4f,0x2d,0xed,0x30,0xf4,0x8e, - 0xda,0xce,0x91,0x5f}; + 0xad,0x22,0x59,0xdf,0xe5,0xec,0x4c,0x6e, + 0xf9,0x43,0xf0,0x4b,0x2d,0x50,0x51,0xc6, + 0x91,0x99,0x8b,0xcf}; + static const PRUint8 dsa_G[] = { - 0x62,0x6d,0x02,0x78,0x39,0xea,0x0a,0x13, - 0x41,0x31,0x63,0xa5,0x5b,0x4c,0xb5,0x00, - 0x29,0x9d,0x55,0x22,0x95,0x6c,0xef,0xcb, - 0x3b,0xff,0x10,0xf3,0x99,0xce,0x2c,0x2e, - 0x71,0xcb,0x9d,0xe5,0xfa,0x24,0xba,0xbf, - 0x58,0xe5,0xb7,0x95,0x21,0x92,0x5c,0x9c, - 0xc4,0x2e,0x9f,0x6f,0x46,0x4b,0x08,0x8c, - 0xc5,0x72,0xaf,0x53,0xe6,0xd7,0x88,0x02}; + 0x78,0x6e,0xa9,0xd8,0xcd,0x4a,0x85,0xa4, + 0x45,0xb6,0x6e,0x5d,0x21,0x50,0x61,0xf6, + 0x5f,0xdf,0x5c,0x7a,0xde,0x0d,0x19,0xd3, + 0xc1,0x3b,0x14,0xcc,0x8e,0xed,0xdb,0x17, + 0xb6,0xca,0xba,0x86,0xa9,0xea,0x51,0x2d, + 0xc1,0xa9,0x16,0xda,0xf8,0x7b,0x59,0x8a, + 0xdf,0xcb,0xa4,0x67,0x00,0x44,0xea,0x24, + 0x73,0xe5,0xcb,0x4b,0xaf,0x2a,0x31,0x25, + 0x22,0x28,0x3f,0x16,0x10,0x82,0xf7,0xeb, + 0x94,0x0d,0xdd,0x09,0x22,0x14,0x08,0x79, + 0xba,0x11,0x0b,0xf1,0xff,0x2d,0x67,0xac, + 0xeb,0xb6,0x55,0x51,0x69,0x97,0xa7,0x25, + 0x6b,0x9c,0xa0,0x9b,0xd5,0x08,0x9b,0x27, + 0x42,0x1c,0x7a,0x69,0x57,0xe6,0x2e,0xed, + 0xa9,0x5b,0x25,0xe8,0x1f,0xd2,0xed,0x1f, + 0xdf,0xe7,0x80,0x17,0xba,0x0d,0x4d,0x38}; /* DSA Known Random Values (known random key block is 160-bits) */ /* and (known random signature block is 160-bits). */ @@ -1325,11 +1737,11 @@ sftk_fips_DSA_PowerUpSelfTest( void ) /* DSA Known Signature (320-bits). */ static const PRUint8 dsa_known_signature[] = { - 0x39,0x0d,0x84,0xb1,0xf7,0x52,0x89,0xba, - 0xec,0x1e,0xa8,0xe2,0x00,0x8e,0x37,0x8f, - 0xc2,0xf5,0xf8,0x70,0x11,0xa8,0xc7,0x02, - 0x0e,0x75,0xcf,0x6b,0x54,0x4a,0x52,0xe8, - 0xd8,0x6d,0x4a,0xe8,0xee,0x56,0x8e,0x59}; + 0x25,0x7c,0x3a,0x79,0x32,0x45,0xb7,0x32, + 0x70,0xca,0x62,0x63,0x2b,0xf6,0x29,0x2c, + 0x22,0x2a,0x03,0xce,0x48,0x15,0x11,0x72, + 0x7b,0x7e,0xf5,0x7a,0xf3,0x10,0x3b,0xde, + 0x34,0xc1,0x9e,0xd7,0x27,0x9e,0x77,0x38}; /* DSA variables. */ DSAPrivateKey * dsa_private_key; @@ -1348,12 +1760,11 @@ sftk_fips_DSA_PowerUpSelfTest( void ) /*******************************************/ /* Generate a DSA public/private key pair. */ - dsa_status = DSA_NewKeyFromSeed(&dsa_pqg, dsa_known_random_key_block, &dsa_private_key); if( dsa_status != SECSuccess ) - return( CKR_HOST_MEMORY ); + return( CKR_HOST_MEMORY ); /* construct public key from private key. */ dsa_public_key.params = dsa_private_key->params; @@ -1372,8 +1783,8 @@ sftk_fips_DSA_PowerUpSelfTest( void ) /* Perform DSA signature process. */ dsa_status = DSA_SignDigestWithSeed( dsa_private_key, &dsa_signature_item, - &dsa_digest_item, - dsa_known_random_signature_block ); + &dsa_digest_item, + dsa_known_random_signature_block ); if( ( dsa_status != SECSuccess ) || ( dsa_signature_item.len != FIPS_DSA_SIGNATURE_LENGTH ) || @@ -1389,7 +1800,7 @@ sftk_fips_DSA_PowerUpSelfTest( void ) /* Perform DSA verification process. */ dsa_status = DSA_VerifyDigest( &dsa_public_key, &dsa_signature_item, - &dsa_digest_item); + &dsa_digest_item); } PORT_FreeArena(dsa_private_key->params.arena, PR_TRUE); @@ -1404,6 +1815,79 @@ sftk_fips_DSA_PowerUpSelfTest( void ) } +static CK_RV +sftk_fips_RNG_PowerUpSelfTest( void ) +{ + static const PRUint8 XKeyValue[] = { + 0x8d,0xf2,0xa4,0x94,0x49,0x22,0x76,0xaa, + 0x3d,0x25,0x75,0x9b,0xb0,0x68,0x69,0xcb, + 0xea,0xc0,0xd8,0x3a,0xfb,0x8d,0x0c,0xf7, + 0xcb,0xb8,0x32,0x4f,0x0d,0x78,0x82,0xe5}; + static const PRUint8 XSeed[] = { + 0xea,0xc0,0xd8,0x3a,0xfb,0x8d,0x0c,0xf7, + 0xcb,0xb8,0x32,0x4f,0x0d,0x78,0x82,0xe5, + 0xd0,0x76,0x2f,0xc5,0xb7,0x21,0x0e,0xaf, + 0xc2,0xe9,0xad,0xac,0x32,0xab,0x7a,0xac}; + static const PRUint8 Q[] = { + 0x85,0x89,0x9c,0x77,0xa3,0x79,0xff,0x1a, + 0x86,0x6f,0x2f,0x3e,0x2e,0xf9,0x8c,0x9c, + 0x9d,0xef,0xeb,0xed}; + static const PRUint8 rng_known_GENX[] = { + 0x65,0x48,0xe3,0xca,0xac,0x64,0x2d,0xf7, + 0x7b,0xd3,0x4e,0x79,0xc9,0x7d,0xa6,0xa8, + 0xa2,0xc2,0x1f,0x8f,0xe9,0xb9,0xd3,0xa1, + 0x3f,0xf7,0x0c,0xcd,0xa6,0xca,0xbf,0xce, + 0x84,0x0e,0xb6,0xf1,0x0d,0xbe,0xa9,0xa3}; + static const PRUint8 rng_known_DSAX[] = { + 0x7a,0x86,0xf1,0x7f,0xbd,0x4e,0x6e,0xd9, + 0x0a,0x26,0x21,0xd0,0x19,0xcb,0x86,0x73, + 0x10,0x1f,0x60,0xd7}; + + SECStatus rng_status = SECSuccess; + PRUint8 GENX[2*SHA1_LENGTH]; + PRUint8 DSAX[FIPS_DSA_SUBPRIME_LENGTH]; + PRUint8 XKey[FIPS_RNG_XKEY_LENGTH]; + + PORT_Memcpy (XKey, XKeyValue, FIPS_RNG_XKEY_LENGTH); + + /*******************************************/ + /* Generate X with a known seed. */ + /*******************************************/ + rng_status = FIPS186Change_GenerateX(XKey, XSeed, GENX); + + /* Verify GENX to perform the RNG integrity check */ + if( ( rng_status != SECSuccess ) || + ( PORT_Memcmp( GENX, rng_known_GENX, + (2*SHA1_LENGTH) ) != 0 ) ) + return( CKR_DEVICE_ERROR ); + + /*******************************************/ + /* Generate DSAX fow given Q. */ + /*******************************************/ + + rng_status = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX); + + /* Verify DSAX to perform the RNG integrity check */ + if( ( rng_status != SECSuccess ) || + ( PORT_Memcmp( DSAX, rng_known_DSAX, + (FIPS_DSA_SUBPRIME_LENGTH) ) != 0 ) ) + return( CKR_DEVICE_ERROR ); + + return( CKR_OK ); +} + +static CK_RV +sftk_fipsSoftwareIntegrityTest(void) +{ + CK_RV crv = CKR_OK; + + /* make sure that our check file signatures are OK */ + if( !BLAPI_VerifySelf( NULL ) || + !BLAPI_SHVerify( SOFTOKEN_LIB_NAME, (PRFuncPtr) sftk_fips_HMAC ) ) { + crv = CKR_DEVICE_ERROR; /* better error code? checksum error? */ + } + return crv; +} CK_RV sftk_fipsPowerUpSelfTest( void ) @@ -1488,6 +1972,26 @@ sftk_fipsPowerUpSelfTest( void ) if( rv != CKR_OK ) return rv; + /* RNG Power-Up SelfTest(s). */ + rv = sftk_fips_RNG_PowerUpSelfTest(); + + if( rv != CKR_OK ) + return rv; + +#ifdef NSS_ENABLE_ECC + /* ECDSA Power-Up SelfTest(s). */ + rv = sftk_fips_ECDSA_PowerUpSelfTest(); + + if( rv != CKR_OK ) + return rv; +#endif + + /* Software/Firmware Integrity Test. */ + rv = sftk_fipsSoftwareIntegrityTest(); + + if( rv != CKR_OK ) + return rv; + /* Passed Power-Up SelfTest(s). */ return( CKR_OK ); } diff --git a/security/nss/lib/softoken/fipstokn.c b/security/nss/lib/softoken/fipstokn.c index 9ef144cb8..6cfcfcb05 100644 --- a/security/nss/lib/softoken/fipstokn.c +++ b/security/nss/lib/softoken/fipstokn.c @@ -55,15 +55,77 @@ #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 + +#ifdef SOLARIS +#include <bsm/libbsm.h> +#define AUE_FIPS_AUDIT 34444 +#endif + +#ifdef LINUX +#include <pthread.h> +#include <dlfcn.h> +#define LIBAUDIT_NAME "libaudit.so.0" +#ifndef AUDIT_USER +#define AUDIT_USER 1005 /* message type: message from userspace */ +#endif +static void *libaudit_handle; +static int (*audit_open_func)(void); +static void (*audit_close_func)(int fd); +static int (*audit_log_user_message_func)(int audit_fd, int type, + const char *message, const char *hostname, const char *addr, + const char *tty, int result); +static int (*audit_send_user_message_func)(int fd, int type, + const char *message); + +static pthread_once_t libaudit_once_control = PTHREAD_ONCE_INIT; + +static void +libaudit_init(void) +{ + libaudit_handle = dlopen(LIBAUDIT_NAME, RTLD_LAZY); + if (!libaudit_handle) { + return; + } + audit_open_func = dlsym(libaudit_handle, "audit_open"); + audit_close_func = dlsym(libaudit_handle, "audit_close"); + /* + * audit_send_user_message is the older function. + * audit_log_user_message, if available, is preferred. + */ + audit_log_user_message_func = dlsym(libaudit_handle, + "audit_log_user_message"); + if (!audit_log_user_message_func) { + audit_send_user_message_func = dlsym(libaudit_handle, + "audit_send_user_message"); + } + if (!audit_open_func || !audit_close_func || + (!audit_log_user_message_func && !audit_send_user_message_func)) { + dlclose(libaudit_handle); + libaudit_handle = NULL; + audit_open_func = NULL; + audit_close_func = NULL; + audit_log_user_message_func = NULL; + audit_send_user_message_func = NULL; + } +} +#endif /* LINUX */ + /* * ******************** Password Utilities ******************************* */ static PRBool isLoggedIn = PR_FALSE; -static PRBool fatalError = PR_FALSE; +PRBool sftk_fatalError = PR_FALSE; /* * This function returns @@ -161,10 +223,10 @@ static CK_RV sftk_newPinCheck(CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { /* FIPS required checks before any useful cryptographic services */ static CK_RV sftk_fipsCheck(void) { - if (isLoggedIn != PR_TRUE) - return CKR_USER_NOT_LOGGED_IN; - if (fatalError) + if (sftk_fatalError) return CKR_DEVICE_ERROR; + if (!isLoggedIn) + return CKR_USER_NOT_LOGGED_IN; return CKR_OK; } @@ -174,7 +236,7 @@ static CK_RV sftk_fipsCheck(void) { if ((rv = sftk_fipsCheck()) != CKR_OK) return rv; #define SFTK_FIPSFATALCHECK() \ - if (fatalError) return CKR_DEVICE_ERROR; + if (sftk_fatalError) return CKR_DEVICE_ERROR; /* grab an attribute out of a raw template */ @@ -233,24 +295,135 @@ static CK_FUNCTION_LIST sftk_fipsTable = { #undef __PASTE +/* CKO_NOT_A_KEY can be any object class that's not a key object. */ +#define CKO_NOT_A_KEY CKO_DATA + +#define SFTK_IS_KEY_OBJECT(objClass) \ + (((objClass) == CKO_PUBLIC_KEY) || \ + ((objClass) == CKO_PRIVATE_KEY) || \ + ((objClass) == CKO_SECRET_KEY)) + +#define SFTK_IS_NONPUBLIC_KEY_OBJECT(objClass) \ + (((objClass) == CKO_PRIVATE_KEY) || ((objClass) == CKO_SECRET_KEY)) + static CK_RV -fips_login_if_key_object(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) +sftk_get_object_class_and_fipsCheck(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, CK_OBJECT_CLASS *pObjClass) { CK_RV rv; - CK_OBJECT_CLASS objClass; CK_ATTRIBUTE class; class.type = CKA_CLASS; - class.pValue = &objClass; - class.ulValueLen = sizeof(objClass); + class.pValue = pObjClass; + class.ulValueLen = sizeof(*pObjClass); rv = NSC_GetAttributeValue(hSession, hObject, &class, 1); - if (rv == CKR_OK) { - if ((objClass == CKO_PRIVATE_KEY) || (objClass == CKO_SECRET_KEY)) { - rv = sftk_fipsCheck(); - } + if ((rv == CKR_OK) && SFTK_IS_NONPUBLIC_KEY_OBJECT(*pObjClass)) { + rv = sftk_fipsCheck(); } 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 + 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 */ + syslog(level | LOG_USER /* facility */, + "NSS " SOFTOKEN_LIB_NAME "[pid=%d uid=%d]: %s", + (int)getpid(), (int)getuid(), msg); +#ifdef LINUX + if (pthread_once(&libaudit_once_control, libaudit_init) != 0) { + return; + } + if (libaudit_handle) { + int audit_fd; + int result = (severity != NSS_AUDIT_ERROR); /* 1=success; 0=failed */ + char *message = PR_smprintf("NSS " SOFTOKEN_LIB_NAME ": %s", msg); + if (!message) { + return; + } + audit_fd = audit_open_func(); + if (audit_fd < 0) { + PR_smprintf_free(message); + return; + } + if (audit_log_user_message_func) { + audit_log_user_message_func(audit_fd, AUDIT_USER, message, + NULL, NULL, NULL, result); + } else { + audit_send_user_message_func(audit_fd, AUDIT_USER, message); + } + audit_close_func(audit_fd); + PR_smprintf_free(message); + } +#endif /* LINUX */ +#ifdef SOLARIS + { + int rd; + char *message = PR_smprintf("NSS " SOFTOKEN_LIB_NAME ": %s", msg); + + if (!message) { + return; + } + + /* open the record descriptor */ + if ((rd = au_open()) == -1) { + PR_smprintf_free(message); + return; + } + + /* write the audit tokens to the audit record */ + if (au_write(rd, au_to_text(message))) { + (void)au_close(rd, AU_TO_NO_WRITE, AUE_FIPS_AUDIT); + PR_smprintf_free(message); + return; + } + + /* close the record and send it to the audit trail */ + (void)au_close(rd, AU_TO_WRITE, AUE_FIPS_AUDIT); + + PR_smprintf_free(message); + } +#endif /* SOLARIS */ +#else + /* do nothing */ +#endif +} + /********************************************************************** * @@ -268,26 +441,39 @@ 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*/ if (crv != CKR_OK) { - fatalError = PR_TRUE; + sftk_fatalError = PR_TRUE; return crv; } - fatalError = PR_FALSE; /* any error has been reset */ + sftk_fatalError = PR_FALSE; /* any error has been reset */ crv = sftk_fipsPowerUpSelfTest(); if (crv != CKR_OK) { nsc_CommonFinalize(NULL, PR_TRUE); - fatalError = PR_TRUE; + sftk_fatalError = PR_TRUE; + if (sftk_audit_enabled) { + char msg[128]; + PR_snprintf(msg,sizeof msg, + "C_Initialize()=0x%08lX " + "power-up self-tests failed", + (PRUint32)crv); + sftk_LogAuditMessage(NSS_AUDIT_ERROR, msg); + } return crv; } nsf_init = PR_TRUE; @@ -321,15 +507,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); } @@ -338,7 +516,8 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV crv; crv = NSC_GetTokenInfo(slotID,pInfo); - pInfo->flags |= CKF_RNG | CKF_LOGIN_REQUIRED; + if (crv == CKR_OK) + pInfo->flags |= CKF_LOGIN_REQUIRED; return crv; } @@ -369,7 +548,20 @@ 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; } @@ -377,9 +569,20 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { 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 (sftk_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=0x%08lX)=0x%08lX", + (PRUint32)hSession,(PRUint32)rv); + sftk_LogAuditMessage(severity, msg); + } + return rv; } @@ -388,9 +591,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=0x%08lX)=0x%08lX", + (PRUint32)hSession,(PRUint32)rv); + sftk_LogAuditMessage(severity, msg); + } + return rv; } /* FC_OpenSession opens a session between an application and a token. */ @@ -435,30 +649,40 @@ 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(); + PRBool successful; + if (sftk_fatalError) return CKR_DEVICE_ERROR; rv = NSC_Login(hSession,userType,pPin,usPinLen); - if (rv == CKR_OK) + successful = (rv == CKR_OK) || (rv == CKR_USER_ALREADY_LOGGED_IN); + if (successful) 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. */ - rv = sftk_fipsPowerUpSelfTest(); - if (rv == CKR_OK) - return CKR_USER_ALREADY_LOGGED_IN; - else - fatalError = PR_TRUE; + if (sftk_audit_enabled) { + char msg[128]; + NSSAuditSeverity severity; + severity = successful ? NSS_AUDIT_INFO : NSS_AUDIT_ERROR; + PR_snprintf(msg,sizeof msg, + "C_Login(hSession=0x%08lX, 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=0x%08lX)=0x%08lX", + (PRUint32)hSession,(PRUint32)rv); + sftk_LogAuditMessage(severity, msg); + } return rv; } @@ -473,10 +697,15 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { if (classptr == NULL) return CKR_TEMPLATE_INCOMPLETE; /* FIPS can't create keys from raw key material */ - if ((*classptr == CKO_SECRET_KEY) || (*classptr == CKO_PRIVATE_KEY)) { - return CKR_ATTRIBUTE_VALUE_INVALID; + if (SFTK_IS_NONPUBLIC_KEY_OBJECT(*classptr)) { + rv = CKR_ATTRIBUTE_VALUE_INVALID; + } else { + rv = NSC_CreateObject(hSession,pTemplate,ulCount,phObject); } - return NSC_CreateObject(hSession,pTemplate,ulCount,phObject); + if (sftk_audit_enabled && SFTK_IS_KEY_OBJECT(*classptr)) { + sftk_AuditCreateObject(hSession,pTemplate,ulCount,phObject,rv); + } + return rv; } @@ -485,15 +714,20 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { /* FC_CopyObject copies an object, creating a new object for the copy. */ CK_RV FC_CopyObject(CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount, + CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject) { CK_RV rv; + CK_OBJECT_CLASS objClass = CKO_NOT_A_KEY; SFTK_FIPSFATALCHECK(); - rv = fips_login_if_key_object(hSession, hObject); - if (rv != CKR_OK) { - return rv; + rv = sftk_get_object_class_and_fipsCheck(hSession, hObject, &objClass); + if (rv == CKR_OK) { + rv = NSC_CopyObject(hSession,hObject,pTemplate,ulCount,phNewObject); } - return NSC_CopyObject(hSession,hObject,pTemplate,usCount,phNewObject); + if (sftk_audit_enabled && SFTK_IS_KEY_OBJECT(objClass)) { + sftk_AuditCopyObject(hSession, + hObject,pTemplate,ulCount,phNewObject,rv); + } + return rv; } @@ -501,51 +735,67 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV FC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) { CK_RV rv; + CK_OBJECT_CLASS objClass = CKO_NOT_A_KEY; SFTK_FIPSFATALCHECK(); - rv = fips_login_if_key_object(hSession, hObject); - if (rv != CKR_OK) { - return rv; + rv = sftk_get_object_class_and_fipsCheck(hSession, hObject, &objClass); + if (rv == CKR_OK) { + rv = NSC_DestroyObject(hSession,hObject); + } + if (sftk_audit_enabled && SFTK_IS_KEY_OBJECT(objClass)) { + sftk_AuditDestroyObject(hSession,hObject,rv); } - return NSC_DestroyObject(hSession,hObject); + return rv; } /* FC_GetObjectSize gets the size of an object in bytes. */ CK_RV FC_GetObjectSize(CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pusSize) { + CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) { CK_RV rv; + CK_OBJECT_CLASS objClass = CKO_NOT_A_KEY; SFTK_FIPSFATALCHECK(); - rv = fips_login_if_key_object(hSession, hObject); - if (rv != CKR_OK) { - return rv; + rv = sftk_get_object_class_and_fipsCheck(hSession, hObject, &objClass); + if (rv == CKR_OK) { + rv = NSC_GetObjectSize(hSession, hObject, pulSize); + } + if (sftk_audit_enabled && SFTK_IS_KEY_OBJECT(objClass)) { + sftk_AuditGetObjectSize(hSession, hObject, pulSize, rv); } - return NSC_GetObjectSize(hSession, hObject, pusSize); + return rv; } /* FC_GetAttributeValue obtains the value of one or more object attributes. */ CK_RV FC_GetAttributeValue(CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG usCount) { + CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount) { CK_RV rv; + CK_OBJECT_CLASS objClass = CKO_NOT_A_KEY; SFTK_FIPSFATALCHECK(); - rv = fips_login_if_key_object(hSession, hObject); - if (rv != CKR_OK) { - return rv; + rv = sftk_get_object_class_and_fipsCheck(hSession, hObject, &objClass); + if (rv == CKR_OK) { + rv = NSC_GetAttributeValue(hSession,hObject,pTemplate,ulCount); + } + if (sftk_audit_enabled && SFTK_IS_KEY_OBJECT(objClass)) { + sftk_AuditGetAttributeValue(hSession,hObject,pTemplate,ulCount,rv); } - return NSC_GetAttributeValue(hSession,hObject,pTemplate,usCount); + return rv; } /* FC_SetAttributeValue modifies the value of one or more object attributes */ CK_RV FC_SetAttributeValue (CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG usCount) { + CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount) { CK_RV rv; + CK_OBJECT_CLASS objClass = CKO_NOT_A_KEY; SFTK_FIPSFATALCHECK(); - rv = fips_login_if_key_object(hSession, hObject); - if (rv != CKR_OK) { - return rv; + rv = sftk_get_object_class_and_fipsCheck(hSession, hObject, &objClass); + if (rv == CKR_OK) { + rv = NSC_SetAttributeValue(hSession,hObject,pTemplate,ulCount); + } + if (sftk_audit_enabled && SFTK_IS_KEY_OBJECT(objClass)) { + sftk_AuditSetAttributeValue(hSession,hObject,pTemplate,ulCount,rv); } - return NSC_SetAttributeValue(hSession,hObject,pTemplate,usCount); + return rv; } @@ -605,7 +855,11 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV FC_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SFTK_FIPSCHECK(); - return NSC_EncryptInit(hSession,pMechanism,hKey); + rv = NSC_EncryptInit(hSession,pMechanism,hKey); + if (sftk_audit_enabled) { + sftk_AuditCryptInit("Encrypt",hSession,pMechanism,hKey,rv); + } + return rv; } /* FC_Encrypt encrypts single-part data. */ @@ -646,7 +900,11 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV FC_DecryptInit( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SFTK_FIPSCHECK(); - return NSC_DecryptInit(hSession,pMechanism,hKey); + rv = NSC_DecryptInit(hSession,pMechanism,hKey); + if (sftk_audit_enabled) { + sftk_AuditCryptInit("Decrypt",hSession,pMechanism,hKey,rv); + } + return rv; } /* FC_Decrypt decrypts encrypted data in a single part. */ @@ -724,7 +982,11 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV FC_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SFTK_FIPSCHECK(); - return NSC_SignInit(hSession,pMechanism,hKey); + rv = NSC_SignInit(hSession,pMechanism,hKey); + if (sftk_audit_enabled) { + sftk_AuditCryptInit("Sign",hSession,pMechanism,hKey,rv); + } + return rv; } @@ -766,7 +1028,11 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV FC_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) { SFTK_FIPSCHECK(); - return NSC_SignRecoverInit(hSession,pMechanism,hKey); + rv = NSC_SignRecoverInit(hSession,pMechanism,hKey); + if (sftk_audit_enabled) { + sftk_AuditCryptInit("SignRecover",hSession,pMechanism,hKey,rv); + } + return rv; } @@ -789,7 +1055,11 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV FC_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) { SFTK_FIPSCHECK(); - return NSC_VerifyInit(hSession,pMechanism,hKey); + rv = NSC_VerifyInit(hSession,pMechanism,hKey); + if (sftk_audit_enabled) { + sftk_AuditCryptInit("Verify",hSession,pMechanism,hKey,rv); + } + return rv; } @@ -832,7 +1102,11 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV FC_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) { SFTK_FIPSCHECK(); - return NSC_VerifyRecoverInit(hSession,pMechanism,hKey); + rv = NSC_VerifyRecoverInit(hSession,pMechanism,hKey); + if (sftk_audit_enabled) { + sftk_AuditCryptInit("VerifyRecover",hSession,pMechanism,hKey,rv); + } + return rv; } @@ -868,7 +1142,11 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { } } - return NSC_GenerateKey(hSession,pMechanism,pTemplate,ulCount,phKey); + rv = NSC_GenerateKey(hSession,pMechanism,pTemplate,ulCount,phKey); + if (sftk_audit_enabled) { + sftk_AuditGenerateKey(hSession,pMechanism,pTemplate,ulCount,phKey,rv); + } + return rv; } @@ -898,7 +1176,12 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { usPrivateKeyAttributeCount,phPublicKey,phPrivateKey); if (crv == CKR_GENERAL_ERROR) { /* pairwise consistency check failed. */ - fatalError = PR_TRUE; + sftk_fatalError = PR_TRUE; + } + if (sftk_audit_enabled) { + sftk_AuditGenerateKeyPair(hSession,pMechanism,pPublicKeyTemplate, + usPublicKeyAttributeCount,pPrivateKeyTemplate, + usPrivateKeyAttributeCount,phPublicKey,phPrivateKey,crv); } return crv; } @@ -908,18 +1191,23 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV FC_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, - CK_ULONG_PTR pusWrappedKeyLen) { + CK_ULONG_PTR pulWrappedKeyLen) { SFTK_FIPSCHECK(); - return NSC_WrapKey(hSession,pMechanism,hWrappingKey,hKey,pWrappedKey, - pusWrappedKeyLen); + rv = NSC_WrapKey(hSession,pMechanism,hWrappingKey,hKey,pWrappedKey, + pulWrappedKeyLen); + if (sftk_audit_enabled) { + sftk_AuditWrapKey(hSession,pMechanism,hWrappingKey,hKey,pWrappedKey, + pulWrappedKeyLen,rv); + } + return rv; } /* FC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */ CK_RV FC_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, - CK_BYTE_PTR pWrappedKey, CK_ULONG usWrappedKeyLen, - CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usAttributeCount, + CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) { CK_BBOOL *boolptr; @@ -928,21 +1216,26 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { /* all secret keys must be sensitive, if the upper level code tries to say * otherwise, reject it. */ boolptr = (CK_BBOOL *) fc_getAttribute(pTemplate, - usAttributeCount, CKA_SENSITIVE); + ulAttributeCount, CKA_SENSITIVE); if (boolptr != NULL) { if (!(*boolptr)) { return CKR_ATTRIBUTE_VALUE_INVALID; } } - return NSC_UnwrapKey(hSession,pMechanism,hUnwrappingKey,pWrappedKey, - usWrappedKeyLen,pTemplate,usAttributeCount,phKey); + rv = NSC_UnwrapKey(hSession,pMechanism,hUnwrappingKey,pWrappedKey, + ulWrappedKeyLen,pTemplate,ulAttributeCount,phKey); + if (sftk_audit_enabled) { + sftk_AuditUnwrapKey(hSession,pMechanism,hUnwrappingKey,pWrappedKey, + ulWrappedKeyLen,pTemplate,ulAttributeCount,phKey,rv); + } + return rv; } /* FC_DeriveKey derives a key from a base key, creating a new key object. */ CK_RV FC_DeriveKey( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, - CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usAttributeCount, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) { CK_BBOOL *boolptr; @@ -951,14 +1244,19 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { /* all secret keys must be sensitive, if the upper level code tries to say * otherwise, reject it. */ boolptr = (CK_BBOOL *) fc_getAttribute(pTemplate, - usAttributeCount, CKA_SENSITIVE); + ulAttributeCount, CKA_SENSITIVE); if (boolptr != NULL) { if (!(*boolptr)) { return CKR_ATTRIBUTE_VALUE_INVALID; } } - return NSC_DeriveKey(hSession,pMechanism,hBaseKey,pTemplate, - usAttributeCount, phKey); + rv = NSC_DeriveKey(hSession,pMechanism,hBaseKey,pTemplate, + ulAttributeCount, phKey); + if (sftk_audit_enabled) { + sftk_AuditDeriveKey(hSession,pMechanism,hBaseKey,pTemplate, + ulAttributeCount,phKey,rv); + } + return rv; } /* @@ -974,7 +1272,7 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { SFTK_FIPSFATALCHECK(); crv = NSC_SeedRandom(hSession,pSeed,usSeedLen); if (crv != CKR_OK) { - fatalError = PR_TRUE; + sftk_fatalError = PR_TRUE; } return crv; } @@ -982,13 +1280,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; + sftk_fatalError = PR_TRUE; + if (sftk_audit_enabled) { + char msg[128]; + PR_snprintf(msg,sizeof msg, + "C_GenerateRandom(hSession=0x%08lX, 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; } @@ -1091,7 +1399,11 @@ CK_RV FC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, */ CK_RV FC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) { SFTK_FIPSCHECK(); - return NSC_DigestKey(hSession,hKey); + rv = NSC_DigestKey(hSession,hKey); + if (sftk_audit_enabled) { + sftk_AuditDigestKey(hSession,hKey,rv); + } + return rv; } diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/keydb.c index 2f685a5a6..81e2802ea 100644 --- a/security/nss/lib/softoken/keydb.c +++ b/security/nss/lib/softoken/keydb.c @@ -49,15 +49,10 @@ #include "lowpbe.h" #include "secerr.h" #include "cdbhdl.h" -#include "nsslocks.h" #include "keydbi.h" +#include "softoken.h" -#ifdef NSS_ENABLE_ECC -extern SECStatus EC_FillParams(PRArenaPool *arena, - const SECItem *encodedParams, - ECParams *params); -#endif /* * Record keys for keydb @@ -175,7 +170,7 @@ static void keydb_InitLocks(NSSLOWKEYDBHandle *handle) { if (handle->lock == NULL) { - nss_InitLock(&handle->lock, nssILockKeyDB); + handle->lock = PZ_NewLock(nssILockKeyDB); } return; @@ -584,13 +579,18 @@ makeGlobalSalt(NSSLOWKEYDBHandle *handle) DBT saltData; unsigned char saltbuf[16]; int status; + SECStatus rv; saltKey.data = SALT_STRING; saltKey.size = sizeof(SALT_STRING) - 1; saltData.data = (void *)saltbuf; saltData.size = sizeof(saltbuf); - RNG_GenerateGlobalRandomBytes(saltbuf, sizeof(saltbuf)); + rv = RNG_GenerateGlobalRandomBytes(saltbuf, sizeof(saltbuf)); + if ( rv != SECSuccess ) { + sftk_fatalError = PR_TRUE; + return(rv); + } /* put global salt into the database now */ status = keydb_Put(handle, &saltKey, &saltData, 0); @@ -717,7 +717,6 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) DBT key; DBT data; unsigned char version; - SECItem *rc4key = NULL; NSSLOWKEYDBKey *dbkey = NULL; NSSLOWKEYDBHandle *update = NULL; SECItem *oldSalt = NULL; @@ -886,10 +885,6 @@ done: nsslowkey_CloseKeyDB(update); - if ( rc4key ) { - SECITEM_FreeItem(rc4key, PR_TRUE); - } - if ( oldSalt ) { SECITEM_FreeItem(oldSalt, PR_TRUE); } @@ -942,7 +937,7 @@ openNewDB(const char *appName, const char *prefix, const char *dbname, * local database we can update from. */ if (appName) { - NSSLOWKEYDBHandle *updateHandle = nsslowkey_NewHandle(updatedb); + NSSLOWKEYDBHandle *updateHandle; updatedb = dbopen( dbname, NO_RDONLY, 0600, DB_HASH, 0 ); if (!updatedb) { goto noupdate; @@ -1429,50 +1424,6 @@ nsslowkey_DeriveKeyDBPassword(NSSLOWKEYDBHandle *keydb, char *pw) return nsslowkey_HashPassword(pw, keydb->global_salt); } -#if 0 -/* Appears obsolete - TNH */ -/* get the algorithm with which a private key - * is encrypted. - */ -SECOidTag -seckey_get_private_key_algorithm(NSSLOWKEYDBHandle *keydb, DBT *index) -{ - NSSLOWKEYDBKey *dbkey = NULL; - SECOidTag algorithm = SEC_OID_UNKNOWN; - NSSLOWKEYEncryptedPrivateKeyInfo *epki = NULL; - PLArenaPool *poolp = NULL; - SECStatus rv; - - poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if(poolp == NULL) - return (SECOidTag)SECFailure; /* TNH - this is bad */ - - dbkey = get_dbkey(keydb, index); - if(dbkey == NULL) - return (SECOidTag)SECFailure; - - epki = (NSSLOWKEYEncryptedPrivateKeyInfo *)PORT_ArenaZAlloc(poolp, - sizeof(NSSLOWKEYEncryptedPrivateKeyInfo)); - if(epki == NULL) - goto loser; - rv = SEC_ASN1DecodeItem(poolp, epki, - nsslowkey_EncryptedPrivateKeyInfoTemplate, &dbkey->derPK); - if(rv == SECFailure) - goto loser; - - algorithm = SECOID_GetAlgorithmTag(&epki->algorithm); - - /* let success fall through */ -loser: - if(poolp != NULL) - PORT_FreeArena(poolp, PR_TRUE);\ - if(dbkey != NULL) - sec_destroy_dbkey(dbkey); - - return algorithm; -} -#endif - /* * Derive an RC4 key from a password key and a salt. This * was the method to used to encrypt keys in the version 2? @@ -1531,11 +1482,12 @@ seckey_create_rc4_salt(void) if(salt->data != NULL) { salt->len = SALT_LENGTH; - RNG_GenerateGlobalRandomBytes(salt->data, salt->len); - rv = SECSuccess; + rv = RNG_GenerateGlobalRandomBytes(salt->data, salt->len); + if(rv != SECSuccess) + sftk_fatalError = PR_TRUE; } - if(rv == SECFailure) + if(rv != SECSuccess) { SECITEM_FreeItem(salt, PR_TRUE); salt = NULL; @@ -1816,7 +1768,7 @@ seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SECItem *pwitem, { NSSLOWKEYDBKey *dbkey = NULL; NSSLOWKEYEncryptedPrivateKeyInfo *epki = NULL; - PLArenaPool *temparena = NULL, *permarena = NULL; + PLArenaPool *arena = NULL; SECItem *dummy = NULL; SECItem *salt = NULL; SECStatus rv = SECFailure; @@ -1825,14 +1777,14 @@ seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SECItem *pwitem, (pk == NULL)) return SECFailure; - permarena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); - if(permarena == NULL) + arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); + if(arena == NULL) return SECFailure; - dbkey = (NSSLOWKEYDBKey *)PORT_ArenaZAlloc(permarena, sizeof(NSSLOWKEYDBKey)); + dbkey = (NSSLOWKEYDBKey *)PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYDBKey)); if(dbkey == NULL) goto loser; - dbkey->arena = permarena; + dbkey->arena = arena; dbkey->nickname = nickname; /* TNH - for RC4, the salt should be created here */ @@ -1840,15 +1792,14 @@ seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SECItem *pwitem, epki = seckey_encrypt_private_key(pk, pwitem, keydb, algorithm, &salt); if(epki == NULL) goto loser; - temparena = epki->arena; if(salt != NULL) { - rv = SECITEM_CopyItem(permarena, &(dbkey->salt), salt); + rv = SECITEM_CopyItem(arena, &(dbkey->salt), salt); SECITEM_ZfreeItem(salt, PR_TRUE); } - dummy = SEC_ASN1EncodeItem(permarena, &(dbkey->derPK), epki, + dummy = SEC_ASN1EncodeItem(arena, &(dbkey->derPK), epki, nsslowkey_EncryptedPrivateKeyInfoTemplate); if(dummy == NULL) rv = SECFailure; @@ -1857,11 +1808,10 @@ seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SECItem *pwitem, /* let success fall through */ loser: - if(rv != SECSuccess) - if(permarena != NULL) - PORT_FreeArena(permarena, PR_TRUE); - if(temparena != NULL) - PORT_FreeArena(temparena, PR_TRUE); + if(arena != NULL) + PORT_FreeArena(arena, PR_TRUE); + if(epki != NULL) + PORT_FreeArena(epki->arena, PR_TRUE); return rv; } @@ -2046,6 +1996,9 @@ seckey_decrypt_private_key(NSSLOWKEYEncryptedPrivateKeyInfo *epki, rv = EC_FillParams(permarena, &pk->u.ec.ecParams.DEREncoding, &pk->u.ec.ecParams); + if (rv != SECSuccess) + goto loser; + /* * NOTE: Encoding of the publicValue is optional * so we need to be able to regenerate the publicValue diff --git a/security/nss/lib/softoken/lowcert.c b/security/nss/lib/softoken/lowcert.c index cb048307d..008687e52 100644 --- a/security/nss/lib/softoken/lowcert.c +++ b/security/nss/lib/softoken/lowcert.c @@ -51,12 +51,8 @@ #include "secasn1.h" #include "secoid.h" #include "secerr.h" +#include "softoken.h" -#ifdef NSS_ENABLE_ECC -extern SECStatus EC_FillParams(PRArenaPool *arena, - const SECItem *encodedParams, - ECParams *params); -#endif static const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTSubjectPublicKeyInfo) }, diff --git a/security/nss/lib/softoken/lowkey.c b/security/nss/lib/softoken/lowkey.c index fb6e30fdc..9c984b4d3 100644 --- a/security/nss/lib/softoken/lowkey.c +++ b/security/nss/lib/softoken/lowkey.c @@ -295,7 +295,6 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk) if (rv == SECSuccess) return pubk; } - nsslowkey_DestroyPublicKey (pubk); } else { PORT_SetError (SEC_ERROR_NO_MEMORY); } diff --git a/security/nss/lib/softoken/lowpbe.c b/security/nss/lib/softoken/lowpbe.c index 81a0cb06b..6b4605b4e 100644 --- a/security/nss/lib/softoken/lowpbe.c +++ b/security/nss/lib/softoken/lowpbe.c @@ -546,13 +546,15 @@ loser: PORT_FreeArena(arena, PR_TRUE); } - /* if i != c, then we didn't complete the loop above and must of failed - * somwhere along the way */ - if (i != c) { - SECITEM_ZfreeItem(A,PR_TRUE); - A = NULL; - } else { - A->len = bytesNeeded; + if (A) { + /* if i != c, then we didn't complete the loop above and must of failed + * somwhere along the way */ + if (i != c) { + SECITEM_ZfreeItem(A,PR_TRUE); + A = NULL; + } else { + A->len = bytesNeeded; + } } return A; @@ -634,7 +636,7 @@ nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, PORT_Memcpy(key->data, hash->data, key->len); } - SECITEM_FreeItem(hash, PR_TRUE); + SECITEM_ZfreeItem(hash, PR_TRUE); return key; loser: @@ -822,7 +824,7 @@ void nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *pbe_param) { if (pbe_param != NULL) { - PORT_FreeArena(pbe_param->poolp, PR_TRUE); + PORT_FreeArena(pbe_param->poolp, PR_FALSE); } } diff --git a/security/nss/lib/softoken/manifest.mn b/security/nss/lib/softoken/manifest.mn index 52d1f75cd..5df3a4517 100644 --- a/security/nss/lib/softoken/manifest.mn +++ b/security/nss/lib/softoken/manifest.mn @@ -59,12 +59,19 @@ EXPORTS = \ PRIVATE_EXPORTS = \ pk11pars.h \ pkcs11ni.h \ + lowkeyi.h \ + lowkeyti.h \ + pcertt.h \ + softoken.h \ + softoknt.h \ + softkver.h \ $(NULL) CSRCS = \ dbinit.c \ dbmshim.c \ ecdecode.c \ + fipsaudt.c \ fipstest.c \ fipstokn.c \ keydb.c \ diff --git a/security/nss/lib/softoken/pcert.h b/security/nss/lib/softoken/pcert.h index a808373d8..d4314f634 100644 --- a/security/nss/lib/softoken/pcert.h +++ b/security/nss/lib/softoken/pcert.h @@ -41,9 +41,16 @@ #include "prlong.h" #include "pcertt.h" +#include "lowkeyti.h" /* for struct NSSLOWKEYPublicKeyStr */ + SEC_BEGIN_PROTOS /* + * initialize any global certificate locks + */ +SECStatus nsslowcert_InitLocks(void); + +/* ** Add a DER encoded certificate to the permanent database. ** "derCert" is the DER encoded certificate. ** "nickname" is the nickname to use for the cert @@ -244,6 +251,11 @@ pkcs11_copyStaticData(unsigned char *data, int datalen, unsigned char *space, int spaceLen); NSSLOWCERTCertificate * nsslowcert_CreateCert(void); + +certDBEntry * +nsslowcert_DecodeAnyDBEntry(SECItem *dbData, SECItem *dbKey, + certDBEntryType entryType, void *pdata); + SEC_END_PROTOS #endif /* _PCERTDB_H_ */ diff --git a/security/nss/lib/softoken/pcertdb.c b/security/nss/lib/softoken/pcertdb.c index 4a7706378..6630b6134 100644 --- a/security/nss/lib/softoken/pcertdb.c +++ b/security/nss/lib/softoken/pcertdb.c @@ -54,7 +54,6 @@ #include "secerr.h" #include "nssilock.h" #include "prmon.h" -#include "nsslocks.h" #include "base64.h" #include "sechash.h" #include "plhash.h" @@ -91,16 +90,42 @@ static int entryListCount = 0; * a global lock to make the database thread safe. */ static PZLock *dbLock = NULL; +static PZLock *certRefCountLock = NULL; +static PZLock *certTrustLock = NULL; +static PZLock *freeListLock = NULL; void certdb_InitDBLock(NSSLOWCERTCertDBHandle *handle) { if (dbLock == NULL) { - nss_InitLock(&dbLock, nssILockCertDB); + dbLock = PZ_NewLock(nssILockCertDB); PORT_Assert(dbLock != NULL); } +} - return; +SECStatus +nsslowcert_InitLocks(void) +{ + if (freeListLock == NULL) { + freeListLock = PZ_NewLock(nssILockRefLock); + if (freeListLock == NULL) { + return SECFailure; + } + } + if (certRefCountLock == NULL) { + certRefCountLock = PZ_NewLock(nssILockRefLock); + if (certRefCountLock == NULL) { + return SECFailure; + } + } + if (certTrustLock == NULL ) { + certTrustLock = PZ_NewLock(nssILockCertDB); + if (certTrustLock == NULL) { + return SECFailure; + } + } + + return SECSuccess; } /* @@ -133,7 +158,6 @@ nsslowcert_UnlockDB(NSSLOWCERTCertDBHandle *handle) return; } -static PZLock *certRefCountLock = NULL; /* * Acquire the cert reference count lock @@ -144,10 +168,7 @@ static PZLock *certRefCountLock = NULL; static void nsslowcert_LockCertRefCount(NSSLOWCERTCertificate *cert) { - if ( certRefCountLock == NULL ) { - nss_InitLock(&certRefCountLock, nssILockRefLock); - PORT_Assert(certRefCountLock != NULL); - } + PORT_Assert(certRefCountLock != NULL); PZ_Lock(certRefCountLock); return; @@ -170,8 +191,6 @@ nsslowcert_UnlockCertRefCount(NSSLOWCERTCertificate *cert) return; } -static PZLock *certTrustLock = NULL; - /* * Acquire the cert trust lock * There is currently one global lock for all certs, but I'm putting a cert @@ -181,11 +200,8 @@ static PZLock *certTrustLock = NULL; void nsslowcert_LockCertTrust(NSSLOWCERTCertificate *cert) { - if ( certTrustLock == NULL ) { - nss_InitLock(&certTrustLock, nssILockCertDB); - PORT_Assert(certTrustLock != NULL); - } - + PORT_Assert(certTrustLock != NULL); + PZ_Lock(certTrustLock); return; } @@ -207,7 +223,6 @@ nsslowcert_UnlockCertTrust(NSSLOWCERTCertificate *cert) return; } -static PZLock *freeListLock = NULL; /* * Acquire the cert reference count lock @@ -218,10 +233,7 @@ static PZLock *freeListLock = NULL; static void nsslowcert_LockFreeList(void) { - if ( freeListLock == NULL ) { - nss_InitLock(&freeListLock, nssILockRefLock); - PORT_Assert(freeListLock != NULL); - } + PORT_Assert(freeListLock != NULL); PZ_Lock(freeListLock); return; @@ -825,8 +837,7 @@ NewDBCertEntry(SECItem *derCert, char *nickname, goto loser; } - entry = (certDBEntryCert *)PORT_ArenaZAlloc(arena, sizeof(certDBEntryCert)); - + entry = PORT_ArenaZNew(arena, certDBEntryCert); if ( entry == NULL ) { goto loser; } @@ -917,21 +928,6 @@ DecodeV4DBCertEntry(unsigned char *buf, int len) goto loser; } - entry->derCert.data = (unsigned char *)PORT_ArenaAlloc(arena, certlen); - if ( !entry->derCert.data ) { - goto loser; - } - entry->derCert.len = certlen; - - if ( nnlen ) { - entry->nickname = (char *) PORT_ArenaAlloc(arena, nnlen); - if ( !entry->nickname ) { - goto loser; - } - } else { - entry->nickname = 0; - } - entry->common.arena = arena; entry->common.version = CERT_DB_FILE_VERSION; entry->common.type = certDBEntryTypeCert; @@ -940,11 +936,25 @@ DecodeV4DBCertEntry(unsigned char *buf, int len) entry->trust.emailFlags = buf[1]; entry->trust.objectSigningFlags = buf[2]; + entry->derCert.data = (unsigned char *)PORT_ArenaAlloc(arena, certlen); + if ( !entry->derCert.data ) { + goto loser; + } + entry->derCert.len = certlen; PORT_Memcpy(entry->derCert.data, &buf[DBCERT_V4_HEADER_LEN], certlen); - PORT_Memcpy(entry->nickname, &buf[DBCERT_V4_HEADER_LEN + certlen], nnlen); - if (PORT_Strcmp(entry->nickname,"Server-Cert") == 0) { - entry->trust.sslFlags |= CERTDB_USER; + if ( nnlen ) { + entry->nickname = (char *) PORT_ArenaAlloc(arena, nnlen); + if ( !entry->nickname ) { + goto loser; + } + PORT_Memcpy(entry->nickname, &buf[DBCERT_V4_HEADER_LEN + certlen], nnlen); + + if (PORT_Strcmp(entry->nickname, "Server-Cert") == 0) { + entry->trust.sslFlags |= CERTDB_USER; + } + } else { + entry->nickname = 0; } return(entry); @@ -1056,7 +1066,7 @@ CreateCertEntry(void) return entry; } - return PORT_ZAlloc(sizeof(certDBEntryCert)); + return PORT_ZNew(certDBEntryCert); } static void @@ -1121,9 +1131,8 @@ loser: pkcs11_freeStaticData(dbkey.data,buf); dbkey.data = NULL; if ( entry ) { - + DestroyDBEntry((certDBEntry *)entry); } - DestroyDBEntry((certDBEntry *)entry); return(NULL); } @@ -1245,9 +1254,7 @@ NewDBCrlEntry(SECItem *derCrl, char * url, certDBEntryType crlType, int flags) goto loser; } - entry = (certDBEntryRevocation*) - PORT_ArenaZAlloc(arena, sizeof(certDBEntryRevocation)); - + entry = PORT_ArenaZNew(arena, certDBEntryRevocation); if ( entry == NULL ) { goto loser; } @@ -1457,7 +1464,6 @@ EncodeDBNicknameEntry(certDBEntryNickname *entry, PRArenaPool *arena, dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len); if ( dbitem->data == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } @@ -2706,36 +2712,37 @@ nsslowcert_UpdateSubjectEmailAddr(NSSLOWCERTCertDBHandle *dbhandle, entry = ReadDBSubjectEntry(dbhandle,derSubject); if (entry == NULL) { - goto loser; + rv = SECFailure; + goto done; } - if ( entry->emailAddrs ) { - for (i=0; i < (int)(entry->nemailAddrs); i++) { - if (PORT_Strcmp(entry->emailAddrs[i],emailAddr) == 0) { - index = i; - } + for (i=0; i < (int)(entry->nemailAddrs); i++) { + if (PORT_Strcmp(entry->emailAddrs[i],emailAddr) == 0) { + index = i; } } - if (updateType == nsslowcert_remove) { if (index == -1) { - return SECSuccess; + rv = SECSuccess; + goto done; } - entry->nemailAddrs--; for (i=index; i < (int)(entry->nemailAddrs); i++) { entry->emailAddrs[i] = entry->emailAddrs[i+1]; } } else { char **newAddrs = NULL; + if (index != -1) { - return SECSuccess; + rv = SECSuccess; + goto done; } newAddrs = (char **)PORT_ArenaAlloc(entry->common.arena, (entry->nemailAddrs+1)* sizeof(char *)); if (!newAddrs) { - goto loser; + rv = SECFailure; + goto done; } for (i=0; i < (int)(entry->nemailAddrs); i++) { newAddrs[i] = entry->emailAddrs[i]; @@ -2743,7 +2750,8 @@ nsslowcert_UpdateSubjectEmailAddr(NSSLOWCERTCertDBHandle *dbhandle, newAddrs[entry->nemailAddrs] = PORT_ArenaStrdup(entry->common.arena,emailAddr); if (!newAddrs[entry->nemailAddrs]) { - goto loser; + rv = SECFailure; + goto done; } entry->emailAddrs = newAddrs; entry->nemailAddrs++; @@ -2754,18 +2762,11 @@ nsslowcert_UpdateSubjectEmailAddr(NSSLOWCERTCertDBHandle *dbhandle, /* write the new one */ rv = WriteDBSubjectEntry(dbhandle, entry); - if ( rv != SECSuccess ) { - goto loser; - } - - DestroyDBEntry((certDBEntry *)entry); - if (emailAddr) PORT_Free(emailAddr); - return(SECSuccess); -loser: + done: if (entry) DestroyDBEntry((certDBEntry *)entry); if (emailAddr) PORT_Free(emailAddr); - return(SECFailure); + return rv; } /* @@ -2794,8 +2795,7 @@ AddNicknameToSubject(NSSLOWCERTCertDBHandle *dbhandle, goto loser; } - entry->nickname = (nickname) ? - PORT_ArenaStrdup(entry->common.arena, nickname) : NULL; + entry->nickname = PORT_ArenaStrdup(entry->common.arena, nickname); if ( entry->nickname == NULL ) { goto loser; @@ -2876,8 +2876,7 @@ ReadDBVersionEntry(NSSLOWCERTCertDBHandle *handle) goto loser; } - entry = (certDBEntryVersion *)PORT_ArenaAlloc(arena, - sizeof(certDBEntryVersion)); + entry = PORT_ArenaZNew(arena, certDBEntryVersion); if ( entry == NULL ) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; @@ -3070,6 +3069,7 @@ AddPermSubjectNode(certDBEntrySubject *entry, NSSLOWCERTCertificate *cert, } if ( nsslowcert_IsNewer(cert, cmpcert) ) { + nsslowcert_DestroyCertificate(cmpcert); /* insert before cmpcert */ rv = SECITEM_CopyItem(entry->common.arena, &newCertKeys[new_i], &cert->certKey); @@ -3097,6 +3097,7 @@ AddPermSubjectNode(certDBEntrySubject *entry, NSSLOWCERTCertificate *cert, added = PR_TRUE; break; } + nsslowcert_DestroyCertificate(cmpcert); /* copy this cert entry */ newCertKeys[new_i] = entry->certKeys[i]; newKeyIDs[new_i] = entry->keyIDs[i]; @@ -3849,6 +3850,8 @@ UpdateV5DB(NSSLOWCERTCertDBHandle *handle, DB *updatedb) updatehandle.permCertDB = updatedb; updatehandle.dbMon = PZ_NewMonitor(nssILockCertDB); + updatehandle.dbVerify = 0; + updatehandle.ref = 1; /* prevent premature close */ rv = nsslowcert_TraversePermCerts(&updatehandle, updateV5Callback, (void *)handle); @@ -4298,7 +4301,8 @@ nsslowcert_TraverseDBEntries(NSSLOWCERTCertDBHandle *handle, keybuf = (unsigned char *)key.data; keyitem.data = &keybuf[SEC_DB_KEY_HEADER_LEN]; keyitem.type = siBuffer; - + /* type should equal keybuf[0]. */ + rv = (* callback)(&dataitem, &keyitem, type, udata); if ( rv != SECSuccess ) { return(rv); @@ -4352,7 +4356,7 @@ CreateTrust(void) return trust; } - return PORT_ZAlloc(sizeof(NSSLOWCERTTrust)); + return PORT_ZNew(NSSLOWCERTTrust); } static void @@ -5079,7 +5083,7 @@ nsslowcert_CreateCert(void) if (cert) { return cert; } - return (NSSLOWCERTCertificate *) PORT_ZAlloc(sizeof(NSSLOWCERTCertificate)); + return PORT_ZNew(NSSLOWCERTCertificate); } static void @@ -5106,6 +5110,9 @@ nsslowcert_DestroyTrust(NSSLOWCERTTrust *trust) if ( entry ) { DestroyDBEntry((certDBEntry *)entry); } + if (trust->dbhandle) { + sftk_freeCertDB(trust->dbhandle); + } pkcs11_freeStaticData(trust->dbKey.data,trust->dbKeySpace); PORT_Memset(trust, 0, sizeof(*trust)); @@ -5338,9 +5345,6 @@ nsslowcert_SaveSMimeProfile(NSSLOWCERTCertDBHandle *dbhandle, char *emailAddr, return(rv); } -/* If the freeListLock doesn't exist when this function is called, -** this function will create it, use it 3 times, and delete it. -*/ void nsslowcert_DestroyFreeLists(void) { @@ -5368,3 +5372,77 @@ nsslowcert_DestroyGlobalLocks(void) } } +certDBEntry * +nsslowcert_DecodeAnyDBEntry(SECItem *dbData, SECItem *dbKey, + certDBEntryType entryType, void *pdata) +{ + PLArenaPool *arena = NULL; + certDBEntry *entry; + SECStatus rv; + SECItem dbEntry; + + + if ((dbData->len < SEC_DB_ENTRY_HEADER_LEN) || (dbKey->len == 0)) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + goto loser; + } + dbEntry.data = &dbData->data[SEC_DB_ENTRY_HEADER_LEN]; + dbEntry.len = dbData->len - SEC_DB_ENTRY_HEADER_LEN; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + goto loser; + } + entry = PORT_ArenaZNew(arena, certDBEntry); + if (!entry) + goto loser; + + entry->common.version = (unsigned int)dbData->data[0]; + entry->common.flags = (unsigned int)dbData->data[2]; + entry->common.type = entryType; + entry->common.arena = arena; + + switch (entryType) { + case certDBEntryTypeContentVersion: /* This type appears to be unused */ + case certDBEntryTypeVersion: /* This type has only the common hdr */ + rv = SECSuccess; + break; + + case certDBEntryTypeSubject: + rv = DecodeDBSubjectEntry(&entry->subject, &dbEntry, dbKey); + break; + + case certDBEntryTypeNickname: + rv = DecodeDBNicknameEntry(&entry->nickname, &dbEntry, + (char *)dbKey->data); + break; + + /* smime profiles need entries created after the certs have + * been imported, loop over them in a second run */ + case certDBEntryTypeSMimeProfile: + rv = DecodeDBSMimeEntry(&entry->smime, &dbEntry, (char *)dbKey->data); + break; + + case certDBEntryTypeCert: + rv = DecodeDBCertEntry(&entry->cert, &dbEntry); + break; + + case certDBEntryTypeKeyRevocation: + case certDBEntryTypeRevocation: + rv = DecodeDBCrlEntry(&entry->revocation, &dbEntry); + break; + + default: + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; + } + + if (rv == SECSuccess) + return entry; + +loser: + if (arena) + PORT_FreeArena(arena, PR_FALSE); + return NULL; +} + diff --git a/security/nss/lib/softoken/pcertt.h b/security/nss/lib/softoken/pcertt.h index e805950e1..848fe69e9 100644 --- a/security/nss/lib/softoken/pcertt.h +++ b/security/nss/lib/softoken/pcertt.h @@ -410,12 +410,14 @@ typedef struct { #define SEC_DB_CONTENT_VERSION_KEY_LEN sizeof(SEC_DB_CONTENT_VERSION_KEY) typedef union { - certDBEntryCommon common; - certDBEntryVersion version; - certDBEntryCert cert; - certDBEntryNickname nickname; - certDBEntrySubject subject; - certDBEntryRevocation revocation; + certDBEntryCommon common; + certDBEntryCert cert; + certDBEntryContentVersion content; + certDBEntryNickname nickname; + certDBEntryRevocation revocation; + certDBEntrySMime smime; + certDBEntrySubject subject; + certDBEntryVersion version; } certDBEntry; /* length of the fixed part of a database entry */ diff --git a/security/nss/lib/softoken/pk11db.c b/security/nss/lib/softoken/pk11db.c index c60e87780..30584c91e 100644 --- a/security/nss/lib/softoken/pk11db.c +++ b/security/nss/lib/softoken/pk11db.c @@ -868,7 +868,7 @@ secmod_ReadPermDB(const char *appName, const char *filename, DBT key,data; int ret; DB *pkcs11db = NULL; - char **moduleList = NULL; + char **moduleList = NULL, **newModuleList = NULL; int moduleCount = 1; int useCount = SECMOD_STEP; @@ -888,9 +888,10 @@ secmod_ReadPermDB(const char *appName, const char *filename, PRBool internal = PR_FALSE; if ((moduleCount+1) >= useCount) { useCount += SECMOD_STEP; - moduleList = + newModuleList = (char **)PORT_Realloc(moduleList,useCount*sizeof(char *)); - if (moduleList == NULL) goto done; + if (newModuleList == NULL) goto done; + moduleList = newModuleList; PORT_Memset(&moduleList[moduleCount+1],0, sizeof(char *)*SECMOD_STEP); } diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index 10a7bcfb7..7061059ce 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -55,7 +55,6 @@ #include "secitem.h" #include "pkcs11.h" #include "pkcs11i.h" -#include "pkcs11p.h" #include "softoken.h" #include "lowkeyi.h" #include "blapi.h" @@ -63,13 +62,12 @@ #include "secport.h" #include "pcert.h" #include "secrng.h" -#include "nss.h" +#include "softkver.h" #include "keydbi.h" -#ifdef NSS_ENABLE_ECC -extern SECStatus EC_FillParams(PRArenaPool *arena, - const SECItem *encodedParams, ECParams *params); +#ifdef DEBUG +#include "cdbhdl.h" #endif /* @@ -77,7 +75,7 @@ extern SECStatus EC_FillParams(PRArenaPool *arena, */ /* The next three strings must be exactly 32 characters long */ -static char *manufacturerID = "mozilla.org "; +static char *manufacturerID = "Mozilla Foundation "; static char manufacturerID_space[33]; static char *libraryDescription = "NSS Internal Crypto Services "; static char libraryDescription_space[33]; @@ -87,6 +85,7 @@ static char libraryDescription_space[33]; * failure so that there are at most 60 login attempts per minute. */ static PRIntervalTime loginWaitTime; +static PRUint32 minSessionObjectHandle = 1U; #define __PASTE(x,y) x##y @@ -1228,6 +1227,7 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE { CK_BBOOL cktrue = CK_TRUE; CK_BBOOL encrypt = CK_TRUE; + CK_BBOOL sign = CK_FALSE; CK_BBOOL recover = CK_TRUE; CK_BBOOL wrap = CK_TRUE; CK_BBOOL derive = CK_FALSE; @@ -1268,15 +1268,18 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE sftk_item_expand(&mod)); if (mod.data) PORT_Free(mod.data); if (crv != CKR_OK) return crv; - + + sign = CK_TRUE; break; case CKK_DSA: if ( !sftk_hasAttribute(object, CKA_SUBPRIME)) { return CKR_TEMPLATE_INCOMPLETE; } - if ( !sftk_hasAttribute(object, CKA_NETSCAPE_DB)) { + if (sftk_isTrue(object,CKA_TOKEN) && + !sftk_hasAttribute(object, CKA_NETSCAPE_DB)) { return CKR_TEMPLATE_INCOMPLETE; } + sign = CK_TRUE; /* fall through */ case CKK_DH: if ( !sftk_hasAttribute(object, CKA_PRIME)) { @@ -1300,10 +1303,12 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE if ( !sftk_hasAttribute(object, CKA_VALUE)) { return CKR_TEMPLATE_INCOMPLETE; } - if ( !sftk_hasAttribute(object, CKA_NETSCAPE_DB)) { + if (sftk_isTrue(object,CKA_TOKEN) && + !sftk_hasAttribute(object, CKA_NETSCAPE_DB)) { return CKR_TEMPLATE_INCOMPLETE; } encrypt = CK_FALSE; + sign = CK_TRUE; recover = CK_FALSE; wrap = CK_FALSE; derive = CK_TRUE; @@ -1320,7 +1325,7 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE if (crv != CKR_OK) return crv; crv = sftk_defaultAttribute(object,CKA_DECRYPT,&encrypt,sizeof(CK_BBOOL)); if (crv != CKR_OK) return crv; - crv = sftk_defaultAttribute(object,CKA_SIGN,&cktrue,sizeof(CK_BBOOL)); + crv = sftk_defaultAttribute(object,CKA_SIGN,&sign,sizeof(CK_BBOOL)); if (crv != CKR_OK) return crv; crv = sftk_defaultAttribute(object,CKA_SIGN_RECOVER,&recover, sizeof(CK_BBOOL)); @@ -1397,7 +1402,7 @@ fail: return CKR_OK; } -/* forward delcare the DES formating function for handleSecretKey */ +/* forward declare the DES formating function for handleSecretKey */ void sftk_FormatDESKey(unsigned char *key, int length); static NSSLOWKEYPrivateKey *sftk_mkSecretKeyRep(SFTKObject *object); @@ -1532,6 +1537,9 @@ sftk_GenerateSecretCKA_ID(NSSLOWKEYDBHandle *handle, SECItem *id, char *label) (++retries <= SFTK_KEY_MAX_RETRIES)); if ((rv != SECSuccess) || (retries > SFTK_KEY_MAX_RETRIES)) { + if (rv != SECSuccess) { + sftk_fatalError = PR_TRUE; + } crv = CKR_DEVICE_ERROR; /* random number generator is bad */ PORT_Free(id->data); id->data = NULL; @@ -1644,6 +1652,9 @@ sftk_handleKeyObject(SFTKSession *session, SFTKObject *object) /* get the key type */ attribute = sftk_FindAttribute(object,CKA_KEY_TYPE); + if (!attribute) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; sftk_FreeAttribute(attribute); @@ -1750,6 +1761,9 @@ sftk_handleKeyParameterObject(SFTKSession *session, SFTKObject *object) /* get the key type */ attribute = sftk_FindAttribute(object,CKA_KEY_TYPE); + if (!attribute) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; sftk_FreeAttribute(attribute); @@ -1773,9 +1787,11 @@ CK_RV sftk_handleObject(SFTKObject *object, SFTKSession *session) { SFTKSlot *slot = session->slot; + SFTKAttribute *attribute; + SFTKObject *duplicateObject = NULL; + CK_OBJECT_HANDLE handle; CK_BBOOL ckfalse = CK_FALSE; CK_BBOOL cktrue = CK_TRUE; - SFTKAttribute *attribute; CK_RV crv; /* make sure all the base object types are defined. If not set the @@ -1801,11 +1817,37 @@ sftk_handleObject(SFTKObject *object, SFTKSession *session) return CKR_SESSION_READ_ONLY; } - /* PKCS #11 object ID's are unique for all objects on a - * token */ - PZ_Lock(slot->objectLock); - object->handle = slot->tokenIDCount++; - PZ_Unlock(slot->objectLock); + /* Assign a unique SESSION object handle to every new object, + * whether it is a session object or a token object. + * At this point, all new objects are structured as session objects. + * Objects with the CKA_TOKEN attribute true will be turned into + * token objects and will have a token object handle assigned to + * them by a call to sftk_mkHandle in the handler for each object + * class, invoked below. + * + * It may be helpful to note/remember that + * sftk_narrowToXxxObject uses sftk_isToken, + * sftk_isToken examines the sign bit of the object's handle, but + * sftk_isTrue(...,CKA_TOKEN) examines the CKA_TOKEN attribute. + */ + do { + PRUint32 wrappedAround; + + duplicateObject = NULL; + PZ_Lock(slot->objectLock); + wrappedAround = slot->sessionObjectHandleCount & SFTK_TOKEN_MASK; + handle = slot->sessionObjectHandleCount & ~SFTK_TOKEN_MASK; + if (!handle) /* don't allow zero handle */ + handle = minSessionObjectHandle; + slot->sessionObjectHandleCount = (handle + 1U) | wrappedAround; + /* Is there already a session object with this handle? */ + if (wrappedAround) { + sftkqueue_find(duplicateObject, handle, slot->sessObjHashTable, \ + slot->sessObjHashSize); + } + PZ_Unlock(slot->objectLock); + } while (duplicateObject != NULL); + object->handle = handle; /* get the object class */ attribute = sftk_FindAttribute(object,CKA_CLASS); @@ -1815,8 +1857,10 @@ sftk_handleObject(SFTKObject *object, SFTKSession *session) object->objclass = *(CK_OBJECT_CLASS *)attribute->attrib.pValue; sftk_FreeAttribute(attribute); - /* now handle the specific. Get a session handle for these functions - * to use */ + /* Now handle the specific object class. + * At this point, all objects are session objects, and the session + * number must be passed to the object class handlers. + */ switch (object->objclass) { case CKO_DATA: crv = sftk_handleDataObject(session,object); @@ -1852,7 +1896,11 @@ sftk_handleObject(SFTKObject *object, SFTKSession *session) return crv; } - /* now link the object into the slot and session structures */ + /* Now link the object into the slot and session structures. + * If the object has a true CKA_TOKEN attribute, the above object + * class handlers will have set the sign bit in the object handle, + * causing the following test to be true. + */ if (sftk_isToken(object->handle)) { sftk_convertSessionToToken(object); } else { @@ -1952,7 +2000,10 @@ NSSLOWKEYPublicKey *sftk_GetPubKey(SFTKObject *object,CK_KEY_TYPE key_type, * based on the encoded params */ if (EC_FillParams(arena, &pubKey->u.ec.ecParams.DEREncoding, - &pubKey->u.ec.ecParams) != SECSuccess) break; + &pubKey->u.ec.ecParams) != SECSuccess) { + crv = CKR_DOMAIN_PARAMS_INVALID; + break; + } crv = sftk_Attribute2SSecItem(arena,&pubKey->u.ec.publicValue, object,CKA_EC_POINT); @@ -2045,9 +2096,12 @@ sftk_mkPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp) crv = sftk_Attribute2SSecItem(arena,&privKey->u.dsa.privateValue, object,CKA_VALUE); if (crv != CKR_OK) break; - crv = sftk_Attribute2SSecItem(arena,&privKey->u.dsa.publicValue, - object,CKA_NETSCAPE_DB); - /* can't set the public value.... */ + if (sftk_hasAttribute(object,CKA_NETSCAPE_DB)) { + crv = sftk_Attribute2SSecItem(arena, &privKey->u.dsa.publicValue, + object,CKA_NETSCAPE_DB); + /* privKey was zero'd so public value is already set to NULL, 0 + * if we don't set it explicitly */ + } break; case CKK_DH: @@ -2061,8 +2115,12 @@ sftk_mkPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp) crv = sftk_Attribute2SSecItem(arena,&privKey->u.dh.privateValue, object,CKA_VALUE); if (crv != CKR_OK) break; - crv = sftk_Attribute2SSecItem(arena,&privKey->u.dh.publicValue, - object,CKA_NETSCAPE_DB); + if (sftk_hasAttribute(object,CKA_NETSCAPE_DB)) { + crv = sftk_Attribute2SSecItem(arena, &privKey->u.dh.publicValue, + object,CKA_NETSCAPE_DB); + /* privKey was zero'd so public value is already set to NULL, 0 + * if we don't set it explicitly */ + } break; #ifdef NSS_ENABLE_ECC @@ -2077,13 +2135,20 @@ sftk_mkPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp) * based on the encoded params */ if (EC_FillParams(arena, &privKey->u.ec.ecParams.DEREncoding, - &privKey->u.ec.ecParams) != SECSuccess) break; + &privKey->u.ec.ecParams) != SECSuccess) { + crv = CKR_DOMAIN_PARAMS_INVALID; + break; + } crv = sftk_Attribute2SSecItem(arena,&privKey->u.ec.privateValue, object,CKA_VALUE); if (crv != CKR_OK) break; - crv = sftk_Attribute2SSecItem(arena, &privKey->u.ec.publicValue, + if (sftk_hasAttribute(object,CKA_NETSCAPE_DB)) { + crv = sftk_Attribute2SSecItem(arena, &privKey->u.ec.publicValue, object,CKA_NETSCAPE_DB); - if (crv != CKR_OK) break; + if (crv != CKR_OK) break; + /* privKey was zero'd so public value is already set to NULL, 0 + * if we don't set it explicitly */ + } rv = DER_SetUInteger(privKey->arena, &privKey->u.ec.version, NSSLOWKEY_EC_PRIVATE_KEY_VERSION); if (rv != SECSuccess) crv = CKR_HOST_MEMORY; @@ -2333,7 +2398,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; } @@ -2355,7 +2420,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; } @@ -2388,6 +2453,8 @@ 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' */ @@ -2622,11 +2689,11 @@ SFTK_SlotInit(char *configdir,sftk_token_parameters *params, int moduleIndex) slot->optimizeSpace = params->optimizeSpace; if (slot->optimizeSpace) { - slot->tokObjHashSize = SPACE_TOKEN_OBJECT_HASH_SIZE; + slot->sessObjHashSize = SPACE_SESSION_OBJECT_HASH_SIZE; slot->sessHashSize = SPACE_SESSION_HASH_SIZE; slot->numSessionLocks = 1; } else { - slot->tokObjHashSize = TIME_TOKEN_OBJECT_HASH_SIZE; + slot->sessObjHashSize = TIME_SESSION_OBJECT_HASH_SIZE; slot->sessHashSize = TIME_SESSION_HASH_SIZE; slot->numSessionLocks = slot->sessHashSize/BUCKETS_PER_SESSION_LOCK; } @@ -2652,16 +2719,16 @@ SFTK_SlotInit(char *configdir,sftk_token_parameters *params, int moduleIndex) slot->head = PORT_ZNewArray(SFTKSession *, slot->sessHashSize); if (slot->head == NULL) goto mem_loser; - slot->tokObjects = PORT_ZNewArray(SFTKObject *, slot->tokObjHashSize); - if (slot->tokObjects == NULL) + slot->sessObjHashTable = PORT_ZNewArray(SFTKObject *, slot->sessObjHashSize); + if (slot->sessObjHashTable == NULL) goto mem_loser; - slot->tokenHashTable = PL_NewHashTable(64,sftk_HashNumber,PL_CompareValues, + slot->tokObjHashTable = PL_NewHashTable(64,sftk_HashNumber,PL_CompareValues, SECITEM_HashCompare, NULL, 0); - if (slot->tokenHashTable == NULL) + if (slot->tokObjHashTable == NULL) goto mem_loser; slot->sessionIDCount = 0; - slot->tokenIDCount = 1; + slot->sessionObjectHandleCount = minSessionObjectHandle; slot->slotID = slotID; sftk_setStringName(params->slotdes ? params->slotdes : sftk_getDefSlotName(slotID), slot->slotDescription, @@ -2756,9 +2823,11 @@ sftk_DBShutdown(SFTKSlot *slot) slot->keyDB = NULL; PZ_Unlock(slot->slotLock); if (certHandle) { + PORT_Assert(certHandle->ref == 1 || slot->slotID > FIPS_SLOT_ID); sftk_freeCertDB(certHandle); } if (keyHandle) { + PORT_Assert(keyHandle->ref == 1 || slot->slotID > FIPS_SLOT_ID); sftk_freeKeyDB(keyHandle); } } @@ -2778,9 +2847,9 @@ SFTK_ShutdownSlot(SFTKSlot *slot) /* clear all objects.. session objects are cleared as a result of * closing all the sessions. We just need to clear the token object - * cache. slot->tokenHashTable guarentees we have the token + * cache. slot->tokObjHashTable guarentees we have the token * infrastructure set up. */ - if (slot->tokenHashTable) { + if (slot->tokObjHashTable) { SFTK_ClearTokenKeyHashTable(slot); } @@ -2802,16 +2871,16 @@ SFTK_DestroySlotData(SFTKSlot *slot) SFTK_ShutdownSlot(slot); - if (slot->tokenHashTable) { - PL_HashTableDestroy(slot->tokenHashTable); - slot->tokenHashTable = NULL; + if (slot->tokObjHashTable) { + PL_HashTableDestroy(slot->tokObjHashTable); + slot->tokObjHashTable = NULL; } - if (slot->tokObjects) { - PORT_Free(slot->tokObjects); - slot->tokObjects = NULL; + if (slot->sessObjHashTable) { + PORT_Free(slot->sessObjHashTable); + slot->sessObjHashTable = NULL; } - slot->tokObjHashSize = 0; + slot->sessObjHashSize = 0; if (slot->head) { PORT_Free(slot->head); @@ -2953,13 +3022,6 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) if (isFIPS) { - /* make sure that our check file signatures are OK */ - if (!BLAPI_VerifySelf(NULL) || - !BLAPI_SHVerify(SOFTOKEN_LIB_NAME, (PRFuncPtr) sftk_closePeer)) { - crv = CKR_DEVICE_ERROR; /* better error code? checksum error? */ - return crv; - } - loginWaitTime = PR_SecondsToInterval(1); } @@ -2976,6 +3038,12 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) } RNG_SystemInfoForRNG(); + rv = nsslowcert_InitLocks(); + if (rv != SECSuccess) { + crv = CKR_DEVICE_ERROR; + return crv; + } + /* NOTE: * we should be getting out mutexes from this list, not statically binding @@ -3022,6 +3090,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++) { @@ -3076,21 +3151,13 @@ CK_RV nsc_CommonFinalize (CK_VOID_PTR pReserved, PRBool isFIPS) nsslowcert_DestroyFreeLists(); nsslowcert_DestroyGlobalLocks(); -#ifdef LEAK_TEST - /* - * do we really want to throw away all our hard earned entropy here!!? - * No we don't! Not calling RNG_RNGShutdown only 'leaks' data on the - * initial call to RNG_Init(). So the only reason to call this is to clean - * up leak detection warnings on shutdown. In many cases we *don't* want - * to free up the global RNG context because the application has Finalized - * simply to swap profiles. We don't want to loose the entropy we've - * already collected. - */ + /* This function does not discard all our previously aquired entropy. */ RNG_RNGShutdown(); -#endif /* tell freeBL to clean up after itself */ BL_Cleanup(); + /* unload freeBL shared library from memory */ + BL_Unload(); /* clean up the default OID table */ SECOID_Shutdown(); nsc_init = PR_FALSE; @@ -3127,8 +3194,8 @@ CK_RV NSC_GetInfo(CK_INFO_PTR pInfo) pInfo->cryptokiVersion.major = 2; pInfo->cryptokiVersion.minor = 20; PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); - pInfo->libraryVersion.major = NSS_VMAJOR; - pInfo->libraryVersion.minor = NSS_VMINOR; + pInfo->libraryVersion.major = SOFTOKEN_VMAJOR; + pInfo->libraryVersion.minor = SOFTOKEN_VMINOR; PORT_Memcpy(pInfo->libraryDescription,libraryDescription,32); pInfo->flags = 0; return CKR_OK; @@ -3173,12 +3240,11 @@ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) } /* ok we really should read it out of the keydb file. */ /* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */ - pInfo->hardwareVersion.major = NSS_VMAJOR; - pInfo->hardwareVersion.minor = NSS_VMINOR; + pInfo->hardwareVersion.major = SOFTOKEN_VMAJOR; + pInfo->hardwareVersion.minor = SOFTOKEN_VMINOR; return CKR_OK; } -#define CKF_THREAD_SAFE 0x8000 /* for now */ /* * check the current state of the 'needLogin' flag in case the database has * been changed underneath us. @@ -3206,14 +3272,17 @@ sftk_checkNeedLogin(SFTKSlot *slot, NSSLOWKEYDBHandle *keyHandle) * the system. */ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) { - SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE); + SFTKSlot *slot; NSSLOWKEYDBHandle *handle; + if (!nsc_init && !nsf_init) return CKR_CRYPTOKI_NOT_INITIALIZED; + slot = sftk_SlotFromID(slotID, PR_FALSE); if (slot == NULL) return CKR_SLOT_ID_INVALID; PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); PORT_Memcpy(pInfo->model,"NSS 3 ",16); PORT_Memcpy(pInfo->serialNumber,"0000000000000000",16); + PORT_Memcpy(pInfo->utcTime,"0000000000000000",16); pInfo->ulMaxSessionCount = 0; /* arbitrarily large */ pInfo->ulSessionCount = slot->sessionCount; pInfo->ulMaxRwSessionCount = 0; /* arbitarily large */ @@ -3222,8 +3291,9 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) pInfo->firmwareVersion.minor = 0; PORT_Memcpy(pInfo->label,slot->tokDescription,32); handle = sftk_getKeyDB(slot); + pInfo->flags = CKF_RNG | CKF_DUAL_CRYPTO_OPERATIONS; if (handle == NULL) { - pInfo->flags= CKF_RNG | CKF_WRITE_PROTECTED | CKF_THREAD_SAFE; + pInfo->flags |= CKF_WRITE_PROTECTED; pInfo->ulMaxPinLen = 0; pInfo->ulMinPinLen = 0; pInfo->ulTotalPublicMemory = 0; @@ -3243,12 +3313,11 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) * we will need to prompt for it. */ if (nsslowkey_HasKeyDBPassword(handle) == SECFailure) { - pInfo->flags = CKF_THREAD_SAFE | CKF_LOGIN_REQUIRED; + pInfo->flags |= CKF_LOGIN_REQUIRED; } else if (!sftk_checkNeedLogin(slot,handle)) { - pInfo->flags = CKF_THREAD_SAFE | CKF_USER_PIN_INITIALIZED; + pInfo->flags |= CKF_USER_PIN_INITIALIZED; } else { - pInfo->flags = CKF_THREAD_SAFE | - CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED; + pInfo->flags |= CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED; } pInfo->ulMaxPinLen = SFTK_MAX_PIN; pInfo->ulMinPinLen = (CK_ULONG)slot->minimumPinLen; @@ -3260,6 +3329,18 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) pInfo->hardwareVersion.minor = handle->version; sftk_freeKeyDB(handle); } + /* + * CKF_LOGIN_REQUIRED CKF_USER_PIN_INITIALIZED how CKF_TOKEN_INITIALIZED + * should be set + * 0 0 1 + * 1 0 0 + * 0 1 1 + * 1 1 1 + */ + if (!(pInfo->flags & CKF_LOGIN_REQUIRED) || + (pInfo->flags & CKF_USER_PIN_INITIALIZED)) { + pInfo->flags |= CKF_TOKEN_INITIALIZED; + } return CKR_OK; } @@ -3392,15 +3473,15 @@ CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin, /* first, delete all our loaded key and cert objects from our * internal list. */ PZ_Lock(slot->objectLock); - for (i=0; i < slot->tokObjHashSize; i++) { + for (i=0; i < slot->sessObjHashSize; i++) { do { - object = slot->tokObjects[i]; + object = slot->sessObjHashTable[i]; /* hand deque */ /* this duplicates function of NSC_close session functions, but * because we know that we are freeing all the sessions, we can * do more efficient processing */ if (object) { - slot->tokObjects[i] = object->next; + slot->sessObjHashTable[i] = object->next; if (object->next) object->next->prev = NULL; object->next = object->prev = NULL; @@ -3551,7 +3632,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) { @@ -3927,7 +4008,7 @@ static CK_RV sftk_CreateNewSlot(SFTKSlot *slot, CK_OBJECT_CLASS class, if (attribute == NULL) { return CKR_TEMPLATE_INCOMPLETE; } - paramString = (unsigned char *)attribute->attrib.pValue; + paramString = (char *)attribute->attrib.pValue; crv = secmod_parseParameters(paramString, ¶mStrings, isFIPS); if (crv != CKR_OK) { goto loser; @@ -3990,7 +4071,9 @@ CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession, SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); SFTKSession *session; SFTKObject *object; - CK_OBJECT_CLASS class; + /* make sure class isn't randomly CKO_NETSCAPE_NEWSLOT or + * CKO_NETSCPE_DELSLOT. */ + CK_OBJECT_CLASS class = CKO_VENDOR_DEFINED; CK_RV crv; int i; @@ -4393,7 +4476,7 @@ sftk_key_collect(DBT *key, DBT *data, void *arg) tmpDBKey.type = siBuffer; PORT_Assert(keyData->keyHandle); - if (!keyData->strict && keyData->id) { + if (!keyData->strict && keyData->id && keyData->id->data) { SECItem result; PRBool haveMatch= PR_FALSE; unsigned char hashKey[SHA1_LENGTH]; @@ -5006,7 +5089,7 @@ sftk_searchTokenList(SFTKSlot *slot, SFTKSearchResults *search, /* keys */ if (classFlags & (NSC_PRIVATE|NSC_PUBLIC|NSC_KEY)) { - PRBool mustStrict = ((classFlags & NSC_KEY) != 0) && (name.len != 0); + PRBool mustStrict = (name.len != 0); sftk_searchKeys(slot, &key_id, isLoggedIn, classFlags, search, mustStrict, pTemplate, ulCount); } @@ -5066,9 +5149,9 @@ CK_RV NSC_FindObjectsInit(CK_SESSION_HANDLE hSession, /* build list of found objects in the session */ if (!tokenOnly) { - crv = sftk_searchObjectList(search, slot->tokObjects, - slot->tokObjHashSize, slot->objectLock, - pTemplate, ulCount, isLoggedIn); + crv = sftk_searchObjectList(search, slot->sessObjHashTable, + slot->sessObjHashSize, slot->objectLock, + pTemplate, ulCount, isLoggedIn); } if (crv != CKR_OK) { goto loser; diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c index 56eb1814c..b722d3d4c 100644 --- a/security/nss/lib/softoken/pkcs11c.c +++ b/security/nss/lib/softoken/pkcs11c.c @@ -73,6 +73,7 @@ #include "pcert.h" #include "ssl3prot.h" /* for SSL3_RANDOM_LENGTH */ +#include "prprf.h" #define __PASTE(x,y) x##y @@ -441,17 +442,23 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, break; } context->multi = PR_FALSE; - context->cipherInfo = isEncrypt ? - (void *)sftk_GetPubKey(key,CKK_RSA,&crv) : - (void *)sftk_GetPrivKey(key,CKK_RSA,&crv); - if (context->cipherInfo == NULL) { - break; - } if (isEncrypt) { + NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key,CKK_RSA,&crv); + if (pubKey == NULL) { + break; + } + context->maxLen = nsslowkey_PublicModulusLen(pubKey); + context->cipherInfo = (void *)pubKey; context->update = (SFTKCipher) (pMechanism->mechanism == CKM_RSA_X_509 ? RSA_EncryptRaw : RSA_EncryptBlock); } else { + NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key,CKK_RSA,&crv); + if (privKey == NULL) { + break; + } + context->maxLen = nsslowkey_PrivateModulusLen(privKey); + context->cipherInfo = (void *)privKey; context->update = (SFTKCipher) (pMechanism->mechanism == CKM_RSA_X_509 ? RSA_DecryptRaw : RSA_DecryptBlock); @@ -717,6 +724,18 @@ CK_RV NSC_EncryptUpdate(CK_SESSION_HANDLE hSession, crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_TRUE,NULL); if (crv != CKR_OK) return crv; + if (!pEncryptedPart) { + if (context->doPad) { + CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength; + CK_ULONG blocksToSend = totalDataAvailable/context->blockSize; + + *pulEncryptedPartLen = blocksToSend * context->blockSize; + return CKR_OK; + } + *pulEncryptedPartLen = ulPartLen; + return CKR_OK; + } + /* do padding */ if (context->doPad) { /* deal with previous buffered data */ @@ -837,7 +856,8 @@ CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, if (crv != CKR_OK) return crv; if (!pEncryptedData) { - *pulEncryptedDataLen = ulDataLen + 2 * context->blockSize; + *pulEncryptedDataLen = context->multi ? + ulDataLen + 2 * context->blockSize : context->maxLen; goto finish; } @@ -923,6 +943,35 @@ CK_RV NSC_DecryptUpdate(CK_SESSION_HANDLE hSession, crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,NULL); if (crv != CKR_OK) return crv; + /* this can only happen on an NSS programming error */ + PORT_Assert((context->padDataLength == 0) + || context->padDataLength == context->blockSize); + + + if (!pPart) { + if (context->doPad) { + /* we can check the data length here because if we are padding, + * then we must be using a block cipher. In the non-padding case + * the error will be returned by the underlying decryption + * function when do do the actual decrypt. We need to do the + * check here to avoid returning a negative length to the caller. + */ + if ((ulEncryptedPartLen == 0) || + (ulEncryptedPartLen % context->blockSize) != 0) { + return CKR_ENCRYPTED_DATA_LEN_RANGE; + } + *pulPartLen = + ulEncryptedPartLen + context->padDataLength - context->blockSize; + return CKR_OK; + } + /* for stream ciphers there is are no constraints on ulEncryptedPartLen. + * for block ciphers, it must be a multiple of blockSize. The error is + * detected when this function is called again do decrypt the output. + */ + *pulPartLen = ulEncryptedPartLen; + return CKR_OK; + } + if (context->doPad) { /* first decrypt our saved buffer */ if (context->padDataLength != 0) { @@ -957,7 +1006,6 @@ CK_RV NSC_DecryptFinal(CK_SESSION_HANDLE hSession, unsigned int maxout = *pulLastPartLen; CK_RV crv; SECStatus rv = SECSuccess; - PRBool contextFinished = PR_TRUE; /* make sure we're legal */ crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,&session); @@ -967,9 +1015,9 @@ CK_RV NSC_DecryptFinal(CK_SESSION_HANDLE hSession, if (!pLastPart) { /* caller is checking the amount of remaining data */ if (context->padDataLength > 0) { - *pulLastPartLen = 2 * context->blockSize; - contextFinished = PR_FALSE; /* still have padding to go */ + *pulLastPartLen = context->padDataLength; } + rv = SECSuccess; goto finish; } @@ -992,11 +1040,9 @@ CK_RV NSC_DecryptFinal(CK_SESSION_HANDLE hSession, } } + sftk_SetContextByType(session, SFTK_DECRYPT, NULL); + sftk_FreeContext(context); finish: - if (contextFinished) { - sftk_SetContextByType(session, SFTK_DECRYPT, NULL); - sftk_FreeContext(context); - } sftk_FreeSession(session); return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR; } @@ -1247,7 +1293,7 @@ static SECStatus sftk_HMACCmp(CK_ULONG *copyLen,unsigned char *sig,unsigned int sigLen, unsigned char *hash, unsigned int hashLen) { - return PORT_Memcmp(sig,hash,*copyLen) ? SECSuccess : SECFailure ; + return (PORT_Memcmp(sig,hash,*copyLen) == 0) ? SECSuccess : SECFailure ; } /* @@ -1548,6 +1594,15 @@ static SECStatus sftk_HashSign(SFTKHashSignInfo *info,unsigned char *sig,unsigned int *sigLen, unsigned int maxLen,unsigned char *hash, unsigned int hashLen) { + return RSA_HashSign(info->hashOid,info->key,sig,sigLen,maxLen, + hash,hashLen); +} + +SECStatus +RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key, + unsigned char *sig, unsigned int *sigLen, unsigned int maxLen, + unsigned char *hash, unsigned int hashLen) +{ SECStatus rv = SECFailure; SECItem digder; @@ -1560,7 +1615,7 @@ sftk_HashSign(SFTKHashSignInfo *info,unsigned char *sig,unsigned int *sigLen, if ( !arena ) { goto loser; } /* Construct digest info */ - di = SGN_CreateDigestInfo(info->hashOid, hash, hashLen); + di = SGN_CreateDigestInfo(hashOid, hash, hashLen); if (!di) { goto loser; } /* Der encode the digest as a DigestInfo */ @@ -1573,7 +1628,7 @@ sftk_HashSign(SFTKHashSignInfo *info,unsigned char *sig,unsigned int *sigLen, ** Encrypt signature after constructing appropriate PKCS#1 signature ** block */ - rv = RSA_Sign(info->key,sig,sigLen,maxLen,digder.data,digder.len); + rv = RSA_Sign(key,sig,sigLen,maxLen,digder.data,digder.len); loser: SGN_DestroyDigestInfo(di); @@ -1611,6 +1666,9 @@ nsc_DSA_Sign_Stub(void *ctx, void *sigBuf, digest.data = (unsigned char *)dataBuf; digest.len = dataLen; rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest); + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } *sigLen = signature.len; return rv; } @@ -1644,6 +1702,9 @@ nsc_ECDSASignStub(void *ctx, void *sigBuf, digest.data = (unsigned char *)dataBuf; digest.len = dataLen; rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest); + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } *sigLen = signature.len; return rv; } @@ -1857,7 +1918,7 @@ sftk_MACUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart, SECStatus rv; /* make sure we're legal */ - crv = sftk_GetContext(hSession,&context,type,PR_FALSE,NULL); + crv = sftk_GetContext(hSession,&context,type,PR_TRUE,NULL); if (crv != CKR_OK) return crv; if (context->hashInfo) { @@ -2055,11 +2116,20 @@ CK_RV NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, ************** Crypto Functions: verify ************************ */ -/* Handle RSA Signature formating */ +/* Handle RSA Signature formatting */ static SECStatus sftk_hashCheckSign(SFTKHashVerifyInfo *info, unsigned char *sig, unsigned int sigLen, unsigned char *digest, unsigned int digestLen) { + return RSA_HashCheckSign(info->hashOid, info->key, sig, sigLen, + digest, digestLen); +} + +SECStatus +RSA_HashCheckSign(SECOidTag hashOid, NSSLOWKEYPublicKey *key, + unsigned char *sig, unsigned int sigLen, + unsigned char *digest, unsigned int digestLen) +{ SECItem it; SGNDigestInfo *di = NULL; @@ -2067,16 +2137,16 @@ sftk_hashCheckSign(SFTKHashVerifyInfo *info, unsigned char *sig, it.data = NULL; - if (info->key == NULL) goto loser; + if (key == NULL) goto loser; - it.len = nsslowkey_PublicModulusLen(info->key); + it.len = nsslowkey_PublicModulusLen(key); if (!it.len) goto loser; it.data = (unsigned char *) PORT_Alloc(it.len); if (it.data == NULL) goto loser; /* decrypt the block */ - rv = RSA_CheckSignRecover(info->key, it.data, &it.len, it.len, sig, sigLen); + rv = RSA_CheckSignRecover(key, it.data, &it.len, it.len, sig, sigLen); if (rv != SECSuccess) goto loser; di = SGN_DecodeDigestInfo(&it); @@ -2084,7 +2154,11 @@ sftk_hashCheckSign(SFTKHashVerifyInfo *info, unsigned char *sig, if (di->digest.len != digestLen) goto loser; /* make sure the tag is OK */ - if (SECOID_GetAlgorithmTag(&di->digestAlgorithm) != info->hashOid) { + if (SECOID_GetAlgorithmTag(&di->digestAlgorithm) != hashOid) { + goto loser; + } + /* make sure the "parameters" are not too bogus. */ + if (di->digestAlgorithm.parameters.len > 2) { goto loser; } /* Now check the signature */ @@ -2093,6 +2167,7 @@ sftk_hashCheckSign(SFTKHashVerifyInfo *info, unsigned char *sig, } loser: + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); rv = SECFailure; done: @@ -2202,7 +2277,6 @@ finish_rsa: crv = CKR_KEY_TYPE_INCONSISTENT; break; } - context->multi = PR_FALSE; pubKey = sftk_GetPubKey(key,CKK_EC,&crv); if (pubKey == NULL) { crv = CKR_HOST_MEMORY; @@ -2246,6 +2320,7 @@ finish_rsa: } if (crv != CKR_OK) { + if (info) PORT_Free(info); PORT_Free(context); sftk_FreeSession(session); return crv; @@ -2263,13 +2338,22 @@ CK_RV NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, { SFTKSession *session; SFTKSessionContext *context; - CK_RV crv; + CK_RV crv, crv2; SECStatus rv; /* make sure we're legal */ crv = sftk_GetContext(hSession,&context,SFTK_VERIFY,PR_FALSE,&session); if (crv != CKR_OK) return crv; + /* multi part Verifying are completely implemented by VerifyUpdate and + * VerifyFinal */ + if (context->multi) { + sftk_FreeSession(session); + crv = NSC_VerifyUpdate(hSession, pData, ulDataLen); + crv2 = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen); + return crv == CKR_OK ? crv2 :crv; + } + rv = (*context->verify)(context->cipherInfo,pSignature, ulSignatureLen, pData, ulDataLen); sftk_FreeContext(context); @@ -2414,14 +2498,23 @@ CK_RV NSC_VerifyRecover(CK_SESSION_HANDLE hSession, crv = sftk_GetContext(hSession,&context,SFTK_VERIFY_RECOVER, PR_FALSE,&session); if (crv != CKR_OK) return crv; + if (pData == NULL) { + /* to return the actual size, we need to do the decrypt, just return + * the max size, which is the size of the input signature. */ + *pulDataLen = ulSignatureLen; + rv = SECSuccess; + goto finish; + } rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, pSignature, ulSignatureLen); *pulDataLen = (CK_ULONG) outlen; + sftk_FreeContext(context); sftk_SetContextByType(session, SFTK_VERIFY_RECOVER, NULL); +finish: sftk_FreeSession(session); - return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR; + return (rv == SECSuccess) ? CKR_OK : CKR_SIGNATURE_INVALID; } /* @@ -2482,9 +2575,13 @@ nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism, SECITEM_ZfreeItem(pbe_key, PR_TRUE); pbe_key = NULL; - if (iv.data && pbe_params->pInitVector != NULL) { - PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len); + if (iv.data) { + if (pbe_params->pInitVector != NULL) { + PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len); + } + PORT_Free(iv.data); } + return CKR_OK; } static CK_RV @@ -2527,6 +2624,9 @@ nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key) } if (rv != SECSuccess) { + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } return CKR_DEVICE_ERROR; } crv = sftk_AddAttributeType(key,CKA_PRIME, @@ -3355,6 +3455,9 @@ CK_RV NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession, rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp); PORT_Free(pubExp.data); if (rsaPriv == NULL) { + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } crv = CKR_DEVICE_ERROR; break; } @@ -3471,7 +3574,13 @@ kpg_done: PORT_Free(pqgParam.subPrime.data); PORT_Free(pqgParam.base.data); - if (rv != SECSuccess) { crv = CKR_DEVICE_ERROR; break; } + if (rv != SECSuccess) { + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } + crv = CKR_DEVICE_ERROR; + break; + } /* store the generated key into the attributes */ crv = sftk_AddAttributeType(publicKey,CKA_VALUE, @@ -3539,6 +3648,9 @@ dsagn_done: PORT_Free(dhParam.prime.data); PORT_Free(dhParam.base.data); if (rv != SECSuccess) { + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } crv = CKR_DEVICE_ERROR; break; } @@ -3588,8 +3700,11 @@ dhgn_done: rv = EC_NewKey(ecParams, &ecPriv); PORT_FreeArena(ecParams->arena, PR_TRUE); if (rv != SECSuccess) { - crv = CKR_DEVICE_ERROR; - break; + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } + crv = CKR_DEVICE_ERROR; + break; } crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, @@ -3695,6 +3810,16 @@ ecgn_done: 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=0x%08lX, " + "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; } @@ -3937,6 +4062,17 @@ CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession, crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data, pText.len, pWrappedKey, pulWrappedKeyLen); + /* always force a finalize, both on errors and when + * we are just getting the size */ + if (crv != CKR_OK || pWrappedKey == NULL) { + CK_RV lcrv ; + lcrv = sftk_GetContext(hSession,&context, + SFTK_ENCRYPT,PR_FALSE,NULL); + sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); + if (lcrv == CKR_OK && context) { + sftk_FreeContext(context); + } + } if (pText.data != (unsigned char *)attribute->attrib.pValue) PORT_ZFree(pText.data, pText.len); @@ -3947,6 +4083,7 @@ CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession, case CKO_PRIVATE_KEY: { SECItem *bpki = sftk_PackagePrivateKey(key, &crv); + SFTKSessionContext *context = NULL; if(!bpki) { break; @@ -3962,6 +4099,16 @@ CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession, crv = NSC_Encrypt(hSession, bpki->data, bpki->len, pWrappedKey, pulWrappedKeyLen); + /* always force a finalize */ + if (crv != CKR_OK || pWrappedKey == NULL) { + CK_RV lcrv ; + lcrv = sftk_GetContext(hSession,&context, + SFTK_ENCRYPT,PR_FALSE,NULL); + sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); + if (lcrv == CKR_OK && context) { + sftk_FreeContext(context); + } + } SECITEM_ZfreeItem(bpki, PR_TRUE); break; } @@ -3989,7 +4136,6 @@ sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki) PLArenaPool *arena; NSSLOWKEYPrivateKey *lpk = NULL; NSSLOWKEYPrivateKeyInfo *pki = NULL; - SECItem *ck_id = NULL; CK_RV crv = CKR_KEY_TYPE_INCONSISTENT; arena = PORT_NewArena(2048); @@ -4000,13 +4146,13 @@ sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki) pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYPrivateKeyInfo)); if(!pki) { - PORT_FreeArena(arena, PR_TRUE); + PORT_FreeArena(arena, PR_FALSE); return SECFailure; } if(SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki) != SECSuccess) { - PORT_FreeArena(arena, PR_FALSE); + PORT_FreeArena(arena, PR_TRUE); return SECFailure; } @@ -4197,10 +4343,6 @@ sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki) } loser: - if(ck_id) { - SECITEM_ZfreeItem(ck_id, PR_TRUE); - } - if(lpk) { nsslowkey_DestroyPrivateKey(lpk); } @@ -4605,14 +4747,6 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, return CKR_KEY_HANDLE_INVALID; } - /* don't use key derive to expose sensitive keys */ - crv = sftk_DeriveSensitiveCheck(sourceKey,key); - if (crv != CKR_OK) { - sftk_FreeObject(key); - sftk_FreeObject(sourceKey); - return crv; - } - /* get the value of the base key */ att = sftk_FindAttribute(sourceKey,CKA_VALUE); if (att == NULL) { @@ -4633,7 +4767,9 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, case CKM_SSL3_MASTER_KEY_DERIVE_DH: { CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master; - SSL3RSAPreMasterSecret *rsa_pms; + SSL3RSAPreMasterSecret * rsa_pms; + unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; + if ((pMechanism->mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) || (pMechanism->mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH)) isDH = PR_TRUE; @@ -4660,10 +4796,15 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, break; } - /* finally do the key gen */ ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *) pMechanism->pParameter; + + PORT_Memcpy(crsrdata, + ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); + PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, + ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); + if (ssl3_master->pVersion) { SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); rsa_pms = (SSL3RSAPreMasterSecret *) att->attrib.pValue; @@ -4686,23 +4827,17 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, } if (isTLS) { - unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; - SECItem crsr = { siBuffer, NULL, 0 }; - SECItem master = { siBuffer, NULL, 0 }; - SECItem pms = { siBuffer, NULL, 0 }; SECStatus status; + SECItem crsr = { siBuffer, NULL, 0 }; + SECItem master = { siBuffer, NULL, 0 }; + SECItem pms = { siBuffer, NULL, 0 }; - pms.data = (unsigned char*)att->attrib.pValue; - pms.len = att->attrib.ulValueLen; - master.data = key_block; - master.len = SSL3_MASTER_SECRET_LENGTH; - crsr.data = crsrdata; - crsr.len = sizeof(crsrdata); - - PORT_Memcpy(crsrdata, ssl3_master->RandomInfo.pClientRandom, - SSL3_RANDOM_LENGTH); - PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, - ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); + crsr.data = crsrdata; + crsr.len = sizeof crsrdata; + master.data = key_block; + master.len = SSL3_MASTER_SECRET_LENGTH; + pms.data = (unsigned char*)att->attrib.pValue; + pms.len = att->attrib.ulValueLen; status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS); if (status != SECSuccess) { @@ -4727,12 +4862,10 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i])); SHA1_Update(sha, (const unsigned char*)att->attrib.pValue, att->attrib.ulValueLen); - SHA1_Update(sha, ssl3_master->RandomInfo.pClientRandom, - ssl3_master->RandomInfo.ulClientRandomLen); - SHA1_Update(sha, ssl3_master->RandomInfo.pServerRandom, - ssl3_master->RandomInfo.ulServerRandomLen); + SHA1_Update(sha, crsrdata, sizeof crsrdata); SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); PORT_Assert(outLen == SHA1_LENGTH); + MD5_Begin(md5); MD5_Update(md5, (const unsigned char*)att->attrib.pValue, att->attrib.ulValueLen); @@ -4773,6 +4906,9 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, CK_SSL3_KEY_MAT_PARAMS *ssl3_keys; CK_SSL3_KEY_MAT_OUT * ssl3_keys_out; CK_ULONG effKeySize; + unsigned int block_needed; + unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2]; + unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; crv = sftk_DeriveSensitiveCheck(sourceKey,key); if (crv != CKR_OK) break; @@ -4801,6 +4937,17 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, break; } ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *) pMechanism->pParameter; + + PORT_Memcpy(srcrdata, + ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); + PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, + ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); + + PORT_Memcpy(crsrdata, + ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); + PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, + ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); + /* * clear out our returned keys so we can recover on failure */ @@ -4811,29 +4958,36 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, ssl3_keys_out->hServerKey = CK_INVALID_HANDLE; /* + * How much key material do we need? + */ + macSize = ssl3_keys->ulMacSizeInBits/8; + effKeySize = ssl3_keys->ulKeySizeInBits/8; + IVSize = ssl3_keys->ulIVSizeInBits/8; + if (keySize == 0) { + effKeySize = keySize; + } + block_needed = 2 * (macSize + effKeySize + + ((!ssl3_keys->bIsExport) * IVSize)); + PORT_Assert(block_needed <= sizeof key_block); + if (block_needed > sizeof key_block) + block_needed = sizeof key_block; + + /* * generate the key material: This looks amazingly similar to the * PMS code, and is clearly crying out for a function to provide it. */ if (isTLS) { SECStatus status; - SECItem master = { siBuffer, NULL, 0 }; SECItem srcr = { siBuffer, NULL, 0 }; SECItem keyblk = { siBuffer, NULL, 0 }; - unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2]; + SECItem master = { siBuffer, NULL, 0 }; - master.data = (unsigned char*)att->attrib.pValue; - master.len = att->attrib.ulValueLen; srcr.data = srcrdata; srcr.len = sizeof srcrdata; keyblk.data = key_block; - keyblk.len = sizeof key_block; - - PORT_Memcpy(srcrdata, - ssl3_keys->RandomInfo.pServerRandom, - SSL3_RANDOM_LENGTH); - PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, - ssl3_keys->RandomInfo.pClientRandom, - SSL3_RANDOM_LENGTH); + keyblk.len = block_needed; + master.data = (unsigned char*)att->attrib.pValue; + master.len = att->attrib.ulValueLen; status = TLS_PRF(&master, "key expansion", &srcr, &keyblk, isFIPS); @@ -4841,6 +4995,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, goto key_and_mac_derive_fail; } } else { + unsigned int block_bytes = 0; /* key_block = * MD5(master_secret + SHA('A' + master_secret + * ServerHello.random + ClientHello.random)) + @@ -4850,15 +5005,12 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, * ServerHello.random + ClientHello.random)) + * [...]; */ - for (i = 0; i < NUM_MIXERS; i++) { + for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) { SHA1_Begin(sha); SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i])); SHA1_Update(sha, (const unsigned char*)att->attrib.pValue, att->attrib.ulValueLen); - SHA1_Update(sha, ssl3_keys->RandomInfo.pServerRandom, - ssl3_keys->RandomInfo.ulServerRandomLen); - SHA1_Update(sha, ssl3_keys->RandomInfo.pClientRandom, - ssl3_keys->RandomInfo.ulClientRandomLen); + SHA1_Update(sha, srcrdata, sizeof srcrdata); SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); PORT_Assert(outLen == SHA1_LENGTH); MD5_Begin(md5); @@ -4867,6 +5019,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, MD5_Update(md5, sha_out, outLen); MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH); PORT_Assert(outLen == MD5_LENGTH); + block_bytes += outLen; } } @@ -4874,12 +5027,6 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, * Put the key material where it goes. */ i = 0; /* now shows how much consumed */ - macSize = ssl3_keys->ulMacSizeInBits/8; - effKeySize = ssl3_keys->ulKeySizeInBits/8; - IVSize = ssl3_keys->ulIVSizeInBits/8; - if (keySize == 0) { - effKeySize = keySize; - } /* * The key_block is partitioned as follows: @@ -4954,10 +5101,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, */ MD5_Begin(md5); MD5_Update(md5, &key_block[i], effKeySize); - MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom, - ssl3_keys->RandomInfo.ulClientRandomLen); - MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom, - ssl3_keys->RandomInfo.ulServerRandomLen); + MD5_Update(md5, crsrdata, sizeof crsrdata); MD5_End(md5, key_block2, &outLen, MD5_LENGTH); i += effKeySize; crv = sftk_buildSSLKey(hSession,key,PR_FALSE,key_block2, @@ -4973,10 +5117,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, */ MD5_Begin(md5); MD5_Update(md5, &key_block[i], effKeySize); - MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom, - ssl3_keys->RandomInfo.ulServerRandomLen); - MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom, - ssl3_keys->RandomInfo.ulClientRandomLen); + MD5_Update(md5, srcrdata, sizeof srcrdata); MD5_End(md5, key_block2, &outLen, MD5_LENGTH); i += effKeySize; crv = sftk_buildSSLKey(hSession,key,PR_FALSE,key_block2, @@ -4990,10 +5131,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, ** MD5(ClientHello.random + ServerHello.random); */ MD5_Begin(md5); - MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom, - ssl3_keys->RandomInfo.ulClientRandomLen); - MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom, - ssl3_keys->RandomInfo.ulServerRandomLen); + MD5_Update(md5, crsrdata, sizeof crsrdata); MD5_End(md5, key_block2, &outLen, MD5_LENGTH); PORT_Memcpy(ssl3_keys_out->pIVClient, key_block2, IVSize); @@ -5002,10 +5140,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, ** MD5(ServerHello.random + ClientHello.random); */ MD5_Begin(md5); - MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom, - ssl3_keys->RandomInfo.ulServerRandomLen); - MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom, - ssl3_keys->RandomInfo.ulClientRandomLen); + MD5_Update(md5, srcrdata, sizeof srcrdata); MD5_End(md5, key_block2, &outLen, MD5_LENGTH); PORT_Memcpy(ssl3_keys_out->pIVServer, key_block2, IVSize); @@ -5018,18 +5153,6 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, SECItem secret = { siBuffer, NULL, 0 }; SECItem crsr = { siBuffer, NULL, 0 }; SECItem keyblk = { siBuffer, NULL, 0 }; - unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; - - crsr.data = crsrdata; - crsr.len = sizeof crsrdata; - - PORT_Memcpy(crsrdata, - ssl3_keys->RandomInfo.pClientRandom, - SSL3_RANDOM_LENGTH); - PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, - ssl3_keys->RandomInfo.pServerRandom, - SSL3_RANDOM_LENGTH); - /* ** client_write_key[CipherSpec.key_material] @@ -5040,6 +5163,8 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, secret.data = &key_block[i]; secret.len = effKeySize; i += effKeySize; + crsr.data = crsrdata; + crsr.len = sizeof crsrdata; keyblk.data = key_block2; keyblk.len = sizeof key_block2; status = TLS_PRF(&secret, "client write key", &crsr, &keyblk, @@ -5177,6 +5302,9 @@ key_and_mac_derive_fail: } case CKM_CONCATENATE_BASE_AND_DATA: + crv = sftk_DeriveSensitiveCheck(sourceKey,key); + if (crv != CKR_OK) break; + stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) pMechanism->pParameter; tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen; if (keySize == 0) keySize = tmpKeySize; @@ -5198,6 +5326,9 @@ key_and_mac_derive_fail: PORT_ZFree(buf,tmpKeySize); break; case CKM_CONCATENATE_DATA_AND_BASE: + crv = sftk_DeriveSensitiveCheck(sourceKey,key); + if (crv != CKR_OK) break; + stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen; if (keySize == 0) keySize = tmpKeySize; @@ -5219,6 +5350,9 @@ key_and_mac_derive_fail: PORT_ZFree(buf,tmpKeySize); break; case CKM_XOR_BASE_AND_DATA: + crv = sftk_DeriveSensitiveCheck(sourceKey,key); + if (crv != CKR_OK) break; + stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; tmpKeySize = PR_MIN(att->attrib.ulValueLen,stringPtr->ulLen); if (keySize == 0) keySize = tmpKeySize; @@ -5249,6 +5383,9 @@ key_and_mac_derive_fail: CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */ CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */ + crv = sftk_DeriveSensitiveCheck(sourceKey,key); + if (crv != CKR_OK) break; + if (keySize == 0) { crv = CKR_TEMPLATE_INCOMPLETE; break; @@ -5382,6 +5519,7 @@ key_and_mac_derive_fail: PRBool withCofactor = PR_FALSE; unsigned char secret_hash[20]; unsigned char *secret; + unsigned char *keyData = NULL; int secretlen; CK_ECDH1_DERIVE_PARAMS *mechParams; NSSLOWKEYPrivateKey *privKey; @@ -5435,26 +5573,59 @@ key_and_mac_derive_fail: break; } + /* + * tmp is the raw data created by ECDH_Derive, + * secret and secretlen are the values we will eventually pass as our + * generated key. + */ secret = tmp.data; secretlen = tmp.len; + + /* + * apply the kdf function. + */ if (mechParams->kdf == CKD_SHA1_KDF) { /* Compute SHA1 hash */ - memset(secret_hash, 0, 20); + PORT_Memset(secret_hash, 0, 20); rv = SHA1_HashBuf(secret_hash, tmp.data, tmp.len); if (rv != SECSuccess) { PORT_ZFree(tmp.data, tmp.len); + crv = CKR_HOST_MEMORY; + break; + } + secret = secret_hash; + secretlen = 20; + } + + /* + * if keySize is supplied, then we are generating a key of a specific + * length. This is done by taking the least significant 'keySize' + * bytes from the unsigned value calculated by ECDH. Note: this may + * mean padding temp with extra leading zeros from what ECDH_Derive + * already returned (which itself may contain leading zeros). + */ + if (keySize) { + if (secretlen < keySize) { + keyData = PORT_ZAlloc(keySize); + if (!keyData) { + PORT_ZFree(tmp.data, tmp.len); + crv = CKR_HOST_MEMORY; + break; + } + PORT_Memcpy(&keyData[keySize-secretlen],secret,secretlen); + secret = keyData; } else { - secret = secret_hash; - secretlen = 20; + secret += (secretlen - keySize); } + secretlen = keySize; } - if (rv == SECSuccess) { - sftk_forceAttribute(key, CKA_VALUE, secret, secretlen); - PORT_ZFree(tmp.data, tmp.len); - memset(secret_hash, 0, 20); - } else - crv = CKR_HOST_MEMORY; + sftk_forceAttribute(key, CKA_VALUE, secret, secretlen); + PORT_ZFree(tmp.data, tmp.len); + if (keyData) { + PORT_ZFree(keyData, keySize); + } + PORT_Memset(secret_hash, 0, 20); break; } @@ -5700,7 +5871,9 @@ CK_RV NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) /* get the key value */ att = sftk_FindAttribute(key,CKA_VALUE); sftk_FreeObject(key); - + if (!att) { + return CKR_KEY_HANDLE_INVALID; + } crv = NSC_DigestUpdate(hSession,(CK_BYTE_PTR)att->attrib.pValue, att->attrib.ulValueLen); sftk_FreeAttribute(att); diff --git a/security/nss/lib/softoken/pkcs11i.h b/security/nss/lib/softoken/pkcs11i.h index 0eaf5bf37..cadcb6ffe 100644 --- a/security/nss/lib/softoken/pkcs11i.h +++ b/security/nss/lib/softoken/pkcs11i.h @@ -88,10 +88,10 @@ * NSS is a shared library. */ #define SPACE_ATTRIBUTE_HASH_SIZE 32 -#define SPACE_TOKEN_OBJECT_HASH_SIZE 32 +#define SPACE_SESSION_OBJECT_HASH_SIZE 32 #define SPACE_SESSION_HASH_SIZE 32 #define TIME_ATTRIBUTE_HASH_SIZE 32 -#define TIME_TOKEN_OBJECT_HASH_SIZE 1024 +#define TIME_SESSION_OBJECT_HASH_SIZE 1024 #define TIME_SESSION_HASH_SIZE 1024 #define MAX_OBJECT_LIST_SIZE 800 /* how many objects to keep on the free list @@ -319,8 +319,9 @@ struct SFTKSessionStr { * * The array of sessionLock's protect the session hash table (head[]) * as well as the reference count of session objects in that bucket - * (head[]->refCount), objectLock protects all elements of the token - * object hash table (tokObjects[], tokenIDCount, and tokenHashTable), + * (head[]->refCount), objectLock protects all elements of the slot's + * object hash tables (sessObjHashTable[] and tokObjHashTable), and + * sessionObjectHandleCount. * slotLock protects the remaining protected elements: * password, isLoggedIn, ssoLoggedIn, and sessionCount, * and pwCheckLock serializes the key database password checks in @@ -366,11 +367,11 @@ struct SFTKSlotStr { int sessionCount; /* variable - reset */ PRInt32 rwSessionCount; /* set by atomic operations */ /* (reset) */ - int tokenIDCount; /* variable - perserved */ + PRUint32 sessionObjectHandleCount; /* variable - preserved */ int index; /* invariant */ - PLHashTable *tokenHashTable; /* invariant */ - SFTKObject **tokObjects; /* variable - reset */ - unsigned int tokObjHashSize; /* invariant */ + PLHashTable *tokObjHashTable; /* invariant */ + SFTKObject **sessObjHashTable; /* variable - reset */ + unsigned int sessObjHashSize; /* invariant */ SFTKSession **head; /* variable -reset */ unsigned int sessHashSize; /* invariant */ char tokDescription[33]; /* per load */ @@ -555,8 +556,8 @@ typedef struct sftk_parametersStr { SEC_BEGIN_PROTOS -/* shared functions between PKCS11.c and SFTKFIPS.c */ -extern int nsf_init; +/* shared functions between pkcs11.c and fipstokn.c */ +extern PRBool nsf_init; extern CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS); extern CK_RV nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS); extern CK_RV nsc_CommonGetSlotList(CK_BBOOL tokPresent, diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c index 8e68587ce..9fc2e08e3 100644 --- a/security/nss/lib/softoken/pkcs11u.c +++ b/security/nss/lib/softoken/pkcs11u.c @@ -67,6 +67,7 @@ sftk_NewAttribute(SFTKObject *object, if (so == NULL) { /* allocate new attribute in a buffer */ PORT_Assert(0); + return NULL; } /* * We attempt to keep down contention on Malloc and Arena locks by @@ -891,6 +892,11 @@ sftk_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, case CKA_BASE: return sftk_NewTokenAttributeSigned(type,key->u.dsa.params.base.data, key->u.dsa.params.base.len, PR_FALSE); + case CKA_NETSCAPE_DB: + return sftk_NewTokenAttributeSigned(type, + key->u.dsa.publicValue.data, + key->u.dsa.publicValue.len, + PR_FALSE); default: break; } @@ -925,6 +931,11 @@ sftk_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type) case CKA_BASE: return sftk_NewTokenAttributeSigned(type,key->u.dh.base.data, key->u.dh.base.len, PR_FALSE); + case CKA_NETSCAPE_DB: + return sftk_NewTokenAttributeSigned(type, + key->u.dh.publicValue.data, + key->u.dh.publicValue.len, + PR_FALSE); default: break; } @@ -960,6 +971,11 @@ sftk_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type) key->u.ec.ecParams.DEREncoding.data, key->u.ec.ecParams.DEREncoding.len, PR_FALSE); + case CKA_NETSCAPE_DB: + return sftk_NewTokenAttributeSigned(type, + key->u.ec.publicValue.data, + key->u.ec.publicValue.len, + PR_FALSE); default: break; } @@ -1502,7 +1518,6 @@ sftk_DeleteAttribute(SFTKObject *object, SFTKAttribute *attribute) sessObject->head, sessObject->hashSize); } PZ_Unlock(sessObject->attributeLock); - sftk_FreeAttribute(attribute); } /* @@ -2078,8 +2093,8 @@ sftk_deleteTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle) SECItem *item; PRBool rem; - item = (SECItem *)PL_HashTableLookup(slot->tokenHashTable, (void *)handle); - rem = PL_HashTableRemove(slot->tokenHashTable,(void *)handle) ; + item = (SECItem *)PL_HashTableLookup(slot->tokObjHashTable, (void *)handle); + rem = PL_HashTableRemove(slot->tokObjHashTable,(void *)handle) ; if (rem && item) { SECITEM_FreeItem(item,PR_TRUE); } @@ -2102,7 +2117,7 @@ sftk_addTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle, SECItem *key) if (item == NULL) { return SECFailure; } - entry = PL_HashTableAdd(slot->tokenHashTable,(void *)handle,item); + entry = PL_HashTableAdd(slot->tokObjHashTable,(void *)handle,item); if (entry == NULL) { SECITEM_FreeItem(item,PR_TRUE); return SECFailure; @@ -2114,7 +2129,7 @@ sftk_addTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle, SECItem *key) static SECItem * sftk_lookupTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle) { - return (SECItem *)PL_HashTableLookup(slot->tokenHashTable, (void *)handle); + return (SECItem *)PL_HashTableLookup(slot->tokObjHashTable, (void *)handle); } /* @@ -2146,7 +2161,7 @@ SFTK_ClearTokenKeyHashTable(SFTKSlot *slot) { sftk_tokenKeyLock(slot); PORT_Assert(!slot->present); - PL_HashTableEnumerateEntries(slot->tokenHashTable, sftk_freeHashItem, NULL); + PL_HashTableEnumerateEntries(slot->tokObjHashTable, sftk_freeHashItem, NULL); sftk_tokenKeyUnlock(slot); return CKR_OK; } @@ -2181,7 +2196,7 @@ sftk_GetObjectFromList(PRBool *hasLocks, PRBool optimizeSpace, + hashSize *sizeof(SFTKAttribute *) : sizeof(SFTKTokenObject); object = (SFTKObject*)PORT_ZAlloc(size); - if (isSessionObject) { + if (isSessionObject && object) { ((SFTKSessionObject *)object)->hashSize = hashSize; } *hasLocks = PR_FALSE; @@ -2393,14 +2408,14 @@ static SFTKObject * sftk_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, SFTKSlot *slot) { SFTKObject *object; - PRUint32 index = sftk_hash(handle, slot->tokObjHashSize); + PRUint32 index = sftk_hash(handle, slot->sessObjHashSize); if (sftk_isToken(handle)) { return sftk_NewTokenObject(slot, NULL, handle); } PZ_Lock(slot->objectLock); - sftkqueue_find2(object, handle, index, slot->tokObjects); + sftkqueue_find2(object, handle, index, slot->sessObjHashTable); if (object) { sftk_ReferenceObject(object); } @@ -2453,10 +2468,10 @@ sftk_FreeObject(SFTKObject *object) void sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object) { - PRUint32 index = sftk_hash(object->handle, slot->tokObjHashSize); + PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize); sftkqueue_init_element(object); PZ_Lock(slot->objectLock); - sftkqueue_add2(object, object->handle, index, slot->tokObjects); + sftkqueue_add2(object, object->handle, index, slot->sessObjHashTable); PZ_Unlock(slot->objectLock); } @@ -2490,7 +2505,7 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object) NSSLOWCERTCertificate *cert; NSSLOWCERTCertTrust tmptrust; PRBool isKrl; - PRUint32 index = sftk_hash(object->handle, slot->tokObjHashSize); + PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize); /* Handle Token case */ if (so && so->session) { @@ -2499,7 +2514,7 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object) sftkqueue_delete(&so->sessionList,0,session->objects,0); PZ_Unlock(session->objectLock); PZ_Lock(slot->objectLock); - sftkqueue_delete2(object, object->handle, index, slot->tokObjects); + sftkqueue_delete2(object, object->handle, index, slot->sessObjHashTable); PZ_Unlock(slot->objectLock); sftkqueue_clear_deleted_element(object); sftk_FreeObject(object); /* reduce it's reference count */ @@ -2749,7 +2764,7 @@ stfk_CopyTokenPrivateKey(SFTKObject *destObject,SFTKTokenObject *src_to) } /* copy the common attributes for all private keys next */ crv = stfk_CopyTokenAttributes(destObject, src_to, commonPrivKeyAttrs, - commonKeyAttrsCount); + commonPrivKeyAttrsCount); if (crv != CKR_OK) { goto fail; } diff --git a/security/nss/lib/softoken/rsawrapr.c b/security/nss/lib/softoken/rsawrapr.c index b40a30d80..c60c71344 100644 --- a/security/nss/lib/softoken/rsawrapr.c +++ b/security/nss/lib/softoken/rsawrapr.c @@ -193,6 +193,7 @@ rsa_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType, unsigned char *bp; int padLen; int i; + SECStatus rv; block = (unsigned char *) PORT_Alloc(modulusLen); if (block == NULL) @@ -254,8 +255,13 @@ rsa_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType, for (i = 0; i < padLen; i++) { /* Pad with non-zero random data. */ do { - RNG_GenerateGlobalRandomBytes(bp + i, 1); - } while (bp[i] == RSA_BLOCK_AFTER_PAD_OCTET); + rv = RNG_GenerateGlobalRandomBytes(bp + i, 1); + } while (rv == SECSuccess && bp[i] == RSA_BLOCK_AFTER_PAD_OCTET); + if (rv != SECSuccess) { + sftk_fatalError = PR_TRUE; + PORT_Free (block); + return NULL; + } } bp += padLen; *bp++ = RSA_BLOCK_AFTER_PAD_OCTET; @@ -292,7 +298,12 @@ rsa_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType, /* * Salt */ - RNG_GenerateGlobalRandomBytes(bp, OAEP_SALT_LEN); + rv = RNG_GenerateGlobalRandomBytes(bp, OAEP_SALT_LEN); + if (rv != SECSuccess) { + sftk_fatalError = PR_TRUE; + PORT_Free (block); + return NULL; + } bp += OAEP_SALT_LEN; /* @@ -310,8 +321,14 @@ rsa_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType, /* * Pad2 */ - if (bp < (block + modulusLen)) - RNG_GenerateGlobalRandomBytes(bp, block - bp + modulusLen); + if (bp < (block + modulusLen)) { + rv = RNG_GenerateGlobalRandomBytes(bp, block - bp + modulusLen); + if (rv != SECSuccess) { + sftk_fatalError = PR_TRUE; + PORT_Free (block); + return NULL; + } + } /* * Now we have the following: @@ -463,6 +480,9 @@ RSA_Sign(NSSLOWKEYPrivateKey *key, goto done; rv = RSA_PrivateKeyOpDoubleChecked(&key->u.rsa, output, formatted.data); + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } *output_len = modulus_len; goto done; @@ -489,7 +509,13 @@ RSA_CheckSign(NSSLOWKEYPublicKey *key, modulus_len = nsslowkey_PublicModulusLen(key); if (sign_len != modulus_len) goto failure; - if (hash_len > modulus_len - 8) + /* + * 0x00 || BT || Pad || 0x00 || ActualData + * + * The "3" below is the first octet + the second octet + the 0x00 + * octet that always comes just before the ActualData. + */ + if (hash_len > modulus_len - (3 + RSA_BLOCK_MIN_PAD_LEN)) goto failure; PORT_Assert(key->keyType == NSSLOWKEYRSAKey); if (key->keyType != NSSLOWKEYRSAKey) @@ -509,11 +535,11 @@ RSA_CheckSign(NSSLOWKEYPublicKey *key, if (buffer[0] != 0 || buffer[1] != 1) goto loser; for (i = 2; i < modulus_len - hash_len - 1; i++) { - if (buffer[i] == 0) - break; if (buffer[i] != 0xff) goto loser; } + if (buffer[i] != 0) + goto loser; /* * make sure we get the same results @@ -659,8 +685,12 @@ RSA_DecryptBlock(NSSLOWKEYPrivateKey *key, goto failure; rv = RSA_PrivateKeyOp(&key->u.rsa, buffer, input); - if (rv != SECSuccess) + if (rv != SECSuccess) { + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } goto loser; + } if (buffer[0] != 0 || buffer[1] != 2) goto loser; @@ -719,6 +749,9 @@ RSA_SignRaw(NSSLOWKEYPrivateKey *key, goto done; rv = RSA_PrivateKeyOpDoubleChecked(&key->u.rsa, output, formatted.data); + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } *output_len = modulus_len; done: @@ -868,8 +901,12 @@ RSA_DecryptRaw(NSSLOWKEYPrivateKey *key, goto failure; rv = RSA_PrivateKeyOp(&key->u.rsa, output, input); - if (rv != SECSuccess) + if (rv != SECSuccess) { + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } goto failure; + } *output_len = modulus_len; return SECSuccess; diff --git a/security/nss/lib/softoken/softkver.c b/security/nss/lib/softoken/softkver.c index 343be94bb..931d620e1 100644 --- a/security/nss/lib/softoken/softkver.c +++ b/security/nss/lib/softoken/softkver.c @@ -36,7 +36,7 @@ /* Library identity and versioning */ -#include "nss.h" +#include "softkver.h" #if defined(DEBUG) #define _DEBUG_STRING " (debug)" @@ -50,7 +50,7 @@ * NOTE: the first component of the concatenated rcsid string * must not end in a '$' to prevent rcs keyword substitution. */ -const char __nss_softokn_rcsid[] = "$Header: NSS " NSS_VERSION _DEBUG_STRING +const char __nss_softokn_rcsid[] = "$Header: NSS " SOFTOKEN_VERSION _DEBUG_STRING " " __DATE__ " " __TIME__ " $"; -const char __nss_softokn_sccsid[] = "@(#)NSS " NSS_VERSION _DEBUG_STRING +const char __nss_softokn_sccsid[] = "@(#)NSS " SOFTOKEN_VERSION _DEBUG_STRING " " __DATE__ " " __TIME__; diff --git a/security/nss/lib/softoken/softkver.h b/security/nss/lib/softoken/softkver.h new file mode 100644 index 000000000..be3ce70fe --- /dev/null +++ b/security/nss/lib/softoken/softkver.h @@ -0,0 +1,66 @@ +/* + * Softoken version numbers + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _SOFTKVER_H_ +#define _SOFTKVER_H_ + +#ifdef NSS_ENABLE_ECC +#ifdef NSS_ECC_MORE_THAN_SUITE_B +#define SOFTOKEN_ECC_STRING " Extended ECC" +#else +#define SOFTOKEN_ECC_STRING " Basic ECC" +#endif +#else +#define SOFTOKEN_ECC_STRING "" +#endif + +/* + * Softoken's major version, minor version, patch level, and whether + * this is a beta release. + * + * The format of the version string should be + * "<major version>.<minor version>[.<patch level>][ <ECC>][ <Beta>]" + */ +#define SOFTOKEN_VERSION "3.11.9.0" SOFTOKEN_ECC_STRING +#define SOFTOKEN_VMAJOR 3 +#define SOFTOKEN_VMINOR 11 +#define SOFTOKEN_VPATCH 9 +#define SOFTOKEN_BETA PR_FALSE + +#endif /* _SOFTKVER_H_ */ diff --git a/security/nss/lib/softoken/softoken.h b/security/nss/lib/softoken/softoken.h index b89546e53..ed9108dcc 100644 --- a/security/nss/lib/softoken/softoken.h +++ b/security/nss/lib/softoken/softoken.h @@ -81,7 +81,7 @@ extern unsigned char *RSA_FormatOneBlock(unsigned int modulusLen, /* * convenience wrappers for doing single RSA operations. They create the * RSA context internally and take care of the formatting - * requirements. Blinding happens automagically within RSA_SignHash and + * requirements. Blinding happens automagically within RSA_Sign and * RSA_DecryptBlock. */ extern @@ -89,10 +89,20 @@ SECStatus RSA_Sign(NSSLOWKEYPrivateKey *key, unsigned char *output, unsigned int *outputLen, unsigned int maxOutputLen, unsigned char *input, unsigned int inputLen); extern +SECStatus RSA_HashSign(SECOidTag hashOid, + NSSLOWKEYPrivateKey *key, unsigned char *sig, + unsigned int *sigLen, unsigned int maxLen, + unsigned char *hash, unsigned int hashLen); +extern SECStatus RSA_CheckSign(NSSLOWKEYPublicKey *key, unsigned char *sign, unsigned int signLength, unsigned char *hash, unsigned int hashLength); extern +SECStatus RSA_HashCheckSign(SECOidTag hashOid, + NSSLOWKEYPublicKey *key, unsigned char *sig, + unsigned int sigLen, unsigned char *digest, + unsigned int digestLen); +extern SECStatus RSA_CheckSignRecover(NSSLOWKEYPublicKey *key, unsigned char *data, unsigned int *data_len,unsigned int max_output_len, unsigned char *sign, unsigned int sign_len); @@ -131,6 +141,14 @@ SECStatus RSA_DecryptRaw(NSSLOWKEYPrivateKey *key, unsigned char *output, unsigned int *output_len, unsigned int max_output_len, unsigned char *input, unsigned int input_len); +#ifdef NSS_ENABLE_ECC +/* +** pepare an ECParam structure from DEREncoded params + */ +extern SECStatus EC_FillParams(PRArenaPool *arena, + const SECItem *encodedParams, ECParams *params); +#endif + /* ** Prepare a buffer for DES encryption, growing to the appropriate boundary, @@ -159,6 +177,83 @@ extern CK_RV sftk_fipsPowerUpSelfTest( void ); */ unsigned long sftk_MapKeySize(CK_KEY_TYPE keyType); +/* +** FIPS 140-2 auditing +*/ +extern PRBool sftk_audit_enabled; + +extern void sftk_LogAuditMessage(NSSAuditSeverity severity, const char *msg); + +extern void sftk_AuditCreateObject(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phObject, CK_RV rv); + +extern void sftk_AuditCopyObject(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phNewObject, CK_RV rv); + +extern void sftk_AuditDestroyObject(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, CK_RV rv); + +extern void sftk_AuditGetObjectSize(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize, + CK_RV rv); + +extern void sftk_AuditGetAttributeValue(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, CK_RV rv); + +extern void sftk_AuditSetAttributeValue(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, CK_RV rv); + +extern void sftk_AuditCryptInit(const char *opName, + CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey, CK_RV rv); + +extern void sftk_AuditGenerateKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey, CK_RV rv); + +extern void sftk_AuditGenerateKeyPair(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pPublicKeyTemplate, + CK_ULONG ulPublicKeyAttributeCount, + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, + CK_ULONG ulPrivateKeyAttributeCount, + CK_OBJECT_HANDLE_PTR phPublicKey, + CK_OBJECT_HANDLE_PTR phPrivateKey, CK_RV rv); + +extern void sftk_AuditWrapKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, + CK_BYTE_PTR pWrappedKey, + CK_ULONG_PTR pulWrappedKeyLen, CK_RV rv); + +extern void sftk_AuditUnwrapKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hUnwrappingKey, + CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, + CK_OBJECT_HANDLE_PTR phKey, CK_RV rv); + +extern void sftk_AuditDeriveKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hBaseKey, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, + CK_OBJECT_HANDLE_PTR phKey, CK_RV rv); + +extern void sftk_AuditDigestKey(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hKey, CK_RV rv); + +/* +** FIPS 140-2 Error state +*/ +extern PRBool sftk_fatalError; + SEC_END_PROTOS #endif /* _SOFTOKEN_H_ */ diff --git a/security/nss/lib/softoken/softokn.rc b/security/nss/lib/softoken/softokn.rc index 0fcaa1219..860155318 100644 --- a/security/nss/lib/softoken/softokn.rc +++ b/security/nss/lib/softoken/softokn.rc @@ -34,7 +34,7 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nss.h" +#include "softkver.h" #include <winver.h> #define MY_LIBNAME "softokn" @@ -42,7 +42,7 @@ #define STRINGIZE(x) #x #define STRINGIZE2(x) STRINGIZE(x) -#define NSS_VMAJOR_STR STRINGIZE2(NSS_VMAJOR) +#define SOFTOKEN_VMAJOR_STR STRINGIZE2(SOFTOKEN_VMAJOR) #ifdef _DEBUG #define MY_DEBUG_STR " (debug)" @@ -51,7 +51,7 @@ #define MY_DEBUG_STR "" #define MY_FILEFLAGS_1 0x0L #endif -#if NSS_BETA +#if SOFTOKEN_BETA #define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE #else #define MY_FILEFLAGS_2 MY_FILEFLAGS_1 @@ -63,7 +63,7 @@ #define MY_FILEOS VOS__WINDOWS32 #endif -#define MY_INTERNAL_NAME MY_LIBNAME NSS_VMAJOR_STR +#define MY_INTERNAL_NAME MY_LIBNAME SOFTOKEN_VMAJOR_STR ///////////////////////////////////////////////////////////////////////////// // @@ -71,8 +71,8 @@ // VS_VERSION_INFO VERSIONINFO - FILEVERSION NSS_VMAJOR,NSS_VMINOR,NSS_VPATCH,0 - PRODUCTVERSION NSS_VMAJOR,NSS_VMINOR,NSS_VPATCH,0 + FILEVERSION SOFTOKEN_VMAJOR,SOFTOKEN_VMINOR,SOFTOKEN_VPATCH,0 + PRODUCTVERSION SOFTOKEN_VMAJOR,SOFTOKEN_VMINOR,SOFTOKEN_VPATCH,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS MY_FILEFLAGS_2 FILEOS MY_FILEOS @@ -84,14 +84,13 @@ BEGIN BEGIN BLOCK "040904B0" // Lang=US English, CharSet=Unicode BEGIN - VALUE "CompanyName", "Netscape Communications Corporation\0" + VALUE "CompanyName", "Mozilla Foundation\0" VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0" - VALUE "FileVersion", NSS_VERSION "\0" + VALUE "FileVersion", SOFTOKEN_VERSION "\0" VALUE "InternalName", MY_INTERNAL_NAME "\0" - VALUE "LegalCopyright", "Copyright \251 1994-2001 Netscape Communications Corporation\0" VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0" VALUE "ProductName", "Network Security Services\0" - VALUE "ProductVersion", NSS_VERSION "\0" + VALUE "ProductVersion", SOFTOKEN_VERSION "\0" END END BLOCK "VarFileInfo" diff --git a/security/nss/lib/softoken/softoknt.h b/security/nss/lib/softoken/softoknt.h index b499eb6b0..3af94e286 100644 --- a/security/nss/lib/softoken/softoknt.h +++ b/security/nss/lib/softoken/softoknt.h @@ -61,4 +61,13 @@ typedef enum { #define NSS_SOFTOKEN_DEFAULT_CHUNKSIZE 2048 +/* + * FIPS 140-2 auditing + */ +typedef enum { + NSS_AUDIT_ERROR = 3, /* errors */ + NSS_AUDIT_WARNING = 2, /* warning messages */ + NSS_AUDIT_INFO = 1 /* informational messages */ +} NSSAuditSeverity; + #endif /* _SOFTOKNT_H_ */ |