Ejemplo n.º 1
0
int p11_find_slot_object(P11_SLOT *pSlot, CK_ULONG type, CK_ULONG id,  P11_OBJECT **ppObject)
{
    int ret = CKR_OK;
    P11_OBJECT *pObject = NULL;
    unsigned int h = 0;
    CK_VOID_PTR  p = NULL;
    CK_ULONG     l = 0;

    *ppObject = NULL;

    for (h=1; h <= pSlot->nobjects; h++)
    {
        pObject = p11_get_slot_object(pSlot, h);
        if (pObject == NULL)
        {
            //no object found with specified attributes
            ret = -1;
            goto cleanup;
        }

        ret = p11_get_attribute_value(pObject->pAttr, pObject->count, CKA_ID, &p, &l);
        if ( (ret != 0) || ( l!= sizeof(CK_ULONG)) || (memcmp(p, &id, sizeof(CK_ULONG)) != 0) )
        {
            continue;
        }
        ret = p11_get_attribute_value(pObject->pAttr, pObject->count, CKA_CLASS, &p, &l);
        if ( (ret != 0) || ( l!= sizeof(CK_ULONG)) || (memcmp(p, &type, sizeof(CK_ULONG)) != 0) )
        {
            continue;
        }
        *ppObject = pObject;
        return (CKR_OK);
    }

cleanup:

    return (ret);
}
Ejemplo n.º 2
0
CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession,   /* the session's handle */
													CK_OBJECT_HANDLE  hObject,    /* the object's handle */
													CK_ATTRIBUTE_PTR  pTemplate,  /* specifies attributes, gets values */
													CK_ULONG          ulCount)    /* attributes in template */
{
	/*
	This function returns the values from the object.
	Object is cached so objects are read only once and remain valid until new session is setup with token.
	Objects are allready initialized (but not read) during connection with token.
	*/

	int status, ret = 0;
	P11_SESSION *pSession = NULL;
	P11_SLOT    *pSlot    = NULL;
	P11_OBJECT  *pObject  = NULL;
	unsigned int j = 0;
	void  *pValue    = NULL;
	CK_ULONG len = 0;
	log_trace(WHERE, "I: enter");

	if (p11_get_init() != BEIDP11_INITIALIZED)
	{
		log_trace(WHERE, "I: leave, CKR_CRYPTOKI_NOT_INITIALIZED");
		return (CKR_CRYPTOKI_NOT_INITIALIZED);
	}		

	ret = p11_lock();
	if (ret != CKR_OK)
		return ret;

	log_trace(WHERE, "S: C_GetAttributeValue(hObject=%d)",hObject);

	ret = p11_get_session(hSession, &pSession);
	if (ret)
	{
		log_trace(WHERE, "E: Invalid session handle (%d)", hSession);
		goto cleanup;
	}

	pSlot = p11_get_slot(pSession->hslot);
	if (pSlot == NULL)
	{
		log_trace(WHERE, "E: p11_get_slot(%d) returns null", pSession->hslot);
		ret = CKR_SLOT_ID_INVALID;
		goto cleanup;
	}

	pObject = p11_get_slot_object(pSlot, hObject);
	if (pObject == NULL)
	{
		log_trace(WHERE, "E: slot %d: object %d does not exist", pSession->hslot, hObject);
		ret = CKR_OBJECT_HANDLE_INVALID;
		goto cleanup;
	}

	//read object from token if not cached allready
	if (pObject->state != P11_CACHED)
	{
		ret = cal_read_object(pSession->hslot, pObject);
		if (ret != 0)
		{
			log_trace(WHERE, "E: p11_read_object() returned %d", ret);
			goto cleanup;
		}
	}

	/*   if (pSlot->login_type < 0) //CKU_SO=0; CKU_USER=1
	{
	if (p11_get_attribute_value(pObject->pAttr, pObject->count, CKA_PRIVATE, (CK_VOID_PTR *) &pbPrivate, &len) != CKR_OK)
	{
	log_trace(WHERE, "E: missing CKA_PRIVATE attribute in our object: bad implementation");
	continue;
	}

	if ( (len == sizeof(CK_BBOOL)) && (*pbPrivate == CK_TRUE) )
	{
	log_trace(WHERE, "E: Not allowed to retrieve private objects");
	continue;
	}
	}*/

	//retrieve all objects as listed in template and fill the template
	//action is done for all attributes, even if some attributes give errors or buffer is too small
	//there is however only one return code to return so we have to keep the most important return code.
	for (j = 0; j < ulCount; j++)
	{
		status = p11_get_attribute_value(pObject->pAttr, pObject->count, pTemplate[j].type, (CK_VOID_PTR *) &pValue, &len);
		if (status != CKR_OK)
		{
			log_template("E: C_GetAttributeValue status != CKR_OK", &pTemplate[j], 1);
			log_trace(WHERE, "E: p11_get_attribute_value (object=%d) returned %s", hObject, log_map_error(status));
			pTemplate[j].ulValueLen = (CK_ULONG) -1;
			ret = status;
			continue;
		}

		if (pTemplate[j].pValue == NULL)
		{
			/* in this case we return the real length of the value */
			pTemplate[j].ulValueLen = len;
			continue;
		}

		if (len > pTemplate[j].ulValueLen)
		{
			pTemplate[j].ulValueLen = (CK_ULONG) -1;
			ret = CKR_BUFFER_TOO_SMALL;
			continue;
		}

		pTemplate[j].ulValueLen = len;
		memcpy(pTemplate[j].pValue, pValue, len);
	}

	if (ulCount != 0)
		log_template("I: Template out:", pTemplate, ulCount);

cleanup:
	p11_unlock();
	return ret;
}
Ejemplo n.º 3
0
CK_RV C_FindObjects(CK_SESSION_HANDLE    hSession,          /* the session's handle */
										CK_OBJECT_HANDLE_PTR phObject,          /* receives object handle array */
										CK_ULONG             ulMaxObjectCount,  /* max handles to be returned */
										CK_ULONG_PTR         pulObjectCount)    /* actual number returned */
{
	/*

	this function finds handles to objects but does not actually reads them.
	this function returns handles to objects that exist on the token.
	PKCS15 defines existance of attributes that should be readable from token

	*/

	int ret = 0;
	P11_SESSION   *pSession = NULL;
	P11_SLOT      *pSlot = NULL;
	P11_FIND_DATA *pData = NULL;
	P11_OBJECT    *pObject = NULL;
	CK_BBOOL      *pbToken = NULL;
	void          *p = NULL;
	CK_ULONG      *pclass = NULL;
	int           match = 0;
	unsigned int           h,j = 0;

	CK_ULONG len = 0;

	log_trace(WHERE, "I: enter");

	if (p11_get_init() != BEIDP11_INITIALIZED)
	{
		log_trace(WHERE, "I: leave, CKR_CRYPTOKI_NOT_INITIALIZED");
		return (CKR_CRYPTOKI_NOT_INITIALIZED);
	}		

	ret = p11_lock();
	if (ret != CKR_OK)
		return ret;

	log_trace(WHERE, "S: C_FindObjects(session %d)", hSession);

	ret = p11_get_session(hSession, &pSession);
	if (pSession == NULL || ret != CKR_OK)
		// if (ret)
	{
		log_trace(WHERE, "E: Invalid session handle (%d)", hSession);
		goto cleanup;
	}

	if (pSession->Operation[P11_OPERATION_FIND].active == 0)
	{
		log_trace(WHERE, "E: For this session no search operation is initiated");
		ret = CKR_OPERATION_NOT_INITIALIZED;
		goto cleanup;
	}

	//get search template
	pData = (P11_FIND_DATA *) pSession->Operation[P11_OPERATION_FIND].pData;
	if (pData == NULL)
	{
		log_trace(WHERE, "E: Session (%d): search data not initialized correctly", hSession);
		ret = CKR_OPERATION_NOT_INITIALIZED;
		goto cleanup;
	}

	/* VSC this code was moved to here since Sun-PKCS11 cannot handle CKR_Attribute_value_invalid in C_FindObjectsInit() properly!!! */
	/* here we just return 0 objects in case of class type that is not supported */
	ret = p11_get_attribute_value(pData->pSearch, pData->size, CKA_CLASS, (CK_VOID_PTR *) &pclass, &len);
	if ( (ret == 0) && (len == sizeof(CK_ULONG) ) )
	{
		if ( (*pclass != CKO_CERTIFICATE) && (*pclass != CKO_PRIVATE_KEY) && (*pclass != CKO_PUBLIC_KEY) && (*pclass != CKO_DATA) )
		{
			ret = CKR_OK; //ret = CKR_ATTRIBUTE_VALUE_INVALID;
			*pulObjectCount = 0;
			goto cleanup;
		}
	}

	//check if we have a TOKEN attribute to look for
	//in case of null search template we search for all objects
	//Firefox does not set TOKEN object for CKO_PRIVATE_KEY objects so for the moment we allow looking for them, id has to match anyway.
	len = sizeof(CK_BBOOL);
	if (pData->size > 0)
	{
		ret = p11_get_attribute_value(pData->pSearch, pData->size, CKA_TOKEN, (CK_VOID_PTR *) &pbToken, &len);
		//if ((ret != CKR_OK) || ( (len == sizeof(CK_BBOOL) ) && (*pbToken == CK_FALSE) ) )
		//for the moment if CKA_TOKEN is specified and set to false, we reply that only token objects can be searched for and continue with ok
		if ((ret == CKR_OK) && (len == sizeof(CK_BBOOL)) && (*pbToken == CK_FALSE) ) 
		{
			log_trace(WHERE, "W: only token objects can be searched for");
			*pulObjectCount = 0;
			ret = CKR_OK;
			goto cleanup;
		}
	}

	pSlot = p11_get_slot(pSession->hslot);
	if (pSlot == NULL)
	{
		log_trace(WHERE, "E: p11_get_slot(%d) returns null", pSession->hslot);
		ret = CKR_SLOT_ID_INVALID;
		goto cleanup;
	}

	*pulObjectCount = 0;

	//for all objects in token, match with search template as long as we need, keep handle to current token object
	for (h = pData->hCurrent; h <= (pSlot->nobjects) && (*pulObjectCount < ulMaxObjectCount); h++, pData->hCurrent++)
	{
		pObject = p11_get_slot_object(pSlot, h);
		if (pObject == NULL)
		{
			log_trace(WHERE, "E: invalid object handle, call C_FindObjectsInit() first");
			ret = CKR_OPERATION_NOT_INITIALIZED;
			goto cleanup;
		}
		if (pObject->inuse == 0)
			continue; //this object is not in use by the token()

		//if not logged in, objects with missing CKA_PRIVATE or CKA_PRIVATE set to false will be ignored
#if 0 //TODO
		if (pSlot->login_type < 0) //CKU_SO=0; CKU_USER=1
		{
			if (p11_get_attribute_value(pObject->pAttr, pObject->count, CKA_PRIVATE, (CK_VOID_PTR *) &pbPrivate, &len) != CKR_OK)
			{
				log_trace(WHERE, "E: missing CKA_PRIVATE attribute in our object: bad implementation");
				continue;
			}

			if ( (len == sizeof(CK_BBOOL)) && (*pbPrivate == CK_TRUE) )
			{
				log_trace(WHERE, "E: Not allowed to retrieve private objects");
				continue;
			}
		}
#endif
		// Try to match every attribute
		match = 1;
		//if pData->size = 0 => this means that we will search for every object!!! match = 1 so for() is skipped and object is returned
		for (j = 0; j < pData->size; j++)
		{
			//get the value of the attribute from the token object and compare with the search attribute
			if (p11_get_attribute_value(pObject->pAttr, pObject->count, pData->pSearch[j].type, &p, &len) != CKR_OK)
			{
				match = 0;
				break;
			}

			// printf("pData->pSearch[%d].ulValueLen=%d <> len=%d\n",j,pData->pSearch[j].ulValueLen,len);

			if (pData->pSearch[j].ulValueLen != len)
			{
				match = 0;
				break;
			}

			if (memcmp(pData->pSearch[j].pValue, p, len) != 0)
			{
				match = 0;
				break;
			}
		}

		if (match)
		{
			log_trace(WHERE, "I: Slot %d: Object %d matches", pSession->hslot, h);
			//put handle to object in list
			phObject[*pulObjectCount] = (CK_OBJECT_HANDLE) h;
			*pulObjectCount +=1;
		}
		else
			log_trace(WHERE, "I: Slot %d: Object %d no match with search template", pSession->hslot, h);
	}

	ret = CKR_OK;

cleanup: 
	p11_unlock();
	return ret;
}
Ejemplo n.º 4
0
Archivo: sign.c Proyecto: Fedict/eid-mw
CK_RV C_SignInit(CK_SESSION_HANDLE hSession,    /* the session's handle */
                 CK_MECHANISM_PTR  pMechanism,  /* the signature mechanism */
                 CK_OBJECT_HANDLE  hKey)        /* handle of the signature key */
{
   CK_RV ret;
   P11_SESSION *pSession = NULL;
   P11_SLOT    *pSlot = NULL;
   P11_SIGN_DATA *pSignData = NULL;
   P11_OBJECT  *pObject = NULL;

   CK_BBOOL       *pcan_sign = NULL;
   CK_KEY_TYPE    *pkeytype = NULL;
   CK_ULONG       *pmodsize = NULL;
   CK_ULONG       *pid = NULL;
   CK_ULONG       *pclass = NULL;
   CK_ULONG len = 0;
   CK_MECHANISM_TYPE_PTR  pMechanismsSupported = NULL;
   CK_ULONG ulSupportedMechLen = 0;
   CK_ULONG ulcounter = 0;
   int ihash;

	if (p11_get_init() != BEIDP11_INITIALIZED)
	{
		log_trace(WHERE, "I: leave, CKR_CRYPTOKI_NOT_INITIALIZED");
		return (CKR_CRYPTOKI_NOT_INITIALIZED);
	}		

   p11_lock();

	 log_trace(WHERE, "I: enter");

   ret = p11_get_session(hSession, &pSession);
   if (ret)
      {
      log_trace(WHERE, "E: Invalid session handle (%d)", hSession);
      goto cleanup;
      }

   //is there an active sign operation for this session
   if (pSession->Operation[P11_OPERATION_SIGN].active)
      {
      log_trace(WHERE, "W: Session %d: sign operation allready exists", hSession);
      ret = CKR_OPERATION_ACTIVE;
      goto cleanup;
      }

   pSlot = p11_get_slot(pSession->hslot);
   if (pSlot == NULL)
      {
      log_trace(WHERE, "E: Slot not found for session %d", hSession);
      ret = CKR_SESSION_HANDLE_INVALID;
      goto cleanup;
      }

   if(!(pSlot->ulCardDataCached & CACHED_DATA_TYPE_CDF))
   {
	   log_trace(WHERE, "E: Key handle but no CDF read yet!");
	   ret = CKR_KEY_HANDLE_INVALID;
	   goto cleanup;
   }

#ifndef PKCS11_FF
   ret = cal_init_objects(pSlot);
   if(ret != CKR_OK)
   {
	   log_trace(WHERE, "E: cal_init_objects() returns %s_", log_map_error(ret));
   }
#endif

   //check mechanism
   //since this module is only for BEID, we check for RSA here and we do not check the device capabilities
   //check mechanism table for signing depending on token in slot

	 //get number of mechanisms
		ret = cal_get_mechanism_list(pSession->hslot, pMechanismsSupported, &ulSupportedMechLen);
		if (ret != CKR_OK)
   {
			log_trace(WHERE, "E: cal_get_mechanism_list(slotid=%d) returns %s", pSession->hslot, log_map_error(ret));
			goto cleanup;
   }

		//get the mechanisms list
		pMechanismsSupported = (CK_MECHANISM_TYPE_PTR) malloc (sizeof(CK_MECHANISM_TYPE)*ulSupportedMechLen);
		if(pMechanismsSupported != NULL)
		{
			ret = cal_get_mechanism_list(pSession->hslot, pMechanismsSupported, &ulSupportedMechLen);
			if (ret != CKR_OK)
			{
				log_trace(WHERE, "E: cal_get_mechanism_list(slotid=%d) returns %s", pSession->hslot, log_map_error(ret));
				free(pMechanismsSupported);
				goto cleanup;
			}

			ret = CKR_MECHANISM_INVALID;

			for(ulcounter = 0; ulcounter < ulSupportedMechLen ; ulcounter++)
			{
				if(pMechanismsSupported[ulcounter] == pMechanism->mechanism)
				{
					ret = CKR_OK;
					break;
				}
			}
			if(ret == CKR_MECHANISM_INVALID)
			{
				free(pMechanismsSupported);
				goto cleanup;  
			}
			free(pMechanismsSupported);
		}

   switch(pMechanism->mechanism)
      {
      case CKM_MD5_RSA_PKCS:
      case CKM_SHA1_RSA_PKCS:
      case CKM_RIPEMD160_RSA_PKCS:
      case CKM_SHA256_RSA_PKCS:
      case CKM_SHA384_RSA_PKCS:
      case CKM_SHA512_RSA_PKCS: 
      case CKM_SHA1_RSA_PKCS_PSS:
      case CKM_SHA256_RSA_PKCS_PSS:
      case CKM_ECDSA_SHA256:
      case CKM_ECDSA_SHA384:
      case CKM_ECDSA_SHA512:
      	ihash = 1; break;
      case CKM_RSA_PKCS:
      case CKM_ECDSA:
      	ihash = 0; break;
      default: 
         ret = CKR_MECHANISM_INVALID;
         goto cleanup;            
      }

   //can we use the object for signing?
   pObject = p11_get_slot_object(pSlot, hKey);
   if (pObject == NULL || pObject->count == 0)
      {
      log_trace(WHERE, "E: invalid key handle");
      ret = CKR_KEY_HANDLE_INVALID;
      goto cleanup;
      }

   //check class, keytype and sign attribute CKO_PRIV_KEY
   /* CKR_KEY_TYPE_INCONSISTENT has higher rank than CKR_KEY_FUNCTION_NOT_PERMITTED */
   ret = p11_get_attribute_value(pObject->pAttr, pObject->count, CKA_KEY_TYPE, (CK_VOID_PTR*) &pkeytype, &len);
   if (ret || (len != sizeof(CK_KEY_TYPE)) || (*pkeytype != CKK_RSA))
      {
      log_trace(WHERE, "E: Wrong keytype");
      ret = CKR_KEY_TYPE_INCONSISTENT;
      goto cleanup;
      }

   ret = p11_get_attribute_value(pObject->pAttr, pObject->count, CKA_CLASS, (CK_VOID_PTR*) &pclass, &len);
   if (ret || (len != sizeof(CK_ULONG)) || (*pclass != CKO_PRIVATE_KEY))
      {
      log_trace(WHERE, "E: Key is not CKO_PRIVATE_KEY");
      ret = CKR_KEY_FUNCTION_NOT_PERMITTED;
      goto cleanup;
      }

   ret = p11_get_attribute_value(pObject->pAttr, pObject->count, CKA_SIGN, (CK_VOID_PTR*) &pcan_sign, &len);
   if (ret || (len != sizeof(CK_BBOOL)) || (*pcan_sign != CK_TRUE))
      {
      log_trace(WHERE, "E: Key cannot be used for signing");
      ret = CKR_KEY_FUNCTION_NOT_PERMITTED;
      goto cleanup;
      }

   ret = p11_get_attribute_value(pObject->pAttr, pObject->count, CKA_MODULUS_BITS, (CK_VOID_PTR*) &pmodsize, &len);
   if (ret || (len != sizeof(CK_ULONG)) )
      {
      log_trace(WHERE, "E: Lengh not defined for modulus bits for private key");
      ret = CKR_FUNCTION_FAILED;
      goto cleanup;
      }

   /* get ID to identify signature key */
   /* at this time, id should be available, otherwise, device is not connected and objects are not initialized */
   ret = p11_get_attribute_value(pObject->pAttr, pObject->count, CKA_ID, (CK_VOID_PTR*) &pid, &len);
   if (ret || (len != sizeof(CK_ULONG)))
      {
      log_trace(WHERE, "E: ID missing for key");
      ret = CKR_FUNCTION_FAILED;
      goto cleanup;
      }

   /* init sign operation */
   if((pSignData = pSession->Operation[P11_OPERATION_SIGN].pData) == NULL)
      {
      pSignData = pSession->Operation[P11_OPERATION_SIGN].pData = (P11_SIGN_DATA *) malloc (sizeof(P11_SIGN_DATA));
      if (pSignData == NULL)
         {
         log_trace( WHERE, "E: error allocating memory");
         ret = CKR_HOST_MEMORY;
         goto cleanup;
         }
      }

   memset(pSignData, 0, sizeof(P11_SIGN_DATA));

   pSignData->mechanism = pMechanism->mechanism;
   pSignData->hKey = hKey;
   pSignData->l_sign = (*pmodsize+7)/8;
   pSignData->id = *pid;

   if (ihash)
      {
      ret = hash_init(pMechanism, &(pSignData->phash), &(pSignData->l_hash));
      if(ret)
         {
         log_trace(WHERE, "E: could not initialize hash()");
         ret = CKR_FUNCTION_FAILED;
         goto cleanup;
         }
      }
   pSession->Operation[P11_OPERATION_SIGN].active = 1;

cleanup:       
   p11_unlock();
	 log_trace(WHERE, "I: leave, ret = 0x%08x",ret);

return ret;
}
Ejemplo n.º 5
0
int p11_add_slot_object(P11_SLOT *pSlot, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_BBOOL bToken, CK_ULONG type, CK_ULONG id,  CK_BBOOL bPrivate, CK_ULONG *phObject)
{
    int ret = CKR_OK;
    P11_OBJECT *pObject = NULL;
//unsigned int hObject = 0;

    *phObject = 0;

    ret = p11_new_slot_object(pSlot, phObject);
    if ((ret != 0) || (*phObject == 0))
    {
        log_trace(WHERE, "E: could not add new slot object during init of objects");
        return(ret);
    }

    pObject = p11_get_slot_object(pSlot, *phObject);

//add room for attributes as in template
    pObject->pAttr = (CK_ATTRIBUTE_PTR) malloc(ulCount * sizeof(CK_ATTRIBUTE));
    if (pObject->pAttr == NULL)
    {
        log_trace(WHERE, "E: alloc error for attribute");
        return (CKR_HOST_MEMORY);
    }

//set the size of the object attributes
    pObject->count = ulCount;

//copy the template to the new object
    ret = p11_copy_object(pTemplate, ulCount, pObject->pAttr);
    if (ret)
    {
        log_trace(WHERE, "E: p11_copy_object() returned %d", ret);
        goto cleanup;
    }

//CKA_TOKEN
    ret = p11_set_attribute_value(pObject->pAttr, ulCount, CKA_TOKEN, (CK_VOID_PTR) &bToken, sizeof(CK_BBOOL));
    if (ret)
    {
        log_trace(WHERE, "E: p11_set_attribute_value(CKA_TOKEN) returned %d", ret);
        goto cleanup;
    }

//CKA_CLASS
    ret = p11_set_attribute_value(pObject->pAttr, ulCount, CKA_CLASS, (CK_VOID_PTR) &type, sizeof(CK_ULONG));
    if (ret)
    {
        log_trace(WHERE, "E: p11_set_attribute_value(CKA_CLASS) returned %d", ret);
        goto cleanup;
    }

//CKA_ID
    ret = p11_set_attribute_value(pObject->pAttr, ulCount, CKA_ID, (CK_VOID_PTR) &id, sizeof(CK_ULONG));
    if (ret)
    {
        log_trace(WHERE, "E: p11_set_attribute_value(CKA_ID) returned %d", ret);
        goto cleanup;
    }

//CKA_PRIVATE
    ret = p11_set_attribute_value(pObject->pAttr, ulCount, CKA_PRIVATE, (CK_VOID_PTR) &bPrivate, sizeof(CK_BBOOL));
    if (ret)
    {
        log_trace(WHERE, "E: p11_set_attribute_value(CKA_PRIVATE) returned %d", ret);
        goto cleanup;
    }

cleanup:

    return (ret);
}
Ejemplo n.º 6
0
CK_RV p11_add_slot_ID_object(P11_SLOT *pSlot, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_BBOOL bToken,
						   CK_ULONG type, CK_BBOOL bPrivate, CK_ULONG *phObject,
						   CK_VOID_PTR plabel, CK_ULONG labelLen, CK_VOID_PTR pvalue, CK_ULONG valueLen, CK_VOID_PTR pobjectID, CK_ULONG objectIDLen)
{
CK_RV ret = CKR_OK;
P11_OBJECT *pObject = NULL;
//unsigned int hObject = 0;

*phObject = 0;

ret = p11_new_slot_object(pSlot, phObject);
if ((ret != CKR_OK) || (*phObject == 0))
   {
   log_trace(WHERE, "E: could not add new slot object during init of objects");
   return(ret);
   }

pObject = p11_get_slot_object(pSlot, *phObject);

//add room for attributes as in template
pObject->pAttr = (CK_ATTRIBUTE_PTR) malloc(ulCount * sizeof(CK_ATTRIBUTE));
if (pObject->pAttr == NULL)
   {
   log_trace(WHERE, "E: alloc error for attribute");
   return (CKR_HOST_MEMORY);
   }
memset(pObject->pAttr, 0, ulCount * sizeof(CK_ATTRIBUTE));

//set the size of the object attributes
pObject->count = ulCount;

//copy the template to the new object
ret = p11_copy_object(pTemplate, ulCount, pObject->pAttr);
if (ret)
   {
   log_trace(WHERE, "E: p11_copy_object() returned %d", ret);
   goto cleanup;
   }

//CKA_TOKEN
ret = p11_set_attribute_value(pObject->pAttr, ulCount, CKA_TOKEN, (CK_VOID_PTR) &bToken, sizeof(CK_BBOOL));
if (ret)
   {
   log_trace(WHERE, "E: p11_set_attribute_value(CKA_TOKEN) returned %d", ret);
   goto cleanup;
   }

//CKA_CLASS
ret = p11_set_attribute_value(pObject->pAttr, ulCount, CKA_CLASS, (CK_VOID_PTR) &type, sizeof(CK_ULONG));
if (ret)
   {
   log_trace(WHERE, "E: p11_set_attribute_value(CKA_CLASS) returned %d", ret);
   goto cleanup;
   }
 
//CKA_PRIVATE
ret = p11_set_attribute_value(pObject->pAttr, ulCount, CKA_PRIVATE, (CK_VOID_PTR) &bPrivate, sizeof(CK_BBOOL));
if (ret)
   {
   log_trace(WHERE, "E: p11_set_attribute_value(CKA_PRIVATE) returned %d", ret);
   goto cleanup;
   }

//CKA_LABEL
ret = p11_set_attribute_value(pObject->pAttr, pObject->count, CKA_LABEL, plabel, labelLen);
if (ret)
   {
   log_trace(WHERE, "E: p11_set_attribute_value(CKA_LABEL) returned %d", ret);
   goto cleanup;
   }

//CKA_VALUE
ret = p11_set_attribute_value(pObject->pAttr, pObject->count, CKA_VALUE, pvalue, valueLen);
if (ret)
   {
   log_trace(WHERE, "E: p11_set_attribute_value(CKA_VALUE) returned %d", ret);
   goto cleanup;
   }

//CKA_VALUE_LEN
ret = p11_set_attribute_value(pObject->pAttr, pObject->count, CKA_VALUE_LEN, &valueLen, sizeof(CK_ULONG));
if (ret)
   {
   log_trace(WHERE, "E: p11_set_attribute_value(CKA_VALUE_LEN) returned %d", ret);
   goto cleanup;
   }

//CKA_OBJECT_ID
ret = p11_set_attribute_value(pObject->pAttr, pObject->count, CKA_OBJECT_ID, pobjectID, objectIDLen);
if (ret)
   {
   log_trace(WHERE, "E: p11_set_attribute_value(CKA_OBJECT_ID) returned %d", ret);
   goto cleanup;
   }

pObject->state=P11_CACHED;

cleanup:

return (ret);
}