示例#1
0
NSS_IMPLEMENT PRBool
nssCKObject_IsAttributeTrue(
    CK_OBJECT_HANDLE object,
    CK_ATTRIBUTE_TYPE attribute,
    nssSession *session,
    NSSSlot *slot,
    PRStatus *rvStatus)
{
    CK_BBOOL bool;
    CK_ATTRIBUTE_PTR attr;
    CK_ATTRIBUTE atemplate = { 0, NULL, 0 };
    CK_RV ckrv;
    void *epv = nssSlot_GetCryptokiEPV(slot);
    attr = &atemplate;
    NSS_CK_SET_ATTRIBUTE_VAR(attr, attribute, bool);
    nssSession_EnterMonitor(session);
    ckrv = CKAPI(epv)->C_GetAttributeValue(session->handle, object,
                                           &atemplate, 1);
    nssSession_ExitMonitor(session);
    if (ckrv != CKR_OK) {
        *rvStatus = PR_FAILURE;
        return PR_FALSE;
    }
    *rvStatus = PR_SUCCESS;
    return (PRBool)(bool == CK_TRUE);
}
示例#2
0
NSS_IMPLEMENT NSSItem *
nssToken_FinishDigest (
  NSSToken *tok,
  nssSession *sessionOpt,
  NSSItem *rvOpt,
  NSSArena *arenaOpt
)
{
    CK_RV ckrv;
    CK_ULONG digestLen;
    CK_BYTE_PTR digest;
    NSSItem *rvItem = NULL;
    void *epv = nssToken_GetCryptokiEPV(tok);
    nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;

    /* Don't ask the module to use an invalid session handle. */
    if (!session || session->handle == CK_INVALID_SESSION) {
	PORT_SetError(SEC_ERROR_NO_TOKEN);
	return NULL;
    }

    nssSession_EnterMonitor(session);
    ckrv = CKAPI(epv)->C_DigestFinal(session->handle, NULL, &digestLen);
    if (ckrv != CKR_OK || digestLen == 0) {
	nssSession_ExitMonitor(session);
	return NULL;
    }
    digest = NULL;
    if (rvOpt) {
	if (rvOpt->size > 0 && rvOpt->size < digestLen) {
	    nssSession_ExitMonitor(session);
	    /* the error should be bad args */
	    return NULL;
	}
	if (rvOpt->data) {
	    digest = rvOpt->data;
	}
	digestLen = rvOpt->size;
    }
    if (!digest) {
	digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen);
	if (!digest) {
	    nssSession_ExitMonitor(session);
	    return NULL;
	}
    }
    ckrv = CKAPI(epv)->C_DigestFinal(session->handle, digest, &digestLen);
    nssSession_ExitMonitor(session);
    if (ckrv != CKR_OK) {
	nss_ZFreeIf(digest);
	return NULL;
    }
    if (!rvOpt) {
	rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest);
    }
    return rvItem;
}
示例#3
0
static nssCryptokiObject *
import_object (
  NSSToken *tok,
  nssSession *sessionOpt,
  CK_ATTRIBUTE_PTR objectTemplate,
  CK_ULONG otsize
)
{
    nssSession *session = NULL;
    PRBool createdSession = PR_FALSE;
    nssCryptokiObject *object = NULL;
    CK_OBJECT_HANDLE handle;
    CK_RV ckrv;
    void *epv = nssToken_GetCryptokiEPV(tok);
    if (nssCKObject_IsTokenObjectTemplate(objectTemplate, otsize)) {
	if (sessionOpt) {
	    if (!nssSession_IsReadWrite(sessionOpt)) {
		nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
		return NULL;
	    }
	    session = sessionOpt;
	} else if (tok->defaultSession && 
	           nssSession_IsReadWrite(tok->defaultSession)) {
	    session = tok->defaultSession;
	} else {
	    session = nssSlot_CreateSession(tok->slot, NULL, PR_TRUE);
	    createdSession = PR_TRUE;
	}
    } else {
	session = (sessionOpt) ? sessionOpt : tok->defaultSession;
    }
    if (session == NULL) {
	nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
	return NULL;
    }
    nssSession_EnterMonitor(session);
    ckrv = CKAPI(epv)->C_CreateObject(session->handle, 
                                      objectTemplate, otsize,
                                      &handle);
    nssSession_ExitMonitor(session);
    if (ckrv == CKR_OK) {
	object = nssCryptokiObject_Create(tok, session, handle);
    } else {
	nss_SetError(ckrv);
	nss_SetError(NSS_ERROR_PKCS11);
    }
    if (createdSession) {
	nssSession_Destroy(session);
    }
    return object;
}
示例#4
0
NSS_IMPLEMENT PRStatus
nssCKObject_SetAttributes(
    CK_OBJECT_HANDLE object,
    CK_ATTRIBUTE_PTR obj_template,
    CK_ULONG count,
    nssSession *session,
    NSSSlot *slot)
{
    CK_RV ckrv;
    void *epv = nssSlot_GetCryptokiEPV(slot);
    nssSession_EnterMonitor(session);
    ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle, object,
                                           obj_template, count);
    nssSession_ExitMonitor(session);
    if (ckrv == CKR_OK) {
        return PR_SUCCESS;
    } else {
        return PR_FAILURE;
    }
}
示例#5
0
NSS_IMPLEMENT PRStatus
nssToken_DeleteStoredObject (
  nssCryptokiObject *instance
)
{
    CK_RV ckrv;
    PRStatus status;
    PRBool createdSession = PR_FALSE;
    NSSToken *token = instance->token;
    nssSession *session = NULL;
    void *epv = nssToken_GetCryptokiEPV(instance->token);
    if (token->cache) {
	nssTokenObjectCache_RemoveObject(token->cache, instance);
    }
    if (instance->isTokenObject) {
       if (token->defaultSession && 
           nssSession_IsReadWrite(token->defaultSession)) {
	   session = token->defaultSession;
       } else {
	   session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE);
	   createdSession = PR_TRUE;
       }
    }
    if (session == NULL) {
	return PR_FAILURE;
    }
    nssSession_EnterMonitor(session);
    ckrv = CKAPI(epv)->C_DestroyObject(session->handle, instance->handle);
    nssSession_ExitMonitor(session);
    if (createdSession) {
	nssSession_Destroy(session);
    }
    status = PR_SUCCESS;
    if (ckrv != CKR_OK) {
	status = PR_FAILURE;
	/* use the error stack to pass the PKCS #11 error out  */
	nss_SetError(ckrv);
	nss_SetError(NSS_ERROR_PKCS11);
    }
    return status;
}
示例#6
0
NSS_IMPLEMENT PRStatus
nssToken_BeginDigest (
  NSSToken *tok,
  nssSession *sessionOpt,
  NSSAlgorithmAndParameters *ap
)
{
    CK_RV ckrv;
    void *epv = nssToken_GetCryptokiEPV(tok);
    nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;

    /* Don't ask the module to use an invalid session handle. */
    if (!session || session->handle == CK_INVALID_SESSION) {
	PORT_SetError(SEC_ERROR_NO_TOKEN);
	return PR_FAILURE;
    }

    nssSession_EnterMonitor(session);
    ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism);
    nssSession_ExitMonitor(session);
    return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
}
示例#7
0
NSS_IMPLEMENT PRStatus
nssToken_ContinueDigest (
  NSSToken *tok,
  nssSession *sessionOpt,
  NSSItem *item
)
{
    CK_RV ckrv;
    void *epv = nssToken_GetCryptokiEPV(tok);
    nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;

    /* Don't ask the module to use an invalid session handle. */
    if (!session || session->handle == CK_INVALID_SESSION) {
	PORT_SetError(SEC_ERROR_NO_TOKEN);
	return PR_FAILURE;
    }

    nssSession_EnterMonitor(session);
    ckrv = CKAPI(epv)->C_DigestUpdate(session->handle, 
                                      (CK_BYTE_PTR)item->data, 
                                      (CK_ULONG)item->size);
    nssSession_ExitMonitor(session);
    return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
}
示例#8
0
/* Sigh.  The methods to find objects declared above cause problems with
 * the low-level object cache in the softoken -- the objects are found in 
 * toto, then one wave of GetAttributes is done, then another.  Having a 
 * large number of objects causes the cache to be thrashed, as the objects 
 * are gone before there's any chance to ask for their attributes.
 * So, for now, bringing back traversal methods for certs.  This way all of 
 * the cert's attributes can be grabbed immediately after finding it,
 * increasing the likelihood that the cache takes care of it.
 */
NSS_IMPLEMENT PRStatus
nssToken_TraverseCertificates (
  NSSToken *token,
  nssSession *sessionOpt,
  nssTokenSearchType searchType,
  PRStatus (* callback)(nssCryptokiObject *instance, void *arg),
  void *arg
)
{
    CK_RV ckrv;
    CK_ULONG count;
    CK_OBJECT_HANDLE *objectHandles;
    CK_ATTRIBUTE_PTR attr;
    CK_ATTRIBUTE cert_template[2];
    CK_ULONG ctsize;
    NSSArena *arena;
    PRStatus status;
    PRUint32 arraySize, numHandles;
    nssCryptokiObject **objects;
    void *epv = nssToken_GetCryptokiEPV(token);
    nssSession *session = (sessionOpt) ? sessionOpt : token->defaultSession;

    /* Don't ask the module to use an invalid session handle. */
    if (!session || session->handle == CK_INVALID_SESSION) {
	PORT_SetError(SEC_ERROR_NO_TOKEN);
	return PR_FAILURE;
    }

    /* template for all certs */
    NSS_CK_TEMPLATE_START(cert_template, attr, ctsize);
    if (searchType == nssTokenSearchType_SessionOnly) {
	NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
    } else if (searchType == nssTokenSearchType_TokenOnly ||
               searchType == nssTokenSearchType_TokenForced) {
	NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
    }
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
    NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize);

    /* the arena is only for the array of object handles */
    arena = nssArena_Create();
    if (!arena) {
	return PR_FAILURE;
    }
    arraySize = OBJECT_STACK_SIZE;
    numHandles = 0;
    objectHandles = nss_ZNEWARRAY(arena, CK_OBJECT_HANDLE, arraySize);
    if (!objectHandles) {
	goto loser;
    }
    nssSession_EnterMonitor(session); /* ==== session lock === */
    /* Initialize the find with the template */
    ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle, 
                                         cert_template, ctsize);
    if (ckrv != CKR_OK) {
	nssSession_ExitMonitor(session);
	goto loser;
    }
    while (PR_TRUE) {
	/* Issue the find for up to arraySize - numHandles objects */
	ckrv = CKAPI(epv)->C_FindObjects(session->handle, 
	                                 objectHandles + numHandles, 
	                                 arraySize - numHandles, 
	                                 &count);
	if (ckrv != CKR_OK) {
	    nssSession_ExitMonitor(session);
	    goto loser;
	}
	/* bump the number of found objects */
	numHandles += count;
	if (numHandles < arraySize) {
	    break;
	}
	/* the array is filled, double it and continue */
	arraySize *= 2;
	objectHandles = nss_ZREALLOCARRAY(objectHandles, 
	                                  CK_OBJECT_HANDLE, 
	                                  arraySize);
	if (!objectHandles) {
	    nssSession_ExitMonitor(session);
	    goto loser;
	}
    }
    ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle);
    nssSession_ExitMonitor(session); /* ==== end session lock === */
    if (ckrv != CKR_OK) {
	goto loser;
    }
    if (numHandles > 0) {
	objects = create_objects_from_handles(token, session,
	                                      objectHandles, numHandles);
	if (objects) {
	    nssCryptokiObject **op;
	    for (op = objects; *op; op++) {
		status = (*callback)(*op, arg);
	    }
	    nss_ZFreeIf(objects);
	}
    }
    nssArena_Destroy(arena);
    return PR_SUCCESS;
loser:
    nssArena_Destroy(arena);
    return PR_FAILURE;
}
示例#9
0
NSS_IMPLEMENT NSSItem *
nssToken_Digest (
  NSSToken *tok,
  nssSession *sessionOpt,
  NSSAlgorithmAndParameters *ap,
  NSSItem *data,
  NSSItem *rvOpt,
  NSSArena *arenaOpt
)
{
    CK_RV ckrv;
    CK_ULONG digestLen;
    CK_BYTE_PTR digest;
    NSSItem *rvItem = NULL;
    void *epv = nssToken_GetCryptokiEPV(tok);
    nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;

    /* Don't ask the module to use an invalid session handle. */
    if (!session || session->handle == CK_INVALID_SESSION) {
	PORT_SetError(SEC_ERROR_NO_TOKEN);
	return rvItem;
    }

    nssSession_EnterMonitor(session);
    ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism);
    if (ckrv != CKR_OK) {
	nssSession_ExitMonitor(session);
	return NULL;
    }
#if 0
    /* XXX the standard says this should work, but it doesn't */
    ckrv = CKAPI(epv)->C_Digest(session->handle, NULL, 0, NULL, &digestLen);
    if (ckrv != CKR_OK) {
	nssSession_ExitMonitor(session);
	return NULL;
    }
#endif
    digestLen = 0; /* XXX for now */
    digest = NULL;
    if (rvOpt) {
	if (rvOpt->size > 0 && rvOpt->size < digestLen) {
	    nssSession_ExitMonitor(session);
	    /* the error should be bad args */
	    return NULL;
	}
	if (rvOpt->data) {
	    digest = rvOpt->data;
	}
	digestLen = rvOpt->size;
    }
    if (!digest) {
	digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen);
	if (!digest) {
	    nssSession_ExitMonitor(session);
	    return NULL;
	}
    }
    ckrv = CKAPI(epv)->C_Digest(session->handle, 
                                (CK_BYTE_PTR)data->data, 
                                (CK_ULONG)data->size,
                                (CK_BYTE_PTR)digest,
                                &digestLen);
    nssSession_ExitMonitor(session);
    if (ckrv != CKR_OK) {
	nss_ZFreeIf(digest);
	return NULL;
    }
    if (!rvOpt) {
	rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest);
    }
    return rvItem;
}
示例#10
0
NSS_IMPLEMENT PRStatus
nssCKObject_GetAttributes(
    CK_OBJECT_HANDLE object,
    CK_ATTRIBUTE_PTR obj_template,
    CK_ULONG count,
    NSSArena *arenaOpt,
    nssSession *session,
    NSSSlot *slot)
{
    nssArenaMark *mark = NULL;
    CK_SESSION_HANDLE hSession;
    CK_ULONG i = 0;
    CK_RV ckrv;
    PRStatus nssrv;
    PRBool alloced = PR_FALSE;
    void *epv = nssSlot_GetCryptokiEPV(slot);
    hSession = session->handle;
    if (arenaOpt) {
        mark = nssArena_Mark(arenaOpt);
        if (!mark) {
            goto loser;
        }
    }
    nssSession_EnterMonitor(session);
    /* XXX kinda hacky, if the storage size is already in the first template
     * item, then skip the alloc portion
     */
    if (obj_template[0].ulValueLen == 0) {
        /* Get the storage size needed for each attribute */
        ckrv = CKAPI(epv)->C_GetAttributeValue(hSession,
                                               object, obj_template, count);
        if (ckrv != CKR_OK &&
            ckrv != CKR_ATTRIBUTE_TYPE_INVALID &&
            ckrv != CKR_ATTRIBUTE_SENSITIVE) {
            nssSession_ExitMonitor(session);
            nss_SetError(NSS_ERROR_DEVICE_ERROR);
            goto loser;
        }
        /* Allocate memory for each attribute. */
        for (i = 0; i < count; i++) {
            CK_ULONG ulValueLen = obj_template[i].ulValueLen;
            if (ulValueLen == 0 || ulValueLen == (CK_ULONG)-1) {
                obj_template[i].pValue = NULL;
                obj_template[i].ulValueLen = 0;
                continue;
            }
            if (is_string_attribute(obj_template[i].type)) {
                ulValueLen++;
            }
            obj_template[i].pValue = nss_ZAlloc(arenaOpt, ulValueLen);
            if (!obj_template[i].pValue) {
                nssSession_ExitMonitor(session);
                goto loser;
            }
        }
        alloced = PR_TRUE;
    }
    /* Obtain the actual attribute values. */
    ckrv = CKAPI(epv)->C_GetAttributeValue(hSession,
                                           object, obj_template, count);
    nssSession_ExitMonitor(session);
    if (ckrv != CKR_OK &&
        ckrv != CKR_ATTRIBUTE_TYPE_INVALID &&
        ckrv != CKR_ATTRIBUTE_SENSITIVE) {
        nss_SetError(NSS_ERROR_DEVICE_ERROR);
        goto loser;
    }
    if (alloced && arenaOpt) {
        nssrv = nssArena_Unmark(arenaOpt, mark);
        if (nssrv != PR_SUCCESS) {
            goto loser;
        }
    }

    if (count > 1 && ((ckrv == CKR_ATTRIBUTE_TYPE_INVALID) ||
                      (ckrv == CKR_ATTRIBUTE_SENSITIVE))) {
        /* old tokens would keep the length of '0' and not deal with any
         * of the attributes we passed. For those tokens read them one at
         * a time */
        for (i = 0; i < count; i++) {
            if ((obj_template[i].ulValueLen == 0) ||
                (obj_template[i].ulValueLen == -1)) {
                obj_template[i].ulValueLen = 0;
                (void)nssCKObject_GetAttributes(object, &obj_template[i], 1,
                                                arenaOpt, session, slot);
            }
        }
    }
    return PR_SUCCESS;
loser:
    if (alloced) {
        if (arenaOpt) {
            /* release all arena memory allocated before the failure. */
            (void)nssArena_Release(arenaOpt, mark);
        } else {
            CK_ULONG j;
            /* free each heap object that was allocated before the failure. */
            for (j = 0; j < i; j++) {
                nss_ZFreeIf(obj_template[j].pValue);
            }
        }
    }
    return PR_FAILURE;
}
示例#11
0
NSS_IMPLEMENT PRBool
nssSlot_IsTokenPresent (
  NSSSlot *slot
)
{
    CK_RV ckrv;
    PRStatus nssrv;
    /* XXX */
    nssSession *session;
    CK_SLOT_INFO slotInfo;
    void *epv;
    /* permanent slots are always present unless they're disabled */
    if (nssSlot_IsPermanent(slot)) {
	return !PK11_IsDisabled(slot->pk11slot);
    }
    /* avoid repeated calls to check token status within set interval */
    if (within_token_delay_period(slot)) {
	return ((slot->ckFlags & CKF_TOKEN_PRESENT) != 0);
    }

    /* First obtain the slot info */
    epv = slot->epv;
    if (!epv) {
	return PR_FALSE;
    }
    nssSlot_EnterMonitor(slot);
    ckrv = CKAPI(epv)->C_GetSlotInfo(slot->slotID, &slotInfo);
    nssSlot_ExitMonitor(slot);
    if (ckrv != CKR_OK) {
	slot->token->base.name[0] = 0; /* XXX */
	return PR_FALSE;
    }
    slot->ckFlags = slotInfo.flags;
    /* check for the presence of the token */
    if ((slot->ckFlags & CKF_TOKEN_PRESENT) == 0) {
	if (!slot->token) {
	    /* token was never present */
	    return PR_FALSE;
	}
	session = nssToken_GetDefaultSession(slot->token);
	if (session) {
	    nssSession_EnterMonitor(session);
	    /* token is not present */
	    if (session->handle != CK_INVALID_SESSION) {
		/* session is valid, close and invalidate it */
		CKAPI(epv)->C_CloseSession(session->handle);
		session->handle = CK_INVALID_SESSION;
	    }
	    nssSession_ExitMonitor(session);
	}
	if (slot->token->base.name[0] != 0) {
	    /* notify the high-level cache that the token is removed */
	    slot->token->base.name[0] = 0; /* XXX */
	    nssToken_NotifyCertsNotVisible(slot->token);
	}
	slot->token->base.name[0] = 0; /* XXX */
	/* clear the token cache */
	nssToken_Remove(slot->token);
	return PR_FALSE;
    }
    /* token is present, use the session info to determine if the card
     * has been removed and reinserted.
     */
    session = nssToken_GetDefaultSession(slot->token);
    if (session) {
	PRBool isPresent = PR_FALSE;
	nssSession_EnterMonitor(session);
	if (session->handle != CK_INVALID_SESSION) {
	    CK_SESSION_INFO sessionInfo;
	    ckrv = CKAPI(epv)->C_GetSessionInfo(session->handle, &sessionInfo);
	    if (ckrv != CKR_OK) {
		/* session is screwy, close and invalidate it */
		CKAPI(epv)->C_CloseSession(session->handle);
		session->handle = CK_INVALID_SESSION;
	    }
	}
	isPresent = session->handle != CK_INVALID_SESSION;
	nssSession_ExitMonitor(session);
	/* token not removed, finished */
	if (isPresent)
	    return PR_TRUE;
    } 
    /* the token has been removed, and reinserted, or the slot contains
     * a token it doesn't recognize. invalidate all the old
     * information we had on this token, if we can't refresh, clear
     * the present flag */
    nssToken_NotifyCertsNotVisible(slot->token);
    nssToken_Remove(slot->token);
    /* token has been removed, need to refresh with new session */
    nssrv = nssSlot_Refresh(slot);
    if (nssrv != PR_SUCCESS) {
        slot->token->base.name[0] = 0; /* XXX */
        slot->ckFlags &= ~CKF_TOKEN_PRESENT;
        return PR_FALSE;
    }
    return PR_TRUE;
}