| Index: mozilla/security/nss/lib/softoken/pkcs11.c
|
| ===================================================================
|
| --- mozilla/security/nss/lib/softoken/pkcs11.c (revision 158129)
|
| +++ mozilla/security/nss/lib/softoken/pkcs11.c (working copy)
|
| @@ -32,9 +32,11 @@
|
| #include "softkver.h"
|
| #include "secoid.h"
|
| #include "sftkdb.h"
|
| -#include "sftkpars.h"
|
| +#include "utilpars.h"
|
| #include "ec.h"
|
| #include "secasn1.h"
|
| +#include "secerr.h"
|
| +#include "lgglue.h"
|
|
|
| PRBool parentForkedAfterC_Initialize;
|
|
|
| @@ -290,6 +292,8 @@
|
| CKF_GENERATE_KEY_PAIR}, PR_TRUE},
|
| {CKM_DSA, {DSA_MIN_P_BITS, DSA_MAX_P_BITS,
|
| CKF_SN_VR}, PR_TRUE},
|
| + {CKM_DSA_PARAMETER_GEN, {DSA_MIN_P_BITS, DSA_MAX_P_BITS,
|
| + CKF_GENERATE}, PR_TRUE},
|
| {CKM_DSA_SHA1, {DSA_MIN_P_BITS, DSA_MAX_P_BITS,
|
| CKF_SN_VR}, PR_TRUE},
|
| /* -------------------- Diffie Hellman Operations --------------------- */
|
| @@ -442,6 +446,10 @@
|
| {CKM_MD5_KEY_DERIVATION, { 0, 16, CKF_DERIVE}, PR_FALSE},
|
| {CKM_MD2_KEY_DERIVATION, { 0, 16, CKF_DERIVE}, PR_FALSE},
|
| {CKM_SHA1_KEY_DERIVATION, { 0, 20, CKF_DERIVE}, PR_FALSE},
|
| + {CKM_SHA224_KEY_DERIVATION, { 0, 28, CKF_DERIVE}, PR_FALSE},
|
| + {CKM_SHA256_KEY_DERIVATION, { 0, 32, CKF_DERIVE}, PR_FALSE},
|
| + {CKM_SHA384_KEY_DERIVATION, { 0, 48, CKF_DERIVE}, PR_FALSE},
|
| + {CKM_SHA512_KEY_DERIVATION, { 0, 64, CKF_DERIVE}, PR_FALSE},
|
| {CKM_TLS_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE},
|
| {CKM_TLS_MASTER_KEY_DERIVE_DH, {8, 128, CKF_DERIVE}, PR_FALSE},
|
| {CKM_TLS_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE},
|
| @@ -860,7 +868,7 @@
|
| break;
|
| case CKK_DSA:
|
| crv = sftk_ConstrainAttribute(object, CKA_SUBPRIME,
|
| - DSA_Q_BITS, DSA_Q_BITS, 0);
|
| + DSA_MIN_Q_BITS, DSA_MAX_Q_BITS, 0);
|
| if (crv != CKR_OK) {
|
| return crv;
|
| }
|
| @@ -869,11 +877,11 @@
|
| if (crv != CKR_OK) {
|
| return crv;
|
| }
|
| - crv = sftk_ConstrainAttribute(object, CKA_BASE, 1, DSA_MAX_P_BITS, 0);
|
| + crv = sftk_ConstrainAttribute(object, CKA_BASE, 2, DSA_MAX_P_BITS, 0);
|
| if (crv != CKR_OK) {
|
| return crv;
|
| }
|
| - crv = sftk_ConstrainAttribute(object, CKA_VALUE, 1, DSA_MAX_P_BITS, 0);
|
| + crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, DSA_MAX_P_BITS, 0);
|
| if (crv != CKR_OK) {
|
| return crv;
|
| }
|
| @@ -887,11 +895,11 @@
|
| if (crv != CKR_OK) {
|
| return crv;
|
| }
|
| - crv = sftk_ConstrainAttribute(object, CKA_BASE, 1, DH_MAX_P_BITS, 0);
|
| + crv = sftk_ConstrainAttribute(object, CKA_BASE, 2, DH_MAX_P_BITS, 0);
|
| if (crv != CKR_OK) {
|
| return crv;
|
| }
|
| - crv = sftk_ConstrainAttribute(object, CKA_VALUE, 1, DH_MAX_P_BITS, 0);
|
| + crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, DH_MAX_P_BITS, 0);
|
| if (crv != CKR_OK) {
|
| return crv;
|
| }
|
| @@ -1349,6 +1357,23 @@
|
| PQGParams params;
|
| PQGVerify vfy, *verify = NULL;
|
| SECStatus result,rv;
|
| + /* This bool keeps track of whether or not we need verify parameters.
|
| + * If a P, Q and G or supplied, we dont' need verify parameters, as we
|
| + * have PQ and G.
|
| + * - If G is not supplied, the presumption is that we want to
|
| + * verify P and Q only.
|
| + * - If counter is supplied, it is presumed we want to verify PQ because
|
| + * the counter is only used in verification.
|
| + * - If H is supplied, is is presumed we want to verify G because H is
|
| + * only used to verify G.
|
| + * - Any verification step must have the SEED (counter or H could be
|
| + * missing depending on exactly what we want to verify). If SEED is supplied,
|
| + * the code just goes ahead and runs verify (other errors are parameter
|
| + * errors are detected by the PQG_VerifyParams function). If SEED is not
|
| + * supplied, but we determined that we are trying to verify (because needVfy
|
| + * is set, go ahead and return CKR_TEMPLATE_INCOMPLETE.
|
| + */
|
| + PRBool needVfy = PR_FALSE;
|
|
|
| primeAttr = sftk_FindAttribute(object,CKA_PRIME);
|
| if (primeAttr == NULL) goto loser;
|
| @@ -1361,26 +1386,43 @@
|
| params.subPrime.len = subPrimeAttr->attrib.ulValueLen;
|
|
|
| baseAttr = sftk_FindAttribute(object,CKA_BASE);
|
| - if (baseAttr == NULL) goto loser;
|
| - params.base.data = baseAttr->attrib.pValue;
|
| - params.base.len = baseAttr->attrib.ulValueLen;
|
| + if (baseAttr != NULL) {
|
| + params.base.data = baseAttr->attrib.pValue;
|
| + params.base.len = baseAttr->attrib.ulValueLen;
|
| + } else {
|
| + params.base.data = NULL;
|
| + params.base.len = 0;
|
| + needVfy = PR_TRUE; /* presumably only including PQ so we can verify
|
| + * them. */
|
| + }
|
|
|
| attribute = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_COUNTER);
|
| if (attribute != NULL) {
|
| vfy.counter = *(CK_ULONG *) attribute->attrib.pValue;
|
| sftk_FreeAttribute(attribute);
|
| + needVfy = PR_TRUE; /* included a count so we can verify PQ */
|
| + } else {
|
| + vfy.counter = -1;
|
| + }
|
|
|
| - seedAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_SEED);
|
| - if (seedAttr == NULL) goto loser;
|
| + hAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_H);
|
| + if (hAttr != NULL) {
|
| + vfy.h.data = hAttr->attrib.pValue;
|
| + vfy.h.len = hAttr->attrib.ulValueLen;
|
| + needVfy = PR_TRUE; /* included H so we can verify G */
|
| + } else {
|
| + vfy.h.data = NULL;
|
| + vfy.h.len = 0;
|
| + }
|
| + seedAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_SEED);
|
| + if (seedAttr != NULL) {
|
| vfy.seed.data = seedAttr->attrib.pValue;
|
| vfy.seed.len = seedAttr->attrib.ulValueLen;
|
|
|
| - hAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_H);
|
| - if (hAttr == NULL) goto loser;
|
| - vfy.h.data = hAttr->attrib.pValue;
|
| - vfy.h.len = hAttr->attrib.ulValueLen;
|
| -
|
| verify = &vfy;
|
| + } else if (needVfy) {
|
| + goto loser; /* Verify always needs seed, if we need verify and not seed
|
| + * then fail */
|
| }
|
|
|
| crv = CKR_FUNCTION_FAILED;
|
| @@ -2590,16 +2632,6 @@
|
| return CKR_OK;
|
| }
|
|
|
| -#ifndef NO_FORK_CHECK
|
| -
|
| -static CK_RV ForkCheck(void)
|
| -{
|
| - CHECK_FORK();
|
| - return CKR_OK;
|
| -}
|
| -
|
| -#endif
|
| -
|
| /*
|
| * handle the SECMOD.db
|
| */
|
| @@ -2609,35 +2641,88 @@
|
| char *secmod = NULL;
|
| char *appName = NULL;
|
| char *filename = NULL;
|
| -#ifdef NSS_DISABLE_DBM
|
| - SDBType dbType = SDB_SQL;
|
| -#else
|
| - SDBType dbType = SDB_LEGACY;
|
| -#endif
|
| + NSSDBType dbType = NSS_DB_TYPE_NONE;
|
| PRBool rw;
|
| static char *success="Success";
|
| char **rvstr = NULL;
|
|
|
| -#ifndef NO_FORK_CHECK
|
| - if (CKR_OK != ForkCheck()) return NULL;
|
| -#endif
|
| + rvstr = NSSUTIL_DoModuleDBFunction(function, parameters, args);
|
| + if (rvstr != NULL) {
|
| + return rvstr;
|
| + }
|
|
|
| - secmod = sftk_getSecmodName(parameters, &dbType, &appName,&filename, &rw);
|
| + if (PORT_GetError() != SEC_ERROR_LEGACY_DATABASE) {
|
| + return NULL;
|
| + }
|
|
|
| + /* The legacy database uses the old dbm, which is only linked with the
|
| + * legacy DB handler, which is only callable from softoken */
|
| +
|
| + secmod = _NSSUTIL_GetSecmodName(parameters, &dbType, &appName,
|
| + &filename, &rw);
|
| +
|
| switch (function) {
|
| case SECMOD_MODULE_DB_FUNCTION_FIND:
|
| - rvstr = sftkdb_ReadSecmodDB(dbType,appName,filename,secmod,(char *)parameters,rw);
|
| + if (secmod == NULL) {
|
| + PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| + return NULL;
|
| + }
|
| + if (rw && (dbType != NSS_DB_TYPE_LEGACY) &&
|
| + (dbType != NSS_DB_TYPE_MULTIACCESS)) {
|
| + /* if we get here, we are trying to update the local database */
|
| + /* force data from the legacy DB */
|
| + char *oldSecmod = NULL;
|
| + char *oldAppName = NULL;
|
| + char *oldFilename = NULL;
|
| + PRBool oldrw;
|
| + char **strings = NULL;
|
| + int i;
|
| +
|
| + dbType = NSS_DB_TYPE_LEGACY;
|
| + oldSecmod = _NSSUTIL_GetSecmodName(parameters,&dbType, &oldAppName,
|
| + &oldFilename, &oldrw);
|
| + strings = sftkdbCall_ReadSecmodDB(appName, oldFilename, oldSecmod,
|
| + (char *)parameters, oldrw);
|
| + if (strings) {
|
| + /* write out the strings */
|
| + for (i=0; strings[i]; i++) {
|
| + NSSUTIL_DoModuleDBFunction(SECMOD_MODULE_DB_FUNCTION_ADD,
|
| + parameters, strings[i]);
|
| + }
|
| + sftkdbCall_ReleaseSecmodDBData(oldAppName,oldFilename,oldSecmod,
|
| + (char **)strings,oldrw);
|
| + } else {
|
| + /* write out a dummy record */
|
| + NSSUTIL_DoModuleDBFunction(SECMOD_MODULE_DB_FUNCTION_ADD,
|
| + parameters, " ");
|
| + }
|
| + if (oldSecmod) { PR_smprintf_free(oldSecmod); }
|
| + if (oldAppName) { PORT_Free(oldAppName); }
|
| + if (oldFilename) { PORT_Free(oldFilename); }
|
| + rvstr = NSSUTIL_DoModuleDBFunction(function, parameters, args);
|
| + break;
|
| + }
|
| + rvstr = sftkdbCall_ReadSecmodDB(appName,filename,secmod,
|
| + (char *)parameters,rw);
|
| break;
|
| case SECMOD_MODULE_DB_FUNCTION_ADD:
|
| - rvstr = (sftkdb_AddSecmodDB(dbType,appName,filename,secmod,(char *)args,rw)
|
| - == SECSuccess) ? &success: NULL;
|
| + if (secmod == NULL) {
|
| + PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| + return NULL;
|
| + }
|
| + rvstr = (sftkdbCall_AddSecmodDB(appName,filename,secmod,
|
| + (char *)args,rw) == SECSuccess) ? &success: NULL;
|
| break;
|
| case SECMOD_MODULE_DB_FUNCTION_DEL:
|
| - rvstr = (sftkdb_DeleteSecmodDB(dbType,appName,filename,secmod,(char *)args,rw)
|
| - == SECSuccess) ? &success: NULL;
|
| + if (secmod == NULL) {
|
| + PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| + return NULL;
|
| + }
|
| + rvstr = (sftkdbCall_DeleteSecmodDB(appName,filename,secmod,
|
| + (char *)args,rw) == SECSuccess) ? &success: NULL;
|
| break;
|
| case SECMOD_MODULE_DB_FUNCTION_RELEASE:
|
| - rvstr = (sftkdb_ReleaseSecmodDBData(dbType, appName,filename,secmod,
|
| + rvstr = (sftkdbCall_ReleaseSecmodDBData(appName,filename,secmod,
|
| (char **)args,rw) == SECSuccess) ? &success: NULL;
|
| break;
|
| }
|
| @@ -3816,16 +3901,19 @@
|
| }
|
|
|
| /*
|
| - * Create a new slot on the fly. The slot that is passed in is the
|
| - * slot the request came from. Only the crypto or FIPS slots can
|
| - * be used. The resulting slot will live in the same module as
|
| - * the slot the request was passed to. object is the creation object
|
| - * that specifies the module spec for the new slot.
|
| + * Create or remove a new slot on the fly.
|
| + * When creating a slot, "slot" is the slot that the request came from. The
|
| + * resulting slot will live in the same module as "slot".
|
| + * When removing a slot, "slot" is the slot to be removed.
|
| + * "object" is the creation object that specifies the module spec for the slot
|
| + * to add or remove.
|
| */
|
| static CK_RV sftk_CreateNewSlot(SFTKSlot *slot, CK_OBJECT_CLASS class,
|
| SFTKObject *object)
|
| {
|
| - CK_SLOT_ID idMin, idMax;
|
| + PRBool isValidUserSlot = PR_FALSE;
|
| + PRBool isValidFIPSUserSlot = PR_FALSE;
|
| + PRBool isValidSlot = PR_FALSE;
|
| PRBool isFIPS = PR_FALSE;
|
| unsigned long moduleIndex;
|
| SFTKAttribute *attribute;
|
| @@ -3835,21 +3923,13 @@
|
| SFTKSlot *newSlot = NULL;
|
| CK_RV crv = CKR_OK;
|
|
|
| - /* only the crypto or FIPS slots can create new slot objects */
|
| - if (slot->slotID == NETSCAPE_SLOT_ID) {
|
| - idMin = SFTK_MIN_USER_SLOT_ID;
|
| - idMax = SFTK_MAX_USER_SLOT_ID;
|
| - moduleIndex = NSC_NON_FIPS_MODULE;
|
| - isFIPS = PR_FALSE;
|
| - } else if (slot->slotID == FIPS_SLOT_ID) {
|
| - idMin = SFTK_MIN_FIPS_USER_SLOT_ID;
|
| - idMax = SFTK_MAX_FIPS_USER_SLOT_ID;
|
| - moduleIndex = NSC_FIPS_MODULE;
|
| - isFIPS = PR_TRUE;
|
| - } else {
|
| + if (class != CKO_NETSCAPE_DELSLOT && class != CKO_NETSCAPE_NEWSLOT) {
|
| return CKR_ATTRIBUTE_VALUE_INVALID;
|
| }
|
| - attribute = sftk_FindAttribute(object,CKA_NETSCAPE_MODULE_SPEC);
|
| + if (class == CKO_NETSCAPE_NEWSLOT && slot->slotID == FIPS_SLOT_ID) {
|
| + isFIPS = PR_TRUE;
|
| + }
|
| + attribute = sftk_FindAttribute(object, CKA_NETSCAPE_MODULE_SPEC);
|
| if (attribute == NULL) {
|
| return CKR_TEMPLATE_INCOMPLETE;
|
| }
|
| @@ -3868,7 +3948,27 @@
|
| slotID = paramStrings.tokens[0].slotID;
|
|
|
| /* stay within the valid ID space */
|
| - if ((slotID < idMin) || (slotID > idMax)) {
|
| + isValidUserSlot = (slotID >= SFTK_MIN_USER_SLOT_ID &&
|
| + slotID <= SFTK_MAX_USER_SLOT_ID);
|
| + isValidFIPSUserSlot = (slotID >= SFTK_MIN_FIPS_USER_SLOT_ID &&
|
| + slotID <= SFTK_MAX_FIPS_USER_SLOT_ID);
|
| +
|
| + if (class == CKO_NETSCAPE_DELSLOT) {
|
| + if (slot->slotID == slotID) {
|
| + isValidSlot = isValidUserSlot || isValidFIPSUserSlot;
|
| + }
|
| + } else {
|
| + /* only the crypto or FIPS slots can create new slot objects */
|
| + if (slot->slotID == NETSCAPE_SLOT_ID) {
|
| + isValidSlot = isValidUserSlot;
|
| + moduleIndex = NSC_NON_FIPS_MODULE;
|
| + } else if (slot->slotID == FIPS_SLOT_ID) {
|
| + isValidSlot = isValidFIPSUserSlot;
|
| + moduleIndex = NSC_FIPS_MODULE;
|
| + }
|
| + }
|
| +
|
| + if (!isValidSlot) {
|
| crv = CKR_ATTRIBUTE_VALUE_INVALID;
|
| goto loser;
|
| }
|
| @@ -3885,7 +3985,7 @@
|
| /* if we were just planning on deleting the slot, then do so now */
|
| if (class == CKO_NETSCAPE_DELSLOT) {
|
| /* sort of a unconventional use of this error code, be we are
|
| - * overusing CKR_ATTRIBUTE_VALUE_INVALID, and it does apply */
|
| + * overusing CKR_ATTRIBUTE_VALUE_INVALID, and it does apply */
|
| crv = newSlot ? CKR_OK : CKR_SLOT_ID_INVALID;
|
| goto loser; /* really exit */
|
| }
|
| @@ -3899,9 +3999,7 @@
|
| paramStrings.updatedir, paramStrings.updateID,
|
| ¶mStrings.tokens[0], moduleIndex);
|
| }
|
| - if (crv != CKR_OK) {
|
| - goto loser;
|
| - }
|
| +
|
| loser:
|
| sftk_freeParams(¶mStrings);
|
| sftk_FreeAttribute(attribute);
|
|
|