Example #1
0
int load_tpm_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata,
		 gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig)
{
	static const TSS_UUID SRK_UUID = TSS_UUID_SRK;
	gnutls_datum_t asn1;
	unsigned int tss_len;
	char *pass;
	int ofs, err;

	err = gnutls_pem_base64_decode_alloc("TSS KEY BLOB", fdata, &asn1);
	if (err) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("Error decoding TSS key blob: %s\n"),
			     gnutls_strerror(err));
		return -EINVAL;
	}
	/* Ick. We have to parse the ASN1 OCTET_STRING for ourselves. */
	if (asn1.size < 2 || asn1.data[0] != 0x04 /* OCTET_STRING */) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("Error in TSS key blob\n"));
		goto out_blob;
	}

	tss_len = asn1.data[1];
	ofs = 2;
	if (tss_len & 0x80) {
		int lenlen = tss_len & 0x7f;

		if (asn1.size < 2 + lenlen || lenlen > 3) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Error in TSS key blob\n"));
			goto out_blob;
		}

		tss_len = 0;
		while (lenlen) {
			tss_len <<= 8;
			tss_len |= asn1.data[ofs++];
			lenlen--;
		}
	}
	if (tss_len + ofs != asn1.size) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("Error in TSS key blob\n"));
		goto out_blob;
	}

	err = Tspi_Context_Create(&vpninfo->tpm_context);
	if (err) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("Failed to create TPM context: %s\n"),
			     Trspi_Error_String(err));
		goto out_blob;
	}
	err = Tspi_Context_Connect(vpninfo->tpm_context, NULL);
	if (err) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("Failed to connect TPM context: %s\n"),
			     Trspi_Error_String(err));
		goto out_context;
	}
	err = Tspi_Context_LoadKeyByUUID(vpninfo->tpm_context, TSS_PS_TYPE_SYSTEM,
					 SRK_UUID, &vpninfo->srk);
	if (err) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("Failed to load TPM SRK key: %s\n"),
			     Trspi_Error_String(err));
		goto out_context;
	}
	err = Tspi_GetPolicyObject(vpninfo->srk, TSS_POLICY_USAGE, &vpninfo->srk_policy);
	if (err) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("Failed to load TPM SRK policy object: %s\n"),
			     Trspi_Error_String(err));
		goto out_srk;
	}

	pass = vpninfo->cert_password;
	vpninfo->cert_password = NULL;
	while (1) {
		static const char nullpass[20];

		/* We don't seem to get the error here... */
		if (pass)
			err = Tspi_Policy_SetSecret(vpninfo->srk_policy,
						    TSS_SECRET_MODE_PLAIN,
						    strlen(pass), (BYTE *)pass);
		else /* Well-known NULL key */
			err = Tspi_Policy_SetSecret(vpninfo->srk_policy,
						    TSS_SECRET_MODE_SHA1,
						    sizeof(nullpass), (BYTE *)nullpass);
		if (err) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Failed to set TPM PIN: %s\n"),
				     Trspi_Error_String(err));
			goto out_srkpol;
		}

		free(pass);

		/* ... we get it here instead. */
		err = Tspi_Context_LoadKeyByBlob(vpninfo->tpm_context, vpninfo->srk,
						 tss_len, asn1.data + ofs,
						 &vpninfo->tpm_key);
		if (!err)
			break;

		if (pass)
			vpn_progress(vpninfo, PRG_ERR,
				     _("Failed to load TPM key blob: %s\n"),
				     Trspi_Error_String(err));

		if (err != TPM_E_AUTHFAIL)
			goto out_srkpol;

		err = request_passphrase(vpninfo, "openconnect_tpm_srk",
					 &pass, _("Enter TPM SRK PIN:"));
		if (err)
			goto out_srkpol;
	}

#ifdef HAVE_GNUTLS_CERTIFICATE_SET_KEY
	gnutls_privkey_init(pkey);
	/* This would be nicer if there was a destructor callback. I could
	   allocate a data structure with the TPM handles and the vpninfo
	   pointer, and destroy that properly when the key is destroyed. */
	gnutls_privkey_import_ext(*pkey, GNUTLS_PK_RSA, vpninfo, tpm_sign_fn, NULL, 0);
#else
	*pkey = OPENCONNECT_TPM_PKEY;
#endif

 retry_sign:
	err = sign_dummy_data(vpninfo, *pkey, fdata, pkey_sig);
	if (err == GNUTLS_E_INSUFFICIENT_CREDENTIALS) {
		if (!vpninfo->tpm_key_policy) {
			err = Tspi_Context_CreateObject(vpninfo->tpm_context,
							TSS_OBJECT_TYPE_POLICY,
							TSS_POLICY_USAGE,
							&vpninfo->tpm_key_policy);
			if (err) {
				vpn_progress(vpninfo, PRG_ERR,
					     _("Failed to create key policy object: %s\n"),
					     Trspi_Error_String(err));
				goto out_key;
			}
			err = Tspi_Policy_AssignToObject(vpninfo->tpm_key_policy,
							 vpninfo->tpm_key);
			if (err) {
				vpn_progress(vpninfo, PRG_ERR,
					     _("Failed to assign policy to key: %s\n"),
					     Trspi_Error_String(err));
				goto out_key_policy;
			}
		}
	        err = request_passphrase(vpninfo, "openconnect_tpm_key",
					 &pass, _("Enter TPM key PIN:"));
		if (err)
			goto out_key_policy;

		err = Tspi_Policy_SetSecret(vpninfo->tpm_key_policy,
					    TSS_SECRET_MODE_PLAIN,
					    strlen(pass), (void *)pass);
		free (pass);

		if (err) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Failed to set key PIN: %s\n"),
				     Trspi_Error_String(err));
			goto out_key_policy;
		}
		goto retry_sign;
	}

	free (asn1.data);
	return 0;
 out_key_policy:
	Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key_policy);
	vpninfo->tpm_key_policy = 0;
 out_key:
	Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key);
	vpninfo->tpm_key = 0;
 out_srkpol:
	Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk_policy);
	vpninfo->srk_policy = 0;
 out_srk:
	Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk);
	vpninfo->srk = 0;
 out_context:
	Tspi_Context_Close(vpninfo->tpm_context);
	vpninfo->tpm_context = 0;
 out_blob:
	free (asn1.data);
	return -EIO;
}
int
main_v1_1( void )
{
	char		*function = "Tspi_Context_LoadKeyByBlob04";
	TSS_HCONTEXT	hContext;
	TSS_HKEY	hSRK, hSigningKey, hBindingKey;
	TSS_HPOLICY	hPolicy;
	TSS_RESULT	result;
	UINT32		exitCode, attrib;
	TSS_FLAG	initFlags;
	BYTE		*signBlob, *bindBlob;
	UINT32		signBlobLen, bindBlobLen;

	print_begin_test( function );

		// Create Context
	if ((result = connect_load_srk(&hContext, &hSRK))) {
		print_error( "connect_load_srk", result );
		exit( result );
	}

		// create a no-auth, signing key
	initFlags = TSS_KEY_TYPE_SIGNING | TSS_KEY_SIZE_2048 |
		    TSS_KEY_NO_AUTHORIZATION;
	if ((result = create_load_key(hContext, initFlags, hSRK, &hSigningKey))) {
		print_error( "create_load_key(Signing Key)", result );
		Tspi_Context_Close( hContext );
		exit( result );
	}
	print_success("Signing key created successfully", TSS_SUCCESS);

		// get blob
	result = Tspi_GetAttribData( hSigningKey, TSS_TSPATTRIB_KEY_BLOB,
					TSS_TSPATTRIB_KEYBLOB_BLOB,
					&signBlobLen, &signBlob );
	if ( result != TSS_SUCCESS )
	{
		print_error( "Tspi_GetAttribData", result );
		Tspi_Context_Close( hContext );
		exit( result );
	}

		// create a auth, binding key
	initFlags = TSS_KEY_TYPE_BIND | TSS_KEY_SIZE_2048 |
		    TSS_KEY_AUTHORIZATION;
	if ((result = create_load_key(hContext, initFlags, hSRK, &hBindingKey))) {
		print_error( "create_load_key(Binding Key)", result );
		Tspi_Context_Close( hContext );
		exit( result );
	}
	print_success("Binding key created successfully", TSS_SUCCESS);

		// get blob
	result = Tspi_GetAttribData( hBindingKey, TSS_TSPATTRIB_KEY_BLOB,
					TSS_TSPATTRIB_KEYBLOB_BLOB,
					&bindBlobLen, &bindBlob );
	if ( result != TSS_SUCCESS )
	{
		print_error( "Tspi_GetAttribData", result );
		Tspi_Context_Close( hContext );
		exit( result );
	}

	// verify attribs before we close the context
	if ((result = verify_sign_attribs(hSigningKey))) {
		print_error( "verify_sign_attribs", result );
		Tspi_Context_Close( hContext );
		exit( result );
	}

	// verify attribs before we close the context
	if ((result = verify_bind_attribs(hBindingKey))) {
		print_error( "verify_bind_attribs", result );
		Tspi_Context_Close( hContext );
		exit( result );
	}

		// close context, to get rid of all context state
	if ((result = Tspi_Context_Close(hContext))) {
		print_error( "Tspi_Context_Close", result );
		exit( result );
	}

		// re-connect
	if ((result = connect_load_srk(&hContext, &hSRK))) {
		print_error( "connect_load_srk", result );
		Tspi_Context_Close( hContext );
		exit( result );
	}

		// Load both Keys by blob
	if ((result = Tspi_Context_LoadKeyByBlob( hContext, hSRK,
						signBlobLen,
						signBlob,
						&hSigningKey ))) {
		print_error( "Tspi_Context_LoadKeyByBlob", result );
		Tspi_Context_Close( hContext );
		exit( result );
	}
	if ((result = Tspi_Context_LoadKeyByBlob( hContext, hSRK,
						bindBlobLen,
						bindBlob,
						&hBindingKey ))) {
		print_error( "Tspi_Context_LoadKeyByBlob", result );
		Tspi_Context_Close( hContext );
		exit( result );
	}

	// verify attribs after we've re-loaded by blob
	if ((result = verify_sign_attribs(hSigningKey))) {
		print_error( "verify_sign_attribs", result );
		Tspi_Context_Close( hContext );
		exit( result );
	}

	// verify attribs after we've re-loaded by blob
	if ((result = verify_bind_attribs(hBindingKey))) {
		print_error( "verify_bind_attribs", result );
		Tspi_Context_Close( hContext );
		exit( result );
	}


	// Do a sign/verify test
	if ((result = sign_and_verify(hContext, hSigningKey))) {
		print_error( "sign_and_verify", result );
		Tspi_Context_Close( hContext );
		exit( result );
	}


	// Do a bind/unbind test
	result = bind_and_unbind(hContext, hBindingKey);
	if (TSS_ERROR_CODE(result) != TSS_E_POLICY_NO_SECRET) {
		print_verifyerr("bind and unbind", TSS_E_POLICY_NO_SECRET, result);
		print_error( function, result );
		Tspi_Context_Close( hContext );
		exit( result );
	}

	// set up policies
	if ((result = set_secret(hContext, hBindingKey, &hPolicy))) {
		print_error("set_secret", result);
		Tspi_Context_Close( hContext );
		exit( result );
	}

	if ((result = bind_and_unbind(hContext, hBindingKey))) {
		print_error( "bind_and_unbind", result );
		Tspi_Context_Close( hContext );
		exit( result );
	}

	exitCode = 0;
	print_success(function, TSS_SUCCESS);
	print_end_test( function );
	Tspi_Context_Close( hContext );
	exit( exitCode );
}
int
main_v1_1( void )
{
	char		*function = "Tspi_Context_LoadKeyByBlob03";
	TSS_HCONTEXT	hContext;
	TSS_HKEY	hSRK;
	TSS_HKEY	hMSigningKey;
	BYTE*		migratableSignKeyBlob;
	UINT32		blobLength;
	TSS_RESULT	result;
	TSS_HPOLICY	srkUsagePolicy;
	UINT32		exitCode = 0;

	print_begin_test( function );

		// Create Context
	result = Tspi_Context_Create( &hContext );
	if ( result != TSS_SUCCESS )
	{
		print_error( "Tspi_Context_Create", result );
		exit( result );
	}

		// Connect to Context
	result = Tspi_Context_Connect( hContext, get_server(GLOBALSERVER) );
	if ( result != TSS_SUCCESS )
	{
		print_error( "Tspi_Context_Connect", result );
		Tspi_Context_FreeMemory( hContext, NULL );
		Tspi_Context_Close( hContext );
		exit( result );
	}

		//Load Key By UUID
	result = Tspi_Context_LoadKeyByUUID( hContext, TSS_PS_TYPE_SYSTEM,
						SRK_UUID, &hSRK );
	if ( result != TSS_SUCCESS )
	{
		print_error( "Tspi_Context_LoadKeyByUUID (hSRK)", result );
		Tspi_Context_FreeMemory( hContext, NULL );
		Tspi_Context_Close( hContext );
		exit( result );
	}

#ifndef TESTSUITE_NOAUTH_SRK
		//Get Policy Object
	result = Tspi_GetPolicyObject( hSRK, TSS_POLICY_USAGE,
					&srkUsagePolicy );
	if ( result != TSS_SUCCESS )
	{
		print_error( "Tspi_GetPolicyObject", result );
		Tspi_Context_FreeMemory( hContext, NULL );
		Tspi_Context_Close( hContext );
		exit( result );
	}

		//Set Secret
	result = Tspi_Policy_SetSecret( srkUsagePolicy, TESTSUITE_SRK_SECRET_MODE,
				TESTSUITE_SRK_SECRET_LEN, TESTSUITE_SRK_SECRET );
	if ( result != TSS_SUCCESS )
	{
		print_error( "Tspi_Policy_SetSecret (1)", result );
		Tspi_Context_FreeMemory( hContext, NULL );
		Tspi_Context_Close( hContext );
		exit( result );
	}
#endif

		//Create Signing Key
	result = Tspi_Context_CreateObject( hContext, TSS_OBJECT_TYPE_RSAKEY,
						TSS_KEY_SIZE_2048 |
						TSS_KEY_TYPE_SIGNING,
						&hMSigningKey );
	if ( result != TSS_SUCCESS )
	{
		print_error( "Tspi_CreateObject (signing key)", result );
		Tspi_Context_FreeMemory( hContext, NULL );
		Tspi_Context_Close( hContext );
		exit( result );
	}

	result = Tspi_Key_CreateKey( hMSigningKey, hSRK, 0 );
	if ( result != TSS_SUCCESS )
	{
		print_error( "Tspi_Key_CreateKey (Signing Key)", result );
		Tspi_Context_FreeMemory( hContext, NULL );
		Tspi_Context_Close( hContext );
		exit( result );
	}

		// get blob
	result = Tspi_GetAttribData( hMSigningKey, TSS_TSPATTRIB_KEY_BLOB,
					TSS_TSPATTRIB_KEYBLOB_BLOB,
					&blobLength, &migratableSignKeyBlob );
	if ( result != TSS_SUCCESS )
	{
		print_error( "Tspi_GetAttribData", result );
		Tspi_Context_FreeMemory( hContext, NULL );
		Tspi_Context_Close( hContext );
		exit( result );
	}

		//Load Key Blob
	result = Tspi_Context_LoadKeyByBlob( hContext, hSRK,
						blobLength,
						NULL,
						&hMSigningKey );
	if ( TSS_ERROR_CODE(result) != TSS_E_BAD_PARAMETER )
	{
		if( !(checkNonAPI(result)) )
		{
			print_error( function, result );
			exitCode = result;
		}
		else
		{
			print_error_nonapi( function, result );
			exitCode = result;
		}
	}
	else
	{
		print_success( function, result );
	}

	print_end_test( function );
	Tspi_Context_FreeMemory( hContext, NULL );
	Tspi_Context_Close( hContext );
	exit( exitCode );
}
Example #4
0
static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id,
				     UI_METHOD *ui, void *cb_data)
{
	ASN1_OCTET_STRING *blobstr;
	TSS_HKEY hKey;
	TSS_RESULT result;
	UINT32 authusage;
	RSA *rsa;
	EVP_PKEY *pkey;
	BIO *bf;


	DBG("%s", __FUNCTION__);

	if (!key_id) {
		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, ERR_R_PASSED_NULL_PARAMETER);
		return NULL;
	}

	if (!tpm_load_srk(ui, cb_data)) {
		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_SRK_LOAD_FAILED);
		return NULL;
	}

	if ((bf = BIO_new_file(key_id, "r")) == NULL) {
		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY,
		       TPM_R_FILE_NOT_FOUND);
		return NULL;
	}

	blobstr = PEM_ASN1_read_bio((void *)d2i_ASN1_OCTET_STRING,
				    "TSS KEY BLOB", bf, NULL, NULL, NULL);
	if (!blobstr) {
		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY,
		       TPM_R_FILE_READ_FAILED);
		BIO_free(bf);
		return NULL;
	}

	BIO_free(bf);
	DBG("Loading blob of size: %d", blobstr->length);
	if ((result = Tspi_Context_LoadKeyByBlob(hContext, hSRK,
						   blobstr->length,
						   blobstr->data, &hKey))) {
		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY,
		       TPM_R_REQUEST_FAILED);
		return NULL;
	}
	ASN1_OCTET_STRING_free(blobstr);

	if ((result = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
					     TSS_TSPATTRIB_KEYINFO_AUTHUSAGE,
					     &authusage))) {
		Tspi_Context_CloseObject(hContext, hKey);
		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY,
		       TPM_R_REQUEST_FAILED);
		return NULL;
	}

	if (authusage) {
		TSS_HPOLICY hPolicy;
		BYTE *auth;

		if ((auth = calloc(1, 128)) == NULL) {
			Tspi_Context_CloseObject(hContext, hKey);
			TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, ERR_R_MALLOC_FAILURE);
			return NULL;
		}

		if (!tpm_engine_get_auth(ui, (char *)auth, 128,
					 "TPM Key Password: ",
					 cb_data)) {
			Tspi_Context_CloseObject(hContext, hKey);
			free(auth);
			TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_REQUEST_FAILED);
			return NULL;
		}

		if ((result = Tspi_Context_CreateObject(hContext,
							 TSS_OBJECT_TYPE_POLICY,
							 TSS_POLICY_USAGE,
							 &hPolicy))) {
			Tspi_Context_CloseObject(hContext, hKey);
			free(auth);
			TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_REQUEST_FAILED);
			return 0;
		}

		if ((result = Tspi_Policy_AssignToObject(hPolicy, hKey))) {
			Tspi_Context_CloseObject(hContext, hKey);
			Tspi_Context_CloseObject(hContext, hPolicy);
			free(auth);
			TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_REQUEST_FAILED);
			return 0;
		}

		if ((result = Tspi_Policy_SetSecret(hPolicy,
						      TSS_SECRET_MODE_PLAIN,
						      strlen((char *)auth), auth))) {
			Tspi_Context_CloseObject(hContext, hKey);
			Tspi_Context_CloseObject(hContext, hPolicy);
			free(auth);
			TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_REQUEST_FAILED);
			return 0;
		}

		free(auth);
	}

	/* create the new objects to return */
	if ((pkey = EVP_PKEY_new()) == NULL) {
		Tspi_Context_CloseObject(hContext, hKey);
		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, ERR_R_MALLOC_FAILURE);
		return NULL;
	}
	pkey->type = EVP_PKEY_RSA;

	if ((rsa = RSA_new()) == NULL) {
		EVP_PKEY_free(pkey);
		Tspi_Context_CloseObject(hContext, hKey);
		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, ERR_R_MALLOC_FAILURE);
		return NULL;
	}
	rsa->meth = &tpm_rsa;
	/* call our local init function here */
	rsa->meth->init(rsa);
	pkey->pkey.rsa = rsa;

	if (!fill_out_rsa_object(rsa, hKey)) {
		EVP_PKEY_free(pkey);
		RSA_free(rsa);
		Tspi_Context_CloseObject(hContext, hKey);
		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_REQUEST_FAILED);
		return NULL;
	}

	EVP_PKEY_assign_RSA(pkey, rsa);

	return pkey;
}
Example #5
0
static int load_key(TSS_HCONTEXT tpm_ctx, TSS_HKEY srk,
		    const gnutls_datum_t * fdata,
		    gnutls_tpmkey_fmt_t format, TSS_HKEY * tpm_key)
{
	int ret, err;
	gnutls_datum_t asn1 = { NULL, 0 };

	if (format == GNUTLS_TPMKEY_FMT_CTK_PEM) {
		gnutls_datum_t td;

		ret =
		    gnutls_pem_base64_decode_alloc("TSS KEY BLOB", fdata,
						   &asn1);
		if (ret) {
			gnutls_assert();
			_gnutls_debug_log
			    ("Error decoding TSS key blob: %s\n",
			     gnutls_strerror(ret));
			return ret;
		}

		ret =
		    _gnutls_x509_decode_string(ASN1_ETYPE_OCTET_STRING,
					       asn1.data, asn1.size, &td);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
		gnutls_free(asn1.data);
		asn1.data = td.data;
		asn1.size = td.size;
	} else {		/* DER */

		UINT32 tint2;
		UINT32 type;

		asn1.size = fdata->size;
		asn1.data = gnutls_malloc(asn1.size);
		if (asn1.data == NULL) {
			gnutls_assert();
			return GNUTLS_E_MEMORY_ERROR;
		}

		tint2 = asn1.size;
		err =
		    Tspi_DecodeBER_TssBlob(fdata->size, fdata->data, &type,
					   &tint2, asn1.data);
		if (err != 0) {
			gnutls_assert();
			ret = tss_err(err);
			goto cleanup;
		}

		asn1.size = tint2;
	}

	/* ... we get it here instead. */
	err = Tspi_Context_LoadKeyByBlob(tpm_ctx, srk,
					 asn1.size, asn1.data, tpm_key);
	if (err != 0) {
		gnutls_assert();
		ret = tss_err(err);
		goto cleanup;
	}

	ret = 0;

      cleanup:
	gnutls_free(asn1.data);

	return ret;
}
Example #6
0
int
main (int ac, char **av)
{
	TSS_HCONTEXT	hContext;
	TSS_HTPM	hTPM;
	TSS_HKEY	hSRK;
	TSS_HKEY	hAIK;
	TSS_HPOLICY	hTPMPolicy;
	TSS_HPOLICY	hSrkPolicy;
	TSS_HPOLICY	hAIKPolicy;
	TSS_UUID	SRK_UUID = TSS_UUID_SRK;
	BYTE		srkSecret[] = TSS_WELL_KNOWN_SECRET;
	FILE		*f_in;
	FILE		*f_out;
	char		*pass = NULL;
	BYTE		*response;
	UINT32		responseLen;
	BYTE		*buf;
	UINT32		bufLen;
	BYTE		*asym;
	UINT32		asymLen;
	BYTE		*sym;
	UINT32		symLen;
	int		i;
	int		result;

	if ((ac<2) || ((0==strcmp(av[1],"-p")) ? (ac!=6) : (ac!=4))) {
		fprintf (stderr, "Usage: %s [-p password] aikblobfile challengefile outresponsefile\n", av[0]);
		exit (1);
	}

	if (0 == strcmp(av[1], "-p")) {
		pass = av[2];
		for (i=3; i<ac; i++)
			av[i-2] = av[i];
		ac -= 2;
	}

	result = Tspi_Context_Create(&hContext); CKERR;
	result = Tspi_Context_Connect(hContext, NULL); CKERR;
	result = Tspi_Context_LoadKeyByUUID(hContext,
			TSS_PS_TYPE_SYSTEM, SRK_UUID, &hSRK); CKERR;
	result = Tspi_GetPolicyObject (hSRK, TSS_POLICY_USAGE, &hSrkPolicy); CKERR;
	result = Tspi_Policy_SetSecret(hSrkPolicy, TSS_SECRET_MODE_SHA1,
			sizeof(srkSecret), srkSecret); CKERR;
	result = Tspi_Context_GetTpmObject (hContext, &hTPM); CKERR;
	result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_POLICY,
			TSS_POLICY_USAGE, &hTPMPolicy); CKERR;
	result = Tspi_Policy_AssignToObject(hTPMPolicy, hTPM);
#ifdef OWNER_SECRET
	result = Tspi_Policy_SetSecret (hTPMPolicy, TSS_SECRET_MODE_PLAIN,
			strlen(OWNER_SECRET)+1, OWNER_SECRET); CKERR;
#else
	result = Tspi_Policy_SetSecret (hTPMPolicy, TSS_SECRET_MODE_POPUP, 0, NULL); CKERR;
#endif

	/* Read AIK blob */
	if ((f_in = fopen(av[1], "rb")) == NULL) {
		fprintf (stderr, "Unable to open file %s\n", av[1]);
		exit (1);
	}
	fseek (f_in, 0, SEEK_END);
	bufLen = ftell (f_in);
	fseek (f_in, 0, SEEK_SET);
	buf = malloc (bufLen);
	if (fread(buf, 1, bufLen, f_in) != bufLen) {
		fprintf (stderr, "Unable to readn file %s\n", av[1]);
		exit (1);
	}
	fclose (f_in);

	result = Tspi_Context_LoadKeyByBlob (hContext, hSRK, bufLen, buf, &hAIK); CKERR;
	free (buf);

	if (pass) {
		result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_POLICY,
				TSS_POLICY_USAGE, &hAIKPolicy); CKERR;
		result = Tspi_Policy_AssignToObject(hAIKPolicy, hAIK);
		result = Tspi_Policy_SetSecret (hAIKPolicy, TSS_SECRET_MODE_PLAIN,
				strlen(pass)+1, pass); CKERR;
	}

	/* Read challenge file */
	if ((f_in = fopen(av[2], "rb")) == NULL) {
		fprintf (stderr, "Unable to open file %s\n", av[2]);
		exit (1);
	}
	fseek (f_in, 0, SEEK_END);
	bufLen = ftell (f_in);
	fseek (f_in, 0, SEEK_SET);
	buf = malloc (bufLen);
	if (fread(buf, 1, bufLen, f_in) != bufLen) {
		fprintf (stderr, "Unable to readn file %s\n", av[2]);
		exit (1);
	}
	fclose (f_in);

	/* Parse challenge */
	if (bufLen < 8)
		goto badchal;
	asymLen = ntohl(*(UINT32*)buf);
	asym = buf + 4;
	buf += asymLen + 4;
	if (bufLen < asymLen+8)
		goto badchal;
	symLen = ntohl(*(UINT32*)buf);
	if (bufLen != asymLen + symLen + 8)
		goto badchal;
	sym = buf + 4;

	/* Decrypt challenge data */
#ifndef OWNER_SECRET
	{
	/* Work around a bug in Trousers 0.3.1 - remove this block when fixed */
	/* Force POPUP to activate, it is being ignored */
		BYTE *dummyblob1; UINT32 dummylen1;
		if (Tspi_TPM_OwnerGetSRKPubKey(hTPM, &dummylen1, &dummyblob1)
				== TSS_SUCCESS) {
			Tspi_Context_FreeMemory (hContext, dummyblob1);
		}
	}
#endif
	result = Tspi_TPM_ActivateIdentity (hTPM, hAIK, asymLen, asym,
						symLen, sym,
						&responseLen, &response); CKERR;

	/* Output response file */
	
	if ((f_out = fopen (av[3], "wb")) == NULL) {
		fprintf (stderr, "Unable to create file %s\n", av[3]);
		exit (1);
	}
	if (fwrite (response, 1, responseLen, f_out) != responseLen) {
		fprintf (stderr, "Unable to write to file %s\n", av[3]);
		exit (1);
	}
	fclose (f_out);

	printf ("Success!\n");
	return 0;

error:
	fprintf (stderr, "Failure, error code: 0x%x\n", result);
	return 1;

badchal:
	fprintf (stderr, "Challenge file format is wrong\n");
	return 1;
}