コード例 #1
0
ファイル: miscfunc.c プロジェクト: cmjonze/rpm5_tarballs
uint32_t TPM_GetCapabilityOwner(unsigned char *ownpass,
				uint32_t * volflags, uint32_t * nvolflags)
{
    uint32_t ret;
    STACK_TPM_BUFFER(tpmdata)
	/* data to be inserted into Request Buffer (in Network Byte Order) */
	/* the uint32_t and uint16_t values are stored in network byte order so they
	 ** are in the correct format when being hashed by the HMAC calculation */
    uint32_t command;		/* command ordinal */
    unsigned char nonceodd[TPM_HASH_SIZE];	/* odd nonce */
    unsigned char authdata[TPM_HASH_SIZE];	/* auth data */
    session sess;

    /* check that parameters are valid */
    if (ownpass == NULL || volflags == NULL || nvolflags == NULL)
	return ERR_NULL_ARG;

    /* set up command and protocol values for TakeOwnership function */
    command = htonl(TPM_ORD_GetCapabilityOwner);
    /* generate the odd nonce */
    ret = TSS_gennonce(nonceodd);
    if (ret == 0)
	return ret;

    /* initiate the OSAP protocol */
    ret = TSS_SessionOpen(SESSION_OSAP, &sess, ownpass, TPM_OWNER_ETYPE,
			TPM_OWNER_EVALUE);
    if (ret)
	return ret;

    /* calculate the Authorization Data */
    ret = TSS_authhmac(authdata, TSS_Session_GetAuth(&sess), TPM_HASH_SIZE,
		     TSS_Session_GetENonce(&sess), nonceodd, 0,
		     TPM_U32_SIZE, &command, 0, 0);
    if (ret) {
	TSS_SessionClose(&sess);
	return ret;
    }
    /* insert all the calculated fields into the request buffer */
    ret = TSS_buildbuff("00 c2 T l L % 00 %", &tpmdata,
			command,
			TSS_Session_GetHandle(&sess),
			TPM_HASH_SIZE, nonceodd, TPM_HASH_SIZE, authdata);
    if (ret & ERR_MASK) {
	TSS_SessionClose(&sess);
	return ret;
    }

    /* transmit the request buffer to the TPM device and read the reply */
    ret = TPM_Transmit(&tpmdata, "GetCapabilityOwner");
    TSS_SessionClose(&sess);
    if (ret)
	return ret;

    ret = TSS_checkhmac1(&tpmdata, command, nonceodd,
		       TSS_Session_GetAuth(&sess), TPM_HASH_SIZE,
		       TPM_U32_SIZE, TPM_DATA_OFFSET, TPM_U32_SIZE,
		       TPM_DATA_OFFSET + TPM_U32_SIZE, TPM_U32_SIZE,
		       TPM_DATA_OFFSET + TPM_U32_SIZE + TPM_U32_SIZE, 0,
		       0);
    if (ret)
	return ret;

    ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET + 4, nvolflags);
    if (ret & ERR_MASK)
	return ret;

    ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET + 4 + TPM_U32_SIZE,
			  volflags);
    if (ret & ERR_MASK)
	return ret;

    return 0;
}
コード例 #2
0
ファイル: miscfunc.c プロジェクト: cmjonze/rpm5_tarballs
uint32_t TPM_GetCapabilitySigned(uint32_t keyhandle,
				 unsigned char *keypass,
				 unsigned char *antiReplay,
				 uint32_t caparea,
				 struct tpm_buffer * scap,
				 struct tpm_buffer * resp,
				 unsigned char *sig, uint32_t * siglen)
{
    uint32_t ret;
    uint32_t rlen;
    STACK_TPM_BUFFER(tpmdata)	/* request/response buffer */
    uint32_t ordinal_no = htonl(TPM_ORD_GetCapabilitySigned);
    uint32_t keyhandle_no = htonl(keyhandle);
    uint32_t caparea_no = htonl(caparea);
    unsigned char c = 0;
    unsigned char authdata[TPM_HASH_SIZE];
    uint32_t ssize;
    unsigned char *buffer = NULL;
    uint32_t subcaplen = 0;
    uint32_t subcaplen_no;

    /* check arguments */
    if (scap) {
	subcaplen = scap->used;
	buffer = scap->buffer;
    }
    subcaplen_no = htonl(subcaplen);

    ret = needKeysRoom(keyhandle, 0, 0, 0);
    if (ret)
	return ret;

    if (resp == NULL)
	return ERR_NULL_ARG;

    if (keypass) {
	unsigned char nonceodd[TPM_HASH_SIZE];
	session sess;

	ret = TSS_gennonce(nonceodd);
	if (ret == 0)
	    return ERR_CRYPT_ERR;

	ret = TSS_SessionOpen(SESSION_OSAP | SESSION_OIAP,
			      &sess, keypass, TPM_ET_KEYHANDLE, keyhandle);
	if (ret)
	    return ret;

	/* move Network byte order data to variable for hmac calculation */
	ret = TSS_authhmac(authdata, TSS_Session_GetAuth(&sess),
			 TPM_HASH_SIZE, TSS_Session_GetENonce(&sess),
			 nonceodd, c, TPM_U32_SIZE, &ordinal_no,
			 TPM_NONCE_SIZE, antiReplay, TPM_U32_SIZE,
			 &caparea_no, TPM_U32_SIZE, &subcaplen_no,
			 subcaplen, buffer, 0, 0);
	if (ret) {
	    TSS_SessionClose(&sess);
	    return ret;
	}

	ret = TSS_buildbuff("00 c2 T l l % l @ L % o %", &tpmdata,
			    ordinal_no,
			    keyhandle_no,
			    TPM_NONCE_SIZE, antiReplay,
			    caparea_no,
			    subcaplen, buffer,
			    TSS_Session_GetHandle(&sess),
			    TPM_NONCE_SIZE, nonceodd,
			    c, TPM_HASH_SIZE, authdata);
	if (ret & ERR_MASK) {
	    TSS_SessionClose(&sess);
	    return ret;
	}

	/* transmit the request buffer to the TPM device and read the reply */
	ret = TPM_Transmit(&tpmdata, "GetCapability - AUTH1");
	TSS_SessionClose(&sess);
	if (ret)
	    return ret;

	ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET+TPM_U32_SIZE, &rlen);
	if (ret & ERR_MASK)
	    return ret;

	ret = tpm_buffer_load32(&tpmdata,
			      TPM_DATA_OFFSET + TPM_U32_SIZE +
			      TPM_U32_SIZE + rlen, &ssize);
	if (ret & ERR_MASK)
	    return ret;

	ret = TSS_checkhmac1(&tpmdata, ordinal_no, nonceodd,
			   TSS_Session_GetAuth(&sess), TPM_HASH_SIZE,
			   TPM_U32_SIZE + TPM_U32_SIZE + rlen +
			   TPM_U32_SIZE + ssize, TPM_DATA_OFFSET, 0, 0);
	if (ret)
	    return ret;
    } else {
	ret = TSS_buildbuff("00 c1 T l l % l @", &tpmdata,
			    ordinal_no,
			    keyhandle_no,
			    TPM_NONCE_SIZE, antiReplay,
			    caparea_no, subcaplen, buffer);
	if (ret & ERR_MASK)
	    return ret;

	/* transmit the request buffer to the TPM device and read the reply */
	ret = TPM_Transmit(&tpmdata, "GetCapability - NO AUTH");
	if (ret)
	    return ret;

	ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET+TPM_U32_SIZE, &rlen);
	if (ret & ERR_MASK)
	    return ret;

	ret = tpm_buffer_load32(&tpmdata,
			      TPM_DATA_OFFSET + TPM_U32_SIZE +
			      TPM_U32_SIZE + rlen, &ssize);
	if (ret & ERR_MASK)
	    return ret;
    }
    if (resp)
	SET_TPM_BUFFER(resp,
		       &tpmdata.buffer[TPM_DATA_OFFSET + TPM_U32_SIZE +
				       TPM_U32_SIZE], rlen);

    if (sig) {
	*siglen = MIN(*siglen, ssize);
	memcpy(sig,
	       &tpmdata.buffer[TPM_DATA_OFFSET + TPM_U32_SIZE +
			       TPM_U32_SIZE + rlen + TPM_U32_SIZE],
	       *siglen);
    }

    return ret;
}
コード例 #3
0
ファイル: dir.c プロジェクト: Jnig/tpm-luks
uint32_t TPM_DirWriteAuth(uint32_t dirIndex,
                          unsigned char * newValue,
                          unsigned char * ownerAuth)
{
	STACK_TPM_BUFFER(tpmdata)
	uint32_t ordinal_no = htonl(TPM_ORD_DirWriteAuth);
	uint32_t ret;
	uint32_t dirIndex_no = htonl(dirIndex);

	unsigned char nonceodd[TPM_NONCE_SIZE];
	unsigned char authdata[TPM_NONCE_SIZE];
	session sess;
	int c = 0;
	
	/* check input arguments */
	if (NULL == ownerAuth ||
	    NULL == newValue) {
		return ERR_NULL_ARG;
	}
	

	/* Open OSAP Session */
	ret = TSS_SessionOpen(SESSION_DSAP | SESSION_OSAP | SESSION_OIAP,
	                      &sess,
	                      ownerAuth, TPM_ET_OWNER, 0);

	if (ret != 0) 
		return ret;

	/* generate odd nonce */
	ret  = TSS_gennonce(nonceodd);
	if (0 == ret) 
		return ERR_CRYPT_ERR;

	/* move Network byte order data to varaible for hmac calcualtion */
	ret = TSS_authhmac(authdata,TSS_Session_GetAuth(&sess),TPM_HASH_SIZE,TSS_Session_GetENonce(&sess),nonceodd,c,
	                   TPM_U32_SIZE,&ordinal_no,
	                   TPM_U32_SIZE,&dirIndex_no,
	                   TPM_HASH_SIZE, newValue,
	                   0,0);

	if (0 != ret) {
		TSS_SessionClose(&sess);
		return ret;
	}
	/* build the request buffer */
	ret = TSS_buildbuff("00 c2 T l l % L % o %", &tpmdata,
	                             ordinal_no,
	                               dirIndex_no,
	                                 TPM_HASH_SIZE, newValue,
	                                   TSS_Session_GetHandle(&sess),
	                                     TPM_HASH_SIZE, nonceodd,
	                                       c,
	                                         TPM_HASH_SIZE, authdata);
		

	if ((ret & ERR_MASK)) {
		TSS_SessionClose(&sess);
		return ret;
	}

	/* transmit the request buffer to the TPM device and read the reply */
	ret = TPM_Transmit(&tpmdata,"DirWriteAuth");
	TSS_SessionClose(&sess);

	if (ret != 0) {
		return ret;
	}
	/* check the HMAC in the response */

	ret = TSS_checkhmac1(&tpmdata,ordinal_no,nonceodd,TSS_Session_GetAuth(&sess),TPM_HASH_SIZE,
	                     0,0);

	return ret;
}
コード例 #4
0
ファイル: pcrs.c プロジェクト: osresearch/tpmtotp
uint32_t TPM_Quote2(uint32_t keyhandle,
                    TPM_PCR_SELECTION * selection,
                    TPM_BOOL addVersion,
                    unsigned char *keyauth,
                    unsigned char *antiReplay,
                    TPM_PCR_INFO_SHORT * pcrinfo,
                    struct tpm_buffer *versionblob,
                    struct tpm_buffer *signature)
{
	uint32_t ret;
	uint32_t rc;
	STACK_TPM_BUFFER( tpmdata )
	session sess;
	unsigned char pubauth[TPM_HASH_SIZE];
	unsigned char nonceodd[TPM_NONCE_SIZE];
	unsigned char c = 0;
	uint32_t ordinal_no = htonl(TPM_ORD_Quote2);
	uint16_t pcrselsize;
	uint32_t verinfosize;
	uint32_t sigsize;
	uint32_t storedsize;
	uint32_t keyhndl = htonl(keyhandle);
	uint16_t keytype;
	struct tpm_buffer * serPCRSelection;
	uint32_t serPCRSelectionSize;

	/* check input arguments */
	if (pcrinfo   == NULL ||
	    selection == NULL ||
	    antiReplay == NULL) return ERR_NULL_ARG;
	keytype = 0x0001;

	ret = needKeysRoom(keyhandle, 0, 0, 0);
	if (ret != 0) {
		return ret;
	}

	TSS_gennonce(antiReplay);

	serPCRSelection = TSS_AllocTPMBuffer(TPM_U16_SIZE +
	                                     selection->sizeOfSelect);
	if (NULL == serPCRSelection) {
		return ERR_MEM_ERR;
	}

	ret = TPM_WritePCRSelection(serPCRSelection, selection);
	if (( ret & ERR_MASK) != 0) {
		TSS_FreeTPMBuffer(serPCRSelection);
		return ret;
	}
	serPCRSelectionSize = ret;

	if (keyauth != NULL) {
		/* Open OSAP Session */
		ret = TSS_SessionOpen(SESSION_OSAP|SESSION_DSAP,&sess,keyauth,keytype,keyhandle);
		if (ret != 0)  {
			TSS_FreeTPMBuffer(serPCRSelection);
			return ret;
		}
		/* generate odd nonce */
		TSS_gennonce(nonceodd);
		/* move Network byte order data to variables for hmac calculation */

		/* calculate authorization HMAC value */
		ret = TSS_authhmac(pubauth,TSS_Session_GetAuth(&sess),TPM_HASH_SIZE,TSS_Session_GetENonce(&sess),nonceodd,c,
		                   TPM_U32_SIZE,&ordinal_no,
		                   TPM_HASH_SIZE,antiReplay,
		                   serPCRSelectionSize, serPCRSelection->buffer,
		                   sizeof(TPM_BOOL), &addVersion,
		                   0,0);
		if (ret != 0) {
			TSS_FreeTPMBuffer(serPCRSelection);
			TSS_SessionClose(&sess);
			return ret;
		}
		/* build the request buffer */
		ret = TSS_buildbuff("00 C2 T l l % % o L % o %",&tpmdata,
		                             ordinal_no,
		                               keyhndl,
		                                 TPM_HASH_SIZE,antiReplay,
		                                   serPCRSelectionSize,serPCRSelection->buffer,
		                                     addVersion,
		                                       TSS_Session_GetHandle(&sess),
		                                         TPM_NONCE_SIZE,nonceodd,
		                                           c,
		                                             TPM_HASH_SIZE,pubauth);
		TSS_FreeTPMBuffer(serPCRSelection);
		if ((ret & ERR_MASK) != 0) {
			TSS_SessionClose(&sess);
			return ret;
		}
		/* transmit the request buffer to the TPM device and read the reply */
		ret = TPM_Transmit(&tpmdata,"Quote2 - AUTH1");
		TSS_SessionClose(&sess);
		if (ret != 0) {
			return ret;
		}
	} else {
		/* build the request buffer */
		ret = TSS_buildbuff("00 C1 T l l % % o",&tpmdata,
		                             ordinal_no,
		                               keyhndl,
		                                 TPM_HASH_SIZE,antiReplay,
		                                   serPCRSelectionSize,serPCRSelection->buffer,
		                                     addVersion);
		TSS_FreeTPMBuffer(serPCRSelection);
		if ((ret & ERR_MASK) != 0) {
			TSS_SessionClose(&sess);
			return ret;
		}

		/* transmit the request buffer to the TPM device and read the reply */
		ret = TPM_Transmit(&tpmdata,"Quote2");
		TSS_SessionClose(&sess);
		if (ret != 0) {
			return ret;
		}
	}
	/* calculate the size of the returned Blob */
        ret =  tpm_buffer_load16(&tpmdata,TPM_DATA_OFFSET, &pcrselsize);
        if ((ret & ERR_MASK)) {
        	return ret;
        }
        pcrselsize += TPM_U16_SIZE + 1 + TPM_HASH_SIZE;
	ret =  tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET + pcrselsize, &verinfosize);
	if ((ret & ERR_MASK)) {
		return ret;
	}
	ret  =  tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET + pcrselsize + TPM_U32_SIZE + verinfosize, &sigsize);
	if ((ret & ERR_MASK)) {
		return ret;
	}
	
	storedsize   = pcrselsize + TPM_U32_SIZE + verinfosize +
	                            TPM_U32_SIZE + sigsize;

	if (keyauth != NULL) {
		/* check the HMAC in the response */
		ret = TSS_checkhmac1(&tpmdata,ordinal_no,nonceodd,TSS_Session_GetAuth(&sess),TPM_HASH_SIZE,
		                     storedsize,TPM_DATA_OFFSET,
		                     0,0);
		if (ret != 0) {
			return ret;
		}
	}
	/* copy the returned PCR composite to caller */
	
	if (pcrselsize != (rc = 
	     TPM_ReadPCRInfoShort(&tpmdata, TPM_DATA_OFFSET,
	                          pcrinfo))) {
		if ((rc & ERR_MASK)) 
			return rc;
		return ERR_BUFFER;
	}
	
	if (NULL != versionblob) {
		SET_TPM_BUFFER(
		       versionblob,
		       &tpmdata.buffer[TPM_DATA_OFFSET+pcrselsize+TPM_U32_SIZE],
		       verinfosize);
	}
	
	if (NULL != signature) {
		SET_TPM_BUFFER(signature,
		       &tpmdata.buffer[TPM_DATA_OFFSET+pcrselsize+TPM_U32_SIZE+verinfosize+TPM_U32_SIZE],
		       sigsize);
	}

	return ret;
}
コード例 #5
0
ファイル: pcrs.c プロジェクト: osresearch/tpmtotp
uint32_t TPM_Quote(uint32_t keyhandle,
                   unsigned char *keyauth,
                   unsigned char *externalData,
                   TPM_PCR_SELECTION *tps,
                   TPM_PCR_COMPOSITE *tpc,
                   struct tpm_buffer *signature)
{
	uint32_t ret;
	STACK_TPM_BUFFER( tpmdata )
	session sess;
	unsigned char pubauth[TPM_HASH_SIZE];
	unsigned char nonceodd[TPM_NONCE_SIZE];
	unsigned char c;
	uint32_t ordinal = htonl(TPM_ORD_Quote);
	uint32_t keyhndl = htonl(keyhandle);
	uint16_t pcrselsize;
	uint32_t valuesize;
	uint32_t sigsize;
	uint32_t offset;
	STACK_TPM_BUFFER( serPcrSel );

	/* check input arguments */
	if (tpc == NULL || externalData == NULL || signature == NULL) return ERR_NULL_ARG;

	ret = needKeysRoom(keyhandle, 0, 0, 0);
	if (ret != 0) {
		return ret;
	}

	ret = TPM_WritePCRSelection(&serPcrSel, tps);

	if ((ret & ERR_MASK))
		return ret;

	if (keyauth != NULL)  /* authdata required */ {
		/* Open OSAP Session */
		ret = TSS_SessionOpen(SESSION_OSAP|SESSION_DSAP,&sess,
		                      keyauth,TPM_ET_KEYHANDLE,keyhandle);
		if (ret != 0) return ret;
		/* generate odd nonce */
		TSS_gennonce(nonceodd);
		/* move Network byte order data to variables for hmac calculation */
		c = 0;
		/* calculate authorization HMAC value */
		ret = TSS_authhmac(pubauth,TSS_Session_GetAuth(&sess),TPM_HASH_SIZE,TSS_Session_GetENonce(&sess),nonceodd,c,
		                   TPM_U32_SIZE,&ordinal,
		                   TPM_HASH_SIZE,externalData,
		                   serPcrSel.used,serPcrSel.buffer,
		                   0,0);
		if (ret != 0) {
			TSS_SessionClose(&sess);
			return ret;
		}
		/* build the request buffer */
		ret = TSS_buildbuff("00 C2 T l l % % L % o %",&tpmdata,
		                             ordinal,
		                               keyhndl,
		                                 TPM_HASH_SIZE,externalData,
		                                   serPcrSel.used, serPcrSel.buffer,
		                                     TSS_Session_GetHandle(&sess),
		                                       TPM_NONCE_SIZE,nonceodd,
		                                         c,
		                                          TPM_HASH_SIZE,pubauth);
		if ((ret & ERR_MASK) != 0) {
			TSS_SessionClose(&sess);
			return ret;
		}
		/* transmit the request buffer to the TPM device and read the reply */
		ret = TPM_Transmit(&tpmdata,"Quote");
		TSS_SessionClose(&sess);
		if (ret != 0) {
			return ret;
		}
		
		offset = TPM_DATA_OFFSET;
		/* calculate the size of the returned Blob */
		ret  =  tpm_buffer_load16(&tpmdata,offset,&pcrselsize);
		if ((ret & ERR_MASK)) {
			return ret;
		}
		offset += TPM_U16_SIZE + pcrselsize;
		
		ret =  tpm_buffer_load32(&tpmdata,offset,&valuesize);
		if ((ret & ERR_MASK)) {
			return ret;
		}
		offset += TPM_U32_SIZE + valuesize;
		ret =  tpm_buffer_load32(&tpmdata,offset, &sigsize);
		if ((ret & ERR_MASK)) {
			return ret;
		}
		offset += TPM_U32_SIZE;

		/* check the HMAC in the response */
		ret = TSS_checkhmac1(&tpmdata,ordinal,nonceodd,TSS_Session_GetAuth(&sess),TPM_HASH_SIZE,
		                     offset-TPM_DATA_OFFSET+sigsize,TPM_DATA_OFFSET,
		                     0,0);
		if (ret != 0) {
			return ret;
		}
		ret = TPM_ReadPCRComposite(&tpmdata,
		                           TPM_DATA_OFFSET,
		                           tpc);
		if ((ret & ERR_MASK)) {
			return ret;
		}
		/* copy the returned blob to caller */
		SET_TPM_BUFFER(signature,
		               &tpmdata.buffer[offset],
		               sigsize);
	} else  /* no authdata required */ {
		/* build the request buffer */
		ret = TSS_buildbuff("00 C1 T l l % %",&tpmdata,
		                             ordinal,
		                               keyhndl,
		                                 TPM_HASH_SIZE,externalData,
		                                   serPcrSel.used,serPcrSel.buffer);
		if ((ret & ERR_MASK) != 0) return ret;
		/* transmit the request buffer to the TPM device and read the reply */
		ret = TPM_Transmit(&tpmdata,"Quote");
		if (ret != 0) return ret;
		/* calculate the size of the returned Blob */
		offset = TPM_DATA_OFFSET;
		ret =  tpm_buffer_load16(&tpmdata,offset, &pcrselsize);
		if ((ret & ERR_MASK)) {
			return ret;
		}
		offset += TPM_U16_SIZE + pcrselsize;
		ret  =  tpm_buffer_load32(&tpmdata,offset, &valuesize);
		if ((ret & ERR_MASK)) {
			return ret;
		}
		offset += TPM_U32_SIZE + valuesize;

		ret =  tpm_buffer_load32(&tpmdata,offset, &sigsize);
		if ((ret & ERR_MASK)) {
			return ret;
		}
		offset += TPM_U32_SIZE;
		
		/* copy the returned PCR composite to caller */
		ret = TPM_ReadPCRComposite(&tpmdata,
		                           TPM_DATA_OFFSET,
		                           tpc);
		if ((ret & ERR_MASK)) {
			return ret;
		}
		/* copy the returned blob to caller */
		SET_TPM_BUFFER(signature,
		               &tpmdata.buffer[offset],
		               sigsize);
	}
	return 0;
}
コード例 #6
0
ファイル: bind.c プロジェクト: cmjonze/rpm5_tarballs
uint32_t TPM_UnBind(uint32_t keyhandle,
		    unsigned char *keyauth,
		    unsigned char *data, uint32_t datalen,
		    unsigned char *blob, uint32_t * bloblen)
{
    uint32_t ret = 0;
    STACK_TPM_BUFFER(tpmdata)
    session sess;
    unsigned char pubauth[TPM_HASH_SIZE];
    unsigned char nonceodd[TPM_NONCE_SIZE];
    unsigned char c = 0;
    uint32_t ordinal = htonl(TPM_ORD_UnBind);
    uint32_t datsize = htonl(datalen);
    uint32_t keyhndl = htonl(keyhandle);
    uint16_t keytype;
    uint32_t infosize;

    /* check input arguments */
    if (data == NULL || blob == NULL)
	return ERR_NULL_ARG;
    if (keyhandle == 0x40000000)
	keytype = TPM_ET_SRK;
    else
	keytype = TPM_ET_KEYHANDLE;

    ret = needKeysRoom(keyhandle, 0, 0, 0);
    if (ret)
	return ret;

    if (keyauth != NULL) {	/* key needs authorization */
	/* Open OSAP Session */
	ret = TSS_SessionOpen(SESSION_OSAP | SESSION_DSAP, &sess, keyauth,
			    keytype, keyhandle);
	if (ret)
	    return ret;

	/* generate odd nonce */
	TSS_gennonce(nonceodd);
	/* move Network byte order data to variables for HMAC calculation */
	/* calculate authorization HMAC value */
	ret = TSS_authhmac(pubauth, TSS_Session_GetAuth(&sess),
			 TPM_HASH_SIZE, TSS_Session_GetENonce(&sess),
			 nonceodd, c, TPM_U32_SIZE, &ordinal, TPM_U32_SIZE,
			 &datsize, datalen, data, 0, 0);
	if (ret) {
	    TSS_SessionClose(&sess);
	    return ret;
	}
	/* build the request buffer */
	ret = TSS_buildbuff("00 C2 T l l @ L % o %", &tpmdata,
			    ordinal,
			    keyhndl,
			    datalen, data,
			    TSS_Session_GetHandle(&sess),
			    TPM_NONCE_SIZE, nonceodd,
			    c, TPM_HASH_SIZE, pubauth);
	if (ret & ERR_MASK) {
	    TSS_SessionClose(&sess);
	    return ret;
	}
	/* transmit the request buffer to the TPM device and read the reply */
	ret = TPM_Transmit(&tpmdata, "UnBind");
	TSS_SessionClose(&sess);
	if (ret)
	    return ret;

	/* calculate the size of the returned Blob */
	ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET, &infosize);
	if (ret & ERR_MASK)
	    return ret;
	/* check the HMAC in the response */
	ret = TSS_checkhmac1(&tpmdata, ordinal, nonceodd,
			   TSS_Session_GetAuth(&sess), TPM_HASH_SIZE,
			   TPM_U32_SIZE, TPM_DATA_OFFSET, infosize,
			   TPM_DATA_OFFSET + TPM_U32_SIZE, 0, 0);
	if (ret)
	    return ret;

	/* copy the returned blob to caller */
	memcpy(blob,
	       &tpmdata.buffer[TPM_DATA_OFFSET + TPM_U32_SIZE], infosize);
	*bloblen = infosize;
    } else {			/* key needs NO authorization */
	/* move Network byte order data to variables for HMAC calculation */

	/* build the request buffer */
	ret = TSS_buildbuff("00 C1 T l l @", &tpmdata,
			    ordinal, keyhndl, datalen, data);
	if (ret & ERR_MASK)
	    return ret;

	/* transmit the request buffer to the TPM device and read the reply */
	ret = TPM_Transmit(&tpmdata, "UnBind");
	if (ret)
	    return ret;

	/* calculate the size of the returned Blob */
	ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET, &infosize);
	if (ret & ERR_MASK)
	    return ret;

	/* copy the returned blob to caller */
	memcpy(blob, &tpmdata.buffer[TPM_DATA_OFFSET + TPM_U32_SIZE], infosize);
	*bloblen = infosize;
    }
    return ret;
}